/** INTERNAL: Return if the expression is for a direct mapped attribute. */
 public boolean isAttribute() {
   if (isAttributeExpression == null) {
     if (getSession() == null) {
       // We can't tell, so say no.
       return false;
     }
     QueryKey queryKey = getQueryKeyOrNull();
     if (queryKey != null) {
       isAttributeExpression = Boolean.valueOf(queryKey.isDirectQueryKey());
     } else {
       DatabaseMapping mapping = getMapping();
       if (mapping != null) {
         if (mapping.isVariableOneToOneMapping()) {
           throw QueryException.cannotQueryAcrossAVariableOneToOneMapping(
               mapping, mapping.getDescriptor());
         } else {
           isAttributeExpression = Boolean.valueOf(mapping.isDirectToFieldMapping());
         }
       } else {
         isAttributeExpression = Boolean.FALSE;
       }
     }
   }
   return isAttributeExpression.booleanValue();
 }
  @Override
  public ClassDescriptor getDescriptor() {
    if (isAttribute()) {
      return null;
    }
    if (descriptor == null) {
      // Look first for query keys, then mappings. Ultimately we should have query keys
      // for everything and can dispense with the mapping part.
      ForeignReferenceQueryKey queryKey = (ForeignReferenceQueryKey) getQueryKeyOrNull();
      if (queryKey != null) {
        descriptor =
            convertToCastDescriptor(
                getSession().getDescriptor(queryKey.getReferenceClass()), getSession());
        return descriptor;
      }
      if (getMapping() == null) {
        throw QueryException.invalidQueryKeyInExpression(this);
      }

      // We assume this is either a foreign reference or an aggregate mapping
      descriptor = getMapping().getReferenceDescriptor();
      if (getMapping().isVariableOneToOneMapping()) {
        throw QueryException.cannotQueryAcrossAVariableOneToOneMapping(getMapping(), descriptor);
      }
      descriptor = convertToCastDescriptor(descriptor, getSession());
    }
    return descriptor;
  }