public QueryParameters getQueryParameters() {
    LockOptions lockOptions = new LockOptions();
    RowSelection selection = new RowSelection();
    selection.setFirstRow(rootCriteria.getFirstResult());
    selection.setMaxRows(rootCriteria.getMaxResults());
    selection.setTimeout(rootCriteria.getTimeout());
    selection.setFetchSize(rootCriteria.getFetchSize());

    Iterator iter = rootCriteria.getLockModes().entrySet().iterator();
    while (iter.hasNext()) {
      Map.Entry me = (Map.Entry) iter.next();
      final Criteria subcriteria = getAliasedCriteria((String) me.getKey());
      lockOptions.setAliasSpecificLockMode(getSQLAlias(subcriteria), (LockMode) me.getValue());
    }
    List values = new ArrayList();
    List types = new ArrayList();
    iter = rootCriteria.iterateSubcriteria();
    while (iter.hasNext()) {
      CriteriaImpl.Subcriteria subcriteria = (CriteriaImpl.Subcriteria) iter.next();
      LockMode lm = subcriteria.getLockMode();
      if (lm != null) {
        lockOptions.setAliasSpecificLockMode(getSQLAlias(subcriteria), lm);
      }
      if (subcriteria.getWithClause() != null) {
        TypedValue[] tv = subcriteria.getWithClause().getTypedValues(subcriteria, this);
        for (int i = 0; i < tv.length; i++) {
          values.add(tv[i].getValue());
          types.add(tv[i].getType());
        }
      }
    }

    // Type and value gathering for the WHERE clause needs to come AFTER lock mode gathering,
    // because the lock mode gathering loop now contains join clauses which can contain
    // parameter bindings (as in the HQL WITH clause).
    iter = rootCriteria.iterateExpressionEntries();
    while (iter.hasNext()) {
      CriteriaImpl.CriterionEntry ce = (CriteriaImpl.CriterionEntry) iter.next();
      TypedValue[] tv = ce.getCriterion().getTypedValues(ce.getCriteria(), this);
      for (int i = 0; i < tv.length; i++) {
        values.add(tv[i].getValue());
        types.add(tv[i].getType());
      }
    }

    Object[] valueArray = values.toArray();
    Type[] typeArray = ArrayHelper.toTypeArray(types);
    return new QueryParameters(
        typeArray,
        valueArray,
        lockOptions,
        selection,
        rootCriteria.isReadOnlyInitialized(),
        (rootCriteria.isReadOnlyInitialized() ? rootCriteria.isReadOnly() : false),
        rootCriteria.getCacheable(),
        rootCriteria.getCacheRegion(),
        rootCriteria.getComment(),
        rootCriteria.isLookupByNaturalKey(),
        rootCriteria.getResultTransformer());
  }
 private void createAliasCriteriaMap() {
   aliasCriteriaMap.put(rootCriteria.getAlias(), rootCriteria);
   Iterator iter = rootCriteria.iterateSubcriteria();
   while (iter.hasNext()) {
     Criteria subcriteria = (Criteria) iter.next();
     if (subcriteria.getAlias() != null) {
       Object old = aliasCriteriaMap.put(subcriteria.getAlias(), subcriteria);
       if (old != null) {
         throw new QueryException("duplicate alias: " + subcriteria.getAlias());
       }
     }
   }
 }
 private void createAssociationPathCriteriaMap() {
   Iterator iter = rootCriteria.iterateSubcriteria();
   while (iter.hasNext()) {
     CriteriaImpl.Subcriteria crit = (CriteriaImpl.Subcriteria) iter.next();
     String wholeAssociationPath = getWholeAssociationPath(crit);
     Object old = associationPathCriteriaMap.put(wholeAssociationPath, crit);
     if (old != null) {
       throw new QueryException("duplicate association path: " + wholeAssociationPath);
     }
     int joinType = crit.getJoinType();
     old = associationPathJoinTypesMap.put(wholeAssociationPath, new Integer(joinType));
     if (old != null) {
       // TODO : not so sure this is needed...
       throw new QueryException("duplicate association path: " + wholeAssociationPath);
     }
     if (crit.getWithClause() != null) {
       this.withClauseMap.put(wholeAssociationPath, crit.getWithClause());
     }
   }
 }