Java tutorial
/** * 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; } }