HHH-3565: adding support for field and property access types; changed the way properties are read. Now, instead of a sole property name, a special "PropertyData" object is passed around which encapsulates the property name and access type information.

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@15481 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Adam Warski 2008-11-03 11:24:30 +00:00
parent 572f412482
commit cc03033e59
56 changed files with 1257 additions and 462 deletions

View File

@ -41,18 +41,18 @@ import org.hibernate.annotations.common.reflection.ReflectionManager;
*/
public class AuditConfiguration {
private final GlobalConfiguration globalCfg;
private final AuditEntitiesConfiguration verEntCfg;
private final AuditSyncManager versionsSyncManager;
private final AuditEntitiesConfiguration auditEntCfg;
private final AuditSyncManager auditSyncManager;
private final EntitiesConfigurations entCfg;
private final RevisionInfoQueryCreator revisionInfoQueryCreator;
private final RevisionInfoNumberReader revisionInfoNumberReader;
public AuditEntitiesConfiguration getVerEntCfg() {
return verEntCfg;
public AuditEntitiesConfiguration getAuditEntCfg() {
return auditEntCfg;
}
public AuditSyncManager getSyncManager() {
return versionsSyncManager;
return auditSyncManager;
}
public GlobalConfiguration getGlobalCfg() {
@ -78,12 +78,12 @@ public class AuditConfiguration {
ReflectionManager reflectionManager = ((AnnotationConfiguration) cfg).getReflectionManager();
RevisionInfoConfiguration revInfoCfg = new RevisionInfoConfiguration();
RevisionInfoConfigurationResult revInfoCfgResult = revInfoCfg.configure(cfg, reflectionManager);
verEntCfg = new AuditEntitiesConfiguration(properties, revInfoCfgResult.getRevisionInfoEntityName());
auditEntCfg = new AuditEntitiesConfiguration(properties, revInfoCfgResult.getRevisionInfoEntityName());
globalCfg = new GlobalConfiguration(properties);
versionsSyncManager = new AuditSyncManager(revInfoCfgResult.getRevisionInfoGenerator());
auditSyncManager = new AuditSyncManager(revInfoCfgResult.getRevisionInfoGenerator());
revisionInfoQueryCreator = revInfoCfgResult.getRevisionInfoQueryCreator();
revisionInfoNumberReader = revInfoCfgResult.getRevisionInfoNumberReader();
entCfg = new EntitiesConfigurator().configure(cfg, reflectionManager, globalCfg, verEntCfg,
entCfg = new EntitiesConfigurator().configure(cfg, reflectionManager, globalCfg, auditEntCfg,
revInfoCfgResult.getRevisionInfoXmlMapping(), revInfoCfgResult.getRevisionInfoRelationMapping());
}

View File

@ -39,7 +39,7 @@ import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.hibernate.envers.configuration.metadata.AnnotationsMetadataReader;
import org.hibernate.envers.configuration.metadata.EntityXmlMappingData;
import org.hibernate.envers.configuration.metadata.PersistentClassVersioningData;
import org.hibernate.envers.configuration.metadata.PersistentClassAuditingData;
import org.hibernate.envers.configuration.metadata.AuditMetadataGenerator;
import org.hibernate.envers.entities.EntitiesConfigurations;
import org.hibernate.envers.tools.StringTools;
@ -64,8 +64,8 @@ public class EntitiesConfigurator {
// Sorting the persistent class topologically - superclass always before subclass
Iterator<PersistentClass> classes = GraphTopologicalSort.sort(new PersistentClassGraphDefiner(cfg)).iterator();
Map<PersistentClass, PersistentClassVersioningData> pcDatas =
new HashMap<PersistentClass, PersistentClassVersioningData>();
Map<PersistentClass, PersistentClassAuditingData> pcDatas =
new HashMap<PersistentClass, PersistentClassAuditingData>();
Map<PersistentClass, EntityXmlMappingData> xmlMappings = new HashMap<PersistentClass, EntityXmlMappingData>();
// First pass
@ -74,23 +74,23 @@ public class EntitiesConfigurator {
// Collecting information from annotations on the persistent class pc
AnnotationsMetadataReader annotationsMetadataReader =
new AnnotationsMetadataReader(globalCfg, reflectionManager, pc);
PersistentClassVersioningData versioningData = annotationsMetadataReader.getVersioningData();
PersistentClassAuditingData auditData = annotationsMetadataReader.getAuditData();
if (versioningData.isVersioned()) {
pcDatas.put(pc, versioningData);
if (auditData.isAudited()) {
pcDatas.put(pc, auditData);
if (!StringTools.isEmpty(versioningData.versionsTable.value())) {
verEntCfg.addCustomVersionsTableName(pc.getEntityName(), versioningData.versionsTable.value());
if (!StringTools.isEmpty(auditData.getAuditTable().value())) {
verEntCfg.addCustomVersionsTableName(pc.getEntityName(), auditData.getAuditTable().value());
}
EntityXmlMappingData xmlMappingData = new EntityXmlMappingData();
versionsMetaGen.generateFirstPass(pc, versioningData, xmlMappingData);
versionsMetaGen.generateFirstPass(pc, auditData, xmlMappingData);
xmlMappings.put(pc, xmlMappingData);
}
}
// Second pass
for (Map.Entry<PersistentClass, PersistentClassVersioningData> pcDatasEntry : pcDatas.entrySet()) {
for (Map.Entry<PersistentClass, PersistentClassAuditingData> pcDatasEntry : pcDatas.entrySet()) {
EntityXmlMappingData xmlMappingData = xmlMappings.get(pcDatasEntry.getKey());
versionsMetaGen.generateSecondPass(pcDatasEntry.getKey(), pcDatasEntry.getValue(), xmlMappingData);

View File

@ -30,6 +30,7 @@ import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.hibernate.envers.Audited;
import org.hibernate.envers.*;
import org.hibernate.envers.entities.PropertyData;
import org.hibernate.envers.configuration.metadata.MetadataTools;
import org.hibernate.envers.revisioninfo.DefaultRevisionInfoGenerator;
import org.hibernate.envers.revisioninfo.RevisionInfoGenerator;
@ -49,16 +50,16 @@ import org.hibernate.mapping.PersistentClass;
*/
public class RevisionInfoConfiguration {
private String revisionInfoEntityName;
private String revisionInfoIdName;
private String revisionInfoTimestampName;
private PropertyData revisionInfoIdData;
private PropertyData revisionInfoTimestampData;
private String revisionInfoTimestampType;
private String revisionPropType;
public RevisionInfoConfiguration() {
revisionInfoEntityName = "org.hibernate.envers.DefaultRevisionEntity";
revisionInfoIdName = "id";
revisionInfoTimestampName = "timestamp";
revisionInfoIdData = new PropertyData("id", "field", null);
revisionInfoTimestampData = new PropertyData("timestamp", "field", null);
revisionInfoTimestampType = "long";
revisionPropType = "integer";
@ -72,11 +73,11 @@ public class RevisionInfoConfiguration {
class_mapping.addAttribute("name", revisionInfoEntityName);
class_mapping.addAttribute("table", "_revisions_info");
Element idProperty = MetadataTools.addNativelyGeneratedId(class_mapping, revisionInfoIdName,
Element idProperty = MetadataTools.addNativelyGeneratedId(class_mapping, revisionInfoIdData.getName(),
revisionPropType);
MetadataTools.addColumn(idProperty, "revision_id", null);
Element timestampProperty = MetadataTools.addProperty(class_mapping, revisionInfoTimestampName,
Element timestampProperty = MetadataTools.addProperty(class_mapping, revisionInfoTimestampData.getName(),
revisionInfoTimestampType, true, false);
MetadataTools.addColumn(timestampProperty, "revision_timestamp", null);
@ -107,11 +108,11 @@ public class RevisionInfoConfiguration {
XClass revisionNumberClass = property.getType();
if (reflectionManager.equals(revisionNumberClass, Integer.class) ||
reflectionManager.equals(revisionNumberClass, Integer.TYPE)) {
revisionInfoIdName = property.getName();
revisionInfoIdData = new PropertyData(property.getName(), accessType, null);
revisionNumberFound.set();
} else if (reflectionManager.equals(revisionNumberClass, Long.class) ||
reflectionManager.equals(revisionNumberClass, Long.TYPE)) {
revisionInfoIdName = property.getName();
revisionInfoIdData = new PropertyData(property.getName(), accessType, null);
revisionNumberFound.set();
// The default is integer
@ -130,7 +131,7 @@ public class RevisionInfoConfiguration {
XClass revisionTimestampClass = property.getType();
if (reflectionManager.equals(revisionTimestampClass, Long.class) ||
reflectionManager.equals(revisionTimestampClass, Long.TYPE)) {
revisionInfoTimestampName = property.getName();
revisionInfoTimestampData = new PropertyData(property.getName(), accessType, null);
revisionTimestampFound.set();
} else {
throw new MappingException("The field annotated with @RevisionTimestamp must be of type " +
@ -178,7 +179,7 @@ public class RevisionInfoConfiguration {
// Checking if custom revision entity isn't versioned
if (clazz.getAnnotation(Audited.class) != null) {
throw new MappingException("An entity annotated with @RevisionEntity cannot be versioned!");
throw new MappingException("An entity annotated with @RevisionEntity cannot be audited!");
}
revisionEntityFound = true;
@ -202,7 +203,7 @@ public class RevisionInfoConfiguration {
revisionInfoClass = pc.getMappedClass();
revisionInfoGenerator = new DefaultRevisionInfoGenerator(revisionInfoEntityName, revisionInfoClass,
revisionEntity.value(), revisionInfoTimestampName);
revisionEntity.value(), revisionInfoTimestampData);
}
}
@ -212,15 +213,16 @@ public class RevisionInfoConfiguration {
if (revisionInfoGenerator == null) {
revisionInfoClass = DefaultRevisionEntity.class;
revisionInfoGenerator = new DefaultRevisionInfoGenerator(revisionInfoEntityName, revisionInfoClass,
RevisionListener.class, revisionInfoTimestampName);
RevisionListener.class, revisionInfoTimestampData);
revisionInfoXmlMapping = generateDefaultRevisionInfoXmlMapping();
}
return new RevisionInfoConfigurationResult(
revisionInfoGenerator, revisionInfoXmlMapping,
new RevisionInfoQueryCreator(revisionInfoEntityName, revisionInfoIdName, revisionInfoTimestampName),
new RevisionInfoQueryCreator(revisionInfoEntityName, revisionInfoIdData.getName(),
revisionInfoTimestampData.getName()),
generateRevisionInfoRelationMapping(),
new RevisionInfoNumberReader(revisionInfoClass, revisionInfoIdName), revisionInfoEntityName);
new RevisionInfoNumberReader(revisionInfoClass, revisionInfoIdData), revisionInfoEntityName);
}
}

View File

@ -24,11 +24,15 @@
package org.hibernate.envers.configuration.metadata;
import java.lang.annotation.Annotation;
import java.util.Set;
import java.util.Iterator;
import javax.persistence.MapKey;
import javax.persistence.Version;
import javax.persistence.JoinColumn;
import org.hibernate.envers.SecondaryAuditTable;
import org.hibernate.envers.*;
import org.hibernate.envers.tools.Tools;
import org.hibernate.envers.configuration.GlobalConfiguration;
import org.hibernate.MappingException;
@ -36,6 +40,7 @@ import org.hibernate.annotations.common.reflection.ReflectionManager;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
/**
* A helper class to read versioning meta-data from annotations on a persistent class.
@ -51,7 +56,16 @@ public final class AnnotationsMetadataReader {
* This object is filled with information read from annotations and returned by the <code>getVersioningData</code>
* method.
*/
private final PersistentClassVersioningData versioningData;
private final PersistentClassAuditingData auditData;
/**
* Not null if the whole class is annotated with @Audited; the variable then holds the value of this
* annotation's "modStore" parameter.
*/
private ModificationStore defaultStore;
private Set<String> propertyPersistentProperties;
private Set<String> fieldPersistentProperties;
public AnnotationsMetadataReader(GlobalConfiguration globalCfg, ReflectionManager reflectionManager,
PersistentClass pc) {
@ -59,54 +73,88 @@ public final class AnnotationsMetadataReader {
this.reflectionManager = reflectionManager;
this.pc = pc;
versioningData = new PersistentClassVersioningData();
auditData = new PersistentClassAuditingData();
propertyPersistentProperties = Tools.newHashSet();
fieldPersistentProperties = Tools.newHashSet();
}
private void addPropertyVersioned(XProperty property) {
Audited ver = property.getAnnotation(Audited.class);
if (ver != null) {
versioningData.propertyStoreInfo.propertyStores.put(property.getName(), ver.modStore());
/**
* Checks if a property is audited and if yes, sets its modification store on the supplied property data.
* @param property Property to check.
* @param propertyData Property data, on which to set this property's modification store.
* @param persistentProperties Persistent properties with the access type of the given property.
* @return True, iff this property is audited.
*/
private boolean ifPropertyAuditedAddStore(XProperty property, PersistentPropertyAuditingData propertyData,
Set<String> persistentProperties) {
// If this is not a persistent property, with the same access type as currently checked,
// it's not audited as well.
if (!persistentProperties.contains(property.getName())) {
return false;
}
}
private void addPropertyMapKey(XProperty property) {
MapKey mapKey = property.getAnnotation(MapKey.class);
if (mapKey != null) {
versioningData.mapKeys.put(property.getName(), mapKey.name());
}
}
private void addPropertyUnversioned(XProperty property) {
// check if a property is declared as unversioned to exclude it
// useful if a class is versioned but some properties should be excluded
// check if a property is declared as not audited to exclude it
// useful if a class is audited but some properties should be excluded
NotAudited unVer = property.getAnnotation(NotAudited.class);
if (unVer != null) {
versioningData.unversionedProperties.add(property.getName());
return false;
} else {
// if the optimistic locking field has to be unversioned and the current property
// is the optimistic locking field, add it to the unversioned properties list
// is the optimistic locking field, don't audit it
if (globalCfg.isUnversionedOptimisticLockingField()) {
Version jpaVer = property.getAnnotation(Version.class);
if (jpaVer != null) {
versioningData.unversionedProperties.add(property.getName());
return false;
}
}
}
// Checking if this property is explicitly audited or if all properties are.
Audited ver = property.getAnnotation(Audited.class);
if (ver != null) {
propertyData.setStore(ver.modStore());
return true;
} else {
if (defaultStore != null) {
propertyData.setStore(defaultStore);
return true;
} else {
return false;
}
}
}
private void addPropertyJoinTables(XProperty property) {
AuditJoinTable joinTable = property.getAnnotation(AuditJoinTable.class);
if (joinTable != null) {
versioningData.versionsJoinTables.put(property.getName(), joinTable);
private void addPropertyMapKey(XProperty property, PersistentPropertyAuditingData propertyData) {
MapKey mapKey = property.getAnnotation(MapKey.class);
if (mapKey != null) {
propertyData.setMapKey(mapKey.name());
}
}
private void addFromProperties(Iterable<XProperty> properties) {
private void addPropertyJoinTables(XProperty property, PersistentPropertyAuditingData propertyData) {
AuditJoinTable joinTable = property.getAnnotation(AuditJoinTable.class);
if (joinTable != null) {
propertyData.setJoinTable(joinTable);
} else {
propertyData.setJoinTable(getDefaultAuditJoinTable());
}
}
private void addFromProperties(Iterable<XProperty> properties, String accessType, Set<String> persistenProperties) {
for (XProperty property : properties) {
addPropertyVersioned(property);
addPropertyUnversioned(property);
addPropertyJoinTables(property);
addPropertyMapKey(property);
PersistentPropertyAuditingData propertyData = new PersistentPropertyAuditingData();
if (ifPropertyAuditedAddStore(property, propertyData, persistenProperties)) {
// Now we know that the property is audited
auditData.getProperties().put(property.getName(), propertyData);
propertyData.setName(property.getName());
propertyData.setAccessType(accessType);
addPropertyJoinTables(property, propertyData);
addPropertyMapKey(property, propertyData);
}
}
}
@ -116,24 +164,36 @@ public final class AnnotationsMetadataReader {
addPropertiesFromClass(superclazz);
}
addFromProperties(clazz.getDeclaredProperties("field"));
addFromProperties(clazz.getDeclaredProperties("property"));
addFromProperties(clazz.getDeclaredProperties("field"), "field", fieldPersistentProperties);
addFromProperties(clazz.getDeclaredProperties("property"), "property", propertyPersistentProperties);
}
private void addDefaultVersioned(XClass clazz) {
Audited defaultVersioned = clazz.getAnnotation(Audited.class);
private void readDefaultAudited(XClass clazz) {
Audited defaultAudited = clazz.getAnnotation(Audited.class);
if (defaultVersioned != null) {
versioningData.propertyStoreInfo.defaultStore = defaultVersioned.modStore();
if (defaultAudited != null) {
defaultStore = defaultAudited.modStore();
}
}
private void readPersistentProperties() {
Iterator propertyIter = pc.getPropertyIterator();
while (propertyIter.hasNext()) {
Property property = (Property) propertyIter.next();
if ("field".equals(property.getPropertyAccessorName())) {
fieldPersistentProperties.add(property.getName());
} else {
propertyPersistentProperties.add(property.getName());
}
}
}
private void addVersionsTable(XClass clazz) {
AuditTable versionsTable = clazz.getAnnotation(AuditTable.class);
if (versionsTable != null) {
versioningData.versionsTable = versionsTable;
AuditTable auditTable = clazz.getAnnotation(AuditTable.class);
if (auditTable != null) {
auditData.setAuditTable(auditTable);
} else {
versioningData.versionsTable = getDefaultVersionsTable();
auditData.setAuditTable(getDefaultAuditTable());
}
}
@ -141,28 +201,30 @@ public final class AnnotationsMetadataReader {
// Getting information on secondary tables
SecondaryAuditTable secondaryVersionsTable1 = clazz.getAnnotation(SecondaryAuditTable.class);
if (secondaryVersionsTable1 != null) {
versioningData.secondaryTableDictionary.put(secondaryVersionsTable1.secondaryTableName(),
auditData.getSecondaryTableDictionary().put(secondaryVersionsTable1.secondaryTableName(),
secondaryVersionsTable1.secondaryVersionsTableName());
}
SecondaryAuditTables secondaryVersionsTables = clazz.getAnnotation(SecondaryAuditTables.class);
if (secondaryVersionsTables != null) {
for (SecondaryAuditTable secondaryVersionsTable2 : secondaryVersionsTables.value()) {
versioningData.secondaryTableDictionary.put(secondaryVersionsTable2.secondaryTableName(),
auditData.getSecondaryTableDictionary().put(secondaryVersionsTable2.secondaryTableName(),
secondaryVersionsTable2.secondaryVersionsTableName());
}
}
}
public PersistentClassVersioningData getVersioningData() {
public PersistentClassAuditingData getAuditData() {
if (pc.getClassName() == null) {
return versioningData;
return auditData;
}
readPersistentProperties();
try {
XClass clazz = reflectionManager.classForName(pc.getClassName(), this.getClass());
addDefaultVersioned(clazz);
readDefaultAudited(clazz);
addPropertiesFromClass(clazz);
addVersionsTable(clazz);
addVersionsSecondaryTables(clazz);
@ -170,15 +232,35 @@ public final class AnnotationsMetadataReader {
throw new MappingException(e);
}
return versioningData;
return auditData;
}
private AuditTable getDefaultVersionsTable() {
return new AuditTable() {
public String value() { return ""; }
public String schema() { return ""; }
public String catalog() { return ""; }
public Class<? extends Annotation> annotationType() { return this.getClass(); }
};
private AuditTable defaultAuditTable;
private AuditTable getDefaultAuditTable() {
if (defaultAuditTable == null) {
defaultAuditTable = new AuditTable() {
public String value() { return ""; }
public String schema() { return ""; }
public String catalog() { return ""; }
public Class<? extends Annotation> annotationType() { return this.getClass(); }
};
}
return defaultAuditTable;
}
private AuditJoinTable defaultAuditJoinTable;
private AuditJoinTable getDefaultAuditJoinTable() {
if (defaultAuditJoinTable == null) {
defaultAuditJoinTable = new AuditJoinTable() {
public String name() { return ""; }
public String schema() { return ""; }
public String catalog() { return ""; }
public JoinColumn[] inverseJoinColumns() { return new JoinColumn[0]; }
public Class<? extends Annotation> annotationType() { return this.getClass(); }
};
}
return defaultAuditJoinTable;
}
}

View File

@ -25,12 +25,9 @@ package org.hibernate.envers.configuration.metadata;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.dom4j.Element;
import org.hibernate.envers.ModificationStore;
import org.hibernate.envers.AuditJoinTable;
import org.hibernate.envers.configuration.GlobalConfiguration;
import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
import org.hibernate.envers.entities.EntityConfiguration;
@ -77,8 +74,8 @@ public final class AuditMetadataGenerator {
private Logger log = LoggerFactory.getLogger(AuditMetadataGenerator.class);
public AuditMetadataGenerator(Configuration cfg, GlobalConfiguration globalCfg,
AuditEntitiesConfiguration verEntCfg,
Element revisionInfoRelationMapping) {
AuditEntitiesConfiguration verEntCfg,
Element revisionInfoRelationMapping) {
this.cfg = cfg;
this.globalCfg = globalCfg;
this.verEntCfg = verEntCfg;
@ -106,38 +103,16 @@ public final class AuditMetadataGenerator {
revTypeProperty.addAttribute("type", "org.hibernate.envers.entities.RevisionTypeType");
}
private ModificationStore getStoreForProperty(Property property, PropertyStoreInfo propertyStoreInfo,
List<String> unversionedProperties) {
/*
* Checks if a property is versioned, which is when:
* - the property isn't unversioned
* - the whole entity is versioned, then the default store is not null
* - there is a store defined for this entity, which is when this property is annotated
*/
if (unversionedProperties.contains(property.getName())) {
return null;
}
ModificationStore store = propertyStoreInfo.propertyStores.get(property.getName());
if (store == null) {
return propertyStoreInfo.defaultStore;
}
return store;
}
@SuppressWarnings({"unchecked"})
void addValue(Element parent, String name, Value value, CompositeMapperBuilder currentMapper,
ModificationStore store, String entityName, EntityXmlMappingData xmlMappingData,
AuditJoinTable joinTable, String mapKey, boolean insertable, boolean firstPass) {
void addValue(Element parent, Value value, CompositeMapperBuilder currentMapper, String entityName,
EntityXmlMappingData xmlMappingData, PersistentPropertyAuditingData persistentPropertyAuditingData,
boolean insertable, boolean firstPass) {
Type type = value.getType();
// only first pass
if (firstPass) {
if (basicMetadataGenerator.addBasic(parent, name, value, currentMapper, store, entityName, insertable,
false)) {
if (basicMetadataGenerator.addBasic(parent, persistentPropertyAuditingData, value, currentMapper,
entityName, insertable, false)) {
// The property was mapped by the basic generator.
return;
}
@ -146,50 +121,49 @@ public final class AuditMetadataGenerator {
if (type instanceof ManyToOneType) {
// only second pass
if (!firstPass) {
toOneRelationMetadataGenerator.addToOne(parent, name, value, currentMapper, entityName);
toOneRelationMetadataGenerator.addToOne(parent, persistentPropertyAuditingData, value, currentMapper,
entityName);
}
} else if (type instanceof OneToOneType) {
// only second pass
if (!firstPass) {
toOneRelationMetadataGenerator.addOneToOneNotOwning(name, value, currentMapper, entityName);
toOneRelationMetadataGenerator.addOneToOneNotOwning(persistentPropertyAuditingData, value,
currentMapper, entityName);
}
} else if (type instanceof CollectionType) {
// only second pass
if (!firstPass) {
CollectionMetadataGenerator collectionMetadataGenerator = new CollectionMetadataGenerator(this,
name, (Collection) value, currentMapper, entityName, xmlMappingData, joinTable, mapKey);
(Collection) value, currentMapper, entityName, xmlMappingData,
persistentPropertyAuditingData);
collectionMetadataGenerator.addCollection();
}
} else {
if (firstPass) {
// If we got here in the first pass, it means the basic mapper didn't map it, and none of the
// above branches either.
throwUnsupportedTypeException(type, entityName, name);
throwUnsupportedTypeException(type, entityName, persistentPropertyAuditingData.getName());
}
}
}
@SuppressWarnings({"unchecked"})
private void addProperties(Element parent, Iterator<Property> properties, CompositeMapperBuilder currentMapper,
PersistentClassVersioningData versioningData, String entityName, EntityXmlMappingData xmlMappingData,
PersistentClassAuditingData versioningData, String entityName, EntityXmlMappingData xmlMappingData,
boolean firstPass) {
while (properties.hasNext()) {
Property property = properties.next();
if (!"_identifierMapper".equals(property.getName())) {
ModificationStore store = getStoreForProperty(property, versioningData.propertyStoreInfo,
versioningData.unversionedProperties);
if (store != null) {
addValue(parent, property.getName(), property.getValue(), currentMapper, store, entityName,
xmlMappingData, versioningData.versionsJoinTables.get(property.getName()),
versioningData.mapKeys.get(property.getName()), property.isInsertable(), firstPass);
}
String propertyName = property.getName();
if (versioningData.getPropertyAuditingData(propertyName) != null) {
addValue(parent, property.getValue(), currentMapper, entityName,
xmlMappingData, versioningData.getPropertyAuditingData(propertyName),
property.isInsertable(), firstPass);
}
}
}
@SuppressWarnings({"unchecked"})
private void createJoins(PersistentClass pc, Element parent, PersistentClassVersioningData versioningData) {
private void createJoins(PersistentClass pc, Element parent, PersistentClassAuditingData versioningData) {
Iterator<Join> joins = pc.getJoinIterator();
Map<Join, Element> joinElements = new HashMap<Join, Element>();
@ -201,17 +175,17 @@ public final class AuditMetadataGenerator {
// Determining the table name. If there is no entry in the dictionary, just constructing the table name
// as if it was an entity (by appending/prepending configured strings).
String originalTableName = join.getTable().getName();
String versionedTableName = versioningData.secondaryTableDictionary.get(originalTableName);
String versionedTableName = versioningData.getSecondaryTableDictionary().get(originalTableName);
if (versionedTableName == null) {
versionedTableName = verEntCfg.getVersionsEntityName(originalTableName);
}
String schema = versioningData.versionsTable.schema();
String schema = versioningData.getAuditTable().schema();
if (StringTools.isEmpty(schema)) {
schema = join.getTable().getSchema();
}
String catalog = versioningData.versionsTable.catalog();
String catalog = versioningData.getAuditTable().catalog();
if (StringTools.isEmpty(catalog)) {
catalog = join.getTable().getCatalog();
}
@ -226,7 +200,7 @@ public final class AuditMetadataGenerator {
}
@SuppressWarnings({"unchecked"})
private void addJoins(PersistentClass pc, CompositeMapperBuilder currentMapper, PersistentClassVersioningData versioningData,
private void addJoins(PersistentClass pc, CompositeMapperBuilder currentMapper, PersistentClassAuditingData versioningData,
String entityName, EntityXmlMappingData xmlMappingData,boolean firstPass) {
Iterator<Join> joins = pc.getJoinIterator();
@ -240,14 +214,14 @@ public final class AuditMetadataGenerator {
}
@SuppressWarnings({"unchecked"})
public void generateFirstPass(PersistentClass pc, PersistentClassVersioningData versioningData,
public void generateFirstPass(PersistentClass pc, PersistentClassAuditingData versioningData,
EntityXmlMappingData xmlMappingData) {
String schema = versioningData.versionsTable.schema();
String schema = versioningData.getAuditTable().schema();
if (StringTools.isEmpty(schema)) {
schema = pc.getTable().getSchema();
}
String catalog = versioningData.versionsTable.catalog();
String catalog = versioningData.getAuditTable().catalog();
if (StringTools.isEmpty(catalog)) {
catalog = pc.getTable().getCatalog();
}
@ -322,7 +296,7 @@ public final class AuditMetadataGenerator {
}
@SuppressWarnings({"unchecked"})
public void generateSecondPass(PersistentClass pc, PersistentClassVersioningData versioningData,
public void generateSecondPass(PersistentClass pc, PersistentClassAuditingData versioningData,
EntityXmlMappingData xmlMappingData) {
String entityName = pc.getEntityName();

View File

@ -49,28 +49,28 @@ import org.hibernate.util.StringHelper;
* @author Adam Warski (adam at warski dot org)
*/
public final class BasicMetadataGenerator {
boolean addBasic(Element parent, String name, Value value, CompositeMapperBuilder mapper,
ModificationStore store, String entityName, boolean insertable, boolean key) {
boolean addBasic(Element parent, PersistentPropertyAuditingData persistentPropertyAuditingData, Value value,
CompositeMapperBuilder mapper, String entityName, boolean insertable, boolean key) {
Type type = value.getType();
if (type instanceof ComponentType) {
addComponent(parent, name, value, mapper, entityName, key);
addComponent(parent, persistentPropertyAuditingData, value, mapper, entityName, key);
return true;
} else {
return addBasicNoComponent(parent, name, value, mapper, store, insertable, key);
return addBasicNoComponent(parent, persistentPropertyAuditingData, value, mapper, insertable, key);
}
}
boolean addBasicNoComponent(Element parent, String name, Value value, SimpleMapperBuilder mapper,
ModificationStore store, boolean insertable, boolean key) {
boolean addBasicNoComponent(Element parent, PersistentPropertyAuditingData persistentPropertyAuditingData,
Value value, SimpleMapperBuilder mapper, boolean insertable, boolean key) {
Type type = value.getType();
if (type instanceof ImmutableType || type instanceof MutableType) {
addSimpleValue(parent, name, value, mapper, store, insertable, key);
addSimpleValue(parent, persistentPropertyAuditingData, value, mapper, insertable, key);
} else if (type instanceof CustomType || type instanceof CompositeCustomType) {
addCustomValue(parent, name, value, mapper, store, insertable, key);
addCustomValue(parent, persistentPropertyAuditingData, value, mapper, insertable, key);
} else if ("org.hibernate.type.PrimitiveByteArrayBlobType".equals(type.getClass().getName())) {
addSimpleValue(parent, name, value, mapper, store, insertable, key);
addSimpleValue(parent, persistentPropertyAuditingData, value, mapper, insertable, key);
} else {
return false;
}
@ -79,25 +79,25 @@ public final class BasicMetadataGenerator {
}
@SuppressWarnings({"unchecked"})
private void addSimpleValue(Element parent, String name, Value value, SimpleMapperBuilder mapper,
ModificationStore store, boolean insertable, boolean key) {
private void addSimpleValue(Element parent, PersistentPropertyAuditingData persistentPropertyAuditingData,
Value value, SimpleMapperBuilder mapper, boolean insertable, boolean key) {
if (parent != null) {
Element prop_mapping = MetadataTools.addProperty(parent, name,
Element prop_mapping = MetadataTools.addProperty(parent, persistentPropertyAuditingData.getName(),
value.getType().getName(), insertable, key);
MetadataTools.addColumns(prop_mapping, (Iterator<Column>) value.getColumnIterator());
}
// A null mapper means that we only want to add xml mappings
if (mapper != null) {
mapper.add(name, store);
mapper.add(persistentPropertyAuditingData.getPropertyData());
}
}
@SuppressWarnings({"unchecked"})
private void addCustomValue(Element parent, String name, Value value, SimpleMapperBuilder mapper,
ModificationStore store, boolean insertable, boolean key) {
private void addCustomValue(Element parent, PersistentPropertyAuditingData persistentPropertyAuditingData,
Value value, SimpleMapperBuilder mapper, boolean insertable, boolean key) {
if (parent != null) {
Element prop_mapping = MetadataTools.addProperty(parent, name,
Element prop_mapping = MetadataTools.addProperty(parent, persistentPropertyAuditingData.getName(),
null, insertable, key);
//CustomType propertyType = (CustomType) value.getType();
@ -120,7 +120,7 @@ public final class BasicMetadataGenerator {
}
if (mapper != null) {
mapper.add(name, store);
mapper.add(persistentPropertyAuditingData.getPropertyData());
}
}
@ -131,8 +131,8 @@ public final class BasicMetadataGenerator {
}
@SuppressWarnings({"unchecked"})
private void addComponent(Element parent, String name, Value value, CompositeMapperBuilder mapper,
String entityName, boolean key) {
private void addComponent(Element parent, PersistentPropertyAuditingData persistentPropertyAuditingData,
Value value, CompositeMapperBuilder mapper, String entityName, boolean key) {
Element component_mapping = null;
Component prop_component = (Component) value;
@ -157,18 +157,19 @@ public final class BasicMetadataGenerator {
*/
component_mapping = parent.addElement("component");
component_mapping.addAttribute("name", name);
component_mapping.addAttribute("name", persistentPropertyAuditingData.getName());
addComponentClassName(component_mapping, prop_component);
}
CompositeMapperBuilder componentMapper = mapper.addComposite(name);
CompositeMapperBuilder componentMapper = mapper.addComposite(persistentPropertyAuditingData.getPropertyData());
Iterator<Property> properties = (Iterator<Property>) prop_component.getPropertyIterator();
while (properties.hasNext()) {
Property property = properties.next();
addBasic(component_mapping, property.getName(), property.getValue(), componentMapper,
ModificationStore.FULL, entityName, property.isInsertable(), key);
addBasic(component_mapping,
new PersistentPropertyAuditingData(property.getName(), property.getPropertyAccessorName(), ModificationStore.FULL),
property.getValue(), componentMapper, entityName, property.isInsertable(), key);
}
}
}

View File

@ -23,7 +23,6 @@
*/
package org.hibernate.envers.configuration.metadata;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@ -37,7 +36,6 @@ import javax.persistence.JoinColumn;
import org.dom4j.Element;
import org.hibernate.envers.ModificationStore;
import org.hibernate.envers.AuditJoinTable;
import org.hibernate.envers.entities.EntityConfiguration;
import org.hibernate.envers.entities.IdMappingData;
import org.hibernate.envers.entities.mapper.CompositeMapperBuilder;
@ -91,8 +89,7 @@ public final class CollectionMetadataGenerator {
private final CompositeMapperBuilder currentMapper;
private final String referencingEntityName;
private final EntityXmlMappingData xmlMappingData;
private final AuditJoinTable joinTable;
private final String mapKey;
private final PersistentPropertyAuditingData persistentPropertyAuditingData;
private final EntityConfiguration referencingEntityConfiguration;
/**
@ -102,29 +99,28 @@ public final class CollectionMetadataGenerator {
/**
* @param mainGenerator Main generator, giving access to configuration and the basic mapper.
* @param propertyName Name of the property that references the collection in the referencing entity.
* @param propertyValue Value of the collection, as mapped by Hibernate.
* @param currentMapper Mapper, to which the appropriate {@link org.hibernate.envers.entities.mapper.PropertyMapper}
* will be added.
* @param referencingEntityName Name of the entity that owns this collection.
* @param xmlMappingData In case this collection requires a middle table, additional mapping documents will
* be created using this object.
* @param joinTable User data for the middle (join) table. <code>null</code> if the user didn't specify it.
* @param mapKey The value of the name() property of the MapKey annotation on this property. Null, if this
* property isn't annotated with this annotation.
* @param persistentPropertyAuditingData Property auditing (meta-)data. Among other things, holds the name of the
* property that references the collection in the referencing entity, the user data for middle (join)
* table and the value of the <code>@MapKey</code> annotation, if there was one.
*/
public CollectionMetadataGenerator(AuditMetadataGenerator mainGenerator, String propertyName,
public CollectionMetadataGenerator(AuditMetadataGenerator mainGenerator,
Collection propertyValue, CompositeMapperBuilder currentMapper,
String referencingEntityName, EntityXmlMappingData xmlMappingData,
AuditJoinTable joinTable, String mapKey) {
PersistentPropertyAuditingData persistentPropertyAuditingData) {
this.mainGenerator = mainGenerator;
this.propertyName = propertyName;
this.propertyValue = propertyValue;
this.currentMapper = currentMapper;
this.referencingEntityName = referencingEntityName;
this.xmlMappingData = xmlMappingData;
this.joinTable = joinTable == null ? getDefaultVersionsJoinTable() : joinTable;
this.mapKey = mapKey;
this.persistentPropertyAuditingData = persistentPropertyAuditingData;
this.propertyName = persistentPropertyAuditingData.getName();
referencingEntityConfiguration = mainGenerator.getEntitiesConfigurations().get(referencingEntityName);
if (referencingEntityConfiguration == null) {
@ -192,7 +188,8 @@ public final class CollectionMetadataGenerator {
// Creating common mapper data.
CommonCollectionMapperData commonCollectionMapperData = new CommonCollectionMapperData(
mainGenerator.getVerEntCfg(), referencedEntityName, propertyName,
mainGenerator.getVerEntCfg(), referencedEntityName,
persistentPropertyAuditingData.getPropertyData(),
referencingIdData, queryGenerator);
// Checking the type of the collection and adding an appropriate mapper.
@ -238,9 +235,9 @@ public final class CollectionMetadataGenerator {
// Generating the name of the middle table
String versionsMiddleTableName;
String versionsMiddleEntityName;
if (!StringTools.isEmpty(joinTable.name())) {
versionsMiddleTableName = joinTable.name();
versionsMiddleEntityName = joinTable.name();
if (!StringTools.isEmpty(persistentPropertyAuditingData.getJoinTable().name())) {
versionsMiddleTableName = persistentPropertyAuditingData.getJoinTable().name();
versionsMiddleEntityName = persistentPropertyAuditingData.getJoinTable().name();
} else {
String middleTableName = getMiddleTableName(propertyValue, referencingEntityName);
versionsMiddleTableName = mainGenerator.getVerEntCfg().getVersionsTableName(null, middleTableName);
@ -304,7 +301,7 @@ public final class CollectionMetadataGenerator {
// Generating the element mapping.
// ******
MiddleComponentData elementComponentData = addValueToMiddleTable(propertyValue.getElement(), middleEntityXml,
queryGeneratorBuilder, referencedPrefix, joinTable.inverseJoinColumns());
queryGeneratorBuilder, referencedPrefix, persistentPropertyAuditingData.getJoinTable().inverseJoinColumns());
// ******
// Generating the index mapping, if an index exists.
@ -319,7 +316,9 @@ public final class CollectionMetadataGenerator {
// Creating common data
CommonCollectionMapperData commonCollectionMapperData = new CommonCollectionMapperData(
mainGenerator.getVerEntCfg(), versionsMiddleEntityName, propertyName, referencingIdData, queryGenerator);
mainGenerator.getVerEntCfg(), versionsMiddleEntityName,
persistentPropertyAuditingData.getPropertyData(),
referencingIdData, queryGenerator);
// Checking the type of the collection and adding an appropriate mapper.
addMapper(commonCollectionMapperData, elementComponentData, indexComponentData);
@ -333,6 +332,7 @@ public final class CollectionMetadataGenerator {
private MiddleComponentData addIndex(Element middleEntityXml, QueryGeneratorBuilder queryGeneratorBuilder) {
if (propertyValue instanceof IndexedCollection) {
IndexedCollection indexedValue = (IndexedCollection) propertyValue;
String mapKey = persistentPropertyAuditingData.getMapKey();
if (mapKey == null) {
// This entity doesn't specify a javax.persistence.MapKey. Mapping it to the middle entity.
return addValueToMiddleTable(indexedValue.getIndex(), middleEntityXml,
@ -347,7 +347,8 @@ public final class CollectionMetadataGenerator {
referencedIdMapping.getIdMapper()), currentIndex);
} else {
// The key of the map is a property of the entity.
return new MiddleComponentData(new MiddleMapKeyPropertyComponentMapper(mapKey), currentIndex);
return new MiddleComponentData(new MiddleMapKeyPropertyComponentMapper(mapKey,
persistentPropertyAuditingData.getAccessType()), currentIndex);
}
}
} else {
@ -399,8 +400,9 @@ public final class CollectionMetadataGenerator {
queryGeneratorBuilder.getCurrentIndex());
} else {
// Last but one parameter: collection components are always insertable
boolean mapped = mainGenerator.getBasicMetadataGenerator().addBasicNoComponent(xmlMapping, prefix, value, null,
ModificationStore.FULL, true, true);
boolean mapped = mainGenerator.getBasicMetadataGenerator().addBasicNoComponent(xmlMapping,
new PersistentPropertyAuditingData(prefix, "field", ModificationStore.FULL), value, null,
true, true);
if (mapped) {
// Simple values are always stored in the first item of the array returned by the query generator.
@ -417,25 +419,31 @@ public final class CollectionMetadataGenerator {
MiddleComponentData indexComponentData) {
Type type = propertyValue.getType();
if (type instanceof SortedSetType) {
currentMapper.addComposite(propertyName, new BasicCollectionMapper<Set>(commonCollectionMapperData,
currentMapper.addComposite(persistentPropertyAuditingData.getPropertyData(),
new BasicCollectionMapper<Set>(commonCollectionMapperData,
TreeSet.class, SortedSetProxy.class, elementComponentData));
} else if (type instanceof SetType) {
currentMapper.addComposite(propertyName, new BasicCollectionMapper<Set>(commonCollectionMapperData,
currentMapper.addComposite(persistentPropertyAuditingData.getPropertyData(),
new BasicCollectionMapper<Set>(commonCollectionMapperData,
HashSet.class, SetProxy.class, elementComponentData));
} else if (type instanceof SortedMapType) {
// Indexed collection, so <code>indexComponentData</code> is not null.
currentMapper.addComposite(propertyName, new MapCollectionMapper<Map>(commonCollectionMapperData,
currentMapper.addComposite(persistentPropertyAuditingData.getPropertyData(),
new MapCollectionMapper<Map>(commonCollectionMapperData,
TreeMap.class, SortedMapProxy.class, elementComponentData, indexComponentData));
} else if (type instanceof MapType) {
// Indexed collection, so <code>indexComponentData</code> is not null.
currentMapper.addComposite(propertyName, new MapCollectionMapper<Map>(commonCollectionMapperData,
currentMapper.addComposite(persistentPropertyAuditingData.getPropertyData(),
new MapCollectionMapper<Map>(commonCollectionMapperData,
HashMap.class, MapProxy.class, elementComponentData, indexComponentData));
} else if (type instanceof BagType) {
currentMapper.addComposite(propertyName, new BasicCollectionMapper<List>(commonCollectionMapperData,
currentMapper.addComposite(persistentPropertyAuditingData.getPropertyData(),
new BasicCollectionMapper<List>(commonCollectionMapperData,
ArrayList.class, ListProxy.class, elementComponentData));
} else if (type instanceof ListType) {
// Indexed collection, so <code>indexComponentData</code> is not null.
currentMapper.addComposite(propertyName, new ListCollectionMapper(commonCollectionMapperData,
currentMapper.addComposite(persistentPropertyAuditingData.getPropertyData(),
new ListCollectionMapper(commonCollectionMapperData,
elementComponentData, indexComponentData));
} else {
mainGenerator.throwUnsupportedTypeException(type, referencingEntityName, propertyName);
@ -454,8 +462,10 @@ public final class CollectionMetadataGenerator {
}
private Element createMiddleEntityXml(String versionsMiddleTableName, String versionsMiddleEntityName) {
String schema = StringTools.isEmpty(joinTable.schema()) ? propertyValue.getCollectionTable().getSchema() : joinTable.schema();
String catalog = StringTools.isEmpty(joinTable.catalog()) ? propertyValue.getCollectionTable().getCatalog() : joinTable.catalog();
String schema = StringTools.isEmpty(persistentPropertyAuditingData.getJoinTable().schema()) ?
propertyValue.getCollectionTable().getSchema() : persistentPropertyAuditingData.getJoinTable().schema();
String catalog = StringTools.isEmpty(persistentPropertyAuditingData.getJoinTable().catalog()) ?
propertyValue.getCollectionTable().getCatalog() : persistentPropertyAuditingData.getJoinTable().catalog();
Element middleEntityXml = MetadataTools.createEntity(xmlMappingData.newAdditionalMapping(),
versionsMiddleEntityName, versionsMiddleTableName, schema, catalog, null);
@ -474,16 +484,6 @@ public final class CollectionMetadataGenerator {
return middleEntityXmlId;
}
private AuditJoinTable getDefaultVersionsJoinTable() {
return new AuditJoinTable() {
public String name() { return ""; }
public String schema() { return ""; }
public String catalog() { return ""; }
public JoinColumn[] inverseJoinColumns() { return new JoinColumn[0]; }
public Class<? extends Annotation> annotationType() { return this.getClass(); }
};
}
@SuppressWarnings({"unchecked"})
private String getMappedBy(Collection collectionValue) {
Iterator<Property> assocClassProps =

View File

@ -29,6 +29,7 @@ import org.dom4j.Element;
import org.dom4j.tree.DefaultElement;
import org.hibernate.envers.ModificationStore;
import org.hibernate.envers.entities.IdMappingData;
import org.hibernate.envers.entities.PropertyData;
import org.hibernate.envers.entities.mapper.SimpleMapperBuilder;
import org.hibernate.envers.entities.mapper.id.EmbeddedIdMapper;
import org.hibernate.envers.entities.mapper.id.MultipleIdMapper;
@ -61,8 +62,9 @@ public final class IdMetadataGenerator {
if (!"_identifierMapper".equals(property.getName())) {
if (propertyType instanceof ImmutableType) {
// Last but one parameter: ids are always insertable
mainGenerator.getBasicMetadataGenerator().addBasicNoComponent(parent, property.getName(),
property.getValue(), mapper, ModificationStore.FULL, true, key);
mainGenerator.getBasicMetadataGenerator().addBasicNoComponent(parent,
getIdPersistentPropertyAuditingData(property),
property.getValue(), mapper, true, key);
} else {
throw new MappingException("Type not supported: " + propertyType.getClass().getName());
}
@ -94,7 +96,7 @@ public final class IdMetadataGenerator {
Component id_component = (Component) id_prop.getValue();
mapper = new EmbeddedIdMapper(id_prop.getName(), id_component.getComponentClassName());
mapper = new EmbeddedIdMapper(getIdPropertyData(id_prop), id_component.getComponentClassName());
addIdProperties(rel_id_mapping, (Iterator<Property>) id_component.getPropertyIterator(), mapper, false);
// null mapper - the mapping where already added the first time, now we only want to generate the xml
@ -105,12 +107,14 @@ public final class IdMetadataGenerator {
mapper = new SingleIdMapper();
// Last but one parameter: ids are always insertable
mainGenerator.getBasicMetadataGenerator().addBasicNoComponent(rel_id_mapping, id_prop.getName(),
id_prop.getValue(), mapper, ModificationStore.FULL, true, false);
mainGenerator.getBasicMetadataGenerator().addBasicNoComponent(rel_id_mapping,
getIdPersistentPropertyAuditingData(id_prop),
id_prop.getValue(), mapper, true, false);
// null mapper - the mapping where already added the first time, now we only want to generate the xml
mainGenerator.getBasicMetadataGenerator().addBasicNoComponent(orig_id_mapping, id_prop.getName(),
id_prop.getValue(), null, ModificationStore.FULL, true, true);
mainGenerator.getBasicMetadataGenerator().addBasicNoComponent(orig_id_mapping,
getIdPersistentPropertyAuditingData(id_prop),
id_prop.getValue(), null, true, true);
}
orig_id_mapping.addAttribute("name", mainGenerator.getVerEntCfg().getOriginalIdPropName());
@ -120,4 +124,13 @@ public final class IdMetadataGenerator {
return new IdMappingData(mapper, orig_id_mapping, rel_id_mapping);
}
private PropertyData getIdPropertyData(Property property) {
return new PropertyData(property.getName(), property.getPropertyAccessorName(), ModificationStore.FULL);
}
private PersistentPropertyAuditingData getIdPersistentPropertyAuditingData(Property property) {
return new PersistentPropertyAuditingData(property.getName(), property.getPropertyAccessorName(),
ModificationStore.FULL);
}
}

View File

@ -25,24 +25,48 @@ package org.hibernate.envers.configuration.metadata;
import java.util.Map;
import org.hibernate.envers.ModificationStore;
import org.hibernate.envers.AuditTable;
import org.hibernate.envers.tools.Tools;
/**
* @author Adam Warski (adam at warski dot org)
* @author Sebastian Komander
*/
public class PropertyStoreInfo {
// Not null if the whole class is versioned
public ModificationStore defaultStore;
// Maps property names to their stores defined in per-field versioned annotations
public Map<String, ModificationStore> propertyStores;
public PropertyStoreInfo(Map<String, ModificationStore> propertyStores) {
this.propertyStores = propertyStores;
public class PersistentClassAuditingData {
public PersistentClassAuditingData() {
properties = Tools.newHashMap();
secondaryTableDictionary = Tools.newHashMap();
}
public PropertyStoreInfo(ModificationStore defaultStore, Map<String, ModificationStore> propertyStores) {
this.defaultStore = defaultStore;
this.propertyStores = propertyStores;
private Map<String, PersistentPropertyAuditingData> properties;
private AuditTable auditTable;
private Map<String, String> secondaryTableDictionary;
public Map<String, PersistentPropertyAuditingData> getProperties() {
return properties;
}
public PersistentPropertyAuditingData getPropertyAuditingData(String propertyName) {
return properties.get(propertyName);
}
public Map<String, String> getSecondaryTableDictionary() {
return secondaryTableDictionary;
}
public AuditTable getAuditTable() {
return auditTable;
}
public void setAuditTable(AuditTable auditTable) {
this.auditTable = auditTable;
}
public boolean isAudited() {
if (properties.size() > 0) {
return true;
} else {
return false;
}
}
}

View File

@ -1,67 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.envers.configuration.metadata;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hibernate.envers.ModificationStore;
import org.hibernate.envers.AuditJoinTable;
import org.hibernate.envers.AuditTable;
/**
* @author Adam Warski (adam at warski dot org)
* @author Sebastian Komander
*/
public class PersistentClassVersioningData {
public PersistentClassVersioningData() {
propertyStoreInfo = new PropertyStoreInfo(new HashMap<String, ModificationStore>());
secondaryTableDictionary = new HashMap<String, String>();
unversionedProperties = new ArrayList<String>();
versionsJoinTables = new HashMap<String, AuditJoinTable>();
mapKeys = new HashMap<String, String>();
}
public PropertyStoreInfo propertyStoreInfo;
public AuditTable versionsTable;
public Map<String, String> secondaryTableDictionary;
public List<String> unversionedProperties;
/**
* A map from property names to custom join tables definitions.
*/
public Map<String, AuditJoinTable> versionsJoinTables;
/**
* A map from property names to the value of the related property names in a map key annotation. An empty string,
* if the property name is not specified in the mapkey annotation.
*/
public Map<String, String> mapKeys;
public boolean isVersioned() {
if (propertyStoreInfo.propertyStores.size() > 0) { return true; }
if (propertyStoreInfo.defaultStore != null) { return true; }
return false;
}
}

View File

@ -0,0 +1,93 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.envers.configuration.metadata;
import org.hibernate.envers.ModificationStore;
import org.hibernate.envers.AuditJoinTable;
import org.hibernate.envers.entities.PropertyData;
/**
* @author Adam Warski (adam at warski dot org)
*/
public class PersistentPropertyAuditingData {
private String name;
private ModificationStore store;
private String mapKey;
private AuditJoinTable joinTable;
private String accessType;
public PersistentPropertyAuditingData() {
}
public PersistentPropertyAuditingData(String name, String accessType, ModificationStore store) {
this.name = name;
this.accessType = accessType;
this.store = store;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ModificationStore getStore() {
return store;
}
public void setStore(ModificationStore store) {
this.store = store;
}
public String getMapKey() {
return mapKey;
}
public void setMapKey(String mapKey) {
this.mapKey = mapKey;
}
public AuditJoinTable getJoinTable() {
return joinTable;
}
public void setJoinTable(AuditJoinTable joinTable) {
this.joinTable = joinTable;
}
public String getAccessType() {
return accessType;
}
public void setAccessType(String accessType) {
this.accessType = accessType;
}
public PropertyData getPropertyData() {
return new PropertyData(name, accessType, store);
}
}

View File

@ -26,6 +26,7 @@ package org.hibernate.envers.configuration.metadata;
import org.dom4j.Element;
import org.hibernate.envers.entities.EntityConfiguration;
import org.hibernate.envers.entities.IdMappingData;
import org.hibernate.envers.entities.PropertyData;
import org.hibernate.envers.entities.mapper.CompositeMapperBuilder;
import org.hibernate.envers.entities.mapper.id.IdMapper;
import org.hibernate.envers.entities.mapper.relation.OneToOneNotOwningMapper;
@ -48,7 +49,8 @@ public final class ToOneRelationMetadataGenerator {
}
@SuppressWarnings({"unchecked"})
void addToOne(Element parent, String name, Value value, CompositeMapperBuilder mapper, String entityName) {
void addToOne(Element parent, PersistentPropertyAuditingData persistentPropertyAuditingData, Value value,
CompositeMapperBuilder mapper, String entityName) {
String referencedEntityName = ((ToOne) value).getReferencedEntityName();
EntityConfiguration configuration = mainGenerator.getEntitiesConfigurations().get(referencedEntityName);
@ -58,28 +60,31 @@ public final class ToOneRelationMetadataGenerator {
IdMappingData idMapping = configuration.getIdMappingData();
String lastPropertyPrefix = name + "_";
String lastPropertyPrefix = persistentPropertyAuditingData.getName() + "_";
// Generating the id mapper for the relation
IdMapper relMapper = idMapping.getIdMapper().prefixMappedProperties(lastPropertyPrefix);
// Storing information about this relation
mainGenerator.getEntitiesConfigurations().get(entityName).addToOneRelation(name, referencedEntityName, relMapper);
mainGenerator.getEntitiesConfigurations().get(entityName).addToOneRelation(
persistentPropertyAuditingData.getName(), referencedEntityName, relMapper);
// Adding an element to the mapping corresponding to the references entity id's
Element properties = (Element) idMapping.getXmlRelationMapping().clone();
properties.addAttribute("name", name);
properties.addAttribute("name", persistentPropertyAuditingData.getName());
MetadataTools.prefixNamesInPropertyElement(properties, lastPropertyPrefix,
MetadataTools.getColumnNameIterator(value.getColumnIterator()), false);
parent.add(properties);
// Adding mapper for the id
mapper.addComposite(name, new ToOneIdMapper(relMapper, name, referencedEntityName));
PropertyData propertyData = persistentPropertyAuditingData.getPropertyData();
mapper.addComposite(propertyData, new ToOneIdMapper(relMapper, propertyData, referencedEntityName));
}
@SuppressWarnings({"unchecked"})
void addOneToOneNotOwning(String name, Value value, CompositeMapperBuilder mapper, String entityName) {
void addOneToOneNotOwning(PersistentPropertyAuditingData persistentPropertyAuditingData, Value value,
CompositeMapperBuilder mapper, String entityName) {
OneToOne propertyValue = (OneToOne) value;
String owningReferencePropertyName = propertyValue.getReferencedPropertyName(); // mappedBy
@ -102,11 +107,13 @@ public final class ToOneRelationMetadataGenerator {
IdMapper ownedIdMapper = ownedIdMapping.getIdMapper().prefixMappedProperties(lastPropertyPrefix);
// Storing information about this relation
mainGenerator.getEntitiesConfigurations().get(entityName).addToOneNotOwningRelation(name, owningReferencePropertyName,
mainGenerator.getEntitiesConfigurations().get(entityName).addToOneNotOwningRelation(
persistentPropertyAuditingData.getName(), owningReferencePropertyName,
referencedEntityName, ownedIdMapper);
// Adding mapper for the id
mapper.addComposite(name, new OneToOneNotOwningMapper(owningReferencePropertyName,
referencedEntityName, name));
PropertyData propertyData = persistentPropertyAuditingData.getPropertyData();
mapper.addComposite(propertyData, new OneToOneNotOwningMapper(owningReferencePropertyName,
referencedEntityName, propertyData));
}
}

View File

@ -67,7 +67,7 @@ public class EntityInstantiator {
// First mapping the primary key
IdMapper idMapper = verCfg.getEntCfg().get(entityName).getIdMapper();
Map originalId = (Map) versionsEntity.get(verCfg.getVerEntCfg().getOriginalIdPropName());
Map originalId = (Map) versionsEntity.get(verCfg.getAuditEntCfg().getOriginalIdPropName());
Object primaryKey = idMapper.mapToIdFromMap(originalId);

View File

@ -0,0 +1,70 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.envers.entities;
import org.hibernate.envers.ModificationStore;
/**
* Holds information on a property that is audited.
* @author Adam Warski (adam at warski dot org)
*/
public class PropertyData {
private final String name;
private final String accessType;
private final ModificationStore store;
/**
* Copies the given property data, except the name.
* @param newName New name.
* @param propertyData Property data to copy the rest of properties from.
*/
public PropertyData(String newName, PropertyData propertyData) {
this.name = newName;
this.accessType = propertyData.accessType;
this.store = propertyData.store;
}
/**
* @param name Name of the property.
* @param accessType Accessor type for this property.
* @param store How this property should be stored.
*/
public PropertyData(String name, String accessType, ModificationStore store) {
this.name = name;
this.accessType = accessType;
this.store = store;
}
public String getName() {
return name;
}
public String getAccessType() {
return accessType;
}
public ModificationStore getStore() {
return store;
}
}

View File

@ -23,10 +23,12 @@
*/
package org.hibernate.envers.entities.mapper;
import org.hibernate.envers.entities.PropertyData;
/**
* @author Adam Warski (adam at warski dot org)
*/
public interface CompositeMapperBuilder extends SimpleMapperBuilder {
public CompositeMapperBuilder addComposite(String propertyName);
public void addComposite(String propertyName, PropertyMapper propertyMapper);
public CompositeMapperBuilder addComposite(PropertyData propertyData);
public void addComposite(PropertyData propertyData, PropertyMapper propertyMapper);
}

View File

@ -28,7 +28,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hibernate.envers.ModificationStore;
import org.hibernate.envers.entities.PropertyData;
import org.hibernate.envers.configuration.AuditConfiguration;
import org.hibernate.envers.exception.AuditException;
import org.hibernate.envers.reader.AuditReaderImplementor;
@ -43,29 +43,29 @@ import org.hibernate.util.ReflectHelper;
* @author Adam Warski (adam at warski dot org)
*/
public class MapPropertyMapper implements PropertyMapper, CompositeMapperBuilder {
private String propertyName;
private PropertyData propertyData;
private ExtendedPropertyMapper delegate;
public MapPropertyMapper(String propertyName) {
this.propertyName = propertyName;
public MapPropertyMapper(PropertyData propertyData) {
this.propertyData = propertyData;
this.delegate = new MultiPropertyMapper();
}
public void add(String propertyName, ModificationStore modStore) {
delegate.add(propertyName, modStore);
public void add(PropertyData propertyData) {
delegate.add(propertyData);
}
public CompositeMapperBuilder addComposite(String propertyName) {
return delegate.addComposite(propertyName);
public CompositeMapperBuilder addComposite(PropertyData propertyData) {
return delegate.addComposite(propertyData);
}
public void addComposite(String propertyName, PropertyMapper propertyMapper) {
delegate.addComposite(propertyName, propertyMapper);
public void addComposite(PropertyData propertyData, PropertyMapper propertyMapper) {
delegate.addComposite(propertyData, propertyMapper);
}
public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
Map<String, Object> newData = new HashMap<String, Object>();
data.put(propertyName, newData);
data.put(propertyData.getName(), newData);
return delegate.mapToMapFromEntity(newData, newObj, oldObj);
}
@ -75,13 +75,13 @@ public class MapPropertyMapper implements PropertyMapper, CompositeMapperBuilder
return;
}
Getter getter = ReflectionTools.getGetter(obj.getClass(), propertyName);
Setter setter = ReflectionTools.getSetter(obj.getClass(), propertyName);
Getter getter = ReflectionTools.getGetter(obj.getClass(), propertyData);
Setter setter = ReflectionTools.getSetter(obj.getClass(), propertyData);
try {
Object subObj = ReflectHelper.getDefaultConstructor(getter.getReturnType()).newInstance();
setter.set(obj, subObj, null);
delegate.mapToEntityFromMap(verCfg, subObj, (Map) data.get(propertyName), primaryKey, versionsReader, revision);
delegate.mapToEntityFromMap(verCfg, subObj, (Map) data.get(propertyData.getName()), primaryKey, versionsReader, revision);
} catch (Exception e) {
throw new AuditException(e);
}

View File

@ -24,14 +24,14 @@
package org.hibernate.envers.entities.mapper;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hibernate.envers.ModificationStore;
import org.hibernate.envers.entities.PropertyData;
import org.hibernate.envers.configuration.AuditConfiguration;
import org.hibernate.envers.reader.AuditReaderImplementor;
import org.hibernate.envers.tools.reflection.ReflectionTools;
import org.hibernate.envers.tools.Tools;
import org.hibernate.MappingException;
import org.hibernate.collection.PersistentCollection;
@ -41,31 +41,36 @@ import org.hibernate.property.Getter;
* @author Adam Warski (adam at warski dot org)
*/
public class MultiPropertyMapper implements ExtendedPropertyMapper {
protected Map<String, PropertyMapper> properties;
protected final Map<PropertyData, PropertyMapper> properties;
private final Map<String, PropertyData> propertyDatas;
public MultiPropertyMapper() {
properties = new HashMap<String, PropertyMapper>();
properties = Tools.newHashMap();
propertyDatas = Tools.newHashMap();
}
public void add(String propertyName, ModificationStore modStore) {
public void add(PropertyData propertyData) {
SinglePropertyMapper single = new SinglePropertyMapper();
single.add(propertyName, modStore);
properties.put(propertyName, single);
single.add(propertyData);
properties.put(propertyData, single);
propertyDatas.put(propertyData.getName(), propertyData);
}
public CompositeMapperBuilder addComposite(String propertyName) {
if (properties.get(propertyName) != null) {
throw new MappingException("Mapping for " + propertyName + " already added!");
public CompositeMapperBuilder addComposite(PropertyData propertyData) {
if (properties.get(propertyData) != null) {
throw new MappingException("Mapping for " + propertyData.getName() + " already added!");
}
MapPropertyMapper mapperBuilder = new MapPropertyMapper(propertyName);
properties.put(propertyName, mapperBuilder);
MapPropertyMapper mapperBuilder = new MapPropertyMapper(propertyData);
properties.put(propertyData, mapperBuilder);
propertyDatas.put(propertyData.getName(), propertyData);
return mapperBuilder;
}
public void addComposite(String propertyName, PropertyMapper propertyMapper) {
properties.put(propertyName, propertyMapper);
public void addComposite(PropertyData propertyData, PropertyMapper propertyMapper) {
properties.put(propertyData, propertyMapper);
propertyDatas.put(propertyData.getName(), propertyData);
}
private Object getAtIndexOrNull(Object[] array, int index) { return array == null ? null : array[index]; }
@ -75,8 +80,8 @@ public class MultiPropertyMapper implements ExtendedPropertyMapper {
for (int i=0; i<propertyNames.length; i++) {
String propertyName = propertyNames[i];
if (properties.containsKey(propertyName)) {
ret |= properties.get(propertyName).mapToMapFromEntity(data,
if (propertyDatas.containsKey(propertyName)) {
ret |= properties.get(propertyDatas.get(propertyName)).mapToMapFromEntity(data,
getAtIndexOrNull(newState, i),
getAtIndexOrNull(oldState, i));
}
@ -87,17 +92,17 @@ public class MultiPropertyMapper implements ExtendedPropertyMapper {
public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
boolean ret = false;
for (String propertyName : properties.keySet()) {
for (PropertyData propertyData : properties.keySet()) {
Getter getter;
if (newObj != null) {
getter = ReflectionTools.getGetter(newObj.getClass(), propertyName);
getter = ReflectionTools.getGetter(newObj.getClass(), propertyData);
} else if (oldObj != null) {
getter = ReflectionTools.getGetter(oldObj.getClass(), propertyName);
getter = ReflectionTools.getGetter(oldObj.getClass(), propertyData);
} else {
return false;
}
ret |= properties.get(propertyName).mapToMapFromEntity(data,
ret |= properties.get(propertyData).mapToMapFromEntity(data,
newObj == null ? null : getter.get(newObj),
oldObj == null ? null : getter.get(oldObj));
}
@ -105,9 +110,10 @@ public class MultiPropertyMapper implements ExtendedPropertyMapper {
return ret;
}
public void mapToEntityFromMap(AuditConfiguration verCfg, Object obj, Map data, Object primaryKey, AuditReaderImplementor versionsReader, Number revision) {
for (String propertyName : properties.keySet()) {
properties.get(propertyName).mapToEntityFromMap(verCfg, obj, data, primaryKey, versionsReader, revision);
public void mapToEntityFromMap(AuditConfiguration verCfg, Object obj, Map data, Object primaryKey,
AuditReaderImplementor versionsReader, Number revision) {
for (PropertyMapper mapper : properties.values()) {
mapper.mapToEntityFromMap(verCfg, obj, data, primaryKey, versionsReader, revision);
}
}
@ -115,7 +121,7 @@ public class MultiPropertyMapper implements ExtendedPropertyMapper {
PersistentCollection newColl,
Serializable oldColl,
Serializable id) {
PropertyMapper mapper = properties.get(referencingPropertyName);
PropertyMapper mapper = properties.get(propertyDatas.get(referencingPropertyName));
if (mapper != null) {
return mapper.mapCollectionChanges(referencingPropertyName, newColl, oldColl, id);
} else {

View File

@ -23,11 +23,11 @@
*/
package org.hibernate.envers.entities.mapper;
import org.hibernate.envers.ModificationStore;
import org.hibernate.envers.entities.PropertyData;
/**
* @author Adam Warski (adam at warski dot org)
*/
public interface SimpleMapperBuilder {
public void add(String propertyName, ModificationStore modStore);
public void add(PropertyData propertyData);
}

View File

@ -27,7 +27,7 @@ import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.hibernate.envers.ModificationStore;
import org.hibernate.envers.entities.PropertyData;
import org.hibernate.envers.configuration.AuditConfiguration;
import org.hibernate.envers.exception.AuditException;
import org.hibernate.envers.reader.AuditReaderImplementor;
@ -42,37 +42,38 @@ import org.hibernate.property.Setter;
* @author Adam Warski (adam at warski dot org)
*/
public class SinglePropertyMapper implements PropertyMapper, SimpleMapperBuilder {
private String propertyName;
private PropertyData propertyData;
public SinglePropertyMapper() { }
public void add(String propertyName, ModificationStore modStore) {
if (this.propertyName != null) {
public void add(PropertyData propertyData) {
if (this.propertyData != null) {
throw new AuditException("Only one property can be added!");
}
this.propertyName = propertyName;
this.propertyData = propertyData;
}
public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
data.put(propertyName, newObj);
data.put(propertyData.getName(), newObj);
return !Tools.objectsEqual(newObj, oldObj);
}
public void mapToEntityFromMap(AuditConfiguration verCfg, Object obj, Map data, Object primaryKey, AuditReaderImplementor versionsReader, Number revision) {
public void mapToEntityFromMap(AuditConfiguration verCfg, Object obj, Map data, Object primaryKey,
AuditReaderImplementor versionsReader, Number revision) {
if (data == null || obj == null) {
return;
}
Setter setter = ReflectionTools.getSetter(obj.getClass(), propertyName);
setter.set(obj, data.get(propertyName), null);
Setter setter = ReflectionTools.getSetter(obj.getClass(), propertyData);
setter.set(obj, data.get(propertyData.getName()), null);
}
public List<PersistentCollectionChangeData> mapCollectionChanges(String referencingPropertyName,
PersistentCollection newColl,
Serializable oldColl,
Serializable id) {
PersistentCollection newColl,
Serializable oldColl,
Serializable id) {
return null;
}

View File

@ -27,7 +27,7 @@ import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.hibernate.envers.ModificationStore;
import org.hibernate.envers.entities.PropertyData;
import org.hibernate.envers.configuration.AuditConfiguration;
import org.hibernate.envers.reader.AuditReaderImplementor;
@ -80,15 +80,15 @@ public class SubclassPropertyMapper implements ExtendedPropertyMapper {
}
}
public CompositeMapperBuilder addComposite(String propertyName) {
return main.addComposite(propertyName);
public CompositeMapperBuilder addComposite(PropertyData propertyData) {
return main.addComposite(propertyData);
}
public void addComposite(String propertyName, PropertyMapper propertyMapper) {
main.addComposite(propertyName, propertyMapper);
public void addComposite(PropertyData propertyData, PropertyMapper propertyMapper) {
main.addComposite(propertyData, propertyMapper);
}
public void add(String propertyName, ModificationStore modStore) {
main.add(propertyName, modStore);
public void add(PropertyData propertyData) {
main.add(propertyData);
}
}

View File

@ -23,27 +23,27 @@
*/
package org.hibernate.envers.entities.mapper.id;
import java.util.LinkedHashMap;
import java.util.Map;
import org.hibernate.envers.ModificationStore;
import org.hibernate.envers.entities.PropertyData;
import org.hibernate.envers.exception.AuditException;
import org.hibernate.envers.tools.Tools;
/**
* @author Adam Warski (adam at warski dot org)
*/
public abstract class AbstractCompositeIdMapper extends AbstractIdMapper implements SimpleIdMapperBuilder {
protected Map<String, SingleIdMapper> ids;
protected Map<PropertyData, SingleIdMapper> ids;
protected String compositeIdClass;
protected AbstractCompositeIdMapper(String compositeIdClass) {
ids = new LinkedHashMap<String, SingleIdMapper>();
ids = Tools.newLinkedHashMap();
this.compositeIdClass = compositeIdClass;
}
public void add(String propertyName, ModificationStore modStore) {
ids.put(propertyName, new SingleIdMapper(propertyName));
public void add(PropertyData propertyData) {
ids.put(propertyData, new SingleIdMapper(propertyData));
}
public Object mapToIdFromMap(Map data) {

View File

@ -30,6 +30,7 @@ import java.util.Map;
import org.hibernate.envers.exception.AuditException;
import org.hibernate.envers.tools.reflection.ReflectionTools;
import org.hibernate.envers.entities.PropertyData;
import org.hibernate.property.Getter;
import org.hibernate.property.Setter;
@ -39,12 +40,12 @@ import org.hibernate.util.ReflectHelper;
* @author Adam Warski (adam at warski dot org)
*/
public class EmbeddedIdMapper extends AbstractCompositeIdMapper implements SimpleIdMapperBuilder {
private String idPropertyName;
private PropertyData idPropertyData;
public EmbeddedIdMapper(String idPropertyName, String compositeIdClass) {
public EmbeddedIdMapper(PropertyData idPropertyData, String compositeIdClass) {
super(compositeIdClass);
this.idPropertyName = idPropertyName;
this.idPropertyData = idPropertyData;
}
public void mapToMapFromId(Map<String, Object> data, Object obj) {
@ -58,7 +59,7 @@ public class EmbeddedIdMapper extends AbstractCompositeIdMapper implements Simpl
return;
}
Getter getter = ReflectionTools.getGetter(obj.getClass(), idPropertyName);
Getter getter = ReflectionTools.getGetter(obj.getClass(), idPropertyData);
mapToMapFromId(data, getter.get(obj));
}
@ -67,8 +68,8 @@ public class EmbeddedIdMapper extends AbstractCompositeIdMapper implements Simpl
return;
}
Getter getter = ReflectionTools.getGetter(obj.getClass(), idPropertyName);
Setter setter = ReflectionTools.getSetter(obj.getClass(), idPropertyName);
Getter getter = ReflectionTools.getGetter(obj.getClass(), idPropertyData);
Setter setter = ReflectionTools.getSetter(obj.getClass(), idPropertyData);
try {
Object subObj = ReflectHelper.getDefaultConstructor(getter.getReturnType()).newInstance();
@ -83,10 +84,12 @@ public class EmbeddedIdMapper extends AbstractCompositeIdMapper implements Simpl
}
public IdMapper prefixMappedProperties(String prefix) {
EmbeddedIdMapper ret = new EmbeddedIdMapper(idPropertyName, compositeIdClass);
EmbeddedIdMapper ret = new EmbeddedIdMapper(idPropertyData, compositeIdClass);
for (String propertyName : ids.keySet()) {
ret.ids.put(propertyName, new SingleIdMapper(propertyName, prefix + propertyName));
for (PropertyData propertyData : ids.keySet()) {
String propertyName = propertyData.getName();
ret.ids.put(propertyData, new SingleIdMapper(propertyName,
new PropertyData(prefix + propertyName, propertyData)));
}
return ret;
@ -97,7 +100,7 @@ public class EmbeddedIdMapper extends AbstractCompositeIdMapper implements Simpl
return null;
}
Getter getter = ReflectionTools.getGetter(data.getClass(), idPropertyName);
Getter getter = ReflectionTools.getGetter(data.getClass(), idPropertyData);
return getter.get(data);
}

View File

@ -29,6 +29,7 @@ import java.util.List;
import java.util.Map;
import org.hibernate.envers.exception.AuditException;
import org.hibernate.envers.entities.PropertyData;
/**
* @author Adam Warski (adam at warski dot org)
@ -57,8 +58,10 @@ public class MultipleIdMapper extends AbstractCompositeIdMapper implements Simpl
public IdMapper prefixMappedProperties(String prefix) {
MultipleIdMapper ret = new MultipleIdMapper(compositeIdClass);
for (String propertyName : ids.keySet()) {
ret.ids.put(propertyName, new SingleIdMapper(propertyName, prefix + propertyName));
for (PropertyData propertyData : ids.keySet()) {
String propertyName = propertyData.getName();
ret.ids.put(propertyData, new SingleIdMapper(propertyName,
new PropertyData(prefix + propertyName, propertyData)));
}
return ret;

View File

@ -27,7 +27,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.hibernate.envers.ModificationStore;
import org.hibernate.envers.entities.PropertyData;
import org.hibernate.envers.exception.AuditException;
import org.hibernate.envers.tools.reflection.ReflectionTools;
@ -39,28 +39,28 @@ import org.hibernate.property.Setter;
*/
public class SingleIdMapper extends AbstractIdMapper implements SimpleIdMapperBuilder {
private String beanPropertyName;
private String propertyName;
private PropertyData propertyData;
public SingleIdMapper() {
}
public SingleIdMapper(String beanPropertyName, String propertyName) {
public SingleIdMapper(String beanPropertyName, PropertyData propertyData) {
this.beanPropertyName = beanPropertyName;
this.propertyName = propertyName;
this.propertyData = propertyData;
}
public SingleIdMapper(String propertyName) {
this.beanPropertyName = propertyName;
this.propertyName = propertyName;
public SingleIdMapper(PropertyData propertyData) {
this.beanPropertyName = propertyData.getName();
this.propertyData = propertyData;
}
public void add(String propertyName, ModificationStore modStore) {
if (this.propertyName != null) {
public void add(PropertyData propertyData) {
if (this.propertyData != null) {
throw new AuditException("Only one property can be added!");
}
this.propertyName = propertyName;
this.beanPropertyName = propertyName;
this.propertyData = propertyData;
this.beanPropertyName = propertyData.getName();
}
public void mapToEntityFromMap(Object obj, Map data) {
@ -68,8 +68,8 @@ public class SingleIdMapper extends AbstractIdMapper implements SimpleIdMapperBu
return;
}
Setter setter = ReflectionTools.getSetter(obj.getClass(), beanPropertyName);
setter.set(obj, data.get(propertyName), null);
Setter setter = ReflectionTools.getSetter(obj.getClass(), beanPropertyName, propertyData.getAccessType());
setter.set(obj, data.get(propertyData.getName()), null);
}
public Object mapToIdFromMap(Map data) {
@ -77,7 +77,7 @@ public class SingleIdMapper extends AbstractIdMapper implements SimpleIdMapperBu
return null;
}
return data.get(propertyName);
return data.get(propertyData.getName());
}
public Object mapToIdFromEntity(Object data) {
@ -85,22 +85,22 @@ public class SingleIdMapper extends AbstractIdMapper implements SimpleIdMapperBu
return null;
}
Getter getter = ReflectionTools.getGetter(data.getClass(), beanPropertyName);
Getter getter = ReflectionTools.getGetter(data.getClass(), beanPropertyName, propertyData.getAccessType());
return getter.get(data);
}
public void mapToMapFromId(Map<String, Object> data, Object obj) {
if (data != null) {
data.put(propertyName, obj);
data.put(propertyData.getName(), obj);
}
}
public void mapToMapFromEntity(Map<String, Object> data, Object obj) {
if (obj == null) {
data.put(propertyName, null);
data.put(propertyData.getName(), null);
} else {
Getter getter = ReflectionTools.getGetter(obj.getClass(), beanPropertyName);
data.put(propertyName, getter.get(obj));
Getter getter = ReflectionTools.getGetter(obj.getClass(), beanPropertyName, propertyData.getAccessType());
data.put(propertyData.getName(), getter.get(obj));
}
}
@ -109,19 +109,20 @@ public class SingleIdMapper extends AbstractIdMapper implements SimpleIdMapperBu
return;
}
Getter getter = ReflectionTools.getGetter(objFrom.getClass(), beanPropertyName);
Setter setter = ReflectionTools.getSetter(objTo.getClass(), beanPropertyName);
Getter getter = ReflectionTools.getGetter(objFrom.getClass(), beanPropertyName, propertyData.getAccessType());
Setter setter = ReflectionTools.getSetter(objTo.getClass(), beanPropertyName, propertyData.getAccessType());
setter.set(objTo, getter.get(objFrom), null);
}
public IdMapper prefixMappedProperties(String prefix) {
return new SingleIdMapper(propertyName, prefix + propertyName);
return new SingleIdMapper(propertyData.getName(),
new PropertyData(prefix + propertyData.getName(), propertyData));
}
public List<QueryParameterData> mapToQueryParametersFromId(Object obj) {
List<QueryParameterData> ret = new ArrayList<QueryParameterData>();
ret.add(new QueryParameterData(propertyName, obj));
ret.add(new QueryParameterData(propertyData.getName(), obj));
return ret;
}

View File

@ -101,7 +101,8 @@ public abstract class AbstractCollectionMapper<T> implements PropertyMapper {
public List<PersistentCollectionChangeData> mapCollectionChanges(String referencingPropertyName,
PersistentCollection newColl,
Serializable oldColl, Serializable id) {
if (!commonCollectionMapperData.getCollectionReferencingPropertyName().equals(referencingPropertyName)) {
if (!commonCollectionMapperData.getCollectionReferencingPropertyData().getName()
.equals(referencingPropertyName)) {
return null;
}
@ -138,7 +139,7 @@ public abstract class AbstractCollectionMapper<T> implements PropertyMapper {
public void mapToEntityFromMap(AuditConfiguration verCfg, Object obj, Map data, Object primaryKey,
AuditReaderImplementor versionsReader, Number revision) {
Setter setter = ReflectionTools.getSetter(obj.getClass(),
commonCollectionMapperData.getCollectionReferencingPropertyName());
commonCollectionMapperData.getCollectionReferencingPropertyData());
try {
setter.set(obj, proxyConstructor.newInstance(getInitializor(verCfg, versionsReader, primaryKey, revision)), null);
} catch (InstantiationException e) {

View File

@ -25,6 +25,7 @@ package org.hibernate.envers.entities.mapper.relation;
import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
import org.hibernate.envers.entities.mapper.relation.query.RelationQueryGenerator;
import org.hibernate.envers.entities.PropertyData;
/**
* Data that is used by all collection mappers, regardless of the type.
@ -33,16 +34,16 @@ import org.hibernate.envers.entities.mapper.relation.query.RelationQueryGenerato
public final class CommonCollectionMapperData {
private final AuditEntitiesConfiguration verEntCfg;
private final String versionsMiddleEntityName;
private final String collectionReferencingPropertyName;
private final PropertyData collectionReferencingPropertyData;
private final MiddleIdData referencingIdData;
private final RelationQueryGenerator queryGenerator;
public CommonCollectionMapperData(AuditEntitiesConfiguration verEntCfg, String versionsMiddleEntityName,
String collectionReferencingPropertyName, MiddleIdData referencingIdData,
PropertyData collectionReferencingPropertyData, MiddleIdData referencingIdData,
RelationQueryGenerator queryGenerator) {
this.verEntCfg = verEntCfg;
this.versionsMiddleEntityName = versionsMiddleEntityName;
this.collectionReferencingPropertyName = collectionReferencingPropertyName;
this.collectionReferencingPropertyData = collectionReferencingPropertyData;
this.referencingIdData = referencingIdData;
this.queryGenerator = queryGenerator;
}
@ -55,8 +56,8 @@ public final class CommonCollectionMapperData {
return versionsMiddleEntityName;
}
public String getCollectionReferencingPropertyName() {
return collectionReferencingPropertyName;
public PropertyData getCollectionReferencingPropertyData() {
return collectionReferencingPropertyData;
}
public MiddleIdData getReferencingIdData() {

View File

@ -31,6 +31,7 @@ import javax.persistence.NoResultException;
import org.hibernate.envers.configuration.AuditConfiguration;
import org.hibernate.envers.entities.mapper.PersistentCollectionChangeData;
import org.hibernate.envers.entities.mapper.PropertyMapper;
import org.hibernate.envers.entities.PropertyData;
import org.hibernate.envers.exception.AuditException;
import org.hibernate.envers.query.AuditRestrictions;
import org.hibernate.envers.reader.AuditReaderImplementor;
@ -46,12 +47,13 @@ import org.hibernate.property.Setter;
public class OneToOneNotOwningMapper implements PropertyMapper {
private String owningReferencePropertyName;
private String owningEntityName;
private String propertyName;
private PropertyData propertyData;
public OneToOneNotOwningMapper(String owningReferencePropertyName, String owningEntityName, String propertyName) {
public OneToOneNotOwningMapper(String owningReferencePropertyName, String owningEntityName,
PropertyData propertyData) {
this.owningReferencePropertyName = owningReferencePropertyName;
this.owningEntityName = owningEntityName;
this.propertyName = propertyName;
this.propertyData = propertyData;
}
public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
@ -77,7 +79,7 @@ public class OneToOneNotOwningMapper implements PropertyMapper {
", " + owningReferencePropertyName + ")");
}
Setter setter = ReflectionTools.getSetter(obj.getClass(), propertyName);
Setter setter = ReflectionTools.getSetter(obj.getClass(), propertyData);
setter.set(obj, value, null);
}

View File

@ -33,6 +33,7 @@ import org.hibernate.envers.entities.mapper.PersistentCollectionChangeData;
import org.hibernate.envers.entities.mapper.PropertyMapper;
import org.hibernate.envers.entities.mapper.id.IdMapper;
import org.hibernate.envers.entities.mapper.relation.lazy.ToOneDelegateSessionImplementor;
import org.hibernate.envers.entities.PropertyData;
import org.hibernate.envers.reader.AuditReaderImplementor;
import org.hibernate.envers.tools.Tools;
import org.hibernate.envers.tools.reflection.ReflectionTools;
@ -45,18 +46,18 @@ import org.hibernate.property.Setter;
*/
public class ToOneIdMapper implements PropertyMapper {
private final IdMapper delegate;
private final String propertyName;
private final PropertyData propertyData;
private final String referencedEntityName;
public ToOneIdMapper(IdMapper delegate, String propertyName, String referencedEntityName) {
public ToOneIdMapper(IdMapper delegate, PropertyData propertyData, String referencedEntityName) {
this.delegate = delegate;
this.propertyName = propertyName;
this.propertyData = propertyData;
this.referencedEntityName = referencedEntityName;
}
public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
HashMap<String, Object> newData = new HashMap<String, Object>();
data.put(propertyName, newData);
data.put(propertyData.getName(), newData);
delegate.mapToMapFromEntity(newData, newObj);
@ -69,7 +70,7 @@ public class ToOneIdMapper implements PropertyMapper {
return;
}
Object entityId = delegate.mapToIdFromMap((Map) data.get(propertyName));
Object entityId = delegate.mapToIdFromMap((Map) data.get(propertyData.getName()));
Object value;
if (entityId == null) {
value = null;
@ -84,7 +85,7 @@ public class ToOneIdMapper implements PropertyMapper {
}
}
Setter setter = ReflectionTools.getSetter(obj.getClass(), propertyName);
Setter setter = ReflectionTools.getSetter(obj.getClass(), propertyData);
setter.set(obj, value, null);
}

View File

@ -35,17 +35,19 @@ import org.hibernate.envers.tools.reflection.ReflectionTools;
* so <code>mapToMapFromObject</code> is empty.
* @author Adam Warski (adam at warski dot org)
*/
public final class MiddleMapKeyPropertyComponentMapper implements MiddleComponentMapper {
public class MiddleMapKeyPropertyComponentMapper implements MiddleComponentMapper {
private final String propertyName;
private final String accessType;
public MiddleMapKeyPropertyComponentMapper(String propertyName) {
public MiddleMapKeyPropertyComponentMapper(String propertyName, String accessType) {
this.propertyName = propertyName;
this.accessType = accessType;
}
public Object mapToObjectFromFullMap(EntityInstantiator entityInstantiator, Map<String, Object> data,
Object dataObject, Number revision) {
// dataObject is not null, as this mapper can only be used in an index.
return ReflectionTools.getGetter(dataObject.getClass(), propertyName).get(dataObject);
return ReflectionTools.getGetter(dataObject.getClass(), propertyName, accessType).get(dataObject);
}
public void mapToMapFromObject(Map<String, Object> data, Object obj) {

View File

@ -124,6 +124,6 @@ public class RevisionProperty implements AuditProjection {
}
public Triple<String, String, Boolean> getData(AuditConfiguration verCfg) {
return Triple.make(null, verCfg.getVerEntCfg().getRevisionPropPath(), false);
return Triple.make(null, verCfg.getAuditEntCfg().getRevisionPropPath(), false);
}
}

View File

@ -42,6 +42,6 @@ public class RevisionTypeProperty implements AuditProjection {
}
public Triple<String, String, Boolean> getData(AuditConfiguration verCfg) {
return Triple.make(null, verCfg.getVerEntCfg().getRevisionTypePropName(), false);
return Triple.make(null, verCfg.getAuditEntCfg().getRevisionTypePropName(), false);
}
}

View File

@ -39,6 +39,6 @@ public class IdentifierEqVersionsExpression implements AuditCriterion {
public void addToQuery(AuditConfiguration verCfg, String entityName, QueryBuilder qb, Parameters parameters) {
verCfg.getEntCfg().get(entityName).getIdMapper()
.addIdEqualsToQuery(parameters, id, verCfg.getVerEntCfg().getOriginalIdPropName(), true);
.addIdEqualsToQuery(parameters, id, verCfg.getAuditEntCfg().getOriginalIdPropName(), true);
}
}

View File

@ -40,6 +40,6 @@ public class RevisionVersionsExpression implements AuditCriterion {
}
public void addToQuery(AuditConfiguration verCfg, String entityName, QueryBuilder qb, Parameters parameters) {
parameters.addWhereWithParam(verCfg.getVerEntCfg().getRevisionPropPath(), op, value);
parameters.addWhereWithParam(verCfg.getAuditEntCfg().getRevisionPropPath(), op, value);
}
}

View File

@ -73,7 +73,7 @@ public abstract class AbstractVersionsQuery implements AuditQuery {
entityInstantiator = new EntityInstantiator(verCfg, versionsReader);
entityName = cls.getName();
versionsEntityName = verCfg.getVerEntCfg().getVersionsEntityName(entityName);
versionsEntityName = verCfg.getAuditEntCfg().getVersionsEntityName(entityName);
qb = new QueryBuilder(versionsEntityName, "e");
}
@ -84,8 +84,6 @@ public abstract class AbstractVersionsQuery implements AuditQuery {
qb.build(querySb, queryParamValues);
System.out.println("QUERY: " + querySb.toString());
Query query = versionsReader.getSession().createQuery(querySb.toString());
for (Map.Entry<String, Object> paramValue : queryParamValues.entrySet()) {
query.setParameter(paramValue.getKey(), paramValue.getValue());

View File

@ -59,7 +59,7 @@ public class EntitiesAtRevisionQuery extends AbstractVersionsQuery {
QueryBuilder maxRevQb = qb.newSubQueryBuilder(versionsEntityName, "e2");
AuditEntitiesConfiguration verEntCfg = verCfg.getVerEntCfg();
AuditEntitiesConfiguration verEntCfg = verCfg.getAuditEntCfg();
String revisionPropertyPath = verEntCfg.getRevisionPropPath();
String originalIdPropertyName = verEntCfg.getOriginalIdPropName();

View File

@ -54,7 +54,7 @@ public class RevisionsOfEntityQuery extends AbstractVersionsQuery {
}
private Number getRevisionNumber(Map versionsEntity) {
AuditEntitiesConfiguration verEntCfg = verCfg.getVerEntCfg();
AuditEntitiesConfiguration verEntCfg = verCfg.getAuditEntCfg();
String originalId = verEntCfg.getOriginalIdPropName();
String revisionPropertyName = verEntCfg.getRevisionPropName();
@ -71,7 +71,7 @@ public class RevisionsOfEntityQuery extends AbstractVersionsQuery {
@SuppressWarnings({"unchecked"})
public List list() throws AuditException {
AuditEntitiesConfiguration verEntCfg = verCfg.getVerEntCfg();
AuditEntitiesConfiguration verEntCfg = verCfg.getAuditEntCfg();
/*
The query that should be executed in the versions table:
@ -97,8 +97,8 @@ public class RevisionsOfEntityQuery extends AbstractVersionsQuery {
}
if (!selectEntitiesOnly) {
qb.addFrom(verCfg.getVerEntCfg().getRevisionInfoEntityName(), "r");
qb.getRootParameters().addWhere(verCfg.getVerEntCfg().getRevisionPropPath(), true, "=", "r.id", false);
qb.addFrom(verCfg.getAuditEntCfg().getRevisionInfoEntityName(), "r");
qb.getRootParameters().addWhere(verCfg.getAuditEntCfg().getRevisionPropPath(), true, "=", "r.id", false);
}
List<Object> queryResult = buildAndExecuteQuery();

View File

@ -37,7 +37,7 @@ public class RevisionVersionsOrder implements AuditOrder {
}
public Pair<String, Boolean> getData(AuditConfiguration verCfg) {
String revisionPropPath = verCfg.getVerEntCfg().getRevisionPropPath();
String revisionPropPath = verCfg.getAuditEntCfg().getRevisionPropPath();
return Pair.make(revisionPropPath, asc);
}
}

View File

@ -45,7 +45,7 @@ public class RevisionVersionsProjection implements AuditProjection {
}
public Triple<String, String, Boolean> getData(AuditConfiguration verCfg) {
String revisionPropPath = verCfg.getVerEntCfg().getRevisionPropPath();
String revisionPropPath = verCfg.getAuditEntCfg().getRevisionPropPath();
switch (type) {
case MAX: return Triple.make("max", revisionPropPath, false);

View File

@ -24,6 +24,7 @@
package org.hibernate.envers.revisioninfo;
import org.hibernate.envers.RevisionListener;
import org.hibernate.envers.entities.PropertyData;
import org.hibernate.envers.tools.reflection.ReflectionTools;
import org.hibernate.MappingException;
@ -41,11 +42,11 @@ public class DefaultRevisionInfoGenerator implements RevisionInfoGenerator {
public DefaultRevisionInfoGenerator(String revisionInfoEntityName, Class<?> revisionInfoClass,
Class<? extends RevisionListener> listenerClass,
String revisionInfoTimestampName) {
PropertyData revisionInfoTimestampData) {
this.revisionInfoEntityName = revisionInfoEntityName;
this.revisionInfoClass = revisionInfoClass;
revisionTimestampSetter = ReflectionTools.getSetter(revisionInfoClass, revisionInfoTimestampName);
revisionTimestampSetter = ReflectionTools.getSetter(revisionInfoClass, revisionInfoTimestampData);
if (!listenerClass.equals(RevisionListener.class)) {
// This is not the default value.

View File

@ -24,6 +24,7 @@
package org.hibernate.envers.revisioninfo;
import org.hibernate.envers.tools.reflection.ReflectionTools;
import org.hibernate.envers.entities.PropertyData;
import org.hibernate.property.Getter;
@ -33,8 +34,8 @@ import org.hibernate.property.Getter;
*/
public class RevisionInfoNumberReader {
private final Getter revisionIdGetter;
public RevisionInfoNumberReader(Class<?> revisionInfoClass, String revisionInfoIdName) {
revisionIdGetter = ReflectionTools.getGetter(revisionInfoClass, revisionInfoIdName);
public RevisionInfoNumberReader(Class<?> revisionInfoClass, PropertyData revisionInfoIdData) {
revisionIdGetter = ReflectionTools.getGetter(revisionInfoClass, revisionInfoIdData);
}
public Number getRevisionNumber(Object revision) {

View File

@ -51,7 +51,7 @@ public abstract class AbstractAuditWorkUnit implements AuditWorkUnit {
}
protected void fillDataWithId(Map<String, Object> data, Object revision, RevisionType revisionType) {
AuditEntitiesConfiguration entitiesCfg = verCfg.getVerEntCfg();
AuditEntitiesConfiguration entitiesCfg = verCfg.getAuditEntCfg();
Map<String, Object> originalId = new HashMap<String, Object>();
originalId.put(entitiesCfg.getRevisionPropName(), revision);
@ -79,7 +79,7 @@ public abstract class AbstractAuditWorkUnit implements AuditWorkUnit {
public void undo(Session session) {
if (isPerformed()) {
session.delete(verCfg.getVerEntCfg().getVersionsEntityName(getEntityName()), performedData);
session.delete(verCfg.getAuditEntCfg().getVersionsEntityName(getEntityName()), performedData);
session.flush();
}
}

View File

@ -58,7 +58,7 @@ public class AddWorkUnit extends AbstractAuditWorkUnit implements AuditWorkUnit
verCfg.getEntCfg().get(getEntityName()).getPropertyMapper().map(data, propertyNames, state, null);
session.save(verCfg.getVerEntCfg().getVersionsEntityName(getEntityName()), data);
session.save(verCfg.getAuditEntCfg().getVersionsEntityName(getEntityName()), data);
setPerformed(data);
}

View File

@ -54,7 +54,7 @@ public class CollectionChangeWorkUnit extends AbstractAuditWorkUnit implements A
verCfg.getEntCfg().get(getEntityName()).getPropertyMapper().mapToMapFromEntity(data, entity, null);
session.save(verCfg.getVerEntCfg().getVersionsEntityName(getEntityName()), data);
session.save(verCfg.getAuditEntCfg().getVersionsEntityName(getEntityName()), data);
setPerformed(data);
}

View File

@ -48,7 +48,7 @@ public class DelWorkUnit extends AbstractAuditWorkUnit implements AuditWorkUnit
Map<String, Object> data = new HashMap<String, Object>();
fillDataWithId(data, revisionData, RevisionType.DEL);
session.save(verCfg.getVerEntCfg().getVersionsEntityName(getEntityName()), data);
session.save(verCfg.getAuditEntCfg().getVersionsEntityName(getEntityName()), data);
setPerformed(data);
}

View File

@ -56,7 +56,7 @@ public class ModWorkUnit extends AbstractAuditWorkUnit implements AuditWorkUnit
public void perform(Session session, Object revisionData) {
fillDataWithId(data, revisionData, RevisionType.MOD);
session.save(verCfg.getVerEntCfg().getVersionsEntityName(getEntityName()), data);
session.save(verCfg.getAuditEntCfg().getVersionsEntityName(getEntityName()), data);
setPerformed(data);
}

View File

@ -58,7 +58,7 @@ public class PersistentCollectionChangeWorkUnit extends AbstractAuditWorkUnit im
@SuppressWarnings({"unchecked"})
public void perform(Session session, Object revisionData) {
AuditEntitiesConfiguration entitiesCfg = verCfg.getVerEntCfg();
AuditEntitiesConfiguration entitiesCfg = verCfg.getAuditEntCfg();
for (PersistentCollectionChangeData persistentCollectionChangeData : collectionChanges) {
// Setting the revision number

View File

@ -23,11 +23,7 @@
*/
package org.hibernate.envers.tools;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* @author Adam Warski (adam at warski dot org)
@ -37,6 +33,14 @@ public class Tools {
return new HashMap<K,V>();
}
public static <E> Set<E> newHashSet() {
return new HashSet<E>();
}
public static <K,V> Map<K,V> newLinkedHashMap() {
return new LinkedHashMap<K,V>();
}
public static boolean objectsEqual(Object obj1, Object obj2) {
if (obj1 == null) {
return obj2 == null;

View File

@ -29,12 +29,9 @@ import org.hibernate.envers.exception.AuditException;
import org.hibernate.envers.tools.ConcurrentReferenceHashMap;
import org.hibernate.envers.tools.Pair;
import static org.hibernate.envers.tools.Pair.make;
import org.hibernate.envers.entities.PropertyData;
import org.hibernate.property.BasicPropertyAccessor;
import org.hibernate.property.Getter;
import org.hibernate.property.PropertyAccessor;
import org.hibernate.property.Setter;
import org.hibernate.util.ReflectHelper;
import org.hibernate.property.*;
/**
* @author Adam Warski (adam at warski dot org)
@ -49,8 +46,6 @@ public class ReflectionTools {
ConcurrentReferenceHashMap.ReferenceType.SOFT,
ConcurrentReferenceHashMap.ReferenceType.SOFT);
private static final PropertyAccessor BASIC_PROPERTY_ACCESSOR = new BasicPropertyAccessor();
public static Class<?> loadClass(String name) {
try {
return Thread.currentThread().getContextClassLoader().loadClass(name);
@ -59,11 +54,19 @@ public class ReflectionTools {
}
}
public static Getter getGetter(Class cls, String propertyName) {
private static PropertyAccessor getAccessor(String accessorType) {
return PropertyAccessorFactory.getPropertyAccessor(accessorType);
}
public static Getter getGetter(Class cls, PropertyData propertyData) {
return getGetter(cls, propertyData.getName(), propertyData.getAccessType());
}
public static Getter getGetter(Class cls, String propertyName, String accessorType) {
Pair<Class, String> key = make(cls, propertyName);
Getter value = getterCache.get(key);
if (value == null) {
value = ReflectHelper.getGetter(cls, propertyName);
value = getAccessor(accessorType).getGetter(cls, propertyName);
// It's ok if two getters are generated concurrently
getterCache.put(key, value);
}
@ -71,11 +74,15 @@ public class ReflectionTools {
return value;
}
public static Setter getSetter(Class cls, String propertyName) {
public static Setter getSetter(Class cls, PropertyData propertyData) {
return getSetter(cls, propertyData.getName(), propertyData.getAccessType());
}
public static Setter getSetter(Class cls, String propertyName, String accessorType) {
Pair<Class, String> key = make(cls, propertyName);
Setter value = setterCache.get(key);
if (value == null) {
value = BASIC_PROPERTY_ACCESSOR.getSetter(cls, propertyName);
value = getAccessor(accessorType).getSetter(cls, propertyName);
// It's ok if two setters are generated concurrently
setterCache.put(key, value);
}

View File

@ -0,0 +1,74 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.envers.test.integration.accesstype;
import java.util.Arrays;
import javax.persistence.EntityManager;
import org.hibernate.envers.test.AbstractEntityTest;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.hibernate.ejb.Ejb3Configuration;
/**
* @author Adam Warski (adam at warski dot org)
*/
public class FieldAccessType extends AbstractEntityTest {
private Integer id1;
public void configure(Ejb3Configuration cfg) {
cfg.addAnnotatedClass(FieldAccessTypeEntity.class);
}
@BeforeClass(dependsOnMethods = "init")
public void initData() {
EntityManager em = getEntityManager();
em.getTransaction().begin();
FieldAccessTypeEntity fate = new FieldAccessTypeEntity("data");
em.persist(fate);
id1 = fate.readId();
em.getTransaction().commit();
em.getTransaction().begin();
fate = em.find(FieldAccessTypeEntity.class, id1);
fate.writeData("data2");
em.getTransaction().commit();
}
@Test
public void testRevisionsCounts() {
assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(FieldAccessTypeEntity.class, id1));
}
@Test
public void testHistoryOfId1() {
FieldAccessTypeEntity ver1 = new FieldAccessTypeEntity(id1, "data");
FieldAccessTypeEntity ver2 = new FieldAccessTypeEntity(id1, "data2");
assert getVersionsReader().find(FieldAccessTypeEntity.class, id1, 1).equals(ver1);
assert getVersionsReader().find(FieldAccessTypeEntity.class, id1, 2).equals(ver2);
}
}

View File

@ -0,0 +1,99 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.envers.test.integration.accesstype;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.hibernate.envers.Audited;
/**
* @author Adam Warski (adam at warski dot org)
*/
@Entity
public class FieldAccessTypeEntity {
@Id
@GeneratedValue
private Integer id;
@Audited
private String data;
public FieldAccessTypeEntity() {
}
public FieldAccessTypeEntity(String data) {
this.data = data;
}
public FieldAccessTypeEntity(Integer id, String data) {
this.id = id;
this.data = data;
}
public Integer getId() {
throw new RuntimeException();
}
public void setId(Integer id) {
throw new RuntimeException();
}
public String getData() {
throw new RuntimeException();
}
public void setData(String data) {
throw new RuntimeException();
}
public Integer readId() {
return id;
}
public void writeData(String data) {
this.data = data;
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof FieldAccessTypeEntity)) return false;
FieldAccessTypeEntity that = (FieldAccessTypeEntity) o;
if (data != null ? !data.equals(that.data) : that.data != null) return false;
if (id != null ? !id.equals(that.id) : that.id != null) return false;
return true;
}
public int hashCode() {
int result;
result = (id != null ? id.hashCode() : 0);
result = 31 * result + (data != null ? data.hashCode() : 0);
return result;
}
}

View File

@ -0,0 +1,79 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.envers.test.integration.accesstype;
import java.util.Arrays;
import javax.persistence.EntityManager;
import org.hibernate.envers.test.AbstractEntityTest;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.hibernate.ejb.Ejb3Configuration;
/**
* @author Adam Warski (adam at warski dot org)
*/
public class MixedAccessType extends AbstractEntityTest {
private Integer id1;
public void configure(Ejb3Configuration cfg) {
cfg.addAnnotatedClass(MixedAccessTypeEntity.class);
}
@BeforeClass(dependsOnMethods = "init")
public void initData() {
EntityManager em = getEntityManager();
em.getTransaction().begin();
MixedAccessTypeEntity mate = new MixedAccessTypeEntity("data");
em.persist(mate);
id1 = mate.readId();
em.getTransaction().commit();
em.getTransaction().begin();
mate = em.find(MixedAccessTypeEntity.class, id1);
mate.writeData("data2");
em.getTransaction().commit();
}
@Test
public void testRevisionsCounts() {
assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(MixedAccessTypeEntity.class, id1));
}
@Test
public void testHistoryOfId1() {
MixedAccessTypeEntity ver1 = new MixedAccessTypeEntity(id1, "data");
MixedAccessTypeEntity ver2 = new MixedAccessTypeEntity(id1, "data2");
MixedAccessTypeEntity rev1 = getVersionsReader().find(MixedAccessTypeEntity.class, id1, 1);
MixedAccessTypeEntity rev2 = getVersionsReader().find(MixedAccessTypeEntity.class, id1, 2);
assert rev1.isDataSet();
assert rev2.isDataSet();
assert rev1.equals(ver1);
assert rev2.equals(ver2);
}
}

View File

@ -0,0 +1,111 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.envers.test.integration.accesstype;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Transient;
import org.hibernate.envers.Audited;
import org.hibernate.annotations.AccessType;
/**
* @author Adam Warski (adam at warski dot org)
*/
@Entity
public class MixedAccessTypeEntity {
@Id
@GeneratedValue
private Integer id;
@AccessType("property")
private String data;
@Transient
private boolean dataSet;
public MixedAccessTypeEntity() {
}
public MixedAccessTypeEntity(String data) {
this.data = data;
}
public MixedAccessTypeEntity(Integer id, String data) {
this.id = id;
this.data = data;
}
public Integer getId() {
throw new RuntimeException();
}
public void setId(Integer id) {
throw new RuntimeException();
}
// TODO: this should be on the property. But how to discover in AnnotationsMetadataReader that the
// we should read annotations from fields, even though the access type is "property"?
@Audited
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
dataSet = true;
}
public boolean isDataSet() {
return dataSet;
}
public Integer readId() {
return id;
}
public void writeData(String data) {
this.data = data;
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof MixedAccessTypeEntity)) return false;
MixedAccessTypeEntity that = (MixedAccessTypeEntity) o;
if (data != null ? !data.equals(that.data) : that.data != null) return false;
if (id != null ? !id.equals(that.id) : that.id != null) return false;
return true;
}
public int hashCode() {
int result;
result = (id != null ? id.hashCode() : 0);
result = 31 * result + (data != null ? data.hashCode() : 0);
return result;
}
}

View File

@ -0,0 +1,82 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.envers.test.integration.accesstype;
import java.util.Arrays;
import javax.persistence.EntityManager;
import org.hibernate.envers.test.AbstractEntityTest;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.hibernate.ejb.Ejb3Configuration;
/**
* @author Adam Warski (adam at warski dot org)
*/
public class PropertyAccessType extends AbstractEntityTest {
private Integer id1;
public void configure(Ejb3Configuration cfg) {
cfg.addAnnotatedClass(PropertyAccessTypeEntity.class);
}
@BeforeClass(dependsOnMethods = "init")
public void initData() {
EntityManager em = getEntityManager();
em.getTransaction().begin();
PropertyAccessTypeEntity pate = new PropertyAccessTypeEntity("data");
em.persist(pate);
id1 = pate.getId();
em.getTransaction().commit();
em.getTransaction().begin();
pate = em.find(PropertyAccessTypeEntity.class, id1);
pate.writeData("data2");
em.getTransaction().commit();
}
@Test
public void testRevisionsCounts() {
assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(PropertyAccessTypeEntity.class, id1));
}
@Test
public void testHistoryOfId1() {
PropertyAccessTypeEntity ver1 = new PropertyAccessTypeEntity(id1, "data");
PropertyAccessTypeEntity ver2 = new PropertyAccessTypeEntity(id1, "data2");
PropertyAccessTypeEntity rev1 = getVersionsReader().find(PropertyAccessTypeEntity.class, id1, 1);
PropertyAccessTypeEntity rev2 = getVersionsReader().find(PropertyAccessTypeEntity.class, id1, 2);
assert rev1.isIdSet();
assert rev2.isIdSet();
assert rev1.isDataSet();
assert rev2.isDataSet();
assert rev1.equals(ver1);
assert rev2.equals(ver2);
}
}

View File

@ -0,0 +1,110 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.envers.test.integration.accesstype;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Transient;
import org.hibernate.envers.Audited;
/**
* @author Adam Warski (adam at warski dot org)
*/
@Entity
public class PropertyAccessTypeEntity {
private Integer id;
private String data;
private boolean idSet;
private boolean dataSet;
public PropertyAccessTypeEntity() {
}
public PropertyAccessTypeEntity(String data) {
this.data = data;
}
public PropertyAccessTypeEntity(Integer id, String data) {
this.id = id;
this.data = data;
}
@Id
@GeneratedValue
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
idSet = true;
}
@Audited
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
dataSet = true;
}
@Transient
public boolean isIdSet() {
return idSet;
}
@Transient
public boolean isDataSet() {
return dataSet;
}
public void writeData(String data) {
this.data = data;
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof PropertyAccessTypeEntity)) return false;
PropertyAccessTypeEntity that = (PropertyAccessTypeEntity) o;
if (data != null ? !data.equals(that.data) : that.data != null) return false;
if (id != null ? !id.equals(that.id) : that.id != null) return false;
return true;
}
public int hashCode() {
int result;
result = (id != null ? id.hashCode() : 0);
result = 31 * result + (data != null ? data.hashCode() : 0);
return result;
}
}

View File

@ -17,6 +17,12 @@
<property name="connection.username">sa</property>
<property name="connection.password"></property>
<!--<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="connection.url">jdbc:mysql:///hibernate_tests?useUnicode=true&amp;characterEncoding=UTF-8</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.username">root</property>
<property name="connection.password"></property>-->
<event type="post-insert">
<listener class="org.hibernate.envers.event.VersionsEventListener" />
</event>

View File

@ -3,6 +3,7 @@
<suite name="Envers">
<test name="All">
<packages>
<package name="org.hibernate.envers.test.integration.accesstype" />
<package name="org.hibernate.envers.test.integration.basic" />
<package name="org.hibernate.envers.test.integration.cache" />
<package name="org.hibernate.envers.test.integration.collection" />