Пример #1
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();
                }
            }
        }
        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));
        }
Пример #3
0
 private MiddleComponentData AddIndex(XmlElement middleEntityXml, QueryGeneratorBuilder queryGeneratorBuilder)
 {
     if (propertyValue is IndexedCollection)
     {
         IndexedCollection indexedValue = (IndexedCollection)propertyValue;
         String            mapKey       = propertyAuditingData.MapKey;
         if (mapKey == null)
         {
             // This entity doesn't specify a javax.persistence.MapKey. Mapping it to the middle entity.
             return(AddValueToMiddleTable(indexedValue.Index, middleEntityXml,
                                          queryGeneratorBuilder, "mapkey", null));
         }
         else
         {
             IdMappingData referencedIdMapping =
                 mainGenerator.EntitiesConfigurations[referencedEntityName].IdMappingData;
             int currentIndex = queryGeneratorBuilder == null ? 0 : queryGeneratorBuilder.CurrentIndex;
             if ("".Equals(mapKey))
             {
                 // The key of the map is the id of the entity.
                 return(new MiddleComponentData(new MiddleMapKeyIdComponentMapper(mainGenerator.VerEntCfg,
                                                                                  referencedIdMapping.IdMapper), currentIndex));
             }
             else
             {
                 // The key of the map is a property of the entity.
                 return(new MiddleComponentData(new MiddleMapKeyPropertyComponentMapper(mapKey,
                                                                                        propertyAuditingData.AccessType), currentIndex));
             }
         }
     }
     else
     {
         // No index - creating a dummy mapper.
         return(new MiddleComponentData(new MiddleDummyComponentMapper(), 0));
     }
 }
Пример #4
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();
        }
Пример #5
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);
        }
Пример #6
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);
        }