protected void processQuery(AST select, AST query) throws SemanticException {
    if (log.isDebugEnabled()) {
      log.debug("processQuery() : " + query.toStringTree());
    }

    try {
      QueryNode qn = (QueryNode) query;

      // Was there an explicit select expression?
      boolean explicitSelect = select != null && select.getNumberOfChildren() > 0;

      if (!explicitSelect) {
        // No explicit select expression; render the id and properties
        // projection lists for every persister in the from clause into
        // a single 'token node'.
        // TODO: the only reason we need this stuff now is collection filters,
        //      we should get rid of derived select clause completely!
        createSelectClauseFromFromClause(qn);
      } else {
        // Use the explicitly declared select expression; determine the
        // return types indicated by each select token
        useSelectClause(select);
      }

      // After that, process the JOINs.
      // Invoke a delegate to do the work, as this is farily complex.
      JoinProcessor joinProcessor = new JoinProcessor(astFactory, queryTranslatorImpl);
      joinProcessor.processJoins(qn, isSubQuery());

      // Attach any mapping-defined "ORDER BY" fragments
      Iterator itr = qn.getFromClause().getProjectionList().iterator();
      while (itr.hasNext()) {
        final FromElement fromElement = (FromElement) itr.next();
        //			if ( fromElement.isFetch() && fromElement.isCollectionJoin() ) {
        if (fromElement.isFetch() && fromElement.getQueryableCollection() != null) {
          // Does the collection referenced by this FromElement
          // specify an order-by attribute?  If so, attach it to
          // the query's order-by
          if (fromElement.getQueryableCollection().hasOrdering()) {
            String orderByFragment =
                fromElement
                    .getQueryableCollection()
                    .getSQLOrderByString(fromElement.getCollectionTableAlias());
            qn.getOrderByClause().addOrderFragment(orderByFragment);
          }
          if (fromElement.getQueryableCollection().hasManyToManyOrdering()) {
            String orderByFragment =
                fromElement
                    .getQueryableCollection()
                    .getManyToManyOrderByString(fromElement.getTableAlias());
            qn.getOrderByClause().addOrderFragment(orderByFragment);
          }
        }
      }
    } finally {
      popFromClause();
    }
  }
  protected void createFromJoinElement(
      AST path, AST alias, int joinType, AST fetchNode, AST propertyFetch, AST with)
      throws SemanticException {
    boolean fetch = fetchNode != null;
    if (fetch && isSubQuery()) {
      throw new QueryException("fetch not allowed in subquery from-elements");
    }
    // The path AST should be a DotNode, and it should have been evaluated already.
    if (path.getType() != SqlTokenTypes.DOT) {
      throw new SemanticException("Path expected for join!");
    }
    DotNode dot = (DotNode) path;
    int hibernateJoinType = JoinProcessor.toHibernateJoinType(joinType);
    dot.setJoinType(hibernateJoinType); // Tell the dot node about the join type.
    dot.setFetch(fetch);
    // Generate an explicit join for the root dot node.   The implied joins will be collected and
    // passed up
    // to the root dot node.
    dot.resolve(true, false, alias == null ? null : alias.getText());
    FromElement fromElement = dot.getImpliedJoin();
    fromElement.setAllPropertyFetch(propertyFetch != null);

    if (with != null) {
      if (fetch) {
        throw new SemanticException("with-clause not allowed on fetched associations; use filters");
      }
      handleWithFragment(fromElement, with);
    }

    if (log.isDebugEnabled()) {
      log.debug(
          "createFromJoinElement() : "
              + getASTPrinter().showAsString(fromElement, "-- join tree --"));
    }
  }
 protected void setImpliedJoinType(int joinType) {
   impliedJoinType = JoinProcessor.toHibernateJoinType(joinType);
 }