private XElement createMiddleEntityXml(string auditMiddleTableName, string auditMiddleEntityName, string where) { var schema = _mainGenerator.GetSchema(_propertyAuditingData.JoinTable.Schema, _propertyValue.CollectionTable); var catalog = _mainGenerator.GetCatalog(_propertyAuditingData.JoinTable.Catalog, _propertyValue.CollectionTable); var middleEntityXml = MetadataTools.CreateEntity(_xmlMappingData.NewAdditionalMapping(), new AuditTableData(auditMiddleEntityName, auditMiddleTableName, schema, catalog), null, false); var middleEntityXmlId = new XElement(MetadataTools.CreateElementName("composite-id"), new XAttribute("name", _mainGenerator.VerEntCfg.OriginalIdPropName)); middleEntityXml.Add(middleEntityXmlId); // If there is a where clause on the relation, adding it to the middle entity. if (where != null) { middleEntityXml.Add(new XAttribute("where", where)); } // Adding the revision number as a foreign key to the revision info entity to the composite id of the // middle table. _mainGenerator.AddRevisionInfoRelation(middleEntityXmlId); // Adding the revision type property to the entity xml. _mainGenerator.AddRevisionType(isEmbeddableElementType() ? middleEntityXmlId : middleEntityXml, middleEntityXml); // All other properties should also be part of the primary key of the middle entity. return(middleEntityXmlId); }
private Triple<XmlElement, IExtendedPropertyMapper, String> GenerateInheritanceMappingData( PersistentClass pc, EntityXmlMappingData xmlMappingData, AuditTableData auditTableData, String inheritanceMappingType) { String extendsEntityName = VerEntCfg.GetAuditEntityName(pc.Superclass.EntityName); XmlElement class_mapping = MetadataTools.CreateSubclassEntity(xmlMappingData.MainXmlMapping, inheritanceMappingType, auditTableData, extendsEntityName, pc.DiscriminatorValue); // The id and revision type is already mapped in the parent // Getting the property mapper of the parent - when mapping properties, they need to be included String parentEntityName = pc.Superclass.EntityName; EntityConfiguration parentConfiguration = EntitiesConfigurations[parentEntityName]; if (parentConfiguration == null) { throw new MappingException("Entity '" + pc.EntityName + "' is audited, but its superclass: '" + parentEntityName + "' is not."); } IExtendedPropertyMapper parentPropertyMapper = parentConfiguration.PropertyMapper; IExtendedPropertyMapper propertyMapper = new SubclassPropertyMapper(new MultiPropertyMapper(), parentPropertyMapper); return Triple<XmlElement, IExtendedPropertyMapper, String>.Make<XmlElement, IExtendedPropertyMapper, String>(class_mapping, propertyMapper, parentEntityName); }
private void addModifiedFlagIfNeeded(XElement parent, PropertyAuditingData propertyAuditingData, bool processModifiedFlag) { if (processModifiedFlag && propertyAuditingData.UsingModifiedFlag) { MetadataTools.AddModifiedFlagProperty(parent, propertyAuditingData.Name, GlobalCfg.ModifiedFlagSuffix); } }
public void AddRevisionType(XmlElement any_mapping) { XmlElement revTypeProperty = MetadataTools.AddProperty(any_mapping, VerEntCfg.RevisionTypePropName, VerEntCfg.RevisionTypePropType, true, false); //TODO Simon Replace with typeof(NHibernate.Envers.Entities.RevisionTypeType).FullName revTypeProperty.SetAttribute("type", "NHibernate.Envers.Entities.RevisionTypeType, Envers.NET"); }
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 Tuple <XElement, IExtendedPropertyMapper, string> generateInheritanceMappingData( PersistentClass pc, EntityXmlMappingData xmlMappingData, AuditTableData auditTableData, string inheritanceMappingType) { var extendsEntityName = VerEntCfg.GetAuditEntityName(pc.Superclass.EntityName); var hasDiscriminator = pc.Discriminator != null; var classMapping = MetadataTools.CreateSubclassEntity(xmlMappingData.MainXmlMapping, inheritanceMappingType, auditTableData, extendsEntityName, hasDiscriminator ? pc.DiscriminatorValue : null, pc.IsAbstract.HasValue && pc.IsAbstract.Value); // The id and revision type is already mapped in the parent // Getting the property mapper of the parent - when mapping properties, they need to be included var parentEntityName = pc.Superclass.EntityName; EntityConfiguration parentConfiguration; if (!EntitiesConfigurations.TryGetValue(parentEntityName, out parentConfiguration)) { throw new MappingException("Entity '" + pc.EntityName + "' is audited, but its superclass: '" + parentEntityName + "' is not."); } var parentPropertyMapper = parentConfiguration.PropertyMapper; var propertyMapper = new SubclassPropertyMapper(new MultiPropertyMapper(), parentPropertyMapper); return(new Tuple <XElement, IExtendedPropertyMapper, string>(classMapping, propertyMapper, parentEntityName)); }
private Tuple <XElement, IExtendedPropertyMapper, string> generateMappingData( PersistentClass pc, EntityXmlMappingData xmlMappingData, AuditTableData auditTableData, IdMappingData idMapper) { var hasDiscriminator = pc.Discriminator != null; var classMapping = MetadataTools.CreateEntity(xmlMappingData.MainXmlMapping, auditTableData, hasDiscriminator ? pc.DiscriminatorValue : null, pc.IsAbstract.HasValue && pc.IsAbstract.Value); var propertyMapper = new MultiPropertyMapper(); // Adding the id mapping classMapping.Add(idMapper.XmlMapping); // Checking if there is a discriminator column if (hasDiscriminator) { var discriminatorElement = new XElement(MetadataTools.CreateElementName("discriminator")); classMapping.Add(discriminatorElement); // Database column or SQL formula allowed to distinguish entity types MetadataTools.AddColumnsOrFormulas(discriminatorElement, pc.Discriminator.ColumnIterator); discriminatorElement.Add(new XAttribute("type", pc.Discriminator.Type.Name)); } // Adding the "revision type" property AddRevisionType(classMapping, classMapping); return(new Tuple <XElement, IExtendedPropertyMapper, string>(classMapping, propertyMapper, null)); }
private XmlElement CreateMiddleEntityXml(String auditMiddleTableName, String auditMiddleEntityName, String where) { String schema = mainGenerator.GetSchema(propertyAuditingData.JoinTable.Schema, propertyValue.CollectionTable); String catalog = mainGenerator.GetCatalog(propertyAuditingData.JoinTable.Catalog, propertyValue.CollectionTable); XmlElement middleEntityXml = MetadataTools.CreateEntity(xmlMappingData.newAdditionalMapping(), new AuditTableData(auditMiddleEntityName, auditMiddleTableName, schema, catalog), null); XmlElement middleEntityXmlId = middleEntityXml.OwnerDocument.CreateElement("composite-id"); middleEntityXml.AppendChild(middleEntityXmlId); // If there is a where clause on the relation, adding it to the middle entity. if (where != null) { middleEntityXml.SetAttribute("where", where); } middleEntityXmlId.SetAttribute("name", mainGenerator.VerEntCfg.OriginalIdPropName); // Adding the revision number as a foreign key to the revision info entity to the composite id of the // middle table. mainGenerator.AddRevisionInfoRelation(middleEntityXmlId); // Adding the revision type property to the entity xml. mainGenerator.AddRevisionType(middleEntityXml); // All other properties should also be part of the primary key of the middle entity. return(middleEntityXmlId); }
private static void addCustomValue(XElement parent, PropertyAuditingData propertyAuditingData, IValue value, ISimpleMapperBuilder mapper, bool insertable, bool key, System.Type typeOfUserImplementation) { if (parent != null) { var propMapping = MetadataTools.AddProperty(parent, propertyAuditingData.Name, typeOfUserImplementation.AssemblyQualifiedName, insertable, key); MetadataTools.AddColumns(propMapping, value.ColumnIterator.OfType <Column>()); var typeElement = new XElement(MetadataTools.CreateElementName("type"), new XAttribute("name", typeOfUserImplementation.AssemblyQualifiedName)); var simpleValue = value as SimpleValue; if (simpleValue != null) { var typeParameters = simpleValue.TypeParameters; if (typeParameters != null) { foreach (var paramKeyValue in typeParameters) { var typeParam = new XElement(MetadataTools.CreateElementName("param"), new XAttribute("name", paramKeyValue.Key), paramKeyValue.Value); typeElement.Add(typeParam); } } } propMapping.Add(typeElement); } if (mapper != null) { mapper.Add(propertyAuditingData.GetPropertyData()); } }
/** * Clones the revision info relation mapping, so that it can be added to other mappings. Also, the name of * the property and the column are set properly. * @return A revision info mapping, which can be added to other mappings (has no parent). */ private XmlElement CloneAndSetupRevisionInfoRelationMapping(XmlDocument doc) { XmlElement rev_mapping = (XmlElement)doc.ImportNode(revisionInfoRelationMapping, true); rev_mapping.SetAttribute("name", VerEntCfg.RevisionFieldName); MetadataTools.AddOrModifyColumn(rev_mapping, VerEntCfg.RevisionFieldName); return rev_mapping; }
public void AddKeyManyToOne(XElement parent, PropertyAuditingData propertyAuditingData, IValue value, ISimpleMapperBuilder mapper) { var type = value.Type; var element = mapper == null? MetadataTools.AddKeyManyToOne(parent, propertyAuditingData.Name, type.ReturnedClass.AssemblyQualifiedName) : MetadataTools.AddManyToOne(parent, propertyAuditingData.Name, type.ReturnedClass.AssemblyQualifiedName, true, false); MetadataTools.AddColumns(element, value.ColumnIterator.OfType <Column>()); mapper?.Add(propertyAuditingData.GetPropertyData()); }
/// <summary> /// Clones the revision info relation mapping, so that it can be added to other mappings. Also, the name of /// the property and the column are set properly. /// </summary> /// <returns>A revision info mapping, which can be added to other mappings (has no parent).</returns> private XElement cloneAndSetupRevisionInfoRelationMapping() { var revMapping = new XElement(revisionInfoRelationMapping); revMapping.Add(new XAttribute("name", VerEntCfg.RevisionFieldName)); MetadataTools.AddOrModifyColumn(revMapping, VerEntCfg.RevisionFieldName); return(revMapping); }
/** * * @param value Value, which should be mapped to the middle-table, either as a relation to another entity, * or as a simple value. * @param xmlMapping If not <code>null</code>, xml mapping for this value is added to this element. * @param queryGeneratorBuilder In case <code>value</code> is a relation to another entity, information about it * should be added to the given. * @param prefix Prefix for proeprty names of related entities identifiers. * @param joinColumns Names of columns to use in the xml mapping, if this array isn't null and has any elements. * @return Data for mapping this component. */ //@SuppressWarnings({"unchecked"}) private MiddleComponentData AddValueToMiddleTable(IValue value, XmlElement xmlMapping, QueryGeneratorBuilder queryGeneratorBuilder, String prefix, JoinColumnAttribute[] joinColumns) { IType type = value.Type; if (type is ManyToOneType) { String prefixRelated = prefix + "_"; String referencedEntityName = MappingTools.getReferencedEntityName(value); IdMappingData referencedIdMapping = mainGenerator.GetReferencedIdMappingData(referencingEntityName, referencedEntityName, propertyAuditingData, true); // Adding related-entity (in this case: the referenced entities id) id mapping to the xml only if the // relation isn't inverse (so when <code>xmlMapping</code> is not null). if (xmlMapping != null) { AddRelatedToXmlMapping(xmlMapping, prefixRelated, joinColumns != null && joinColumns.Length > 0 ? MetadataTools.GetColumnNameEnumerator(joinColumns) : MetadataTools.GetColumnNameEnumerator(value.ColumnIterator.GetEnumerator()), referencedIdMapping); } // Storing the id data of the referenced entity: original mapper, prefixed mapper and entity name. MiddleIdData referencedIdData = CreateMiddleIdData(referencedIdMapping, prefixRelated, referencedEntityName); // And adding it to the generator builder. queryGeneratorBuilder.AddRelation(referencedIdData); return(new MiddleComponentData(new MiddleRelatedComponentMapper(referencedIdData), queryGeneratorBuilder.CurrentIndex)); } else { // Last but one parameter: collection components are always insertable bool mapped = mainGenerator.BasicMetadataGenerator.AddBasic(xmlMapping, new PropertyAuditingData(prefix, "field", ModificationStore.FULL, RelationTargetAuditMode.AUDITED, null, null, false), value, null, true, true); if (mapped) { // Simple values are always stored in the first item of the array returned by the query generator. return(new MiddleComponentData(new MiddleSimpleComponentMapper(mainGenerator.VerEntCfg, prefix), 0)); } else { mainGenerator.ThrowUnsupportedTypeException(type, referencingEntityName, propertyName); // Impossible to get here. throw new AssertionFailure(); } } }
public IdMappingData AddId(PersistentClass pc) { var relIdMapping = new XElement(MetadataTools.CreateElementName("properties")); // Xml mapping which will be used for the primary key of the versions table var origIdMapping = new XElement(MetadataTools.CreateElementName("composite-id"), new XAttribute("name", _mainGenerator.VerEntCfg.OriginalIdPropName)); var idProp = pc.IdentifierProperty; var idMapper = pc.IdentifierMapper; // Checking if the id mapping is supported if (idMapper == null && idProp == null) { return(null); } ISimpleIdMapperBuilder mapper; if (idMapper != null) { // Multiple id throw new MappingException("Multi id mapping isn't (wasn't?) available in NH Core"); } if (idProp.IsComposite) { // Embedded id var idComponent = (Component)idProp.Value; mapper = new EmbeddedIdMapper(getIdPropertyData(idProp), idComponent.ComponentClass); addIdProperties(relIdMapping, idComponent.PropertyIterator, mapper, false); // null mapper - the mapping where already added the first time, now we only want to generate the xml addIdProperties(origIdMapping, idComponent.PropertyIterator, null, true); } else { // Single id mapper = new SingleIdMapper(); // Last but one parameter: ids are always insertable _mainGenerator.BasicMetadataGenerator.AddBasic(relIdMapping, getIdPersistentPropertyAuditingData(idProp), idProp.Value, mapper, true, false); // null mapper - the mapping where already added the first time, now we only want to generate the xml _mainGenerator.BasicMetadataGenerator.AddBasic(origIdMapping, getIdPersistentPropertyAuditingData(idProp), idProp.Value, null, true, true); } // Adding a relation to the revision entity (effectively: the "revision number" property) _mainGenerator.AddRevisionInfoRelation(origIdMapping); return(new IdMappingData(mapper, origIdMapping, relIdMapping)); }
/// <summary> /// Adds mapping of the id of a related entity to the given xml mapping, prefixing the id with the given prefix. /// </summary> /// <param name="xmlMapping">Mapping, to which to add the xml.</param> /// <param name="prefix">Prefix for the names of properties which will be prepended to properties that form the id.</param> /// <param name="columnNames">Column names that will be used for properties that form the id.</param> /// <param name="relatedIdMapping">Id mapping data of the related entity.</param> private static void addRelatedToXmlMapping(XElement xmlMapping, string prefix, IEnumerable <string> columnNames, IdMappingData relatedIdMapping) { var properties = new XElement(relatedIdMapping.XmlRelationMapping); MetadataTools.PrefixNamesInPropertyElement(properties, prefix, columnNames, true, true, null); foreach (var idProperty in properties.Elements()) { xmlMapping.Add(idProperty); } }
//@SuppressWarnings({"unchecked"}) public void AddToOne(XmlElement parent, PropertyAuditingData propertyAuditingData, IValue value, ICompositeMapperBuilder mapper, String entityName, bool insertable) { String referencedEntityName = ((ToOne)value).ReferencedEntityName; IdMappingData idMapping = mainGenerator.GetReferencedIdMappingData(entityName, referencedEntityName, propertyAuditingData, true); String lastPropertyPrefix = MappingTools.createToOneRelationPrefix(propertyAuditingData.Name); // Generating the id mapper for the relation IIdMapper relMapper = idMapping.IdMapper.PrefixMappedProperties(lastPropertyPrefix); // Storing information about this relation mainGenerator.EntitiesConfigurations[entityName].AddToOneRelation( propertyAuditingData.Name, referencedEntityName, relMapper, insertable); // If the property isn't insertable, checking if this is not a "fake" bidirectional many-to-one relationship, // that is, when the one side owns the relation (and is a collection), and the many side is non insertable. // When that's the case and the user specified to store this relation without a middle table (using // @AuditMappedBy), we have to make the property insertable for the purposes of Envers. In case of changes to // the entity that didn't involve the relation, it's value will then be stored properly. In case of changes // to the entity that did involve the relation, it's the responsibility of the collection side to store the // proper data. bool nonInsertableFake; if (!insertable && propertyAuditingData.ForceInsertable) { nonInsertableFake = true; insertable = true; } else { nonInsertableFake = false; } // Adding an element to the mapping corresponding to the references entity id's // Use OwnerDocument.ImportNode() instead of XmlNode.Clone(); XmlElement properties = (XmlElement)parent.OwnerDocument.ImportNode(idMapping.XmlRelationMapping, true); properties.SetAttribute("name", propertyAuditingData.Name); MetadataTools.PrefixNamesInPropertyElement(properties, lastPropertyPrefix, MetadataTools.GetColumnNameEnumerator((IEnumerator <ISelectable>)value.ColumnIterator.GetEnumerator()), false, insertable); parent.AppendChild(properties); // Adding mapper for the id PropertyData propertyData = propertyAuditingData.getPropertyData(); mapper.AddComposite(propertyData, new ToOneIdMapper(relMapper, propertyData, referencedEntityName, nonInsertableFake)); }
/** * Adds mapping of the id of a related entity to the given xml mapping, prefixing the id with the given prefix. * @param xmlMapping Mapping, to which to add the xml. * @param prefix Prefix for the names of properties which will be prepended to properties that form the id. * @param columnNameIterator Iterator over the column names that will be used for properties that form the id. * @param relatedIdMapping Id mapping data of the related entity. */ private void AddRelatedToXmlMapping(XmlElement xmlMapping, String prefix, MetadataTools.ColumnNameEnumerator columnNameIterator, IdMappingData relatedIdMapping) { XmlElement properties = (XmlElement)relatedIdMapping.XmlRelationMapping.Clone(); MetadataTools.PrefixNamesInPropertyElement(properties, prefix, columnNameIterator, true, true); foreach (XmlElement idProperty in (System.Collections.Generic.IList <XmlElement>)properties.ChildNodes) { xmlMapping.AppendChild((XmlElement)idProperty.Clone()); } }
public void AddRevisionType(XElement anyMapping, XElement anyMappingEnd) { var partOfId = anyMapping != anyMappingEnd; var revTypeProperty = MetadataTools.AddProperty(anyMapping, VerEntCfg.RevisionTypePropName, typeof(RevisionTypeType).AssemblyQualifiedName, true, partOfId, null); if (!partOfId) { revTypeProperty.Add(new XAttribute("not-null", "true")); } GlobalCfg.AuditStrategy.AddExtraRevisionMapping(anyMappingEnd, revisionInfoRelationMapping); }
private static void addSimpleValue(XElement parent, PropertyAuditingData propertyAuditingData, IValue value, ISimpleMapperBuilder mapper, bool insertable, bool key) { if (parent != null) { var propMapping = MetadataTools.AddProperty(parent, propertyAuditingData.Name, value.Type.Name, propertyAuditingData.ForceInsertable || insertable, key, propertyAuditingData.AccessType); MetadataTools.AddColumns(propMapping, value.ColumnIterator.OfType <Column>()); } // A null mapper means that we only want to add xml mappings mapper?.Add(propertyAuditingData.GetPropertyData()); }
private void AddSimpleValue(XmlElement parent, PropertyAuditingData propertyAuditingData, IValue value, ISimpleMapperBuilder mapper, bool insertable, bool key) { if (parent != null) { XmlElement prop_mapping = MetadataTools.AddProperty(parent, propertyAuditingData.Name, value.Type.Name, propertyAuditingData.ForceInsertable || insertable, key); MetadataTools.AddColumns(prop_mapping, (IEnumerator <ISelectable>)value.ColumnIterator.GetEnumerator()); } // A null mapper means that we only want to add xml mappings if (mapper != null) { mapper.Add(propertyAuditingData.getPropertyData()); } }
private static string searchMappedBy(PersistentClass referencedClass, Mapping.Collection collectionValue) { foreach (var property in referencedClass.PropertyIterator) { if (MetadataTools.IsNoneAccess(property.PropertyAccessorName)) { continue; } //should probably not care if order is same... if (property.Value.ColumnIterator.SequenceEqual(collectionValue.Key.ColumnIterator)) { return(property.Name); } } return(null); }
//@SuppressWarnings({"unchecked"}) private Triple<XmlElement, IExtendedPropertyMapper, String> GenerateMappingData( PersistentClass pc, EntityXmlMappingData xmlMappingData, AuditTableData auditTableData, IdMappingData idMapper) { bool hasDiscriminator = pc.Discriminator != null; XmlElement class_mapping = MetadataTools.CreateEntity(xmlMappingData.MainXmlMapping, auditTableData, hasDiscriminator ? pc.DiscriminatorValue : null); IExtendedPropertyMapper propertyMapper = new MultiPropertyMapper(); // Checking if there is a discriminator column if (hasDiscriminator) { XmlElement discriminator_element = class_mapping.OwnerDocument.CreateElement("discriminator"); class_mapping.AppendChild(discriminator_element); MetadataTools.AddColumns(discriminator_element, (IEnumerator<ISelectable>)pc.Discriminator.ColumnIterator.GetEnumerator()); discriminator_element.SetAttribute("type", pc.Discriminator.Type.Name); } InheritanceType.Type parentInheritance = InheritanceType.GetForParent(pc); switch (parentInheritance) { case InheritanceType.Type.NONE: break; case InheritanceType.Type.SINGLE: AddSingleInheritancePersisterHack(class_mapping); break; case InheritanceType.Type.JOINED: AddJoinedInheritancePersisterHack(class_mapping); break; case InheritanceType.Type.TABLE_PER_CLASS: AddTablePerClassInheritancePersisterHack(class_mapping); break; } // Adding the id mapping XmlNode xmlMp = class_mapping.OwnerDocument.ImportNode(idMapper.XmlMapping,true); class_mapping.AppendChild(xmlMp); // Adding the "revision type" property AddRevisionType(class_mapping); return Triple<XmlElement, IExtendedPropertyMapper, string>.Make<XmlElement, IExtendedPropertyMapper, string>(class_mapping, propertyMapper, null); }
//@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); } }
private void AddCustomValue(XmlElement parent, PropertyAuditingData propertyAuditingData, IValue value, ISimpleMapperBuilder mapper, bool insertable, bool key) { if (parent != null) { XmlElement prop_mapping = MetadataTools.AddProperty(parent, propertyAuditingData.Name, null, insertable, key); //CustomType propertyType = (CustomType) value.getType(); XmlElement type_mapping = parent.OwnerDocument.CreateElement("type"); prop_mapping.AppendChild(type_mapping); type_mapping.SetAttribute("name", value.GetType().Name); if (value is SimpleValue) { IDictionary <string, string> typeParameters = ((SimpleValue)value).TypeParameters; if (typeParameters != null) { foreach (KeyValuePair <string, string> paramKeyValue in typeParameters) { XmlElement type_param = parent.OwnerDocument.CreateElement("param"); type_param.SetAttribute("name", (String)paramKeyValue.Key); type_param["name"].Value = paramKeyValue.Value; } } } MetadataTools.AddColumns(prop_mapping, (IEnumerator <ISelectable>)value.ColumnIterator); } if (mapper != null) { mapper.Add(propertyAuditingData.getPropertyData()); } }
/** * Adds mapping of the id of a related entity to the given xml mapping, prefixing the id with the given prefix. * @param xmlMapping Mapping, to which to add the xml. * @param prefix Prefix for the names of properties which will be prepended to properties that form the id. * @param columnNameIterator Iterator over the column names that will be used for properties that form the id. * @param relatedIdMapping Id mapping data of the related entity. */ private void AddRelatedToXmlMapping(XmlElement xmlMapping, String prefix, MetadataTools.ColumnNameEnumerator columnNameIterator, IdMappingData relatedIdMapping) { XmlElement properties = (XmlElement) relatedIdMapping.XmlRelationMapping.Clone(); MetadataTools.PrefixNamesInPropertyElement(properties, prefix, columnNameIterator, true, true); foreach (XmlElement idProperty in (System.Collections.Generic.IList<XmlElement>) properties.ChildNodes) { xmlMapping.AppendChild((XmlElement) idProperty.Clone()); } }
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); }
public void AddToOne(XElement parent, PropertyAuditingData propertyAuditingData, IValue value, ICompositeMapperBuilder mapper, string entityName, bool insertable) { var referencedEntityName = ((ToOne)value).ReferencedEntityName; var idMapping = _mainGenerator.GetReferencedIdMappingData(entityName, referencedEntityName, propertyAuditingData, true); var lastPropertyPrefix = MappingTools.CreateToOneRelationPrefix(propertyAuditingData.Name); // Generating the id mapper for the relation var relMapper = idMapping.IdMapper.PrefixMappedProperties(lastPropertyPrefix); // Storing information about this relation _mainGenerator.EntitiesConfigurations[entityName].AddToOneRelation( propertyAuditingData.Name, referencedEntityName, relMapper, insertable, MappingTools.IgnoreNotFound(value)); // If the property isn't insertable, checking if this is not a "fake" bidirectional many-to-one relationship, // that is, when the one side owns the relation (and is a collection), and the many side is non insertable. // When that's the case and the user specified to store this relation without a middle table (using // @AuditMappedBy), we have to make the property insertable for the purposes of Envers. In case of changes to // the entity that didn't involve the relation, it's value will then be stored properly. In case of changes // to the entity that did involve the relation, it's the responsibility of the collection side to store the // proper data. bool nonInsertableFake; if (!insertable && propertyAuditingData.ForceInsertable) { nonInsertableFake = true; insertable = true; } else { nonInsertableFake = false; } // Adding an element to the mapping corresponding to the references entity id's var properties = new XElement(idMapping.XmlRelationMapping); properties.Add(new XAttribute("name", propertyAuditingData.Name)); MetadataTools.PrefixNamesInPropertyElement(properties, lastPropertyPrefix, MetadataTools.GetColumnNameEnumerator(value.ColumnIterator), false, insertable, propertyAuditingData.AccessType); // Extracting related id properties from properties tag var firstJoin = firstJoinElement(parent); foreach (var element in properties.Elements()) { if (firstJoin == null) { parent.Add(element); } else { firstJoin.AddBeforeSelf(element); } } // Adding mapper for the id var propertyData = propertyAuditingData.GetPropertyData(); mapper.AddComposite(propertyData, new ToOneIdMapper(relMapper, propertyData, referencedEntityName, nonInsertableFake)); }
private static XElement firstJoinElement(XElement classElement) { //do we have to check for other elements than join here? return(classElement.Element(MetadataTools.CreateElementName("join"))); }
private void addWithMiddleTable() { log.Debug("Adding audit mapping for property {0}. {1}" + ": collection with a join table.", _referencingEntityName, _propertyName); // Generating the name of the middle table string auditMiddleTableName; string auditMiddleEntityName; if (!string.IsNullOrEmpty(_propertyAuditingData.JoinTable.TableName)) { auditMiddleTableName = _propertyAuditingData.JoinTable.TableName; auditMiddleEntityName = _propertyAuditingData.JoinTable.TableName; } else { // We check how Hibernate maps the collection. if (_propertyValue.Element is OneToMany && !_propertyValue.IsInverse) { // This must be a @JoinColumn+@OneToMany mapping. Generating the table name, as Hibernate doesn't use a // middle table for mapping this relation. var referencingPersistentClass = _mainGenerator.Cfg.GetClassMapping(_referencingEntityName); var referencedPersistentClass = _mainGenerator.Cfg.GetClassMapping(_referencedEntityName); auditMiddleTableName = _mainGenerator.VerEntCfg.UnidirectionOneToManyTableName(referencingPersistentClass, referencedPersistentClass); auditMiddleEntityName = _mainGenerator.VerEntCfg.GetAuditEntityName(_referencingEntityName, _referencedEntityName); } else { auditMiddleTableName = _mainGenerator.VerEntCfg.CollectionTableName(_propertyValue); auditMiddleEntityName = _mainGenerator.VerEntCfg.GetAuditEntityName(_propertyValue.CollectionTable.Name); } } log.Debug("Using join table name: {0}", auditMiddleTableName); // Generating the XML mapping for the middle entity, only if the relation isn't inverse. // If the relation is inverse, will be later checked by comparing middleEntityXml with null. XElement middleEntityXml; if (!_propertyValue.IsInverse) { // Generating a unique middle entity name auditMiddleEntityName = _mainGenerator.AuditEntityNameRegister.CreateUnique(auditMiddleEntityName); // Registering the generated name _mainGenerator.AuditEntityNameRegister.Register(auditMiddleEntityName); middleEntityXml = createMiddleEntityXml(auditMiddleTableName, auditMiddleEntityName, _propertyValue.Where); } else { middleEntityXml = null; } // ****** // Generating the mapping for the referencing entity (it must be an entity). // ****** // Getting the id-mapping data of the referencing entity (the entity that "owns" this collection). var referencingIdMapping = _referencingEntityConfiguration.IdMappingData; // Only valid for an inverse relation; null otherwise. string mappedBy; // The referencing prefix is always for a related entity. So it has always the "_" at the end added. string referencingPrefixRelated; string referencedPrefix; if (_propertyValue.IsInverse) { // If the relation is inverse, then referencedEntityName is not null. mappedBy = getMappedBy(_propertyValue.CollectionTable, _mainGenerator.Cfg.GetClassMapping(_referencedEntityName)); referencingPrefixRelated = mappedBy + "_"; referencedPrefix = StringTools.GetLastComponent(_referencedEntityName); } else { mappedBy = null; referencingPrefixRelated = StringTools.GetLastComponent(_referencingEntityName) + "_"; referencedPrefix = _referencedEntityName == null ? "element" : _propertyName; } // Storing the id data of the referencing entity: original mapper, prefixed mapper and entity name. var referencingIdData = createMiddleIdData(referencingIdMapping, referencingPrefixRelated, _referencingEntityName); // Creating a query generator builder, to which additional id data will be added, in case this collection // references some entities (either from the element or index). At the end, this will be used to build // a query generator to read the raw data collection from the middle table. var queryGeneratorBuilder = new QueryGeneratorBuilder(_mainGenerator.VerEntCfg, _mainGenerator.GlobalCfg.AuditStrategy, referencingIdData, auditMiddleEntityName, isEmbeddableElementType()); // Adding the XML mapping for the referencing entity, if the relation isn't inverse. if (middleEntityXml != null) { // Adding related-entity (in this case: the referencing's entity id) id mapping to the xml. addRelatedToXmlMapping(middleEntityXml, referencingPrefixRelated, MetadataTools.GetColumnNameEnumerator(_propertyValue.Key.ColumnIterator), referencingIdMapping); } // ****** // Generating the element mapping. // ****** var elementComponentData = addValueToMiddleTable(_propertyValue.Element, middleEntityXml, queryGeneratorBuilder, referencedPrefix, _propertyAuditingData.JoinTable.InverseJoinColumns); // ****** // Generating the index mapping, if an index exists. // ****** var indexComponentData = addIndex(middleEntityXml, queryGeneratorBuilder); // ****** // Generating the property mapper. // ****** // Building the query generator. var queryGenerator = queryGeneratorBuilder.Build(new Collection <MiddleComponentData> { elementComponentData, indexComponentData }); // Creating common data var commonCollectionMapperData = new CommonCollectionMapperData( _mainGenerator.VerEntCfg, auditMiddleEntityName, _propertyAuditingData.GetPropertyData(), referencingIdData, queryGenerator); // Checking the type of the collection and adding an appropriate mapper. addMapper(commonCollectionMapperData, elementComponentData, indexComponentData); // ****** // Storing information about this relation. // ****** storeMiddleEntityRelationInformation(mappedBy); }
/// <summary> /// Add value to middle table /// </summary> /// <param name="value">Value, which should be mapped to the middle-table, either as a relation to another entity, or as a simple value.</param> /// <param name="xmlMapping">If not <code>null</code>, xml mapping for this value is added to this element.</param> /// <param name="queryGeneratorBuilder">In case <code>value</code> is a relation to another entity, information about it should be added to the given.</param> /// <param name="prefix">Prefix for proeprty names of related entities identifiers.</param> /// <param name="joinColumns">Names of columns to use in the xml mapping, if this array isn't null and has any elements.</param> /// <returns>Data for mapping this component.</returns> private MiddleComponentData addValueToMiddleTable(IValue value, XElement xmlMapping, QueryGeneratorBuilder queryGeneratorBuilder, string prefix, string[] joinColumns) { var type = value.Type; if (type is ManyToOneType) { var prefixRelated = prefix + "_"; var referencedEntityName = MappingTools.ReferencedEntityName(value); var referencedIdMapping = _mainGenerator.GetReferencedIdMappingData(_referencingEntityName, referencedEntityName, _propertyAuditingData, true); // Adding related-entity (in this case: the referenced entities id) id mapping to the xml only if the // relation isn't inverse (so when <code>xmlMapping</code> is not null). if (xmlMapping != null) { addRelatedToXmlMapping(xmlMapping, prefixRelated, joinColumns != null && joinColumns.Length > 0 ? joinColumns : MetadataTools.GetColumnNameEnumerator(value.ColumnIterator), referencedIdMapping); } // Storing the id data of the referenced entity: original mapper, prefixed mapper and entity name. var referencedIdData = createMiddleIdData(referencedIdMapping, prefixRelated, referencedEntityName); // And adding it to the generator builder. queryGeneratorBuilder.AddRelation(referencedIdData); return(new MiddleComponentData(new MiddleRelatedComponentMapper(referencedIdData), queryGeneratorBuilder.CurrentIndex)); } else if (type is ComponentType) { //collection of embaddable elements var component = (Component)value; var componentMapper = new MiddleEmbeddableComponentMapper(new MultiPropertyMapper(), component.ComponentClassName); var parentXmlMapping = xmlMapping.Parent; var auditData = new ComponentAuditingData(); new ComponentAuditedPropertiesReader(_metaDataStore, new AuditedPropertiesReader.ComponentPropertiesSource(component), auditData, _mainGenerator.GlobalCfg, "").Read(); // Emulating first pass. foreach (var auditedPropertyName in auditData.PropertyNames) { var nestedAuditingData = auditData.GetPropertyAuditingData(auditedPropertyName); _mainGenerator.AddValue(parentXmlMapping, component.GetProperty(auditedPropertyName).Value, componentMapper, prefix, _xmlMappingData, nestedAuditingData, true, true, true); } // Emulating second pass so that the relations can be mapped too. foreach (var auditedPropertyName in auditData.PropertyNames) { var nestedAuditingData = auditData.GetPropertyAuditingData(auditedPropertyName); _mainGenerator.AddValue(parentXmlMapping, component.GetProperty(auditedPropertyName).Value, componentMapper, _referencingEntityName, _xmlMappingData, nestedAuditingData, true, false, true); } // Add an additional column holding a number to make each entry unique within the set. // Embeddable properties may contain null values, so cannot be stored within composite primary key. if (_propertyValue.IsSet) { var setOrdinalPropertyName = _mainGenerator.VerEntCfg.EmbeddableSetOrdinalPropertyName; var ordinalProperty = MetadataTools.AddProperty(xmlMapping, setOrdinalPropertyName, "int", true, true, null); MetadataTools.AddColumn(ordinalProperty, setOrdinalPropertyName, -1, -1, -1, null, false); } return(new MiddleComponentData(componentMapper, 0)); } // Last but one parameter: collection components are always insertable var mapped = _mainGenerator.BasicMetadataGenerator.AddBasic(xmlMapping, new PropertyAuditingData(prefix, "field"), value, null, true, true); if (mapped) { // Simple values are always stored in the first item of the array returned by the query generator. return(new MiddleComponentData(new MiddleSimpleComponentMapper(_mainGenerator.VerEntCfg, prefix), 0)); } _mainGenerator.ThrowUnsupportedTypeException(type, _referencingEntityName, _propertyName); // Impossible to get here. throw new AssertionFailure(); }
//@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); }