From 403b15cae8d19f83c35c9490826d24b0bf5c2fa0 Mon Sep 17 00:00:00 2001 From: Lukasz Antoniak Date: Tue, 17 May 2011 23:14:01 +0200 Subject: [PATCH] HHH-5580 - Query refactoring --- .../configuration/AuditConfiguration.java | 7 ++ .../RevisionInfoConfiguration.java | 18 ++-- .../envers/reader/AuditReaderImpl.java | 19 +--- .../ModifiedEntityTypesReader.java | 41 +++++++++ .../tools/reflection/ReflectionTools.java | 88 ------------------- 5 files changed, 62 insertions(+), 111 deletions(-) create mode 100644 hibernate-envers/src/main/java/org/hibernate/envers/revisioninfo/ModifiedEntityTypesReader.java diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/AuditConfiguration.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/AuditConfiguration.java index 969efd46f2..00b1d20b8c 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/AuditConfiguration.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/AuditConfiguration.java @@ -30,6 +30,7 @@ import org.hibernate.annotations.common.reflection.ReflectionManager; import org.hibernate.cfg.Configuration; import org.hibernate.envers.entities.EntitiesConfigurations; import org.hibernate.envers.entities.PropertyData; +import org.hibernate.envers.revisioninfo.ModifiedEntityTypesReader; import org.hibernate.envers.revisioninfo.RevisionInfoNumberReader; import org.hibernate.envers.revisioninfo.RevisionInfoQueryCreator; import org.hibernate.envers.strategy.AuditStrategy; @@ -50,6 +51,7 @@ public class AuditConfiguration { private final EntitiesConfigurations entCfg; private final RevisionInfoQueryCreator revisionInfoQueryCreator; private final RevisionInfoNumberReader revisionInfoNumberReader; + private final ModifiedEntityTypesReader modifiedEntityTypesReader; public AuditEntitiesConfiguration getAuditEntCfg() { return auditEntCfg; @@ -75,6 +77,10 @@ public class AuditConfiguration { return revisionInfoNumberReader; } + public ModifiedEntityTypesReader getModifiedEntityTypesReader() { + return modifiedEntityTypesReader; + } + public AuditStrategy getAuditStrategy() { return auditStrategy; } @@ -90,6 +96,7 @@ public class AuditConfiguration { auditProcessManager = new AuditProcessManager(revInfoCfgResult.getRevisionInfoGenerator()); revisionInfoQueryCreator = revInfoCfgResult.getRevisionInfoQueryCreator(); revisionInfoNumberReader = revInfoCfgResult.getRevisionInfoNumberReader(); + modifiedEntityTypesReader = revInfoCfgResult.getModifiedEntityTypesReader(); auditStrategy = initializeAuditStrategy(revInfoCfgResult.getRevisionInfoClass(), revInfoCfgResult.getRevisionInfoTimestampData()); entCfg = new EntitiesConfigurator().configure(cfg, reflectionManager, globalCfg, auditEntCfg, auditStrategy, diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/RevisionInfoConfiguration.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/RevisionInfoConfiguration.java index 4282ad8464..1cf06be6b6 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/RevisionInfoConfiguration.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/RevisionInfoConfiguration.java @@ -309,8 +309,10 @@ public class RevisionInfoConfiguration { new RevisionInfoQueryCreator(revisionInfoEntityName, revisionInfoIdData.getName(), revisionInfoTimestampData.getName(), isTimestampAsDate()), generateRevisionInfoRelationMapping(), - new RevisionInfoNumberReader(revisionInfoClass, revisionInfoIdData), revisionInfoEntityName, - revisionInfoClass, revisionInfoTimestampData); + new RevisionInfoNumberReader(revisionInfoClass, revisionInfoIdData), + globalCfg.isTrackEntitiesChangedInRevisionEnabled() ? new ModifiedEntityTypesReader(revisionInfoClass, modifiedEntityTypesData) + : null, + revisionInfoEntityName, revisionInfoClass, revisionInfoTimestampData); } private boolean isTimestampAsDate() { @@ -325,20 +327,22 @@ class RevisionInfoConfigurationResult { private final RevisionInfoQueryCreator revisionInfoQueryCreator; private final Element revisionInfoRelationMapping; private final RevisionInfoNumberReader revisionInfoNumberReader; + private final ModifiedEntityTypesReader modifiedEntityTypesReader; private final String revisionInfoEntityName; private final Class revisionInfoClass; private final PropertyData revisionInfoTimestampData; RevisionInfoConfigurationResult(RevisionInfoGenerator revisionInfoGenerator, Document revisionInfoXmlMapping, RevisionInfoQueryCreator revisionInfoQueryCreator, - Element revisionInfoRelationMapping, - RevisionInfoNumberReader revisionInfoNumberReader, String revisionInfoEntityName, Class revisionInfoClass, - PropertyData revisionInfoTimestampData) { + Element revisionInfoRelationMapping, RevisionInfoNumberReader revisionInfoNumberReader, + ModifiedEntityTypesReader modifiedEntityTypesReader, String revisionInfoEntityName, + Class revisionInfoClass, PropertyData revisionInfoTimestampData) { this.revisionInfoGenerator = revisionInfoGenerator; this.revisionInfoXmlMapping = revisionInfoXmlMapping; this.revisionInfoQueryCreator = revisionInfoQueryCreator; this.revisionInfoRelationMapping = revisionInfoRelationMapping; this.revisionInfoNumberReader = revisionInfoNumberReader; + this.modifiedEntityTypesReader = modifiedEntityTypesReader; this.revisionInfoEntityName = revisionInfoEntityName; this.revisionInfoClass = revisionInfoClass; this.revisionInfoTimestampData = revisionInfoTimestampData; @@ -375,4 +379,8 @@ class RevisionInfoConfigurationResult { public PropertyData getRevisionInfoTimestampData() { return revisionInfoTimestampData; } + + public ModifiedEntityTypesReader getModifiedEntityTypesReader() { + return modifiedEntityTypesReader; + } } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/reader/AuditReaderImpl.java b/hibernate-envers/src/main/java/org/hibernate/envers/reader/AuditReaderImpl.java index 9733257205..538f036d00 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/reader/AuditReaderImpl.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/reader/AuditReaderImpl.java @@ -33,7 +33,6 @@ import org.hibernate.HibernateException; import org.hibernate.NonUniqueResultException; import org.hibernate.Session; import org.hibernate.engine.SessionImplementor; -import org.hibernate.envers.ModifiedEntityTypes; import org.hibernate.envers.RevisionType; import org.hibernate.envers.configuration.AuditConfiguration; import org.hibernate.envers.exception.AuditException; @@ -43,7 +42,6 @@ import org.hibernate.envers.query.AuditEntity; import org.hibernate.envers.query.AuditQueryCreator; import org.hibernate.envers.query.criteria.RevisionTypeAuditExpression; import org.hibernate.envers.synchronization.AuditProcess; -import org.hibernate.envers.tools.reflection.ReflectionTools; import org.hibernate.event.EventSource; import org.hibernate.proxy.HibernateProxy; @@ -294,22 +292,7 @@ public class AuditReaderImpl implements AuditReaderImplementor { Object revisionInfo = query.uniqueResult(); if (revisionInfo != null) { // If revision exists - if (modifiedEntityTypesProperty == null) { - // Only one field or method (getter) can be marked with @ModifiedEntityTypes annotation - modifiedEntityTypesProperty = (Member) ReflectionTools.getAnnotatedMembers(revisionInfo.getClass(), - ModifiedEntityTypes.class).toArray()[0]; - } - Set modifiedEntityTypes = (Set) ReflectionTools.getPropertyValue(modifiedEntityTypesProperty, revisionInfo); - Set result = new HashSet(modifiedEntityTypes.size()); - for (String entityClassName : modifiedEntityTypes) { - try { - result.add(Class.forName(entityClassName)); - } catch (ClassNotFoundException e) { - // This shall never happen - throw new RuntimeException(e); - } - } - return result; + return verCfg.getModifiedEntityTypesReader().getModifiedEntityTypes(revisionInfo); } return Collections.EMPTY_SET; } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/revisioninfo/ModifiedEntityTypesReader.java b/hibernate-envers/src/main/java/org/hibernate/envers/revisioninfo/ModifiedEntityTypesReader.java new file mode 100644 index 0000000000..858d13b53d --- /dev/null +++ b/hibernate-envers/src/main/java/org/hibernate/envers/revisioninfo/ModifiedEntityTypesReader.java @@ -0,0 +1,41 @@ +package org.hibernate.envers.revisioninfo; + +import org.hibernate.envers.entities.PropertyData; +import org.hibernate.envers.tools.reflection.ReflectionTools; +import org.hibernate.property.Getter; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +/** + * Returns modified entity types from a persisted revision info entity. + * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) + */ +public class ModifiedEntityTypesReader { + private final Getter modifiedEntityTypesGetter; + + public ModifiedEntityTypesReader(Class revisionInfoClass, PropertyData modifiedEntityTypesData) { + modifiedEntityTypesGetter = ReflectionTools.getGetter(revisionInfoClass, modifiedEntityTypesData); + } + + @SuppressWarnings({"unchecked"}) + public Set getModifiedEntityTypes(Object revisionEntity) { + // The default mechanism of tracking entity types that have been changed during each revision, stores + // fully qualified Java class names. + Set modifiedEntityClassNames = (Set) modifiedEntityTypesGetter.get(revisionEntity); + if (modifiedEntityClassNames != null) { + Set result = new HashSet(modifiedEntityClassNames.size()); + for (String entityClassName : modifiedEntityClassNames) { + try { + result.add(Thread.currentThread().getContextClassLoader().loadClass(entityClassName)); + } catch (ClassNotFoundException e) { + // This shall never happen + throw new RuntimeException(e); + } + } + return result; + } + return Collections.EMPTY_SET; + } +} diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/tools/reflection/ReflectionTools.java b/hibernate-envers/src/main/java/org/hibernate/envers/tools/reflection/ReflectionTools.java index 6c5d2e4b3d..3d41e39455 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/tools/reflection/ReflectionTools.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/tools/reflection/ReflectionTools.java @@ -45,7 +45,6 @@ import static org.hibernate.envers.tools.Pair.make; /** * @author Adam Warski (adam at warski dot org) - * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) */ public class ReflectionTools { private static final Map, Getter> getterCache = @@ -100,91 +99,4 @@ public class ReflectionTools { return value; } - - /** - * Returns property value by invoking getter method or directly retrieving field's reference. - * @param member Field or getter method representation. - * @param object Object instance. - * @return Property value. - */ - public static Object getPropertyValue(Member member, Object object) { - try { - if (member instanceof Field) { - Field field = (Field) member; - field.setAccessible(true); - return field.get(object); - } else if (member instanceof Method) { - Method method = (Method) member; - method.setAccessible(true); - return method.invoke(object); - } - } catch (Exception e) { - throw new RuntimeException(e); - } - throw new IllegalArgumentException("Unsupported member type: " + member + "."); - } - - /** - * @param clazz Class type. - * @param annotation Searched annotation. - * @return Set of annotated members ({@link Field} and/or {@link Method}). - */ - public static Set getAnnotatedMembers(Class clazz, Class annotation) { - try { - Set annotatedFields = new HashSet(); - Set annotatedMethods = new HashSet(); - doGetAnnotatedFields(clazz, annotation, annotatedFields); - doGetAnnotatedMethods(clazz, annotation, annotatedMethods); - Set result = new HashSet(annotatedFields.size() + annotatedMethods.size()); - for (Field field : annotatedFields) { - field.setAccessible(true); - result.add(field); - } - for (Method method : annotatedMethods) { - method.setAccessible(true); - result.add(method); - } - return result; - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - /** - * Populates {@code fields} set with all properties marked with a given annotation. - * @param clazz Class type. - * @param annotation Annotation. - * @param fields Set of annotated fields. Shall be initialized externally. - */ - private static void doGetAnnotatedFields(Class clazz, Class annotation, Set fields) { - for (Field field : clazz.getDeclaredFields()) { - field.setAccessible(true); - if (field.isAnnotationPresent(annotation)) { - fields.add(field); - } - } - Class superClass = clazz.getSuperclass(); - if (!Object.class.equals(superClass)) { - doGetAnnotatedFields(superClass, annotation, fields); - } - } - - /** - * Populates {@code methods} set with all functions marked with a given annotation. - * @param clazz Class type. - * @param annotation Annotation. - * @param methods Set of annotated methods. Shall be initialized externally. - */ - private static void doGetAnnotatedMethods(Class clazz, Class annotation, Set methods) { - for (Method method : clazz.getDeclaredMethods()) { - method.setAccessible(true); - if (method.isAnnotationPresent(annotation)) { - methods.add(method); - } - } - Class superClass = clazz.getSuperclass(); - if (!Object.class.equals(superClass)) { - doGetAnnotatedMethods(superClass, annotation, methods); - } - } }