From efc9377b3177d0f29701c96d591be362ea9b1f69 Mon Sep 17 00:00:00 2001 From: Lukasz Antoniak Date: Sat, 18 Jun 2011 10:04:52 +0200 Subject: [PATCH] HHH-5917 - Fix and test --- .../java/org/hibernate/envers/Audited.java | 9 ++ .../reader/AuditedPropertiesReader.java | 78 ++++++++- .../auditparents/AuditParentsTest.java | 153 ++++++++++++++++++ .../auditparents/BabyCompleteEntity.java | 53 ++++++ .../auditparents/ChildCompleteEntity.java | 54 +++++++ .../ChildMultipleParentsEntity.java | 55 +++++++ .../auditparents/ChildSingleParentEntity.java | 54 +++++++ .../ExplicitTransitiveChildEntity.java | 53 ++++++ .../ImplicitTransitiveChildEntity.java | 53 ++++++ .../auditparents/MappedGrandparentEntity.java | 74 +++++++++ .../auditparents/MappedParentEntity.java | 61 +++++++ .../auditparents/TransitiveParentEntity.java | 53 ++++++ 12 files changed, 745 insertions(+), 5 deletions(-) create mode 100644 hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/AuditParentsTest.java create mode 100644 hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/BabyCompleteEntity.java create mode 100644 hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/ChildCompleteEntity.java create mode 100644 hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/ChildMultipleParentsEntity.java create mode 100644 hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/ChildSingleParentEntity.java create mode 100644 hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/ExplicitTransitiveChildEntity.java create mode 100644 hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/ImplicitTransitiveChildEntity.java create mode 100644 hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/MappedGrandparentEntity.java create mode 100644 hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/MappedParentEntity.java create mode 100644 hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/TransitiveParentEntity.java diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/Audited.java b/hibernate-envers/src/main/java/org/hibernate/envers/Audited.java index 01dc2134c1..bd7fdcffba 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/Audited.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/Audited.java @@ -33,6 +33,7 @@ import java.lang.annotation.Target; * When applied to a field, indicates that this field should be audited. * @author Adam Warski (adam at warski dot org) * @author Tomasz Bech + * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}) @@ -45,4 +46,12 @@ public @interface Audited { * This is useful for dictionary-like entities, which don't change and don't need to be audited. */ RelationTargetAuditMode targetAuditMode() default RelationTargetAuditMode.AUDITED; + + /** + * @return Set of superclasses which properties shall be audited. The behavior of listed classes + * is the same as if they had {@link Audited} annotation applied on a type level. The scope of this functionality + * is limited to the context of actually mapped entity and its class hierarchy. If a parent type lists any of + * its parent types using this attribute, all fields encapsulated by marked classes are implicitly audited. + */ + Class[] auditParents() default {}; } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/metadata/reader/AuditedPropertiesReader.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/metadata/reader/AuditedPropertiesReader.java index 090baabd43..f4a8fa2537 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/metadata/reader/AuditedPropertiesReader.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/metadata/reader/AuditedPropertiesReader.java @@ -3,6 +3,7 @@ package org.hibernate.envers.configuration.metadata.reader; import static org.hibernate.envers.tools.Tools.newHashSet; import java.lang.annotation.Annotation; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; @@ -31,6 +32,7 @@ import org.hibernate.MappingException; * @author Adam Warski (adam at warski dot org) * @author Erik-Berndt Scheper * @author Hern&aacut;n Chanfreau + * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) */ public class AuditedPropertiesReader { protected final ModificationStore defaultStore; @@ -64,10 +66,50 @@ public class AuditedPropertiesReader { // First reading the access types for the persistent properties. readPersistentPropertiesAccess(); - // Adding all properties from the given class. - addPropertiesFromClass(persistentPropertiesSource.getXClass()); + // Retrieve classes that are explicitly marked for auditing process by any superclass of currently mapped + // entity or itself. + XClass clazz = persistentPropertiesSource.getXClass(); + Set declaredAuditedSuperclasses = new HashSet(); + doGetDeclaredAuditedSuperclasses(clazz, declaredAuditedSuperclasses); + + // Adding all properties from the given class. + addPropertiesFromClass(clazz, declaredAuditedSuperclasses); } + /** + * Recursively constructs a set of classes that have been declared for auditing process. + * @param clazz Class that is being processed. Currently mapped entity shall be passed during first invocation. + * @param declaredAuditedSuperclasses Total collection of classes listed in {@link Audited#auditParents()} property + * by any superclass starting with class specified as the first argument. + */ + @SuppressWarnings("unchecked") + private void doGetDeclaredAuditedSuperclasses(XClass clazz, Set declaredAuditedSuperclasses) { + Audited allClassAudited = clazz.getAnnotation(Audited.class); + if (allClassAudited != null && allClassAudited.auditParents().length > 0) { + for (Class c : allClassAudited.auditParents()) { + XClass parentClass = reflectionManager.toXClass(c); + checkSuperclass(clazz, parentClass); + declaredAuditedSuperclasses.add(parentClass); + } + } + XClass superclass = clazz.getSuperclass(); + if (!clazz.isInterface() && !Object.class.getName().equals(superclass.getName())) { + doGetDeclaredAuditedSuperclasses(superclass, declaredAuditedSuperclasses); + } + } + + /** + * Checks whether one class is assignable from another. If not {@link MappingException} is thrown. + * @param child Subclass. + * @param parent Superclass. + */ + private void checkSuperclass(XClass child, XClass parent) { + if (!parent.isAssignableFrom(child)) { + throw new MappingException("Class " + parent.getName() + " is not assignable from " + child.getName() + ". " + + "Please revise @Audited.auditParents value in " + child.getName() + " type."); + } + } + private void readPersistentPropertiesAccess() { Iterator propertyIter = persistentPropertiesSource.getPropertyIterator(); while (propertyIter.hasNext()) { @@ -80,8 +122,34 @@ public class AuditedPropertiesReader { } } - private void addPropertiesFromClass(XClass clazz) { - Audited allClassAudited = clazz.getAnnotation(Audited.class); + /** + * @param clazz Class which properties are currently being added. + * @param declaredAuditedSuperclasses Collection of superclasses that have been explicitly declared to be audited. + * @return {@link Audited} annotation of specified class. If processed type hasn't been explicitly marked, method + * checks whether given class exists in collection passed as the second argument. In case of success, + * {@link Audited} configuration of currently mapped entity is returned, otherwise {@code null}. + */ + private Audited computeAuditConfiguration(XClass clazz, Set declaredAuditedSuperclasses) { + Audited allClassAudited = clazz.getAnnotation(Audited.class); + // If processed class is not explicitly marked with @Audited annotation, check whether auditing is + // forced by any of its child entities configuration (@Audited.auditParents). + if (allClassAudited == null && declaredAuditedSuperclasses.contains(clazz)) { + // Declared audited parent copies @Audited.modStore and @Audited.targetAuditMode configuration from + // currently mapped entity. + allClassAudited = persistentPropertiesSource.getXClass().getAnnotation(Audited.class); + } + return allClassAudited; + } + + /** + * Recursively adds all audited properties of entity class and its superclasses. + * @param clazz Currently processed class. + * @param declaredAuditedSuperclasses Collection of classes that are declared to be audited + * (see {@link Audited#auditParents()}). + */ + private void addPropertiesFromClass(XClass clazz, Set declaredAuditedSuperclasses) { + Audited allClassAudited = computeAuditConfiguration(clazz, declaredAuditedSuperclasses); + //look in the class addFromProperties(clazz.getDeclaredProperties("field"), "field", fieldAccessedPersistentProperties, allClassAudited); addFromProperties(clazz.getDeclaredProperties("property"), "property", propertyAccessedPersistentProperties, allClassAudited); @@ -89,7 +157,7 @@ public class AuditedPropertiesReader { if(allClassAudited != null || !auditedPropertiesHolder.isEmpty()) { XClass superclazz = clazz.getSuperclass(); if (!clazz.isInterface() && !"java.lang.Object".equals(superclazz.getName())) { - addPropertiesFromClass(superclazz); + addPropertiesFromClass(superclazz, declaredAuditedSuperclasses); } } } diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/AuditParentsTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/AuditParentsTest.java new file mode 100644 index 0000000000..723846a7d5 --- /dev/null +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/AuditParentsTest.java @@ -0,0 +1,153 @@ +package org.hibernate.envers.test.integration.superclass.auditparents; + +import org.hibernate.ejb.Ejb3Configuration; +import org.hibernate.envers.Audited; +import org.hibernate.envers.test.AbstractEntityTest; +import org.hibernate.envers.test.Priority; +import org.hibernate.envers.test.entities.StrIntTestEntity; +import org.hibernate.envers.test.tools.TestTools; +import org.hibernate.mapping.Column; +import org.hibernate.mapping.Table; +import org.junit.Assert; +import org.junit.Test; + +import javax.persistence.EntityManager; +import java.util.Set; + +/** + * Tests several configurations of entity hierarchy that utilizes {@link Audited#auditParents()} property. + * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) + */ +public class AuditParentsTest extends AbstractEntityTest { + private long childSingleId = 1L; + private long childMultipleId = 2L; + private long childImpTransId = 3L; + private long childExpTransId = 4L; + private long babyCompleteId = 5L; + private Integer siteSingleId = null; + private Integer siteMultipleId = null; + private Integer siteCompleteId = null; + + @Override + public void configure(Ejb3Configuration cfg) { + cfg.addAnnotatedClass(MappedGrandparentEntity.class); + cfg.addAnnotatedClass(MappedParentEntity.class); + cfg.addAnnotatedClass(ChildSingleParentEntity.class); + cfg.addAnnotatedClass(ChildMultipleParentsEntity.class); + cfg.addAnnotatedClass(TransitiveParentEntity.class); + cfg.addAnnotatedClass(ImplicitTransitiveChildEntity.class); + cfg.addAnnotatedClass(ExplicitTransitiveChildEntity.class); + cfg.addAnnotatedClass(StrIntTestEntity.class); + cfg.addAnnotatedClass(ChildCompleteEntity.class); + cfg.addAnnotatedClass(BabyCompleteEntity.class); + } + + @Test + @Priority(10) + public void initData() { + EntityManager em = getEntityManager(); + + // Revision 1 + em.getTransaction().begin(); + StrIntTestEntity siteSingle = new StrIntTestEntity("data 1", 1); + em.persist(siteSingle); + em.persist(new ChildSingleParentEntity(childSingleId, "grandparent 1", "notAudited 1", "parent 1", "child 1", siteSingle)); + em.getTransaction().commit(); + siteSingleId = siteSingle.getId(); + + // Revision 2 + em.getTransaction().begin(); + StrIntTestEntity siteMultiple = new StrIntTestEntity("data 2", 2); + em.persist(siteMultiple); + em.persist(new ChildMultipleParentsEntity(childMultipleId, "grandparent 2", "notAudited 2", "parent 2", "child 2", siteMultiple)); + em.getTransaction().commit(); + siteMultipleId = siteMultiple.getId(); + + // Revision 3 + em.getTransaction().begin(); + em.persist(new ImplicitTransitiveChildEntity(childImpTransId, "grandparent 3", "notAudited 3", "parent 3", "child 3")); + em.getTransaction().commit(); + + // Revision 4 + em.getTransaction().begin(); + em.persist(new ExplicitTransitiveChildEntity(childExpTransId, "grandparent 4", "notAudited 4", "parent 4", "child 4")); + em.getTransaction().commit(); + + // Revision 5 + em.getTransaction().begin(); + StrIntTestEntity siteComplete = new StrIntTestEntity("data 5", 5); + em.persist(siteComplete); + em.persist(new BabyCompleteEntity(babyCompleteId, "grandparent 5", "notAudited 5", "parent 5", "child 5", siteComplete, "baby 5")); + em.getTransaction().commit(); + siteCompleteId = siteComplete.getId(); + } + + @Test + public void testCreatedAuditTables() { + Table babyCompleteTable = getCfg().getClassMapping("org.hibernate.envers.test.integration.superclass.auditparents.BabyCompleteEntity_AUD").getTable(); + checkTableColumns(TestTools.makeSet("baby", "child", "parent", "relation_id", "grandparent", "id"), babyCompleteTable); + + Table explicitTransChildTable = getCfg().getClassMapping("org.hibernate.envers.test.integration.superclass.auditparents.ExplicitTransitiveChildEntity_AUD").getTable(); + checkTableColumns(TestTools.makeSet("child", "parent", "grandparent", "id"), explicitTransChildTable); + + Table implicitTransChildTable = getCfg().getClassMapping("org.hibernate.envers.test.integration.superclass.auditparents.ImplicitTransitiveChildEntity_AUD").getTable(); + checkTableColumns(TestTools.makeSet("child", "parent", "grandparent", "id"), implicitTransChildTable); + + Table multipleParentChildTable = getCfg().getClassMapping("org.hibernate.envers.test.integration.superclass.auditparents.ChildMultipleParentsEntity_AUD").getTable(); + checkTableColumns(TestTools.makeSet("child", "parent", "relation_id", "grandparent", "id"), multipleParentChildTable); + + Table singleParentChildTable = getCfg().getClassMapping("org.hibernate.envers.test.integration.superclass.auditparents.ChildSingleParentEntity_AUD").getTable(); + checkTableColumns(TestTools.makeSet("child", "grandparent", "id"), singleParentChildTable); + } + + @SuppressWarnings("unchecked") + private void checkTableColumns(Set expectedColumns, Table table) { + for (String columnName : expectedColumns) { + // Check whether expected column exists. + Assert.assertNotNull(table.getColumn(new Column(columnName))); + } + } + + @Test + public void testSingleAuditParent() { + // expectedSingleChild.parent, expectedSingleChild.relation and expectedSingleChild.notAudited shall be null, because they are not audited. + ChildSingleParentEntity expectedSingleChild = new ChildSingleParentEntity(childSingleId, "grandparent 1", null, null, "child 1", null); + ChildSingleParentEntity child = getAuditReader().find(ChildSingleParentEntity.class, childSingleId, 1); + Assert.assertEquals(expectedSingleChild, child); + Assert.assertNull(child.getRelation()); + } + + @Test + public void testMultipleAuditParents() { + // expectedMultipleChild.notAudited shall be null, because it is not audited. + ChildMultipleParentsEntity expectedMultipleChild = new ChildMultipleParentsEntity(childMultipleId, "grandparent 2", null, "parent 2", "child 2", new StrIntTestEntity("data 2", 2, siteMultipleId)); + ChildMultipleParentsEntity child = getAuditReader().find(ChildMultipleParentsEntity.class, childMultipleId, 2); + Assert.assertEquals(expectedMultipleChild, child); + Assert.assertEquals(expectedMultipleChild.getRelation().getId(), child.getRelation().getId()); + } + + @Test + public void testImplicitTransitiveAuditParents() { + // expectedChild.notAudited shall be null, because it is not audited. + ImplicitTransitiveChildEntity expectedChild = new ImplicitTransitiveChildEntity(childImpTransId, "grandparent 3", null, "parent 3", "child 3"); + ImplicitTransitiveChildEntity child = getAuditReader().find(ImplicitTransitiveChildEntity.class, childImpTransId, 3); + Assert.assertEquals(expectedChild, child); + } + + @Test + public void testExplicitTransitiveAuditParents() { + // expectedChild.notAudited shall be null, because it is not audited. + ExplicitTransitiveChildEntity expectedChild = new ExplicitTransitiveChildEntity(childExpTransId, "grandparent 4", null, "parent 4", "child 4"); + ExplicitTransitiveChildEntity child = getAuditReader().find(ExplicitTransitiveChildEntity.class, childExpTransId, 4); + Assert.assertEquals(expectedChild, child); + } + + @Test + public void testCompleteAuditParents() { + // expectedBaby.notAudited shall be null, because it is not audited. + BabyCompleteEntity expectedBaby = new BabyCompleteEntity(babyCompleteId, "grandparent 5", null, "parent 5", "child 5", new StrIntTestEntity("data 5", 5, siteCompleteId), "baby 5"); + BabyCompleteEntity baby = getAuditReader().find(BabyCompleteEntity.class, babyCompleteId, 5); + Assert.assertEquals(expectedBaby, baby); + Assert.assertEquals(expectedBaby.getRelation().getId(), baby.getRelation().getId()); + } +} diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/BabyCompleteEntity.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/BabyCompleteEntity.java new file mode 100644 index 0000000000..ae564aaea0 --- /dev/null +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/BabyCompleteEntity.java @@ -0,0 +1,53 @@ +package org.hibernate.envers.test.integration.superclass.auditparents; + +import org.hibernate.envers.Audited; +import org.hibernate.envers.test.entities.StrIntTestEntity; + +import javax.persistence.Entity; + +/** + * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) + */ +@Entity +@Audited(auditParents = {MappedParentEntity.class}) +public class BabyCompleteEntity extends ChildCompleteEntity { + private String baby; + + public BabyCompleteEntity() { + } + + public BabyCompleteEntity(Long id, String grandparent, String notAudited, String parent, String child, StrIntTestEntity relation, String baby) { + super(id, grandparent, notAudited, parent, child, relation); + this.baby = baby; + } + + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof BabyCompleteEntity)) return false; + if (!super.equals(o)) return false; + + BabyCompleteEntity that = (BabyCompleteEntity) o; + + if (baby != null ? !baby.equals(that.baby) : that.baby != null) return false; + + return true; + } + + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (baby != null ? baby.hashCode() : 0); + return result; + } + + public String toString() { + return "BabyCompleteEntity(" + super.toString() + ", baby = " + baby + ")"; + } + + public String getBaby() { + return baby; + } + + public void setBaby(String baby) { + this.baby = baby; + } +} diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/ChildCompleteEntity.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/ChildCompleteEntity.java new file mode 100644 index 0000000000..b8152ac592 --- /dev/null +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/ChildCompleteEntity.java @@ -0,0 +1,54 @@ +package org.hibernate.envers.test.integration.superclass.auditparents; + +import org.hibernate.envers.Audited; +import org.hibernate.envers.test.entities.StrIntTestEntity; + +import javax.persistence.MappedSuperclass; + +/** + * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) + */ +@MappedSuperclass +@Audited(auditParents = {MappedGrandparentEntity.class}) +public class ChildCompleteEntity extends MappedParentEntity { + private String child; + + public ChildCompleteEntity() { + super(null, null, null, null, null); + } + + public ChildCompleteEntity(Long id, String grandparent, String notAudited, String parent, String child, StrIntTestEntity relation) { + super(id, grandparent, notAudited, parent, relation); + this.child = child; + } + + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ChildCompleteEntity)) return false; + if (!super.equals(o)) return false; + + ChildCompleteEntity that = (ChildCompleteEntity) o; + + if (child != null ? !child.equals(that.child) : that.child != null) return false; + + return true; + } + + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (child != null ? child.hashCode() : 0); + return result; + } + + public String toString() { + return "ChildCompleteEntity(" + super.toString() + ", child = " + child + ")"; + } + + public String getChild() { + return child; + } + + public void setChild(String child) { + this.child = child; + } +} diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/ChildMultipleParentsEntity.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/ChildMultipleParentsEntity.java new file mode 100644 index 0000000000..2029067fd0 --- /dev/null +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/ChildMultipleParentsEntity.java @@ -0,0 +1,55 @@ +package org.hibernate.envers.test.integration.superclass.auditparents; + +import org.hibernate.envers.Audited; +import org.hibernate.envers.test.entities.StrIntTestEntity; + +import javax.persistence.Entity; + +/** + * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) + */ +@Entity +@Audited(auditParents = {MappedParentEntity.class, MappedGrandparentEntity.class}) +public class ChildMultipleParentsEntity extends MappedParentEntity { + private String child; + + public ChildMultipleParentsEntity() { + super(null, null, null, null, null); + } + + public ChildMultipleParentsEntity(Long id, String grandparent, String notAudited, String parent, String child, StrIntTestEntity relation) { + super(id, grandparent, notAudited, parent, relation); + this.child = child; + } + + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ChildMultipleParentsEntity)) return false; + if (!super.equals(o)) return false; + + ChildMultipleParentsEntity that = (ChildMultipleParentsEntity) o; + + if (child != null ? !child.equals(that.child) : that.child != null) return false; + + return true; + } + + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (child != null ? child.hashCode() : 0); + return result; + } + + public String toString() { + return "ChildMultipleParentsEntity(" + super.toString() + ", child = " + child + ")"; + } + + public String getChild() { + return child; + } + + public void setChild(String child) { + this.child = child; + } +} + diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/ChildSingleParentEntity.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/ChildSingleParentEntity.java new file mode 100644 index 0000000000..2670f3eabb --- /dev/null +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/ChildSingleParentEntity.java @@ -0,0 +1,54 @@ +package org.hibernate.envers.test.integration.superclass.auditparents; + +import org.hibernate.envers.Audited; +import org.hibernate.envers.test.entities.StrIntTestEntity; + +import javax.persistence.Entity; + +/** + * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) + */ +@Entity +@Audited(auditParents = {MappedGrandparentEntity.class}) +public class ChildSingleParentEntity extends MappedParentEntity { + private String child; + + public ChildSingleParentEntity() { + super(null, null, null, null, null); + } + + public ChildSingleParentEntity(Long id, String grandparent, String notAudited, String parent, String child, StrIntTestEntity relation) { + super(id, grandparent, notAudited, parent, relation); + this.child = child; + } + + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ChildSingleParentEntity)) return false; + if (!super.equals(o)) return false; + + ChildSingleParentEntity that = (ChildSingleParentEntity) o; + + if (child != null ? !child.equals(that.child) : that.child != null) return false; + + return true; + } + + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (child != null ? child.hashCode() : 0); + return result; + } + + public String toString() { + return "ChildSingleParentEntity(" + super.toString() + ", child = " + child + ")"; + } + + public String getChild() { + return child; + } + + public void setChild(String child) { + this.child = child; + } +} diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/ExplicitTransitiveChildEntity.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/ExplicitTransitiveChildEntity.java new file mode 100644 index 0000000000..b392323571 --- /dev/null +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/ExplicitTransitiveChildEntity.java @@ -0,0 +1,53 @@ +package org.hibernate.envers.test.integration.superclass.auditparents; + +import org.hibernate.envers.Audited; + +import javax.persistence.Entity; + +/** + * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) + */ +@Entity +@Audited(auditParents = {TransitiveParentEntity.class}) +public class ExplicitTransitiveChildEntity extends TransitiveParentEntity { + private String child; + + public ExplicitTransitiveChildEntity() { + super(null, null, null, null); + } + + public ExplicitTransitiveChildEntity(Long id, String grandparent, String notAudited, String parent, String child) { + super(id, grandparent, notAudited, parent); + this.child = child; + } + + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ExplicitTransitiveChildEntity)) return false; + if (!super.equals(o)) return false; + + ExplicitTransitiveChildEntity that = (ExplicitTransitiveChildEntity) o; + + if (child != null ? !child.equals(that.child) : that.child != null) return false; + + return true; + } + + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (child != null ? child.hashCode() : 0); + return result; + } + + public String toString() { + return "ExplicitTransitiveChildEntity(" + super.toString() + ", child = " + child + ")"; + } + + public String getChild() { + return child; + } + + public void setChild(String child) { + this.child = child; + } +} diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/ImplicitTransitiveChildEntity.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/ImplicitTransitiveChildEntity.java new file mode 100644 index 0000000000..a5c010374a --- /dev/null +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/ImplicitTransitiveChildEntity.java @@ -0,0 +1,53 @@ +package org.hibernate.envers.test.integration.superclass.auditparents; + +import org.hibernate.envers.Audited; + +import javax.persistence.Entity; + +/** + * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) + */ +@Entity +@Audited +public class ImplicitTransitiveChildEntity extends TransitiveParentEntity { + private String child; + + public ImplicitTransitiveChildEntity() { + super(null, null, null, null); + } + + public ImplicitTransitiveChildEntity(Long id, String grandparent, String notAudited, String parent, String child) { + super(id, grandparent, notAudited, parent); + this.child = child; + } + + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ImplicitTransitiveChildEntity)) return false; + if (!super.equals(o)) return false; + + ImplicitTransitiveChildEntity that = (ImplicitTransitiveChildEntity) o; + + if (child != null ? !child.equals(that.child) : that.child != null) return false; + + return true; + } + + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (child != null ? child.hashCode() : 0); + return result; + } + + public String toString() { + return "ImplicitTransitiveChildEntity(" + super.toString() + ", child = " + child + ")"; + } + + public String getChild() { + return child; + } + + public void setChild(String child) { + this.child = child; + } +} diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/MappedGrandparentEntity.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/MappedGrandparentEntity.java new file mode 100644 index 0000000000..79a4f20ff3 --- /dev/null +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/MappedGrandparentEntity.java @@ -0,0 +1,74 @@ +package org.hibernate.envers.test.integration.superclass.auditparents; + +import org.hibernate.envers.NotAudited; + +import javax.persistence.Id; +import javax.persistence.MappedSuperclass; + +/** + * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) + */ +@MappedSuperclass +public class MappedGrandparentEntity { + @Id + private Long id; + + private String grandparent; + + @NotAudited + private String notAudited; + + public MappedGrandparentEntity(Long id, String grandparent, String notAudited) { + this.id = id; + this.grandparent = grandparent; + this.notAudited = notAudited; + } + + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof MappedGrandparentEntity)) return false; + + MappedGrandparentEntity that = (MappedGrandparentEntity) o; + + if (id != null ? !id.equals(that.id) : that.id != null) return false; + if (grandparent != null ? !grandparent.equals(that.grandparent) : that.grandparent != null) return false; + if (notAudited != null ? !notAudited.equals(that.notAudited) : that.notAudited != null) return false; + + return true; + } + + public int hashCode() { + int result = (id != null ? id.hashCode() : 0); + result = 31 * result + (grandparent != null ? grandparent.hashCode() : 0); + result = 31 * result + (notAudited != null ? notAudited.hashCode() : 0); + return result; + } + + public String toString() { + return "MappedGrandparentEntity(id = " + id + ", grandparent = " + grandparent + ", notAudited = " + notAudited + ")"; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getGrandparent() { + return grandparent; + } + + public void setGrandparent(String grandparent) { + this.grandparent = grandparent; + } + + public String getNotAudited() { + return notAudited; + } + + public void setNotAudited(String notAudited) { + this.notAudited = notAudited; + } +} diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/MappedParentEntity.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/MappedParentEntity.java new file mode 100644 index 0000000000..9d83b0e754 --- /dev/null +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/MappedParentEntity.java @@ -0,0 +1,61 @@ +package org.hibernate.envers.test.integration.superclass.auditparents; + +import org.hibernate.envers.test.entities.StrIntTestEntity; + +import javax.persistence.ManyToOne; +import javax.persistence.MappedSuperclass; + +/** + * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) + */ +@MappedSuperclass +public class MappedParentEntity extends MappedGrandparentEntity { + private String parent; + + @ManyToOne + private StrIntTestEntity relation; + + public MappedParentEntity(Long id, String grandparent, String notAudited, String parent, StrIntTestEntity relation) { + super(id, grandparent, notAudited); + this.parent = parent; + this.relation = relation; + } + + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof MappedParentEntity)) return false; + if (!super.equals(o)) return false; + + MappedParentEntity that = (MappedParentEntity) o; + + if (parent != null ? !parent.equals(that.parent) : that.parent != null) return false; + + return true; + } + + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (parent != null ? parent.hashCode() : 0); + return result; + } + + public String toString() { + return "MappedParentEntity(" + super.toString() + ", parent = " + parent + ", relation = " + relation + ")"; + } + + public String getParent() { + return parent; + } + + public void setParent(String parent) { + this.parent = parent; + } + + public StrIntTestEntity getRelation() { + return relation; + } + + public void setRelation(StrIntTestEntity relation) { + this.relation = relation; + } +} diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/TransitiveParentEntity.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/TransitiveParentEntity.java new file mode 100644 index 0000000000..e58c979f65 --- /dev/null +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/superclass/auditparents/TransitiveParentEntity.java @@ -0,0 +1,53 @@ +package org.hibernate.envers.test.integration.superclass.auditparents; + +import org.hibernate.envers.Audited; + +import javax.persistence.MappedSuperclass; + +/** + * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) + */ +@MappedSuperclass +@Audited(auditParents = {MappedGrandparentEntity.class}) +public class TransitiveParentEntity extends MappedGrandparentEntity { + private String parent; + + public TransitiveParentEntity() { + super(null, null, null); + } + + public TransitiveParentEntity(Long id, String grandparent, String notAudited, String parent) { + super(id, grandparent, notAudited); + this.parent = parent; + } + + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof TransitiveParentEntity)) return false; + if (!super.equals(o)) return false; + + TransitiveParentEntity that = (TransitiveParentEntity) o; + + if (parent != null ? !parent.equals(that.parent) : that.parent != null) return false; + + return true; + } + + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (parent != null ? parent.hashCode() : 0); + return result; + } + + public String toString() { + return "TransitiveParentEntity(" + super.toString() + ", parent = " + parent + ")"; + } + + public String getParent() { + return parent; + } + + public void setParent(String parent) { + this.parent = parent; + } +}