/** * After all meta-data is read, updates calculated fields. This includes: * <ul> * <li>setting {@code forceInsertable} to {@code true} for properties specified by {@code @AuditMappedBy}</li> * </ul> */ public void UpdateCalculatedFields() { foreach (KeyValuePair <PersistentClass, ClassAuditingData> classAuditingDataEntry in persistentClassToAuditingData) { PersistentClass pc = classAuditingDataEntry.Key; ClassAuditingData classAuditingData = classAuditingDataEntry.Value; foreach (String propertyName in classAuditingData.getPropertyNames()) { PropertyAuditingData propertyAuditingData = classAuditingData.getPropertyAuditingData(propertyName); // If a property had the @AuditMappedBy annotation, setting the referenced fields to be always insertable. if (propertyAuditingData.AuditMappedBy != null) { String referencedEntityName = MappingTools.getReferencedEntityName(pc.GetProperty(propertyName).Value); ClassAuditingData referencedClassAuditingData = entityNameToAuditingData[referencedEntityName]; ForcePropertyInsertable(referencedClassAuditingData, propertyAuditingData.AuditMappedBy, pc.EntityName, referencedEntityName); ForcePropertyInsertable(referencedClassAuditingData, propertyAuditingData.PositionMappedBy, pc.EntityName, referencedEntityName); } } } }
private void createJoins(PersistentClass pc, XElement parent, ClassAuditingData auditingData) { var joinElements = new Dictionary <Join, XElement>(); entitiesJoins.Add(pc.EntityName, joinElements); foreach (var join in pc.JoinIterator) { // Checking if any of the join properties are audited if (!checkAnyPropertyAudited(join.PropertyIterator, auditingData)) { continue; } // 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 auditTableName; if (!auditingData.JoinTableDictionary.TryGetValue(join.Table.Name, out auditTableName)) { auditTableName = VerEntCfg.JoinTableName(join); } var schema = GetSchema(auditingData.AuditTable.Schema, join.Table); var catalog = GetCatalog(auditingData.AuditTable.Catalog, join.Table); var joinElement = MetadataTools.CreateJoin(parent, auditTableName, schema, catalog); joinElements.Add(join, joinElement); var joinKey = new XElement(MetadataTools.CreateElementName("key")); joinElement.Add(joinKey); MetadataTools.AddColumns(joinKey, join.Key.ColumnIterator.OfType <Column>()); MetadataTools.AddColumn(joinKey, VerEntCfg.RevisionFieldName, -1, -1, -1, null, false); } }
private void addProperties(XElement parent, IEnumerable <Property> properties, ICompositeMapperBuilder currentMapper, ClassAuditingData auditingData, string entityName, EntityXmlMappingData xmlMappingData, bool firstPass) { foreach (var property in properties) { var propertyName = property.Name; var propertyAuditingData = auditingData.GetPropertyAuditingData(propertyName); if (propertyAuditingData != null) { AddValue(parent, property.Value, currentMapper, entityName, xmlMappingData, propertyAuditingData, property.IsInsertable, firstPass, true); } } }
private bool CheckPropertiesAudited(IEnumerator<Property> properties, ClassAuditingData auditingData) { while (properties.MoveNext()) { Property property = properties.Current; String propertyName = property.Name; PropertyAuditingData propertyAuditingData = auditingData.getPropertyAuditingData(propertyName); if (propertyAuditingData == null) { return false; } } return true; }
//@SuppressWarnings({"unchecked"}) private void AddProperties(XmlElement parent, IEnumerator<Property> properties, ICompositeMapperBuilder currentMapper, ClassAuditingData auditingData, String entityName, EntityXmlMappingData xmlMappingData, bool firstPass) { while (properties.MoveNext()) { Property property = properties.Current; String propertyName = property.Name; PropertyAuditingData propertyAuditingData = auditingData.getPropertyAuditingData(propertyName); if (propertyAuditingData != null) { AddValue(parent, property.Value, currentMapper, entityName, xmlMappingData, propertyAuditingData, property.IsInsertable, firstPass); } } }
private static void forcePropertyInsertable(ClassAuditingData classAuditingData, string propertyName, string entityName, string referencedEntityName) { if (propertyName != null) { if (classAuditingData.GetPropertyAuditingData(propertyName) == null) { throw new MappingException("@AuditMappedBy points to a property that doesn't exist: " + referencedEntityName + "." + propertyName); } log.Debug("Non-insertable property {0}, {1} will be made insertable because a matching @AuditMappedBy was found in the {2} entity.", referencedEntityName, propertyName, entityName); classAuditingData .GetPropertyAuditingData(propertyName) .ForceInsertable = true; } }
public void GenerateSecondPass(PersistentClass pc, ClassAuditingData auditingData, EntityXmlMappingData xmlMappingData) { String entityName = pc.EntityName; if (log.IsDebugEnabled) { log.Debug("Generating first-pass auditing mapping for entity " + entityName + "."); } ICompositeMapperBuilder propertyMapper = EntitiesConfigurations[entityName].PropertyMapper; // Mapping unjoined properties XmlElement parent = xmlMappingData.ClassMapping; AddProperties(parent, (IEnumerator<Property>) pc.UnjoinedPropertyIterator.GetEnumerator(), propertyMapper, auditingData, entityName, xmlMappingData, false); // Mapping joins (second pass) AddJoins(pc, propertyMapper, auditingData, entityName, xmlMappingData, false); }
public void GenerateSecondPass(PersistentClass pc, ClassAuditingData auditingData, EntityXmlMappingData xmlMappingData) { var entityName = pc.EntityName; if (log.IsDebugEnabled) { log.DebugFormat("Generating second-pass auditing mapping for entity {0}.", entityName); } var propertyMapper = EntitiesConfigurations[entityName].PropertyMapper; // Mapping unjoined properties var parent = xmlMappingData.ClassMapping; addProperties(parent, pc.UnjoinedPropertyIterator, propertyMapper, auditingData, entityName, xmlMappingData, false); // Mapping joins (second pass) addJoins(pc, propertyMapper, auditingData, entityName, xmlMappingData, false); }
//@SuppressWarnings({"unchecked"}) private void CreateJoins(PersistentClass pc, XmlElement parent, ClassAuditingData auditingData) { IEnumerator<Join> joins = pc.JoinIterator.GetEnumerator(); IDictionary<Join, XmlElement> JoinElements = new Dictionary<Join, XmlElement>(); entitiesJoins.Add(pc.EntityName, JoinElements); while (joins.MoveNext()) { Join join = joins.Current; // Checking if all of the join properties are audited if (!CheckPropertiesAudited(join.PropertyIterator.GetEnumerator(), auditingData)) { continue; } // 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.Table.Name; String auditTableName = auditingData.SecondaryTableDictionary[originalTableName]; if (auditTableName == null) { auditTableName = VerEntCfg.GetAuditEntityName(originalTableName); } String schema = GetSchema(auditingData.AuditTable.schema, join.Table); String catalog = GetCatalog(auditingData.AuditTable.catalog, join.Table); XmlElement joinElement = MetadataTools.CreateJoin(parent, auditTableName, schema, catalog); JoinElements.Add(join, joinElement); XmlElement joinKey = joinElement.OwnerDocument.CreateElement("key"); joinElement.AppendChild(joinKey); MetadataTools.AddColumns(joinKey, (IEnumerator<ISelectable>)join.Key.ColumnIterator.GetEnumerator()); MetadataTools.AddColumn(joinKey, VerEntCfg.RevisionFieldName, -1, 0, 0, null); } }
public void GenerateFirstPass(PersistentClass pc, ClassAuditingData auditingData, EntityXmlMappingData xmlMappingData, bool isAudited) { var schema = GetSchema(auditingData.AuditTable.Schema, pc.Table); var catalog = GetCatalog(auditingData.AuditTable.Catalog, pc.Table); Func <System.Type, object> factory = auditingData.Factory.Factory.Instantiate; var entityName = pc.EntityName; if (!isAudited) { var _idMapper = idMetadataGenerator.AddId(pc); if (_idMapper == null) { // Unsupported id mapping, e.g. key-many-to-one. If the entity is used in auditing, an exception // will be thrown later on. if (log.IsDebugEnabled) { log.DebugFormat("Unable to create auditing id mapping for entity {0}" + ", because of an unsupported Hibernate id mapping (e.g. key-many-to-one).", entityName); } return; } //ORIG: //IExtendedPropertyMapper propertyMapper = null; //String parentEntityName = null; var _entityCfg = new EntityConfiguration(entityName, pc.ClassName, _idMapper, null, null, factory); NotAuditedEntitiesConfigurations.Add(entityName, _entityCfg); return; } if (log.IsDebugEnabled) { log.DebugFormat("Generating first-pass auditing mapping for entity {0}.", entityName); } var auditEntityName = VerEntCfg.GetAuditEntityName(entityName); var auditTableName = VerEntCfg.AuditTableName(entityName, pc); // Registering the audit entity name, now that it is known AuditEntityNameRegister.Register(auditEntityName); var auditTableData = new AuditTableData(auditEntityName, auditTableName, schema, catalog); // Generating a mapping for the id var idMapper = idMetadataGenerator.AddId(pc); if (idMapper == null) { throw new AuditException("Id mapping for type " + pc.ClassName + " is currently not supported in Envers. If you need composite-id, use 'Components as composite identifiers'."); } var inheritanceType = pc.GetInheritanceType(); // These properties will be read from the mapping data Tuple <XElement, IExtendedPropertyMapper, string> mappingData; // Reading the mapping data depending on inheritance type (if any) switch (inheritanceType) { case InheritanceType.None: mappingData = generateMappingData(pc, xmlMappingData, auditTableData, idMapper); break; case InheritanceType.Single: auditTableData = new AuditTableData(auditEntityName, null, schema, catalog); mappingData = generateInheritanceMappingData(pc, xmlMappingData, auditTableData, "subclass"); break; case InheritanceType.Joined: mappingData = generateInheritanceMappingData(pc, xmlMappingData, auditTableData, "joined-subclass"); // Adding the "key" element with all id columns... var keyMapping = new XElement(MetadataTools.CreateElementName("key")); mappingData.Item1.Add(keyMapping); MetadataTools.AddColumns(keyMapping, pc.Table.PrimaryKey.ColumnIterator); // ... and the revision number column, read from the revision info relation mapping. keyMapping.Add(cloneAndSetupRevisionInfoRelationMapping().Element(MetadataTools.CreateElementName("column"))); break; case InheritanceType.TablePerClass: mappingData = generateInheritanceMappingData(pc, xmlMappingData, auditTableData, "union-subclass"); break; default: throw new AssertionFailure("AuditMetadataGenerator.GenerateFirstPass: Impossible enum value."); } var classMapping = mappingData.Item1; var propertyMapper = mappingData.Item2; var parentEntityName = mappingData.Item3; xmlMappingData.ClassMapping = classMapping; // Mapping unjoined properties addProperties(classMapping, pc.UnjoinedPropertyIterator, propertyMapper, auditingData, pc.EntityName, xmlMappingData, true); // Creating and mapping joins (first pass) createJoins(pc, classMapping, auditingData); addJoins(pc, propertyMapper, auditingData, pc.EntityName, xmlMappingData, true); // Storing the generated configuration var entityCfg = new EntityConfiguration(auditEntityName, pc.ClassName, idMapper, propertyMapper, parentEntityName, factory); EntitiesConfigurations.Add(pc.EntityName, entityCfg); }
private void addJoins(PersistentClass pc, ICompositeMapperBuilder currentMapper, ClassAuditingData auditingData, string entityName, EntityXmlMappingData xmlMappingData, bool firstPass) { var entityJoin = entitiesJoins[entityName]; foreach (var join in pc.JoinIterator) { XElement joinElement; if (entityJoin.TryGetValue(join, out joinElement)) { addProperties(joinElement, join.PropertyIterator, currentMapper, auditingData, entityName, xmlMappingData, firstPass); } } }
private static bool checkAnyPropertyAudited(IEnumerable <Property> properties, ClassAuditingData auditingData) { foreach (var property in properties) { var propertyName = property.Name; var propertyAuditingData = auditingData.GetPropertyAuditingData(propertyName); if (propertyAuditingData != null) { return(true); } } return(false); }
//@SuppressWarnings({"unchecked"}) public void GenerateFirstPass(PersistentClass pc, ClassAuditingData auditingData, EntityXmlMappingData xmlMappingData, bool isAudited) { String schema = GetSchema(auditingData.AuditTable.schema, pc.Table); String catalog = GetCatalog(auditingData.AuditTable.catalog, pc.Table); String entityName = pc.EntityName; if (!isAudited) { IdMappingData _idMapper = idMetadataGenerator.AddId(pc); if (_idMapper == null) { // Unsupported id mapping, e.g. key-many-to-one. If the entity is used in auditing, an exception // will be thrown later on. if (log.IsDebugEnabled) { log.Debug("Unable to create auditing id mapping for entity " + entityName + ", because of an unsupported Hibernate id mapping (e.g. key-many-to-one)."); } return; } //ORIG: //IExtendedPropertyMapper propertyMapper = null; //String parentEntityName = null; EntityConfiguration _entityCfg = new EntityConfiguration(entityName, _idMapper, null, null); NotAuditedEntitiesConfigurations.Add(entityName, _entityCfg); return; } if (log.IsDebugEnabled) { log.Debug("Generating first-pass auditing mapping for entity " + entityName + "."); } String auditEntityName = VerEntCfg.GetAuditEntityName(entityName); String auditTableName = VerEntCfg.GetAuditTableName(entityName, pc.Table.Name); // Registering the audit entity name, now that it is known AuditEntityNameRegister.register(auditEntityName); AuditTableData auditTableData = new AuditTableData(auditEntityName, auditTableName, schema, catalog); // Generating a mapping for the id IdMappingData idMapper = idMetadataGenerator.AddId(pc); InheritanceType.Type inheritanceType = InheritanceType.GetForChild(pc); // These properties will be read from the mapping data XmlElement class_mapping; IExtendedPropertyMapper propertyMapper; String parentEntityName; Triple<XmlElement, IExtendedPropertyMapper, String> mappingData; // Reading the mapping data depending on inheritance type (if any) switch (inheritanceType) { case InheritanceType.Type.NONE: mappingData = GenerateMappingData(pc, xmlMappingData, auditTableData, idMapper); break; case InheritanceType.Type.SINGLE: mappingData = GenerateInheritanceMappingData(pc, xmlMappingData, auditTableData, "subclass"); break; case InheritanceType.Type.JOINED: mappingData = GenerateInheritanceMappingData(pc, xmlMappingData, auditTableData, "joined-subclass"); AddJoinedInheritancePersisterHack(mappingData.First); // Adding the "key" element with all id columns... XmlElement keyMapping = mappingData.First.OwnerDocument.CreateElement("key"); mappingData.First.AppendChild(keyMapping); MetadataTools.AddColumns(keyMapping, (IEnumerator<ISelectable>)pc.Table.PrimaryKey.ColumnIterator.GetEnumerator()); // ... and the revision number column, read from the revision info relation mapping. keyMapping.AppendChild((XmlElement)CloneAndSetupRevisionInfoRelationMapping(keyMapping.OwnerDocument).GetElementsByTagName("column")[0].Clone()); break; case InheritanceType.Type.TABLE_PER_CLASS: mappingData = GenerateInheritanceMappingData(pc, xmlMappingData, auditTableData, "union-subclass"); AddTablePerClassInheritancePersisterHack(mappingData.First); break; default: throw new AssertionFailure("Envers.NET: AuditMetadataGenerator.GenerateFirstPass: Impossible enum value."); } class_mapping = mappingData.First; propertyMapper = mappingData.Second; parentEntityName = mappingData.Third; xmlMappingData.ClassMapping = class_mapping; // Mapping unjoined properties AddProperties(class_mapping, (IEnumerator<Property>)pc.UnjoinedPropertyIterator.GetEnumerator(), propertyMapper, auditingData, pc.EntityName, xmlMappingData, true); // Creating and mapping joins (first pass) CreateJoins(pc, class_mapping, auditingData); AddJoins(pc, propertyMapper, auditingData, pc.EntityName, xmlMappingData, true); // Storing the generated configuration EntityConfiguration entityCfg = new EntityConfiguration(auditEntityName, idMapper, propertyMapper, parentEntityName); EntitiesConfigurations.Add(pc.EntityName, entityCfg); }
//@SuppressWarnings({"unchecked"}) private void AddJoins(PersistentClass pc, ICompositeMapperBuilder currentMapper, ClassAuditingData auditingData, String entityName, EntityXmlMappingData xmlMappingData, bool firstPass) { IEnumerator<Join> joins = pc.JoinIterator.GetEnumerator(); while (joins.MoveNext()) { Join join = joins.Current; XmlElement joinElement = entitiesJoins[entityName][join]; if (joinElement != null) { AddProperties(joinElement, (IEnumerator<Property>)join.PropertyIterator.GetEnumerator(), currentMapper, auditingData, entityName, xmlMappingData, firstPass); } } }
/** * Stores information about auditing meta-data for the given class. * @param pc Persistent class. * @param cad Auditing meta-data for the given class. */ public void AddClassAuditingData(PersistentClass pc, ClassAuditingData cad) { entityNameToAuditingData.Add(pc.EntityName, cad); persistentClassToAuditingData.Add(pc, cad); }
public EntitiesConfigurations Configure(NHibernate.Cfg.Configuration cfg, GlobalConfiguration globalCfg, AuditEntitiesConfiguration verEntCfg, XmlDocument revisionInfoXmlMapping, XmlElement revisionInfoRelationMapping) { // Creating a name register to capture all audit entity names created. AuditEntityNameRegister auditEntityNameRegister = new AuditEntityNameRegister(); //XmlWriter writer = new XmlTextWriter(.. // Sorting the persistent class topologically - superclass always before subclass IEnumerator <PersistentClass> classes = GraphTopologicalSort.Sort <PersistentClass, String>(new PersistentClassGraphDefiner(cfg)).GetEnumerator(); ClassesAuditingData classesAuditingData = new ClassesAuditingData(); IDictionary <PersistentClass, EntityXmlMappingData> xmlMappings = new Dictionary <PersistentClass, EntityXmlMappingData>(); // Reading metadata from annotations while (classes.MoveNext()) { PersistentClass pc = classes.Current; // Collecting information from annotations on the persistent class pc AnnotationsMetadataReader annotationsMetadataReader = new AnnotationsMetadataReader(globalCfg, pc); ClassAuditingData auditData = annotationsMetadataReader.AuditData; classesAuditingData.AddClassAuditingData(pc, auditData); } // Now that all information is read we can update the calculated fields. classesAuditingData.UpdateCalculatedFields(); AuditMetadataGenerator auditMetaGen = new AuditMetadataGenerator(cfg, globalCfg, verEntCfg, revisionInfoRelationMapping, auditEntityNameRegister, classesAuditingData); // First pass foreach (KeyValuePair <PersistentClass, ClassAuditingData> pcDatasEntry in classesAuditingData.GetAllClassAuditedData()) { PersistentClass pc = pcDatasEntry.Key; ClassAuditingData auditData = pcDatasEntry.Value; EntityXmlMappingData xmlMappingData = new EntityXmlMappingData(); if (auditData.IsAudited()) { if (!String.IsNullOrEmpty(auditData.AuditTable.value)) // .getAuditTable().value())) { { verEntCfg.AddCustomAuditTableName(pc.EntityName, auditData.AuditTable.value); } auditMetaGen.GenerateFirstPass(pc, auditData, xmlMappingData, true); } else { auditMetaGen.GenerateFirstPass(pc, auditData, xmlMappingData, false); } xmlMappings.Add(pc, xmlMappingData); } // Second pass foreach (KeyValuePair <PersistentClass, ClassAuditingData> pcDatasEntry in classesAuditingData.GetAllClassAuditedData()) { EntityXmlMappingData xmlMappingData = xmlMappings[pcDatasEntry.Key]; if (pcDatasEntry.Value.IsAudited()) { auditMetaGen.GenerateSecondPass(pcDatasEntry.Key, pcDatasEntry.Value, xmlMappingData); try { //cfg.AddDocument(writer.write(xmlMappingData.MainXmlMapping)); cfg.AddDocument(xmlMappingData.MainXmlMapping); //WriteDocument(xmlMappingData.getMainXmlMapping()); foreach (XmlDocument additionalMapping in xmlMappingData.AdditionalXmlMappings) { //cfg.AddDocument(writer.write(additionalMapping)); cfg.AddDocument(additionalMapping); //WriteDocument(additionalMapping); } } catch (MappingException e) { //catch (DocumentException e) { //?Catalina DocumentException NOT IMPLEMENTED throw new MappingException(e); } } } // Only if there are any versioned classes if (classesAuditingData.GetAllClassAuditedData().Count > 0) { try { if (revisionInfoXmlMapping != null) { //WriteDocument(revisionInfoXmlMapping); //cfg.addDocument(writer.write(revisionInfoXmlMapping)); cfg.AddDocument((revisionInfoXmlMapping)); } } catch (MappingException e) { //catch (DocumentException e) { //?Catalina throw new MappingException(e); } } return(new EntitiesConfigurations(auditMetaGen.EntitiesConfigurations, auditMetaGen.NotAuditedEntitiesConfigurations)); }