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

import org.apache.wicket.Page;
import org.apache.wicket.RestartResponseException;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.MarkupStream;
import org.apache.wicket.markup.html.form.ILabelProvider;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.link.PopupSettings;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.efaps.admin.ui.AbstractCommand.Target;
import org.efaps.admin.ui.Menu;
import org.efaps.db.Instance;
import org.efaps.ui.wicket.models.field.AbstractUIField;
import org.efaps.ui.wicket.models.field.FieldConfiguration;
import org.efaps.ui.wicket.pages.content.structurbrowser.StructurBrowserPage;
import org.efaps.ui.wicket.pages.contentcontainer.ContentContainerPage;
import org.efaps.ui.wicket.pages.error.ErrorPage;
import org.efaps.util.EFapsException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Class extends a Link open a new content container. Used also by the
 * StructurBrowserTable.
 *
 * @author The eFaps Team
 */
public class ContentContainerLink
    extends Link<AbstractUIField>
    implements ILabelProvider<String>
{

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

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

    /**
     * Content for this link.
     */
    private final String content;

    /**
     * Constructor.
     *
     * @param _wicketId wicket id of this component
     * @param _model model fore this component
     * @param _content the content
     */
    public ContentContainerLink(final String _wicketId,
                                final IModel<AbstractUIField> _model,
                                final String _content)
    {
        super(_wicketId, _model);
        this.content = _content;
        if (Target.POPUP.equals(_model.getObject().getFieldConfiguration().getField().getTarget())) {
            final PopupSettings popup = new PopupSettings("popup");
            setPopupSettings(popup);
        }
    }

    /**
     * Getter method for the instance variable {@link #config}.
     *
     * @return value of instance variable {@link #config}
     */
    protected FieldConfiguration getConfig()
    {
        return ((AbstractUIField) getDefaultModelObject()).getFieldConfiguration();
    }

    /**
     * The tag must be overwritten.
     *
     * @param _tag tag to write.
     */
    @Override
    protected void onComponentTag(final ComponentTag _tag)
    {
        _tag.setName("a");
        super.onComponentTag(_tag);
        onComponentTagInternal(_tag);
    }

    /**
     * Add to the tag.
     *
     * @param _tag tag to write
     */
    protected void onComponentTagInternal(final ComponentTag _tag)
    {
        _tag.put("name", getConfig().getName());
        _tag.append("style", "text-align:" + getConfig().getAlign(), ";");
    }

    /**
     * Getter method for the instance variable {@link #content}.
     *
     * @return value of instance variable {@link #content}
     */
    protected String getContent()
    {
        return this.content;
    }

    @Override
    public void onComponentTagBody(final MarkupStream _markupStream,
                                   final ComponentTag _openTag)
    {
        Object ret = null;
        try {
            if (this.content == null) {
                final AbstractUIField uiField = (AbstractUIField) getDefaultModelObject();
                ret = uiField.getValue().getReadOnlyValue(uiField.getParent().getMode());
            } else {
                ret = this.content;
            }
        } catch (final EFapsException e) {
            LOG.error("Catched error on setting tag body for: {}", this);
        }
        replaceComponentTagBody(_markupStream, _openTag, ret == null ? "" : String.valueOf(ret));
    }

    @Override
    public IModel<?> getBody()
    {
        String body = "";
        try {
            if (this.content == null) {
                final AbstractUIField uiField = (AbstractUIField) getDefaultModelObject();
                body = String.valueOf(uiField.getValue().getReadOnlyValue(uiField.getParent().getMode()));
            } else {
                body = this.content;
            }
        } catch (final EFapsException e) {
            LOG.error("Catched error on setting tag body for: {}", this);
        }
        return Model.of(body);
    }

    /**
     * Method is executed on click.
     */
    @Override
    public void onClick()
    {
        Instance instance = null;
        final AbstractUIField uiField = super.getModelObject();
        if (uiField.getInstanceKey() != null) {
            Menu menu = null;
            try {
                instance = uiField.getInstance();
                menu = Menu.getTypeTreeMenu(instance.getType());
            } catch (final EFapsException e) {
                throw new RestartResponseException(new ErrorPage(e));
            }
            if (menu == null) {
                final Exception ex = new Exception("no tree menu defined for type " + instance.getType().getName());
                throw new RestartResponseException(new ErrorPage(ex));
            }

            Page page;
            try {
                page = new ContentContainerPage(menu.getUUID(), uiField.getInstanceKey(),
                                getPage() instanceof StructurBrowserPage);
            } catch (final EFapsException e) {
                page = new ErrorPage(e);
            }
            this.setResponsePage(page);
        }
    }

    @Override
    public IModel<String> getLabel()
    {
        String ret = "NONE";
        try {
            ret = ((AbstractUIField) getDefaultModelObject()).getLabel();
        } catch (final EFapsException e) {
            LOG.error("Catched error on evaluating label: {}", this);
        }
        return Model.of(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.request;

import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.request.Request;
import org.apache.wicket.request.cycle.IRequestCycleListener;
import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.session.ISessionStore;
import org.efaps.ui.wicket.EFapsSession;
import org.efaps.ui.wicket.connectionregistry.RegistryManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This class extends the
 * {@link org.apache.wicket.protocol.http.WebRequestCycle} to throw a own
 * ErrorPage and to open/close the Context on begin/end of a Request.
 *
 * @author The eFaps Team
 */
public class EFapsRequestCycleListener
    implements IRequestCycleListener
{

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

    /**
     * Method to get the EFapsSession.
     *
     * @param _request Request the Session is wanted for
     * @return EFapsSession
     */
    private EFapsSession getEFapsSession(final Request _request)
    {
        final ISessionStore sessionStore = WebApplication.get().getSessionStore();
        final EFapsSession session = (EFapsSession) sessionStore.lookup(_request);
        return session;
    }

    /**
     * Called when the request cycle object is beginning its response.
     *
     * @param _cycle    RequestCycle this Listener belongs to
     */
    @Override
    public void onBeginRequest(final RequestCycle _cycle)
    {
        final EFapsSession session = getEFapsSession(_cycle.getRequest());
        if (session != null) {
            session.openContext();
            RegistryManager.registerActivity(session);
        }
        EFapsRequestCycleListener.LOG.debug("Begin of Request.");
    }

    /**
     * Called when the request cycle object has finished its response.
     *
     * @param _cycle    RequestCycle this Listener belongs to
     */
    @Override
    public void onEndRequest(final RequestCycle _cycle)
    {
        final EFapsSession session = getEFapsSession(_cycle.getRequest());
        if (session != null) {
            session.closeContext();
        }
        EFapsRequestCycleListener.LOG.debug("End of Request.");
    }
}


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

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import javax.servlet.http.HttpServletRequest;

import org.apache.wicket.Session;
import org.apache.wicket.protocol.ws.WebSocketSettings;
import org.apache.wicket.protocol.ws.api.IWebSocketConnection;
import org.apache.wicket.protocol.ws.api.registry.IKey;
import org.apache.wicket.protocol.ws.api.registry.IWebSocketConnectionRegistry;
import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.request.http.WebRequest;
import org.efaps.admin.program.esjp.EFapsClassLoader;
import org.efaps.db.Context;
import org.efaps.ui.wicket.EFapsApplication;
import org.efaps.ui.wicket.EFapsSession;
import org.efaps.util.EFapsException;
import org.efaps.util.cache.InfinispanCache;
import org.hibernate.search.query.dsl.QueryBuilder;
import org.infinispan.Cache;
import org.infinispan.configuration.cache.Configuration;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.manager.EmbeddedCacheManager;
import org.infinispan.query.CacheQuery;
import org.infinispan.query.ResultIterator;
import org.infinispan.query.Search;
import org.infinispan.query.SearchManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The Class RegistryManager.
 *
 * @author The eFaps Team
 */
public final class RegistryManager
{
    /**
     * Name of the Cache for Instances.
     */
    public static final String SESSIONCACHE = RegistryManager.class.getName() + ".Session";

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

    /**
     * Instantiates a new registry manager.
     */
    private RegistryManager()
    {
    }

    /**
     * Register user session.
     *
     * @param _userName the user name
     * @param _sessionId the session ID
     */
    public static void registerUserSession(final String _userName,
                                           final String _sessionId)
    {
        if (EFapsApplication.getMaxInactiveInterval() > 0) {
            RegistryManager.getCache().put(_sessionId,
                            new UserSession().setUserName(_userName).setSessionId(_sessionId), -1,
                            TimeUnit.MINUTES, EFapsApplication.getMaxInactiveInterval() + 600, TimeUnit.SECONDS);
        } else {
            RegistryManager.getCache().put(_sessionId,
                            new UserSession().setUserName(_userName).setSessionId(_sessionId));
        }
        RegistryManager.registerLogin4History(_userName, _sessionId);
    }

    /**
     * @param _userName userName
     * @param _sessionId sessionid
     */
    private static void registerLogin4History(final String _userName,
                                              final String _sessionId)
    {
        try {
            final WebRequest req = (WebRequest) RequestCycle.get().getRequest();
            final HttpServletRequest httpReq = (HttpServletRequest) req.getContainerRequest();
            String ipAddress = httpReq.getHeader("X-FORWARDED-FOR");
            if (ipAddress == null) {
                ipAddress = httpReq.getRemoteAddr();
            }
            final Class<?> clazz = Class.forName("org.efaps.esjp.common.history.LoginHistory", true,
                            EFapsClassLoader.getInstance());
            final Object obj = clazz.newInstance();
            final Method method = clazz.getMethod("register", String.class, String.class, String.class);
            method.invoke(obj, _userName, _sessionId, ipAddress);
        } catch (final ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException
                        | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            RegistryManager.LOG.error("Error on registering Login", e);
        }
    }

    /**
     * Register activity.
     *
     * @param _session the session
     */
    public static void registerActivity(final EFapsSession _session)
    {
        if (_session.isLogedIn() && RegistryManager.getCache().containsKey(_session.getId())) {
            final UserSession userSession = RegistryManager.getCache().get(_session.getId());
            if (userSession.isInvalidated()) {
                _session.invalidate();
            } else {
                userSession.registerActivity();
            }
        }
    }

    /**
     * Register keep alive.
     *
     * @param _session the session
     */
    public static void registerKeepAlive(final Session _session)
    {
        // TODO Auto-generated method stub
    }

    /**
     * Adds the msg connection.
     *
     * @param _sessionId the session ID
     * @param _key the key
     */
    public static void addMsgConnection(final String _sessionId,
                                        final IKey _key)
    {
        if (RegistryManager.getCache().containsKey(_sessionId)) {
            RegistryManager.getCache().get(_sessionId).setConnectionKey(_key);
        }
        RegistryManager.LOG.debug("Added Message Connection for Session: {}", _sessionId);
    }

    /**
     * Invalidate session.
     *
     * @param _sessionId the session id
     */
    public static void invalidateSession(final String _sessionId)
    {
        if (RegistryManager.getCache().containsKey(_sessionId)) {
            RegistryManager.getCache().get(_sessionId).markInvalid();
        }
    }

    /**
     * Removes the user session.
     *
     * @param _sessionId the session id
     */
    public static void removeUserSession(final String _sessionId)
    {
        if (RegistryManager.getCache().containsKey(_sessionId)) {
            RegistryManager.registerLogout4History(
                            RegistryManager.getCache().get(_sessionId).getUserName(), _sessionId);
            RegistryManager.getCache().remove(_sessionId);
        }

    }

    /**
     * @param _userName userName
     * @param _sessionId sessionid
     */
    private static void registerLogout4History(final String _userName,
                                               final String _sessionId)
    {
        boolean contextOpened = false;
        try {
            if (!Context.isThreadActive()) {
                Context.begin(_userName);
                contextOpened = true;
            }
            final Class<?> clazz = Class.forName("org.efaps.esjp.common.history.LogoutHistory", true, EFapsClassLoader
                            .getInstance());
            final Object obj = clazz.newInstance();
            final Method method = clazz.getMethod("register", String.class, String.class, String.class);
            method.invoke(obj, _userName, _sessionId, "N.A.");
        } catch (final ClassNotFoundException | EFapsException | InstantiationException | IllegalAccessException
                        | NoSuchMethodException | SecurityException | IllegalArgumentException
                        | InvocationTargetException e) {
            RegistryManager.LOG.error("Error on registering Logout", e);
        } finally {
            if (contextOpened && Context.isThreadActive()) {
                try {
                    Context.commit();
                } catch (final EFapsException e) {
                    RegistryManager.LOG.error("Error on registering Logout", e);
                }
            }
        }
    }

    /**
     * Gets the users.
     *
     * @return the users
     */
    public static Set<String> getUsers()
    {
        final Set<String> ret = new HashSet<>();
        for (final UserSession userSession : RegistryManager.getCache().values()) {
            ret.add(userSession.getUserName());
        }
        return ret;
    }

    /**
     * Gets the user sessions.
     *
     * @return the user sessions
     */
    public static Collection<UserSession> getUserSessions()
    {
        return Collections.unmodifiableCollection(RegistryManager.getCache().values());
    }

    /**
     * Gets the connections 4 user.
     *
     * @param _login the login
     * @return the connections 4 user
     */
    public static List<IWebSocketConnection> getConnections4User(final String _login)
    {
        final List<IWebSocketConnection> ret = new ArrayList<>();
        final SearchManager searchManager = Search.getSearchManager(RegistryManager.getCache());
        final QueryBuilder qbldr = searchManager.buildQueryBuilderForClass(UserSession.class).get();
        final CacheQuery<?> query = searchManager.getQuery(qbldr.keyword().onField("userName").matching(_login)
                        .createQuery());
        try (ResultIterator<?> iter = query.iterator()) {
            while (iter.hasNext()) {
                final UserSession userSession = (UserSession) iter.next();
                if (userSession.getConnectionKey() != null) {
                    final IWebSocketConnectionRegistry registry = WebSocketSettings.Holder.get(EFapsApplication.get())
                                    .getConnectionRegistry();
                    final IWebSocketConnection conn = registry.getConnection(EFapsApplication.get(), userSession
                                    .getSessionId(), userSession.getConnectionKey());
                    if (conn != null) {
                        ret.add(conn);
                    }
                }
            }
        }
        return ret;
    }

    /**
     * Gets the connection 4 session.
     *
     * @param _sessionId the session id
     * @return the connection 4 session
     */
    public static IWebSocketConnection getConnection4Session(final String _sessionId)
    {
        IWebSocketConnection ret = null;
        if (RegistryManager.getCache().containsKey(_sessionId)) {
            final UserSession userSession = RegistryManager.getCache().get(_sessionId);
            if (userSession.getConnectionKey() != null) {
                final IWebSocketConnectionRegistry registry = WebSocketSettings.Holder.get(EFapsApplication.get())
                                .getConnectionRegistry();
                ret = registry.getConnection(EFapsApplication.get(),
                                userSession.getSessionId(), userSession.getConnectionKey());
            }
        }
        return ret;
    }

    /**
     * Gets the cache.
     *
     * @return the cache
     */
    private static Cache<String, UserSession> getCache()
    {
        // before the first use the Entity used for indexing must be added
        if (!((EmbeddedCacheManager) InfinispanCache.get().getContainer()).cacheExists(RegistryManager.SESSIONCACHE)) {
            final Configuration config = ((EmbeddedCacheManager) InfinispanCache.get().getContainer())
                            .getCacheConfiguration(RegistryManager.SESSIONCACHE);
            final ConfigurationBuilder bldr = new ConfigurationBuilder().read(config);
            bldr.indexing().addIndexedEntity(UserSession.class);
            ((EmbeddedCacheManager) InfinispanCache.get().getContainer()).undefineConfiguration(
                            RegistryManager.SESSIONCACHE);

            ((EmbeddedCacheManager) InfinispanCache.get().getContainer()).defineConfiguration(
                            RegistryManager.SESSIONCACHE, bldr.build());
        }
        return InfinispanCache.get().getIgnReCache(RegistryManager.SESSIONCACHE);
    }
}


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

import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import org.apache.wicket.RestartResponseException;
import org.efaps.admin.dbproperty.DBProperties;
import org.efaps.admin.event.EventType;
import org.efaps.admin.event.Parameter;
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.admin.ui.AbstractCommand.Target;
import org.efaps.admin.ui.AbstractUserInterfaceObject.TargetMode;
import org.efaps.admin.ui.Command;
import org.efaps.admin.ui.Menu;
import org.efaps.admin.ui.Search;
import org.efaps.admin.user.Role;
import org.efaps.beans.ValueList;
import org.efaps.beans.valueparser.ParseException;
import org.efaps.beans.valueparser.ValueParser;
import org.efaps.db.Context;
import org.efaps.db.Instance;
import org.efaps.db.PrintQuery;
import org.efaps.ui.wicket.models.field.UIPicker;
import org.efaps.ui.wicket.pages.error.ErrorPage;
import org.efaps.ui.wicket.util.Configuration;
import org.efaps.util.EFapsException;
import org.efaps.util.cache.CacheReloadException;

/**
 * @author The eFaps Team
 */
public abstract class AbstractUIObject
    extends AbstractUIModeObject
{

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

    /**
     * This instance variable stores the UUID of the CommandAbstract which was
     * originally called from the Frontend and let to the construction of this
     * model.
     *
     * @see #getCallingCommandUUID()
     * @see #getCallingCommand()
     * @see #setCallingCommandUUID(UUID)
     */
    private UUID callingCmdUUID;

    /**
     * The instance variable stores the UUID of the Command for this Model.
     *
     * @see #getCommandUUID()
     * @see #getCommand
     */
    private UUID cmdUUID;

    /**
     * The instance variable is the flag if this class instance is already
     * Initialized.
     *
     * @see #isInitialised
     * @see #setInitialised
     */
    private boolean initialized = false;

    /**
     * This instance variable stores, if the Model is supposed to be submitted.
     *
     * @see #isSubmit()
     * @see #setSubmit(boolean)
     */
    private boolean submit = false;

    /**
     * This instance variable stores the Target of this Model.
     *
     * @see #getTarget()
     */
    private Target target = Target.UNKNOWN;

    /**
     * In case that the model was opened as a popup this variable stores the id
     * of the opener, so that it can be accessed in the EFapsSession.
     */
    private String openerId;

    /**
     * Picker that opened this object.
     */
    private UIPicker picker;

    /**
     * Constructor.
     *
     * @param _commandUUID UUID for this Model
     * @param _instanceKey instance id for this Model
     * @throws CacheReloadException on error
     */
    public AbstractUIObject(final UUID _commandUUID,
                            final String _instanceKey)
        throws CacheReloadException
    {
        this(_commandUUID, _instanceKey, null);
    }

    /**
     * Constructor.
     *
     * @param _commandUUID UUID for this Model
     * @param _instanceKey instance id for this Model
     * @param _openerId id of the opener UIClassification
     * @throws CacheReloadException on error
     */
    public AbstractUIObject(final UUID _commandUUID,
                            final String _instanceKey,
                            final String _openerId)
        throws CacheReloadException
    {
        super(_instanceKey);
        initialize(_commandUUID, _openerId);
    }

    /**
     * Method initializes the model.
     *
     * @param _commandUUID UUID for this Model
     * @param _openerId id of the opener
     * @throws CacheReloadException on error
     */
    protected void initialize(final UUID _commandUUID,
                              final String _openerId)
        throws CacheReloadException
    {
        this.openerId = _openerId;
        if (_commandUUID != null) {
            final AbstractCommand command = getCommand(_commandUUID);
            this.cmdUUID = command.getUUID();
            setMode(command.getTargetMode());
            this.target = command.getTarget();
            this.submit = command.isSubmit();
            if (command.getTargetSearch() != null && !(this instanceof UIMenuItem)) {
                this.callingCmdUUID = this.cmdUUID;
                this.cmdUUID = command.getTargetSearch().getDefaultCommand().getUUID();
                setMode(TargetMode.SEARCH);
                if (command.hasEvents(EventType.UI_COMMAND_EXECUTE)) {
                    this.submit = true;
                }
            }
        }
    }

    /**
     * @see org.efaps.ui.wicket.models.
     *      AbstractInstanceObject#getInstanceFromManager()
     * @return instance from a esjp
     * @throws EFapsException on error
     */
    @Override
    public Instance getInstanceFromManager()
        throws EFapsException
    {
        final AbstractCommand cmd = getCommand();
        final List<Return> rets = cmd.executeEvents(EventType.UI_INSTANCEMANAGER,
                        ParameterValues.OTHERS, getInstanceKey(),
                        ParameterValues.PARAMETERS, Context.getThreadContext().getParameters());

        return (Instance) rets.get(0).get(ReturnValues.VALUES);
    }

    /**
     * @see org.efaps.ui.wicket.models.AbstractInstanceObject#hasInstanceManager()
     * @return true if related command has got a event of type
     *         UI_INSTANCEMANAGER else false
     * @throws CacheReloadException on eror
     */
    @Override
    public boolean hasInstanceManager()
        throws CacheReloadException
    {
        return getCommand().hasEvents(EventType.UI_INSTANCEMANAGER);
    }

    /**
     * Method is used to execute the UIObject (Fill it with data).
     */
    public abstract void execute();

    /**
     * This Method resets the Model, so that the next time the Model is going to
     * be connected, the underlying Data will be received newly from the
     * eFapsDataBase.
     */
    public abstract void resetModel();

    /**
     * Get the CommandAbstract which was originally called from the Frontend and
     * let to the construction of this model.
     *
     * @see #callingCmdUUID
     * @return the calling CommandAbstract UIClassification
     * @throws CacheReloadException on error
     */
    public AbstractCommand getCallingCommand()
        throws CacheReloadException
    {
        AbstractCommand cmd = null;
        if (getCallingCommandUUID() != null) {
            cmd = Command.get(getCallingCommandUUID());
            if (cmd == null) {
                cmd = Menu.get(getCallingCommandUUID());
            }
        }
        return cmd;
    }

    /**
     * This is the getter method for the instance variable
     * {@link #callingCmdUUID}.
     *
     * @return value of instance variable {@link #cmdUUID}
     */
    public UUID getCallingCommandUUID()
    {
        return this.callingCmdUUID;
    }

    /**
     * This is the setter method for the instance variable
     * {@link #callingCmdUUID}.
     *
     * @param _uuid UUID of the CommandAbstract
     */
    public void setCallingCommandUUID(final UUID _uuid)
    {
        this.callingCmdUUID = _uuid;
    }

    /**
     * get the CommandAbstract for the instance variable {@link #cmdUUID}.
     *
     * @return CommandAbstract for the instance variable {@link #cmdUUID}
     * @throws CacheReloadException on error
     */
    public AbstractCommand getCommand()
        throws CacheReloadException
    {
        AbstractCommand cmd = Command.get(this.cmdUUID);
        if (cmd == null) {
            cmd = Menu.get(this.cmdUUID);
        }
        if (cmd == null) {
            cmd = Search.get(this.cmdUUID);
        }
        return cmd;
    }

    /**
     * For given UUID of command / menu / Search, the related command / menu
     * /search Java instance is searched and, if found, returned.
     *
     * @param _uuid UUID of searched command object
     * @return found command / menu instance, or null if not found
     * @throws CacheReloadException on error
     */
    protected AbstractCommand getCommand(final UUID _uuid)
        throws CacheReloadException
    {
        AbstractCommand cmd = Command.get(_uuid);
        if (cmd == null) {
            cmd = Menu.get(_uuid);
            if (cmd == null) {
                cmd = Search.get(_uuid);
            }
        }
        return cmd;
    }

    /**
     * This is the getter method for the instance variable {@link #cmdUUID}.
     *
     * @return value of instance variable {@link #cmdUUID}
     */
    public UUID getCommandUUID()
    {
        return this.cmdUUID;
    }

    /**
     * This is the setter method for the instance variable {@link #cmdUUID}.
     *
     * @param _uuid UUID to set for teh instance varaiable {@link #cmdUUID}.
     */
    public void setCommandUUID(final UUID _uuid)
    {
        this.cmdUUID = _uuid;
    }

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

    /**
     * Setter method for instance variable {@link #openerId}.
     *
     * @param _openerId value for instance variable {@link #openerId}
     */
    public void setOpenerId(final String _openerId)
    {
        this.openerId = _openerId;
    }

    /**
     * This is the getter method for the instance variable {@link #target}.
     *
     * @return value of instance variable {@link #target}
     */
    public Target getTarget()
    {
        return this.target;
    }

    /**
     * This method retrieves the Value for the Title from the eFaps Database.
     *
     * @return Value of the Title
     * @throws Exception
     */
    public String getTitle()
    {
        String title = "";
        try {
            final String key = this.getCommand().getTargetTitle() == null
                            ? this.getCommand().getName() + ".Title"
                            : this.getCommand().getTargetTitle();
            title = DBProperties.getProperty(key);
            if (title != null && getInstance() != null) {
                final PrintQuery print = new PrintQuery(getInstance());
                final ValueParser parser = new ValueParser(new StringReader(title));
                final ValueList list = parser.ExpressionString();
                list.makeSelect(print);
                if (print.execute()) {
                    title = list.makeString(getInstance(), print, getMode());
                }
                // Administration
                if (Configuration.getAttributeAsBoolean(Configuration.ConfigAttribute.SHOW_OID)
                                && Context.getThreadContext()
                                                .getPerson()
                                                .isAssigned(Role.get(UUID
                                                                .fromString("1d89358d-165a-4689-8c78-fc625d37aacd")))) {
                    title = title + " " + getInstance().getOid();
                }
            }
        } catch (final ParseException e) {
            throw new RestartResponseException(new ErrorPage(new EFapsException(this.getClass(), "",
                            "Error reading the Title")));
            // CHECKSTYLE:OFF
        } catch (final Exception e) {
            throw new RestartResponseException(new ErrorPage(new EFapsException(this.getClass(), "",
                            "Error reading the Title")));
        } // CHECKSTYLE:ON
        return title;
    }

    /**
     * This is the getter method for the instance variable {@link #initialized}.
     *
     * @return value of instance variable {@link #initialized}
     * @see #initialized
     * @see #setInitialised
     */
    public boolean isInitialized()
    {
        return this.initialized;
    }

    /**
     * This is the setter method for the instance variable {@link #initialized}.
     *
     * @param _initialized new value for instance variable {@link #initialized}
     * @see #initialized
     * @see #isInitialised
     */
    public void setInitialized(final boolean _initialized)
    {
        this.initialized = _initialized;
    }

    /**
     * This is the getter method for the instance variable {@link #submit}.
     *
     * @return value of instance variable {@link #submit}
     * @see #setSubmit(boolean)
     */
    public boolean isSubmit()
    {
        return this.submit;
    }

    /**
     * This is the setter method for the instance variable {@link #submit}.
     *
     * @param _submit submit
     * @see #isSubmit()
     */
    public void setSubmit(final boolean _submit)
    {
        this.submit = _submit;
    }

    /**
     * This method executes the Events which are related to this Model. It will
     * take the Events of the CallingCommand {@link #callingCmdUUID}, if it is
     * declared, otherwise it will take the Events of the Command
     * {@link #cmdUUID}. The Method also adds the oid {@link #instanceKey} to
     * the Context, so that it is accessible for the esjp.

     * This method throws an eFpasError to provide the possibility for different
     * responses in the components.
     *
     * @param _objectTuples n tuples of ParamterValue and Object
     * @throws EFapsException on error
     * @return List of Returns
     */
    public List<Return> executeEvents(final Object... _objectTuples)
        throws EFapsException
    {
        return executeEvents(EventType.UI_COMMAND_EXECUTE, _objectTuples);
    }

    /**
     * Execute the events.
     *
     * @param _eventType type of events to be executed
     * @param _objectTuples tuples of objects passed to the event
     * @return Lsit of returns from the events
     * @throws EFapsException on error
     */
    public List<Return> executeEvents(final EventType _eventType,
                                      final Object... _objectTuples)
        throws EFapsException
    {
        List<Return> ret = new ArrayList<>();
        final AbstractCommand command;
        if (this.callingCmdUUID == null) {
            command = this.getCommand();
        } else {
            command = getCallingCommand();
        }

        if (command.hasEvents(_eventType)) {
            final Parameter param = new Parameter();
            if (_objectTuples != null) {
                // add all parameters
                for (int i = 0; i < _objectTuples.length; i += 2) {
                    if (i + 1 < _objectTuples.length && _objectTuples[i] instanceof ParameterValues) {
                        param.put((ParameterValues) _objectTuples[i], _objectTuples[i + 1]);
                    }
                }
            }
            param.put(ParameterValues.PARAMETERS, Context.getThreadContext().getParameters());
            if (getInstance() != null) {
                final String[] contextoid = { getInstanceKey() };
                Context.getThreadContext().getParameters().put("oid", contextoid);
                param.put(ParameterValues.CALL_INSTANCE, getInstance());
                param.put(ParameterValues.INSTANCE, getInstance());
            }
            ret = command.executeEvents(_eventType, param);
        }
        return ret;
    }

    /**
     * This method executes the Validate-Events which are related to this Model.
     * It will take the Events of the Command {@link #cmdUUID}.
     *
     * @param _objectTuples tuples of Objects to be added to the event
     * @return List with Return from the esjp
     * @throws EFapsException on error
     */
    public List<Return> validate(final Object... _objectTuples)
        throws EFapsException
    {
        return executeEvents(EventType.UI_VALIDATE, _objectTuples);
    }

    /**
     * Getter method for the instance variable {@link #picker}.
     *
     * @return value of instance variable {@link #picker}
     */
    public boolean isOpenedByPicker()
    {
        return this.picker != null;
    }

    /**
     * Setter method for instance variable {@link #picker}.
     *
     * @param _uiObject value for instance variable {@link #picker}
     */
    public void setPicker(final ICmdUIObject _uiObject)
    {
        if (_uiObject instanceof UIPicker) {
            this.picker = (UIPicker) _uiObject;
        } else if (_uiObject == null) {
            this.picker = null;
        }
    }

    /**
     * Getter method for the instance variable {@link #picker}.
     *
     * @return value of instance variable {@link #picker}
     */
    public UIPicker getPicker()
    {
        return this.picker;
    }
}


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

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.behavior.AttributeAppender;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.IChoiceRenderer;
import org.apache.wicket.markup.html.form.IFormSubmittingComponent;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.efaps.admin.event.EventDefinition;
import org.efaps.admin.event.EventType;
import org.efaps.api.ci.UIFormFieldProperty;
import org.efaps.db.Context;
import org.efaps.ui.wicket.behaviors.AjaxFieldUpdateBehavior;
import org.efaps.ui.wicket.models.field.AbstractUIField;
import org.efaps.ui.wicket.models.field.FieldConfiguration;
import org.efaps.ui.wicket.models.field.set.UIFieldSet;
import org.efaps.ui.wicket.models.field.set.UIFieldSetValue;
import org.efaps.ui.wicket.models.objects.DropDownOption;
import org.efaps.util.EFapsException;
import org.efaps.util.cache.CacheReloadException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Render a DropDown Field.
 *
 * @author The eFaps Team
 */
public class DropDownField
    extends DropDownChoice<DropDownOption>
    implements IFieldConfig, IFormSubmittingComponent
{

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

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

    /**
     * value of this field.
     */
    private final AbstractUIField uiField;

    /**
     * Was the value already converted.
     */
    private boolean converted = false;

    /**
     * Instantiates a new drop down field.
     *
     * @param _wicketId     wicket id for this component
     * @param _model        Model for this component
     * @param _choices    Choices for the dropdowns
     */
    public DropDownField(final String _wicketId,
                         final Model<AbstractUIField> _model,
                         final IModel<Map<Object, Object>> _choices)
    {
        super(_wicketId);
        setOutputMarkupId(true);
        this.uiField = _model.getObject();
        final Serializable value = this.uiField.getValue().getDbValue();
        if (value != null) {
            setDefaultModel(Model.of(new DropDownOption(String.valueOf(value), null)));
        } else {
            setDefaultModel(new Model<String>());
        }
        setChoices(DropDownField.getSelectChoices(_choices.getObject()));
        setChoiceRenderer(new ChoiceRenderer());
        addBehaviors();
    }

    /**
     * @param _wicketId     wicket id for this component
     * @param _model        Model for this component
     * @param _choices    Choices for the dropdowns
     */
    public DropDownField(final String _wicketId,
                         final Model<AbstractUIField> _model,
                         final List<DropDownOption> _choices)
    {
        super(_wicketId);
        this.uiField = _model.getObject();
        for (final DropDownOption choice : _choices) {
            if (choice.isSelected()) {
                setDefaultModel(Model.of(choice));
                break;
            }
        }
        if (getDefaultModel() == null) {
            if (_choices.isEmpty()) {
                setDefaultModel(new Model<String>());
            } else {
                // check if value is set before
                for (final DropDownOption choice : _choices) {
                    if (choice.getValue().equals(String.valueOf(_model.getObject().getValue().getDbValue()))) {
                        setDefaultModel(Model.of(choice));
                        break;
                    }
                }
                if (getDefaultModel() == null) {
                    setDefaultModel(Model.of(_choices.get(0)));
                }
            }
        }
        setChoices(_choices);
        setChoiceRenderer(new ChoiceRenderer());
        addBehaviors();
    }

    /**
     * Adds the behaviors.
     */
    private void addBehaviors()
    {
        if (this.uiField.getFieldConfiguration().getField().hasEvents(EventType.UI_FIELD_UPDATE)) {
            final List<EventDefinition> events =
                            this.uiField.getFieldConfiguration().getField().getEvents(EventType.UI_FIELD_UPDATE);
            String eventName = "change";
            for (final EventDefinition event : events) {
                eventName = event.getProperty("Event") == null ? "change" : event.getProperty("Event");
            }
            add(new AjaxFieldUpdateBehavior(eventName, Model.of(this.uiField), false) {

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

                @Override
                protected void onSubmit(final AjaxRequestTarget _target)
                {
                    // add the previous value as a parameter
                    final DropDownOption option = (DropDownOption) getDefaultModelObject();
                    try {
                        if (option != null) {
                            Context.getThreadContext().getParameters().put(
                                            getFieldConfig().getName() + "_eFapsPrevious",
                                            new String[] { option.getValue() });
                        }
                    } catch (final EFapsException e) {
                        DropDownField.LOG.error("EFapsException", e);
                    }
                    super.onSubmit(_target);
                    DropDownField.this.converted = false;
                    updateModel();
                    DropDownField.this.converted = false;
                }
            });
        }
        add(new AttributeAppender("style", "text-align:" + getFieldConfig().getAlign(), ";"));
        // add the width only if not in a table
        if (getFieldConfig().hasProperty(UIFormFieldProperty.WIDTH) && !getFieldConfig().isTableField()) {
            add(new AttributeAppender("style", "width:" + getFieldConfig().getWidth(), ";"));
        }
    }

    @Override
    protected CharSequence getDefaultChoice(final String _selectedValue)
    {
        // do not set a default choice, because the esjp must do that
        return "";
    }

    @Override
    protected void onComponentTag(final ComponentTag _tag)
    {
        _tag.setName("select");
        super.onComponentTag(_tag);
    }

    @Override
    public String getInputName()
    {
        return getFieldConfig().getName();
    }

    @Override
    public void convertInput()
    {
        this.converted = true;
        int i = 0;
        if (this.uiField instanceof UIFieldSetValue) {
            final UIFieldSet cellset = ((UIFieldSetValue) this.uiField).getCellSet();
            i = cellset.getIndex(getInputName());
        }
        final String[] value = getInputAsArray();
        setConvertedInput(new DropDownOption(
                        String.valueOf(value != null && value.length > 0 && value[i] != null ? trim(value[i]) : null),
                        null));
    }

    @Override
    public void updateModel()
    {
        if (!this.converted) {
            convertInput();
        }
        setModelObject(getConvertedInput());
        try {
            this.uiField.setValue(this.uiField.getValue().clone(((DropDownOption) getDefaultModelObject()).getValue()));
        } catch (final CacheReloadException e) {
            DropDownField.LOG.error("EFapsException", e);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public FieldConfiguration getFieldConfig()
    {
        return this.uiField.getFieldConfiguration();
    }

    /**
     * @param _values value to convert to dropdown otions
     * @return list of options
     */
    private static List<DropDownOption> getSelectChoices(final Map<Object, Object> _values)
    {
        final List<DropDownOption> list = new ArrayList<>();
        for (final Entry<Object, Object> entry : _values.entrySet()) {
            list.add(new DropDownOption(String.valueOf(entry.getKey()),
                            String.valueOf(entry.getValue())));
        }
        return list;
    }

    @Override
    public IModel<String> getLabel()
    {
        String ret = null;
        try {
            ret = this.uiField.getLabel();
        } catch (final EFapsException e) {
            DropDownField.LOG.error("EFapsException", e);
        }
        return  Model.of(ret);
    }

    @Override
    public boolean getDefaultFormProcessing()
    {
        return true;
    }

    @Override
    public void onSubmit()
    {
    }

    @Override
    public void onAfterSubmit()
    {
    }

    @Override
    public void onError()
    {
    }

    @Override
    public Component setDefaultFormProcessing(final boolean _defaultFormProcessing)
    {
        return this;
    }

    /**
     * Sets the was the value already converted.
     *
     * @param _converted the new was the value already converted
     */
    public void setConverted(final boolean _converted)
    {
        this.converted = _converted;
    }

    /**
     * The renderer for this dropdown.
     */
    public final static class ChoiceRenderer
        implements IChoiceRenderer<DropDownOption>
    {
        /**
         * Needed fro serialization.
         */
        private static final long serialVersionUID = 1L;

        @Override
        public Object getDisplayValue(final DropDownOption _option)
        {
            return _option.getLabel();
        }

        @Override
        public String getIdValue(final DropDownOption _object,
                                 final int _index)
        {
            return _object.getValue();
        }

        @Override
        public DropDownOption getObject(final String _id,
                                        final IModel<? extends List<? extends DropDownOption>> _choices)
        {
            DropDownOption ret = null;
            final List<?> choices = _choices.getObject();
            for (int index = 0; index < choices.size(); index++) {
                final DropDownOption choice = (DropDownOption) choices.get(index);
                if (getIdValue(choice, index).equals(_id)) {
                    ret = choice;
                    break;
                }
            }
            return ret;
        }
    }
}


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

import java.io.Serializable;

import org.apache.commons.lang3.EnumUtils;
import org.apache.commons.lang3.StringUtils;
import org.efaps.admin.datamodel.ui.UIValue;
import org.efaps.admin.dbproperty.DBProperties;
import org.efaps.admin.ui.Table;
import org.efaps.admin.ui.field.Field;
import org.efaps.api.IEnumValue;
import org.efaps.api.ci.UIFormFieldProperty;
import org.efaps.api.ui.UIType;
import org.efaps.db.Instance;
import org.efaps.util.cache.CacheReloadException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * TODO comment!
 *
 * @author The eFaps Team
 */
public class FieldConfiguration
    implements Serializable
{

    /**
     * Logger.
     */
    private static final Logger LOG =  LoggerFactory.getLogger(FieldConfiguration.class);

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

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

    /**
     * Label for the related field.
     */
    private String label;

    /**
     * @param _fieldId id of the field
     */
    public FieldConfiguration(final long _fieldId)
    {
        this.fieldId = _fieldId;
    }

    /**
     * @return the name of this configuration
     * @throws EFapsException on error
     */
    public String getName()
    {
        return getField().getName();
    }

    /**
     * @return the field this configuration belongs to
     */
    public Field getField()
    {
        return Field.get(this.fieldId);
    }

    /**
     * @return the alignment of the field
     */
    public String getAlign()
    {
        return getField().getAlign();
    }

    /**
     * @return the alignment of the field
     */
    public int getRowSpan()
    {
        return getField().getRowSpan();
    }

    /**
     * @return the alignment of the field
     */
    public int getColSpan()
    {
        return getField().containsProperty(UIFormFieldProperty.COL_SPAN)
                        ? Integer.valueOf(getField().getProperty(UIFormFieldProperty.COL_SPAN)) : 1;
    }

    /**
     * @return the size of the field
     */
    public String getWidth()
    {
        String ret = "";
        if (hasProperty(UIFormFieldProperty.WIDTH)) {
            final String widthTmp = getProperty(UIFormFieldProperty.WIDTH);
            if (StringUtils.isNumeric(widthTmp)) {
                ret = widthTmp + "ch";
            } else {
                ret = widthTmp;
            }
        }
        return ret;
    }

    /**
     * Gets the width weight.
     *
     * @return the width weight
     */
    public int getWidthWeight()
    {
        int ret = 1;
        if (!isFixedWidth() && hasProperty(UIFormFieldProperty.WIDTH)) {
            ret = Integer.valueOf(getProperty(UIFormFieldProperty.WIDTH));
        }
        return ret;
    }

    /**
     * Checks for property.
     *
     * @param _enum the _enum
     * @return true, if successful
     */
    public boolean hasProperty(final IEnumValue _enum)
    {
        return getField().containsProperty(_enum);
    }

    /**
     * Gets the property.
     *
     * @param _enum the _enum
     * @return the property
     */
    public String getProperty(final IEnumValue _enum)
    {
        return getField().getProperty(_enum);
    }

    /**
     * @return the size of the field
     */
    public boolean isFixedWidth()
    {
        return hasProperty(UIFormFieldProperty.WIDTH)
                        && !StringUtils.isNumeric(getField().getProperty(UIFormFieldProperty.WIDTH));
    }

    /**
     * @return the rows of the field
     */
    public int getRows()
    {
        return getField().getRows();
    }

    /**
     * @return the label of this field
     */
    public String getLabel()
    {
        final String ret;
        if (this.label == null) {
            if (getField().getLabel() == null) {
                ret = "";
            } else {
                ret =  DBProperties.getProperty(getField().getLabel());
            }
        } else {
            ret = this.label;
        }
        return ret;
    }

    /**
     * Evaluate the label.
     *
     * @param _uiValue the _ui value
     * @param _fieldInst the _field inst
     * @return the label
     * @throws CacheReloadException the cache reload exception
     */
    public String evalLabel(final UIValue _uiValue,
                            final Instance _fieldInst)
        throws CacheReloadException
    {
        final String key;
        if (getField().getLabel() == null) {
            if (_uiValue != null && _uiValue.getAttribute() != null) {
                if (_fieldInst != null && _fieldInst.isValid()
                                && _fieldInst.getType()
                                                .getAttribute(_uiValue.getAttribute().getName()) != null) {
                    key = _fieldInst.getType().getAttribute(_uiValue.getAttribute().getName()).getLabelKey();
                } else if (_uiValue.getInstance() != null
                                && _uiValue.getInstance().getType()
                                                .getAttribute(_uiValue.getAttribute().getName()) != null) {
                    key = _uiValue.getInstance().getType().getAttribute(_uiValue.getAttribute().getName())
                                    .getLabelKey();
                } else {
                    key = _uiValue.getAttribute().getLabelKey();
                }
            } else {
                key = FieldConfiguration.class.getName() + ".NoLabel";
            }
        } else {
            key = getField().getLabel();
        }
        this.label = DBProperties.getProperty(key);
        return this.label;
    }

    /**
     * @return must the label been hidden
     */
    public boolean isHideLabel()
    {
        return getField().isHideLabel();
    }

    /**
     * @return the UIType
     */
    public UIType getUIType()
    {
        final UIType ret;
        final String uiTypeStr = getProperty(UIFormFieldProperty.UI_TYPE);
        if (EnumUtils.isValidEnum(UIType.class, uiTypeStr)) {
            ret = UIType.valueOf(uiTypeStr);
        } else {
            ret = UIType.DEFAULT;
        }
        return ret;
    }

    /**
     * Sets the label for the related field.
     *
     * @param _label the new label for the related field
     */
    public void setLabel(final String _label)
    {
        this.label = _label;
    }

    /**
     * Checks if is table.
     *
     * @return true, if is table
     */
    public boolean isTableField()
    {
        boolean ret = false;
        try {
            ret = getField().getCollection() instanceof Table;
        } catch (final CacheReloadException e) {
            LOG.error("CacheReloadException", e);
        }
        return ret;
    }

    /**
     * Gets the field config.
     *
     * @return the field config
     */
    public static FieldConfiguration getSimFieldConfig(final String _fieldName)
    {
        final Field field = new Field(0, "", _fieldName);
        final FieldConfiguration ret = new FieldConfiguration(0)
        {
            /** The Constant serialVersionUID. */
            private static final long serialVersionUID = 1L;

            @Override
            public Field getField()
            {
                return field;
            }
        };
        return ret;
    }
}


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

import java.io.Serializable;

import org.efaps.admin.program.esjp.EFapsClassLoader;
import org.efaps.api.ui.IEsjpSnipplet;
import org.efaps.api.ui.IEsjpSnippletProvider;
import org.efaps.util.EFapsBaseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * TODO comment!
 *
 * @author The eFaps Team
 */
public class EsjpInvoker
    implements Serializable
{

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

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

    /**
     * ClassName of the esjp that will be invoked.
     */
    private String esjp;

    /** The init. */
    private boolean init = false;

    /** The snipplet. */
    private IEsjpSnipplet snipplet;

    /** The provider. */
    private IEsjpSnippletProvider provider;

    /** The key. */
    private String key;

    /**
     * Instantiates a new esjp invoker.
     *
     * @param _esjp the _esjp
     */
    public EsjpInvoker(final String _esjp)
    {
        this.esjp = _esjp;
    }

    /**
     * Instantiates a new esjp invoker.
     *
     * @param _provider the _provider
     * @param _key the _key
     */
    public EsjpInvoker(final IEsjpSnippletProvider _provider,
                       final String _key)
    {
        this.provider = _provider;
        this.key = _key;
    }

    /**
     * Gets the html snipplet.
     *
     * @return the html snipplet
     * @throws EFapsBaseException the e faps base exception
     */
    public CharSequence getHtmlSnipplet()
        throws EFapsBaseException
    {
        initialize();
        return this.snipplet.getHtmlSnipplet();
    }

    /**
     * @return
     */
    private void initialize()
    {
        try {
            if (!this.init) {
                if (this.esjp != null) {
                    final Class<?> clazz = Class.forName(this.esjp, false, EFapsClassLoader.getInstance());
                    this.snipplet = (IEsjpSnipplet) clazz.newInstance();
                    this.init = true;
                } else if (this.provider != null) {
                    this.snipplet = this.provider.getEsjpSnipplet(this.key);
                    this.init = true;
                }
            }
        } catch (final ClassNotFoundException e) {
            EsjpInvoker.LOG.error("ClassNotFoundException", e);
        } catch (final SecurityException e) {
            EsjpInvoker.LOG.error("SecurityException", e);
        } catch (final IllegalAccessException e) {
            EsjpInvoker.LOG.error("IllegalAccessException", e);
        } catch (final IllegalArgumentException e) {
            EsjpInvoker.LOG.error("IllegalArgumentException", e);
        } catch (final InstantiationException e) {
            EsjpInvoker.LOG.error("InstantiationException", e);
        }
    }

    /**
     * Checks if is visible.
     *
     * @return true, if is visible
     */
    public boolean isVisible()
    {
        initialize();
        boolean ret = false;
        try {
            ret = this.snipplet.isVisible();
        } catch (final EFapsBaseException e) {
            EsjpInvoker.LOG.error("EFapsException", e);
        }
        return ret;
    }

    /**
     * Getter method for the instance variable {@link #snipplet}.
     *
     * @return value of instance variable {@link #snipplet}
     */
    public IEsjpSnipplet getSnipplet()
    {
        return this.snipplet;
    }

    /**
     * Getter method for the instance variable {@link #provider}.
     *
     * @return value of instance variable {@link #provider}
     */
    public IEsjpSnippletProvider getProvider()
    {
        return this.provider;
    }
}


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

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.efaps.jaas.AppAccessHandler;

/**
 * @author The eFaps Team
 */
public abstract class AbstractFilter
    implements Filter
{
    /**
     * Name of the InitParameter variable for the login roles.
     */
    public static final String INITPARAM_LOGIN_ROLES = "org.efaps.login.roles";

    /**
     * Name of the InitParameter variable for the application key.
     */
    public static final String INITPARAM_APP_KEY = "org.efaps.application.key";

    /**
     * Name of the InitParameter variable for the login name.
     */
    private static final String SESSIONPARAM_LOGIN_NAME = "login.name";

    /**
     * Name of the session variable for the login name.
     */
    private String sessionParameterLoginName = "org.efaps.login.name";

    /**
     * Called by the web container to indicate to a filter that it is being
     * placed into service. The servlet container calls the init method exactly
     * once after instantiating the filter. The init method must complete
     * successfully before the filter is asked to do any filtering work. The web
     * container cannot place the filter into service if the init method either
     * 1.Throws a ServletException 2.Does not return within a time period
     * defined by the web container // sets the login handler
     *
     * @param _filterConfig filter configuration instance
     * @see #INIT_PARAM_TITLE
     * @see #title
     * @see #INIT_PARAM_APPLICATION
     * @see #loginhandler
     * @throws ServletException on error
     */
    @Override
    public void init(final FilterConfig _filterConfig)
        throws ServletException
    {
        final String appkey = _filterConfig.getInitParameter(AbstractFilter.INITPARAM_APP_KEY);
        final String loginName = _filterConfig.getInitParameter(AbstractFilter.SESSIONPARAM_LOGIN_NAME);
        final String loginRolesTmp = _filterConfig.getInitParameter(AbstractFilter.INITPARAM_LOGIN_ROLES);
        if (loginName != null) {
            this.sessionParameterLoginName = loginName;
        }
        final Set<UUID> temp = new HashSet<>();
        if (loginRolesTmp != null) {
            final String[] loginRolesAr = loginRolesTmp.split(",");
            for (final String loginRole : loginRolesAr) {
                temp.add(UUID.fromString(loginRole));
            }
        }
        AppAccessHandler.init(appkey, temp);
    }

    /**
     * Destroys the filter. Is an empty method in this implementation which
     * could be overwritten by derived classes.

     * The method is called by the web container to indicate to a filter that it
     * is being taken out of service. This method is only called once all
     * threads within the filter's doFilter method have exited or after a
     * timeout period has passed. After the web container calls this method, it
     * will not call the doFilter method again on this instance of the filter.

     * This method gives the filter an opportunity to clean up any resources
     * that are being held (for example, memory, file handles, threads) and make
     * sure that any persistent state is synchronized with the filter's current
     * state in memory.
     */
    @Override
    public void destroy()
    {
    }

    /**
     * First the filtes tests, if the http(s) protokoll is used. If the request
     * is not implementing the {@link HttpServletRequest} and the response is
     * not implementing the {@link HttpServletResponse} interface, a
     * {@link ServletException} is thrown.

     *
     * @param _request  ServletRequest
     * @param _response ServletResponse
     * @param _chain    FilterChain
     * @throws ServletException if the request and response does not use the
     *             http(s) protokoll
     * @see HttpServletRequest
     * @see HttpServletResponse
     * @see #checkLogin
     * @throws IOException on error
     */
    @Override
    public void doFilter(final ServletRequest _request,
                         final ServletResponse _response,
                         final FilterChain _chain)
        throws IOException, ServletException
    {

        if (_request instanceof HttpServletRequest
                        && _response instanceof HttpServletResponse) {

            doFilter((HttpServletRequest) _request, (HttpServletResponse) _response, _chain);
        } else {
            throw new ServletException("request not allowed");
        }
    }

    /**
     * @param _request  ServletRequest
     * @param _response ServletResponse
     * @param _chain    FilterChain
     * @throws IOException  on error
     * @throws ServletException on error
     */
    protected abstract void doFilter(final HttpServletRequest _request,
                                     final HttpServletResponse _response,
                                     final FilterChain _chain)
        throws IOException, ServletException;

    /**
     * Check, if the session variable {@link #sessionParameterLoginName} is set.
     * If not, user is not logged in. Normally then a redirect to login page is
     * made with method {@link #doRedirect2Login}.
     *
     * @param _request http servlet request variable
     * @return true if user logged in, otherwise false
     */
    protected boolean isLoggedIn(final HttpServletRequest _request)
    {
        return getLoggedInUser(_request) != null ? true : false;
    }

    /**
     * Stores the logged in user name in a session attribute of the http servlet
     * request. If the new user name is null, the session attribute
     * is removed.
     *
     * @param _request http servlet request
     * @param _userName name of logged in user to set (or null if not defined)
     */
    protected void setLoggedInUser(final HttpServletRequest _request,
                                   final String _userName)
    {
        if (_userName == null) {
            _request.getSession(true).removeAttribute(this.sessionParameterLoginName);
        } else {
            _request.getSession(true).setAttribute(this.sessionParameterLoginName,
                            _userName);
        }
    }

    /**
     * @param _request HttpServletRequest
     * @return nmae of the logged in user
     */
    protected String getLoggedInUser(final HttpServletRequest _request)
    {
        return (String) _request.getSession(true).getAttribute(this.sessionParameterLoginName);
    }
}


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

import org.apache.wicket.Component;
import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
import org.apache.wicket.ajax.attributes.AjaxRequestAttributes.Method;
import org.apache.wicket.ajax.attributes.CallbackParameter;
import org.apache.wicket.ajax.attributes.ThrottlingSettings;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.JavaScriptHeaderItem;
import org.apache.wicket.util.string.StringValue;
import org.apache.wicket.util.time.Duration;
import org.efaps.ui.wicket.pages.contentcontainer.ContentContainerPage;
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;

/**
 * Class renders an ajax post link which is used to store the position of the
 * horizontal splitter.
 *
 * @author The eFaps Team
 */
public class AjaxStorePositionBehavior
    extends AbstractDefaultAjaxBehavior
{

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

    /**
     * String used as the parameter name.
     */
    private static final String PARAMETER_VERTICALPOSITION = "eFapsPosV";

    /**
     * String used as the parameter name.
     */
    private static final String PARAMETER_HORIZONTALPOSITION = "eFapsPosH";

    /**
     * Store the vertical.
     */
    private final boolean vertical;

    /**
     * @param _vertical store vertical to
     */
    public AjaxStorePositionBehavior(final boolean _vertical)
    {
        this.vertical = _vertical;
    }

    /**
     * On request the values are stored.
     *
     * @param _target AjaxRequestTarget
     */
    @Override
    protected void respond(final AjaxRequestTarget _target)
    {
        final StringValue horizontal = getComponent().getRequest().getRequestParameters().getParameterValue(
                        AjaxStorePositionBehavior.PARAMETER_HORIZONTALPOSITION);
        final StringValue verticalTmp = getComponent().getRequest().getRequestParameters().getParameterValue(
                        AjaxStorePositionBehavior.PARAMETER_VERTICALPOSITION);
        if (!horizontal.isNull()) {
            Configuration.setAttribute(ConfigAttribute.SPLITTERPOSHORIZONTAL, horizontal.toString());
        }
        if (!verticalTmp.isNull()) {
            Configuration.setAttribute(ConfigAttribute.SPLITTERPOSVERTICAL, verticalTmp.toString());
        }
    }

    @Override
    public void renderHead(final Component _component,
                           final IHeaderResponse _response)
    {
        super.renderHead(_component, _response);
        _response.render(JavaScriptHeaderItem.forScript(getCallbackScript(),
                        AjaxStorePositionBehavior.class.getName()));
    }

    /**
     * @see org.apache.wicket.ajax.AbstractDefaultAjaxBehavior#getCallbackScript()
     * @param _component Component the script belongs to
     * @return script
     */
    @Override
    public CharSequence getCallbackScript(final Component _component)
    {
        final String borderPanelId = ((ContentContainerPage) _component.getPage()).getBorderPanelId();
        final String leftPanelId = _component.getMarkupId(true);
        final String topPanelId = ((SidePanel) _component).getTopPanelId();

        final StringBuilder storeJs = new StringBuilder();
        if (this.vertical) {
            storeJs.append("var storePosV = ")
                .append(getCallbackFunction(
                            CallbackParameter.explicit(AjaxStorePositionBehavior.PARAMETER_VERTICALPOSITION)));
        }
        storeJs.append("var storePosH = ").
                append(getCallbackFunction(
                            CallbackParameter.explicit(AjaxStorePositionBehavior.PARAMETER_HORIZONTALPOSITION)));

        final StringBuilder js = new StringBuilder()
            .append("ready(function() {\n")
            .append("var bp = registry.byId(\"").append(borderPanelId).append("\");\n")
            .append("var lp = registry.byId(\"").append(leftPanelId).append("\");\n")
            .append("var hs = bp.getSplitter(\"leading\");\n");

        if (this.vertical) {
            js.append("var tp = registry.byId(\"").append(topPanelId).append("\");\n")
                .append("var vs = lp.getSplitter(\"top\");\n");
        }

        js.append(" aspect.after(hs, \"onOpen\",function(pane){\n")
            .append("storePosH(pane.domNode.clientWidth);")
            .append("});\n")
            .append(" aspect.after(hs, \"onClosed\",function(pane){\n")
            .append("storePosH(pane.domNode.clientWidth);")
            .append("});\n")
            .append(" aspect.after(hs, \"_stopDrag\",function(e){\n")
            .append("storePosH(lp.domNode.clientWidth);")
            .append("});\n");

        if (this.vertical) {
            js.append(" aspect.after(vs, \"onOpen\",function(pane){\n")
                .append("storePosV(pane.domNode.clientHeight);")
                .append("});\n")
                .append(" aspect.after(vs, \"onClosed\",function(pane){\n")
                .append("storePosV(pane.domNode.clientHeight);")
                .append("});\n")
                .append(" aspect.after(vs, \"_stopDrag\",function(e){\n")
                .append("storePosV(tp.domNode.clientHeight);")
                .append("});\n");
        }
        js.append("});");
        return storeJs.toString() + DojoWrapper.require(js, DojoClasses.ready, DojoClasses.registry,
                        DojoClasses.aspect);
    }

    @Override
    protected void updateAjaxAttributes(final AjaxRequestAttributes _attributes)
    {
        super.updateAjaxAttributes(_attributes);
        _attributes.setThrottlingSettings(new ThrottlingSettings("storeThrottel", Duration.seconds(2)));
        _attributes.setMethod(Method.POST);
    }
}


/*
 * Copyright 2003 - 2015 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;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.lang3.EnumUtils;
import org.efaps.admin.event.EventType;
import org.efaps.admin.event.Parameter;
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.Command;
import org.efaps.admin.ui.field.FieldPicker;
import org.efaps.api.ui.UIType;
import org.efaps.db.Context;
import org.efaps.db.Instance;
import org.efaps.ui.wicket.models.AbstractInstanceObject;
import org.efaps.ui.wicket.models.objects.ICmdUIObject;
import org.efaps.util.EFapsException;
import org.efaps.util.cache.CacheReloadException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * TODO comment!
 *
 * @author The eFaps Team
 */
public class UIPicker
    extends AbstractInstanceObject
    implements Serializable, ICmdUIObject
{
    /**
     * Logging instance used in this class.
     */
    private static final Logger LOG = LoggerFactory.getLogger(UIPicker.class);

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

    /**
     * UUID of the command used for this PickerObject.
     */
    private final UUID cmdUUID;

    /**
     * Label of this Picker.
     */
    private final String label;

    /**
     * The parent UIObject.
     */
    private final AbstractInstanceObject parent;

    /**
     * Was the event already executed.
     */
    private boolean executed = false;

    /**
     * UItype used.
     */
    private UIType uiType;

    /**
     * Map returned by the esjp.
     */
    private Map<String, Object> returnMap = new HashMap<>();

    /**
     * Parameter map.
     */
    private Map<String, String[]> parentParameters;

    /**
     * @param _field    fieldPicker this UIObject belongs to
     * @param _parent   parent field this fieldpicker belongs to
     * @throws CacheReloadException on error during access to command
     */
    public UIPicker(final FieldPicker _field,
                    final AbstractInstanceObject _parent)
        throws CacheReloadException
    {
        this.cmdUUID = _field.getCommand().getUUID();
        this.label = _field.getCommand().getLabelProperty();
        this.parent = _parent;
        final String uiTypeStr = _field.getProperty("UIType");
        if (EnumUtils.isValidEnum(UIType.class, uiTypeStr)) {
            this.uiType = UIType.valueOf(uiTypeStr);
        } else {
            this.uiType = UIType.DEFAULT;
        }

    }

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

    /**
     * @return the command underlying this picker
     * @throws CacheReloadException on error during access to command
     */
    @Override
    public Command getCommand()
        throws CacheReloadException
    {
        return Command.get(this.cmdUUID);
    }

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

    /**
     * @return the height of the window to be opened
     */
    public int getWindowHeight()
    {
        int ret = 0;
        try {
            ret = getCommand().getWindowHeight();
        } catch (final CacheReloadException e) {
            UIPicker.LOG.error("Coould not read WindowHeight for Command with uuid:{}", getCmdUUID());
        }
        return ret;
    }

    /**
     * @return the width of the window to be opened
     */
    public int getWindowWidth()
    {
        int ret = 0;
        try {
            ret = getCommand().getWindowWidth();
        } catch (final CacheReloadException e) {
            UIPicker.LOG.error("Coould not read WindowWith for Command with uuid:{}", getCmdUUID());
        }
        return ret;
    }

    /**
     * {@inheritDoc}
     *
     * @throws EFapsException
     */
    @Override
    public Instance getInstance()
        throws EFapsException
    {
        return this.parent.getInstance();
    }

    /**
     * Execute events.
     *
     * @param _eventType the event type
     * @param _objectTuples the object tuples
     * @return the list< return>
     * @throws EFapsException on error
     */
    @Override
    @SuppressWarnings("unchecked")
    public List<Return> executeEvents(final EventType _eventType,
                                      final Object... _objectTuples)
        throws EFapsException
    {
        List<Return> ret = new ArrayList<>();
        if (_eventType.equals(EventType.UI_COMMAND_EXECUTE) && getCommand().hasEvents(EventType.UI_PICKER)) {
            this.executed  = true;
            final Parameter param = new Parameter();
            if (_objectTuples != null) {
                // add all parameters
                for (int i = 0; i < _objectTuples.length; i += 2) {
                    if (i + 1 < _objectTuples.length && _objectTuples[i] instanceof ParameterValues) {
                        param.put((ParameterValues) _objectTuples[i], _objectTuples[i + 1]);
                    }
                }
            }
            param.put(ParameterValues.PARAMETERS, Context.getThreadContext().getParameters());
            param.put(ParameterValues.PARENTPARAMETERS, this.parentParameters);
            if (getInstance() != null) {
                final String[] contextoid = { getInstanceKey() };
                Context.getThreadContext().getParameters().put("oid", contextoid);
                param.put(ParameterValues.CALL_INSTANCE, getInstance());
                param.put(ParameterValues.INSTANCE, getInstance());
            }
            ret = getCommand().executeEvents(EventType.UI_PICKER, param);
            this.returnMap = (Map<String, Object>) ret.get(0).get(ReturnValues.VALUES);
        }
        return ret;
    }

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

    /**
     * Setter method for instance variable {@link #executed}.
     *
     * @param _executed value for instance variable {@link #executed}
     */

    public void setExecuted(final boolean _executed)
    {
        this.executed = _executed;
    }

    /**
     * Getter method for the instance variable {@link #returnMap}.
     *
     * @return value of instance variable {@link #returnMap}
     */
    public Map<String, Object> getReturnMap()
    {
        return this.returnMap;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Instance getInstanceFromManager()
        throws EFapsException
    {
        return getParent().getInstanceFromManager();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean hasInstanceManager()
        throws EFapsException
    {
        return getParent().hasInstanceManager();
    }

    /**
     * Checks if is button.
     *
     * @return true, if is button
     */
    public boolean isButton()
    {
        return UIType.BUTTON.equals(this.uiType);
    }

    /**
     * Gets the parent UIObject.
     *
     * @return the parent UIObject
     */
    public AbstractInstanceObject getParent()
    {
        return this.parent;
    }

    /**
     * Sets the parameter map.
     *
     * @param _parameters the new parameter map
     */
    public void setParentParameters(final Map<String, String[]> _parameters)
    {
        this.parentParameters = _parameters;
    }
}


/*
 * 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.textindex.query.search;

import com.fasterxml.jackson.databind.JavaType;
import com.hp.autonomy.hod.client.api.authentication.AuthenticationToken;
import com.hp.autonomy.hod.client.api.authentication.EntityType;
import com.hp.autonomy.hod.client.api.authentication.TokenType;
import com.hp.autonomy.hod.client.config.HodServiceConfig;
import com.hp.autonomy.hod.client.config.Requester;
import com.hp.autonomy.hod.client.error.HodErrorException;
import com.hp.autonomy.hod.client.token.TokenProxy;
import com.hp.autonomy.hod.client.util.TypedByteArrayWithFilename;
import org.apache.commons.io.IOUtils;
import retrofit.client.Response;
import retrofit.mime.TypedFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;

/**
 * Default implementation of FindSimilarService
 * <p/>
 * If you don't need a custom return type use the {@link #documentsService(HodServiceConfig)} static factory
 * @param <T> The desired return type of the service
 */
@SuppressWarnings("WeakerAccess")
public class FindSimilarServiceImpl<T extends Serializable> implements FindSimilarService<T> {

    private static final String MIME_TYPE = "application/octet-stream";

    private final FindSimilarBackend findSimilarBackend;
    private final Requester<?, TokenType.Simple> requester;
    private final JavaType returnType;

    /**
     * Creates a new FindSimilarServiceImpl with the given configuration and return type
     * @param hodServiceConfig The configuration to use
     * @param documentType The desired type of the documents returned by the service. This type must have the correct Jackson
     * annotations to read responses from HP Haven OnDemand
     */
    public FindSimilarServiceImpl(final HodServiceConfig<?, TokenType.Simple> hodServiceConfig, final Class<T> documentType) {
        findSimilarBackend = hodServiceConfig.getRestAdapter().create(FindSimilarBackend.class);
        requester = hodServiceConfig.getRequester();
        returnType = hodServiceConfig.getObjectMapper().getTypeFactory().constructParametrizedType(QueryResults.class, QueryResults.class , documentType);
    }

    /**
     * Creates a new FindSimilarServiceImpl of type {@link QueryResults}
     * @param hodServiceConfig The configuration to use
     * @return The new service
     */
    public static FindSimilarServiceImpl<Document> documentsService(final HodServiceConfig<?, TokenType.Simple> hodServiceConfig) {
        return new FindSimilarServiceImpl<>(hodServiceConfig, Document.class);
    }

    @Override
    public QueryResults<T> findSimilarDocumentsToText(final String text, final QueryRequestBuilder params) throws HodErrorException {
        return requester.unsafeMakeRequest(returnType, getTextBackendCaller(text, params));
    }

    @Override
    public QueryResults<T> findSimilarDocumentsToText(final TokenProxy<?, TokenType.Simple> tokenProxy, final String text, final QueryRequestBuilder params) throws HodErrorException {
        return requester.unsafeMakeRequest(tokenProxy, returnType, getTextBackendCaller(text, params));
    }

    @Override
    public QueryResults<T> findSimilarDocumentsToReference(final String reference, final QueryRequestBuilder params) throws HodErrorException {
        return requester.unsafeMakeRequest(returnType, getReferenceBackendCaller(reference, params));
    }

    @Override
    public QueryResults<T> findSimilarDocumentsToReference(final TokenProxy<?, TokenType.Simple> tokenProxy, final String reference, final QueryRequestBuilder params) throws HodErrorException {
        return requester.unsafeMakeRequest(tokenProxy, returnType, getReferenceBackendCaller(reference, params));
    }

    @Override
    public QueryResults<T> findSimilarDocumentsToUrl(final String url, final QueryRequestBuilder params) throws HodErrorException {
        return requester.unsafeMakeRequest(returnType, getUrlBackendCaller(url, params));
    }

    @Override
    public QueryResults<T> findSimilarDocumentsToUrl(final TokenProxy<?, TokenType.Simple> tokenProxy, final String url, final QueryRequestBuilder params) throws HodErrorException {
        return requester.unsafeMakeRequest(tokenProxy, returnType, getUrlBackendCaller(url, params));
    }

    @Override
    public QueryResults<T> findSimilarDocumentsToIndexReference(final String indexReference, final QueryRequestBuilder params) throws HodErrorException {
        return requester.unsafeMakeRequest(returnType, getIndexReferenceBackendCaller(indexReference, params));
    }

    @Override
    public QueryResults<T> findSimilarDocumentsToIndexReference(final TokenProxy<?, TokenType.Simple> tokenProxy, final String indexReference, final QueryRequestBuilder params) throws HodErrorException {
        return requester.unsafeMakeRequest(tokenProxy, returnType, getIndexReferenceBackendCaller(indexReference, params));
    }

    @Override
    public QueryResults<T> findSimilarDocumentsToFile(final File file, final QueryRequestBuilder params) throws HodErrorException {
        return requester.unsafeMakeRequest(returnType, getFileBackendCaller(file, params));
    }

    @Override
    public QueryResults<T> findSimilarDocumentsToFile(final TokenProxy<?, TokenType.Simple> tokenProxy, final File file, final QueryRequestBuilder params) throws HodErrorException {
        return requester.unsafeMakeRequest(tokenProxy, returnType, getFileBackendCaller(file, params));
    }

    @Override
    public QueryResults<T> findSimilarDocumentsToFile(final byte[] bytes, final QueryRequestBuilder params) throws HodErrorException {
        return requester.unsafeMakeRequest(returnType, getByteArrayBackendCaller(bytes, params));
    }

    @Override
    public QueryResults<T> findSimilarDocumentsToFile(final TokenProxy<?, TokenType.Simple> tokenProxy, final byte[] bytes, final QueryRequestBuilder params) throws HodErrorException {
        return requester.unsafeMakeRequest(tokenProxy, returnType, getByteArrayBackendCaller(bytes, params));
    }

    @Override
    public QueryResults<T> findSimilarDocumentsToFile(final InputStream inputStream, final QueryRequestBuilder params) throws HodErrorException {
        return requester.unsafeMakeRequest(returnType, getInputStreamBackendCaller(inputStream, params));
    }

    @Override
    public QueryResults<T> findSimilarDocumentsToFile(final TokenProxy<?, TokenType.Simple> tokenProxy, final InputStream inputStream, final QueryRequestBuilder params) throws HodErrorException {
        return requester.unsafeMakeRequest(tokenProxy, returnType, getInputStreamBackendCaller(inputStream, params));
    }

    private Requester.BackendCaller<EntityType, TokenType.Simple> getTextBackendCaller(final String text, final QueryRequestBuilder params) {
        return authenticationToken -> findSimilarBackend.findSimilarDocumentsToText(authenticationToken, text, params.build());
    }

    private Requester.BackendCaller<EntityType, TokenType.Simple> getReferenceBackendCaller(final String reference, final QueryRequestBuilder params) {
        return authenticationToken -> findSimilarBackend.findSimilarDocumentsToReference(authenticationToken, reference, params.build());
    }

    private Requester.BackendCaller<EntityType, TokenType.Simple> getUrlBackendCaller(final String url, final QueryRequestBuilder params) {
        return authenticationToken -> findSimilarBackend.findSimilarDocumentsToUrl(authenticationToken, url, params.build());
    }

    private Requester.BackendCaller<EntityType, TokenType.Simple> getIndexReferenceBackendCaller(final String indexReference, final QueryRequestBuilder params) {
        return authenticationToken -> findSimilarBackend.findSimilarDocumentsToIndexReference(authenticationToken, indexReference, params.build());
    }

    private Requester.BackendCaller<EntityType, TokenType.Simple> getFileBackendCaller(final File file, final QueryRequestBuilder params) {
        return authenticationToken -> findSimilarBackend.findSimilarDocumentsToFile(authenticationToken, new TypedFile(MIME_TYPE, file), params.build());
    }

    private Requester.BackendCaller<EntityType, TokenType.Simple> getByteArrayBackendCaller(final byte[] bytes, final QueryRequestBuilder params) {
        return authenticationToken -> findSimilarBackend.findSimilarDocumentsToFile(authenticationToken, new TypedByteArrayWithFilename(MIME_TYPE, bytes), params.build());
    }

    private Requester.BackendCaller<EntityType, TokenType.Simple> getInputStreamBackendCaller(final InputStream inputStream, final QueryRequestBuilder params) {
        return authenticationToken -> {
            try {
                return findSimilarBackend.findSimilarDocumentsToFile(authenticationToken, new TypedByteArrayWithFilename(MIME_TYPE, IOUtils.toByteArray(inputStream)), params.build());
            } catch (final IOException e) {
                throw new RuntimeException(e);
            }
        };
    }
}