Java tutorial
/** * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program 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 General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package richtercloud.reflection.form.builder.jpa.fieldhandler; import java.awt.Component; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Type; import java.util.List; import java.util.Map; import javax.persistence.ElementCollection; import javax.persistence.Embeddable; import javax.persistence.EntityManager; import javax.persistence.Id; import javax.persistence.ManyToMany; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import javax.persistence.OneToOne; import javax.swing.JComponent; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; import richtercloud.reflection.form.builder.ComponentHandler; import richtercloud.reflection.form.builder.FieldRetriever; import richtercloud.reflection.form.builder.components.AmountMoneyCurrencyStorage; import richtercloud.reflection.form.builder.components.AmountMoneyExchangeRateRetriever; import richtercloud.reflection.form.builder.components.AmountMoneyUsageStatisticsStorage; import richtercloud.reflection.form.builder.fieldhandler.AmountMoneyFieldHandler; import richtercloud.reflection.form.builder.fieldhandler.FieldHandler; import richtercloud.reflection.form.builder.fieldhandler.FieldHandlingException; import richtercloud.reflection.form.builder.fieldhandler.FieldUpdateEvent; import richtercloud.reflection.form.builder.fieldhandler.FieldUpdateListener; import richtercloud.reflection.form.builder.fieldhandler.MappingFieldHandler; import richtercloud.reflection.form.builder.fieldhandler.factory.AmountMoneyMappingFieldHandlerFactory; import richtercloud.reflection.form.builder.jpa.IdGenerator; import richtercloud.reflection.form.builder.jpa.JPAReflectionFormBuilder; import richtercloud.reflection.form.builder.jpa.fieldhandler.factory.JPAAmountMoneyMappingFieldHandlerFactory; import richtercloud.reflection.form.builder.jpa.panels.LongIdPanel; import richtercloud.reflection.form.builder.jpa.typehandler.ElementCollectionTypeHandler; import richtercloud.reflection.form.builder.jpa.typehandler.ToManyTypeHandler; import richtercloud.reflection.form.builder.jpa.typehandler.ToOneTypeHandler; import richtercloud.reflection.form.builder.jpa.typehandler.factory.JPAAmountMoneyMappingTypeHandlerFactory; import richtercloud.reflection.form.builder.message.MessageHandler; import richtercloud.reflection.form.builder.panels.NumberPanel; import richtercloud.reflection.form.builder.panels.NumberPanelUpdateEvent; import richtercloud.reflection.form.builder.panels.NumberPanelUpdateListener; /** * Handles entities and embeddables differently based on two type component-{@link FieldHandler} mappings. * * @author richter */ public class JPAMappingFieldHandler<T, E extends FieldUpdateEvent<T>> extends MappingFieldHandler<T, E, JPAReflectionFormBuilder, Component> { private final static ComponentHandler<LongIdPanel> LONG_ID_PANEL_COMPONENT_RESETTER = new ComponentHandler<LongIdPanel>() { @Override public void reset(LongIdPanel component) { component.reset(); } }; private final ElementCollectionTypeHandler elementCollectionTypeHandler; private final Map<Type, FieldHandler<?, ?, ?, ?>> embeddableMapping; private final ToManyTypeHandler toManyTypeHandler; private final ToOneTypeHandler toOneTypeHandler; private final IdGenerator idGenerator; private final MessageHandler messageHandler; private final FieldRetriever fieldRetriever; public static JPAMappingFieldHandler create(EntityManager entityManager, int initialQueryLimit, MessageHandler messageHandler, FieldRetriever fieldRetriever, AmountMoneyUsageStatisticsStorage amountMoneyUsageStatisticsStorage, AmountMoneyCurrencyStorage amountMoneyCurrencyStorage, AmountMoneyExchangeRateRetriever amountMoneyConversionRateRetriever, IdGenerator idGenerator, String bidirectionalHelpDialogTitle) { JPAAmountMoneyMappingFieldHandlerFactory jPAAmountMoneyClassMappingFactory = new JPAAmountMoneyMappingFieldHandlerFactory( entityManager, initialQueryLimit, messageHandler, amountMoneyUsageStatisticsStorage, amountMoneyCurrencyStorage, amountMoneyConversionRateRetriever, bidirectionalHelpDialogTitle); AmountMoneyMappingFieldHandlerFactory amountMoneyClassMappingFactory = new AmountMoneyMappingFieldHandlerFactory( amountMoneyUsageStatisticsStorage, amountMoneyCurrencyStorage, amountMoneyConversionRateRetriever, messageHandler); JPAAmountMoneyMappingTypeHandlerFactory jPAAmountMoneyTypeHandlerMappingFactory = new JPAAmountMoneyMappingTypeHandlerFactory( entityManager, initialQueryLimit, messageHandler, bidirectionalHelpDialogTitle); AmountMoneyFieldHandler amountMoneyFieldHandler = new AmountMoneyFieldHandler( amountMoneyUsageStatisticsStorage, amountMoneyConversionRateRetriever, amountMoneyCurrencyStorage, messageHandler); ElementCollectionTypeHandler elementCollectionTypeHandler = new ElementCollectionTypeHandler( jPAAmountMoneyTypeHandlerMappingFactory.generateTypeHandlerMapping(), jPAAmountMoneyTypeHandlerMappingFactory.generateTypeHandlerMapping(), messageHandler, amountMoneyFieldHandler); ToManyTypeHandler toManyTypeHandler = new ToManyTypeHandler(entityManager, messageHandler, jPAAmountMoneyTypeHandlerMappingFactory.generateTypeHandlerMapping(), jPAAmountMoneyTypeHandlerMappingFactory.generateTypeHandlerMapping(), bidirectionalHelpDialogTitle); ToOneTypeHandler toOneTypeHandler = new ToOneTypeHandler(entityManager, messageHandler, bidirectionalHelpDialogTitle); return new JPAMappingFieldHandler(jPAAmountMoneyClassMappingFactory.generateClassMapping(), amountMoneyClassMappingFactory.generateClassMapping(), jPAAmountMoneyClassMappingFactory.generatePrimitiveMapping(), elementCollectionTypeHandler, toManyTypeHandler, toOneTypeHandler, idGenerator, messageHandler, fieldRetriever); } public JPAMappingFieldHandler(Map<Type, FieldHandler<?, ?, ?, ?>> classMapping, Map<Type, FieldHandler<?, ?, ?, ?>> embeddableMapping, Map<Class<?>, FieldHandler<?, ?, ?, ?>> primitiveMapping, ElementCollectionTypeHandler elementCollectionTypeHandler, ToManyTypeHandler oneToManyTypeHandler, ToOneTypeHandler toOneTypeHandler, IdGenerator idGenerator, MessageHandler messageHandler, FieldRetriever fieldRetriever) { super(classMapping, primitiveMapping); this.elementCollectionTypeHandler = elementCollectionTypeHandler; this.embeddableMapping = embeddableMapping; this.toManyTypeHandler = oneToManyTypeHandler; this.toOneTypeHandler = toOneTypeHandler; this.idGenerator = idGenerator; this.messageHandler = messageHandler; this.fieldRetriever = fieldRetriever; } public MessageHandler getMessageHandler() { return messageHandler; } @Override protected Pair<JComponent, ComponentHandler<?>> handle0(Field field, Object instance, final FieldUpdateListener updateListener, JPAReflectionFormBuilder reflectionFormBuilder) throws IllegalArgumentException, IllegalAccessException, FieldHandlingException, InvocationTargetException, NoSuchMethodException, InstantiationException { if (field == null) { throw new IllegalArgumentException("fieldClass mustn't be null"); } Type fieldType = field.getGenericType(); Object fieldValue = field.get(instance); String fieldName = field.getName(); Class<?> fieldDeclaringClass = field.getDeclaringClass(); if (field.getAnnotation(Id.class) != null) { if (!(fieldType instanceof Class)) { throw new IllegalArgumentException("@Id annotated field has to be a class"); } Class<?> fieldTypeClass = (Class<?>) fieldType; if (fieldTypeClass.equals(Long.class)) { Long fieldValueCast = (Long) field.get(instance); NumberPanel<Long> retValue; if (fieldType.equals(Long.class)) { retValue = new LongIdPanel(this.idGenerator, instance, fieldValueCast, //initialValue messageHandler, fieldRetriever); } else { throw new IllegalArgumentException( String.format("field type %s is not supported", fieldValue.getClass())); } retValue.addUpdateListener(new NumberPanelUpdateListener<Long>() { @Override public void onUpdate(NumberPanelUpdateEvent<Long> event) { updateListener.onUpdate(new FieldUpdateEvent<>(event.getNewValue())); } }); return new ImmutablePair<JComponent, ComponentHandler<?>>(retValue, LONG_ID_PANEL_COMPONENT_RESETTER); } else { throw new IllegalArgumentException( String.format("@Id annotated field type %s not supported", field.getGenericType())); } } if (field.getAnnotation(ElementCollection.class) != null) { //can't be handled differently because otherwise a QueryPanel would //be tried to be used and IllegalArgumentException thrown at //initialization if (fieldValue != null && !(fieldValue instanceof List)) { throw new IllegalArgumentException("field values isn't an instance of List"); } Pair<JComponent, ComponentHandler<?>> retValue = this.elementCollectionTypeHandler.handle( field.getGenericType(), (List<Object>) fieldValue, fieldName, fieldDeclaringClass, updateListener, reflectionFormBuilder); return retValue; } if (field.getAnnotation(OneToMany.class) != null || field.getAnnotation(ManyToMany.class) != null) { Pair<JComponent, ComponentHandler<?>> retValue = this.toManyTypeHandler.handle(field.getGenericType(), (List<Object>) fieldValue, fieldName, fieldDeclaringClass, updateListener, reflectionFormBuilder); return retValue; } if (field.getAnnotation(OneToOne.class) != null || field.getAnnotation(ManyToOne.class) != null) { Pair<JComponent, ComponentHandler<?>> retValue = this.toOneTypeHandler.handle(field.getGenericType(), fieldValue, fieldName, fieldDeclaringClass, updateListener, reflectionFormBuilder); return retValue; } if (field.getType() instanceof Class) { Class<?> fieldTypeClass = field.getType(); if (fieldTypeClass.getAnnotation(Embeddable.class) != null) { FieldHandler fieldHandler = embeddableMapping.get(fieldType); JComponent retValue = fieldHandler.handle(field, instance, updateListener, reflectionFormBuilder); return new ImmutablePair<JComponent, ComponentHandler<?>>(retValue, fieldHandler); } } return super.handle0(field, instance, updateListener, reflectionFormBuilder); } }