private FromElement createManyToMany(
     String role,
     String associatedEntityName,
     String roleAlias,
     Queryable entityPersister,
     EntityType type,
     int joinType)
     throws SemanticException {
   FromElement elem;
   SessionFactoryHelper sfh = fromClause.getSessionFactoryHelper();
   if (inElementsFunction /*implied*/) {
     // For implied many-to-many, just add the end join.
     JoinSequence joinSequence = createJoinSequence(roleAlias, joinType);
     elem = createJoin(associatedEntityName, roleAlias, joinSequence, type, true);
   } else {
     // For an explicit many-to-many relationship, add a second join from the intermediate
     // (many-to-many) table to the destination table.  Also, make sure that the from element's
     // idea of the destination is the destination table.
     String tableAlias =
         fromClause.getAliasGenerator().createName(entityPersister.getEntityName());
     String[] secondJoinColumns = sfh.getCollectionElementColumns(role, roleAlias);
     // Add the second join, the one that ends in the destination table.
     JoinSequence joinSequence = createJoinSequence(roleAlias, joinType);
     joinSequence.addJoin(
         sfh.getElementAssociationType(collectionType), tableAlias, joinType, secondJoinColumns);
     elem = createJoin(associatedEntityName, tableAlias, joinSequence, type, false);
     elem.setUseFromFragment(true);
   }
   return elem;
 }
  public String addFromCollection(QueryTranslatorImpl q) throws QueryException {
    Type collectionElementType = getPropertyType();

    if (collectionElementType == null) {
      throw new QueryException(
          "must specify 'elements' for collection valued property in from clause: " + path);
    }

    if (collectionElementType.isEntityType()) {
      // an association
      QueryableCollection collectionPersister = q.getCollectionPersister(collectionRole);
      Queryable entityPersister = (Queryable) collectionPersister.getElementPersister();
      String clazz = entityPersister.getEntityName();

      final String elementName;
      if (collectionPersister.isOneToMany()) {
        elementName = collectionName;
        // allow index() function:
        q.decoratePropertyMapping(elementName, collectionPersister);
      } else { // many-to-many
        q.addCollection(collectionName, collectionRole);
        elementName = q.createNameFor(clazz);
        addJoin(elementName, (AssociationType) collectionElementType);
      }
      q.addFrom(elementName, clazz, joinSequence);
      currentPropertyMapping = new CollectionPropertyMapping(collectionPersister);
      return elementName;
    } else {
      // collections of values
      q.addFromCollection(collectionName, collectionRole, joinSequence);
      return collectionName;
    }
  }
  protected AST createIntoClause(String path, AST propertySpec) throws SemanticException {
    Queryable persister = (Queryable) getSessionFactoryHelper().requireClassPersister(path);

    IntoClause intoClause = (IntoClause) getASTFactory().create(INTO, persister.getEntityName());
    intoClause.setFirstChild(propertySpec);
    intoClause.initialize(persister);

    addQuerySpaces(persister.getQuerySpaces());

    return intoClause;
  }
  protected String generateIdInsertSelect(Queryable persister, String tableAlias, AST whereClause) {
    Select select = new Select(getFactory().getDialect());
    SelectFragment selectFragment =
        new SelectFragment()
            .addColumns(
                tableAlias,
                persister.getIdentifierColumnNames(),
                persister.getIdentifierColumnNames());
    select.setSelectClause(selectFragment.toFragmentString().substring(2));

    String rootTableName = persister.getTableName();
    String fromJoinFragment = persister.fromJoinFragment(tableAlias, true, false);
    String whereJoinFragment = persister.whereJoinFragment(tableAlias, true, false);

    select.setFromClause(rootTableName + ' ' + tableAlias + fromJoinFragment);

    if (whereJoinFragment == null) {
      whereJoinFragment = "";
    } else {
      whereJoinFragment = whereJoinFragment.trim();
      if (whereJoinFragment.startsWith("and")) {
        whereJoinFragment = whereJoinFragment.substring(4);
      }
    }

    String userWhereClause = "";
    if (whereClause.getNumberOfChildren() != 0) {
      // If a where clause was specified in the update/delete query, use it to limit the
      // returned ids here...
      try {
        SqlGenerator sqlGenerator = new SqlGenerator(getFactory());
        sqlGenerator.whereClause(whereClause);
        userWhereClause = sqlGenerator.getSQL().substring(7); // strip the " where "
      } catch (RecognitionException e) {
        throw new HibernateException("Unable to generate id select for DML operation", e);
      }
      if (whereJoinFragment.length() > 0) {
        whereJoinFragment += " and ";
      }
    }

    select.setWhereClause(whereJoinFragment + userWhereClause);

    InsertSelect insert = new InsertSelect(getFactory().getDialect());
    if (getFactory().getSettings().isCommentsEnabled()) {
      insert.setComment("insert-select for " + persister.getEntityName() + " ids");
    }
    insert.setTableName(persister.getTemporaryIdTableName());
    insert.setSelect(select);
    return insert.toStatementString();
  }
  private FromElement createEntityAssociation(String role, String roleAlias, int joinType)
      throws SemanticException {
    FromElement elem;
    Queryable entityPersister = (Queryable) queryableCollection.getElementPersister();
    String associatedEntityName = entityPersister.getEntityName();
    // Get the class name of the associated entity.
    if (queryableCollection.isOneToMany()) {
      if (log.isDebugEnabled()) {
        log.debug(
            "createEntityAssociation() : One to many - path = "
                + path
                + " role = "
                + role
                + " associatedEntityName = "
                + associatedEntityName);
      }
      JoinSequence joinSequence = createJoinSequence(roleAlias, joinType);

      elem =
          createJoin(
              associatedEntityName,
              roleAlias,
              joinSequence,
              (EntityType) queryableCollection.getElementType(),
              false);
    } else {
      if (log.isDebugEnabled()) {
        log.debug(
            "createManyToMany() : path = "
                + path
                + " role = "
                + role
                + " associatedEntityName = "
                + associatedEntityName);
      }
      elem =
          createManyToMany(
              role,
              associatedEntityName,
              roleAlias,
              entityPersister,
              (EntityType) queryableCollection.getElementType(),
              joinType);
      fromClause.getWalker().addQuerySpaces(queryableCollection.getCollectionSpaces());
    }
    elem.setCollectionTableAlias(roleAlias);
    return elem;
  }
  /**
   * Return the names of all persistent (mapped) classes that extend or implement the given class or
   * interface, accounting for implicit/explicit polymorphism settings and excluding mapped
   * subclasses/joined-subclasses of other classes in the result.
   */
  public String[] getImplementors(String className) throws MappingException {

    final Class clazz;
    try {
      clazz = ReflectHelper.classForName(className);
    } catch (ClassNotFoundException cnfe) {
      return new String[] {className}; // for a dynamic-class
    }

    ArrayList results = new ArrayList();
    Iterator iter = entityPersisters.values().iterator();
    while (iter.hasNext()) {
      // test this entity to see if we must query it
      EntityPersister testPersister = (EntityPersister) iter.next();
      if (testPersister instanceof Queryable) {
        Queryable testQueryable = (Queryable) testPersister;
        String testClassName = testQueryable.getEntityName();
        boolean isMappedClass = className.equals(testClassName);
        if (testQueryable.isExplicitPolymorphism()) {
          if (isMappedClass) {
            return new String[] {className}; // NOTE EARLY EXIT
          }
        } else {
          if (isMappedClass) {
            results.add(testClassName);
          } else {
            final Class mappedClass = testQueryable.getMappedClass(EntityMode.POJO);
            if (mappedClass != null && clazz.isAssignableFrom(mappedClass)) {
              final boolean assignableSuperclass;
              if (testQueryable.isInherited()) {
                Class mappedSuperclass =
                    getEntityPersister(testQueryable.getMappedSuperclass())
                        .getMappedClass(EntityMode.POJO);
                assignableSuperclass = clazz.isAssignableFrom(mappedSuperclass);
              } else {
                assignableSuperclass = false;
              }
              if (!assignableSuperclass) {
                results.add(testClassName);
              }
            }
          }
        }
      }
    }
    return (String[]) results.toArray(new String[results.size()]);
  }
 private String getPathEntityName(String path) {
   Queryable persister = (Queryable) sessionFactory.getEntityPersister(rootEntityName);
   StringTokenizer tokens = new StringTokenizer(path, ".");
   String componentPath = "";
   while (tokens.hasMoreTokens()) {
     componentPath += tokens.nextToken();
     Type type = persister.toType(componentPath);
     if (type.isAssociationType()) {
       AssociationType atype = (AssociationType) type;
       persister =
           (Queryable)
               sessionFactory.getEntityPersister(atype.getAssociatedEntityName(sessionFactory));
       componentPath = "";
     } else if (type.isComponentType()) {
       componentPath += '.';
     } else {
       throw new QueryException("not an association: " + componentPath);
     }
   }
   return persister.getEntityName();
 }
  public CustomLoader(CustomQuery customQuery, SessionFactoryImplementor factory) {
    super(factory);

    this.sql = customQuery.getSQL();
    this.querySpaces.addAll(customQuery.getQuerySpaces());
    this.namedParameterBindPoints = customQuery.getNamedParameterBindPoints();

    List entityPersisters = new ArrayList();
    List entityOwners = new ArrayList();
    List entityAliases = new ArrayList();

    List collectionPersisters = new ArrayList();
    List collectionOwners = new ArrayList();
    List collectionAliases = new ArrayList();

    List lockModes = new ArrayList();
    List resultColumnProcessors = new ArrayList();
    List nonScalarReturnList = new ArrayList();
    List resultTypes = new ArrayList();
    List specifiedAliases = new ArrayList();
    int returnableCounter = 0;
    boolean hasScalars = false;

    List includeInResultRowList = new ArrayList();

    Iterator itr = customQuery.getCustomQueryReturns().iterator();
    while (itr.hasNext()) {
      final Return rtn = (Return) itr.next();
      if (rtn instanceof ScalarReturn) {
        ScalarReturn scalarRtn = (ScalarReturn) rtn;
        resultTypes.add(scalarRtn.getType());
        specifiedAliases.add(scalarRtn.getColumnAlias());
        resultColumnProcessors.add(
            new ScalarResultColumnProcessor(
                StringHelper.unquote(scalarRtn.getColumnAlias(), factory.getDialect()),
                scalarRtn.getType()));
        includeInResultRowList.add(true);
        hasScalars = true;
      } else if (ConstructorReturn.class.isInstance(rtn)) {
        final ConstructorReturn constructorReturn = (ConstructorReturn) rtn;
        resultTypes.add(null); // this bit makes me nervous
        includeInResultRowList.add(true);
        hasScalars = true;

        ScalarResultColumnProcessor[] scalarProcessors =
            new ScalarResultColumnProcessor[constructorReturn.getScalars().length];
        int i = 0;
        for (ScalarReturn scalarReturn : constructorReturn.getScalars()) {
          scalarProcessors[i++] =
              new ScalarResultColumnProcessor(
                  StringHelper.unquote(scalarReturn.getColumnAlias(), factory.getDialect()),
                  scalarReturn.getType());
        }

        resultColumnProcessors.add(
            new ConstructorResultColumnProcessor(
                constructorReturn.getTargetClass(), scalarProcessors));
      } else if (rtn instanceof RootReturn) {
        RootReturn rootRtn = (RootReturn) rtn;
        Queryable persister = (Queryable) factory.getEntityPersister(rootRtn.getEntityName());
        entityPersisters.add(persister);
        lockModes.add((rootRtn.getLockMode()));
        resultColumnProcessors.add(new NonScalarResultColumnProcessor(returnableCounter++));
        nonScalarReturnList.add(rtn);
        entityOwners.add(-1);
        resultTypes.add(persister.getType());
        specifiedAliases.add(rootRtn.getAlias());
        entityAliases.add(rootRtn.getEntityAliases());
        ArrayHelper.addAll(querySpaces, persister.getQuerySpaces());
        includeInResultRowList.add(true);
      } else if (rtn instanceof CollectionReturn) {
        CollectionReturn collRtn = (CollectionReturn) rtn;
        String role = collRtn.getOwnerEntityName() + "." + collRtn.getOwnerProperty();
        QueryableCollection persister = (QueryableCollection) factory.getCollectionPersister(role);
        collectionPersisters.add(persister);
        lockModes.add(collRtn.getLockMode());
        resultColumnProcessors.add(new NonScalarResultColumnProcessor(returnableCounter++));
        nonScalarReturnList.add(rtn);
        collectionOwners.add(-1);
        resultTypes.add(persister.getType());
        specifiedAliases.add(collRtn.getAlias());
        collectionAliases.add(collRtn.getCollectionAliases());
        // determine if the collection elements are entities...
        Type elementType = persister.getElementType();
        if (elementType.isEntityType()) {
          Queryable elementPersister =
              (Queryable) ((EntityType) elementType).getAssociatedJoinable(factory);
          entityPersisters.add(elementPersister);
          entityOwners.add(-1);
          entityAliases.add(collRtn.getElementEntityAliases());
          ArrayHelper.addAll(querySpaces, elementPersister.getQuerySpaces());
        }
        includeInResultRowList.add(true);
      } else if (rtn instanceof EntityFetchReturn) {
        EntityFetchReturn fetchRtn = (EntityFetchReturn) rtn;
        NonScalarReturn ownerDescriptor = fetchRtn.getOwner();
        int ownerIndex = nonScalarReturnList.indexOf(ownerDescriptor);
        entityOwners.add(ownerIndex);
        lockModes.add(fetchRtn.getLockMode());
        Queryable ownerPersister = determineAppropriateOwnerPersister(ownerDescriptor);
        EntityType fetchedType =
            (EntityType) ownerPersister.getPropertyType(fetchRtn.getOwnerProperty());
        String entityName = fetchedType.getAssociatedEntityName(getFactory());
        Queryable persister = (Queryable) factory.getEntityPersister(entityName);
        entityPersisters.add(persister);
        nonScalarReturnList.add(rtn);
        specifiedAliases.add(fetchRtn.getAlias());
        entityAliases.add(fetchRtn.getEntityAliases());
        ArrayHelper.addAll(querySpaces, persister.getQuerySpaces());
        includeInResultRowList.add(false);
      } else if (rtn instanceof CollectionFetchReturn) {
        CollectionFetchReturn fetchRtn = (CollectionFetchReturn) rtn;
        NonScalarReturn ownerDescriptor = fetchRtn.getOwner();
        int ownerIndex = nonScalarReturnList.indexOf(ownerDescriptor);
        collectionOwners.add(ownerIndex);
        lockModes.add(fetchRtn.getLockMode());
        Queryable ownerPersister = determineAppropriateOwnerPersister(ownerDescriptor);
        String role = ownerPersister.getEntityName() + '.' + fetchRtn.getOwnerProperty();
        QueryableCollection persister = (QueryableCollection) factory.getCollectionPersister(role);
        collectionPersisters.add(persister);
        nonScalarReturnList.add(rtn);
        specifiedAliases.add(fetchRtn.getAlias());
        collectionAliases.add(fetchRtn.getCollectionAliases());
        // determine if the collection elements are entities...
        Type elementType = persister.getElementType();
        if (elementType.isEntityType()) {
          Queryable elementPersister =
              (Queryable) ((EntityType) elementType).getAssociatedJoinable(factory);
          entityPersisters.add(elementPersister);
          entityOwners.add(ownerIndex);
          entityAliases.add(fetchRtn.getElementEntityAliases());
          ArrayHelper.addAll(querySpaces, elementPersister.getQuerySpaces());
        }
        includeInResultRowList.add(false);
      } else {
        throw new HibernateException(
            "unexpected custom query return type : " + rtn.getClass().getName());
      }
    }

    this.entityPersisters = new Queryable[entityPersisters.size()];
    for (int i = 0; i < entityPersisters.size(); i++) {
      this.entityPersisters[i] = (Queryable) entityPersisters.get(i);
    }
    this.entiytOwners = ArrayHelper.toIntArray(entityOwners);
    this.entityAliases = new EntityAliases[entityAliases.size()];
    for (int i = 0; i < entityAliases.size(); i++) {
      this.entityAliases[i] = (EntityAliases) entityAliases.get(i);
    }

    this.collectionPersisters = new QueryableCollection[collectionPersisters.size()];
    for (int i = 0; i < collectionPersisters.size(); i++) {
      this.collectionPersisters[i] = (QueryableCollection) collectionPersisters.get(i);
    }
    this.collectionOwners = ArrayHelper.toIntArray(collectionOwners);
    this.collectionAliases = new CollectionAliases[collectionAliases.size()];
    for (int i = 0; i < collectionAliases.size(); i++) {
      this.collectionAliases[i] = (CollectionAliases) collectionAliases.get(i);
    }

    this.lockModes = new LockMode[lockModes.size()];
    for (int i = 0; i < lockModes.size(); i++) {
      this.lockModes[i] = (LockMode) lockModes.get(i);
    }

    this.resultTypes = ArrayHelper.toTypeArray(resultTypes);
    this.transformerAliases = ArrayHelper.toStringArray(specifiedAliases);

    this.rowProcessor =
        new ResultRowProcessor(
            hasScalars,
            (ResultColumnProcessor[])
                resultColumnProcessors.toArray(
                    new ResultColumnProcessor[resultColumnProcessors.size()]));

    this.includeInResultRow = ArrayHelper.toBooleanArray(includeInResultRowList);
  }
 void addFromClass(String name, Queryable classPersister) throws QueryException {
   JoinSequence joinSequence = new JoinSequence(getFactory()).setRoot(classPersister, name);
   // crossJoins.add(name);
   addFrom(name, classPersister.getEntityName(), joinSequence);
 }