com.premiumminds.wicket.crudifier.form.elements.ListControlGroups.java Source code

Java tutorial

Introduction

Here is the source code for com.premiumminds.wicket.crudifier.form.elements.ListControlGroups.java

Source

/**
 * Copyright (C) 2014 Premium Minds.
 *
 * This file is part of wicket-crudifier.
 *
 * wicket-crudifier is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option) any
 * later version.
 *
 * wicket-crudifier is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with wicket-crudifier. If not, see <http://www.gnu.org/licenses/>.
 */
package com.premiumminds.wicket.crudifier.form.elements;

import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.validation.Validator;
import javax.validation.constraints.NotNull;
import javax.validation.metadata.BeanDescriptor;
import javax.validation.metadata.ConstraintDescriptor;
import javax.validation.metadata.ElementDescriptor;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.wicket.Component;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.repeater.RepeatingView;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.PropertyModel;
import org.hibernate.validator.constraints.NotBlank;
import org.hibernate.validator.constraints.NotEmpty;
import org.joda.time.DateTime;
import org.joda.time.Instant;

import com.premiumminds.webapp.wicket.validators.HibernateValidatorProperty;
import com.premiumminds.wicket.crudifier.IObjectRenderer;
import com.premiumminds.wicket.crudifier.form.CrudifierEntitySettings;
import com.premiumminds.wicket.crudifier.form.EntityProvider;

public abstract class ListControlGroups<T> extends Panel {
    private static final long serialVersionUID = 7205285700113097720L;

    private Map<String, AbstractControlGroup<?>> fieldComponents = new HashMap<String, AbstractControlGroup<?>>();

    private Map<Class<?>, ControlGroupProvider<?>> controlGroupProviders = new HashMap<Class<?>, ControlGroupProvider<?>>();

    @SuppressWarnings("rawtypes")
    private final Map<Class<?>, Class<? extends AbstractControlGroup>> typesControlGroups = new HashMap<Class<?>, Class<? extends AbstractControlGroup>>();

    private List<ObjectProperties> objectProperties;
    private CrudifierEntitySettings entitySettings;
    private Map<Class<?>, IObjectRenderer<?>> renderers;

    public ListControlGroups(String id, IModel<T> model, CrudifierEntitySettings entitySettings,
            Map<Class<?>, IObjectRenderer<?>> renderers) {
        super(id, model);

        typesControlGroups.put(Date.class, DateControlGroup.class);
        typesControlGroups.put(DateTime.class, JodaInstantControlGroup.class);
        typesControlGroups.put(Instant.class, JodaInstantControlGroup.class);
        typesControlGroups.put(String.class, TextFieldControlGroup.class);
        typesControlGroups.put(Integer.class, TextFieldControlGroup.class);
        typesControlGroups.put(int.class, TextFieldControlGroup.class);
        typesControlGroups.put(Long.class, TextFieldControlGroup.class);
        typesControlGroups.put(long.class, TextFieldControlGroup.class);
        typesControlGroups.put(Double.class, TextFieldControlGroup.class);
        typesControlGroups.put(double.class, TextFieldControlGroup.class);
        typesControlGroups.put(BigDecimal.class, TextFieldControlGroup.class);
        typesControlGroups.put(BigInteger.class, TextFieldControlGroup.class);
        typesControlGroups.put(Boolean.class, CheckboxControlGroup.class);
        typesControlGroups.put(boolean.class, CheckboxControlGroup.class);
        typesControlGroups.put(Set.class, CollectionControlGroup.class);

        objectProperties = new ArrayList<ObjectProperties>();
        this.entitySettings = entitySettings;
        this.renderers = renderers;
    }

    private Set<String> getPropertiesByOrder(Class<?> modelClass) {
        Set<String> properties = new LinkedHashSet<String>();

        for (String property : entitySettings.getOrderOfFields()) {
            if (!entitySettings.getHiddenFields().contains(property))
                properties.add(property);
        }
        for (PropertyDescriptor descriptor : PropertyUtils.getPropertyDescriptors(modelClass)) {
            if (!entitySettings.getHiddenFields().contains(descriptor.getName())
                    && !properties.contains(descriptor.getName()) && !descriptor.getName().equals("class"))
                properties.add(descriptor.getName());
        }

        return properties;
    }

    protected abstract EntityProvider<?> getEntityProvider(String name);

    @Override
    protected void onInitialize() {
        super.onInitialize();

        Class<?> modelClass = getModel().getObject().getClass();

        Set<String> properties = getPropertiesByOrder(modelClass);

        Validator validator = HibernateValidatorProperty.validatorFactory.getValidator();
        BeanDescriptor constraintDescriptors = validator.getConstraintsForClass(modelClass);
        for (String property : properties) {
            PropertyDescriptor descriptor;
            try {
                descriptor = PropertyUtils.getPropertyDescriptor(getModel().getObject(), property);
            } catch (Exception e) {
                throw new RuntimeException("error getting property " + property, e);
            }

            boolean required = false;

            ElementDescriptor constraintDescriptor = constraintDescriptors
                    .getConstraintsForProperty(descriptor.getName());
            if (constraintDescriptor != null) {
                Set<ConstraintDescriptor<?>> constraintsSet = constraintDescriptor.getConstraintDescriptors();
                for (ConstraintDescriptor<?> constraint : constraintsSet) {
                    if (constraint.getAnnotation() instanceof NotNull
                            || constraint.getAnnotation() instanceof NotEmpty
                            || constraint.getAnnotation() instanceof NotBlank)
                        required = true;
                }
            }

            objectProperties.add(new ObjectProperties(descriptor, required));
        }

        RepeatingView view = new RepeatingView("controlGroup");
        for (ObjectProperties objectProperty : objectProperties) {
            try {
                AbstractControlGroup<?> controlGroup;
                if (!controlGroupProviders.containsKey(objectProperty.type)) {
                    Constructor<?> constructor;
                    Class<? extends Panel> typesControlGroup = getControlGroupByType(objectProperty.type);
                    if (typesControlGroup == null) {
                        if (objectProperty.type.isEnum())
                            typesControlGroup = EnumControlGroup.class;
                        else
                            typesControlGroup = ObjectChoiceControlGroup.class;
                    }

                    constructor = typesControlGroup.getConstructor(String.class, IModel.class);

                    controlGroup = (AbstractControlGroup<?>) constructor.newInstance(view.newChildId(),
                            new PropertyModel<Object>(ListControlGroups.this.getModel(), objectProperty.name));
                    controlGroup.init(objectProperty.name, getResourceBase(), objectProperty.required,
                            objectProperty.type, entitySettings);
                    controlGroup.setEnabled(objectProperty.enabled);

                    if (typesControlGroup == ObjectChoiceControlGroup.class) {
                        IObjectRenderer<?> renderer = renderers.get(objectProperty.type);
                        if (renderer == null) {
                            renderer = new IObjectRenderer<Object>() {
                                private static final long serialVersionUID = -6171655578529011405L;

                                public String render(Object object) {
                                    return object.toString();
                                }
                            };
                        }
                        ((ObjectChoiceControlGroup<?>) controlGroup)
                                .setConfiguration(getEntityProvider(objectProperty.name), renderer);
                    } else if (typesControlGroup == CollectionControlGroup.class) {
                        ((CollectionControlGroup<?>) controlGroup)
                                .setConfiguration(getEntityProvider(objectProperty.name), renderers);
                    }

                } else {
                    controlGroup = controlGroupProviders.get(objectProperty.type)
                            .createControlGroup(view.newChildId(),
                                    new PropertyModel<Object>(ListControlGroups.this.getModel(),
                                            objectProperty.name),
                                    objectProperty.name, getResourceBase(), objectProperty.required,
                                    objectProperty.type, entitySettings);
                }
                view.add(controlGroup);

                fieldComponents.put(objectProperty.name, controlGroup);
            } catch (SecurityException e) {
                throw new RuntimeException(e);
            } catch (NoSuchMethodException e) {
                throw new RuntimeException(e);
            } catch (IllegalArgumentException e) {
                throw new RuntimeException(e);
            } catch (InstantiationException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            } catch (InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        }

        add(view);
    }

    @SuppressWarnings("unchecked")
    public IModel<T> getModel() {
        return (IModel<T>) getDefaultModel();
    }

    public Component getResourceBase() {
        return this;
    }

    public Map<String, AbstractControlGroup<?>> getFieldsControlGroup() {
        return Collections.unmodifiableMap(fieldComponents);
    }

    @SuppressWarnings("rawtypes")
    private Class<? extends AbstractControlGroup> getControlGroupByType(Class<?> type) {
        for (Class<?> mapType : typesControlGroups.keySet()) {
            if (type.isAssignableFrom(mapType))
                return typesControlGroups.get(mapType);
        }
        return null;
    }

    private static final class ObjectProperties implements Serializable {
        private static final long serialVersionUID = 1747577998897955928L;
        private String name;
        private boolean enabled;
        private Class<?> type;
        private boolean required;

        public ObjectProperties(PropertyDescriptor descriptor, boolean required) {
            this.name = descriptor.getName();
            this.enabled = descriptor.getWriteMethod() != null;
            this.type = descriptor.getPropertyType();
            this.required = required;
        }
    }

    @SuppressWarnings("rawtypes")
    public Map<Class<?>, Class<? extends AbstractControlGroup>> getControlGroupsTypesMap() {
        return typesControlGroups;
    }

    public Map<Class<?>, ControlGroupProvider<? extends AbstractControlGroup<?>>> getControlGroupProviders() {
        return this.controlGroupProviders;
    }
}