private void addMapper(
     CommonCollectionMapperData commonCollectionMapperData,
     MiddleComponentData elementComponentData,
     MiddleComponentData indexComponentData) {
   Type type = propertyValue.getType();
   if (type instanceof SortedSetType) {
     currentMapper.addComposite(
         propertyAuditingData.getPropertyData(),
         new SortedSetCollectionMapper(
             commonCollectionMapperData,
             TreeSet.class,
             SortedSetProxy.class,
             elementComponentData,
             propertyValue.getComparator()));
   } else if (type instanceof SetType) {
     currentMapper.addComposite(
         propertyAuditingData.getPropertyData(),
         new BasicCollectionMapper<Set>(
             commonCollectionMapperData, HashSet.class, SetProxy.class, elementComponentData));
   } else if (type instanceof SortedMapType) {
     // Indexed collection, so <code>indexComponentData</code> is not null.
     currentMapper.addComposite(
         propertyAuditingData.getPropertyData(),
         new SortedMapCollectionMapper(
             commonCollectionMapperData,
             TreeMap.class,
             SortedMapProxy.class,
             elementComponentData,
             indexComponentData,
             propertyValue.getComparator()));
   } else if (type instanceof 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 instanceof BagType) {
     currentMapper.addComposite(
         propertyAuditingData.getPropertyData(),
         new BasicCollectionMapper<List>(
             commonCollectionMapperData, ArrayList.class, ListProxy.class, elementComponentData));
   } else if (type instanceof 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);
   }
 }
  /**
   * @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(
      Value value,
      Element xmlMapping,
      QueryGeneratorBuilder queryGeneratorBuilder,
      String prefix,
      JoinColumn[] joinColumns) {
    Type type = value.getType();
    if (type instanceof 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.getColumnNameIterator(joinColumns)
                : MetadataTools.getColumnNameIterator(value.getColumnIterator()),
            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.getCurrentIndex());
    } else {
      // Last but one parameter: collection components are always insertable
      boolean mapped =
          mainGenerator
              .getBasicMetadataGenerator()
              .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.getVerEntCfg(), prefix), 0);
      } else {
        mainGenerator.throwUnsupportedTypeException(type, referencingEntityName, propertyName);
        // Impossible to get here.
        throw new AssertionError();
      }
    }
  }