示例#1
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);
        }
示例#2
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);
                    }
                }
            }
        }
        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);
                    }
                }
            }
        }
示例#4
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);
                    }
                }
            }
        }
示例#5
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);
        }
示例#6
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();
        }