public void processJoins(QueryNode query) {
    final FromClause fromClause = query.getFromClause();

    final List fromElements;
    if (DotNode.useThetaStyleImplicitJoins) {
      // for regression testing against output from the old parser...
      // found it easiest to simply reorder the FromElements here into ascending order
      // in terms of injecting them into the resulting sql ast in orders relative to those
      // expected by the old parser; this is definitely another of those "only needed
      // for regression purposes".  The SyntheticAndFactory, then, simply injects them as it
      // encounters them.
      fromElements = new ArrayList();
      ListIterator liter =
          fromClause.getFromElements().listIterator(fromClause.getFromElements().size());
      while (liter.hasPrevious()) {
        fromElements.add(liter.previous());
      }
    } else {
      fromElements = fromClause.getFromElements();
    }

    // Iterate through the alias,JoinSequence pairs and generate SQL token nodes.
    Iterator iter = fromElements.iterator();
    while (iter.hasNext()) {
      final FromElement fromElement = (FromElement) iter.next();
      JoinSequence join = fromElement.getJoinSequence();
      join.setSelector(
          new JoinSequence.Selector() {
            public boolean includeSubclasses(String alias) {
              // The uber-rule here is that we need to include subclass joins if
              // the FromElement is in any way dereferenced by a property from
              // the subclass table; otherwise we end up with column references
              // qualified by a non-existent table reference in the resulting SQL...
              boolean containsTableAlias = fromClause.containsTableAlias(alias);
              if (fromElement.isDereferencedBySubclassProperty()) {
                // TODO : or should we return 'containsTableAlias'??
                LOG.trace(
                    "Forcing inclusion of extra joins [alias="
                        + alias
                        + ", containsTableAlias="
                        + containsTableAlias
                        + "]");
                return true;
              }
              boolean shallowQuery = walker.isShallowQuery();
              boolean includeSubclasses = fromElement.isIncludeSubclasses();
              boolean subQuery = fromClause.isSubQuery();
              return includeSubclasses && containsTableAlias && !subQuery && !shallowQuery;
            }
          });
      addJoinNodes(query, join, fromElement);
    }
  }
  private void mergeJoins(JoinFragment ojf) throws MappingException, QueryException {

    Iterator iter = joins.entrySet().iterator();
    while (iter.hasNext()) {
      Map.Entry me = (Map.Entry) iter.next();
      String name = (String) me.getKey();
      JoinSequence join = (JoinSequence) me.getValue();
      join.setSelector(
          new JoinSequence.Selector() {
            public boolean includeSubclasses(String alias) {
              boolean include = returnedTypes.contains(alias) && !isShallowQuery();
              return include;
            }
          });

      if (typeMap.containsKey(name)) {
        ojf.addFragment(join.toJoinFragment(enabledFilters, true));
      } else if (collections.containsKey(name)) {
        ojf.addFragment(join.toJoinFragment(enabledFilters, true));
      } else {
        // name from a super query (a bit inelegant that it shows up here)
      }
    }
  }