public void testProjectOuterJoinTeamLeaderAddressTeamMembersAddressPhonesWhereProjectName() {
    ReadAllQuery query = new ReadAllQuery();
    query.setReferenceClass(Project.class);
    query.setSelectionCriteria(
        query
            .getExpressionBuilder()
            .get("name")
            .equal("Problem Reporting System")
            .or(query.getExpressionBuilder().get("name").equal("Bleep Blob")));

    ReadAllQuery controlQuery = (ReadAllQuery) query.clone();

    Expression teamLeader = query.getExpressionBuilder().getAllowingNull("teamLeader");
    query.addJoinedAttribute(teamLeader);
    Expression teamLeaderAddress = teamLeader.getAllowingNull("address");
    query.addJoinedAttribute(teamLeaderAddress);
    Expression teamMembers = query.getExpressionBuilder().anyOfAllowingNone("teamMembers");
    query.addJoinedAttribute(teamMembers);
    Expression teamMembersAddress = teamMembers.getAllowingNull("address");
    query.addJoinedAttribute(teamMembersAddress);
    Expression teamMembersPhones = teamMembers.anyOfAllowingNone("phoneNumbers");
    query.addJoinedAttribute(teamMembersPhones);

    String errorMsg = executeQueriesAndCompareResults(controlQuery, query);
    if (errorMsg.length() > 0) {
      fail(errorMsg);
    }
  }
  public void findEmployeeWithWorkPhone2258812() {
    EntityManager em = createEntityManager();
    ExpressionBuilder builder = new ExpressionBuilder();
    Expression whereClause1 = builder.anyOf("phoneNumbers").get("type").equal("Work");
    Expression whereClause2 = builder.anyOf("phoneNumbers").get("number").equal("2258812");

    ReadAllQuery raq = new ReadAllQuery(Employee.class);
    raq.setSelectionCriteria(whereClause1.and(whereClause2));
    if (usesSOP() && getServerSession().getPlatform().isOracle()) {
      // distinct is incompatible with blob in selection clause on Oracle
    } else {
      raq.useDistinct();
    }

    List expectedResult = (List) getServerSession().executeQuery(raq);

    String ejbqlString;
    if (usesSOP() && getServerSession().getPlatform().isOracle()) {
      // distinct is incompatible with blob in selection clause on Oracle
      ejbqlString =
          "SELECT e FROM Employee e JOIN e.phoneNumbers p "
              + "WHERE p.type = 'Work' AND p.number = '2258812' ";
    } else {
      ejbqlString =
          "SELECT DISTINCT e FROM Employee e JOIN e.phoneNumbers p "
              + "WHERE p.type = 'Work' AND p.number = '2258812' ";
    }
    List result = em.createQuery(ejbqlString).getResultList();
    // 8 employees
    Assert.assertEquals(
        "Find employee with 2258812 number test failed: data validation error", result.size(), 8);
    Assert.assertTrue(
        "Find employee with 2258812 number test failed",
        comparer.compareObjects(expectedResult, result));
  }
  protected Expression processPropertyGe(
      Attribute<?, ?> attr, Expression builder, List<Parameter> parameters) {

    ConditionQueryParameter p;
    // convenient expression, only used by simple case
    Expression exp = null;

    p = new ConditionQueryParameter(this, getQuery().getPrefix() + parameters.size());
    parameters.add(p);
    if (attr.isCollection()) {
      if (isAllColllectionMode()) {
        ReportQuery subQuery = formReportQueryForDirectCollection(attr, builder);
        subQuery.setSelectionCriteria(
            builder.anyOf(getProp()).lessThan(builder.getParameter(p.getParamName())));
        exp = builder.notExists(subQuery);
      } else if (isNoneColllectionMode()) {
        ReportQuery subQuery = formReportQueryForDirectCollection(attr, builder);
        subQuery.setSelectionCriteria(
            builder.anyOf(getProp()).greaterThanEqual(builder.getParameter(p.getParamName())));
        exp = builder.notExists(subQuery);
      } else {
        exp = builder.anyOf(getProp()).greaterThanEqual(builder.getParameter(p.getParamName()));
      }
    } else {
      exp = builder.get(getProp()).greaterThanEqual(builder.getParameter(p.getParamName()));
    }
    return exp;
  }
  /*
   * INTERNAL:
   * If this query key represents a foreign reference answer the
   * base expression -> foreign reference join criteria.
   */
  public Expression mappingCriteria() {
    Expression selectionCriteria;

    // First look for a query key, then a mapping
    if (getQueryKeyOrNull() == null) {
      if ((getMapping() == null) || (!getMapping().isForeignReferenceMapping())) {
        return null;
      } else {
        // The join criteria is now twisted by the mappings.
        selectionCriteria = ((ForeignReferenceMapping) getMapping()).getJoinCriteria(this);
      }
    } else {
      if (!getQueryKeyOrNull().isForeignReferenceQueryKey()) {
        return null;
      } else {
        selectionCriteria = ((ForeignReferenceQueryKey) getQueryKeyOrNull()).getJoinCriteria();
        selectionCriteria = getBaseExpression().twist(selectionCriteria, this);
      }
    }

    if (shouldUseOuterJoin() && getSession().getPlatform().shouldPrintOuterJoinInWhereClause()) {
      selectionCriteria = selectionCriteria.convertToUseOuterJoin();
    }

    return selectionCriteria;
  }
 /**
  * INTERNAL: this returns a single expression to represent the join from the main table to all
  * child descriptor tables Only if outer joins should be printed in the where clause
  *
  * @return Expression
  */
 public Expression getTreatCriteria() {
   if (getDescriptor() == null) {
     return null;
   }
   // need to build this using just the multiple tables on this descriptor not included in the
   // parent's join expression
   Expression criteria = null;
   if (getSession().getPlatform().shouldPrintOuterJoinInWhereClause()) {
     Vector tables = getDescriptor().getTables(); // This child's tables
     ClassDescriptor parentDescriptor = this.typeExpressionBase.getDescriptor();
     int tablesSize = tables.size();
     if (parentDescriptor.hasInheritance()
         && parentDescriptor.getInheritancePolicy().hasMultipleTableChild()) {
       // look up the joins from the parent descriptor to our tables.
       for (int i = 0; i < tablesSize; i++) {
         DatabaseTable table = (DatabaseTable) tables.elementAt(i);
         Expression joinExpression =
             parentDescriptor.getInheritancePolicy().getChildrenTablesJoinExpressions().get(table);
         // Some of our tables might be the in our parent as well, so ignore the lack of a
         // joinExpression
         if (joinExpression != null) {
           joinExpression = this.baseExpression.twist(joinExpression, this);
           if (shouldUseOuterJoin()) {
             joinExpression = joinExpression.convertToUseOuterJoin();
           }
           criteria = joinExpression.and(criteria);
         }
       }
     }
   }
   return criteria;
 }
 /** INTERNAL Return true if treat was used on this expression */
 public boolean isTreatUsed() {
   if (this.hasDerivedExpressions())
     for (Expression exp : this.derivedExpressions) {
       if (exp.isTreatExpression()) {
         return true;
       }
     }
   return false;
 }
 /** INTERNAL Generate the EclipseLink expression for this node */
 public Expression generateExpression(GenerationContext context) {
   Expression whereClause = getFindIn().generateExpression(context);
   Expression findExpr = getFind().generateExpression(context);
   if (startPosition != null) {
     whereClause = whereClause.locate(findExpr, getStartPosition().generateExpression(context));
   } else {
     whereClause = whereClause.locate(findExpr);
   }
   return whereClause;
 }
  protected Expression processPropertyTracedownTooneOptimized(
      Attribute<?, ?> attr, Expression builder, List<Parameter> parameters) {
    ConditionQuery subQuery = getTraceDownQuery();

    Expression finalExp = null;
    for (PropertyCondition subPc : subQuery.getConditions()) {
      if (subPc.isReturnSimpleExpression()) {
        Expression subExp = subPc.processProperty(builder.get(getProp()), parameters);
        if (finalExp == null) {
          finalExp = subExp;
        } else {
          finalExp = finalExp.and(subExp);
        }
      } else {
        // low-performance query since an extra layer of exists added
        // but this is the only way to make it work.
        // this situation is rare. So we may do not need to optimize it
        Expression subBuilder = new ExpressionBuilder();
        Expression subExp = subPc.processProperty(subBuilder, parameters);
        ReportQuery childQuery = formRelationReportQuery(attr, subBuilder);
        childQuery.retrievePrimaryKeys();
        childQuery.setSelectionCriteria(subBuilder.equal(builder.get(getProp())).and(subExp));
        if (finalExp == null) {
          finalExp = builder.exists(childQuery);
        } else {
          finalExp = finalExp.and(builder.exists(childQuery));
        }
      }
    }
    return finalExp;
  }
 /**
  * INTERNAL: Rebuild myself against the base, with the values of parameters supplied by the
  * context expression. This is used for transforming a standalone expression (e.g. the join
  * criteria of a mapping) into part of some larger expression. You normally would not call this
  * directly, instead calling twist See the comment there for more details"
  */
 public Expression twistedForBaseAndContext(Expression newBase, Expression context) {
   Expression twistedBase = getBaseExpression().twistedForBaseAndContext(newBase, context);
   QueryKeyExpression result = (QueryKeyExpression) twistedBase.get(getName());
   if (shouldUseOuterJoin) {
     result.doUseOuterJoin();
   }
   if (shouldQueryToManyRelationship) {
     result.doQueryToManyRelationship();
   }
   return result;
 }
 public void test() {
   ExpressionBuilder eb = new ExpressionBuilder();
   ReportQuery rq = new ReportQuery(Employee.class, eb);
   rq.addAttribute("firstName");
   rq.addAttribute("lastName");
   Expression exp = eb.getFunction("dbms_random.value");
   exp.setSelectIfOrderedBy(false);
   rq.addOrdering(exp.ascending());
   rq.setSelectionCriteria(eb.anyOf("projects").get("teamLeader").isNull());
   results = (Vector) getSession().executeQuery(rq);
 }
  protected Expression processPropertyNotEmpty(
      Attribute<?, ?> attr, Expression builder, List<Parameter> parameters) {

    Expression exp = null;
    if (JpaMetamodelHelper.isRelation(attr)) {
      exp = builder.notEmpty(getProp());
    } else {
      // https://bugs.eclipse.org/bugs/show_bug.cgi?id=396892
      exp = builder.subQuery(this.formSizeReportQuery(attr, builder)).greaterThan(0);
    }
    return exp;
  }
 public List<Expression> copyDerivedExpressions(Map alreadyDone) {
   if (this.derivedExpressions == null) {
     return null;
   }
   List<Expression> derivedExpressionsCopy;
   synchronized (this) {
     derivedExpressionsCopy = new ArrayList(this.derivedExpressions);
   }
   List<Expression> result = new ArrayList(derivedExpressionsCopy.size());
   for (Expression exp : derivedExpressionsCopy) {
     result.add(exp.copiedVersionFrom(alreadyDone));
   }
   return result;
 }
 /** INTERNAL Generate the EclipseLink expression for this node */
 public Expression generateExpression(GenerationContext context) {
   Expression expr = context.getBaseExpression();
   if (expr == null) {
     expr = new ExpressionBuilder();
   }
   Expression result = null;
   if (type == Date.class) {
     result = expr.currentDateDate();
   } else if (type == Time.class) {
     result = expr.currentTime();
   } else if (type == Timestamp.class) {
     result = expr.currentDate();
   }
   return result;
 }
  public void testProjectJoinTeamMembersOuterJoinAddress() {
    ReadAllQuery query = new ReadAllQuery();
    query.setReferenceClass(Project.class);

    ReadAllQuery controlQuery = (ReadAllQuery) query.clone();

    Expression teamMembers = query.getExpressionBuilder().anyOf("teamMembers");
    query.addJoinedAttribute(teamMembers);
    Expression teamMembersAddress = teamMembers.getAllowingNull("address");
    query.addJoinedAttribute(teamMembersAddress);

    String errorMsg = executeQueriesAndCompareResults(controlQuery, query);
    if (errorMsg.length() > 0) {
      fail(errorMsg);
    }
  }
  /**
   * INTERNAL: This expression is built on a different base than the one we want. Rebuild it and
   * return the root of the new tree
   */
  public Expression rebuildOn(Expression newBase) {
    Expression newLocalBase = getBaseExpression().rebuildOn(newBase);
    QueryKeyExpression result = null;

    // For bug 3096634 rebuild outer joins correctly from the start.
    if (shouldUseOuterJoin) {
      result = (QueryKeyExpression) newLocalBase.getAllowingNull(getName());
    } else {
      result = (QueryKeyExpression) newLocalBase.get(getName());
    }
    if (shouldQueryToManyRelationship) {
      result.doQueryToManyRelationship();
    }
    result.setSelectIfOrderedBy(selectIfOrderedBy());
    return result;
  }
 /**
  * INTERNAL: Return the expression to join the main table of this node to any auxiliary tables.
  */
 public Expression additionalTreatExpressionCriteria() {
   if (getDescriptor() == null) {
     return null;
   }
   // need to build this using just the multiple tables on this descriptor not included in the
   // parent's join expression
   Expression criteria = null;
   if (getSession().getPlatform().shouldPrintOuterJoinInWhereClause()) {
     if (isUsingOuterJoinForMultitableInheritance()) {
       criteria = getDescriptor().getInheritancePolicy().getChildrenJoinExpression();
       criteria = this.baseExpression.twist(criteria, this);
       criteria.convertToUseOuterJoin();
     }
   }
   return criteria;
 }
  public void testProjectJoinTeamLeaderJoinAddressWhereTeamLeaderNotNull() {
    ReadAllQuery query = new ReadAllQuery();
    query.setReferenceClass(Project.class);
    Expression teamLeader = query.getExpressionBuilder().get("teamLeader");
    query.setSelectionCriteria(teamLeader.notNull());

    ReadAllQuery controlQuery = (ReadAllQuery) query.clone();

    query.addJoinedAttribute(teamLeader);
    Expression teamLeaderAddress = teamLeader.get("address");
    query.addJoinedAttribute(teamLeaderAddress);

    String errorMsg = executeQueriesAndCompareResults(controlQuery, query);
    if (errorMsg.length() > 0) {
      fail(errorMsg);
    }
  }
  private Expression buildExpressionFrom(Expression expression) {
    String name = "";
    if (getQueryable() != null) {
      name = getQueryable().getName();
    }

    if (getQueryable() != null && !getQueryable().usesAnyOf()) {
      if (!this.allowsNull) {
        return expression.get(name);
      }
      return expression.getAllowingNull(name);
    }
    if (!this.allowsNull) {
      return expression.anyOf(name);
    }
    return expression.anyOfAllowingNone(name);
  }
  public void testProblemReporterProjectJoinTeamMembersJoinAddress() {
    ReadAllQuery query = new ReadAllQuery();
    query.setReferenceClass(Project.class);
    query.setSelectionCriteria(query.getExpressionBuilder().get("name").equal("Problem Reporter"));

    ReadAllQuery controlQuery = (ReadAllQuery) query.clone();

    Expression teamMembers = query.getExpressionBuilder().anyOf("teamMembers");
    query.addJoinedAttribute(teamMembers);
    Expression teamMembersAddress = teamMembers.get("address");
    query.addJoinedAttribute(teamMembersAddress);

    String errorMsg = executeQueriesAndCompareResults(controlQuery, query);
    if (errorMsg.length() > 0) {
      fail(errorMsg);
    }
  }
  public Expression twistedForBaseAndContext(
      Expression newBase, Expression context, Expression oldBase) {
    if (oldBase == null || this.typeExpressionBase == oldBase) {
      Expression twistedBase =
          this.typeExpressionBase.twistedForBaseAndContext(newBase, context, oldBase);
      TreatAsExpression result = (TreatAsExpression) twistedBase.treat(this.castClass);
      if (shouldUseOuterJoin) {
        result.doUseOuterJoin();
      }
      if (shouldQueryToManyRelationship) {
        result.doQueryToManyRelationship();
      }
      return result;
    }

    return this;
  }
  public void testEmployeeOuterJoinAddressPhoneProjectsTeamLeaderAddressTeamMembersPhones() {
    ReadAllQuery query = new ReadAllQuery();
    query.setReferenceClass(Employee.class);

    ReadAllQuery controlQuery = (ReadAllQuery) query.clone();

    // Note that without the following two lines address and phones are not read not for all
    // Employees:
    // once an Employee is built (without Address and Phones)
    // it's not going to be rebuilt (get Address and Phones) when it's
    // up again either as a teamLeader or teamMember.
    // That means that only Employees read first indirectly (either as teamLeaders or
    // teamMembers would've got Phones and Addresses).
    query.addJoinedAttribute(query.getExpressionBuilder().getAllowingNull("address"));
    query.addJoinedAttribute(query.getExpressionBuilder().anyOfAllowingNone("phoneNumbers"));

    Expression projects = query.getExpressionBuilder().anyOfAllowingNone("projects");
    query.addJoinedAttribute(projects);
    Expression teamLeader = projects.getAllowingNull("teamLeader");
    query.addJoinedAttribute(teamLeader);
    Expression teamLeaderAddress = teamLeader.getAllowingNull("address");
    query.addJoinedAttribute(teamLeaderAddress);
    Expression teamMembers = projects.anyOfAllowingNone("teamMembers");
    query.addJoinedAttribute(teamMembers);
    Expression teamMembersPhones = teamMembers.anyOfAllowingNone("phoneNumbers");
    query.addJoinedAttribute(teamMembersPhones);

    String errorMsg = executeQueriesAndCompareResults(controlQuery, query);
    if (errorMsg.length() > 0) {
      fail(errorMsg);
    }
  }
  public void testEmployeeJoinProjectsJoinTeamLeaderJoinAddressWhereManagerIsNull() {
    ReadAllQuery query = new ReadAllQuery();
    query.setReferenceClass(Employee.class);
    query.setSelectionCriteria(query.getExpressionBuilder().get("manager").isNull());

    ReadAllQuery controlQuery = (ReadAllQuery) query.clone();
    Expression projects = query.getExpressionBuilder().anyOf("projects");
    query.addJoinedAttribute(projects);
    Expression teamLeader = projects.get("teamLeader");
    query.addJoinedAttribute(teamLeader);
    Expression teamLeaderAddress = teamLeader.get("address");
    query.addJoinedAttribute(teamLeaderAddress);

    String errorMsg = executeQueriesAndCompareResults(controlQuery, query);
    if (errorMsg.length() > 0) {
      fail(errorMsg);
    }
  }
    public void test() {
      ReadAllQuery query = new ReadAllQuery();
      query.setReferenceClass(Employee.class);
      setSelectionCriteria(query);

      ReadAllQuery controlQuery = (ReadAllQuery) query.clone();

      Expression employees = query.getExpressionBuilder().anyOf("managedEmployees");
      query.addJoinedAttribute(employees);
      Expression phones = employees.anyOf("phoneNumbers");
      query.addJoinedAttribute(phones);

      String errorMsg =
          JoinedAttributeTestHelper.executeQueriesAndCompareResults(
              controlQuery, query, (AbstractSession) getSession());
      if (errorMsg.length() > 0) {
        throw new TestErrorException(errorMsg);
      }
    }
  /**
   * Iterate the set of variables declared in an outer scope and connect the inner variable
   * expression with the outer one.
   */
  public Expression joinVariables(Set variables) {
    if ((outer == null) || (variables == null) || variables.isEmpty()) {
      // not an inner query or no variables to join
      return null;
    }
    Expression expr = null;
    for (Iterator i = variables.iterator(); i.hasNext(); ) {
      String name = (String) i.next();
      VariableNode var = new VariableNode(name);
      Expression innerExpr = var.generateExpression(this);
      Expression outerExpr = var.generateExpression(outer);

      // Join them only if they are not the same.
      if (innerExpr != outerExpr) {
        Expression join = innerExpr.equal(outerExpr);
        expr = var.appendExpression(expr, join);
      }
    }
    return expr;
  }
  public void testCountExpression() {
    EntityManager em = createEntityManager();

    ReportQuery query = new ReportQuery(Employee.class, new ExpressionBuilder());
    Expression whereClause1 =
        query.getExpressionBuilder().get("address").get("province").equal("QUE");
    Expression whereClause2 =
        query.getExpressionBuilder().get("address").get("city").equal("Montreal");
    query.setSelectionCriteria(whereClause1.and(whereClause2));
    query.addCount(
        "areaCodeCount",
        query.getExpressionBuilder().anyOf("phoneNumbers").get("areaCode"),
        Long.class);
    query.returnSingleResult();
    Long expectedResult =
        (Long) ((ReportQueryResult) getServerSession().executeQuery(query)).get("areaCodeCount");

    String ejbqlString =
        "SELECT COUNT(p.areaCode) FROM Employee e JOIN e.phoneNumbers p JOIN e.address a "
            + " WHERE a.province='QUE' AND a.city='Montreal'";
    Long result = (Long) em.createQuery(ejbqlString).getSingleResult();

    String alternateEjbqlString =
        "SELECT COUNT(p) FROM Employee e JOIN e.phoneNumbers p JOIN e.address a "
            + " WHERE a.province='QUE' AND a.city='Montreal' AND p.areaCode IS NOT NULL";
    Long alternateResult = (Long) em.createQuery(alternateEjbqlString).getSingleResult();

    Assert.assertTrue(
        "Count expression test failed: data validation error, ReportQuery returned 0",
        expectedResult.intValue() > 0);
    Assert.assertTrue(
        "Count expression test failed: data validation error, first JPQL returned 0",
        result.intValue() > 0);
    Assert.assertTrue(
        "Count expression test failed: data validation error, second JPQL returned 0",
        alternateResult.intValue() > 0);
    Assert.assertTrue(
        "Count expression test failed: two equivalent ejb queries return different results",
        alternateResult.equals(result));
    Assert.assertEquals("Count expression test failed", expectedResult, result);
  }
  private void createEmployeeAndSearchExpression() {
    // Create the example employee
    employee =
        (org.eclipse.persistence.testing.models.employee.domain.Employee)
            new org.eclipse.persistence.testing.models.employee.domain.EmployeePopulator()
                .basicEmployeeExample1();
    employee.setFirstName("Timugen");
    employee.setLastName("Singaera");
    employee.addResponsibility("Answer the phones.");

    // Create an expression to retreive the employee from the database
    ExpressionBuilder expressionBuilder = new ExpressionBuilder();
    Expression exp1;
    Expression exp2;
    Expression expression;

    exp1 = expressionBuilder.get("firstName").equal(employee.getFirstName());
    exp2 = expressionBuilder.get("lastName").equal(employee.getLastName());

    searchExpression = exp1.or(exp2);
  }
  protected Expression processPropertyTracedownToManyNone(
      Attribute<?, ?> attr, Expression builder, List<Parameter> parameters) {
    ConditionQuery subQuery = getTraceDownQuery();
    // subQuery.setPrefix(getQuery().getPrefix()+parameters.size()+"_");
    Expression subBuilder = new ExpressionBuilder();
    List<Expression> childExps = new ArrayList<Expression>(3);
    for (PropertyCondition subPc : subQuery.getConditions()) {
      Expression subExp = subPc.processProperty(subBuilder, parameters);
      childExps.add(subExp);
    }
    if (childExps.isEmpty()) {
      throw new InvalidQueryException("No expression from subquery.");
    }
    Expression finalExp = childExps.get(0);

    for (int i = 1; i < childExps.size(); i++) {
      finalExp = finalExp.and(childExps.get(i));
    }

    return builder.noneOf(getProp(), finalExp);
  }
  public void getOrderLargerThan() {
    EntityManager em = createEntityManager();

    ExpressionBuilder builder1 = new ExpressionBuilder(Order.class);
    ExpressionBuilder builder2 = new ExpressionBuilder(Order.class);
    Expression o1Quantity = builder1.get("quantity");
    Expression o2Quantity = builder2.get("quantity");
    Expression quantityComparison = o1Quantity.greaterThan(o2Quantity);
    Expression o2CustomerName = builder2.get("customer").get("name");
    Expression nameComparison = o2CustomerName.equal("Jane Smith");
    Expression whereClause = quantityComparison.and(nameComparison);

    ReadAllQuery raq = new ReadAllQuery();
    raq.setSelectionCriteria(whereClause);
    raq.setReferenceClass(Order.class);
    raq.useDistinct();
    List expectedResult = (List) getServerSession().executeQuery(raq);

    String ejbqlString =
        "SELECT DISTINCT o1 FROM OrderBean o1, OrderBean o2 WHERE o1.quantity > o2.quantity AND"
            + " o2.customer.name = 'Jane Smith' ";
    List result = em.createQuery(ejbqlString).getResultList();
    // only 1 order
    Assert.assertEquals(
        "Get order larger than test failed: data validation error", result.size(), 1);
    Assert.assertTrue(
        "Get order larger than test failed", comparer.compareObjects(expectedResult, result));
  }
  /**
   * INTERNAL: Selection criteria is created with source foreign keys and target keys. This criteria
   * is then used to read target records from the table.
   */
  public void initializeSelectionCriteria(AbstractSession session) {
    Expression selectionCriteria = null;
    Expression expression;

    ExpressionBuilder expBuilder = new ExpressionBuilder();

    Iterator sourceKeysEnum = getSourceToTargetQueryKeyNames().keySet().iterator();

    while (sourceKeysEnum.hasNext()) {
      DatabaseField sourceKey = (DatabaseField) sourceKeysEnum.next();
      String target = (String) this.getSourceToTargetQueryKeyNames().get(sourceKey);
      expression = expBuilder.getParameter(sourceKey).equal(expBuilder.get(target));

      if (selectionCriteria == null) {
        selectionCriteria = expression;
      } else {
        selectionCriteria = expression.and(selectionCriteria);
      }
    }

    setSelectionCriteria(selectionCriteria);
  }
  /**
   * INTERNAL: Return the expression to join the main table of this node to any auxiliary tables.
   */
  public Expression additionalExpressionCriteria() {
    if (getDescriptor() == null) {
      return null;
    }

    Expression criteria = getDescriptor().getQueryManager().getAdditionalJoinExpression();
    if (getSession().getPlatform().shouldPrintOuterJoinInWhereClause()) {
      if (isUsingOuterJoinForMultitableInheritance()) {
        Expression childrenCriteria =
            getDescriptor().getInheritancePolicy().getChildrenJoinExpression();
        childrenCriteria = getBaseExpression().twist(childrenCriteria, this);
        childrenCriteria.convertToUseOuterJoin();
        if (criteria == null) {
          criteria = childrenCriteria;
        } else {
          criteria = criteria.and(childrenCriteria);
        }
      }
    }

    return criteria;
  }