Exemplo n.º 1
0
        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));
        }
Exemplo n.º 3
0
        /// <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);
        }
Exemplo n.º 4
0
        /// <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);
                    }
                }
            }
        }
Exemplo n.º 5
0
        /**
         * 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));
        }
Exemplo n.º 7
0
        /**
         *
         * @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();
                }
            }
        }
Exemplo n.º 8
0
        //@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);
                    }
                }
            }
        }
Exemplo n.º 11
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)
                    {
                        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);
                    }
                }
            }
        }
Exemplo n.º 12
0
 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));
        }
Exemplo n.º 14
0
 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);
                    }
                }
            }
        }
Exemplo n.º 16
0
        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);
        }
Exemplo n.º 18
0
        /**
         * @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);
        }
Exemplo n.º 19
0
        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);
        }
Exemplo n.º 20
0
        //@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));
 }
Exemplo n.º 23
0
 private static bool isRelation(Mapping.Collection collectionValue, Property referencedProperty)
 {
     return(MappingTools.SameColumns(referencedProperty.ColumnIterator, collectionValue.Key.ColumnIterator) &&
            collectionValue.Owner.MappedClass.IsAssignableFrom(referencedProperty.Type.ReturnedClass));
 }
Exemplo n.º 24
0
        /// <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();
        }
Exemplo n.º 25
0
        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));
        }