com.haulmont.cuba.web.gui.components.WebAbstractOptionsField.java Source code

Java tutorial

Introduction

Here is the source code for com.haulmont.cuba.web.gui.components.WebAbstractOptionsField.java

Source

/*
 * Copyright (c) 2008-2016 Haulmont.
 *
 * 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 com.haulmont.cuba.web.gui.components;

import com.haulmont.chile.core.datatypes.Enumeration;
import com.haulmont.chile.core.datatypes.impl.EnumClass;
import com.haulmont.chile.core.model.MetaClass;
import com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesUtils;
import com.haulmont.cuba.core.app.dynamicattributes.PropertyType;
import com.haulmont.cuba.core.entity.CategoryAttribute;
import com.haulmont.cuba.core.global.AppBeans;
import com.haulmont.cuba.core.global.MessageTools;
import com.haulmont.cuba.gui.components.CaptionMode;
import com.haulmont.cuba.gui.components.OptionsField;
import com.haulmont.cuba.gui.data.CollectionDatasource;
import com.haulmont.cuba.gui.data.Datasource;
import com.haulmont.cuba.gui.data.impl.WeakItemChangeListener;
import com.haulmont.cuba.web.gui.data.CollectionDsWrapper;
import com.haulmont.cuba.web.gui.data.EnumerationContainer;
import com.haulmont.cuba.web.gui.data.ItemWrapper;
import com.haulmont.cuba.web.gui.data.ObjectContainer;
import com.vaadin.data.Property;
import com.vaadin.ui.AbstractSelect;
import org.apache.commons.lang.StringUtils;

import java.util.*;

import static com.haulmont.cuba.gui.ComponentsHelper.handleFilteredAttributes;

public abstract class WebAbstractOptionsField<T extends com.vaadin.ui.AbstractSelect> extends WebAbstractField<T>
        implements OptionsField {

    protected List optionsList;
    protected Map<String, Object> optionsMap;
    protected Class<? extends EnumClass> optionsEnum;
    protected CollectionDatasource optionsDatasource;

    protected CaptionMode captionMode = CaptionMode.ITEM;
    protected String captionProperty;
    protected String descriptionProperty;

    /**
     * In the initialization list of options updating the data source is prohibited
     */
    protected boolean optionsInitialization = false;

    protected Datasource.ItemChangeListener securitytemChangeListener;

    @Override
    public void setDatasource(Datasource datasource, String property) {
        this.datasource = datasource;

        MetaClass metaClass = datasource.getMetaClass();
        resolveMetaPropertyPath(metaClass, property);

        if (metaProperty.getRange().getCardinality() != null) {
            setMultiSelect(metaProperty.getRange().getCardinality().isMany());
        }

        ItemWrapper wrapper = createDatasourceWrapper(datasource, Collections.singleton(metaPropertyPath));
        Property itemProperty = wrapper.getItemProperty(metaPropertyPath);

        setRequired(metaProperty.isMandatory());
        if (StringUtils.isEmpty(getRequiredMessage())) {
            MessageTools messageTools = AppBeans.get(MessageTools.NAME);
            setRequiredMessage(messageTools.getDefaultRequiredMessage(metaClass, property));
        }

        if (metaProperty.getRange().isEnum()) {
            Enumeration enumeration = metaProperty.getRange().asEnumeration();
            List options = Arrays.asList(enumeration.getJavaClass().getEnumConstants());
            setComponentContainerDs(createEnumContainer(options));

            setCaptionMode(CaptionMode.ITEM);
        }

        if (DynamicAttributesUtils.isDynamicAttribute(metaProperty)) {
            CategoryAttribute categoryAttribute = DynamicAttributesUtils.getCategoryAttribute(metaProperty);
            if (categoryAttribute != null && categoryAttribute.getDataType() == PropertyType.ENUMERATION) {
                setOptionsList(categoryAttribute.getEnumerationOptions());
            }
        }

        component.setPropertyDataSource(itemProperty);

        if (metaProperty.isReadOnly()) {
            setEditable(false);
        }

        handleFilteredAttributes(this, this.datasource, metaPropertyPath);
        securitytemChangeListener = e -> handleFilteredAttributes(this, this.datasource, metaPropertyPath);
        //noinspection unchecked
        this.datasource.addItemChangeListener(new WeakItemChangeListener(datasource, securitytemChangeListener));
    }

    protected EnumerationContainer createEnumContainer(List options) {
        return new EnumerationContainer(options);
    }

    protected ObjectContainer createObjectContainer(List opts) {
        return new ObjectContainer(opts);
    }

    @Override
    public void setOptionsMap(Map<String, Object> options) {
        if (metaProperty != null && metaProperty.getRange().isEnum()) {
            List constants = Arrays
                    .asList(metaProperty.getRange().asEnumeration().getJavaClass().getEnumConstants());
            List opts = new ArrayList();

            for (Map.Entry<String, Object> entry : options.entrySet()) {
                String key = entry.getKey();
                Object itemId = entry.getValue();

                component.setItemCaption(itemId, key);
                if (!constants.contains(itemId)) {
                    throw new UnsupportedOperationException(
                            itemId + " is not of class of meta property" + metaProperty);
                }
                opts.add(itemId);
            }
            this.optionsList = opts;

            setComponentContainerDs(createEnumContainer(opts));
            setCaptionMode(CaptionMode.ITEM);
        } else {
            List opts = new ArrayList();
            for (Map.Entry<String, Object> entry : options.entrySet()) {
                String key = entry.getKey();
                Object itemId = entry.getValue();

                component.setItemCaption(itemId, key);
                opts.add(itemId);
            }
            setComponentContainerDs(createObjectContainer(opts));
            component.setItemCaptionMode(AbstractSelect.ItemCaptionMode.EXPLICIT_DEFAULTS_ID);
            this.optionsMap = options;
        }
    }

    protected void setComponentContainerDs(com.vaadin.data.Container newDataSource) {
        optionsInitialization = true;
        component.setContainerDataSource(newDataSource);
        optionsInitialization = false;
    }

    @Override
    public void setOptionsList(List optionsList) {
        if (metaProperty != null) {
            Object currentValue = component.getValue();
            if (metaProperty.getRange().isEnum()) {
                setComponentContainerDs(createEnumContainer(optionsList));
                setCaptionMode(CaptionMode.ITEM);
            } else {
                setComponentContainerDs(createObjectContainer(optionsList));
                component.setItemCaptionMode(AbstractSelect.ItemCaptionMode.ITEM);
            }

            component.setValue(currentValue);
            this.optionsList = optionsList;
        } else if (!optionsList.isEmpty()) {
            final Object o = optionsList.iterator().next();
            if (o instanceof Enum) {
                setComponentContainerDs(createEnumContainer(optionsList));
            } else {
                setComponentContainerDs(createObjectContainer(optionsList));
            }
            setCaptionMode(CaptionMode.ITEM);
            this.optionsList = optionsList;
        } else {
            setComponentContainerDs(createObjectContainer(optionsList));
            setCaptionMode(CaptionMode.ITEM);
            this.optionsList = optionsList;
        }
    }

    @Override
    public Class<? extends EnumClass> getOptionsEnum() {
        return optionsEnum;
    }

    @Override
    public void setOptionsEnum(Class<? extends EnumClass> optionsEnum) {
        Object currentValue = null;
        if (metaProperty != null) {
            currentValue = component.getValue();
        }
        List options = Arrays.asList(optionsEnum.getEnumConstants());
        setComponentContainerDs(createEnumContainer(options));
        setCaptionMode(CaptionMode.ITEM);

        if (metaProperty != null) {
            component.setValue(currentValue);
        }

        this.optionsEnum = optionsEnum;
    }

    @Override
    public boolean isMultiSelect() {
        return component.isMultiSelect();
    }

    @Override
    public void setMultiSelect(boolean multiselect) {
        component.setMultiSelect(multiselect);
    }

    @Override
    public CaptionMode getCaptionMode() {
        return captionMode;
    }

    @Override
    public void setCaptionMode(CaptionMode captionMode) {
        this.captionMode = captionMode;
        switch (captionMode) {
        case ITEM:
            component.setItemCaptionMode(AbstractSelect.ItemCaptionMode.ITEM);
            break;

        case PROPERTY:
            component.setItemCaptionMode(AbstractSelect.ItemCaptionMode.PROPERTY);
            break;

        default:
            throw new UnsupportedOperationException();
        }
    }

    @Override
    public String getCaptionProperty() {
        return captionProperty;
    }

    @Override
    public void setCaptionProperty(String captionProperty) {
        this.captionProperty = captionProperty;
        if (optionsDatasource != null) {
            component.setItemCaptionPropertyId(optionsDatasource.getMetaClass().getProperty(captionProperty));
        }
    }

    @Override
    public String getDescriptionProperty() {
        return descriptionProperty;
    }

    @Override
    public void setDescriptionProperty(String descriptionProperty) {
        this.descriptionProperty = descriptionProperty;
        //todo gorodnov: support description for all option fields
    }

    @Override
    public List getOptionsList() {
        return optionsList;
    }

    @Override
    public Map<String, Object> getOptionsMap() {
        return optionsMap;
    }

    @Override
    public CollectionDatasource getOptionsDatasource() {
        return optionsDatasource;
    }

    @Override
    public void setOptionsDatasource(CollectionDatasource datasource) {
        this.optionsDatasource = datasource;
        setComponentContainerDs(new CollectionDsWrapper(datasource, true));

        if (captionProperty != null) {
            component.setItemCaptionPropertyId(optionsDatasource.getMetaClass().getProperty(captionProperty));
        }
    }

    @SuppressWarnings({ "unchecked" })
    protected <T> T wrapAsCollection(Object o) {
        if (isMultiSelect()) {
            if (o instanceof Collection) {
                return (T) Collections.unmodifiableCollection((Collection) o);
            } else if (o != null) {
                return (T) Collections.singleton(o);
            } else {
                return (T) Collections.emptySet();
            }
        } else {
            return (T) o;
        }
    }
}