private String getMappedBy(Table collectionTable, PersistentClass referencedClass) {
    // If there's an @AuditMappedBy specified, returning it directly.
    String auditMappedBy = propertyAuditingData.getAuditMappedBy();
    if (auditMappedBy != null) {
      return auditMappedBy;
    }

    // searching in referenced class
    String mappedBy = this.searchMappedBy(referencedClass, collectionTable);

    // not found on referenced class, searching on superclasses
    if (mappedBy == null) {
      LOG.debugf(
          "Going to search the mapped by attribute for %s in superclasses of entity: %s",
          propertyName, referencedClass.getClassName());

      PersistentClass tempClass = referencedClass;
      while ((mappedBy == null) && (tempClass.getSuperclass() != null)) {
        LOG.debugf("Searching in superclass: %s", tempClass.getSuperclass().getClassName());
        mappedBy = this.searchMappedBy(tempClass.getSuperclass(), collectionTable);
        tempClass = tempClass.getSuperclass();
      }
    }

    if (mappedBy == null) {
      throw new MappingException(
          "Unable to read the mapped by attribute for "
              + propertyName
              + " in "
              + referencedClass.getClassName()
              + "!");
    }

    return mappedBy;
  }
  public ClassAuditingData getAuditData() {
    if (pc.getClassName() == null) {
      return auditData;
    }

    try {
      XClass xclass = reflectionManager.classForName(pc.getClassName(), this.getClass());

      ModificationStore defaultStore = getDefaultAudited(xclass);
      if (defaultStore != null) {
        auditData.setDefaultAudited(true);
      }

      new AuditedPropertiesReader(
              defaultStore,
              new PersistentClassPropertiesSource(xclass),
              auditData,
              globalCfg,
              reflectionManager,
              "")
          .read();

      addAuditTable(xclass);
      addAuditSecondaryTables(xclass);
    } catch (ClassNotFoundException e) {
      throw new MappingException(e);
    }

    return auditData;
  }
  private String getMappedBy(Collection collectionValue) {
    PersistentClass referencedClass = null;
    if (collectionValue.getElement() instanceof OneToMany) {
      OneToMany oneToManyValue = (OneToMany) collectionValue.getElement();
      referencedClass = oneToManyValue.getAssociatedClass();
    } else if (collectionValue.getElement() instanceof ManyToOne) {
      // Case for bi-directional relation with @JoinTable on the owning @ManyToOne side.
      ManyToOne manyToOneValue = (ManyToOne) collectionValue.getElement();
      referencedClass =
          manyToOneValue.getMappings().getClass(manyToOneValue.getReferencedEntityName());
    }

    // If there's an @AuditMappedBy specified, returning it directly.
    String auditMappedBy = propertyAuditingData.getAuditMappedBy();
    if (auditMappedBy != null) {
      return auditMappedBy;
    }

    // searching in referenced class
    String mappedBy = this.searchMappedBy(referencedClass, collectionValue);

    if (mappedBy == null) {
      LOG.debugf(
          "Going to search the mapped by attribute for %s in superclasses of entity: %s",
          propertyName, referencedClass.getClassName());

      PersistentClass tempClass = referencedClass;
      while ((mappedBy == null) && (tempClass.getSuperclass() != null)) {
        LOG.debugf("Searching in superclass: %s", tempClass.getSuperclass().getClassName());
        mappedBy = this.searchMappedBy(tempClass.getSuperclass(), collectionValue);
        tempClass = tempClass.getSuperclass();
      }
    }

    if (mappedBy == null) {
      throw new MappingException(
          "Unable to read the mapped by attribute for "
              + propertyName
              + " in "
              + referencedClass.getClassName()
              + "!");
    }

    return mappedBy;
  }
 private EntityMetamodel getDeclarerEntityMetamodel(IdentifiableType<?> ownerType) {
   final Type.PersistenceType persistenceType = ownerType.getPersistenceType();
   if (persistenceType == Type.PersistenceType.ENTITY) {
     return context
         .getSessionFactory()
         .getEntityPersister(ownerType.getJavaType().getName())
         .getEntityMetamodel();
   } else if (persistenceType == Type.PersistenceType.MAPPED_SUPERCLASS) {
     PersistentClass persistentClass =
         context.getPersistentClassHostingProperties((MappedSuperclassTypeImpl<?>) ownerType);
     return context
         .getSessionFactory()
         .getEntityPersister(persistentClass.getClassName())
         .getEntityMetamodel();
   } else {
     throw new AssertionFailure(
         "Cannot get the metamodel for PersistenceType: " + persistenceType);
   }
 }
  OgmEntityPersister(
      final PersistentClass persistentClass,
      final EntityRegionAccessStrategy cacheAccessStrategy,
      final NaturalIdRegionAccessStrategy naturalIdRegionAccessStrategy,
      final SessionFactoryImplementor factory,
      final Mapping mapping,
      final EntityDiscriminator discriminator)
      throws HibernateException {
    super(persistentClass, cacheAccessStrategy, naturalIdRegionAccessStrategy, factory);
    if (log.isTraceEnabled()) {
      log.tracef("Creating OgmEntityPersister for %s", persistentClass.getClassName());
    }
    ServiceRegistryImplementor serviceRegistry = factory.getServiceRegistry();
    this.gridDialect = serviceRegistry.getService(GridDialect.class);
    this.optionsService = serviceRegistry.getService(OptionsService.class);

    tableName =
        persistentClass
            .getTable()
            .getQualifiedName(
                factory.getDialect(),
                factory.getSettings().getDefaultCatalogName(),
                factory.getSettings().getDefaultSchemaName());

    this.discriminator = discriminator;

    // SPACES
    // TODO: i'm not sure, but perhaps we should exclude
    //      abstract denormalized tables?

    int spacesSize = 1 + persistentClass.getSynchronizedTables().size();
    spaces = new String[spacesSize];
    spaces[0] = tableName;
    @SuppressWarnings("unchecked")
    Iterator<String> syncTablesIter = persistentClass.getSynchronizedTables().iterator();
    for (int i = 1; i < spacesSize; i++) {
      spaces[i] = syncTablesIter.next();
    }

    HashSet<String> subclassTables = new HashSet<String>();
    Iterator<Table> tableIter = persistentClass.getSubclassTableClosureIterator();
    while (tableIter.hasNext()) {
      Table table = tableIter.next();
      subclassTables.add(
          table.getQualifiedName(
              factory.getDialect(),
              factory.getSettings().getDefaultCatalogName(),
              factory.getSettings().getDefaultSchemaName()));
    }
    subclassSpaces = ArrayHelper.toStringArray(subclassTables);

    if (isMultiTable()) {
      int idColumnSpan = getIdentifierColumnSpan();
      ArrayList<String> tableNames = new ArrayList<String>();
      ArrayList<String[]> keyColumns = new ArrayList<String[]>();
      if (!isAbstract()) {
        tableNames.add(tableName);
        keyColumns.add(getIdentifierColumnNames());
      }
      @SuppressWarnings("unchecked")
      Iterator<Table> iter = persistentClass.getSubclassTableClosureIterator();
      while (iter.hasNext()) {
        Table tab = iter.next();
        if (!tab.isAbstractUnionTable()) {
          String tableName =
              tab.getQualifiedName(
                  factory.getDialect(),
                  factory.getSettings().getDefaultCatalogName(),
                  factory.getSettings().getDefaultSchemaName());
          tableNames.add(tableName);
          String[] key = new String[idColumnSpan];
          @SuppressWarnings("unchecked")
          Iterator<Column> citer = tab.getPrimaryKey().getColumnIterator();
          for (int k = 0; k < idColumnSpan; k++) {
            key[k] = citer.next().getQuotedName(factory.getDialect());
          }
          keyColumns.add(key);
        }
      }

      constraintOrderedTableNames = ArrayHelper.toStringArray(tableNames);
      constraintOrderedKeyColumnNames = ArrayHelper.to2DStringArray(keyColumns);
    } else {
      constraintOrderedTableNames = new String[] {tableName};
      constraintOrderedKeyColumnNames = new String[][] {getIdentifierColumnNames()};
    }

    initPropertyPaths(mapping);

    // Grid related metadata
    TypeTranslator typeTranslator = serviceRegistry.getService(TypeTranslator.class);
    final Type[] types = getPropertyTypes();
    final int length = types.length;
    gridPropertyTypes = new GridType[length];
    for (int index = 0; index < length; index++) {
      gridPropertyTypes[index] = typeTranslator.getType(types[index]);
    }
    gridVersionType = typeTranslator.getType(getVersionType());
    gridIdentifierType = typeTranslator.getType(getIdentifierType());
    List<String> columnNames = new ArrayList<String>();
    for (int propertyCount = 0; propertyCount < this.getPropertySpan(); propertyCount++) {
      String[] property = this.getPropertyColumnNames(propertyCount);
      for (int columnCount = 0; columnCount < property.length; columnCount++) {
        columnNames.add(property[columnCount]);
      }
    }
    if (discriminator.getColumnName() != null) {
      columnNames.add(discriminator.getColumnName());
    }
    this.tupleContext =
        new TupleContext(columnNames, optionsService.context().getEntityOptions(getMappedClass()));
    jpaEntityName = persistentClass.getJpaEntityName();
    entityKeyMetadata = new EntityKeyMetadata(getTableName(), getIdentifierColumnNames());
    // load unique key association key metadata
    associationKeyMetadataPerPropertyName = new HashMap<String, AssociationKeyMetadata>();
    initAssociationKeyMetadata();
    initCustomSQLStrings();
  }
  public RevisionInfoConfigurationResult configure(
      Configuration cfg, ReflectionManager reflectionManager) {
    Iterator<PersistentClass> classes = (Iterator<PersistentClass>) cfg.getClassMappings();
    boolean revisionEntityFound = false;
    RevisionInfoGenerator revisionInfoGenerator = null;

    Class<?> revisionInfoClass = null;

    while (classes.hasNext()) {
      PersistentClass pc = classes.next();
      XClass clazz;
      try {
        clazz = reflectionManager.classForName(pc.getClassName(), this.getClass());
      } catch (ClassNotFoundException e) {
        throw new MappingException(e);
      }

      RevisionEntity revisionEntity = clazz.getAnnotation(RevisionEntity.class);
      if (revisionEntity != null) {
        if (revisionEntityFound) {
          throw new MappingException("Only one entity may be annotated with @RevisionEntity!");
        }

        // Checking if custom revision entity isn't audited
        if (clazz.getAnnotation(Audited.class) != null) {
          throw new MappingException("An entity annotated with @RevisionEntity cannot be audited!");
        }

        revisionEntityFound = true;

        MutableBoolean revisionNumberFound = new MutableBoolean();
        MutableBoolean revisionTimestampFound = new MutableBoolean();
        MutableBoolean modifiedEntityNamesFound = new MutableBoolean();

        searchForRevisionInfoCfg(
            clazz,
            reflectionManager,
            revisionNumberFound,
            revisionTimestampFound,
            modifiedEntityNamesFound);

        if (!revisionNumberFound.isSet()) {
          throw new MappingException(
              "An entity annotated with @RevisionEntity must have a field annotated "
                  + "with @RevisionNumber!");
        }

        if (!revisionTimestampFound.isSet()) {
          throw new MappingException(
              "An entity annotated with @RevisionEntity must have a field annotated "
                  + "with @RevisionTimestamp!");
        }

        revisionInfoEntityName = pc.getEntityName();
        revisionInfoClass = pc.getMappedClass();
        Class<? extends RevisionListener> revisionListenerClass =
            getRevisionListenerClass(revisionEntity.value());
        revisionInfoTimestampType = pc.getProperty(revisionInfoTimestampData.getName()).getType();
        if (globalCfg.isTrackEntitiesChangedInRevisionEnabled()
            || DefaultTrackingModifiedEntitiesRevisionEntity.class.isAssignableFrom(
                revisionInfoClass)
            || modifiedEntityNamesFound.isSet()) {
          // If tracking modified entities parameter is enabled, custom revision info entity is a
          // subtype
          // of DefaultTrackingModifiedEntitiesRevisionEntity class, or @ModifiedEntityNames
          // annotation is used.
          revisionInfoGenerator =
              new DefaultTrackingModifiedEntitiesRevisionInfoGenerator(
                  revisionInfoEntityName,
                  revisionInfoClass,
                  revisionListenerClass,
                  revisionInfoTimestampData,
                  isTimestampAsDate(),
                  modifiedEntityNamesData);
          globalCfg.setTrackEntitiesChangedInRevisionEnabled(true);
        } else {
          revisionInfoGenerator =
              new DefaultRevisionInfoGenerator(
                  revisionInfoEntityName,
                  revisionInfoClass,
                  revisionListenerClass,
                  revisionInfoTimestampData,
                  isTimestampAsDate());
        }
      }
    }

    // In case of a custom revision info generator, the mapping will be null.
    Document revisionInfoXmlMapping = null;

    Class<? extends RevisionListener> revisionListenerClass =
        getRevisionListenerClass(RevisionListener.class);

    if (revisionInfoGenerator == null) {
      if (globalCfg.isTrackEntitiesChangedInRevisionEnabled()) {
        revisionInfoClass = DefaultTrackingModifiedEntitiesRevisionEntity.class;
        revisionInfoEntityName = DefaultTrackingModifiedEntitiesRevisionEntity.class.getName();
        revisionInfoGenerator =
            new DefaultTrackingModifiedEntitiesRevisionInfoGenerator(
                revisionInfoEntityName,
                revisionInfoClass,
                revisionListenerClass,
                revisionInfoTimestampData,
                isTimestampAsDate(),
                modifiedEntityNamesData);
      } else {
        revisionInfoClass = DefaultRevisionEntity.class;
        revisionInfoGenerator =
            new DefaultRevisionInfoGenerator(
                revisionInfoEntityName,
                revisionInfoClass,
                revisionListenerClass,
                revisionInfoTimestampData,
                isTimestampAsDate());
      }
      revisionInfoXmlMapping = generateDefaultRevisionInfoXmlMapping();
    }

    return new RevisionInfoConfigurationResult(
        revisionInfoGenerator,
        revisionInfoXmlMapping,
        new RevisionInfoQueryCreator(
            revisionInfoEntityName,
            revisionInfoIdData.getName(),
            revisionInfoTimestampData.getName(),
            isTimestampAsDate()),
        generateRevisionInfoRelationMapping(),
        new RevisionInfoNumberReader(revisionInfoClass, revisionInfoIdData),
        globalCfg.isTrackEntitiesChangedInRevisionEnabled()
            ? new ModifiedEntityNamesReader(revisionInfoClass, modifiedEntityNamesData)
            : null,
        revisionInfoEntityName,
        revisionInfoClass,
        revisionInfoTimestampData);
  }