info.magnolia.cms.gui.dialog.DialogControlImpl.java Source code

Java tutorial

Introduction

Here is the source code for info.magnolia.cms.gui.dialog.DialogControlImpl.java

Source

/**
 *
 * Magnolia and its source-code is licensed under the LGPL.
 * You may copy, adapt, and redistribute this file for commercial or non-commercial use.
 * When copying, adapting, or redistributing this document in keeping with the guidelines above,
 * you are required to provide proper attribution to obinary.
 * If you reproduce or distribute the document without making any substantive modifications to its content,
 * please use the following attribution line:
 *
 * Copyright 1993-2006 obinary Ltd. (http://www.obinary.com) All rights reserved.
 *
 */
package info.magnolia.cms.gui.dialog;

import info.magnolia.cms.core.Content;
import info.magnolia.cms.core.ItemType;
import info.magnolia.cms.core.NodeData;
import info.magnolia.cms.i18n.Messages;
import info.magnolia.cms.i18n.MessagesUtil;
import info.magnolia.cms.i18n.TemplateMessagesUtil;
import info.magnolia.cms.util.AlertUtil;
import info.magnolia.cms.util.RequestFormUtil;

import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.Writer;
import java.util.*;

/**
 * @author Vinzenz Wyser
 * @version 2.0
 */
public abstract class DialogControlImpl implements DialogControl {

    private static final String I18N_BASENAME_PROPERTY = "i18nBasename";

    public static final String SESSION_ATTRIBUTENAME_DIALOGOBJECT = "mgnlSessionAttribute"; //$NON-NLS-1$

    public static final String SESSION_ATTRIBUTENAME_DIALOGOBJECT_REMOVE = "mgnlSessionAttributeRemove"; //$NON-NLS-1$

    /**
     * Logger.
     */
    private static Logger log = LoggerFactory.getLogger(DialogControlImpl.class);

    /**
     * Current request.
     */
    private HttpServletRequest request;

    /**
     * Current response.
     */
    private HttpServletResponse response;

    /**
     * content data.
     */
    private Content websiteNode;

    /**
     * config data.
     */
    private Map config = new Hashtable();

    /**
     * Sub controls.
     */
    private List subs = new ArrayList();

    /**
     * options (radio, checkbox...).
     */
    private List options = new ArrayList();

    /**
     * The id is used to make the controls unic. Used by the javascripts. This is not a configurable value. See method
     * set and getName().
     */
    private String id = "mgnlControl"; //$NON-NLS-1$

    protected String value;

    /**
     * multiple values, e.g. checkbox.
     */
    private List values;

    private DialogControlImpl parent;

    private DialogControlImpl topParent;

    /**
     * Used if this control has its own message bundle defined or if this is the dialog object itself. Use getMessages
     * method to get the object for a control.
     */
    private Messages messages;

    /**
     */
    public void init(HttpServletRequest request, HttpServletResponse response, Content websiteNode,
            Content configNode) throws RepositoryException {

        if (log.isDebugEnabled()) {
            log.debug("Init " + getClass().getName()); //$NON-NLS-1$
        }

        this.websiteNode = websiteNode;
        this.request = request;
        this.response = response;

        this.initializeConfig(configNode);
    }

    /**
     * @see info.magnolia.cms.gui.dialog.DialogControl#drawHtml(Writer)
     */
    public void drawHtml(Writer out) throws IOException {
        this.drawHtmlPreSubs(out);
        this.drawSubs(out);
        this.drawHtmlPostSubs(out);
    }

    public void addSub(Object o) {
        this.getSubs().add(o);
    }

    public void setConfig(String key, String value) {
        if (value != null) {
            this.config.put(key, value);
        }
    }

    public void setConfig(String key, boolean value) {
        this.config.put(key, BooleanUtils.toBooleanObject(value).toString());
    }

    public void setConfig(String key, int value) {
        this.config.put(key, Integer.toString(value));
    }

    public String getConfigValue(String key, String nullValue) {
        if (this.config.containsKey(key)) {
            return (String) this.config.get(key);
        }

        return nullValue;
    }

    public String getConfigValue(String key) {
        return this.getConfigValue(key, StringUtils.EMPTY);
    }

    public void setValue(String s) {
        this.value = s;
    }

    public String getValue() {
        if (this.value == null) {
            if (this.getWebsiteNode() != null) {
                this.value = this.getWebsiteNode().getNodeData(this.getName()).getString();
            }
            RequestFormUtil params = new RequestFormUtil(request);
            if (params.getParameter(this.getName()) != null) {
                this.value = params.getParameter(this.getName());
            }

            if (this.value == null && StringUtils.isNotEmpty(getConfigValue("defaultValue"))) {
                return this.getMessage(this.getConfigValue("defaultValue"));
            }

            if (this.value == null) {
                this.value = StringUtils.EMPTY;
            }
        }
        return this.value;
    }

    public void setSaveInfo(boolean b) {
        this.setConfig("saveInfo", b); //$NON-NLS-1$
    }

    /**
     * Set the name of this control. This is not the same value as the id setted by the parent. In common this value is
     * setted in the dialog configuration.
     * @param the name
     */
    public void setName(String s) {
        this.setConfig("name", s); //$NON-NLS-1$
    }

    /**
     * Return the configured name of this control (not the id).
     * @return the name
     */
    public String getName() {
        return this.getConfigValue("name"); //$NON-NLS-1$
    }

    public void addOption(Object o) {
        this.getOptions().add(o);
    }

    public Content getWebsiteNode() {
        return this.websiteNode;
    }

    public void setLabel(String s) {
        this.config.put("label", s); //$NON-NLS-1$
    }

    public void setDescription(String s) {
        this.config.put("description", s); //$NON-NLS-1$
    }

    public void removeSessionAttribute() {
        String name = this.getConfigValue(SESSION_ATTRIBUTENAME_DIALOGOBJECT);
        HttpServletRequest request = this.getRequest();
        if (request == null) {
            request = this.getTopParent().getRequest();
        }
        try {
            HttpSession httpsession = request.getSession(false);
            if (httpsession != null) {
                httpsession.removeAttribute(name);
            }
        } catch (Exception e) {
            if (log.isDebugEnabled())
                log.debug("removeSessionAttribute() for " + name + " failed because this.request is null"); //$NON-NLS-1$ //$NON-NLS-2$
        }
    }

    public HttpServletRequest getRequest() {
        return this.request;
    }

    public void setOptions(List options) {
        this.options = options;
    }

    protected void drawHtmlPreSubs(Writer out) throws IOException {
        // do nothing
    }

    protected void drawSubs(Writer out) throws IOException {
        Iterator it = this.getSubs().iterator();
        int i = 0;
        while (it.hasNext()) {
            // use underscore (not divis)! could be used as js variable names
            String dsId = this.getId() + "_" + i; //$NON-NLS-1$

            DialogControlImpl ds = (DialogControlImpl) it.next();
            ds.setId(dsId);
            ds.setParent(this);
            if (this.getParent() == null) {
                this.setTopParent(this);
            }
            ds.setTopParent(this.getTopParent());
            ds.drawHtml(out);
            i++;
        }
    }

    protected void drawHtmlPostSubs(Writer out) throws IOException {
        // do nothing
    }

    public DialogControlImpl getParent() {
        return this.parent;
    }

    protected void setTopParent(DialogControlImpl top) {
        this.topParent = top;
    }

    public DialogControlImpl getTopParent() {
        return this.topParent;
    }

    public List getSubs() {
        return this.subs;
    }

    /**
     * Find a control by its name
     * @param name the name of the control to find
     * @return the found control or null
     */
    public DialogControlImpl getSub(String name) {
        DialogControlImpl found;
        for (Iterator iter = subs.iterator(); iter.hasNext();) {
            Object control = iter.next();

            // could be an implementation of DialogControl only
            if (control instanceof DialogControlImpl) {
                if (StringUtils.equals(((DialogControlImpl) control).getName(), name)) {
                    return (DialogControlImpl) control;
                }
                found = ((DialogControlImpl) control).getSub(name);
                if (found != null) {
                    return found;
                }
            }
        }
        return null;
    }

    protected HttpServletResponse getResponse() {
        return this.response;
    }

    /**
     * @deprecated websitenode should only be set in init(), this is a workaround used in DialogDate
     */
    protected void clearWebsiteNode() {
        this.websiteNode = null;
    }

    public String getId() {
        return this.id;
    }

    public String getLabel() {
        return this.getConfigValue("label", StringUtils.EMPTY); //$NON-NLS-1$
    }

    public String getDescription() {
        return this.getConfigValue("description", StringUtils.EMPTY); //$NON-NLS-1$
    }

    public List getOptions() {
        return this.options;
    }

    public List getValues() {
        if (this.values == null) {
            this.values = new ArrayList();
            if (this.getWebsiteNode() != null) {
                try {
                    Iterator it = this.getWebsiteNode().getContent(this.getName()).getNodeDataCollection()
                            .iterator();
                    while (it.hasNext()) {
                        NodeData data = (NodeData) it.next();
                        this.values.add(data.getString());
                    }
                } catch (PathNotFoundException e) {
                    // not yet existing: OK
                } catch (RepositoryException re) {
                    log.error("can't set values", re);
                }
            }

            if (request != null) {
                RequestFormUtil params = new RequestFormUtil(request);
                String[] values = params.getParameterValues(this.getName());
                if (values != null && values.length > 0) {
                    this.values.clear();
                    for (int i = 0; i < values.length; i++) {
                        String value = values[i];
                        this.values.add(value);
                    }
                }
            }
        }

        return this.values;
    }

    /**
     * This method sets a control into the session
     */
    public void setSessionAttribute() {
        String name = SESSION_ATTRIBUTENAME_DIALOGOBJECT + "_" + this.getName() + "_" + new Date().getTime(); //$NON-NLS-1$ //$NON-NLS-2$
        this.setConfig(SESSION_ATTRIBUTENAME_DIALOGOBJECT, name);
        HttpServletRequest request = this.getRequest();
        if (request == null) {
            request = this.getTopParent().getRequest();
        }
        try {

            // @todo IMPORTANT remove use of http session
            HttpSession httpsession = request.getSession(true);
            httpsession.setAttribute(name, this);
        } catch (Exception e) {
            log.error("setSessionAttribute() for " + name + " failed because this.request is null"); //$NON-NLS-1$ //$NON-NLS-2$
        }
    }

    private void setId(String id) {
        this.id = id;
    }

    private void initializeConfig(Content configNodeParent) throws RepositoryException {
        // create config and subs out of dialog structure
        Map config = new Hashtable();

        if (configNodeParent == null) {
            // can happen only if Dialog is instantiated directly
            return;
        }

        // get properties -> to this.config
        Iterator itProps = configNodeParent.getNodeDataCollection().iterator();
        while (itProps.hasNext()) {
            NodeData data = (NodeData) itProps.next();
            String name = data.getName();
            String value = data.getString();
            config.put(name, value);
        }

        // name is usually mandatory, use node name if a name property is not set
        if (!config.containsKey("name")) {
            config.put("name", configNodeParent.getName());
        }

        this.config = config;

        Iterator it = configNodeParent.getChildren(ItemType.CONTENTNODE).iterator();
        while (it.hasNext()) {
            Content configNode = (Content) it.next();
            String controlType = configNode.getNodeData("controlType").getString(); //$NON-NLS-1$

            if (StringUtils.isEmpty(controlType)) {
                String name = configNode.getName();
                if (!name.startsWith("options")) { //$NON-NLS-1$
                    log.warn("Missing control type for configNode " + name); //$NON-NLS-1$
                }
                return;
            }

            if (log.isDebugEnabled()) {
                log.debug("Loading control \"" + controlType + "\" for " + configNode.getHandle()); //$NON-NLS-1$ //$NON-NLS-2$
            }
            DialogControl dialogControl = DialogFactory.loadDialog(request, response, this.getWebsiteNode(),
                    configNode);
            this.addSub(dialogControl);
        }
    }

    private void setParent(DialogControlImpl parent) {
        this.parent = parent;
    }

    /**
     * Get the AbstractMessagesImpl object for this dialog/control. It checks first if there was a bundle defined
     * <code>i18nBasename</code>, then it tries to find the parent with the first definition.
     * @return
     */
    protected Messages getMessages() {
        if (messages == null) {
            // if this is the root
            if (this.getParent() == null) {
                messages = TemplateMessagesUtil.getMessages();
            } else {
                // try to get it from the control nearest to the root
                messages = this.getParent().getMessages();
            }
            // if this control defines a bundle (basename in the terms of jstl)
            String basename = this.getConfigValue(I18N_BASENAME_PROPERTY);
            if (StringUtils.isNotEmpty(basename)) {
                // extend the chain with this bundle
                messages = MessagesUtil.chain(basename, messages);
            }
        }
        return messages;
    }

    /**
     * Get the message.
     * @param key key
     * @return message
     */
    public String getMessage(String key) {
        return this.getMessages().getWithDefault(key, key);
    }

    /**
     * Get the message with replacement strings. Use the {nr} syntax
     * @param key key
     * @param args replacement strings
     * @return message
     */
    public String getMessage(String key, Object[] args) {
        return this.getMessages().getWithDefault(key, args, key);
    }

    /**
     * If the validation fails the code will set a message in the context using the AlertUtil.
     * @return true if valid
     */
    public boolean validate() {
        if (this.isRequired()) {
            if (StringUtils.isEmpty(this.getValue()) && this.getValues().size() == 0) {
                String name = this.getMessage(this.getLabel());
                AlertUtil.setMessage(this.getMessage("dialogs.validation.required", new Object[] { name }));
                return false;
            }
        }
        for (Iterator iter = this.getSubs().iterator(); iter.hasNext();) {
            DialogControl sub = (DialogControl) iter.next();
            if (sub instanceof DialogControlImpl) {
                if (!((DialogControlImpl) sub).validate()) {
                    return false;
                }
            }

        }
        return true;
    }

    /**
     * True if a value is required. Set it in the configuration
     * @return
     */
    public boolean isRequired() {
        if (BooleanUtils.toBoolean(this.getConfigValue("required"))) {
            return true;
        }
        return false;
    }

    public void setRequired(boolean required) {
        this.setConfig("required", BooleanUtils.toStringTrueFalse(required));
    }

}