private void prepareForIndex(QueryTranslatorImpl q) throws QueryException {

    QueryableCollection collPersister = q.getCollectionPersister(collectionRole);

    if (!collPersister.hasIndex())
      throw new QueryException("unindexed collection before []: " + path);
    String[] indexCols = collPersister.getIndexColumnNames();
    if (indexCols.length != 1) throw new QueryException("composite-index appears in []: " + path);
    // String[] keyCols = collPersister.getKeyColumnNames();

    JoinSequence fromJoins =
        new JoinSequence(q.getFactory())
            .setUseThetaStyle(useThetaStyleJoin)
            .setRoot(collPersister, collectionName)
            .setNext(joinSequence.copy());

    if (!continuation) addJoin(collectionName, collPersister.getCollectionType());

    joinSequence.addCondition(
        collectionName + '.' + indexCols[0] + " = "); // TODO: get SQL rendering out of here

    CollectionElement elem = new CollectionElement();
    elem.elementColumns = collPersister.getElementColumnNames(collectionName);
    elem.elementType = collPersister.getElementType();
    elem.isOneToMany = collPersister.isOneToMany();
    elem.alias = collectionName;
    elem.joinSequence = joinSequence;
    collectionElements.addLast(elem);
    setExpectingCollectionIndex();

    q.addCollection(collectionName, collectionRole);
    q.addFromJoinOnly(collectionName, fromJoins);
  }
  /** Used for collection filters */
  private void addFromAssociation(final String elementName, final String collectionRole)
      throws QueryException {
    // q.addCollection(collectionName, collectionRole);
    QueryableCollection persister = getCollectionPersister(collectionRole);
    Type collectionElementType = persister.getElementType();
    if (!collectionElementType.isEntityType()) {
      throw new QueryException("collection of values in filter: " + elementName);
    }

    String[] keyColumnNames = persister.getKeyColumnNames();
    // if (keyColumnNames.length!=1) throw new QueryException("composite-key collection in filter: "
    // + collectionRole);

    String collectionName;
    JoinSequence join = new JoinSequence(getFactory());
    collectionName =
        persister.isOneToMany() ? elementName : createNameForCollection(collectionRole);
    join.setRoot(persister, collectionName);
    if (!persister.isOneToMany()) {
      // many-to-many
      addCollection(collectionName, collectionRole);
      try {
        join.addJoin(
            (AssociationType) persister.getElementType(),
            elementName,
            JoinType.INNER_JOIN,
            persister.getElementColumnNames(collectionName));
      } catch (MappingException me) {
        throw new QueryException(me);
      }
    }
    join.addCondition(collectionName, keyColumnNames, " = ?");
    // if ( persister.hasWhere() ) join.addCondition( persister.getSQLWhereString(collectionName) );
    EntityType elemType = (EntityType) collectionElementType;
    addFrom(elementName, elemType.getAssociatedEntityName(), join);
  }
  public void token(String token, QueryTranslatorImpl q) throws QueryException {

    if (token != null) path.append(token);

    String alias = q.getPathAlias(path.toString());
    if (alias != null) {
      reset(q); // reset the dotcount (but not the path)
      currentName = alias; // after reset!
      currentPropertyMapping = q.getPropertyMapping(currentName);
      if (!ignoreInitialJoin) {
        JoinSequence ojf = q.getPathJoin(path.toString());
        try {
          joinSequence.addCondition(
              ojf.toJoinFragment(q.getEnabledFilters(), true)
                  .toWhereFragmentString()); // after reset!
        } catch (MappingException me) {
          throw new QueryException(me);
        }
        // we don't need to worry about any condition in the ON clause
        // here (toFromFragmentString), since anything in the ON condition
        // is already applied to the whole query
      }
    } else if (".".equals(token)) {
      dotcount++;
    } else {
      if (dotcount == 0) {
        if (!continuation) {
          if (!q.isName(token)) throw new QueryException("undefined alias: " + token);
          currentName = token;
          currentPropertyMapping = q.getPropertyMapping(currentName);
        }
      } else if (dotcount == 1) {
        if (currentName != null) {
          currentProperty = token;
        } else if (collectionName != null) {
          // processCollectionProperty(token, q.getCollectionPersister(collectionRole),
          // collectionName);
          continuation = false;
        } else {
          throw new QueryException("unexpected");
        }
      } else { // dotcount>=2

        // Do the corresponding RHS
        Type propertyType = getPropertyType();

        if (propertyType == null) {
          throw new QueryException("unresolved property: " + path);
        }

        if (propertyType.isComponentType()) {
          dereferenceComponent(token);
        } else if (propertyType.isEntityType()) {
          if (!isCollectionValued()) dereferenceEntity(token, (EntityType) propertyType, q);
        } else if (propertyType.isCollectionType()) {
          dereferenceCollection(token, ((CollectionType) propertyType).getRole(), q);

        } else {
          if (token != null) throw new QueryException("dereferenced: " + path);
        }
      }
    }
  }