protected AST lookupProperty(AST dot, boolean root, boolean inSelect) throws SemanticException {
   DotNode dotNode = (DotNode) dot;
   FromReferenceNode lhs = dotNode.getLhs();
   AST rhs = lhs.getNextSibling();
   switch (rhs.getType()) {
     case SqlTokenTypes.ELEMENTS:
     case SqlTokenTypes.INDICES:
       if (log.isDebugEnabled()) {
         log.debug(
             "lookupProperty() "
                 + dotNode.getPath()
                 + " => "
                 + rhs.getText()
                 + "("
                 + lhs.getPath()
                 + ")");
       }
       CollectionFunction f = (CollectionFunction) rhs;
       // Re-arrange the tree so that the collection function is the root and the lhs is the path.
       f.setFirstChild(lhs);
       lhs.setNextSibling(null);
       dotNode.setFirstChild(f);
       resolve(lhs); // Don't forget to resolve the argument!
       f.resolve(inSelect); // Resolve the collection function now.
       return f;
     default:
       // Resolve everything up to this dot, but don't resolve the placeholders yet.
       dotNode.resolveFirstChild();
       return dotNode;
   }
 }
    public void visit(AST node) {
      // todo : currently expects that the individual with expressions apply to the same sql table
      // join.
      //      This may not be the case for joined-subclass where the property values
      //      might be coming from different tables in the joined hierarchy.  At some
      //      point we should expand this to support that capability.  However, that has
      //      some difficulties:
      //          1) the biggest is how to handle ORs when the individual comparisons are
      //              linked to different sql joins.
      //          2) here we would need to track each comparison individually, along with
      //              the join alias to which it applies and then pass that information
      //              back to the FromElement so it can pass it along to the JoinSequence

      if (node instanceof DotNode) {
        DotNode dotNode = (DotNode) node;
        FromElement fromElement = dotNode.getFromElement();
        if (referencedFromElement != null) {
          if (fromElement != referencedFromElement) {
            throw new HibernateException(
                "with-clause referenced two different from-clause elements");
          }
        } else {
          referencedFromElement = fromElement;
          joinAlias = extractAppliedAlias(dotNode);
          // todo : temporary
          //      needed because currently persister is the one that
          //      creates and renders the join fragments for inheritence
          //      hierarchies...
          if (!joinAlias.equals(referencedFromElement.getTableAlias())) {
            throw new HibernateException(
                "with clause can only reference columns in the driving table");
          }
        }
      }
    }
  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 resolveSelectExpression(AST node) throws SemanticException {
   // This is called when it's time to fully resolve a path expression.
   int type = node.getType();
   switch (type) {
     case DOT:
       DotNode dot = (DotNode) node;
       dot.resolveSelectExpression();
       break;
     case ALIAS_REF:
       // Notify the FROM element that it is being referenced by the select.
       FromReferenceNode aliasRefNode = (FromReferenceNode) node;
       // aliasRefNode.resolve( false, false, aliasRefNode.getText() ); //TODO: is it kosher to do
       // it here?
       aliasRefNode.resolve(false, false); // TODO: is it kosher to do it here?
       FromElement fromElement = aliasRefNode.getFromElement();
       if (fromElement != null) {
         fromElement.setIncludeSubclasses(true);
       }
     default:
       break;
   }
 }
  private AST generateSyntheticDotNodeForNonQualifiedPropertyRef(
      AST property, FromElement fromElement) {
    AST dot = getASTFactory().create(DOT, "{non-qualified-property-ref}");
    // TODO : better way?!?
    ((DotNode) dot).setPropertyPath(((FromReferenceNode) property).getPath());

    IdentNode syntheticAlias = (IdentNode) getASTFactory().create(IDENT, "{synthetic-alias}");
    syntheticAlias.setFromElement(fromElement);
    syntheticAlias.setResolved();

    dot.setFirstChild(syntheticAlias);
    dot.addChild(property);

    return dot;
  }
 private String extractAppliedAlias(DotNode dotNode) {
   return dotNode.getText().substring(0, dotNode.getText().indexOf('.'));
 }