/**
  * INTERNAL: Return if the expression is equal to the other. This is used to allow dynamic
  * expression's SQL to be cached.
  */
 public boolean equals(Object object) {
   if (this == object) {
     return true;
   }
   if (!super.equals(object)) {
     return false;
   }
   QueryKeyExpression expression = (QueryKeyExpression) object;
   // Return false for anyOf expressions, as equality is unknown.
   if (shouldQueryToManyRelationship() || expression.shouldQueryToManyRelationship()) {
     return false;
   }
   return ((getName() == expression.getName())
       || ((getName() != null) && getName().equals(expression.getName())));
 }
 public QueryKeyExpression existingDerivedExpressionNamed(String attributeName) {
   if (this.derivedExpressions == null) {
     return null;
   }
   List<Expression> derivedExpressionsCopy;
   synchronized (this) {
     derivedExpressionsCopy = new ArrayList(this.derivedExpressions);
   }
   for (Expression derivedExpression : derivedExpressionsCopy) {
     QueryKeyExpression exp = (QueryKeyExpression) derivedExpression;
     if (exp.getName().equals(attributeName)) {
       return exp;
     }
   }
   return null;
 }
 /** INTERNAL: Return if the attribute is specified for batch reading. */
 public boolean isAttributeBatchRead(String attributeName) {
   if (!hasBatchReadAttributes()) {
     return false;
   }
   Vector batchReadAttributeExpressions = getBatchReadAttributeExpressions();
   int size = batchReadAttributeExpressions.size();
   for (int index = 0; index < size; index++) {
     QueryKeyExpression expression = (QueryKeyExpression) batchReadAttributeExpressions.get(index);
     while (!expression.getBaseExpression().isExpressionBuilder()) {
       expression = (QueryKeyExpression) expression.getBaseExpression();
     }
     if (expression.getName().equals(attributeName)) {
       return true;
     }
   }
   return false;
 }