/*
 * Copyright 2003 - 2018 The eFaps Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.efaps.ui.wicket.request;

import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.commons.collections.CollectionUtils;
import org.apache.wicket.ajax.AjaxRequestHandler;
import org.apache.wicket.core.util.string.JavaScriptUtils;
import org.apache.wicket.markup.head.CssHeaderItem;
import org.apache.wicket.markup.head.HeaderItem;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.JavaScriptHeaderItem;
import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
import org.apache.wicket.markup.head.ResourceAggregator;
import org.apache.wicket.request.Response;
import org.apache.wicket.request.cycle.RequestCycle;
import org.efaps.admin.program.bundle.BundleMaker;
import org.efaps.admin.program.bundle.TempFileBundle;
import org.efaps.ui.wicket.EFapsApplication;
import org.efaps.ui.wicket.behaviors.dojo.AutoCompleteBehavior;
import org.efaps.ui.wicket.behaviors.dojo.AutoCompleteHeaderItem;
import org.efaps.ui.wicket.behaviors.dojo.OnDojoReadyHeaderItem;
import org.efaps.ui.wicket.behaviors.dojo.RequireHeaderItem;
import org.efaps.ui.wicket.resources.AbstractEFapsHeaderItem;
import org.efaps.ui.wicket.resources.EFapsJavaScriptHeaderItem;
import org.efaps.ui.wicket.util.DojoClass;
import org.efaps.ui.wicket.util.DojoWrapper;
import org.efaps.util.EFapsException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * TODO comment!
 *
 * @author The eFaps Team
 */
public class EFapsResourceAggregator
    extends ResourceAggregator
{

    /**
     * Logger for this class.
     */
    private static final Logger LOG = LoggerFactory.getLogger(EFapsResourceAggregator.class);

    /**
     * List of HeaderItems that will be rendered in on dojo ready script.
     */
    private final List<OnDojoReadyHeaderItem> dojoReadyItems = new ArrayList<>();

    /**
    * List of HeaderItems that will be rendered in on dojo ready script.
    */
    private final List<AutoCompleteHeaderItem> autoCompleteItems = new ArrayList<>();

    /**
     * List of HeaderItems that will be rendered file using the eFaps kernel.
     */
    private final List<AbstractEFapsHeaderItem> eFapsHeaderItems = new ArrayList<>();

    /**
     * List of HeaderItems that will be rendered file using the eFaps kernel.
     */
    private final Set<RequireHeaderItem> requireHeaderItems = new HashSet<>();

    /**
     * @param _real orginial Response
     */
    public EFapsResourceAggregator(final IHeaderResponse _real)
    {
        super(_real);
    }

    /**
     * Renders the given {@link HeaderItem} to the response if none of the
     * {@linkplain HeaderItem#getRenderTokens() tokens} of the item has been rendered before.
     *
     * @param _item  The item to render.
     */
    @Override
    public void render(final HeaderItem _item)
    {
        if (_item instanceof OnDojoReadyHeaderItem) {
            this.dojoReadyItems.add((OnDojoReadyHeaderItem) _item);
        } else if (_item instanceof AbstractEFapsHeaderItem) {
            this.eFapsHeaderItems.add((AbstractEFapsHeaderItem) _item);
        } else if (_item instanceof AutoCompleteHeaderItem) {
            this.autoCompleteItems.add((AutoCompleteHeaderItem) _item);
        } else if (_item instanceof RequireHeaderItem) {
            this.requireHeaderItems.add((RequireHeaderItem) _item);
        } else {
            super.render(_item);
        }
    }

    /**
     * Before closing the combined Script and EFapsHeaderItems are added.
     */
    @Override
    public void close()
    {
        renderCombinedEventScripts();
        renderEFapsHeaderItems();
        renderCombinedAutoCompleteScripts();
        renderCombinedRequireScripts();
        super.close();
    }

    /**
     * render the eFaps Resource items.
     */
    private void renderEFapsHeaderItems()
    {
        Collections.sort(this.eFapsHeaderItems, (_item0, _item1) -> _item0.getSortWeight().compareTo(_item1.getSortWeight()));

        final List<String> css = new ArrayList<>();
        final List<String> js = new ArrayList<>();
        for (final AbstractEFapsHeaderItem item : this.eFapsHeaderItems) {
            if (item instanceof EFapsJavaScriptHeaderItem) {
                js.add(item.getReference().getName());
            } else {
                css.add(item.getReference().getName());
            }
        }
        try {
            if (!css.isEmpty()) {
                final String key = BundleMaker.getBundleKey(css, TempFileBundle.class);
                final TempFileBundle bundle = (TempFileBundle) BundleMaker.getBundle(key);
                bundle.setContentType("text/css");
                super.render(CssHeaderItem.forUrl(EFapsApplication.get().getServletContext()
                                .getContextPath() + "/servlet/static/" + key));
            }
            if (!js.isEmpty()) {
                final String key = BundleMaker.getBundleKey(js, TempFileBundle.class);
                final TempFileBundle bundle = (TempFileBundle) BundleMaker.getBundle(key);
                bundle.setContentType("text/javascript");
                super.render(JavaScriptHeaderItem.forUrl(EFapsApplication.get().getServletContext()
                                .getContextPath() + "/servlet/static/" + key));
            }
        } catch (final EFapsException e) {
            EFapsResourceAggregator.LOG.error("Error on rendering eFaps Header items: ", e);
        }
    }

    /**
     * Combines all DOM ready and onLoad scripts and renders them as 2 script
     * tags.
     */
    private void renderCombinedEventScripts()
    {
        final StringBuilder combinedScript = new StringBuilder();

        for (final OnDojoReadyHeaderItem curItem : this.dojoReadyItems) {
            combinedScript.append("\n");
            combinedScript.append(curItem.getJavaScript());
            combinedScript.append(";");
        }

        if (combinedScript.length() > 0) {
            super.render(OnDojoReadyHeaderItem.forScript(combinedScript.append("\n").toString()));
        }
    }

    /**
     * Combines all DOM ready and onLoad scripts and renders them as 2 script
     * tags.
     */
    private void renderCombinedAutoCompleteScripts()
    {
        final StringBuilder combinedScript = new StringBuilder();
        final EnumSet<AutoCompleteBehavior.Type> types = EnumSet.noneOf(AutoCompleteBehavior.Type.class);
        for (final AutoCompleteHeaderItem curItem : this.autoCompleteItems) {
            for (final AutoCompleteBehavior.Type type : curItem.getTypes()) {
                if (!types.contains(type)) {
                    types.add(type);
                }
            }
            combinedScript.append("\n");
            combinedScript.append(curItem.getJavaScript());
            combinedScript.append(";");
        }

        if (combinedScript.length() > 0) {
            if (RequestCycle.get().getActiveRequestHandler() instanceof AjaxRequestHandler) {
                super.render(new OnDomReadyHeaderItem(AutoCompleteHeaderItem.writeJavaScript(
                                combinedScript.append("\n"), types, false)));
            } else {
                super.render(AutoCompleteHeaderItem.forScript(combinedScript.append("\n").toString(), types));
            }
        }
    }

    /**
     * Render combined requir scripts.
     */
    private void renderCombinedRequireScripts()
    {
        final Set<DojoClass> dojoClasses = this.requireHeaderItems.stream().flatMap(o -> o.getDojoClasses().stream())
                        .collect(Collectors.toSet());
        if (CollectionUtils.isNotEmpty(dojoClasses)) {
            super.render(new HeaderItem()
            {

                /** The Constant serialVersionUID. */
                private static final long serialVersionUID = 1L;

                @Override
                public Iterable<?> getRenderTokens()
                {
                    return dojoClasses;
                }

                @Override
                public void render(final Response _response)
                {
                    JavaScriptUtils.writeJavaScript(_response,
                                    DojoWrapper.require(null, dojoClasses.toArray(new DojoClass[dojoClasses.size()])),
                                    RequireHeaderItem.class.getName());
                }
            });
        }
    }
}


/*
 * Copyright 2003 - 2014 The eFaps Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Revision:        $Rev$
 * Last Changed:    $Date$
 * Last Changed By: $Author$
 */

package org.efaps.ui.wicket.behaviors.dojo;

import org.apache.wicket.Component;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.efaps.ui.wicket.util.DojoClasses;
import org.efaps.ui.wicket.util.DojoWrapper;

/**
 * TODO comment!
 *
 * @author The eFaps Team
 * @version $Id$
 */
public class MenuBarBehavior
    extends AbstractDojoBehavior
{
    /**
     * Needed for serialization.
     */
    private static final long serialVersionUID = 1L;

    /**
     * The tag of the related component must be set, so that a dojo
     * BorderContainer will be rendered.
     *
     * @param _component component this Behavior belongs to
     * @param _tag Tag to write to
     */
    @Override
    public void onComponentTag(final Component _component,
                               final ComponentTag _tag)
    {
        super.onComponentTag(_component, _tag);
        _tag.put("data-dojo-type", "dijit/MenuBar");
        _tag.append("style", "visibility: hidden; position: relative; left: -99999px;", ";");
    }

    /**
     * Render the links for the head.
     *
     * @param _component component the header will be rendered for
     * @param _response resonse to add
     */
    @Override
    public void renderHead(final Component _component,
                           final IHeaderResponse _response)
    {
        super.renderHead(_component, _response);
        _response.render(RequireHeaderItem.forClasses(DojoClasses.MenuBar, DojoClasses.parser));

        _response.render(OnDojoReadyHeaderItem.forScript(DojoWrapper.require(
                            "  domStyle.set(\"" + _component.getMarkupId(true) + "\",\"visibility\",\"visible\");\n"
                            + "  domStyle.set(\"" + _component.getMarkupId(true) + "\",\"position\",\"\");\n"
                            + "  domStyle.set(\"" + _component.getMarkupId(true) + "\",\"left\",\"\");\n"
                            , DojoClasses.domStyle)));
    }
}


/*
 * Copyright 2003 - 2017 The eFaps Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.efaps.ui.wicket.components.gridx.filter;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import org.apache.commons.text.StringEscapeUtils;
import org.apache.wicket.core.util.string.JavaScriptUtils;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.MarkupStream;
import org.apache.wicket.markup.html.WebComponent;
import org.apache.wicket.model.Model;
import org.efaps.admin.access.AccessTypeEnums;
import org.efaps.admin.datamodel.Classification;
import org.efaps.admin.ui.field.Field;
import org.efaps.api.ui.IClassificationFilter;
import org.efaps.ui.wicket.util.DojoClass;
import org.efaps.ui.wicket.util.DojoClasses;
import org.efaps.ui.wicket.util.DojoWrapper;
import org.efaps.util.EFapsException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The Class ClassificationFilter.
 */
public class ClassificationFilter
    extends WebComponent
{

    /** The Constant INPUTNAME. */
    public static final String INPUTNAME = "eFapsClassification";

    /**
     * Logger for this class.
     */
    private static final Logger LOG = LoggerFactory.getLogger(ClassificationFilter.class);

    /** The Constant serialVersionUID. */
    private static final long serialVersionUID = 1L;

    /**
     * Instantiates a new classification filter panel.
     *
     * @param _wicketId the wicket id
     * @param _model the model
     */
    public ClassificationFilter(final String _wicketId,
                                final Model<IClassificationFilter> _model)
    {
        super(_wicketId, _model);
        setOutputMarkupId(true);
    }

    @Override
    public void onComponentTagBody(final MarkupStream _markupStream, final ComponentTag _openTag)
    {
        try {
            final Set<DojoClass> dojoClasses = new HashSet<>();
            Collections.addAll(dojoClasses, DojoClasses.Memory, DojoClasses.ObjectStoreModel, DojoClasses.Tree,
                            DojoClasses.CheckBox);
            final StringBuilder js = new StringBuilder()
                            .append("var classStore = new Memory({\n")
                            .append("data: [\n")
                            .append(getData())
                            .append("],\n")
                            .append("getChildren: function(object){\n")
                            .append(" return this.query({parent: object.id});\n")
                            .append("}\n")
                            .append("});\n")
                            .append("var classModel = new ObjectStoreModel({\n")
                            .append("store: classStore,\n")
                            .append(" query: {id: 'root'}\n")
                            .append("});\n")
                            .append("\n")
                            .append("var tree = new Tree({\n")
                            .append("model: classModel,\n")
                            .append("showRoot: false,\n")
                            .append("autoExpand: true,\n")
                            .append("_createTreeNode: ").append(getCreateTreeNodeScript())
                            .append(" });\n")
                            .append("\n")
                            .append("tree.placeAt('").append(getMarkupId(true)).append("');\n")
                            .append("tree.startup();\n");

            final StringBuilder html = new StringBuilder().append(JavaScriptUtils.SCRIPT_OPEN_TAG)
                            .append(DojoWrapper.require(js, dojoClasses.toArray(new DojoClass[dojoClasses.size()])))
                            .append("\n" + JavaScriptUtils.SCRIPT_CLOSE_TAG);

            replaceComponentTagBody(_markupStream, _openTag, html);
        } catch (final EFapsException e) {
            LOG.error("Catched", e);
        }
    }

    /**
     * Gets the creates the tree node script.
     *
     * @return the creates the tree node script
     */
    protected CharSequence getCreateTreeNodeScript() {
        final StringBuilder js = new StringBuilder();
        js.append("function(args) {\n")
        .append("var tn = new dijit._TreeNode(args);\n")
        .append("tn.labelNode.innerHTML = args.label;\n")
        .append("var cb = new CheckBox({\n")
        .append("name: '").append(INPUTNAME).append("',\n")
        .append("value: args.item.id,\n")
        .append("checked: args.item.selected,\n")
        .append("onChange: function(b){\n")
        .append("this.focusNode.checked=this.checked;\n")
        .append("\n")
        .append("}\n")
        .append("});\n")
        .append("cb.placeAt(tn.labelNode, 'first');\n")
        .append("tn.cb = cb;\n")
        .append("return tn;\n")
        .append("}\n");
        return js;
    }

    /**
     * Gets the data.
     *
     * @return the data
     * @throws EFapsException the e faps exception
     */
    protected CharSequence getData()
        throws EFapsException
    {
        final StringBuilder js = new StringBuilder();
        js.append("{ id: 'root', name: 'You cannot see this one.'}");
        final IClassificationFilter filter = (IClassificationFilter) getDefaultModelObject();
        final Field field = Field.get(filter.getFieldId());
        final String[] names = field.getClassificationName().split(";");
        for (final String className : names) {
            final Classification clazz = Classification.get(className);
            js.append(getDataLine(clazz, filter));
        }
        return js;
    }

    /**
     * Gets the data line.
     *
     * @param _clazz the clazz
     * @param _filter the filter
     * @return the data line
     * @throws EFapsException the e faps exception
     */
    protected CharSequence getDataLine(final Classification _clazz, final IClassificationFilter _filter)
        throws EFapsException
    {
        final StringBuilder js = new StringBuilder();
        if (_clazz.hasAccess(null, AccessTypeEnums.SHOW.getAccessType())) {
            js.append(",\n{id:'").append(_clazz.getUUID()).append("', name:'")
                .append(StringEscapeUtils.escapeEcmaScript(_clazz.getLabel())).append("', parent:'")
                .append(_clazz.isRoot() ? "root" : _clazz.getParentClassification().getUUID()).append("', selected:")
                .append(_filter.contains(_clazz.getUUID())).append("}");
            for (final Classification childClazz: _clazz.getChildClassifications()) {
                js.append(getDataLine(childClazz, _filter));
            }
        }
        return js;
    }
}


/*
 * Copyright 2003 - 2014 The eFaps Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Revision:        $Rev$
 * Last Changed:    $Date$
 * Last Changed By: $Author$
 */

package org.efaps.ui.wicket.models.objects;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import org.apache.wicket.util.io.IClusterable;
import org.efaps.admin.access.AccessTypeEnums;
import org.efaps.admin.datamodel.Classification;
import org.efaps.admin.datamodel.Type;
import org.efaps.admin.dbproperty.DBProperties;
import org.efaps.admin.ui.AbstractUserInterfaceObject.TargetMode;
import org.efaps.admin.ui.field.Field;
import org.efaps.db.Context;
import org.efaps.db.Instance;
import org.efaps.db.InstanceQuery;
import org.efaps.db.MultiPrintQuery;
import org.efaps.db.QueryBuilder;
import org.efaps.ui.wicket.models.AbstractInstanceObject;
import org.efaps.util.EFapsException;
import org.efaps.util.cache.CacheReloadException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Class is used as a model for a classification.
 *
 * @author The eFaps Team
 * @version $Id: UIClassification.java 8530 2013-01-16 01:56:29Z jan@moxter.net$
 */
public final class UIClassification
    implements IFormElement, IClusterable
{

    /**
     * Needed for serialization.
     */
    private static final long serialVersionUID = 1L;

    /**
     * Static part of the key to get the Information stored in the session in
     * relation to this StruturBrowser.
     */
    private static final String USERSESSIONKEY = "org.efaps.ui.wicket.models.objects.UIClassification.UserSessionKey";

    /**
     * Logging instance used in this class.
     */
    private static final Logger LOG = LoggerFactory.getLogger(UIClassification.class);

    /**
     * Id of the field this UIClassification belongs to.
     */
    private final long fieldId;

    /**
     * Is this UIClassification initialized.
     */
    private boolean initialized = false;

    /**
     * Label for this UIClassification.
     */
    private String label;

    /**
     * Is this Classification selected.
     */
    private boolean selected;

    /**
     * Set containing the children of this UIClassification.
     */
    private final List<UIClassification> children = new ArrayList<UIClassification>();

    /**
     * UUID of the classification this UIClassification belongs to.
     */
    private final UUID classificationUUID;

    /**
     * List of classification UUIDs that are connected to the given base
     * instance. This variable is used only for the root. In any instances it
     * will be empty.
     */
    private final Set<UUID> selectedUUID = new HashSet<UUID>();

    /**
     * Contains the parent UIClassification.
     */
    private UIClassification parent;

    /**
     * Is this UIClassification the root.
     */
    private final boolean root;

    /**
     * Is this UIClassification a base classification.
     */
    private final boolean base;

    /**
     * Target mode.
     */
    private final TargetMode mode;

    /**
     * Stores the name of the command that called this object. Needed for
     * getting DBProperties.
     */
    private String commandName;

    /**
     * Is this classification multipleselect.
     */
    private final boolean multipleSelect;

    /**
     * Is this model expanded.
     */
    private boolean expanded;

    /**
     * Instance thisclassificatio belongs to.
     */
    private Instance instance;

    /**
     * @param _fieldId id of the FieldClassification
     * @param _uiObject ui object
     * @throws EFapsException on error
     */
    private UIClassification(final long _fieldId,
                             final AbstractUIObject _uiObject)
        throws EFapsException
    {
        this.classificationUUID = null;
        this.multipleSelect = true;
        this.fieldId = _fieldId;
        this.root = true;
        this.base = false;
        this.mode = _uiObject.getMode();
        this.commandName = _uiObject.getCommand().getName();
        this.instance = _uiObject.getInstance();
    }

    /**
     * Private constructor used for instantiating child UIClassification.
     *
     * @param _uuid UUID of the classification type
     * @param _mode target mode
     * @param _base is base classfication
     * @throws CacheReloadException on error
     */
    private UIClassification(final UUID _uuid,
                             final TargetMode _mode,
                             final boolean _base)
        throws CacheReloadException
    {
        this.multipleSelect = Classification.get(_uuid).isMultipleSelect();
        this.fieldId = 0;
        this.classificationUUID = _uuid;
        this.label = DBProperties.getProperty(Type.get(this.classificationUUID).getName() + ".Label");
        this.root = false;
        this.mode = _mode;
        this.base = _base;
    }

    /**
     * Getter method for instance variable {@link #fieldId}.
     *
     * @return value of instance variable {@link #fieldId}
     */
    public long getFieldId()
    {
        return this.fieldId;
    }

    /**
     * Getter method for the instance variable {@link #multipleSelect}.
     *
     * @return value of instance variable {@link #multipleSelect}
     */
    public boolean isMultipleSelect()
    {
        return this.multipleSelect;
    }

    /**
     * Getter method for the instance variable {@link #expanded}.
     *
     * @return value of instance variable {@link #expanded}
     */
    public boolean isExpanded()
    {
        return this.expanded;
    }

    /**
     * Setter method for instance variable {@link #expanded}.
     *
     * @param _expanded value for instance variable {@link #expanded}
     */
    private void setExpandedInternal(final boolean _expanded)
    {
        this.expanded = _expanded;
    }

    /**
     * Setter method for instance variable {@link #expanded}.
     *
     * @param _expanded value for instance variable {@link #expanded}
     */
    public void setExpanded(final boolean _expanded)
    {
        this.expanded = _expanded;
        storeInSession();
    }

    /**
     * Getter method for instance variable {@link #selected}.
     *
     * @return value of instance variable {@link #selected}
     */
    public boolean isSelected()
    {
        return this.selected;
    }

    /**
     * Setter method for instance variable {@link #selected}.
     *
     * @param _selected value for instance variable {@link #selected}
     */
    public void setSelected(final boolean _selected)
    {
        this.selected = _selected;
    }

    /**
     * Getter method for instance variable {@link #root}.
     *
     * @return value of instance variable {@link #root}
     */
    public boolean isRoot()
    {
        return this.root;
    }

    /**
     * Getter method for the instance variable {@link #base}.
     *
     * @return value of instance variable {@link #base}
     */
    public boolean isBase()
    {
        return this.base;
    }

    /**
     * Getter method for instance variable {@link #label}.
     *
     * @return value of instance variable {@link #label}
     */
    public String getLabel()
    {
        return this.label;
    }

    /**
     * Execute the model.
     * @param _instance Instance
     * @throws EFapsException on error
     */
    public void execute(final Instance _instance)
        throws EFapsException
    {
        UIClassification clazz = this;
        while (!clazz.isRoot()) {
            clazz = clazz.getParent();
        }
        clazz.initialized = true;
        for (final UIClassification child : clazz.getChildren()) {
            final Classification type = (Classification) Type.get(child.getClassificationUUID());
            if (clazz.selectedUUID.contains(child.getClassificationUUID())) {
                child.setSelected(true);
            }
            child.addChildren(child, type.getChildClassifications(), clazz.selectedUUID, _instance);
            clazz.expand();
        }
    }

    /**
     * Expand the Tree.
     */
    @SuppressWarnings("unchecked")
    private void expand()
    {
        try {
            final String key = getCacheKey();
            if (Context.getThreadContext().containsSessionAttribute(key)) {
                final Set<UUID> sessMap = (Set<UUID>) Context
                                .getThreadContext().getSessionAttribute(key);
                setExpandedInternal(sessMap.contains(this.classificationUUID));
                for (final UIClassification uiClazz : getDescendants()) {
                    if (sessMap.contains(uiClazz.classificationUUID)) {
                        uiClazz.setExpandedInternal(true);
                    }
                }
            }
        } catch (final EFapsException e) {
            UIClassification.LOG.error("Error reading Session info for UICLassificagtion called by Filed with ID: {}",
                            this.fieldId, e);
        }
    }

    /**
     * Store the Information in the Session.
     */
    @SuppressWarnings("unchecked")
    private void storeInSession()
    {
        try {
            final Set<UUID> sessMap;
            final String key = getCacheKey();
            if (Context.getThreadContext().containsSessionAttribute(key)) {
                sessMap = (Set<UUID>) Context.getThreadContext().getSessionAttribute(key);
            } else {
                sessMap = new HashSet<UUID>();
            }
            if (this.expanded) {
                sessMap.add(this.classificationUUID);
            } else if (sessMap.contains(this.classificationUUID)) {
                sessMap.remove(this.classificationUUID);
            }
            Context.getThreadContext().setSessionAttribute(key, sessMap);
        } catch (final EFapsException e) {
            UIClassification.LOG.error("Error storing Session info for UICLassificagtion called by Filed with ID: {}",
                            this.fieldId, e);
        }
    }

    /**
     * Recursive method used to add the children to this UIClassification.
     *
     * @param _parent parent
     * @param _children children
     * @param _selectedUUID set of selected classification uuids
     * @param _instance instance the classifcation belongs to
     * @throws EFapsException on error
     */
    private void addChildren(final UIClassification _parent,
                             final Set<Classification> _children,
                             final Set<UUID> _selectedUUID,
                             final Instance _instance)
        throws EFapsException
    {
        for (final Classification child : _children) {
            boolean access;
            if (!child.isAbstract()) {
                final Instance inst = AbstractInstanceObject.getInstance4Create(child);
                access = child.hasAccess(inst, getMode() == TargetMode.CREATE
                                || getMode() == TargetMode.EDIT ? AccessTypeEnums.CREATE.getAccessType()
                                : AccessTypeEnums.SHOW.getAccessType());
            } else {
                access = true;
            }
            if (access) {
                final UIClassification childUI = new UIClassification(child.getUUID(), _parent.mode, false);
                if (_selectedUUID.contains(child.getUUID())) {
                    childUI.selected = true;
                }
                childUI.addChildren(childUI, child.getChildClassifications(), _selectedUUID, _instance);
                _parent.children.add(childUI);
                childUI.setParent(_parent);
            }
        }
        Collections.sort(_parent.children, new Comparator<UIClassification>()
        {
            @Override
            public int compare(final UIClassification _class0,
                               final UIClassification _class2)
            {
                return _class0.getLabel().compareTo(_class2.getLabel());
            }
        });
    }

    /**
     * Method to get the key to the instances related to this classification.
     *
     * @param _instance Instance the related instance key are searched for
     * @return Map of instance keys
     * @throws EFapsException on error
     */
    public Map<UUID, String> getClassInstanceKeys(final Instance _instance)
        throws EFapsException
    {
        final Map<UUID, String> ret = new HashMap<UUID, String>();
        UIClassification clazz = this;
        while (!clazz.isRoot()) {
            clazz = clazz.getParent();
        }
        Type reltype = null;
        for (final UIClassification child : clazz.getChildren()) {
            final Classification classType = (Classification) Type.get(child.getClassificationUUID());
            if (!classType.getClassifyRelationType().equals(reltype)) {
                final QueryBuilder queryBldr = new QueryBuilder(classType.getClassifyRelationType());
                queryBldr.addWhereAttrEqValue(classType.getRelLinkAttributeName(), _instance.getId());
                final MultiPrintQuery multi = queryBldr.getPrint();
                multi.addAttribute(classType.getRelTypeAttributeName());
                multi.execute();
                while (multi.next()) {
                    final Long typeid = multi.<Long>getAttribute(classType.getRelTypeAttributeName());
                    final Classification subClassType = (Classification) Type.get(typeid);
                    final QueryBuilder subQueryBldr = new QueryBuilder(subClassType);
                    subQueryBldr.addWhereAttrEqValue(subClassType.getLinkAttributeName(), _instance.getId());
                    subQueryBldr.addOrderByAttributeAsc("ID");
                    final InstanceQuery query = subQueryBldr.getQuery();
                    query.execute();
                    if (query.next()) {
                        // TODO must return an instanceKey!!! not necessary the
                        // oid
                        final String instanceKey = query.getCurrentValue().getOid();
                        ret.put(query.getCurrentValue().getType().getUUID(), instanceKey);
                        this.selectedUUID.add(query.getCurrentValue().getType().getUUID());
                    }
                }
            }
            reltype = classType.getClassifyRelationType();
        }
        return ret;
    }

    /**
     * Getter method for instance variable {@link #initialized}.
     *
     * @return value of instance variable {@link #initialized}
     */
    public boolean isInitialized()
    {
        return this.initialized;
    }

    /**
     * Getter method for instance variable {@link #classificationUUID}.
     *
     * @return value of instance variable {@link #classificationUUID}
     */
    public UUID getClassificationUUID()
    {
        return this.classificationUUID;
    }

    /**
     * Getter method for instance variable {@link #children}.
     *
     * @return value of instance variable {@link #children}
     */
    public List<UIClassification> getChildren()
    {
        return this.children;
    }

    /**
     * @return a flat list of all decscandants.
     */
    public List<UIClassification> getDescendants()
    {
        final List<UIClassification> ret = new ArrayList<UIClassification>();
        for (final UIClassification uiClass : getChildren()) {
            ret.add(uiClass);
            ret.addAll(uiClass.getDescendants());
        }
        return ret;
    }

    /**
     * Getter method for instance variable {@link #parent}.
     *
     * @return value of instance variable {@link #parent}
     */
    public UIClassification getParent()
    {
        return this.parent;
    }

    /**
     * Setter method for instance variable {@link #parent}.
     *
     * @param _parent value for instance variable {@link #parent}
     */
    private void setParent(final UIClassification _parent)
    {
        this.parent = _parent;
    }

    /**
     * Getter method for instance variable {@link #mode}.
     *
     * @return value of instance variable {@link #mode}
     */
    public TargetMode getMode()
    {
        return this.mode;
    }

    /**
     * Getter method for instance variable {@link #commandName}.
     *
     * @return value of instance variable {@link #commandName}
     */
    public String getCommandName()
    {
        return this.commandName;
    }

    /**
     * Method to add a uuid to the set of selected classifications. This method
     * should only be called on a root classification. e.;g. on cretae mode to
     * set the default selected classifications.
     *
     * @param _uuid uuid to set as selected
     */
    public void addSelectedUUID(final UUID _uuid)
    {
        this.selectedUUID.add(_uuid);
    }

    /**
     * This method generates the Key for a UserAttribute by using the UUID of
     * the Command and the given static part, so that for every StruturBrowser a
     * unique key for expand etc, is created.
     *
     * @return String with the key
     */
    public String getCacheKey()
    {
        String ret = "noKey";
        UIClassification clazz = this;
        while (!clazz.isRoot()) {
            clazz = clazz.getParent();
        }
        final Field field = Field.get(clazz.getFieldId());
        if (field != null) {
            try {
                ret = field.getCollection().getUUID().toString() + "-" + field.getName() + "-"
                                + UIClassification.USERSESSIONKEY;
            } catch (final CacheReloadException e) {
                UIClassification.LOG.error("Cannot generate CacheKey", e);
            }
        }
        return ret;
    }

    @Override
    public String toString()
    {
        return getLabel();
    }

    /**
     * @return instance
     */
    public Instance getInstance()
    {
        Instance ret = this.instance;
        UIClassification clazz = this;
        while (!clazz.isRoot() && ret == null) {
            clazz = clazz.getParent();
            ret = clazz.instance;
        }
        return ret;
    }

    /**
     * @param _field FieldClassification
     * @param _uiObject ui object
     * @throws EFapsException on error
     * @return new UIClassifcation
     */
    public static UIClassification getUIClassification(final Field _field,
                                                       final AbstractUIObject _uiObject)
        throws EFapsException
    {
        final String[] names = _field.getClassificationName().split(";");
        final UIClassification root = new UIClassification(_field.getId(), _uiObject);
        for (final String className : names) {
            final Classification clazz = Classification.get(className);
            if (clazz.hasAccess(root.getInstance(), root.getMode() == TargetMode.CREATE
                            || root.getMode() == TargetMode.EDIT ? AccessTypeEnums.CREATE.getAccessType()
                            : AccessTypeEnums.SHOW.getAccessType())) {
                final UIClassification childUI = new UIClassification(clazz.getUUID(), root.getMode(), true);
                root.children.add(childUI);
                childUI.setParent(root);
            }
        }
        return root;
                                                                       }
}


/*
 * Copyright 2003 - 2016 The eFaps Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.efaps.ui.wicket.behaviors.dojo;

import org.apache.wicket.Component;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.head.CssHeaderItem;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.request.resource.CssResourceReference;
import org.apache.wicket.request.resource.ResourceReference;
import org.efaps.ui.wicket.util.DojoClasses;

/**
 * Class renders a dojo border. It can be used to render a slipt between the
 * children of this container. BorderContainer operates in a choice of two
 * layout modes: <br>
 * the design attribute may be set to "headline" (by default) or "sidebar". With
 * the "headline" layout, the top and bottom sections extend the entire width of
 * the box and the remaining regions are placed in the middle. With the
 * "sidebar" layout, the side panels take priority, extending the full height of
 * the box.
 *
 * @author The eFaps Team
 */
public class BorderContainerBehavior
    extends AbstractDojoBehavior
{

    /**
     * Needed for serialization.
     */
    private static final long serialVersionUID = 1L;

    /**
     * Reference to the stylesheet.
     */
    public static final ResourceReference CSS_SPLITTER = new CssResourceReference(BorderContainerBehavior.class,
                    "dojox/layout/resources/ToggleSplitter.css");

    /**
     * Enum for the different Designs of a dojo BorderContainer.
     */
    public enum Design
    {
        /** "headline" design. */
        HEADLINE("headline"),
        /** "sidebar" design. */
        SIDEBAR("sidebar");

        /**
         * Stores the key of the Design.
         */
        private final String key;

        /**
         * Private Constructor.
         *
         * @param _key Key
         */
        private Design(final String _key)
        {
            this.key = _key;
        }

        /**
         * Getter method for instance variable {@link #key}.
         *
         * @return value of instance variable {@link #key}
         */
        public String getKey()
        {
            return this.key;
        }
    }

    /**
     * Stores the design of this BorderBehavior.
     */
    private final Design design;

    /**
     * Will the Container use a toggle splitter.
     */
    private final boolean toggleSplitter;

    /**
     * Constructor.
     *
     * @param _design           Design for this BorderBehavior.
     * @param _toggleSplitter   Will the Container use a toggle splitter.
     */
    public BorderContainerBehavior(final Design _design,
                                   final boolean _toggleSplitter)
    {
        this.design = _design;
        this.toggleSplitter = _toggleSplitter;
    }

    /**
     * The tag of the related component must be set, so that a dojo
     * BorderContainer will be rendered.
     *
     * @param _component component this Behavior belongs to
     * @param _tag Tag to write to
     */
    @Override
    public void onComponentTag(final Component _component,
                               final ComponentTag _tag)
    {
        super.onComponentTag(_component, _tag);
        _tag.put("data-dojo-type", "dijit/layout/BorderContainer");
        _tag.append("data-dojo-props", "design: '" + this.design.key + "'", ",");
        _tag.append("class", "tundra eFapsBorderContainer", " ");
    }

    /**
     * Render the links for the head.
     *
     * @param _component component the header will be rendered for
     * @param _response resonse to add
     */
    @Override
    public void renderHead(final Component _component,
                           final IHeaderResponse _response)
    {
        super.renderHead(_component, _response);
        if (this.toggleSplitter) {
            _response.render(RequireHeaderItem.forClasses(DojoClasses.ToggleSplitter));
            _response.render(CssHeaderItem.forReference(BorderContainerBehavior.CSS_SPLITTER));
        }
        _response.render(RequireHeaderItem.forClasses(DojoClasses.BorderContainer, DojoClasses.parser));
    }
}


/*
 * Copyright 2003 - 2017 The eFaps Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.efaps.ui.wicket.models.field.factories;

import org.apache.commons.lang3.StringUtils;
import org.apache.wicket.Component;
import org.apache.wicket.model.Model;
import org.efaps.admin.datamodel.ui.DateUI;
import org.efaps.db.Context;
import org.efaps.ui.wicket.components.date.DatePanel;
import org.efaps.ui.wicket.models.field.AbstractUIField;
import org.efaps.ui.wicket.util.DateUtil;
import org.efaps.util.EFapsException;
import org.joda.time.DateTime;

/**
 * TODO comment!
 *
 * @author The eFaps Team
 */
@SuppressWarnings("checkstyle:abstractclassname")
public final class DateUIFactory
    extends AbstractUIFactory
{

    /**
     * Factory Instance.
     */
    private static DateUIFactory FACTORY;

    /**
     * Singelton.
     */
    private DateUIFactory()
    {
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Component getEditable(final String _wicketId,
                                 final AbstractUIField _abstractUIField)
        throws EFapsException
    {
        Component ret = null;
        if (applies(_abstractUIField)) {
            ret = new DatePanel(_wicketId, Model.of(_abstractUIField), _abstractUIField.getFieldConfiguration(),
                            _abstractUIField.getValue().getEditValue(_abstractUIField.getParent().getMode()));
        }
        return ret;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean applies(final AbstractUIField _abstractUIField)
        throws EFapsException
    {
        return _abstractUIField.getValue().getUIProvider() instanceof DateUI;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected String getReadOnlyValue(final AbstractUIField _abstractUIField)
        throws EFapsException
    {
        String strValue = "";
        final Object valueTmp = _abstractUIField.getValue()
                        .getReadOnlyValue(_abstractUIField.getParent().getMode());
        if (valueTmp instanceof DateTime) {
            final DateTime datetime = (DateTime) valueTmp;
            final DateTime dateTmp = datetime.withChronology(Context.getThreadContext().getChronology())
                            .withTimeAtStartOfDay();
            strValue = dateTmp.toString(DateUtil.getDateFormatter());
        }
        return strValue;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getKey()
    {
        return DateUIFactory.class.getName();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getPickListValue(final AbstractUIField _uiField)
        throws EFapsException
    {
        return getReadOnlyValue(_uiField);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Comparable<?> getCompareValue(final AbstractUIField _uiField)
        throws EFapsException
    {
        Comparable<?> ret = (Comparable<?>) _uiField.getValue().getReadOnlyValue(_uiField.getParent().getMode());
        if (ret instanceof String && StringUtils.isEmpty((String) ret)) {
            ret = null;
        }
        return ret;
    }

    /**
     * @return IComponentFactory instance
     */
    public static IComponentFactory get()
    {
        if (DateUIFactory.FACTORY == null) {
            DateUIFactory.FACTORY = new DateUIFactory();
        }
        return DateUIFactory.FACTORY;
    }
}


/*
 * Copyright 2015-2016 Hewlett-Packard Development Company, L.P.
 * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
 */

package com.hp.autonomy.hod.client.api.analysis.viewdocument;

import com.hp.autonomy.hod.client.util.MultiMap;
import lombok.AccessLevel;
import lombok.Data;
import lombok.Setter;
import lombok.experimental.Accessors;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * Helper class for building up optional parameters for the Query Text Index API. The default value for all parameters
 * is null. Null parameters will not be sent to HP Haven OnDemand
 */
@Data
@Accessors(chain = true)
public class ViewDocumentRequestBuilder {

    private List<String> highlightExpressions = new ArrayList<>();
    private List<String> startTags = new ArrayList<>();
    private List<String> endTags = new ArrayList<>();

    /**
     * Sets the value for the raw_html parameter
     *
     * @param rawHtml Value of the raw_html parameter
     */
    @Setter(AccessLevel.PACKAGE) // setting this parameter messes with return values, so should only be used with the appropriate methods
    private Boolean rawHtml;

    /**
     * @param highlightExpressions Sets the value of the highlight_expressions parameter
     * @return this
     */
    public ViewDocumentRequestBuilder setHighlightExpressions(final List<String> highlightExpressions) {
        this.highlightExpressions = highlightExpressions;
        return this;
    }

    /**
     * Adds values to the highlight_expression parameter
     *
     * @param highlightExpression  The first highlight expression
     * @param highlightExpressions The remaining highlight expressions
     * @return this
     */
    public ViewDocumentRequestBuilder addHighlightExpressions(final String highlightExpression, final String... highlightExpressions) {
        this.highlightExpressions.add(highlightExpression);
        this.highlightExpressions.addAll(Arrays.asList(highlightExpressions));
        return this;
    }

    /**
     * @param startTags Sets the value of the start_tag parameter
     * @return this
     */
    public ViewDocumentRequestBuilder setStartTags(final List<String> startTags) {
        this.startTags = startTags;
        return this;
    }

    /**
     * Adds values to the start_tag parameter
     *
     * @param startTag  The first start tag
     * @param startTags The remaining start tags
     * @return this
     */
    public ViewDocumentRequestBuilder addStartTags(final String startTag, final String... startTags) {
        this.startTags.add(startTag);
        this.startTags.addAll(Arrays.asList(startTags));
        return this;
    }

    /**
     * @param endTags Sets the value of the end_tag parameter
     * @return this
     */
    public ViewDocumentRequestBuilder setEndTags(final List<String> endTags) {
        this.endTags = endTags;
        return this;
    }

    /**
     * Adds values to the end_tag parameter
     *
     * @param endTag  The first end tag
     * @param endTags The remaining end tags
     * @return this
     */
    public ViewDocumentRequestBuilder addEndTags(final String endTag, final String... endTags) {
        this.endTags.add(endTag);
        this.endTags.addAll(Arrays.asList(endTags));
        return this;
    }

    /**
     * @return A map of query parameters suitable for use with {@link ViewDocumentBackend}. get is NOT supported on
     * the resulting map
     */
    Map<String, Object> build() {
        final Map<String, Object> params = new MultiMap<>();

        params.put("raw_html", rawHtml);

        for (final String highlightExpression : highlightExpressions) {
            params.put("highlight_expression", highlightExpression);
        }

        for (final String startTag : startTags) {
            params.put("start_tag", startTag);
        }

        for (final String endTag : endTags) {
            params.put("end_tag", endTag);
        }

        return params;
    }

}


/*
 * Copyright 2003 - 2014 The eFaps Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Revision:        $Rev$
 * Last Changed:    $Date$
 * Last Changed By: $Author$
 */

package org.efaps.ui.wicket.behaviors.dojo;

import java.util.ArrayList;
import java.util.List;

import org.apache.wicket.Component;
import org.apache.wicket.markup.ComponentTag;

/**
 * Class renders a dojo editor.This widget provides basic WYSIWYG editing
 * features, based on the browser's underlying rich text editing capability,
 * accompanied by a toolbar (dijit.Toolbar). A plugin model is available
 * to extend the editor's capabilities as well as the the options available
 * in the toolbar. Content generation may vary across browsers, and clipboard
 * operations may have different results, to name a few limitations.
 * Note: this widget should not be used with the HTML <TEXTAREA> tag.
 * The default menu from dojo is:
 * UNDO,REDO,SEPERATOR,CUT,COPY,PASTE,SEPERATOR,BOLD,ITALIC,UNDERLINE,
 * STRIKETROUGH,SEPERATOR,ORDEREDLIST,UNORDERLIST,INDENT,OUTENT,
 * SEPERATOR,JUSTIFYLEFT,JUSTIFYRIGHT,JUSTIFYCENTER,JUSTIFYFULL
 *
 * @author The eFaps Team
 * @version $Id$
 */
public class EditorBehavior extends AbstractDojoBehavior
{

    /**
     * Needed for serialization.
     */
    private static final long serialVersionUID = 1L;

    /**
     * Enum for the different MenuCommands of a dojo Editor.
     */
    public enum MenuCommands
    {
        /** undo. */
        UNDO("undo"),
        /** redo. */
        REDO("redo"),
        /** cut. */
        CUT("cut"),
        /** paste. */
        COPY("copy"),
        /** paste. */
        PASTE("paste"),
        /** selectAll. */
        SELECTALL("selectAll"),
        /** bold. */
        BOLD("bold"),
        /** italic. */
        ITALIC("italic"),
        /** underline. */
        UNDERLINE("underline"),
        /** strikethrough. */
        STRIKETHROUGH("strikethrough"),
        /** subscript. */
        SUBSRCIPT("subscript"),
        /** superscript. */
        SUPERSCRIPT("superscript"),
        /** removeFormat. */
        REMOVEFORMAT("removeFormat"),
        /** insertOrderedList. */
        ORDEREDLIST("insertOrderedList"),
        /** insertUnorderedList. */
        UNORDERLIST("insertUnorderedList"),
        /** insertHorizontalRule. */
        HR("insertHorizontalRule"),
        /** indent. */
        INDENT("indent"),
        /** outdent. */
        OUTENT("outdent"),
        /** justifyLeft. */
        JUSTIFYLEFT("justifyLeft"),
        /** justifyRight. */
        JUSTIFYRIGHT("justifyRight"),
        /** justifyCenter. */
        JUSTIFYCENTER("justifyCenter"),
        /** justifyFull. */
        JUSTIFYFULL("justifyFull"),
        /** createLink. */
        CREATELINK("createLink"),
        /** unlink. */
        UNLINK("unlink"),
        /** delete. */
        DELETE("delete"),
        /** |. */
        SEPERATOR("|");

        /**
         * Stores the key of the MenuCommands.
         */
        private final String key;

        /**
         * Private Constructor.
         *
         * @param _key Key
         */
        private MenuCommands(final String _key)
        {
            this.key = _key;
        }

        /**
         * Getter method for instance variable {@link #key}.
         *
         * @return value of instance variable {@link #key}
         */
        public String getKey()
        {
            return this.key;
        }
    }

    /**
     * Stores the design of this BorderBehavior.
     */
    private final List<EditorBehavior.MenuCommands> cmds = new ArrayList<EditorBehavior.MenuCommands>();

    /**
     * Constructor.
     *
     * @param _cmds List of cmds to be used in this editor, null if default
     *              from dojo should be used
     */
    public EditorBehavior(final List<EditorBehavior.MenuCommands> _cmds)
    {
        if (_cmds != null) {
            this.cmds.addAll(_cmds);
        }
    }

    /**
     * The tag of the related component must be set, so that a dojo
     * BorderContainer will be rendered.
     *
     * @param _component component this Behavior belongs to
     * @param _tag Tag to write to
     */
    @Override
    public void onComponentTag(final Component _component,
                               final ComponentTag _tag)
    {
        super.onComponentTag(_component, _tag);
        _tag.put("dojoType", "dijit.Editor");
        if (this.cmds.size() > 0) {
            final StringBuilder str = new StringBuilder();
            str.append("[");
            boolean first = true;
            for (final MenuCommands cmd : this.cmds) {
                if (first) {
                    first = false;
                } else {
                    str.append(",");
                }
                str.append("'").append(cmd.key).append("'");
            }
            str.append("]");
            _tag.put("plugins", str.toString());
        }
    }
}


/*
 * Copyright 2003 - 2014 The eFaps Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Revision:        $Rev$
 * Last Changed:    $Date$
 * Last Changed By: $Author$
 */

package org.efaps.ui.wicket.models.field.factories;

import org.apache.wicket.Component;
import org.apache.wicket.model.Model;
import org.efaps.admin.datamodel.IEnum;
import org.efaps.admin.datamodel.ui.EnumUI;
import org.efaps.ui.wicket.components.values.RadioField;
import org.efaps.ui.wicket.models.field.AbstractUIField;
import org.efaps.ui.wicket.models.field.set.UIFieldSetValue;
import org.efaps.ui.wicket.util.EnumUtil;
import org.efaps.util.EFapsException;

/**
 * TODO comment!
 *
 * @author The eFaps Team
 * @version $Id$
 */
// CHECKSTYLE:OFF
public final class EnumUIFactory
    extends AbstractUIFactory
// CHECKSTYLE:ON
{

    /**
     * Factory Instance.
     */
    private static EnumUIFactory FACTORY;

    /**
     * Singelton.
     */
    private EnumUIFactory()
    {
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Component getEditable(final String _wicketId,
                                 final AbstractUIField _uiField)
        throws EFapsException
    {
        Component ret = null;
        if (applies(_uiField)) {
            ret = new RadioField(_wicketId, Model.of(_uiField), _uiField.getValue().getEditValue(
                            _uiField.getParent().getMode()),
                            _uiField.getFieldConfiguration(),
                            _uiField instanceof UIFieldSetValue);
        }
        return ret;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean applies(final AbstractUIField _uiField)
        throws EFapsException
    {
        return _uiField.getValue().getUIProvider() instanceof EnumUI;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected String getReadOnlyValue(final AbstractUIField _uiField)
        throws EFapsException
    {
        final Object valueTmp = _uiField.getValue()
                        .getReadOnlyValue(_uiField.getParent().getMode());
        final String ret = valueTmp == null ? null : EnumUtil.getUILabel((IEnum) valueTmp);
        return ret;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getKey()
    {
        return EnumUIFactory.class.getName();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getPickListValue(final AbstractUIField _uiField)
        throws EFapsException
    {
        return getReadOnlyValue(_uiField);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Comparable<String> getCompareValue(final AbstractUIField _uiField)
        throws EFapsException
    {
        return getReadOnlyValue(_uiField);
    }

    /**
     * @return IComponentFactory instance
     */
    public static IComponentFactory get()
    {
        if (EnumUIFactory.FACTORY == null) {
            EnumUIFactory.FACTORY = new EnumUIFactory();
        }
        return EnumUIFactory.FACTORY;
    }
}


/*
 * Copyright 2003 - 2016 The eFaps Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package org.efaps.ui.wicket.components.dashboard;

import java.util.Iterator;

import org.apache.wicket.Component;
import org.apache.wicket.ajax.AbstractAjaxTimerBehavior;
import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.MarkupStream;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.repeater.RepeatingView;
import org.apache.wicket.model.IModel;
import org.apache.wicket.request.IRequestHandler;
import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.request.handler.resource.ResourceReferenceRequestHandler;
import org.apache.wicket.util.time.Duration;
import org.efaps.api.background.IExecutionBridge;
import org.efaps.ui.wicket.EFapsApplication;
import org.efaps.ui.wicket.EFapsSession;
import org.efaps.ui.wicket.components.embeddedlink.LinkElementLink;
import org.efaps.ui.wicket.models.EmbeddedLink;
import org.efaps.ui.wicket.models.EsjpInvoker;
import org.efaps.util.EFapsBaseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The Class DashboardPanel.
 *
 * @author The eFaps Team
 */
public class DashboardPanel
    extends Panel
{

    /**
     * The component id which will be used to load the lazily loaded component.
     */
    public static final String LAZY_LOAD_COMPONENT_ID = "content";

    /** */
    private static final long serialVersionUID = 1L;

    /**
     * Logger for this class.
     */
    private static final Logger LOG = LoggerFactory.getLogger(DashboardPanel.class);

    /**
     * The state.
     * 0:add loading component
     * 1:loading component added, waiting for ajax replace
     * 2:ajax replacement completed
     */
    private byte state = 0;

    /** The job name. */
    private String jobName;

    /**
     * Instantiates a new panel.
     *
     * @param _wicketId the _wicket id
     * @param _model the _model
     */
    public DashboardPanel(final String _wicketId,
                          final IModel<EsjpInvoker> _model)
    {
        super(_wicketId, _model);

        setOutputMarkupId(true);
        add(new WebMarkupContainer("hiddenRepeater").setOutputMarkupId(true).setVisible(false));

        add(new AbstractAjaxTimerBehavior(Duration.milliseconds(500))
        {

            private static final long serialVersionUID = 1L;

            @Override
            protected void onTimer(final AjaxRequestTarget _target)
            {
                if (DashboardPanel.this.state < 2) {
                    if (DashboardPanel.this.jobName != null) {
                        final IExecutionBridge bridge = EFapsSession.get().getBridge4Job(DashboardPanel.this.jobName,
                                        true);
                        if (bridge == null) {
                            stop(_target);
                        } else if (bridge.isFinished()) {
                            final Component component = getLazyLoadComponent(LAZY_LOAD_COMPONENT_ID, (String) bridge
                                            .getContent());
                            DashboardPanel.this.replace(component);
                            setState((byte) 2);
                            stop(_target);
                        }
                    }
                    setUpdateInterval(Duration.seconds(3));
                    final RepeatingView hiddenRepeater = new RepeatingView("hiddenRepeater");
                    DashboardPanel.this.replace(hiddenRepeater);
                    final Iterator<EmbeddedLink> linksIter = EFapsSession.get().getEmbededLinks().iterator();
                    while (linksIter.hasNext()) {
                        final EmbeddedLink link = linksIter.next();
                        if (DashboardPanel.this.jobName.equals(link.getIdentifier())) {
                            hiddenRepeater.add(new LinkElementLink(hiddenRepeater.newChildId(), link));
                            linksIter.remove();
                        }
                    }
                }
                _target.add(DashboardPanel.this);
            }
        });
    }

    /**
     * Gets the lazy load component.
     *
     * @param _markupId the _markup id
     * @param _html the _html
     * @return the lazy load component
     */
    public Component getLazyLoadComponent(final String _markupId,
                                          final String _html)
    {
        return new WebMarkupContainer(_markupId)
        {
            /** */
            private static final long serialVersionUID = 1L;

            @Override
            public void onComponentTagBody(final MarkupStream _markupStream,
                                           final ComponentTag _openTag)
            {
                replaceComponentTagBody(_markupStream, _openTag, _html);
            }
        };
    }

    @Override
    public boolean isVisible()
    {
        final EsjpInvoker invoker = (EsjpInvoker) getDefaultModelObject();
        return invoker.isVisible();
    }

    /**
     * @see org.apache.wicket.Component#onBeforeRender()
     */
    @Override
    protected void onBeforeRender()
    {
        if (this.state == 0) {
            add(getLoadingComponent(LAZY_LOAD_COMPONENT_ID));
            setState((byte) 1);
            try {
                this.jobName = ((EsjpInvoker) getDefaultModelObject()).getSnipplet().getIdentifier();
                IExecutionBridge bridge = EFapsSession.get().getBridge4Job(this.jobName, false);
                if (bridge == null) {
                    bridge = EFapsApplication.get().launch(new DashboardJob(
                                    (EsjpInvoker) getDefaultModelObject()), this.jobName);
                }
                this.jobName = bridge.getJobName();
            } catch (final EFapsBaseException e) {
                LOG.error("Catched error on startng background job.", e);
            }
        }
        super.onBeforeRender();
    }

    /**
     * Sets the state.
     *
     * @param _state the new state
     */
    private void setState(final byte _state)
    {
        this.state = _state;
        getPage().dirty();
    }

    /**
     * Gets the loading component.
     *
     * @param _markupId the markup id
     * @return The component to show while the real component is being created.
     */
    public Component getLoadingComponent(final String _markupId)
    {
        final IRequestHandler handler = new ResourceReferenceRequestHandler(AbstractDefaultAjaxBehavior.INDICATOR);
        return new Label(_markupId, "<img alt=\"Loading...\" src=\"" + RequestCycle.get().urlFor(handler) + "\"/>")
                        .setEscapeModelStrings(false);
    }
}


/*
 * Copyright 2003 - 2014 The eFaps Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Revision:        $Rev$
 * Last Changed:    $Date$
 * Last Changed By: $Author$
 */

package org.efaps.ui.wicket.components.modalwindow;

import org.apache.wicket.PageReference;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.apache.wicket.model.Model;
import org.apache.wicket.request.cycle.RequestCycle;
import org.efaps.ui.wicket.models.objects.AbstractUIObject;
import org.efaps.ui.wicket.models.objects.UIForm;
import org.efaps.ui.wicket.models.objects.UIStructurBrowser;
import org.efaps.ui.wicket.models.objects.UITable;
import org.efaps.ui.wicket.models.objects.grid.UIGrid;
import org.efaps.ui.wicket.pages.content.AbstractContentPage;
import org.efaps.ui.wicket.pages.content.form.FormPage;
import org.efaps.ui.wicket.pages.content.grid.GridPage;
import org.efaps.ui.wicket.pages.content.structurbrowser.StructurBrowserPage;
import org.efaps.ui.wicket.pages.content.table.TablePage;
import org.efaps.ui.wicket.pages.error.ErrorPage;
import org.efaps.util.EFapsException;

/**
 * Class implements the WindowClosedCallback to be able to update (refresch)
 * the parent page on closing a modal window.
 *
 * @author The eFaps Team
 * @version $Id$
 */
public class UpdateParentCallback
    implements ModalWindow.WindowClosedCallback
{

    /**
     * Needed for serialization.
     */
    private static final long serialVersionUID = 1L;

    /**
     * Reference to the Page this call back belongs to.
     */
    private final PageReference pageReference;

    /**
     * Modal window this call back belongs to.
     */
    private final ModalWindowContainer modalwindow;

    /**
     * Must the model of the page be updated on update of the parent page.
     */
    private final boolean clearmodel;

    /**
     * Constructor setting the panel and the modal window.
     *
     * @see #UpdateParentCallback(Component, ModalWindowContainer, boolean)
     *
     * @param _pageReference Reference to the Page this call back belongs to
     * @param _modalwindow modal window belonging to this call back
     *
     */
    public UpdateParentCallback(final PageReference _pageReference,
                                final ModalWindowContainer _modalwindow)
    {
        this(_pageReference, _modalwindow, true);
    }

    /**
     * Constructor setting the panel and the modal window.
     *
     *
     *
     * @param _pageReference Reference to the Page this call back belongs to
     * @param _modalwindow modal window belonging to this call back
     * @param _clearmodel must the model of the page be updated
     */
    public UpdateParentCallback(final PageReference _pageReference,
                                final ModalWindowContainer _modalwindow,
                                final boolean _clearmodel)
    {
        this.pageReference = _pageReference;
        this.modalwindow = _modalwindow;
        this.clearmodel = _clearmodel;
    }

    /**
     * Method is executed on close of the modal window.
     *
     * @param _target Target
     */
    @Override
    public void onClose(final AjaxRequestTarget _target)
    {
        if (this.modalwindow.isUpdateParent()) {
            final Object object = this.pageReference.getPage().getDefaultModelObject();
            try {
                if (object instanceof AbstractUIObject) {

                    final AbstractUIObject uiObject = (AbstractUIObject) object;
                    if (this.clearmodel) {
                        uiObject.resetModel();
                    }
                    AbstractContentPage page = null;

                    if (uiObject instanceof UITable) {
                        page = new TablePage(Model.of((UITable) uiObject), ((AbstractContentPage) this.pageReference
                                        .getPage()).getModalWindow(), ((AbstractContentPage) this.pageReference
                                                        .getPage()).getCalledByPageReference());
                    } else if (uiObject instanceof UIForm) {
                        page = new FormPage(Model.of((UIForm) uiObject), ((AbstractContentPage) this.pageReference
                                        .getPage()).getModalWindow(), ((AbstractContentPage) this.pageReference
                                                        .getPage()).getCalledByPageReference());
                    } else if (uiObject instanceof UIStructurBrowser) {
                        page = new StructurBrowserPage(Model.of((UIStructurBrowser) uiObject),
                                        ((AbstractContentPage) this.pageReference.getPage()).getModalWindow(),
                                        ((AbstractContentPage) this.pageReference.getPage())
                                                        .getCalledByPageReference());
                    }
                    RequestCycle.get().setResponsePage(page);
                } else if (object instanceof UIGrid) {
                    final UIGrid uiGrid = (UIGrid) object;
                    uiGrid.reload();
                    RequestCycle.get().setResponsePage(new GridPage(Model.of(uiGrid)));
                }
            } catch (final EFapsException e) {
                RequestCycle.get().setResponsePage(new ErrorPage(e));
            }
        }
    }
}


/*
 * Copyright 2003 - 2018 The eFaps Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.efaps.ui.wicket.components.menu;

import org.apache.wicket.model.IModel;
import org.efaps.ui.wicket.models.objects.UIMenuItem;
import org.efaps.ui.wicket.pages.connection.ConnectionPage;
import org.efaps.util.EFapsException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Render an home link.
 *
 * @author The eFaps Team
 */
public class ConnectionItem
    extends LinkItem
{

    /**
     * Needed for serialization.
     */
    private static final long serialVersionUID = 1L;

    /**
     * Logger for this class.
     */
    private static final Logger LOG = LoggerFactory.getLogger(ConnectionItem.class);

    /**
     * @param _wicketId     wicketId for this item
     * @param _model        model for this item
     */
    public ConnectionItem(final String _wicketId,
                         final IModel<UIMenuItem> _model)
    {
        super(_wicketId, _model);
    }

    /**
     * On click it is evaluated what must be responded.
     */
    @Override
    public void onClick()
    {
        try {
            setResponsePage(new ConnectionPage(getPage().getPageReference()));
        } catch (final EFapsException e) {
            ConnectionItem.LOG.error("", e);
        }
    }
}


/*
 * Copyright 2003 - 2017 The eFaps Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.efaps.ui.wicket.models.objects;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.wicket.util.io.IClusterable;

/**
 * Class is used to create wizard like behavior for a webpage. Meaning that it
 * is possible to go forward and backward in the pages without loosing
 * parameters, which were already given from the user.<br>
 * It contains a list that stores the UIObjects hyrachical so that they can be
 * accessed using methods like previous.
 *
 * @author The eFaps Team
 */
public class UIWizardObject
    implements IClusterable
{

    /**
     * Needed for serialization.
     */
    private static final long serialVersionUID = 1L;

    /**
     * Mapping between UIObject and parameters.
     */
    private final Map<IWizardElement, Map<String, String[]>> parameters
            = new HashMap<>();

    /**
     * List of UIObjects in this wizard.
     */
    private final List<IWizardElement> elements = new ArrayList<>();

    /**
     * Current UIObject.
     */
    private IWizardElement current = null;

    /**
     * Constructor setting the current UIObject.
     *
     * @param _element current UIOBject
     */
    public UIWizardObject(final IWizardElement _element)
    {
        this.elements.add(_element);
        this.current = _element;
        _element.setUIWizardObject(this);
    }

    /**
     * Add a UIOBject to the list of objects.
     *
     * @param _element Object to add
     */
    public void add(final IWizardElement _element)
    {
        this.elements.add(_element);
        _element.setUIWizardObject(this);
    }

    /**
     * Insert a UIObject before the current one.
     *
     * @param _element Object to insert
     */
    public void insertBefore(final IWizardElement _element)
    {
        int i = 0;
        for (final IWizardElement uiObject : this.elements) {
            if (uiObject == this.current) {
                this.elements.add(i, _element);
                break;
            }
            i++;
        }
    }

    /**
     * Method to get the previous object.
     *
     * @return previous object
     */
    public IWizardElement getPrevious()
    {
        IWizardElement ret = null;
        for (final IWizardElement uiObject : this.elements) {
            if (uiObject == this.current) {
                break;
            } else {
                ret = uiObject;
            }
        }
        this.current = ret;
        return ret;
    }

    /**
     * Add parameters.
     *
     * @param _element object used as key
     * @param _parameters parameters
     */
    public void addParameters(final IWizardElement _element,
                              final Map<String, String[]> _parameters)
    {
        this.parameters.put(_element, _parameters);
    }

    /**
     * Get a parameter map from the mapping.
     *
     * @param _element key fot the parameter map.
     * @return parameter map
     */
    public Map<String, String[]> getParameters(final IWizardElement _element)
    {
        return this.parameters.get(_element);
    }

    /**
     * Getter method for the instance variable {@link #elements}.
     *
     * @return value of instance variable {@link #elements}
     */
    public List<IWizardElement> getWizardElement()
    {
        return this.elements;
    }
}