/** INTERNAL: Transform the object-level value into a database-level value */
  public Object getFieldValue(Object objectValue, AbstractSession session) {
    DatabaseMapping mapping = getMapping();
    Object fieldValue = objectValue;
    if ((mapping != null)
        && (mapping.isDirectToFieldMapping() || mapping.isDirectCollectionMapping())) {
      // CR#3623207, check for IN Collection here not in mapping.
      if (objectValue instanceof Collection) {
        // This can actually be a collection for IN within expressions... however it would be better
        // for expressions to handle this.
        Collection values = (Collection) objectValue;
        Vector fieldValues = new Vector(values.size());
        for (Iterator iterator = values.iterator(); iterator.hasNext(); ) {
          Object value = iterator.next();
          if (!(value instanceof Expression)) {
            value = getFieldValue(value, session);
          }
          fieldValues.add(value);
        }
        fieldValue = fieldValues;
      } else {
        if (mapping.isDirectToFieldMapping()) {
          fieldValue = ((AbstractDirectMapping) mapping).getFieldValue(objectValue, session);
        } else if (mapping.isDirectCollectionMapping()) {
          fieldValue = ((DirectCollectionMapping) mapping).getFieldValue(objectValue, session);
        }
      }
    }

    return fieldValue;
  }
  /** INTERNAL: Find the alias for a given table */
  public DatabaseTable aliasForTable(DatabaseTable table) {
    DatabaseMapping mapping = getMapping();
    if (isAttribute()
        || ((mapping != null)
            && (mapping.isAggregateObjectMapping() || mapping.isTransformationMapping()))) {
      return ((DataExpression) getBaseExpression()).aliasForTable(table);
    }

    // "ref" and "structure" mappings, no table printed in the FROM clause, need to get the table
    // alias form the parent table
    if ((mapping != null) && (mapping.isReferenceMapping() || mapping.isStructureMapping())) {
      DatabaseTable alias =
          getBaseExpression().aliasForTable(mapping.getDescriptor().getTables().firstElement());
      alias.setName(alias.getName() + "." + mapping.getField().getName());
      return alias;
    }

    // For direct-collection mappings the alias is store on the table expression.
    if ((mapping != null) && (mapping.isDirectCollectionMapping())) {
      if (tableAliases != null) {
        DatabaseTable aliasedTable = tableAliases.keyAtValue(table);
        if (aliasedTable != null) {
          return aliasedTable;
        }
      }
      return getTable(table).aliasForTable(table);
    }

    return super.aliasForTable(table);
  }
  /** Do any required validation for this node. Throw an exception if it's incorrect. */
  public void validateNode() {
    if ((getQueryKeyOrNull() == null) && (getMapping() == null)) {
      throw QueryException.invalidQueryKeyInExpression(getName());
    }

    QueryKey queryKey = getQueryKeyOrNull();
    DatabaseMapping mapping = getMapping();

    Object theOneThatsNotNull = null;
    boolean qkIsToMany = false;
    if (queryKey != null) {
      theOneThatsNotNull = queryKey;
      qkIsToMany = queryKey.isManyToManyQueryKey() || queryKey.isOneToManyQueryKey();
    }
    boolean isNestedMapping = false;
    if (mapping != null) {
      // Bug 2847621 - Add Aggregate Collection to the list of valid items for outer join.
      if (shouldUseOuterJoin
          && (!(mapping.isOneToOneMapping()
              || mapping.isOneToManyMapping()
              || mapping.isManyToManyMapping()
              || mapping.isAggregateCollectionMapping()
              || mapping.isDirectCollectionMapping()))) {
        throw QueryException.outerJoinIsOnlyValidForOneToOneMappings(getMapping());
      }
      qkIsToMany = mapping.isCollectionMapping();
      if (index != null) {
        if (qkIsToMany) {
          CollectionMapping collectionMapping = (CollectionMapping) getMapping();
          if (collectionMapping.getListOrderField() != null) {
            index.setField(collectionMapping.getListOrderField());
            if (collectionMapping.shouldUseListOrderFieldTableExpression()) {
              Expression newBase = getTable(collectionMapping.getListOrderField().getTable());
              index.setBaseExpression(newBase);
            } else {
              addDerivedField(index);
            }
          } else {
            throw QueryException.indexRequiresCollectionMappingWithListOrderField(
                this, collectionMapping);
          }
        } else {
          throw QueryException.indexRequiresCollectionMappingWithListOrderField(this, mapping);
        }
      }
      isNestedMapping = mapping.isNestedTableMapping();
      theOneThatsNotNull = mapping;
    } else {
      if (index != null) {
        throw QueryException.indexRequiresCollectionMappingWithListOrderField(this, null);
      }
    }
    if ((!shouldQueryToManyRelationship()) && qkIsToMany && (!isNestedMapping)) {
      throw QueryException.invalidUseOfToManyQueryKeyInExpression(theOneThatsNotNull);
    }
    if (shouldQueryToManyRelationship() && !qkIsToMany) {
      throw QueryException.invalidUseOfAnyOfInExpression(theOneThatsNotNull);
    }
  }