private async Task _OnBeforeSaving() { var entries = ChangeTracker.Entries().ToList(); using var sha512 = SHA512.Create(); foreach (var template in _filter <TemplateRevisionEntity>(entries)) { template.CWeightTsvHelper = Fields.fromString.Invoke(template.Fields).Select(x => x.Name) .Append(MappingTools.stripHtmlTags(template.CardTemplates)) .Apply(x => string.Join(' ', x)); } foreach (var revision in _filter <RevisionEntity>(entries)) { if (revision.TemplateRevision == null) { revision.TemplateRevision = await TemplateRevision.FindAsync(revision.TemplateRevisionId); } var templateHash = revision.TemplateRevision?.Hash ?? TemplateRevision.Find(revision.TemplateRevisionId).Hash; revision.TsvHelper = MappingTools.stripHtmlTags(revision.FieldValues); } foreach (var card in _filter <CardEntity>(entries)) { card.TsvHelper = MappingTools.stripHtmlTags(card.FrontPersonalField) + " " + MappingTools.stripHtmlTags(card.BackPersonalField); } }
public void AddOneToOneNotOwning(PropertyAuditingData propertyAuditingData, IValue value, ICompositeMapperBuilder mapper, string entityName) { var propertyValue = (OneToOne)value; var owningReferencePropertyName = propertyValue.ReferencedPropertyName; // mappedBy var configuration = _mainGenerator.EntitiesConfigurations[entityName]; if (configuration == null) { throw new MappingException("An audited relation to a non-audited entity " + entityName + "!"); } var ownedIdMapping = configuration.IdMappingData; if (ownedIdMapping == null) { throw new MappingException("An audited relation to a non-audited entity " + entityName + "!"); } var lastPropertyPrefix = MappingTools.CreateToOneRelationPrefix(owningReferencePropertyName); var referencedEntityName = propertyValue.ReferencedEntityName; // Generating the id mapper for the relation var ownedIdMapper = ownedIdMapping.IdMapper.PrefixMappedProperties(lastPropertyPrefix); // Storing information about this relation _mainGenerator.EntitiesConfigurations[entityName].AddToOneNotOwningRelation( propertyAuditingData.Name, owningReferencePropertyName, referencedEntityName, ownedIdMapper, MappingTools.IgnoreNotFound(value)); // Adding mapper for the id var propertyData = propertyAuditingData.GetPropertyData(); mapper.AddComposite(propertyData, new OneToOneNotOwningMapper(entityName, referencedEntityName, owningReferencePropertyName, propertyData)); }
/// <summary> /// Ctor /// </summary> /// <param name="metaDataStore"></param> /// <param name="mainGenerator">Main generator, giving access to configuration and the basic mapper.</param> /// <param name="propertyValue">Value of the collection, as mapped by Hibernate.</param> /// <param name="currentMapper">Mapper, to which the appropriate {@link org.hibernate.envers.entities.mapper.PropertyMapper} will be added.</param> /// <param name="referencingEntityName">Name of the entity that owns this collection.</param> /// <param name="xmlMappingData">In case this collection requires a middle table, additional mapping documents will be created using this object.</param> /// <param name="propertyAuditingData"> /// 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. /// </param> public CollectionMetadataGenerator(IMetaDataStore metaDataStore, AuditMetadataGenerator mainGenerator, Mapping.Collection propertyValue, ICompositeMapperBuilder currentMapper, string referencingEntityName, EntityXmlMappingData xmlMappingData, PropertyAuditingData propertyAuditingData) { _metaDataStore = metaDataStore; _mainGenerator = mainGenerator; _propertyValue = propertyValue; _currentMapper = currentMapper; _referencingEntityName = referencingEntityName; _xmlMappingData = xmlMappingData; _propertyAuditingData = propertyAuditingData; _propertyName = propertyAuditingData.Name; _referencingEntityConfiguration = mainGenerator.EntitiesConfigurations[referencingEntityName]; if (_referencingEntityConfiguration == null) { throw new MappingException("Unable to read auditing configuration for " + referencingEntityName + "!"); } _referencedEntityName = MappingTools.ReferencedEntityName(propertyValue.Element); }
/// <summary> /// 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> /// </summary> public void UpdateCalculatedFields() { foreach (var classAuditingDataEntry in persistentClassToAuditingData) { var pc = classAuditingDataEntry.Key; var classAuditingData = classAuditingDataEntry.Value; foreach (var propertyName in classAuditingData.PropertyNames) { var propertyAuditingData = classAuditingData.GetPropertyAuditingData(propertyName); // If a property had the @AuditMappedBy annotation, setting the referenced fields to be always insertable. if (propertyAuditingData.ForceInsertable) { var referencedEntityName = MappingTools.ReferencedEntityName(pc.GetProperty(propertyName).Value); var referencedClassAuditingData = entityNameToAuditingData[referencedEntityName]; forcePropertyInsertable(referencedClassAuditingData, propertyAuditingData.MappedBy, pc.EntityName, referencedEntityName); forcePropertyInsertable(referencedClassAuditingData, propertyAuditingData.PositionMappedBy, pc.EntityName, referencedEntityName); } } } }
/** * 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 Tuple <IPropertyMapper, string> mapperAndDelegatePropertyName(string referencingPropertyName) { // Name of the property, to which we will delegate the mapping. string delegatePropertyName; // Checking if the property name doesn't reference a collection in a component - then the name will containa a . var dotIndex = referencingPropertyName.IndexOf('.'); if (dotIndex != -1) { // Computing the name of the component var componentName = referencingPropertyName.Substring(0, dotIndex); // And the name of the property in the component var propertyInComponentName = MappingTools.CreateComponentPrefix(componentName) + referencingPropertyName.Substring(dotIndex + 1); // We need to get the mapper for the component. referencingPropertyName = componentName; // As this is a component, we delegate to the property in the component. delegatePropertyName = propertyInComponentName; } else { // If this is not a component, we delegate to the same property. delegatePropertyName = referencingPropertyName; } var propertyMapper = propertyMapperKey(referencingPropertyName); return(propertyMapper == null ? null : new Tuple <IPropertyMapper, string>(propertyMapper, delegatePropertyName)); }
/** * * @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(); } } }
//@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)); }
private MiddleComponentData addIndex(XElement middleEntityXml, QueryGeneratorBuilder queryGeneratorBuilder) { var indexedValue = _propertyValue as IndexedCollection; if (indexedValue != null) { var idMatch = false; Property referencedProperty = null; PersistentClass refPc = null; if (_referencedEntityName != null) { refPc = _mainGenerator.Cfg.GetClassMapping(_referencedEntityName); } if (refPc != null) { idMatch = MappingTools.SameColumns(refPc.IdentifierProperty.ColumnIterator, indexedValue.Index.ColumnIterator); foreach (var propertyRef in refPc.PropertyIterator) { if (MappingTools.SameColumns(propertyRef.ColumnIterator, indexedValue.Index.ColumnIterator)) { referencedProperty = propertyRef; break; } } } if (!idMatch && referencedProperty == null) { return(addValueToMiddleTable(indexedValue.Index, middleEntityXml, queryGeneratorBuilder, "mapkey", null)); } var currentIndex = queryGeneratorBuilder?.CurrentIndex ?? 0; if (idMatch) { // The key of the map is the id of the entity. var referencedIdMapping = _mainGenerator.EntitiesConfigurations[_referencedEntityName].IdMappingData; return(new MiddleComponentData(new MiddleMapKeyIdComponentMapper(_mainGenerator.VerEntCfg, referencedIdMapping.IdMapper), currentIndex)); } if (indexedValue is Map) { // The key of the map is a property of the entity. return(new MiddleComponentData(new MiddleMapKeyPropertyComponentMapper(referencedProperty.Name, referencedProperty.PropertyAccessorName), currentIndex)); } //bidirectional list // The key of the map is a property of the entity. return(new MiddleComponentData(new MiddleStraightComponentMapper(referencedProperty.Name), currentIndex)); } // No index - creating a dummy mapper. return(new MiddleComponentData(new MiddleDummyComponentMapper(), 0)); }
private void addBidirectionalInfo(IDictionary <System.Type, IEntityMeta> metas) { foreach (var type in metas.Keys) { var persistentClass = _nhibernateConfiguration.GetClassMapping(type); if (persistentClass == null) { continue; } foreach (var property in persistentClass.PropertyIterator) { //is it a collection? var collectionValue = property.Value as Mapping.Collection; if (collectionValue == null) { continue; } //find referenced entity name var referencedEntity = MappingTools.ReferencedEntityName(property.Value); if (referencedEntity == null) { continue; } var refPersistentClass = _nhibernateConfiguration.GetClassMapping(referencedEntity); foreach (var refProperty in refPersistentClass.PropertyClosureIterator) { var attr = createAuditMappedByAttributeIfReferenceImmutable(collectionValue, refProperty); if (attr == null) { continue; } mightAddIndexToAttribute(attr, collectionValue, refPersistentClass.PropertyClosureIterator); var entityMeta = (EntityMeta)metas[type]; var declaredPersistentProperty = PropertyAndMemberInfo.PersistentInfo(type, new[] { property }).FirstOrDefault(); if (declaredPersistentProperty == null) { //pawel owerko log.WarnFormat(string.Format("Cannot create '{0}' object for property '{1}'. Property not found in type '{2}'.", typeof(DeclaredPersistentProperty).Name, property.Name, type.FullName)); continue; //todo: Can we handle declaredPersistentProperty==null in that way ? } var methodInfo = declaredPersistentProperty.Member; addToEntityMeta(attr, entityMeta, methodInfo); } } } }
private void addBidirectionalInfo(IDictionary <System.Type, IEntityMeta> metas) { foreach (var type in metas.Keys) { var persistentClass = _nhibernateConfiguration.GetClassMapping(type); if (persistentClass == null) { continue; } foreach (var property in persistentClass.PropertyIterator) { //is it a collection? var collectionValue = property.Value as Mapping.Collection; if (collectionValue == null) { continue; } //find referenced entity name var referencedEntity = MappingTools.ReferencedEntityName(property.Value); if (referencedEntity == null) { continue; } var refPersistentClass = _nhibernateConfiguration.GetClassMapping(referencedEntity); foreach (var refProperty in refPersistentClass.PropertyClosureIterator) { if (MetadataTools.IsNoneAccess(refProperty.PropertyAccessorName)) { continue; } var attr = createAuditMappedByAttributeIfReferenceImmutable(collectionValue, refProperty); if (attr == null) { continue; } mightAddIndexToAttribute(attr, collectionValue, refPersistentClass.PropertyClosureIterator); var entityMeta = (EntityMeta)metas[type]; var methodInfo = PropertyAndMemberInfo.PersistentInfo(type, new[] { property }).First().Member; addToEntityMeta(attr, entityMeta, methodInfo); } } } }
private static void mightAddIndexToAttribute(AuditMappedByAttribute auditMappedByAttribute, Mapping.Collection collectionValue, IEnumerable <Property> referencedProperties) { //check index value if (!(collectionValue is IndexedCollection indexValue)) { return; } foreach (var referencedProperty in referencedProperties) { if (MappingTools.SameColumns(referencedProperty.ColumnIterator, indexValue.Index.ColumnIterator) && !referencedProperty.IsUpdateable && !referencedProperty.IsInsertable) { auditMappedByAttribute.PositionMappedBy = referencedProperty.Name; } } }
public void AddOneToOnePrimaryKeyJoinColumn(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)); // Adding mapper for the id var propertyData = propertyAuditingData.GetPropertyData(); mapper.AddComposite(propertyData, new OneToOnePrimaryKeyJoinColumnMapper(entityName, referencedEntityName, propertyData)); }
private String GetMiddleTableName(Mapping.Collection value, String entityName) { // We check how Hibernate maps the collection. if (value.Element is OneToMany && !value.IsInverse) { // This must be a @JoinColumn+@OneToMany mapping. Generating the table name, as Hibernate doesn't use a // middle table for mapping this relation. String refEntName = MappingTools.getReferencedEntityName(value.Element); return(entityName.Substring(entityName.LastIndexOf(".") + 1) + "_" + refEntName.Substring(refEntName.LastIndexOf(".") + 1)); } else { // Hibernate uses a middle table for mapping this relation, so we get it's name directly. return(value.CollectionTable.Name); } }
private void AddFromProperties(IEnumerable <PropertyInfo> properties, String accessType, ISet <String> persistentProperties) { //ORIG: foreach (XProperty property in properties) { foreach (PropertyInfo property in properties) { // 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.Name)) { IValue propertyValue = _persistentPropertiesSource.GetProperty(property.Name).Value; PropertyAuditingData propertyData; bool isAudited; if (propertyValue is Component) { ComponentAuditingData componentData = new ComponentAuditingData(); isAudited = FillPropertyData(property, componentData, accessType); IPersistentPropertiesSource componentPropertiesSource = new ComponentPropertiesSource( (Component)propertyValue); new AuditedPropertiesReader(ModificationStore.FULL, componentPropertiesSource, componentData, _globalCfg, _propertyNamePrefix + MappingTools.createComponentPrefix(property.Name)) .read(); propertyData = componentData; } else { propertyData = new PropertyAuditingData(); isAudited = FillPropertyData(property, propertyData, accessType); } if (isAudited) { // Now we know that the property is audited _auditedPropertiesHolder.addPropertyAuditingData(property.Name, propertyData); } } } }
public IList <PersistentCollectionChangeData> MapCollectionChanges(String referencingPropertyName, IPersistentCollection newColl, object oldColl, object id) { // Name of the property, to which we will delegate the mapping. String delegatePropertyName; // Checking if the property name doesn't reference a collection in a component - then the name will containa a . int dotIndex = referencingPropertyName.IndexOf('.'); if (dotIndex != -1) { // Computing the name of the component String componentName = referencingPropertyName.Substring(0, dotIndex); // And the name of the property in the component String propertyInComponentName = MappingTools.createComponentPrefix(componentName) + referencingPropertyName.Substring(dotIndex + 1); // We need to get the mapper for the component. referencingPropertyName = componentName; // As this is a component, we delegate to the property in the component. delegatePropertyName = propertyInComponentName; } else { // If this is not a component, we delegate to the same property. delegatePropertyName = referencingPropertyName; } IPropertyMapper mapper = Properties[propertyDatas[referencingPropertyName]]; if (mapper != null) { return(mapper.MapCollectionChanges(delegatePropertyName, newColl, oldColl, id)); } else { return(null); } }
private static AuditMappedByAttribute createAuditMappedByAttributeIfReferenceImmutable(Mapping.Collection collectionValue, Property referencedProperty) { AuditMappedByAttribute attr = null; //check if bidrectional //TODO: backref check here is wrong! But if it's fixed it will be a big breaking change I guess.. For now, an extra table will be created. if (!referencedProperty.BackRef && isRelation(collectionValue, referencedProperty)) { attr = new AuditMappedByAttribute { MappedBy = referencedProperty.Name }; if (!referencedProperty.IsUpdateable && !referencedProperty.IsInsertable && //check that non update/insert properties are not also part of id! !MappingTools.AnyColumnMatches(referencedProperty.ColumnIterator, referencedProperty.PersistentClass.Identifier.ColumnIterator)) { attr.ForceInsertOverride = true; } } return(attr); }
/** * @param mainGenerator Main generator, giving access to configuration and the basic mapper. * @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 propertyAuditingData 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, Mapping.Collection propertyValue, ICompositeMapperBuilder currentMapper, String referencingEntityName, EntityXmlMappingData xmlMappingData, PropertyAuditingData propertyAuditingData) { this.mainGenerator = mainGenerator; this.propertyValue = propertyValue; this.currentMapper = currentMapper; this.referencingEntityName = referencingEntityName; this.xmlMappingData = xmlMappingData; this.propertyAuditingData = propertyAuditingData; this.propertyName = propertyAuditingData.Name; referencingEntityConfiguration = mainGenerator.EntitiesConfigurations[referencingEntityName]; if (referencingEntityConfiguration == null) { throw new MappingException("Unable to read auditing configuration for " + referencingEntityName + "!"); } referencedEntityName = MappingTools.getReferencedEntityName(propertyValue.Element); }
private string getMappedBy(Mapping.Collection collectionValue) { var referencedClass = _mainGenerator.Cfg.GetClassMapping(MappingTools.ReferencedEntityName(collectionValue.Element)); var mappedBy = searchMappedBy(referencedClass, collectionValue); if (mappedBy == null) { log.Debug("Going to search the mapped by attribute for " + _propertyName + " in superclasses of entity: " + referencedClass.ClassName); var tempClass = referencedClass; while (mappedBy == null && tempClass.Superclass != null) { log.Debug("Searching in superclass: " + tempClass.Superclass.ClassName); mappedBy = searchMappedBy(tempClass.Superclass, collectionValue); tempClass = tempClass.Superclass; } } if (mappedBy == null) { throw new MappingException("Cannot find the inverse side for " + _propertyName + " in " + _referencingEntityName + "!"); } return(mappedBy); }
//@SuppressWarnings({"unchecked"}) public void AddOneToOneNotOwning(PropertyAuditingData propertyAuditingData, IValue value, ICompositeMapperBuilder mapper, String entityName) { OneToOne propertyValue = (OneToOne)value; String owningReferencePropertyName = propertyValue.ReferencedPropertyName; // mappedBy EntityConfiguration configuration = mainGenerator.EntitiesConfigurations[entityName]; if (configuration == null) { throw new MappingException("An audited relation to a non-audited entity " + entityName + "!"); } IdMappingData ownedIdMapping = configuration.IdMappingData; if (ownedIdMapping == null) { throw new MappingException("An audited relation to a non-audited entity " + entityName + "!"); } String lastPropertyPrefix = MappingTools.createToOneRelationPrefix(owningReferencePropertyName); String referencedEntityName = propertyValue.ReferencedEntityName; // Generating the id mapper for the relation IIdMapper ownedIdMapper = ownedIdMapping.IdMapper.PrefixMappedProperties(lastPropertyPrefix); // Storing information about this relation mainGenerator.EntitiesConfigurations[entityName].AddToOneNotOwningRelation( propertyAuditingData.Name, owningReferencePropertyName, referencedEntityName, ownedIdMapper); // Adding mapper for the id PropertyData propertyData = propertyAuditingData.getPropertyData(); mapper.AddComposite(propertyData, new OneToOneNotOwningMapper(owningReferencePropertyName, referencedEntityName, propertyData)); }
private void addFromComponentProperty(DeclaredPersistentProperty property, Component componentValue, AuditedAttribute allClassAudited) { var componentData = new ComponentAuditingData(); var isAudited = fillPropertyData(property.Member, property.Property.Name, componentData, property.Property.PropertyAccessorName, allClassAudited); var componentPropertiesSource = new ComponentPropertiesSource(componentValue); var audPropReader = new ComponentAuditedPropertiesReader(_metaDataStore, componentPropertiesSource, componentData, _globalCfg, _propertyNamePrefix + MappingTools.CreateComponentPrefix(property.Property.Name)); audPropReader.Read(); if (isAudited) { // Now we know that the property is audited _auditedPropertiesHolder.AddPropertyAuditingData(property.Property.Name, componentData); } }
private static bool isRelation(Mapping.Collection collection, Property potentialBackRefProperty) { return(MappingTools.SameColumns(potentialBackRefProperty.ColumnIterator, collection.Key.ColumnIterator) && isEqualOrDerived(collection.Owner.MappedClass, potentialBackRefProperty.Type.ReturnedClass)); }
private static bool isRelation(Mapping.Collection collectionValue, Property referencedProperty) { return(MappingTools.SameColumns(referencedProperty.ColumnIterator, collectionValue.Key.ColumnIterator) && collectionValue.Owner.MappedClass.IsAssignableFrom(referencedProperty.Type.ReturnedClass)); }
/// <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(); }
private void addOneToManyAttached(bool fakeOneToManyBidirectional) { log.Debug("Adding audit mapping for property {0}. {1}" + ": one-to-many collection, using a join column on the referenced entity.", _referencingEntityName, _propertyName); var mappedBy = getMappedBy(_propertyValue); var referencedIdMapping = _mainGenerator.GetReferencedIdMappingData(_referencingEntityName, _referencedEntityName, _propertyAuditingData, false); var referencingIdMapping = _referencingEntityConfiguration.IdMappingData; // Generating the id mappers data for the referencing side of the relation. var referencingIdData = createMiddleIdData(referencingIdMapping, mappedBy + "_", _referencingEntityName); // And for the referenced side. The prefixed mapper won't be used (as this collection isn't persisted // in a join table, so the prefix value is arbitrary). var referencedIdData = createMiddleIdData(referencedIdMapping, null, _referencedEntityName); // Generating the element mapping. var elementComponentData = new MiddleComponentData( new MiddleRelatedComponentMapper(referencedIdData), 0); // Generating the index mapping, if an index exists. It can only exists in case a javax.persistence.MapKey // annotation is present on the entity. So the middleEntityXml will be not be used. The queryGeneratorBuilder // will only be checked for nullnes. var indexComponentData = addIndex(null, null); // Generating the query generator - it should read directly from the related entity. var queryGenerator = new OneAuditEntityQueryGenerator(_mainGenerator.VerEntCfg, _mainGenerator.GlobalCfg.AuditStrategy, referencingIdData, _referencedEntityName, referencedIdData, isEmbeddableElementType()); // Creating common mapper data. var commonCollectionMapperData = new CommonCollectionMapperData( _mainGenerator.VerEntCfg, _referencedEntityName, _propertyAuditingData.GetPropertyData(), referencingIdData, queryGenerator); IPropertyMapper fakeBidirectionalRelationMapper; IPropertyMapper fakeBidirectionalRelationIndexMapper; if (fakeOneToManyBidirectional) { // In case of a fake many-to-one bidirectional relation, we have to generate a mapper which maps // the mapped-by property name to the id of the related entity (which is the owner of the collection). var auditMappedBy = _propertyAuditingData.MappedBy; // Creating a prefixed relation mapper. var relMapper = referencingIdMapping.IdMapper.PrefixMappedProperties( MappingTools.CreateToOneRelationPrefix(auditMappedBy)); fakeBidirectionalRelationMapper = new ToOneIdMapper( _mainGenerator.GlobalCfg.EnversProxyFactory, relMapper, // The mapper will only be used to map from entity to map, so no need to provide other details // when constructing the PropertyData. new PropertyData(auditMappedBy, null, null), _referencedEntityName, false); // Checking if there's an index defined. If so, adding a mapper for it. if (_propertyAuditingData.PositionMappedBy != null) { var positionMappedBy = _propertyAuditingData.PositionMappedBy; fakeBidirectionalRelationIndexMapper = new SinglePropertyMapper(new PropertyData(positionMappedBy, null, null)); // Also, overwriting the index component data to properly read the index. indexComponentData = new MiddleComponentData(new MiddleStraightComponentMapper(positionMappedBy), 0); } else { fakeBidirectionalRelationIndexMapper = null; } } else { fakeBidirectionalRelationMapper = null; fakeBidirectionalRelationIndexMapper = null; } // Checking the type of the collection and adding an appropriate mapper. addMapper(commonCollectionMapperData, elementComponentData, indexComponentData); // Storing information about this relation. _referencingEntityConfiguration.AddToManyNotOwningRelation(_propertyName, mappedBy, _referencedEntityName, referencingIdData.PrefixedMapper, fakeBidirectionalRelationMapper, fakeBidirectionalRelationIndexMapper); }
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)); }