org.tylproject.vaadin.addon.fieldbinder.FieldBinderFieldFactory.java Source code

Java tutorial

Introduction

Here is the source code for org.tylproject.vaadin.addon.fieldbinder.FieldBinderFieldFactory.java

Source

/*
 * Copyright (c) 2015 - Tyl Consulting s.a.s.
 *
 *   Authors: Edoardo Vacchi
 *   Contributors: Marco Pancotti, Daniele Zonca
 *
 * 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.tylproject.vaadin.addon.fieldbinder;

import com.vaadin.data.Item;
import com.vaadin.data.fieldgroup.DefaultFieldGroupFieldFactory;
import com.vaadin.data.util.converter.Converter;
import com.vaadin.shared.util.SharedUtil;
import com.vaadin.ui.*;
import org.joda.time.DateTime;
import org.tylproject.vaadin.addon.fields.collectiontables.CollectionTable;
import org.tylproject.vaadin.addon.fields.collectiontables.ListTable;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * An extended {@link com.vaadin.data.fieldgroup.FieldGroupFieldFactory}
 * that supports {@link org.tylproject.vaadin.addon.fields.collectiontables.ListTable}
 */
public class FieldBinderFieldFactory extends DefaultFieldGroupFieldFactory {

    protected ResourceBundle resourceBundle = null;

    public void setResourceBundle(ResourceBundle resourceBundle) {
        this.resourceBundle = resourceBundle;
    }

    public ResourceBundle getResourceBundle() {
        return resourceBundle;
    }

    public boolean hasResourceBundle() {
        return resourceBundle != null;
    }

    public String createCaptionByPropertyId(Object propertyId) {
        if (hasResourceBundle()) {
            String propertyIdString = propertyId.toString();
            if (resourceBundle.containsKey(propertyIdString)) {
                return resourceBundle.getString(propertyIdString);
            }
        }
        return SharedUtil.propertyIdToHumanFriendly(propertyId);
    }

    public <T extends Field> T createField(Class<?> type, Class<T> fieldType) {
        Field<?> f;
        if (AbstractSelect.class.isAssignableFrom(fieldType)) {
            f = createCompatibleSelect((Class<AbstractSelect>) fieldType);
        } else {
            f = super.createField(type, fieldType);
        }

        if (f instanceof AbstractTextField) {
            ((AbstractTextField) f).setConverter(type);
        }

        f = configureJodaTimeField(type, f);

        ((AbstractField<?>) f).setImmediate(true);
        return (T) f;
    }

    private Field<?> configureJodaTimeField(Class<?> type, Field<?> f) {
        boolean isJoda = false;
        try {
            isJoda = DateTime.class.isAssignableFrom(type);
        } catch (NoClassDefFoundError ex) {
            // then it can't be joda
        }
        // FIXME: pull out Joda-specific logic for date-time
        if (isJoda) {
            DateField dateField = createField(Date.class, DateField.class);
            f = dateField;
            dateField.setConverter(new Converter<Date, DateTime>() {
                @Override
                public DateTime convertToModel(Date date, Class<? extends DateTime> aClass, Locale locale)
                        throws ConversionException {
                    return date == null ? null : new DateTime(date);
                }

                @Override
                public Date convertToPresentation(DateTime o, Class<? extends Date> aClass, Locale locale)
                        throws ConversionException {
                    return o == null ? null : o.toDate();
                }

                @Override
                public Class<DateTime> getModelType() {
                    return DateTime.class;
                }

                @Override
                public Class<Date> getPresentationType() {
                    return Date.class;
                }
            });
        }

        if (Date.class.isAssignableFrom(type) || isJoda) {

            // try to assign a locale-specific date pattern
            DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault());

            if (dateFormat instanceof SimpleDateFormat) {
                String pattern = ((SimpleDateFormat) dateFormat).toLocalizedPattern();
                DateField dateField = (DateField) f;

                // hack: turn 2-digits year into 4-digits year
                dateField.setDateFormat(pattern.replace("yy", "yyyy"));

            }
        }
        return f;
    }

    @Override
    protected AbstractSelect createCompatibleSelect(Class<? extends AbstractSelect> fieldType) {

        AbstractSelect select;

        if (fieldType.isAssignableFrom(ComboBox.class)) {
            select = new ComboBox();
            select.setImmediate(true);
            select.setNullSelectionAllowed(false);
            return select;
        } else if (OptionGroup.class.isAssignableFrom(fieldType)) {
            select = new OptionGroup();
            select.setMultiSelect(false);
            return select;
        } else {
            return super.createCompatibleSelect(fieldType);
        }
    }

    @Override
    protected <T extends AbstractTextField> T createAbstractTextField(Class<T> fieldType) {
        T field = super.createAbstractTextField(fieldType);
        field.setNullRepresentation("");
        return field;
    }

    public <T, U extends Collection<T>> CollectionTable<T, U> createDetailField(Class<U> dataType,
            Class<T> containedBeanClass, GridSupport gridSupport) {
        if (List.class.isAssignableFrom(dataType)) {
            return (CollectionTable<T, U>) new ListTable<T>(containedBeanClass, gridSupport);
        } else if (Collection.class.isAssignableFrom(dataType)) {
            return new CollectionTable<T, U>(containedBeanClass, dataType, gridSupport);
        } else
            throw new UnsupportedOperationException("Unsupported type " + dataType);
    }

    @Override
    protected void populateWithEnumData(AbstractSelect select, Class<? extends Enum> enumClass) {
        select.removeAllItems();
        for (Object p : select.getContainerPropertyIds()) {
            select.removeContainerProperty(p);
        }
        select.addContainerProperty(CAPTION_PROPERTY_ID, String.class, "");
        select.setItemCaptionPropertyId(CAPTION_PROPERTY_ID);
        @SuppressWarnings("unchecked")
        EnumSet<?> enumSet = EnumSet.allOf(enumClass);
        for (Enum<?> r : enumSet) {
            Item newItem = select.addItem(r);
            newItem.getItemProperty(CAPTION_PROPERTY_ID).setValue(getLocalizedEnumCaption(r));
        }
    }

    protected String getLocalizedEnumCaption(Enum<?> enumValue) {
        String enumName = enumValue.name();
        String baseName = enumValue.getDeclaringClass().getCanonicalName();

        String key = baseName + '.' + enumName;

        if (hasResourceBundle()) {
            if (resourceBundle.containsKey(key)) {
                return resourceBundle.getString(key);
            }
        }

        return enumValue.toString();
    }
}