org.efaps.ui.wicket.models.field.AbstractUIField.java Source code

Java tutorial

Introduction

Here is the source code for org.efaps.ui.wicket.models.field.AbstractUIField.java

Source

/*
 * 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.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang3.EnumUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.wicket.Component;
import org.apache.wicket.model.Model;
import org.efaps.admin.datamodel.ui.UIValue;
import org.efaps.admin.dbproperty.DBProperties;
import org.efaps.admin.event.EventDefinition;
import org.efaps.admin.event.EventType;
import org.efaps.admin.event.Parameter.ParameterValues;
import org.efaps.admin.event.Return;
import org.efaps.admin.ui.field.Field;
import org.efaps.api.ui.IOption;
import org.efaps.db.Context;
import org.efaps.db.Instance;
import org.efaps.ui.wicket.behaviors.dojo.AutoCompleteBehavior;
import org.efaps.ui.wicket.components.values.LabelField;
import org.efaps.ui.wicket.models.AbstractInstanceObject;
import org.efaps.ui.wicket.models.field.AutoCompleteSettings.EditValue;
import org.efaps.ui.wicket.models.field.factories.AutoCompleteFactory;
import org.efaps.ui.wicket.models.field.factories.BitEnumUIFactory;
import org.efaps.ui.wicket.models.field.factories.BooleanUIFactory;
import org.efaps.ui.wicket.models.field.factories.DateTimeUIFactory;
import org.efaps.ui.wicket.models.field.factories.DateUIFactory;
import org.efaps.ui.wicket.models.field.factories.DecimalUIFactory;
import org.efaps.ui.wicket.models.field.factories.EnumUIFactory;
import org.efaps.ui.wicket.models.field.factories.FormatedStringUIFactory;
import org.efaps.ui.wicket.models.field.factories.HRefFactory;
import org.efaps.ui.wicket.models.field.factories.IComponentFactory;
import org.efaps.ui.wicket.models.field.factories.JaxbUIFactory;
import org.efaps.ui.wicket.models.field.factories.LinkWithRangesUIFactory;
import org.efaps.ui.wicket.models.field.factories.NumberUIFactory;
import org.efaps.ui.wicket.models.field.factories.PasswordUIFactory;
import org.efaps.ui.wicket.models.field.factories.RateUIFactory;
import org.efaps.ui.wicket.models.field.factories.StringUIFactory;
import org.efaps.ui.wicket.models.field.factories.TypeUIFactory;
import org.efaps.ui.wicket.models.field.factories.UITypeFactory;
import org.efaps.ui.wicket.models.field.factories.UserUIFactory;
import org.efaps.ui.wicket.models.objects.AbstractUIModeObject;
import org.efaps.ui.wicket.models.objects.AbstractUIObject;
import org.efaps.util.EFapsException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * TODO comment!
 *
 * @author The eFaps Team
 */
public abstract class AbstractUIField extends AbstractInstanceObject
        implements IPickable, IHidden, IFilterable, IAutoComplete, IUIElement {
    /**
     * Needed for serialization.
     */
    private static final long serialVersionUID = 1L;

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

    /**
     * The factories used to construct the components.
     */
    private static final Map<String, IComponentFactory> FACTORIES = new LinkedHashMap<>();

    static {
        AbstractUIField.FACTORIES.put(HRefFactory.get().getKey(), HRefFactory.get());
        AbstractUIField.FACTORIES.put(AutoCompleteFactory.get().getKey(), AutoCompleteFactory.get());
        AbstractUIField.FACTORIES.put(NumberUIFactory.get().getKey(), NumberUIFactory.get());
        AbstractUIField.FACTORIES.put(PasswordUIFactory.get().getKey(), PasswordUIFactory.get());
        AbstractUIField.FACTORIES.put(StringUIFactory.get().getKey(), StringUIFactory.get());
        AbstractUIField.FACTORIES.put(LinkWithRangesUIFactory.get().getKey(), LinkWithRangesUIFactory.get());
        AbstractUIField.FACTORIES.put(BooleanUIFactory.get().getKey(), BooleanUIFactory.get());
        AbstractUIField.FACTORIES.put(DateUIFactory.get().getKey(), DateUIFactory.get());
        AbstractUIField.FACTORIES.put(DateTimeUIFactory.get().getKey(), DateTimeUIFactory.get());
        AbstractUIField.FACTORIES.put(DecimalUIFactory.get().getKey(), DecimalUIFactory.get());
        AbstractUIField.FACTORIES.put(UserUIFactory.get().getKey(), UserUIFactory.get());
        AbstractUIField.FACTORIES.put(TypeUIFactory.get().getKey(), TypeUIFactory.get());
        AbstractUIField.FACTORIES.put(RateUIFactory.get().getKey(), RateUIFactory.get());
        AbstractUIField.FACTORIES.put(EnumUIFactory.get().getKey(), EnumUIFactory.get());
        AbstractUIField.FACTORIES.put(BitEnumUIFactory.get().getKey(), BitEnumUIFactory.get());
        AbstractUIField.FACTORIES.put(JaxbUIFactory.get().getKey(), JaxbUIFactory.get());
        AbstractUIField.FACTORIES.put(FormatedStringUIFactory.get().getKey(), FormatedStringUIFactory.get());
        AbstractUIField.FACTORIES.put(UITypeFactory.get().getKey(), UITypeFactory.get());
    }

    /**
     * Configuration of the related field.
     */
    private FieldConfiguration fieldConfiguration;

    /**
     * Parent Object.
     */
    private final AbstractUIModeObject parent;

    /**
     * UserInterface Value.
     */
    private UIValue value;

    /**
     * Picker related to this field.
     */
    private UIPicker picker;

    /**
     * Already added.
     */
    private boolean added;

    /**
     * Factory applied for this field.
     */
    private String factoryKey;

    /**
     * Value as shown for a picklist.
     */
    private String pickListValue;

    /**
     * Settings for the AutoComplete.
     */
    private AutoCompleteSettings autoCompleteSetting;

    /** The sort value. */
    private Comparable<?> sortValue;

    /** The hide. */
    private boolean hide;

    /**
     * @param _instanceKey key to the instance
     * @param _parent       parent object
     * @param _value        value
     * @throws EFapsException on error
     */
    public AbstractUIField(final AbstractUIModeObject _parent, final String _instanceKey, final UIValue _value)
            throws EFapsException {
        super(_instanceKey);
        this.parent = _parent;
        this.value = _value;
        this.fieldConfiguration = getNewFieldConfiguration();
    }

    /**
     * Getter method for the instance variable {@link #autoCompleteSetting}.
     *
     * @return value of instance variable {@link #autoCompleteSetting}
     */
    @Override
    public AutoCompleteSettings getAutoCompleteSetting() {
        if (this.autoCompleteSetting == null && isAutoComplete()) {
            this.autoCompleteSetting = new AutoCompleteSettings(getFieldConfiguration());

            final List<EventDefinition> events = getFieldConfiguration().getField()
                    .getEvents(EventType.UI_FIELD_AUTOCOMPLETE);
            for (final EventDefinition event : events) {
                this.autoCompleteSetting.setMinInputLength(event.getProperty("MinInputLength") == null ? 1
                        : Integer.valueOf(event.getProperty("MinInputLength")));
                this.autoCompleteSetting.setMaxChoiceLength(event.getProperty("MaxChoiceLength") == null ? -1
                        : Integer.valueOf(event.getProperty("MaxChoiceLength")));
                this.autoCompleteSetting.setMaxValueLength(event.getProperty("MaxValueLength") == null ? -1
                        : Integer.valueOf(event.getProperty("MaxValueLength")));
                if (event.getProperty("MaxResult") != null) {
                    this.autoCompleteSetting.setMaxResult(Integer.valueOf(event.getProperty("MaxResult")));
                }
                if (event.getProperty("HasDownArrow") != null) {
                    this.autoCompleteSetting
                            .setHasDownArrow("true".equalsIgnoreCase(event.getProperty("HasDownArrow")));
                }
                if (event.getProperty("Required") != null) {
                    this.autoCompleteSetting.setRequired(!"false".equalsIgnoreCase(event.getProperty("Required")));
                }

                if (event.getProperty("AutoType") != null) {
                    this.autoCompleteSetting.setAutoType(
                            EnumUtils.getEnum(AutoCompleteBehavior.Type.class, event.getProperty("AutoType")));
                }

                // add the ExtraParameter definitions
                final String ep = event.getProperty("ExtraParameter");
                if (ep != null) {
                    this.autoCompleteSetting.getExtraParameters().add(ep);
                }
                int i = 1;
                String keyTmp = "ExtraParameter" + String.format("%02d", i);
                while (event.getProperty(keyTmp) != null) {
                    this.autoCompleteSetting.getExtraParameters().add(event.getProperty(keyTmp));
                    i++;
                    keyTmp = "ExtraParameter" + String.format("%02d", i);
                }

                final String value4EditStr = event.getProperty("Value4Edit");
                if (value4EditStr != null) {
                    this.autoCompleteSetting.setValue4Edit(EditValue.valueOf(value4EditStr));
                }
            }
        }
        return this.autoCompleteSetting;
    }

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

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean hasInstanceManager() throws EFapsException {
        return getParent() != null ? getParent().hasInstanceManager() : false;
    }

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

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

    /**
     * Setter method for instance variable {@link #value}.
     *
     * @param _value value for instance variable {@link #value}
     */
    public void setValue(final UIValue _value) {
        this.value = _value;
    }

    /**
     * Getter method for the instance variable {@link #fieldConfiguration}.
     *
     * @return value of instance variable {@link #fieldConfiguration}
     */
    public FieldConfiguration getFieldConfiguration() {
        return this.fieldConfiguration;
    }

    /**
     * @return the label for the UserInterface
     * @throws CacheReloadException on error
     */
    @Override
    public String getLabel() throws EFapsException {
        final String ret;
        if (getFieldConfiguration() != null) {
            ret = getFieldConfiguration().evalLabel(getValue(), getInstance());
        } else {
            ret = DBProperties.getProperty(FieldConfiguration.class.getName() + ".NoLabel");
        }
        return ret;
    }

    /**
     * Setter method for instance variable {@link #fieldConfiguration}.
     *
     * @param _fieldConfiguration value for instance variable {@link #fieldConfiguration}
     */

    protected void setFieldConfiguration(final FieldConfiguration _fieldConfiguration) {
        this.fieldConfiguration = _fieldConfiguration;
    }

    /**
     * @return a new FieldConfiguration
     * @throws EFapsException on error
     */
    protected FieldConfiguration getNewFieldConfiguration() throws EFapsException {
        final FieldConfiguration ret;
        if (getValue() == null) {
            ret = null;
        } else {
            ret = new FieldConfiguration(getValue().getField().getId());
        }
        return ret;
    }

    /**
     * @return is this value editable
     */
    public boolean editable() {
        return getValue().getField().isEditableDisplay(getParent().getMode());
    }

    /**
     * @return is this value editable
     */
    public boolean hidden() {
        return getValue().getField().isHiddenDisplay(getParent().getMode());
    }

    /**
     * @return the List of Factories used for this Field on construction of the component.
     */
    public Map<String, IComponentFactory> getFactories() {
        return AbstractUIField.FACTORIES;
    }

    /**
     * @param _wicketId wicket id
     * @return Component
     * @throws EFapsException on error
     */
    @Override
    public Component getComponent(final String _wicketId) throws EFapsException {
        Component ret = null;
        final IComponentFactory factory = getFactory();
        if (factory == null) {
            ret = new LabelField(_wicketId, Model.of("No Factory was applied successfully"),
                    this.fieldConfiguration, "NONE");
        } else {
            if (hidden()) {
                ret = factory.getHidden(_wicketId, this);
            } else if (editable()) {
                ret = factory.getEditable(_wicketId, this);
            } else {
                ret = factory.getReadOnly(_wicketId, this);
            }
        }
        if (ret == null) {
            throw new EFapsException(AbstractUIField.class, "factoryReturnsNoComponent",
                    getFieldConfiguration().getField());
        }
        return ret;
    }

    /**
     * Execute events.
     *
     * @param _eventType the event type
     * @param _others the others
     * @param _uiID2Oid the ui i d2 oid
     * @return the list< return>
     * @throws EFapsException on error
     */
    public List<Return> executeEvents(final EventType _eventType, final Object _others,
            final Map<String, String> _uiID2Oid) throws EFapsException {
        List<Return> ret = new ArrayList<Return>();
        final Field field = getFieldConfiguration().getField();
        if (field.hasEvents(_eventType)) {
            final Context context = Context.getThreadContext();
            final String[] contextoid = { getInstanceKey() };
            context.getParameters().put("oid", contextoid);
            ret = field.executeEvents(_eventType, ParameterValues.INSTANCE, getInstance(), ParameterValues.OTHERS,
                    _others, ParameterValues.PARAMETERS, context.getParameters(), ParameterValues.CLASS, this,
                    ParameterValues.OIDMAP4UI, _uiID2Oid, ParameterValues.CALL_INSTANCE, getParent().getInstance(),
                    ParameterValues.CALL_CMD, ((AbstractUIObject) getParent()).getCommand());
        }
        return ret;
    }

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

    /**
     * Setter method for instance variable {@link #picker}.
     *
     * @param _picker value for instance variable {@link #picker}
     */
    public void setPicker(final UIPicker _picker) {
        this.picker = _picker;
    }

    /**
     * @return true if a picker is assigned else false;
     */
    public boolean hasPicker() {
        return getPicker() != null;
    }

    /**
     * Hide label.
     *
     * @return true, if successful
     */
    public boolean hideLabel() {
        return hasPicker() && getPicker().isButton() || getFieldConfiguration().isHideLabel();
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this).append("Field", getFieldConfiguration().getField().getName())
                .append("Value", getValue()).build();
    }

    @Override
    public IHidden setAdded(final boolean _added) {
        this.added = _added;
        return this;
    }

    @Override
    public boolean isAdded() {
        return this.added;
    }

    @Override
    public boolean belongsTo(final Long _fieldId) {
        return getFieldConfiguration().getField().getId() == _fieldId;
    }

    @Override
    public String getPickListValue() throws EFapsException {
        if (this.pickListValue == null) {
            this.pickListValue = getFactory().getPickListValue(this);
        }
        return this.pickListValue;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Comparable<?> getCompareValue() {
        Comparable<?> ret = null;
        try {
            if (this.sortValue == null) {
                ret = getFactory().getCompareValue(this);
            } else {
                ret = this.sortValue;
            }
        } catch (final EFapsException e) {
            LOG.error("Catched error", e);
        }
        return ret;
    }

    @Override
    public ISortable setCompareValue(final Object _object) {
        if (_object != null && _object instanceof Comparable) {
            this.sortValue = (Comparable<?>) _object;
        }
        return this;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int compareTo(final ISortable _arg0) {
        return ObjectUtils.compare(getCompareValue(), _arg0.getCompareValue());
    }

    /**
     * Getter method for the instance variable {@link #factory}.
     *
     * @return value of instance variable {@link #factory}
     * @throws EFapsException on error
     */
    public IComponentFactory getFactory() throws EFapsException {
        if (getFactoryKey() == null) {
            for (final IComponentFactory factory : getFactories().values()) {
                if (factory.applies(this)) {
                    setFactory(factory);
                    break;
                }
            }
            if (getFactoryKey() == null) {
                LOG.error("Could not find factory for field '{}' in '{}'", getFieldConfiguration().getName(),
                        getFieldConfiguration().getField().getCollection().getName());
            }
        }
        return getFactories().get(getFactoryKey());
    }

    /**
     * Setter method for instance variable {@link #factory}.
     *
     * @param _factory value for instance variable {@link #factory}
     */
    public void setFactory(final IComponentFactory _factory) {
        this.factoryKey = _factory.getKey();
    }

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

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

    /**
     * Checks if is auto complete.
     *
     * @return true, if is auto complete
     */
    @Override
    public boolean isAutoComplete() {
        return getFieldConfiguration().getField().hasEvents(EventType.UI_FIELD_AUTOCOMPLETE);
    }

    @Override
    public boolean isFieldUpdate() {
        return getFieldConfiguration().getField().hasEvents(EventType.UI_FIELD_UPDATE);
    }

    @Override
    public List<Return> getAutoCompletion(final String _input, final Map<String, String> _uiID2Oid)
            throws EFapsException {
        return executeEvents(EventType.UI_FIELD_AUTOCOMPLETE, _input, _uiID2Oid);
    }

    @Override
    public String getAutoCompleteValue() throws EFapsException {
        final Object val = getValue().getReadOnlyValue(getParent().getMode());
        return val == null ? null : String.valueOf(val);
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<IOption> getTokens() throws EFapsException {
        final List<IOption> ret = new ArrayList<>();
        if (isAutoComplete() && getParent().isEditMode() && editable()
                && getFieldConfiguration().getField().hasEvents(EventType.UI_FIELD_VALUE)) {
            final Object obj = getValue().getEditValue(getParent().getMode());
            if (obj instanceof List<?>) {
                ret.addAll((Collection<? extends IOption>) obj);
            }
        }
        return ret;
    }

    @Override
    public Instance getInstance() throws EFapsException {
        final Instance ret;
        // in case of an autocomplete in editmode give the chance to set the instance
        if (isAutoComplete() && getParent().isEditMode() && editable()
                && getFieldConfiguration().getField().hasEvents(EventType.UI_FIELD_VALUE)) {
            getValue().getEditValue(getParent().getMode());
            ret = getValue().getInstance();
        } else {
            ret = super.getInstance();
        }
        return ret;
    }

    /**
     * Checks if is hide.
     *
     * @return the hide
     */
    public boolean isHide() {
        return this.hide;
    }

    /**
     * Sets the hide.
     *
     * @param _hide the new hide
     */
    public void setHide(final boolean _hide) {
        this.hide = _hide;
    }
}