| /** |
| * Copyright (c) 2011, 2015 - Lunifera GmbH (Gross Enzersdorf, Austria), Loetz GmbH&Co.KG (69115 Heidelberg, Germany) |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Florian Pirchner - Initial implementation |
| */ |
| package org.eclipse.osbp.runtime.common.annotations; |
| |
| import java.beans.BeanInfo; |
| import java.beans.IntrospectionException; |
| import java.beans.Introspector; |
| import java.beans.PropertyChangeListener; |
| import java.beans.PropertyChangeSupport; |
| import java.beans.PropertyDescriptor; |
| import java.lang.reflect.Field; |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.Date; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.apache.commons.lang.reflect.MethodUtils; |
| import org.apache.commons.lang3.ClassUtils; |
| import org.eclipse.osbp.runtime.common.historized.UUIDHist; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| /** |
| * The Class DtoUtils. |
| */ |
| public class DtoUtils { |
| |
| /** The Constant LOGGER. */ |
| private static final Logger LOGGER = LoggerFactory.getLogger(DtoUtils.class); |
| |
| /** The infos. */ |
| private static Map<Class<?>, Info> INFOS = Collections.synchronizedMap(new HashMap<Class<?>, DtoUtils.Info>()); |
| |
| /** |
| * Returns the dispose field. Field annotated with {@link Dispose}. |
| * |
| * @param clazz |
| * the clazz |
| * @return the dispose field |
| */ |
| public static Field getDisposeField(Class<?> clazz) { |
| Info info = getInfo(clazz); |
| return info.getDisposeField(); |
| } |
| |
| /** |
| * Returns the dispose field. Field annotated with {@link Dirty}. |
| * |
| * @param clazz |
| * the clazz |
| * @return the dirty field |
| */ |
| public static Field getDirtyField(Class<?> clazz) { |
| Info info = getInfo(clazz); |
| return info.getDirtyField(); |
| } |
| |
| /** |
| * Returns the domain key field. Field annotated with {@link DomainKey}. |
| * |
| * @param clazz |
| * the clazz |
| * @return the domain key field |
| */ |
| public static Field getDomainKeyField(Class<?> clazz) { |
| Info info = getInfo(clazz); |
| return info.getDomainKeyField(); |
| } |
| |
| /** |
| * Returns the id field. Field annotated with {@link Id}. |
| * |
| * @param clazz |
| * the clazz |
| * @return the id field |
| */ |
| public static Field getIdField(Class<?> clazz) { |
| Info info = getInfo(clazz); |
| return info.getIdField(); |
| } |
| |
| /** |
| * Returns the idValidFrom field for historized objects. Field annotated |
| * with {@link IdValidFrom}. |
| * |
| * @param clazz |
| * the clazz |
| * @return the idValidFrom field |
| */ |
| public static Field getIdValidFromField(Class<?> clazz) { |
| Info info = getInfo(clazz); |
| return info.getIdValidFromField(); |
| } |
| |
| public static boolean isUUID(Class<?> clazz) { |
| Info info = getInfo(clazz); |
| Field field = info.getIdField(); |
| if (field.getType() == String.class) { |
| return true; |
| } |
| return false; |
| } |
| |
| public static Object cloneDto(Object dto) { |
| Object cloneDto = null; |
| try { |
| cloneDto = dto.getClass().newInstance(); |
| |
| Map<String, Field> fields = getAllFieldsAsMap(dto.getClass()); |
| BeanInfo beanInfo = Introspector.getBeanInfo(dto.getClass()); |
| for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors()) { |
| Field field = fields.get(pd.getName()); |
| if (field == null || field.isAnnotationPresent(Dispose.class)) { |
| continue; |
| } |
| |
| if (pd.getPropertyType().isAssignableFrom(List.class)) { |
| continue; |
| } |
| |
| pd.getWriteMethod().invoke(cloneDto, pd.getReadMethod().invoke(dto)); |
| } |
| |
| } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException |
| | SecurityException | IntrospectionException e) { |
| e.printStackTrace(); |
| } |
| return cloneDto; |
| } |
| |
| |
| /** |
| * Creates a copy of the given dto and sets a new historized uuid version. |
| * @param dto |
| * @return |
| */ |
| public static <T> T newHistorizedVersionCopy(T dto){ |
| @SuppressWarnings("unchecked") |
| T copy = (T) copyDto(dto); |
| UUIDHist id = (UUIDHist) getIdValue(copy); |
| setIdValue(copy, id.newVersion()); |
| return copy; |
| } |
| |
| |
| public static Object copyDto(Object dto) { |
| Object copyDto = null; |
| try { |
| copyDto = dto.getClass().newInstance(); |
| |
| Map<String, Field> fields = getAllFieldsAsMap(dto.getClass()); |
| BeanInfo beanInfo = Introspector.getBeanInfo(dto.getClass()); |
| for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors()) { |
| Field field = fields.get(pd.getName()); |
| if (field == null || field.isAnnotationPresent(Id.class) || field.isAnnotationPresent(Version.class) |
| || field.isAnnotationPresent(Dispose.class)) { |
| continue; |
| } |
| |
| if (pd.getPropertyType().isAssignableFrom(List.class)) { |
| continue; |
| } |
| |
| pd.getWriteMethod().invoke(copyDto, pd.getReadMethod().invoke(dto)); |
| } |
| |
| } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException |
| | SecurityException | IntrospectionException e) { |
| e.printStackTrace(); |
| } |
| return copyDto; |
| } |
| |
| public static void invokeSetOwner(Object obj, String setterName, Object ref) { |
| for (Method method : obj.getClass().getDeclaredMethods()) { |
| if (setterName.equals(method.getName())) { |
| try { |
| method.invoke(obj, ref); |
| } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { |
| e.printStackTrace(); |
| } |
| return; |
| } |
| } |
| } |
| |
| /** |
| * Gets the version field. Field annotated with {@link Version}. |
| * |
| * @param clazz |
| * the clazz |
| * @return the version field |
| */ |
| public static Field getVersionField(Class<?> clazz) { |
| Info info = getInfo(clazz); |
| return info.getVersionField(); |
| } |
| |
| /** |
| * Returns the id field. Field annotated with {@link Id}. |
| * |
| * @param dto |
| * the dto |
| * @return the id field |
| */ |
| public static Object getIdValue(Object dto) { |
| Info info = getInfo(dto.getClass()); |
| Field f = info.getIdField(); |
| f.setAccessible(true); |
| try { |
| return f.get(dto); |
| } catch (IllegalArgumentException | IllegalAccessException e) { |
| throw new IllegalStateException(e); |
| } |
| } |
| |
| public static void setIdValue(Object dto, Object idValue) { |
| Info info = getInfo(dto.getClass()); |
| Field f = info.getIdField(); |
| f.setAccessible(true); |
| try { |
| f.set(dto, idValue); |
| } catch (IllegalArgumentException | IllegalAccessException e) { |
| throw new IllegalStateException(e); |
| } |
| } |
| |
| public static void setVersionValue(Object dto, Object versionValue) { |
| Info info = getInfo(dto.getClass()); |
| Field f = info.getVersionField(); |
| f.setAccessible(true); |
| try { |
| f.set(dto, versionValue); |
| } catch (IllegalArgumentException | IllegalAccessException e) { |
| throw new IllegalStateException(e); |
| } |
| } |
| |
| public static void setCreateUser(Object dto, String user) { |
| Info info = getInfo(dto.getClass()); |
| Field f = info.getCreateByField(); |
| f.setAccessible(true); |
| try { |
| f.set(dto, user); |
| } catch (IllegalArgumentException | IllegalAccessException e) { |
| throw new IllegalStateException(e); |
| } |
| } |
| |
| public static void setUpdateUser(Object dto, String user) { |
| Info info = getInfo(dto.getClass()); |
| Field f = info.getUpdateByField(); |
| f.setAccessible(true); |
| try { |
| f.set(dto, user); |
| } catch (IllegalArgumentException | IllegalAccessException e) { |
| throw new IllegalStateException(e); |
| } |
| } |
| |
| public static void setCreateAt(Object dto, Date date) { |
| Info info = getInfo(dto.getClass()); |
| Field f = info.getCreateAtField(); |
| f.setAccessible(true); |
| try { |
| f.set(dto, date); |
| } catch (IllegalArgumentException | IllegalAccessException e) { |
| throw new IllegalStateException(e); |
| } |
| } |
| |
| public static void setUpdateAt(Object dto, Date date) { |
| Info info = getInfo(dto.getClass()); |
| Field f = info.getUpdateAtField(); |
| f.setAccessible(true); |
| try { |
| f.set(dto, date); |
| } catch (IllegalArgumentException | IllegalAccessException e) { |
| throw new IllegalStateException(e); |
| } |
| } |
| |
| public static String getCreateUser(Object dto) { |
| Info info = getInfo(dto.getClass()); |
| Field f = info.getCreateByField(); |
| f.setAccessible(true); |
| try { |
| return (String) f.get(dto); |
| } catch (IllegalArgumentException | IllegalAccessException e) { |
| throw new IllegalStateException(e); |
| } |
| } |
| |
| public static String getUpdateUser(Object dto) { |
| Info info = getInfo(dto.getClass()); |
| Field f = info.getUpdateByField(); |
| f.setAccessible(true); |
| try { |
| return (String) f.get(dto); |
| } catch (IllegalArgumentException | IllegalAccessException e) { |
| throw new IllegalStateException(e); |
| } |
| } |
| |
| public static Date getCreateAt(Object dto) { |
| Info info = getInfo(dto.getClass()); |
| Field f = info.getCreateAtField(); |
| f.setAccessible(true); |
| try { |
| return (Date) f.get(dto); |
| } catch (IllegalArgumentException | IllegalAccessException e) { |
| throw new IllegalStateException(e); |
| } |
| } |
| |
| public static Date getUpdateAt(Object dto) { |
| Info info = getInfo(dto.getClass()); |
| Field f = info.getUpdateAtField(); |
| f.setAccessible(true); |
| try { |
| return (Date) f.get(dto); |
| } catch (IllegalArgumentException | IllegalAccessException e) { |
| throw new IllegalStateException(e); |
| } |
| } |
| |
| public static List<Field> getAllFields(Class<?> clazz) { |
| if (clazz == null) { |
| return null; |
| } |
| |
| List<Field> result = new ArrayList<>(); |
| try { |
| result.addAll(Arrays.asList(clazz.getDeclaredFields())); |
| } catch (SecurityException e) { |
| LOGGER.warn("{}", e); |
| } |
| |
| Class<?> superClass = clazz.getSuperclass(); |
| if (superClass != null) { |
| List<Field> temp = getAllFields(superClass); |
| result.addAll(temp); |
| } |
| return result; |
| } |
| |
| public static Map<String, Field> getAllFieldsAsMap(Class<?> clazz) { |
| if (clazz == null) { |
| return null; |
| } |
| |
| Map<String, Field> result = new HashMap<>(); |
| try { |
| for (Field field : clazz.getDeclaredFields()) { |
| result.put(field.getName(), field); |
| } |
| } catch (SecurityException e) { |
| LOGGER.warn("{}", e); |
| } |
| |
| Class<?> superClass = clazz.getSuperclass(); |
| if (superClass != null) { |
| Map<String, Field> temp = getAllFieldsAsMap(superClass); |
| result.putAll(temp); |
| } |
| return result; |
| } |
| |
| /** |
| * Returns the field value. |
| * |
| * @param instance |
| * the instance |
| * @param idProperty |
| * the id property |
| * @return the value |
| */ |
| public static Object getValue(Object instance, String idProperty) { |
| try { |
| BeanInfo beanInfo = Introspector.getBeanInfo(instance.getClass()); |
| for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors()) { |
| if (pd.getName().equals(idProperty)) { |
| Method idMethod = pd.getReadMethod(); |
| return idMethod.invoke(instance); |
| } |
| } |
| } catch (Exception e) { |
| LOGGER.error("{}", e); |
| } |
| return null; |
| } |
| |
| /** |
| * Sets the field value. |
| * |
| * @param instance |
| * the instance |
| * @param idProperty |
| * the id property |
| * @param value |
| * the value |
| */ |
| public static void setValue(Object dto, String idProperty, Object value) { |
| try { |
| BeanInfo beanInfo = Introspector.getBeanInfo(dto.getClass()); |
| for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors()) { |
| if (pd.getName().equals(idProperty) |
| && (value == null || ClassUtils.isAssignable(pd.getPropertyType(), value.getClass(), true))) { |
| pd.getWriteMethod().invoke(dto, value); |
| break; |
| } |
| } |
| } catch (IntrospectionException | IllegalAccessException | IllegalArgumentException |
| | InvocationTargetException e) { |
| LOGGER.error("{}", e); |
| } |
| } |
| |
| /** |
| * Returns the domain description field. Field annotated with |
| * #DomainDescription. |
| * |
| * @param clazz |
| * the clazz |
| * @return the domain description field |
| */ |
| public static Field getDomainDescriptionField(Class<?> clazz) { |
| Info info = getInfo(clazz); |
| return info.getDomainDescriptionField(); |
| } |
| |
| /** |
| * Returns the dispose field. Field annotated with {@link Dirty}. |
| * |
| * @param clazz |
| * the clazz |
| * @return the dirty getter |
| */ |
| public static Method getDirtyGetter(Class<?> clazz) { |
| Info info = getInfo(clazz); |
| return info.getDirtyGetter(); |
| } |
| |
| /** |
| * Returns the dispose field. Field annotated with {@link Dirty}. |
| * |
| * @param clazz |
| * the clazz |
| * @return the dirty setter |
| */ |
| public static Method getDirtySetter(Class<?> clazz) { |
| Info info = getInfo(clazz); |
| return info.getDirtySetter(); |
| } |
| |
| /** |
| * Returns the dispose method. Method annotated with {@link Dispose}. |
| * |
| * @param clazz |
| * the clazz |
| * @return the dispose method |
| */ |
| public static Method getDisposeMethod(Class<?> clazz) { |
| Info info = getInfo(clazz); |
| return info.getDisposeMethod(); |
| } |
| |
| /** |
| * Returns true, if the given field is a dispose field. |
| * |
| * @param clazz |
| * the clazz |
| * @param fieldName |
| * the field name |
| * @return true, if is dispose field |
| */ |
| public static boolean isDisposeField(Class<?> clazz, String fieldName) { |
| Info info = getInfo(clazz); |
| return info.getDisposeField() != null ? info.getDisposeField().getName().equals(fieldName) : false; |
| } |
| |
| /** |
| * Returns true, if the given field is a id field. |
| * |
| * @param clazz |
| * the clazz |
| * @param fieldName |
| * the field name |
| * @return true, if is id field |
| */ |
| public static boolean isIdField(Class<?> clazz, String fieldName) { |
| Info info = getInfo(clazz); |
| return info.getIdField() != null ? info.getIdField().getName().equals(fieldName) : false; |
| } |
| |
| /** |
| * Returns true, if the given field is a domainkey field. |
| * |
| * @param clazz |
| * the clazz |
| * @param fieldName |
| * the field name |
| * @return true, if is domainkey field |
| */ |
| public static boolean isDomainkeyField(Class<?> clazz, String fieldName) { |
| Field dkField = getDomainKeyField(clazz); |
| return dkField != null && dkField.getName().equals(fieldName); |
| } |
| |
| /** |
| * Returns true, if the given field is a version field. |
| * |
| * @param clazz |
| * the clazz |
| * @param fieldName |
| * the field name |
| * @return true, if is version field |
| */ |
| public static boolean isVersionField(Class<?> clazz, String fieldName) { |
| Info info = getInfo(clazz); |
| return info.getVersionField() != null ? info.getVersionField().getName().equals(fieldName) : false; |
| } |
| |
| /** |
| * Returns true, if the given field is a dirty field. Dirty fields indicate |
| * that the dto is dirty. |
| * |
| * @param clazz |
| * the clazz |
| * @param fieldName |
| * the field name |
| * @return true, if is dirty field |
| */ |
| public static boolean isDirtyField(Class<?> clazz, String fieldName) { |
| Info info = getInfo(clazz); |
| return info.getDirtyField() != null ? info.getDirtyField().getName().equals(fieldName) : false; |
| } |
| |
| /** |
| * Returns true, if the given method is a dispose method. |
| * |
| * @param clazz |
| * the clazz |
| * @param methodName |
| * the method name |
| * @return true, if is dispose method |
| */ |
| public static boolean isDisposeMethod(Class<?> clazz, String methodName) { |
| Info info = getInfo(clazz); |
| return info.getDisposeField() != null ? info.getDisposeMethod().getName().equals(methodName) : false; |
| } |
| |
| /** |
| * Tries to invoke the dispose method. |
| * |
| * @param obj |
| * the obj |
| * @return true, if the method could be invoked. False otherwise. |
| */ |
| public static boolean invokeDisposeMethod(Object obj) { |
| Info info = getInfo(obj.getClass()); |
| if (info != null && info.getDisposeMethod() != null) { |
| try { |
| info.getDisposeMethod().invoke(obj, new Object[0]); |
| } catch (IllegalAccessException e) { |
| return false; |
| } catch (IllegalArgumentException e) { |
| return false; |
| } catch (InvocationTargetException e) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| /** |
| * Tries to invoke the setDirty method. |
| * |
| * @param obj |
| * the obj |
| * @param value |
| * the value |
| * @return true, if the method could be invoked. False otherwise. |
| */ |
| public static boolean invokeDirtySetter(Object obj, boolean value) { |
| Info info = getInfo(obj.getClass()); |
| if (info.getDirtySetter() != null) { |
| try { |
| info.getDirtySetter().invoke(obj, new Object[] { value }); |
| } catch (IllegalAccessException e) { |
| return false; |
| } catch (IllegalArgumentException e) { |
| return false; |
| } catch (InvocationTargetException e) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| /** |
| * Tries to invoke the dirty getter. If there is no dirty getter available, |
| * the method throws an {@link IllegalAccessException}. |
| * |
| * @param obj |
| * the obj |
| * @return true, if is dirty |
| * @throws IllegalAccessException |
| * the illegal access exception |
| */ |
| public static boolean isDirty(Object obj) throws IllegalAccessException { |
| return invokeDirtyGetter(obj); |
| } |
| |
| /** |
| * Tries to invoke the isDirty method. |
| * |
| * @param obj |
| * the obj |
| * @return true, if the method could be invoked. False otherwise. |
| * @throws IllegalAccessException |
| * the illegal access exception |
| */ |
| public static boolean invokeDirtyGetter(Object obj) throws IllegalAccessException { |
| Info info = getInfo(obj.getClass()); |
| if (info.getDirtySetter() != null) { |
| try { |
| return (Boolean) info.getDirtyGetter().invoke(obj, new Object[0]); |
| } catch (IllegalAccessException e) { |
| } catch (IllegalArgumentException e) { |
| } catch (InvocationTargetException e) { |
| } |
| } |
| throw new IllegalAccessException("Not a valid call"); |
| } |
| |
| /** |
| * Gets the owner domain references. |
| * |
| * @param clazz |
| * the clazz |
| * @return the owner domain references |
| */ |
| public static List<Field> getOwnerDomainReferences(Class<?> clazz) { |
| Info info = getInfo(clazz); |
| return info.getOwnerDomainReferences(); |
| } |
| |
| /** |
| * Gets the member domain references. |
| * |
| * @param clazz |
| * the clazz |
| * @return the member domain references |
| */ |
| public static List<Field> getMemberDomainReferences(Class<?> clazz) { |
| Info info = getInfo(clazz); |
| return info.getMemberDomainReferences(); |
| } |
| |
| /** |
| * Returns the info for the given class. |
| * |
| * @param clazz |
| * the clazz |
| * @return the info |
| */ |
| protected static Info getInfo(Class<?> clazz) { |
| Info info = INFOS.get(clazz); |
| if (info == null) { |
| info = createInfo(clazz); |
| } |
| return info; |
| } |
| |
| /** |
| * Creates a new info. |
| * |
| * @param clazz |
| * the clazz |
| * @return info |
| */ |
| private static Info createInfo(Class<?> clazz) { |
| Info info = new Info(); |
| applyFieldInfo(clazz, info); |
| applyMethodInfo(clazz, info); |
| |
| INFOS.put(clazz, info); |
| |
| return info; |
| } |
| |
| /** |
| * Returns the adapter which has proper type from the given dto. Or |
| * <code>null</code> if no adapter is available. |
| * |
| * @param <A> |
| * the generic type |
| * @param type |
| * the type |
| * @param dto |
| * the dto |
| * @return the adapter |
| */ |
| @SuppressWarnings("unchecked") |
| public static <A> A getAdapter(Class<A> type, Object dto) { |
| if (type == null || dto == null) { |
| return null; |
| } |
| Info info = getInfo(dto.getClass()); |
| if (info.getPropertyChangeSupportField() == null) { |
| return null; |
| } |
| |
| try { |
| info.getPropertyChangeSupportField().setAccessible(true); |
| PropertyChangeSupport changeSupport = (PropertyChangeSupport) info.getPropertyChangeSupportField().get(dto); |
| if (changeSupport == null) { |
| return null; |
| } |
| |
| for (PropertyChangeListener listener : changeSupport.getPropertyChangeListeners()) { |
| if (type.isAssignableFrom(listener.getClass())) { |
| return (A) listener; |
| } |
| } |
| } catch (IllegalArgumentException e) { |
| LOGGER.error("{}", e); |
| } catch (IllegalAccessException e) { |
| LOGGER.error("{}", e); |
| } |
| return null; |
| } |
| |
| /** |
| * Registers the adapter as a property changed listener. |
| * |
| * @param adapter |
| * the adapter |
| * @param dto |
| * the dto |
| */ |
| public static void registerAdapter(PropertyChangeListener adapter, Object dto) { |
| if (adapter == null || dto == null) { |
| return; |
| } |
| |
| try { |
| MethodUtils.invokeMethod(dto, "addPropertyChangeListener", adapter); |
| } catch (SecurityException e) { |
| LOGGER.info("Observer for dirtyState handling could not be added for " + dto.getClass().getName()); |
| } catch (IllegalAccessException e) { |
| LOGGER.info("Observer for dirtyState handling could not be added for " + dto.getClass().getName()); |
| } catch (IllegalArgumentException e) { |
| LOGGER.info("Observer for dirtyState handling could not be added for " + dto.getClass().getName()); |
| } catch (InvocationTargetException e) { |
| LOGGER.info("Observer for dirtyState handling could not be added for " + dto.getClass().getName()); |
| } catch (NoSuchMethodException e) { |
| LOGGER.info("Observer for dirtyState handling could not be added for " + dto.getClass().getName()); |
| } |
| } |
| |
| /** |
| * Returns true, if the given id is a {@link UUIDHist}. |
| * |
| * @param id |
| * @return |
| */ |
| public static boolean isHistorizedId(Object id) { |
| return id instanceof UUIDHist; |
| } |
| |
| /** |
| * Unregisters the adapter as a property changed listener. |
| * |
| * @param adapter |
| * the adapter |
| * @param dto |
| * the dto |
| */ |
| public static void unregisterAdapter(PropertyChangeListener adapter, Object dto) { |
| if (adapter == null || dto == null) { |
| return; |
| } |
| |
| try { |
| MethodUtils.invokeMethod(dto, "removePropertyChangeListener", adapter); |
| } catch (SecurityException e) { |
| LOGGER.info("Observer for dirtyState handling could not be added for " + dto.getClass().getName()); |
| } catch (IllegalAccessException e) { |
| LOGGER.info("Observer for dirtyState handling could not be added for " + dto.getClass().getName()); |
| } catch (IllegalArgumentException e) { |
| LOGGER.info("Observer for dirtyState handling could not be added for " + dto.getClass().getName()); |
| } catch (InvocationTargetException e) { |
| LOGGER.info("Observer for dirtyState handling could not be added for " + dto.getClass().getName()); |
| } catch (NoSuchMethodException e) { |
| LOGGER.info("Observer for dirtyState handling could not be added for " + dto.getClass().getName()); |
| } |
| } |
| |
| public static List<String> getFieldNames(Class<?> clazz) { |
| List<String> fieldNames = new ArrayList<>(); |
| try { |
| for (Field field : clazz.getDeclaredFields()) { |
| fieldNames.add(field.getName()); |
| } |
| |
| Class<?> superClass = clazz.getSuperclass(); |
| if (superClass != null) { |
| fieldNames.addAll(getFieldNames(superClass)); |
| } |
| } catch (SecurityException e) { |
| LOGGER.error("{}", e); |
| } |
| return fieldNames; |
| } |
| |
| /** |
| * Applies all required field infos to the info object. |
| * |
| * @param clazz |
| * the clazz |
| * @param info |
| * the info |
| */ |
| private static void applyFieldInfo(Class<?> clazz, Info info) { |
| try { |
| |
| info.historized = clazz.isAnnotationPresent(HistorizedObject.class); |
| info.timedependent = clazz.isAnnotationPresent(TimedependentObject.class); |
| info.compoundHistKey = info.historized || info.timedependent; |
| |
| for (Field field : clazz.getDeclaredFields()) { |
| if (field.getAnnotation(Dispose.class) != null) { |
| info.disposeField = field; |
| } |
| if (field.getAnnotation(DomainKey.class) != null) { |
| info.domainKeyField = field; |
| } |
| if (field.getAnnotation(DomainDescription.class) != null) { |
| info.domainDescriptionField = field; |
| } |
| if (field.getAnnotation(Id.class) != null) { |
| info.idField = field; |
| if (info.compoundHistKey) { |
| Class<?> idType = field.getType(); |
| info.histIdInfo = toHistIdInfo(idType); |
| } |
| } |
| if (field.getAnnotation(Version.class) != null) { |
| info.versionField = field; |
| } |
| |
| if (field.getAnnotation(CreateAt.class) != null) { |
| info.createAtField = field; |
| } |
| if (field.getAnnotation(CreateBy.class) != null) { |
| info.createByField = field; |
| } |
| if (field.getAnnotation(UpdateAt.class) != null) { |
| info.updateAtField = field; |
| } |
| if (field.getAnnotation(UpdateBy.class) != null) { |
| info.updateByField = field; |
| } |
| |
| if (field.getAnnotation(DomainReference.class) != null) { |
| if (field.getType().isAssignableFrom(List.class)) { |
| info.memberDomainReferences.add(field); |
| } else { |
| info.ownerDomainReferences.add(field); |
| } |
| } |
| |
| if (field.getType() == PropertyChangeSupport.class) { |
| info.propertyChangeSupportField = field; |
| } |
| |
| if (field.getAnnotation(Dirty.class) != null) { |
| info.dirtyField = field; |
| |
| try { |
| BeanInfo beanInfo = Introspector.getBeanInfo(clazz); |
| for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors()) { |
| if (pd.getName().equals(info.dirtyField.getName())) { |
| info.dirtyPropertyDescriptor = pd; |
| break; |
| } |
| } |
| } catch (IntrospectionException e) { |
| LOGGER.error("{}", e); |
| } |
| } |
| if (info.disposeField != null && info.dirtyField != null && info.domainKeyField != null |
| && info.domainDescriptionField != null && info.idField != null) { |
| break; |
| } |
| } |
| |
| if (info.disposeField == null || info.domainKeyField == null || info.domainDescriptionField == null |
| || info.idField == null) { |
| Class<?> superClass = clazz.getSuperclass(); |
| if (superClass != null) { |
| applyFieldInfo(superClass, info); |
| } |
| } |
| } catch (SecurityException e) { |
| LOGGER.error("{}", e); |
| } |
| } |
| |
| /** |
| * Creates an info object for historized and timedependent objects. |
| * |
| * @param idType |
| * @return |
| */ |
| private static CompoundHistIdInfo toHistIdInfo(Class<?> idType) { |
| CompoundHistIdInfo histInfo = new CompoundHistIdInfo(); |
| for (Field field : idType.getDeclaredFields()) { |
| if (field.getAnnotation(HistUUID.class) != null) { |
| histInfo.rawUUIDField = field; |
| } else if (field.getAnnotation(HistValidFrom.class) != null) { |
| histInfo.rawVersionFromField = field; |
| } |
| if (histInfo.rawUUIDField != null && histInfo.rawVersionFromField != null) { |
| break; |
| } |
| } |
| |
| if (histInfo.rawUUIDField == null || histInfo.rawVersionFromField == null) { |
| throw new IllegalStateException( |
| "rawUUID and rawVersionFrom must be present for historized and timedependet objects"); |
| } |
| |
| return histInfo; |
| } |
| |
| /** |
| * Applies all required field infos to the info object. |
| * |
| * @param clazz |
| * the clazz |
| * @param info |
| * the info |
| */ |
| private static void applyMethodInfo(Class<?> clazz, Info info) { |
| try { |
| for (Method method : clazz.getDeclaredMethods()) { |
| if (method.getAnnotation(Dispose.class) != null) { |
| info.disposeMethod = method; |
| break; |
| } |
| } |
| |
| if (info.disposeMethod == null) { |
| Class<?> superClass = clazz.getSuperclass(); |
| if (superClass != null) { |
| applyMethodInfo(superClass, info); |
| } |
| } |
| } catch (SecurityException e) { |
| LOGGER.error("{}", e); |
| } |
| } |
| |
| /** |
| * Find field. |
| * |
| * @param clazz |
| * the clazz |
| * @param name |
| * the name |
| * @return the field |
| */ |
| protected static Field findField(Class<?> clazz, String name) { |
| try { |
| Field field = clazz.getDeclaredField(name); |
| return field; |
| } catch (NoSuchFieldException e) { |
| Class<?> superClass = clazz.getSuperclass(); |
| if (superClass != null) { |
| return findField(superClass, name); |
| } |
| } catch (SecurityException e) { |
| LOGGER.error("{}", e); |
| } |
| return null; |
| } |
| |
| /** |
| * The Class Info. |
| */ |
| private static class Info { |
| |
| public boolean historized; |
| public boolean timedependent; |
| |
| /** |
| * Is true, if {@link #historized} or {@link #timedependent} is true. |
| */ |
| public boolean compoundHistKey; |
| |
| public CompoundHistIdInfo histIdInfo; |
| |
| public Field updateByField; |
| |
| public Field updateAtField; |
| |
| public Field createByField; |
| |
| public Field createAtField; |
| |
| /** The property change support field. */ |
| private Field propertyChangeSupportField; |
| |
| /** The dispose field. */ |
| private Field disposeField; |
| |
| /** The dispose method. */ |
| private Method disposeMethod; |
| |
| /** The id field. */ |
| private Field idField; |
| |
| private Field idValidFromField; |
| |
| /** The dirty field. */ |
| private Field dirtyField; |
| |
| /** The dirty property descriptor. */ |
| private PropertyDescriptor dirtyPropertyDescriptor; |
| |
| /** The domain key field. */ |
| private Field domainKeyField; |
| |
| /** The domain description field. */ |
| private Field domainDescriptionField; |
| |
| /** The version field. */ |
| private Field versionField; |
| |
| /** |
| * The owner domain references = all 1 references of a oneToMany |
| * relationship. |
| */ |
| private List<Field> ownerDomainReferences = new ArrayList<>(); |
| |
| /** |
| * The member domain references = all n references of a oneToMany |
| * relationship. |
| */ |
| private List<Field> memberDomainReferences = new ArrayList<>(); |
| |
| /** |
| * Gets the dispose field. |
| * |
| * @return the dispose field |
| */ |
| public Field getDisposeField() { |
| return disposeField; |
| } |
| |
| /** |
| * Gets the owner domain references. |
| * |
| * @return the owner domain references |
| */ |
| public List<Field> getOwnerDomainReferences() { |
| return ownerDomainReferences; |
| } |
| |
| /** |
| * Gets the member domain references. |
| * |
| * @return the member domain references |
| */ |
| public List<Field> getMemberDomainReferences() { |
| return memberDomainReferences; |
| } |
| |
| /** |
| * Gets the version field. |
| * |
| * @return the version field |
| */ |
| public Field getVersionField() { |
| return versionField; |
| } |
| |
| /** |
| * Gets the dirty field. |
| * |
| * @return the dirty field |
| */ |
| public Field getDirtyField() { |
| return dirtyField; |
| } |
| |
| /** |
| * Gets the dirty getter. |
| * |
| * @return the dirty getter |
| */ |
| public Method getDirtyGetter() { |
| return dirtyPropertyDescriptor != null ? dirtyPropertyDescriptor.getReadMethod() : null; |
| } |
| |
| /** |
| * Gets the dirty setter. |
| * |
| * @return the dirty setter |
| */ |
| public Method getDirtySetter() { |
| return dirtyPropertyDescriptor != null ? dirtyPropertyDescriptor.getWriteMethod() : null; |
| } |
| |
| /** |
| * Gets the dispose method. |
| * |
| * @return the dispose method |
| */ |
| public Method getDisposeMethod() { |
| return disposeMethod; |
| } |
| |
| /** |
| * Gets the domain key field. |
| * |
| * @return the domain key field |
| */ |
| public Field getDomainKeyField() { |
| return domainKeyField; |
| } |
| |
| /** |
| * Gets the domain description field. |
| * |
| * @return the domain description field |
| */ |
| public Field getDomainDescriptionField() { |
| return domainDescriptionField; |
| } |
| |
| /** |
| * Gets the property change support field. |
| * |
| * @return the property change support field |
| */ |
| public Field getPropertyChangeSupportField() { |
| return propertyChangeSupportField; |
| } |
| |
| public Field getIdField() { |
| return idField; |
| } |
| |
| public Field getIdValidFromField() { |
| return idValidFromField; |
| } |
| |
| public Field getUpdateByField() { |
| return updateByField; |
| } |
| |
| public Field getUpdateAtField() { |
| return updateAtField; |
| } |
| |
| public Field getCreateByField() { |
| return createByField; |
| } |
| |
| public Field getCreateAtField() { |
| return createAtField; |
| } |
| } |
| |
| public static class CompoundHistIdInfo { |
| public Field rawUUIDField; |
| public Field rawVersionFromField; |
| |
| } |
| } |