/*
 * 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.menu;

import java.io.File;
import java.util.List;

import org.apache.wicket.Component;
import org.apache.wicket.RestartResponseException;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.MarkupStream;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.request.http.handler.RedirectRequestHandler;
import org.efaps.admin.event.Parameter.ParameterValues;
import org.efaps.admin.event.Return;
import org.efaps.admin.event.Return.ReturnValues;
import org.efaps.admin.ui.AbstractCommand;
import org.efaps.ui.wicket.EFapsSession;
import org.efaps.ui.wicket.components.IRecent;
import org.efaps.ui.wicket.models.objects.PagePosition;
import org.efaps.ui.wicket.models.objects.UIForm;
import org.efaps.ui.wicket.models.objects.UIMenuItem;
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.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.ui.wicket.pages.main.MainPage;
import org.efaps.ui.wicket.resources.EFapsContentReference;
import org.efaps.ui.wicket.util.Configuration;
import org.efaps.ui.wicket.util.Configuration.ConfigAttribute;
import org.efaps.ui.wicket.util.DojoClasses;
import org.efaps.ui.wicket.util.DojoWrapper;
import org.efaps.util.EFapsException;

/**
 * Class renders a standard link for the menu.
 *
 * @author The eFaps Team
 */
public class LinkItem
    extends Link<UIMenuItem>
    implements IRecent
{

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

    /**
     * Constructor.
     *
     * @param _wicketId wicket id of this component
     * @param _model model for this component
     */
    public LinkItem(final String _wicketId,
                    final IModel<UIMenuItem> _model)
    {
        super(_wicketId, _model);
    }

    /**
     * On click it is evaluated what must be responded.
     */
    @Override
    public void onClick()
    {
        ((EFapsSession) getSession()).addRecent(this);
        final UIMenuItem model = super.getModelObject();
        try {
            final AbstractCommand command = model.getCommand();
            final PagePosition pagePosition = isPopup() ? PagePosition.POPUP : PagePosition.CONTENT;

            if (command.getTargetTable() != null) {
                final WebPage page;
                if (command.getTargetStructurBrowserField() != null) {
                    if ("GridX".equals(Configuration.getAttribute(ConfigAttribute.STRUCBRWSR_DEFAULTTYPECONTENT))) {
                        page = new GridPage(Model.of(UIGrid.get(command.getUUID(), pagePosition)));
                    } else {
                        final UIStructurBrowser uiStrBrws = new UIStructurBrowser(model.getCommandUUID(),
                                    model.getInstanceKey()).setPagePosition(pagePosition);
                        page = new StructurBrowserPage(Model.of(uiStrBrws), getPage().getPageReference());
                    }
                } else {
                    if ("GridX".equals(Configuration.getAttribute(ConfigAttribute.TABLE_DEFAULTTYPECONTENT))) {
                        page = new GridPage(Model.of(UIGrid.get(command.getUUID(), pagePosition)));
                    } else {
                        final UITable uiTable = new UITable(model.getCommandUUID(), model.getInstanceKey())
                                        .setPagePosition(pagePosition);
                        page = new TablePage(Model.of(uiTable), null, getPage().getPageReference());
                    }
                }
                setResponsePage(page);
            } else if (command.getTargetForm() != null || command.getTargetSearch() != null) {
                final UIForm uiForm = new UIForm(model.getCommandUUID(), model.getInstanceKey()).setPagePosition(
                                pagePosition);
                final FormPage page = new FormPage(Model.of(uiForm), getPage().getPageReference());
                setResponsePage(page);
            } else {
                try {
                    final List<Return> rets = model.executeEvents(ParameterValues.OTHERS, this);
                    if (command.isTargetShowFile()) {
                        final Object object = rets.get(0).get(ReturnValues.VALUES);
                        if (object instanceof File) {
                            getRequestCycle().scheduleRequestHandlerAfterCurrent(new RedirectRequestHandler(
                                            "/usage.html"));
                        }
                    }
                } catch (final EFapsException e) {
                    throw new RestartResponseException(new ErrorPage(e));
                }
            }
        } catch (final EFapsException e) {
            setResponsePage(new ErrorPage(e));
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void open(final Component _openComponent)
        throws EFapsException
    {
        final UIMenuItem model = super.getModelObject();

        final AbstractCommand command = model.getCommand();
        _openComponent.getPage();
        if (command.getTargetTable() != null) {
            if (command.getTargetStructurBrowserField() != null) {
                final StructurBrowserPage page = new StructurBrowserPage(model.getCommandUUID(), model
                                .getInstanceKey());
                setResponsePage(page);
            } else {
                if ("GridX".equals(Configuration.getAttribute(ConfigAttribute.TABLE_DEFAULTTYPECONTENT))) {
                    final GridPage page = new GridPage(Model.of(UIGrid.get(command.getUUID(), PagePosition.CONTENT)));
                    setResponsePage(page);
                } else {
                    final UITable uiTable = new UITable(model.getCommandUUID(), model.getInstanceKey())
                                    .setPagePosition( PagePosition.CONTENT);
                    final TablePage page = new TablePage(Model.of(uiTable));
                    setResponsePage(page);
                }
            }
        } else if (command.getTargetForm() != null) {
            final UIForm uiForm = new UIForm(model.getCommandUUID(), model.getInstanceKey()).setPagePosition(
                            PagePosition.CONTENT);
            final FormPage page = new FormPage(Model.of(uiForm));
            setResponsePage(page);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getLabel(final int _maxLength)
        throws EFapsException
    {
        final UIMenuItem model = super.getModelObject();
        String label = model.getLabel();
        if (label.length() > _maxLength) {
            label = label.substring(0, _maxLength - 3) + "...";
        }
        return label;
    }

    @Override
    public void onComponentTagBody(final MarkupStream _markupStream,
                                   final ComponentTag _openTag)
    {
        super.onComponentTagBody(_markupStream, _openTag);
        final StringBuilder html = new StringBuilder();
        if (getModelObject().getImage() == null) {
            html.append("
").append("
");
        } else {
            html.append("");
        }
        html.append("").append(getModelObject().getLabel()).append("");
        replaceComponentTagBody(_markupStream, _openTag, html);
    }

    @Override
    protected CharSequence getOnClickScript(final CharSequence _url)
    {
        final StringBuilder js = new StringBuilder()
                        .append("registry.byId(\"").append("mainPanel").append(
                                        "\").set(\"content\", domConstruct.create(\"iframe\", {").append("\"id\": \"")
                        .append(MainPage.IFRAME_ID).append("\",\"src\": \"").append(_url).append(
                                        "\",\"style\": \"border: 0; width: 100%; height: 99%\"").append(",\"id\": \"")
                        .append(MainPage.IFRAME_ID).append("\"").append("}));");
        return DojoWrapper.require(js, DojoClasses.registry, DojoClasses.domConstruct);
    }

    /**
     * Checks if is popup.
     *
     * @return true, if is popup
     */
    protected boolean isPopup()
    {
        return false;
    }
}


/*
 * 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.button;

import org.apache.wicket.ajax.AjaxEventBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.IAjaxIndicatorAware;
import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
import org.apache.wicket.ajax.form.AjaxFormSubmitBehavior;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.panel.GenericPanel;
import org.apache.wicket.model.IModel;
import org.efaps.ui.wicket.components.efapscontent.StaticImageComponent;
import org.efaps.ui.wicket.resources.AbstractEFapsHeaderItem;
import org.efaps.ui.wicket.resources.EFapsContentReference;

/**
 * @author The eFaps Team
 * @param <T> the generic type
 */
@SuppressWarnings("checkstyle:abstractclassname")
public abstract class AjaxButton<T>
    extends GenericPanel<T>
{

    /**
     * Reference to an icon in the eFaps Database.
     */
    public enum ICON {
        /** accept.png. */
        ACCEPT("accept.png"),
        /** add.png. */
        ADD("add.png"),
        /** cancel.png. */
        CANCEL("cancel.png"),
        /** delete.png. */
        DELETE("delete.png"),
        /** next.png. */
        NEXT("next.png"),
        /** previous. */
        PREVIOUS("previous.png"),
        /** config. */
        CONFIG("config.png");

        /**
         * reference.
         */
        private final EFapsContentReference reference;

        /**
         * @param _image image
         */
        ICON(final String _image)
        {
            this.reference = new EFapsContentReference(AjaxButton.class, _image);
        }

        /**
         * Getter method for the instance variable {@link #reference}.
         *
         * @return value of instance variable {@link #reference}
         */
        public EFapsContentReference getReference()
        {
            return this.reference;
        }
    }

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

    /** The submit. */
    private boolean submit = true;

    /**
     * Instantiates a new ajax button.
     *
     * @param _wicketId wicketid for this component
     */
    public AjaxButton(final String _wicketId)
    {
        this(_wicketId, (String) null);
    }

    /**
     * Instantiates a new ajax button.
     *
     * @param _wicketId     WicketId for this component
     * @param _label        label of the button
     */
    public AjaxButton(final String _wicketId,
                      final String _label)
    {
        this(_wicketId, null, _label);
    }

    /**
     * Instantiates a new ajax button.
     *
     * @param _wicketId     WicketId for this component
     * @param _reference    reference to an icon
     */
    public AjaxButton(final String _wicketId,
                      final EFapsContentReference _reference)
    {
        this(_wicketId, _reference, null);
    }

    /**
     * Instantiates a new ajax button.
     *
     * @param _wicketId     WicketId for this component
     * @param _reference    reference to an icon
     * @param _label        label of the button
     */
    public AjaxButton(final String _wicketId,
                      final EFapsContentReference _reference,
                      final String _label)
    {
        super(_wicketId);
        initialize(null, _reference, _label);
    }

    /**
     * Instantiates a new ajax button.
     *
     * @param _wicketId     WicketId for this component
     * @param _model        Model for this component
     */
    public AjaxButton(final String _wicketId,
                      final IModel<T> _model)
    {
        this(_wicketId, _model, null);
    }

    /**
     * Instantiates a new ajax button.
     *
     * @param _wicketId     WicketId for this component
     * @param _model        Model for this component
     * @param _reference    reference to an icon
     */
    public AjaxButton(final String _wicketId,
                      final IModel<T> _model,
                      final EFapsContentReference _reference)
    {
        this(_wicketId, _model, _reference, null);
    }

    /**
     * Instantiates a new ajax button.
     *
     * @param _wicketId     WicketId for this component
     * @param _model        Model for this component
     * @param _reference    reference to an icon
     * @param _label        label of the button
     */
    public AjaxButton(final String _wicketId,
                      final IModel<T> _model,
                      final EFapsContentReference _reference,
                      final String _label)
    {
        super(_wicketId, _model);
        initialize(_model, _reference, _label);
    }

    /**
     * Init the component.
     * @param _model        Model for this component
     * @param _reference    refernce to an icon
     * @param _label        label of the button
     */
    protected void initialize(final IModel<T> _model,
                              final EFapsContentReference _reference,
                              final String _label)
    {
        final ButtonLink<T> link;
        if (_model == null) {
            link = new ButtonLink<>("button");
        } else {
            link = new ButtonLink<>("button", _model);
        }
        add(link);
        link.add(new ButtonImage("icon", _reference));
        link.add(new Label("label", _label == null ? "" : _label));
    }

    @Override
    public void renderHead(final IHeaderResponse _response)
    {
        super.renderHead(_response);
        _response.render(AbstractEFapsHeaderItem.forCss(ButtonStyleBehavior.CSS));
    }

    /**
     * Gets the default processing.
     *
     * @return {@code true} for default processing
     */
    protected boolean getDefaultProcessing()
    {
        return true;
    }

    /**
     * Listener method invoked on the ajax request generated when
     * the user clicks the link.
     *
     * @param _target AjaxRequestTarget
     */
    public abstract void onRequest(AjaxRequestTarget _target);

    /**
     * Listener method invoked on the ajax request generated when
     * the user clicks the link.
     *
     * @param _target AjaxRequestTarget
     */
    public void onError(final AjaxRequestTarget _target)
    {
        // to be used by implementations
    }

    /**
     * Update ajax attributes.
     *
     * @param _attributes the attributes
     */
    protected void updateAjaxAttributes(final AjaxRequestAttributes _attributes)
    {
        // to be able to overwrite
    }

    /**
     * Gets the form.
     *
     * @return the form
     */
    public Form<?> getForm()
    {
        return null;
    }

    /**
     * Checks if is submit.
     *
     * @return true, if is submit
     */
    protected boolean isSubmit()
    {
        return this.submit;
    }

    /**
     * Setter method for instance variable {@link #submit}.
     *
     * @param _submit value for instance variable {@link #submit}
     * @return the ajax button< t>
     */
    public AjaxButton<T> setSubmit(final boolean _submit)
    {
        this.submit = _submit;
        return this;
    }

    /**
     * Underlying link.
     *
     * @param <T> the generic type
     */
    public static class ButtonLink<T>
        extends WebMarkupContainer
        implements IAjaxIndicatorAware
    {

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

        /**
         * Instantiates a new button link.
         *
         * @param _wicketId wicketid for this component
         * @param _model   model for this component
         */
        public ButtonLink(final String _wicketId,
                          final IModel<T> _model)
        {
            super(_wicketId, _model);
        }

        /**
         * Instantiates a new button link.
         *
         * @param _wicketId wicketid for this component
         */
        public ButtonLink(final String _wicketId)
        {
            super(_wicketId);
        }

        @Override
        public String getAjaxIndicatorMarkupId()
        {
            return "eFapsVeil";
        }

        @Override
        protected void onInitialize()
        {
            super.onInitialize();
            final AjaxButton<?> pBtn = findParent(AjaxButton.class);
            if (pBtn.isSubmit()) {
                add(new AjaxFormSubmitBehavior("click")
                {
                    private static final long serialVersionUID = 1L;

                    @Override
                    protected void onSubmit(final AjaxRequestTarget _target)
                    {
                        pBtn.onRequest(_target);
                    }

                    @Override
                    protected void onError(final AjaxRequestTarget _target)
                    {
                        pBtn.onError(_target);
                    }

                    @Override
                    public boolean getDefaultProcessing()
                    {
                        return pBtn.getDefaultProcessing();
                    }

                    @Override
                    protected void updateAjaxAttributes(final AjaxRequestAttributes _attributes)
                    {
                        super.updateAjaxAttributes(_attributes);
                        pBtn.updateAjaxAttributes(_attributes);
                    }

                    @Override
                    protected Form<?> findForm()
                    {
                        final Form<?> ret;
                        if (pBtn.getForm() != null) {
                            ret = pBtn.getForm();
                        } else {
                            ret = super.findForm();
                        }
                        return ret;
                    }
                });
            } else {
                add(new AjaxEventBehavior("click") {

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

                    @Override
                    protected void onEvent(final AjaxRequestTarget _target)
                    {
                        pBtn.onRequest(_target);
                    }
                });
            }
        }
    }

    /**
     * Render the image span.
     *
     * @author The eFaps Team
     */
    public static class ButtonImage
        extends StaticImageComponent
    {
        /**
         * Needed for serialization.
         */
        private static final long serialVersionUID = 1L;

        /**
         * Has a reference or not.
         */
        private boolean hasReference = false;

        /**
         * Instantiates a new button image.
         *
         * @param _wicketId wicketid for this component
         */
        public ButtonImage(final String _wicketId)
        {
            this(_wicketId, null);
        }

        /**
         * Instantiates a new button image.
         *
         * @param _wicketId wicketid for this component
         * @param _reference reference to an icon that will be shown
         */
        public ButtonImage(final String _wicketId,
                           final EFapsContentReference _reference)
        {
            super(_wicketId);
            setReference(_reference);
        }

        /**
         * Checks for reference.
         *
         * @return true if has reference, else false
         */
        public boolean hasReference()
        {
            return this.hasReference;
        }

        @Override
        public boolean isVisible()
        {
            return hasReference();
        }

        @Override
        public void setReference(final EFapsContentReference _reference)
        {
            if (_reference != null) {
                super.setReference(_reference);
                this.hasReference = true;
            }
        }

        @Override
        protected void onComponentTag(final ComponentTag _tag)
        {
            _tag.append("style", "background-image:url(" + super.getUrl() + ")", " ");
        }
    }
}


/*
 * 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.autocomplete;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.efaps.admin.event.Return;
import org.efaps.admin.event.Return.ReturnValues;
import org.efaps.api.ui.IOption;
import org.efaps.db.Instance;
import org.efaps.ui.wicket.behaviors.AjaxFieldUpdateBehavior;
import org.efaps.ui.wicket.behaviors.SetSelectedRowBehavior;
import org.efaps.ui.wicket.behaviors.dojo.AutoCompleteBehavior;
import org.efaps.ui.wicket.behaviors.dojo.AutoCompleteBehavior.AutoCompleteField;
import org.efaps.ui.wicket.models.field.AutoCompleteSettings.EditValue;
import org.efaps.ui.wicket.models.field.IAutoComplete;
import org.efaps.ui.wicket.models.objects.AbstractUIPageObject;
import org.efaps.util.EFapsException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * TODO comment!
 *
 * @author The eFaps Team
 */
public class AutoCompleteComboBox
    extends TextField<String>
    implements AutoCompleteField
{
    /**
     * Logger.
     */
    private static final Logger LOG =  LoggerFactory.getLogger(AutoCompleteField.class);

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

    /**
     * the cell this automcoplete belongs to.
     */
    private final IAutoComplete autoComplete;

    /**
     * @param _wicketId     wicket id for this component
     * @param _model        model for this component
     * @param _selectRow    add selected row behavior
     */
    public AutoCompleteComboBox(final String _wicketId,
                                final IModel<IAutoComplete> _model,
                                final boolean _selectRow)
    {
        super(_wicketId, Model.of(""));
        this.autoComplete = _model.getObject();
        try {
            setLabel(Model.of(this.autoComplete.getLabel()));
        } catch (final EFapsException e) {
            AutoCompleteComboBox.LOG.error("Error in setting of label)", e);
        }
        final AutoCompleteBehavior acBehavior = new AutoCompleteBehavior(this.autoComplete.getAutoCompleteSetting());
        this.add(acBehavior);

        if (_selectRow) {
            this.add(new SetSelectedRowBehavior(this.autoComplete.getAutoCompleteSetting().getFieldName()));
        }
        if (this.autoComplete.isFieldUpdate()) {
            final AjaxFieldUpdateBehavior fieldUpdate = new AjaxFieldUpdateBehavior("domready",
                            Model.of(_model.getObject()), false);
            fieldUpdate.setDojoCall(true);
            this.add(fieldUpdate);
            acBehavior.addFieldUpdate(fieldUpdate);
        }
    }

    @Override
    protected void onComponentTag(final ComponentTag _tag)
    {
        _tag.setName("input");
        super.onComponentTag(_tag);
        _tag.put("value", "");
    }

    /**
     * Method to get the values from the esjp.
     *
     * @see org.apache.wicket.extensions.ajax.markup.html.autocomplete
     *      .AutoCompleteTextField#getChoices(java.lang.String)
     * @param _input input from the webform
     * @return iterator
     */
    @SuppressWarnings("unchecked")
    @Override
    public Iterator<Map<String, String>> getChoices(final String _input)
    {
        final List<Map<String, String>> retList = new ArrayList<Map<String, String>>();
        try {
            final AbstractUIPageObject pageObject = (AbstractUIPageObject) getPage().getDefaultModelObject();
            final Map<String, String> uiID2Oid = pageObject == null ? null : pageObject.getUiID2Oid();
            final List<Return> returns = this.autoComplete.getAutoCompletion(_input, uiID2Oid);
            for (final Return aReturn : returns) {
                final Object ob = aReturn.get(ReturnValues.VALUES);
                if (ob instanceof List) {
                    retList.addAll((Collection<? extends Map<String, String>>) ob);
                }
            }
        } catch (final EFapsException e) {
            AutoCompleteComboBox.LOG.error("Error in getChoice()", e);
        }
        return retList.iterator();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getItemValue()
    {
        String ret = null;
        try {
            if (this.autoComplete != null && this.autoComplete.getParent().isEditMode()
                            && !EditValue.NONE.equals(this.autoComplete.getAutoCompleteSetting().getValue4Edit())) {
                final Instance instance = this.autoComplete.getInstance();
                if (instance != null && instance.isValid()) {
                    switch (this.autoComplete.getAutoCompleteSetting().getValue4Edit()) {
                        case OID:
                            ret = instance.getOid();
                            break;
                        case ID:
                            ret = String.valueOf(instance.getId());
                            break;
                        default:
                            break;
                    }
                }
            } else if (this.autoComplete != null
                            && (this.autoComplete.getParent().isEditMode()
                                            || this.autoComplete.getParent().isCreateMode())
                            && !this.autoComplete.getAutoCompleteSetting().isRequired()) {
                ret = this.autoComplete.getAutoCompleteValue();
            }
        } catch (final EFapsException e) {
            AutoCompleteComboBox.LOG.error("Error in getItemValue()", e);
        }
        return ret;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getItemLabel()
    {
        String ret = null;
        if ((this.autoComplete.getParent().isEditMode() || this.autoComplete.getParent().isCreateMode())
                        && !EditValue.NONE.equals(this.autoComplete.getAutoCompleteSetting().getValue4Edit())) {
            try {
                ret = this.autoComplete.getAutoCompleteValue();
            } catch (final EFapsException e) {
                AutoCompleteComboBox.LOG.error("Error in getItemValue()", e);
            }
        }
        return ret;
    }

    @Override
    public String getInputName()
    {
        return this.autoComplete.getAutoCompleteSetting().getFieldName();
    }

    @Override
    public List<IOption> getTokens()
    {
        final List<IOption> ret = new ArrayList<>();
        if ((this.autoComplete.getParent().isEditMode() || this.autoComplete.getParent().isCreateMode())
                        && !EditValue.NONE.equals(this.autoComplete.getAutoCompleteSetting().getValue4Edit())) {
            try {
                ret.addAll(this.autoComplete.getTokens());
            } catch (final EFapsException e) {
                AutoCompleteComboBox.LOG.error("Error in getItemValue()", e);
            }
        }
        return ret;
    }
}


/*
 * 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.util;

import org.efaps.db.Context;
import org.efaps.util.EFapsException;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.wicketstuff.datetime.StyleDateConverter;

/**
 * Singelton class for date functions.
 *
 * @author The eFaps Team
 */
public final class DateUtil
{
    /**
     * Singelton.
     */
    private DateUtil()
    {
    }

    /**
     * Convert a date from a parameter into a DateTime.
     *
     * @param _value value to be converted
     * @return DateTime
     * @throws EFapsException on error
     */
    public static DateTime getDateFromParameter(final String _value)
        throws EFapsException
    {
        final StyleDateConverter styledate = new StyleDateConverter(false);
        final DateTimeFormatter fmt = DateTimeFormat.forPattern(styledate.getDatePattern(Context.getThreadContext()
                        .getLocale()));
        fmt.withLocale(Context.getThreadContext().getLocale());
        final DateTime dt = fmt.parseDateTime(_value);
        return dt;
    }

    /**
     * Convert a DateTime to a String for parameter.
     *
     * @param _value value to be converted
     * @return DateTime
     * @throws EFapsException on error
     */
    public static String getDate4Parameter(final DateTime _value)
        throws EFapsException
    {
        final StyleDateConverter styledate = new StyleDateConverter(false);
        final DateTimeFormatter fmt = DateTimeFormat.forPattern(styledate.getDatePattern(Context.getThreadContext()
                        .getLocale()));
        fmt.withLocale(Context.getThreadContext().getLocale());
        return _value.toString(fmt);
    }

    /**
     * Gets the date time formatter.
     *
     * @return the date time formatter
     * @throws EFapsException the e faps exception
     */
    public static DateTimeFormatter getDateFormatter()
        throws EFapsException
    {
        final String formatStr = Configuration.getAttribute(Configuration.ConfigAttribute.FORMAT_DATE);
        final DateTimeFormatter ret;
        if (formatStr.matches("^[S,M,L,F,-]{2}$")) {
            ret = DateTimeFormat.forStyle(formatStr);
        } else {
            ret = DateTimeFormat.forPattern(formatStr);
        }
        return ret.withLocale(Context.getThreadContext().getLocale());
    }

    /**
     * Gets the date pattern.
     *
     * @return the date pattern
     * @throws EFapsException the e faps exception
     */
    public static String getDatePattern()
        throws EFapsException
    {
        final String formatStr = Configuration.getAttribute(Configuration.ConfigAttribute.FORMAT_DATE);
        return formatStr.matches("^[S,M,L,F,-]{2}$")
                        ? DateTimeFormat.patternForStyle(formatStr, Context.getThreadContext().getLocale())
                        : formatStr;
    }

    /**
     * Gets the date time formatter.
     *
     * @return the date time formatter
     * @throws EFapsException the e faps exception
     */
    public static DateTimeFormatter getDateTimeFormatter()
        throws EFapsException
    {
        final String formatStr = Configuration.getAttribute(Configuration.ConfigAttribute.FORMAT_DATETIME);
        final DateTimeFormatter ret;
        if (formatStr.matches("^[S,M,L,F,-]{2}$")) {
            ret = DateTimeFormat.forStyle(formatStr);
        } else {
            ret = DateTimeFormat.forPattern(formatStr);
        }
        return ret.withLocale(Context.getThreadContext().getLocale());
    }

    /**
     * Gets the date pattern.
     *
     * @return the date pattern
     * @throws EFapsException the e faps exception
     */
    public static String getDateTimePattern()
        throws EFapsException
    {
        final String formatStr = Configuration.getAttribute(Configuration.ConfigAttribute.FORMAT_DATETIME);
        return formatStr.matches("^[S,M,L,F,-]{2}$")
                        ? DateTimeFormat.patternForStyle(formatStr, Context.getThreadContext().getLocale())
                        : formatStr;
    }
}


/*
 * 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.UUID;

import org.efaps.admin.AbstractAdminObject;
import org.efaps.admin.ui.AbstractCommand.SortDirection;
import org.efaps.admin.ui.AbstractUserInterfaceObject.TargetMode;
import org.efaps.admin.ui.field.Field.Display;
import org.efaps.admin.ui.field.FieldTable;
import org.efaps.db.Context;
import org.efaps.db.Instance;
import org.efaps.util.EFapsException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Object used for a StructurBrowser nested in a Form.
 *
 * @author The eFaps Team
 * @version $Id$
 */
public class UIFieldStructurBrowser
    extends UIStructurBrowser
    implements IFormElement
{

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

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

    /**
     * Id of the Field this Field Structur Browser belongs to.
     */
    private final Long fieldTabelId;

    /**
     * @param _commandUUID  uuid of the calling command
     * @param _instanceKey  key to the instance
     * @param _field        Field
     * @throws EFapsException on error
     */
    public UIFieldStructurBrowser(final UUID _commandUUID,
                                  final String _instanceKey,
                                  final FieldTable _field)
        throws EFapsException
    {
        super(_commandUUID, _instanceKey);
        setTableUUID(_field.getTargetTable().getUUID());
        setBrowserFieldName(_field.getTargetStructurBrowserField());
        this.fieldTabelId = _field.getId();
        setShowCheckBoxes(_field.isTargetShowCheckBoxes());
        setForceExpanded(_field.isTargetStructurBrowserForceExpand());
    }

    /**
     * @param _commandUUID  uuid of the calling command
     * @param _instanceKey  key to the instance
     * @param _sortdirection sort direction
     * @param _field        Field
     * @throws EFapsException on error
     */
    private UIFieldStructurBrowser(final UUID _commandUUID,
                                   final String _instanceKey,
                                   final SortDirection _sortdirection,
                                   final FieldTable _field)
        throws EFapsException
    {
        super(_commandUUID, _instanceKey, false, _sortdirection);
        setTableUUID(_field.getTargetTable().getUUID());
        setBrowserFieldName(_field.getTargetStructurBrowserField());
        this.fieldTabelId = _field.getId();
        setShowCheckBoxes(_field.isTargetShowCheckBoxes());
        setForceExpanded(_field.isTargetStructurBrowserForceExpand());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected UIStructurBrowser getNewStructurBrowser(final Instance _instance,
                                                      final UIStructurBrowser _parent)
        throws EFapsException
    {
        final FieldTable field = FieldTable.get(((UIFieldStructurBrowser) _parent).getFieldTabelId());
        final UIFieldStructurBrowser ret = new UIFieldStructurBrowser(_parent.getCommandUUID(), _instance == null
                        ? null : _instance.getKey(), _parent.getSortDirection(), field);
        ret.setParentBrws(this);
        ret.setLevel(getLevel() + 1);
        return ret;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void initialise()
        throws EFapsException
    {
        if (getCommand() == null) {
            super.initialise();
        } else {
            try {
                if (Context.getThreadContext().containsUserAttribute(
                                getCacheKey(UITable.UserCacheKey.SORTKEY))) {
                    setSortKeyInternal(Context.getThreadContext().getUserAttribute(
                                    getCacheKey(UITable.UserCacheKey.SORTKEY)));
                }
                if (Context.getThreadContext().containsUserAttribute(
                                getCacheKey(UITable.UserCacheKey.SORTDIRECTION))) {
                    setSortDirection(SortDirection.getEnum(Context.getThreadContext()
                                    .getUserAttribute(getCacheKey(UITable.UserCacheKey.SORTDIRECTION))));
                }
            } catch (final EFapsException e) {
                // we don't throw an error because this are only Usersettings
                UIFieldStructurBrowser.LOG.error("error during the retrieve of UserAttributes", e);
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected AbstractAdminObject getObject4Event()
    {
        return FieldTable.get(this.getFieldTabelId());
    }

    /**
     * Get the Display of the Field this StructurBrowser is bedded in.
     * @param _mode target mode the display will be evaluate for
     * @return Display
     */
    public Display getFieldDisplay(final TargetMode _mode)
    {
        return FieldTable.get(this.getFieldTabelId()).getDisplay(_mode);
    }

    /**
     * In create or edit mode this StructurBrowser is editable,
     * if the Field this StructurBroeser is bedded in is editable also.
     *
     * @return is this StructurBrowser editable.
     */
    @Override
    public boolean isEditable()
    {
        return getFieldDisplay(getMode()).equals(Display.EDITABLE) && (isCreateMode() || isEditMode());
    }

    @Override
    public String getCacheKey()
    {
        return super.getCommandUUID() + "-" + this.getFieldTabelId() + "-" + UIStructurBrowser.USERSESSIONKEY;
    }

    /**
     * Gets the id of the Field this Field Structur Browser belongs to.
     *
     * @return the id of the Field this Field Structur Browser belongs to
     */
    public Long getFieldTabelId()
    {
        return this.fieldTabelId;
    }
}


/*
 * 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.servlet;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.NumberFormat;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.efaps.admin.AppConfigHandler;
import org.efaps.admin.user.Person;
import org.efaps.db.Context;
import org.efaps.util.EFapsException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Servlet used to give access to files for a user.
 *
 * @author The eFaps Team
 * @version $Id$
 */
public class FileServlet
    extends HttpServlet
{
    /**
     * Name of the folder inside the "official" temporary folder.
     */
    public static final String TMPFOLDERNAME = "eFapsUserDepTemp";

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

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

    /**
     * Search for the requested file in the folder corresponding to the user of the context.
     *
     * @param _req request variable
     * @param _resp response variable
     * @throws ServletException on error
     */
    @Override
    protected void doGet(final HttpServletRequest _req,
                         final HttpServletResponse _resp)
        throws ServletException
    {
        String fileName = _req.getRequestURI();
        fileName = fileName.substring(fileName.lastIndexOf('/') + 1);
        try {
            final Person pers = Context.getThreadContext().getPerson();
            if (pers != null) {
                final File file = getFile(pers.getId(), fileName);
                if (file != null && file.exists()) {
                    _resp.setContentType(getServletContext().getMimeType(file.getName()));
                    _resp.setContentLength((int) file.length());
                    _resp.setDateHeader("Last-Modified", System.currentTimeMillis());
                    _resp.setDateHeader("Expires", System.currentTimeMillis());
                    _resp.addHeader("Content-Disposition", "inline; filename=\"" + file.getName() + "\"");
                    _resp.setHeader("Cache-Control", "max-age=10");
                    final FileInputStream input = new FileInputStream(file);
                    IOUtils.copy(input, _resp.getOutputStream());
                }
            }
        } catch (final EFapsException e) {
            FileServlet.LOG.error("EFapsException", e);
            throw new ServletException(e);
        } catch (final IOException e) {
            FileServlet.LOG.error("IOException", e);
            throw new ServletException(e);
        }
    }

    /**
     * @param _personId personid
     * @param _fileName name of the file
     * @return the file if found
     * @throws IOException on error
     */
    private File getFile(final Long _personId,
                         final String _fileName)
        throws IOException
    {
        File tmpfld = AppConfigHandler.get().getTempFolder();
        if (tmpfld == null) {
            final File temp = File.createTempFile("eFaps", ".tmp");
            tmpfld = temp.getParentFile();
            temp.delete();
        }
        final File storeFolder = new File(tmpfld, FileServlet.TMPFOLDERNAME);
        final NumberFormat formater = NumberFormat.getInstance();
        formater.setMinimumIntegerDigits(8);
        formater.setGroupingUsed(false);
        final File userFolder = new File(storeFolder, formater.format(_personId));
        if (!userFolder.exists()) {
            userFolder.mkdirs();
        }
        return new File(userFolder, _fileName);
    }
}


/*
 * 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:1510 $
 * Last Changed:    $Date:2007-10-18 09:35:40 -0500 (Thu, 18 Oct 2007) $
 * Last Changed By: $Author:jmox $
 */

package org.efaps.ui.servlet;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.efaps.admin.datamodel.Type;
import org.efaps.admin.dbproperty.DBProperties;
import org.efaps.ci.CIAdminProgram;
import org.efaps.db.Checkout;
import org.efaps.db.Context;
import org.efaps.db.Instance;
import org.efaps.db.InstanceQuery;
import org.efaps.db.MultiPrintQuery;
import org.efaps.db.PrintQuery;
import org.efaps.db.QueryBuilder;
import org.efaps.ui.wicket.behaviors.dojo.AbstractDojoBehavior;
import org.efaps.util.EFapsException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The servlet shows the help.
 *
 * @author The eFaps Team
 * @version $Id$
 */
public class HelpServlet
    extends HttpServlet
{
    /**
     * Key to store the menu in the session context of the user.
     */
    public static final String MENU_SESSION_KEY = "eFapsHelpServletMenu";

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

    /**
     * Defaut serial Number.
     */
    private static final long serialVersionUID = 1L;

    /**
     * The method checks the file from the object out and returns them in a
     * output stream to the web client. The object id must be given with
     * paramter {@link #PARAM_OID}.

     *
     * @param _req request variable
     * @param _res response variable
     * @throws ServletException on error
     */
    @Override
    protected void doGet(final HttpServletRequest _req,
                         final HttpServletResponse _res)
        throws ServletException
    {
        HelpServlet.LOG.debug("Recieved Request for Help Servlet: {}", _req);
        try {
            final List<String> wikis = new ArrayList<String>();
            String path = _req.getPathInfo().substring(1);
            final String end = path.substring(path.lastIndexOf("."), path.length());
            if (end.equalsIgnoreCase(".png") || end.equalsIgnoreCase(".jpg") || end.equalsIgnoreCase(".jpeg")
                            || end.equalsIgnoreCase(".gif")) {
                final QueryBuilder queryBldr = new QueryBuilder(CIAdminProgram.WikiImage);
                queryBldr.addWhereAttrEqValue("Name", path);
                final MultiPrintQuery multi = queryBldr.getPrint();
                multi.addAttribute("FileLength");
                multi.execute();
                if (multi.next()) {
                    final Long length = multi.<Long>getAttribute("FileLength");
                    final Checkout checkout = new Checkout(multi.getCurrentInstance());
                    _res.setContentType(getServletContext().getMimeType(end));
                    _res.setContentLength(length.intValue());
                    _res.setDateHeader("Expires", System.currentTimeMillis() + (3600 * 1000));
                    _res.setHeader("Cache-Control", "max-age=3600");
                    checkout.execute(_res.getOutputStream());
                    checkout.close();
                }
            } else {
                if (!path.contains(".")) {
                    String referer = _req.getHeader("Referer");
                    if (referer.contains(":")) {
                        final String[] paths = referer.split(":");
                        referer = paths[0];
                    }
                    final String[] pack = referer.substring(referer.lastIndexOf("/") + 1).split("\\.");
                    final StringBuilder newPath = new StringBuilder();
                    for (int i = 0; i < pack.length - 2; i++) {
                        newPath.append(pack[i]).append(".");
                    }
                    newPath.append(path).append(".wiki");
                    path = newPath.toString();
                    wikis.add(path);
                } else if (path.contains(":")) {
                    final String[] paths = path.split(":");
                    for (final String apath : paths) {
                        wikis.add(apath);
                    }
                } else {
                    wikis.add(path);
                }

                final String menuStr;
                if (Context.getThreadContext().containsSessionAttribute(HelpServlet.MENU_SESSION_KEY)) {
                    menuStr = (String) Context.getThreadContext().getSessionAttribute(HelpServlet.MENU_SESSION_KEY);
                } else {
                    menuStr = getMenu();
                    Context.getThreadContext().setSessionAttribute(HelpServlet.MENU_SESSION_KEY, menuStr);
                }

                final StringBuilder html = new StringBuilder();
                html.append("")
                    .append("\n")
                    .append("\n")
                    .append("<link rel=\"stylesheet\" type=\"text/css\" href=\"../../wicket/resource/")
                    .append(AbstractDojoBehavior.CSS_TUNDRA.getScope().getName()).append("/")
                    .append(AbstractDojoBehavior.CSS_TUNDRA.getName())
                    .append("\" />")
                    .append("<link rel=\"stylesheet\" type=\"text/css\" ")
                    .append(" href=\"../../servlet/static/org.efaps.help.Help.css?")
                    .append("\" />")
                    .append("")
                    .append("
")
                    .append("
")
                    .append("
")
                    .append(menuStr)
                    .append("

")
                    .append("

");

                for (final String wiki : wikis) {
                    final QueryBuilder queryBldr = new QueryBuilder(CIAdminProgram.WikiCompiled);
                    queryBldr.addWhereAttrEqValue("Name", wiki);
                    final InstanceQuery query = queryBldr.getQuery();
                    query.execute();
                    if (query.next()) {
                        final Checkout checkout = new Checkout(query.getCurrentValue());
                        final InputStreamReader in = new InputStreamReader(checkout.execute(), "UTF8");
                        if (in != null) {
                            final BufferedReader reader = new BufferedReader(in);
                            String line = null;
                            while ((line = reader.readLine()) != null) {
                                html.append(line);
                            }
                        }
                    }
                }
                html.append("

");
                _res.setContentType("text/html;charset=UTF-8");
                _res.setContentLength(html.length());
                _res.getOutputStream().write(html.toString().getBytes("UTF8"));
            }
        } catch (final EFapsException e) {
            throw new ServletException(e);
        } catch (final IOException e) {
            throw new ServletException(e);
        }
    }

    /**
     * get the CharSequence for the menu.
     *
     * @return the menu
     * @throws EFapsException on error
     */
    private String getMenu()
        throws EFapsException
    {
        HelpServlet.LOG.debug("Reading Main Help Menu");
        final StringBuilder ret = new StringBuilder();
        ret.append("
");
        final QueryBuilder queryBldr = new QueryBuilder(Type.get("Admin_Help_Menu"));
        // Admin_Help_MainMenu
        queryBldr.addWhereAttrEqValue("UUID", "dead549e-5cc6-49f9-9a79-8e33aa139f6d");
        final MultiPrintQuery multi = queryBldr.getPrint();
        multi.addAttribute("Name");
        multi.addSelect("linkfrom[Admin_Help_Menu2Wiki#FromLink].linkto[ToLink].attribute[Name]");
        multi.execute();
        if (multi.next()) {
            final String name = multi.<String>getAttribute("Name");
            String link = "";
            final Object links = multi
                            .getSelect("linkfrom[Admin_Help_Menu2Wiki#FromLink].linkto[ToLink].attribute[Name]");
            if (links instanceof List<?>) {
                for (final Object alink : (List<?>) links) {
                    link = link + ":" + alink;
                }
            } else {
                link = (String) links;
            }
            ret.append("
").append(DBProperties.getProperty(name + ".Label"))
                            .append("
");
            ret.append(getSubMenues(multi.getCurrentInstance()));
        }
        ret.append("
");
        return ret.toString();
    }

    /**
     * Recursive method to get the CharSequence for the sub menu.
     *
     * @param _instance Instance of the parent menu
     * @return the menu
     * @throws EFapsException on error
     */
    private CharSequence getSubMenues(final Instance _instance)
        throws EFapsException
    {
        HelpServlet.LOG.debug("Reading Submenues for OID: {}", _instance.getOid());
        final StringBuilder ret = new StringBuilder();

        final QueryBuilder queryBldr = new QueryBuilder(Type.get("Admin_Help_Menu2Menu"));
        queryBldr.addWhereAttrEqValue("FromLink", _instance.getId());
        final MultiPrintQuery multi = queryBldr.getPrint();
        multi.addSelect("linkto[ToLink].attribute[Name]", "linkto[ToLink].oid");
        multi.execute();
        final Map<Long, String> subs = new TreeMap<Long, String>();

        while (multi.next()) {
            final String name = multi.<String>getSelect("linkto[ToLink].attribute[Name]");
            final String oid = multi.<String>getSelect("linkto[ToLink].oid");
            final PrintQuery print = new PrintQuery(oid);
            print.addSelect("linkfrom[Admin_Help_Menu2Wiki#FromLink].linkto[ToLink].attribute[Name]");
            print.execute();
            String link = "";
            final Object links = print
                            .getSelect("linkfrom[Admin_Help_Menu2Wiki#FromLink].linkto[ToLink].attribute[Name]");
            if (links instanceof List<?>) {
                for (final Object alink : (List<?>) links) {
                    link = link + ":" + alink;
                }
            } else {
                link = (String) links;
            }
            HelpServlet.LOG.debug("  Submenue '{}' with OID: {}", name, print.getCurrentInstance().getOid());
            final StringBuilder menu = new StringBuilder()
                .append("
")
                .append(DBProperties.getProperty(name + ".Label")).append("
")
                .append(getSubMenues(print.getCurrentInstance()));
            subs.put(multi.getCurrentInstance().getId(), menu.toString());
        }
        if (!subs.isEmpty()) {
            ret.append("
");
            for (final String sub : subs.values()) {
                ret.append(sub).append("\n");
            }
            ret.append("
");
        }
        return ret;
    }
}