/**
   * Returns true if the constraint is associated with the given FromElement. Associated with means
   * relating directly to a field of the QueryClass but NOT a cross-reference contraint (which
   * compares two arbitrary fields of different QueryClasses.
   *
   * @param constraint the constraint in question
   * @param fromElement the FromElement to check
   * @return true if associated
   */
  public static boolean isAssociatedWith(Constraint constraint, FromElement fromElement) {

    Object left = getLeftArgument(constraint);
    Object right = getRightArgument(constraint);

    // ignore cross-references
    if (left instanceof QueryEvaluable && !(isCrossReference(constraint))) {
      // not a cross-reference -> at most one QueryClass.  find it.
      QueryClass qc = null; // TODO test for a bug here? left not assoc by right is
      if (getQueryFields((QueryEvaluable) left).iterator().hasNext()) {
        QueryField qf = getQueryFields((QueryEvaluable) left).iterator().next();
        qc = (QueryClass) qf.getFromElement();
      } else if (getQueryFields((QueryEvaluable) right).iterator().hasNext()) {
        QueryField qf = getQueryFields((QueryEvaluable) right).iterator().next();
        qc = (QueryClass) qf.getFromElement();
      } else {
        return false; // does not relate to any QueryClass
      }
      return (fromElement == qc);
    } else if (left instanceof QueryClass && right instanceof QueryClass) {
      return (fromElement == left || fromElement == right);
    } else if (left instanceof QueryClass) {
      return (fromElement == left);
    } else if (left instanceof QueryReference) {
      return (fromElement == ((QueryReference) left).getQueryClass());
    } else if (right instanceof Query) {
      return (fromElement == right);
    }
    return false;
  }
  /**
   * Returns true if the constraint is associated with the given FromElement.
   *
   * @param constraint the constraint in question
   * @param fromElement the FromElement to check
   * @return true if associated
   */
  public static boolean isRelatedTo(Constraint constraint, FromElement fromElement) {
    if (isAssociatedWith(constraint, fromElement)) {
      return true;
    }

    // also want to find out if this is referred to in a Contains or Subquery
    // constraint that is associated with another fromElement.

    if (constraint instanceof ContainsConstraint) {
      if (fromElement == ((ContainsConstraint) constraint).getQueryClass()) {
        return true;
      }
    } else if (constraint instanceof SubqueryConstraint) {
      if (fromElement == ((SubqueryConstraint) constraint).getQuery()) {
        return true;
      }
    } else if (constraint instanceof SimpleConstraint) {
      SimpleConstraint sc = (SimpleConstraint) constraint;
      Set<QueryField> qFields = getQueryFields(sc.getArg1());
      qFields.addAll(getQueryFields(sc.getArg2()));
      for (QueryField qf : qFields) {
        if (fromElement == qf.getFromElement()) {
          return true;
        }
      }
    }
    return false;
  }
 /**
  * Returns true if the Constraint is a cross-reference between two QueryClasses. A constraint is
  * deemed to be a cross-reference if it compares fields of two different QueryClasses, either
  * directly or via QueryExpressions.
  *
  * @param constraint the contraint to test
  * @return true if the contraint is a cross-reference
  */
 public static boolean isCrossReference(Constraint constraint) {
   if (constraint instanceof SimpleConstraint) {
     // if QueryField exposed part of a subquery QueryField.getFromElement()
     // returns a query, does not cause any problem.
     Set<FromElement> qcs = new HashSet<FromElement>();
     for (QueryField qf : getQueryFields(((SimpleConstraint) constraint).getArg1())) {
       qcs.add(qf.getFromElement());
     }
     for (QueryField qf : getQueryFields(((SimpleConstraint) constraint).getArg2())) {
       qcs.add(qf.getFromElement());
     }
     if (qcs.size() > 1) {
       return true;
     }
   }
   return false;
 }