예제 #1
0
 public CustomListCollectionMapper(CommonCollectionMapperData commonCollectionMapperData,
                                   System.Type proxyType,
                                   MiddleComponentData elementComponentData,
                                   MiddleComponentData indexComponentData,
                                   bool revisionTypeInId)
     : base(commonCollectionMapperData, proxyType, false, revisionTypeInId)
 {
     _elementComponentData = elementComponentData;
     _indexComponentData   = indexComponentData;
 }
예제 #2
0
        private void AddMapper(CommonCollectionMapperData commonCollectionMapperData, MiddleComponentData elementComponentData,
                               MiddleComponentData indexComponentData)
        {
            IType type = propertyValue.Type;

            if (type is SortedSetType)
            {
                currentMapper.AddComposite(propertyAuditingData.getPropertyData(),
                                           new BasicCollectionMapper <IDictionary>(commonCollectionMapperData,
                                                                                   typeof(TreeSet <>), typeof(SortedSetProxy <>), elementComponentData));
            }
            else if (type is SetType)
            {
                currentMapper.AddComposite(propertyAuditingData.getPropertyData(),
                                           new BasicCollectionMapper <Set>(commonCollectionMapperData,
                                                                           typeof(HashedSet <>), typeof(SetProxy <>), elementComponentData));
            }
            else
            {
                throw new NotImplementedException();
            }
            //else if (type is SortedMapType) {
            //    // Indexed collection, so <code>indexComponentData</code> is not null.
            //    currentMapper.addComposite(propertyAuditingData.getPropertyData(),
            //            new MapCollectionMapper<Map>(commonCollectionMapperData,
            //            TreeMap.class, SortedMapProxy.class, elementComponentData, indexComponentData));
            //} else if (type is MapType) {
            //    // Indexed collection, so <code>indexComponentData</code> is not null.
            //    currentMapper.addComposite(propertyAuditingData.getPropertyData(),
            //            new MapCollectionMapper<Map>(commonCollectionMapperData,
            //            HashMap.class, MapProxy.class, elementComponentData, indexComponentData));
            //} else if (type is BagType) {
            //    currentMapper.addComposite(propertyAuditingData.getPropertyData(),
            //            new BasicCollectionMapper<List>(commonCollectionMapperData,
            //            ArrayList.class, ListProxy.class, elementComponentData));
            //} else if (type is ListType) {
            //    // Indexed collection, so <code>indexComponentData</code> is not null.
            //    currentMapper.addComposite(propertyAuditingData.getPropertyData(),
            //            new ListCollectionMapper(commonCollectionMapperData,
            //            elementComponentData, indexComponentData));
            //} else {
            //    mainGenerator.ThrowUnsupportedTypeException(type, referencingEntityName, propertyName);
            //}
        }
예제 #3
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 IPropertyMapper Create(IEnversProxyFactory enversProxyFactory, CommonCollectionMapperData commonCollectionMapperData, MiddleComponentData elementComponentData, MiddleComponentData indexComponentData, bool embeddableElementType)
 {
     return(null);
 }
예제 #5
0
 public IPropertyMapper Create(IEnversProxyFactory enversProxyFactory, CommonCollectionMapperData commonCollectionMapperData, MiddleComponentData elementComponentData, MiddleComponentData indexComponentData, bool embeddableElementType)
 {
     return(new CustomListCollectionMapper <CustomList <TItem>, TItem>(enversProxyFactory, commonCollectionMapperData, typeof(CustomList <TItem>), elementComponentData, indexComponentData, embeddableElementType));
 }
 public IPropertyMapper Create(CommonCollectionMapperData commonCollectionMapperData, MiddleComponentData elementComponentData, MiddleComponentData indexComponentDatabool, bool embeddableElementType)
 {
     return(new SpecialMapper(commonCollectionMapperData, elementComponentData, embeddableElementType));
 }
예제 #7
0
 public virtual IPropertyMapper Bag <T>(CommonCollectionMapperData commonCollectionMapperData, MiddleComponentData elementComponentData, bool embeddableElementType)
 {
     return(new BagCollectionMapper <T>(commonCollectionMapperData, typeof(ListProxy <T>), elementComponentData, embeddableElementType));
 }
예제 #8
0
        private void AddWithMiddleTable()
        {
            log.Debug("Adding audit mapping for property " + referencingEntityName + "." + propertyName +
                      ": collection with a join table.");

            // Generating the name of the middle table
            String auditMiddleTableName;
            String auditMiddleEntityName;

            if (!String.IsNullOrEmpty(propertyAuditingData.JoinTable.Name))
            {
                auditMiddleTableName  = propertyAuditingData.JoinTable.Name;
                auditMiddleEntityName = propertyAuditingData.JoinTable.Name;
            }
            else
            {
                String middleTableName = GetMiddleTableName(propertyValue, referencingEntityName);
                auditMiddleTableName  = mainGenerator.VerEntCfg.GetAuditTableName(null, middleTableName);
                auditMiddleEntityName = mainGenerator.VerEntCfg.GetAuditEntityName(middleTableName);
            }

            log.Debug("Using join table name: " + auditMiddleTableName);

            // Generating the XML mapping for the middle entity, only if the relation isn't inverse.
            // If the relation is inverse, will be later checked by comparing middleEntityXml with null.
            XmlElement middleEntityXml;

            if (!propertyValue.IsInverse)
            {
                // Generating a unique middle entity name
                auditMiddleEntityName = mainGenerator.AuditEntityNameRegister.createUnique(auditMiddleEntityName);

                // Registering the generated name
                mainGenerator.AuditEntityNameRegister.register(auditMiddleEntityName);

                middleEntityXml = CreateMiddleEntityXml(auditMiddleTableName, auditMiddleEntityName, propertyValue.Where);
            }
            else
            {
                middleEntityXml = null;
            }

            // ******
            // Generating the mapping for the referencing entity (it must be an entity).
            // ******
            // Getting the id-mapping data of the referencing entity (the entity that "owns" this collection).
            IdMappingData referencingIdMapping = referencingEntityConfiguration.IdMappingData;

            // Only valid for an inverse relation; null otherwise.
            String mappedBy;

            // The referencing prefix is always for a related entity. So it has always the "_" at the end added.
            String referencingPrefixRelated;
            String referencedPrefix;

            if (propertyValue.IsInverse)
            {
                // If the relation is inverse, then referencedEntityName is not null.
                mappedBy = GetMappedBy(propertyValue.CollectionTable, mainGenerator.Cfg.GetClassMapping(referencedEntityName));

                referencingPrefixRelated = mappedBy + "_";
                referencedPrefix         = StringTools.GetLastComponent(referencedEntityName);
            }
            else
            {
                mappedBy = null;

                referencingPrefixRelated = StringTools.GetLastComponent(referencingEntityName) + "_";
                referencedPrefix         = referencedEntityName == null ? "element" : propertyName;
            }

            // Storing the id data of the referencing entity: original mapper, prefixed mapper and entity name.
            MiddleIdData referencingIdData = CreateMiddleIdData(referencingIdMapping,
                                                                referencingPrefixRelated, referencingEntityName);

            // Creating a query generator builder, to which additional id data will be added, in case this collection
            // references some entities (either from the element or index). At the end, this will be used to build
            // a query generator to read the raw data collection from the middle table.
            QueryGeneratorBuilder queryGeneratorBuilder = new QueryGeneratorBuilder(mainGenerator.GlobalCfg,
                                                                                    mainGenerator.VerEntCfg, referencingIdData, auditMiddleEntityName);

            // Adding the XML mapping for the referencing entity, if the relation isn't inverse.
            if (middleEntityXml != null)
            {
                // Adding related-entity (in this case: the referencing's entity id) id mapping to the xml.
                AddRelatedToXmlMapping(middleEntityXml, referencingPrefixRelated,
                                       MetadataTools.GetColumnNameEnumerator(propertyValue.Key.ColumnIterator.GetEnumerator()),
                                       referencingIdMapping);
            }

            // ******
            // Generating the element mapping.
            // ******
            MiddleComponentData elementComponentData = AddValueToMiddleTable(propertyValue.Element, middleEntityXml,
                                                                             queryGeneratorBuilder, referencedPrefix, propertyAuditingData.JoinTable.InverseJoinColumns);

            // ******
            // Generating the index mapping, if an index exists.
            // ******
            MiddleComponentData indexComponentData = AddIndex(middleEntityXml, queryGeneratorBuilder);

            // ******
            // Generating the property mapper.
            // ******
            // Building the query generator.
            IRelationQueryGenerator queryGenerator = queryGeneratorBuilder.Build(new Collection <MiddleComponentData> {
                elementComponentData, indexComponentData
            });

            // Creating common data
            CommonCollectionMapperData commonCollectionMapperData = new CommonCollectionMapperData(
                mainGenerator.VerEntCfg, auditMiddleEntityName,
                propertyAuditingData.getPropertyData(),
                referencingIdData, queryGenerator);

            // Checking the type of the collection and adding an appropriate mapper.
            AddMapper(commonCollectionMapperData, elementComponentData, indexComponentData);

            // ******
            // Storing information about this relation.
            // ******
            StoreMiddleEntityRelationInformation(mappedBy);
        }
예제 #9
0
 public virtual IPropertyMapper SortedSet <T>(CommonCollectionMapperData commonCollectionMapperData, MiddleComponentData elementComponentData, IComparer <T> comparer, bool embeddableElementType)
 {
     return(new SortedSetCollectionMapper <T>(commonCollectionMapperData, typeof(SetProxy <T>), elementComponentData, comparer, embeddableElementType, embeddableElementType));
 }
예제 #10
0
 public virtual IPropertyMapper Array(System.Type elementType, CommonCollectionMapperData commonCollectionMapperData, MiddleComponentData elementComponentData, MiddleComponentData indexComponentData, bool embeddableElementType)
 {
     throw new NotImplementedException("Array is not supported by DefaultCollectionMapperFactory");
 }
예제 #11
0
 public virtual IPropertyMapper Bag <T>(IEnversProxyFactory enversProxyFactory, CommonCollectionMapperData commonCollectionMapperData, MiddleComponentData elementComponentData, bool embeddableElementType)
 {
     return(new BagCollectionMapper <T>(enversProxyFactory, commonCollectionMapperData, typeof(IList <T>), elementComponentData, embeddableElementType));
 }
예제 #12
0
 public virtual IPropertyMapper Map <TKey, TValue>(IEnversProxyFactory enversProxyFactory, CommonCollectionMapperData commonCollectionMapperData, MiddleComponentData elementComponentData, MiddleComponentData indexComponentData, bool embeddableElementType)
 {
     return(new MapCollectionMapper <TKey, TValue>(enversProxyFactory, commonCollectionMapperData, typeof(IDictionary <TKey, TValue>), elementComponentData, indexComponentData, embeddableElementType));
 }
예제 #13
0
 public SpecialMapper(CommonCollectionMapperData commonCollectionMapperData, MiddleComponentData elementComponentData, bool embeddableElementType)
     : base(commonCollectionMapperData, typeof(SpecialProxyCollectionType), elementComponentData, embeddableElementType)
 {
     _elementComponentData = elementComponentData;
 }
예제 #14
0
 public SpecialMapper(IEnversProxyFactory enversProxyFactory, CommonCollectionMapperData commonCollectionMapperData, MiddleComponentData elementComponentData, bool embeddableElementType)
     : base(enversProxyFactory, commonCollectionMapperData, typeof(ISpecialCollection), elementComponentData, embeddableElementType)
 {
     _elementComponentData = elementComponentData;
 }
예제 #15
0
        private void addWithMiddleTable()
        {
            log.Debug("Adding audit mapping for property {0}. {1}" +
                      ": collection with a join table.", _referencingEntityName, _propertyName);

            // Generating the name of the middle table
            string auditMiddleTableName;
            string auditMiddleEntityName;

            if (!string.IsNullOrEmpty(_propertyAuditingData.JoinTable.TableName))
            {
                auditMiddleTableName  = _propertyAuditingData.JoinTable.TableName;
                auditMiddleEntityName = _propertyAuditingData.JoinTable.TableName;
            }
            else
            {
                // We check how Hibernate maps the collection.
                if (_propertyValue.Element is OneToMany && !_propertyValue.IsInverse)
                {
                    // This must be a @JoinColumn+@OneToMany mapping. Generating the table name, as Hibernate doesn't use a
                    // middle table for mapping this relation.
                    var referencingPersistentClass = _mainGenerator.Cfg.GetClassMapping(_referencingEntityName);
                    var referencedPersistentClass  = _mainGenerator.Cfg.GetClassMapping(_referencedEntityName);
                    auditMiddleTableName  = _mainGenerator.VerEntCfg.UnidirectionOneToManyTableName(referencingPersistentClass, referencedPersistentClass);
                    auditMiddleEntityName = _mainGenerator.VerEntCfg.GetAuditEntityName(_referencingEntityName, _referencedEntityName);
                }
                else
                {
                    auditMiddleTableName  = _mainGenerator.VerEntCfg.CollectionTableName(_propertyValue);
                    auditMiddleEntityName = _mainGenerator.VerEntCfg.GetAuditEntityName(_propertyValue.CollectionTable.Name);
                }
            }

            log.Debug("Using join table name: {0}", auditMiddleTableName);

            // Generating the XML mapping for the middle entity, only if the relation isn't inverse.
            // If the relation is inverse, will be later checked by comparing middleEntityXml with null.
            XElement middleEntityXml;

            if (!_propertyValue.IsInverse)
            {
                // Generating a unique middle entity name
                auditMiddleEntityName = _mainGenerator.AuditEntityNameRegister.CreateUnique(auditMiddleEntityName);

                // Registering the generated name
                _mainGenerator.AuditEntityNameRegister.Register(auditMiddleEntityName);

                middleEntityXml = createMiddleEntityXml(auditMiddleTableName, auditMiddleEntityName, _propertyValue.Where);
            }
            else
            {
                middleEntityXml = null;
            }

            // ******
            // Generating the mapping for the referencing entity (it must be an entity).
            // ******
            // Getting the id-mapping data of the referencing entity (the entity that "owns" this collection).
            var referencingIdMapping = _referencingEntityConfiguration.IdMappingData;

            // Only valid for an inverse relation; null otherwise.
            string mappedBy;

            // The referencing prefix is always for a related entity. So it has always the "_" at the end added.
            string referencingPrefixRelated;
            string referencedPrefix;

            if (_propertyValue.IsInverse)
            {
                // If the relation is inverse, then referencedEntityName is not null.
                mappedBy = getMappedBy(_propertyValue.CollectionTable, _mainGenerator.Cfg.GetClassMapping(_referencedEntityName));

                referencingPrefixRelated = mappedBy + "_";
                referencedPrefix         = StringTools.GetLastComponent(_referencedEntityName);
            }
            else
            {
                mappedBy = null;

                referencingPrefixRelated = StringTools.GetLastComponent(_referencingEntityName) + "_";
                referencedPrefix         = _referencedEntityName == null ? "element" : _propertyName;
            }

            // Storing the id data of the referencing entity: original mapper, prefixed mapper and entity name.
            var referencingIdData = createMiddleIdData(referencingIdMapping, referencingPrefixRelated, _referencingEntityName);

            // Creating a query generator builder, to which additional id data will be added, in case this collection
            // references some entities (either from the element or index). At the end, this will be used to build
            // a query generator to read the raw data collection from the middle table.
            var queryGeneratorBuilder = new QueryGeneratorBuilder(_mainGenerator.VerEntCfg, _mainGenerator.GlobalCfg.AuditStrategy, referencingIdData, auditMiddleEntityName, isEmbeddableElementType());

            // Adding the XML mapping for the referencing entity, if the relation isn't inverse.
            if (middleEntityXml != null)
            {
                // Adding related-entity (in this case: the referencing's entity id) id mapping to the xml.
                addRelatedToXmlMapping(middleEntityXml, referencingPrefixRelated,
                                       MetadataTools.GetColumnNameEnumerator(_propertyValue.Key.ColumnIterator),
                                       referencingIdMapping);
            }

            // ******
            // Generating the element mapping.
            // ******
            var elementComponentData = addValueToMiddleTable(_propertyValue.Element, middleEntityXml,
                                                             queryGeneratorBuilder, referencedPrefix, _propertyAuditingData.JoinTable.InverseJoinColumns);

            // ******
            // Generating the index mapping, if an index exists.
            // ******
            var indexComponentData = addIndex(middleEntityXml, queryGeneratorBuilder);

            // ******
            // Generating the property mapper.
            // ******
            // Building the query generator.
            var queryGenerator = queryGeneratorBuilder.Build(new Collection <MiddleComponentData> {
                elementComponentData, indexComponentData
            });

            // Creating common data
            var commonCollectionMapperData = new CommonCollectionMapperData(
                _mainGenerator.VerEntCfg, auditMiddleEntityName,
                _propertyAuditingData.GetPropertyData(),
                referencingIdData, queryGenerator);

            // Checking the type of the collection and adding an appropriate mapper.
            addMapper(commonCollectionMapperData, elementComponentData, indexComponentData);

            // ******
            // Storing information about this relation.
            // ******
            storeMiddleEntityRelationInformation(mappedBy);
        }
예제 #16
0
 public virtual IPropertyMapper SortedMap <TKey, TValue>(CommonCollectionMapperData commonCollectionMapperData, MiddleComponentData elementComponentData, MiddleComponentData indexComponentData, IComparer <TKey> comparer, bool embeddableElementType)
 {
     return(new SortedMapCollectionMapper <TKey, TValue>(commonCollectionMapperData, typeof(DictionaryProxy <TKey, TValue>), elementComponentData, indexComponentData, comparer, embeddableElementType));
 }
예제 #17
0
        private void addMapper(CommonCollectionMapperData commonCollectionMapperData, MiddleComponentData elementComponentData, MiddleComponentData indexComponentData)
        {
            var propertyValueType = _propertyValue.GetType();
            var type = _propertyValue.Type;
            var embeddableElementType = isEmbeddableElementType();

            IPropertyMapper collectionMapper;
            var             collectionProxyMapperFactory = _mainGenerator.GlobalCfg.CollectionMapperFactory;

            if (_propertyAuditingData.CustomCollectionMapperFactory != null)
            {
                collectionMapper = _propertyAuditingData.CustomCollectionMapperFactory.Create(_mainGenerator.GlobalCfg.EnversProxyFactory, commonCollectionMapperData, elementComponentData, indexComponentData, embeddableElementType);
            }
            else if (propertyValueType == typeof(Set))
            {
                if (_propertyValue.IsSorted)
                {
                    var methodInfo = sortedSetDefinition.MakeGenericMethod(type.ReturnedClass.GetGenericArguments());
                    collectionMapper = (IPropertyMapper)methodInfo.Invoke(collectionProxyMapperFactory,
                                                                          new[] { _mainGenerator.GlobalCfg.EnversProxyFactory, commonCollectionMapperData, elementComponentData, _propertyValue.Comparer, embeddableElementType });
                }
                else
                {
                    var methodInfo = setDefinition.MakeGenericMethod(type.ReturnedClass.GetGenericArguments());
                    collectionMapper = (IPropertyMapper)methodInfo.Invoke(collectionProxyMapperFactory,
                                                                          new object[] { _mainGenerator.GlobalCfg.EnversProxyFactory, commonCollectionMapperData, elementComponentData, embeddableElementType });
                }
            }
            else if (propertyValueType == typeof(List))
            {
                var methodInfo = listDefinition.MakeGenericMethod(type.ReturnedClass.GetGenericArguments());
                collectionMapper = (IPropertyMapper)methodInfo.Invoke(collectionProxyMapperFactory,
                                                                      new object[] { _mainGenerator.GlobalCfg.EnversProxyFactory, commonCollectionMapperData, elementComponentData, indexComponentData, embeddableElementType });
            }
            else if (propertyValueType == typeof(Map))
            {
                if (_propertyValue.IsSorted)
                {
                    var methodInfo = sortedMapDefinition.MakeGenericMethod(type.ReturnedClass.GetGenericArguments());
                    collectionMapper = (IPropertyMapper)methodInfo.Invoke(collectionProxyMapperFactory,
                                                                          new[] { _mainGenerator.GlobalCfg.EnversProxyFactory, commonCollectionMapperData, elementComponentData, indexComponentData, _propertyValue.Comparer, embeddableElementType });
                }
                else
                {
                    var methodInfo = mapDefinition.MakeGenericMethod(type.ReturnedClass.GetGenericArguments());
                    collectionMapper = (IPropertyMapper)methodInfo.Invoke(collectionProxyMapperFactory,
                                                                          new object[] { _mainGenerator.GlobalCfg.EnversProxyFactory, commonCollectionMapperData, elementComponentData, indexComponentData, embeddableElementType });
                }
            }
            else if (propertyValueType == typeof(Bag))
            {
                var methodInfo = bagDefinition.MakeGenericMethod(type.ReturnedClass.GetGenericArguments());
                collectionMapper = (IPropertyMapper)methodInfo.Invoke(collectionProxyMapperFactory,
                                                                      new object[] { _mainGenerator.GlobalCfg.EnversProxyFactory, commonCollectionMapperData, elementComponentData, embeddableElementType });
            }
            else if (propertyValueType == typeof(IdentifierBag))
            {
                var methodInfo = idBagDefinition.MakeGenericMethod(type.ReturnedClass.GetGenericArguments());
                collectionMapper = (IPropertyMapper)methodInfo.Invoke(collectionProxyMapperFactory,
                                                                      new object[] { _mainGenerator.GlobalCfg.EnversProxyFactory, commonCollectionMapperData, elementComponentData, embeddableElementType });
            }
            else
            {
                throw new NotImplementedException("Mapped collection type " + type.Name + " is not currently supported in Envers");
            }
            _currentMapper.AddComposite(_propertyAuditingData.GetPropertyData(), collectionMapper);
        }
        private void addMapper(CommonCollectionMapperData commonCollectionMapperData, MiddleComponentData elementComponentData,
                               MiddleComponentData indexComponentData)
        {
            var type = _propertyValue.Type;
            var embeddableElementType = isEmbeddableElementType();

            IPropertyMapper collectionMapper;
            var             collectionProxyMapperFactory = _mainGenerator.GlobalCfg.CollectionMapperFactory;
            var             genericType = genericTypeDefinition(type);

            if (_propertyAuditingData.CustomCollectionMapperFactory != null)
            {
                collectionMapper = _propertyAuditingData.CustomCollectionMapperFactory.Create(_mainGenerator.GlobalCfg.EnversProxyFactory, commonCollectionMapperData, elementComponentData, indexComponentData, embeddableElementType);
            }
            else if (genericType == typeof(GenericSortedSetType <>))
            {
                var comparerType = createGenericComparerType(type);
                var methodInfo   = ReflectHelper.GetGenericMethodFrom <ICollectionMapperFactory>("SortedSet",
                                                                                                 type.ReturnedClass.GetGenericArguments(),
                                                                                                 new[] { typeof(IEnversProxyFactory), typeof(CommonCollectionMapperData), typeof(MiddleComponentData), comparerType, typeof(bool) });
                collectionMapper = (IPropertyMapper)methodInfo.Invoke(collectionProxyMapperFactory,
                                                                      new[] { _mainGenerator.GlobalCfg.EnversProxyFactory, commonCollectionMapperData, elementComponentData, _propertyValue.Comparer, embeddableElementType });
            }
            else if (genericType == typeof(GenericSetType <>))
            {
                var methodInfo = ReflectHelper.GetGenericMethodFrom <ICollectionMapperFactory>("Set",
                                                                                               type.ReturnedClass.GetGenericArguments(),
                                                                                               new[] { typeof(IEnversProxyFactory), typeof(CommonCollectionMapperData), typeof(MiddleComponentData), typeof(bool) });
                collectionMapper = (IPropertyMapper)methodInfo.Invoke(collectionProxyMapperFactory,
                                                                      new object[] { _mainGenerator.GlobalCfg.EnversProxyFactory, commonCollectionMapperData, elementComponentData, embeddableElementType });
            }
            else if (genericType == typeof(GenericListType <>))
            {
                var methodInfo = ReflectHelper.GetGenericMethodFrom <ICollectionMapperFactory>("List",
                                                                                               type.ReturnedClass.GetGenericArguments(),
                                                                                               new[] { typeof(IEnversProxyFactory), typeof(CommonCollectionMapperData), typeof(MiddleComponentData), typeof(MiddleComponentData), typeof(bool) });
                collectionMapper = (IPropertyMapper)methodInfo.Invoke(collectionProxyMapperFactory,
                                                                      new object[] { _mainGenerator.GlobalCfg.EnversProxyFactory, commonCollectionMapperData, elementComponentData, indexComponentData, embeddableElementType });
            }
            else if (genericType == typeof(GenericSortedDictionaryType <,>))
            {
                var comparerType = createGenericComparerType(type);
                var methodInfo   = ReflectHelper.GetGenericMethodFrom <ICollectionMapperFactory>("SortedMap",
                                                                                                 type.ReturnedClass.GetGenericArguments(),
                                                                                                 new[] { typeof(IEnversProxyFactory), typeof(CommonCollectionMapperData), typeof(MiddleComponentData), typeof(MiddleComponentData), comparerType, typeof(bool) });
                collectionMapper = (IPropertyMapper)methodInfo.Invoke(collectionProxyMapperFactory,
                                                                      new[] { _mainGenerator.GlobalCfg.EnversProxyFactory, commonCollectionMapperData, elementComponentData, indexComponentData, _propertyValue.Comparer, embeddableElementType });
            }
            else if (genericType == typeof(GenericMapType <,>))
            {
                var methodInfo = ReflectHelper.GetGenericMethodFrom <ICollectionMapperFactory>("Map",
                                                                                               type.ReturnedClass.GetGenericArguments(),
                                                                                               new[] { typeof(IEnversProxyFactory), typeof(CommonCollectionMapperData), typeof(MiddleComponentData), typeof(MiddleComponentData), typeof(bool) });
                collectionMapper = (IPropertyMapper)methodInfo.Invoke(collectionProxyMapperFactory,
                                                                      new object[] { _mainGenerator.GlobalCfg.EnversProxyFactory, commonCollectionMapperData, elementComponentData, indexComponentData, embeddableElementType });
            }
            else if (genericType == typeof(GenericBagType <>))
            {
                var methodInfo = ReflectHelper.GetGenericMethodFrom <ICollectionMapperFactory>("Bag",
                                                                                               type.ReturnedClass.GetGenericArguments(),
                                                                                               new[] { typeof(IEnversProxyFactory), typeof(CommonCollectionMapperData), typeof(MiddleComponentData), typeof(bool) });
                collectionMapper = (IPropertyMapper)methodInfo.Invoke(collectionProxyMapperFactory,
                                                                      new object[] { _mainGenerator.GlobalCfg.EnversProxyFactory, commonCollectionMapperData, elementComponentData, embeddableElementType });
            }
            else if (genericType == typeof(GenericIdentifierBagType <>))
            {
                var methodInfo = ReflectHelper.GetGenericMethodFrom <ICollectionMapperFactory>("IdBag",
                                                                                               type.ReturnedClass.GetGenericArguments(),
                                                                                               new[] { typeof(IEnversProxyFactory), typeof(CommonCollectionMapperData), typeof(MiddleComponentData), typeof(bool) });
                collectionMapper = (IPropertyMapper)methodInfo.Invoke(collectionProxyMapperFactory,
                                                                      new object[] { _mainGenerator.GlobalCfg.EnversProxyFactory, commonCollectionMapperData, elementComponentData, embeddableElementType });
            }
            else
            {
                if (type is CustomCollectionType)
                {
                    throw new NotImplementedException("Your custom collection type " + type.Name + " needs a defined " + typeof(ICustomCollectionMapperFactory).Name);
                }
                throw new NotImplementedException("Mapped collection type " + type.Name + " is not currently supported in Envers");
            }

            _currentMapper.AddComposite(_propertyAuditingData.GetPropertyData(), collectionMapper);
        }