/**
   * INTERNAL Return true if it uses a cast class and query is downcasting. It will look into
   * inheritance hierarchy of the root descriptor.
   */
  public boolean isDowncast(ClassDescriptor rootDescriptor, AbstractSession session) {
    if (castClass == null) {
      return false;
    }

    if (rootDescriptor.getJavaClass() == castClass) {
      return false;
    }

    ClassDescriptor castDescriptor = session.getClassDescriptor(castClass);

    if (castDescriptor == null) {
      throw QueryException.couldNotFindCastDescriptor(castClass, getBaseExpression());
    }
    if (castDescriptor.getInheritancePolicy() == null) {
      throw QueryException.castMustUseInheritance(getBaseExpression());
    }
    ClassDescriptor parentDescriptor = castDescriptor.getInheritancePolicy().getParentDescriptor();
    while (parentDescriptor != null) {
      if (parentDescriptor == rootDescriptor) {
        return true;
      }
      parentDescriptor = parentDescriptor.getInheritancePolicy().getParentDescriptor();
    }

    throw QueryException.couldNotFindCastDescriptor(castClass, getBaseExpression());
  }
  /**
   * INTERNAL Return the descriptor which contains this query key, look in the inheritance hierarchy
   * of rootDescriptor for the descriptor.
   */
  public ClassDescriptor convertToCastDescriptor(
      ClassDescriptor rootDescriptor, AbstractSession session) {
    if (castClass == null || rootDescriptor == null || rootDescriptor.getJavaClass() == castClass) {
      return rootDescriptor;
    }

    ClassDescriptor castDescriptor = session.getClassDescriptor(castClass);

    if (castDescriptor == null) {
      throw QueryException.couldNotFindCastDescriptor(castClass, getBaseExpression());
    }
    if (!castDescriptor.hasInheritance()) {
      throw QueryException.castMustUseInheritance(getBaseExpression());
    }
    ClassDescriptor parentDescriptor = castDescriptor.getInheritancePolicy().getParentDescriptor();
    while (parentDescriptor != null) {
      if (parentDescriptor == rootDescriptor) {
        return castDescriptor;
      }
      parentDescriptor = parentDescriptor.getInheritancePolicy().getParentDescriptor();
    }

    ClassDescriptor childDescriptor = rootDescriptor;
    while (childDescriptor != null) {
      if (childDescriptor == castDescriptor) {
        return rootDescriptor;
      }
      childDescriptor = childDescriptor.getInheritancePolicy().getParentDescriptor();
    }

    throw QueryException.couldNotFindCastDescriptor(castClass, getBaseExpression());
  }
  /**
   * INTERNAL - Return the descriptor which contains this query key, look in the inheritance
   * hierarchy of rootDescriptor for the descriptor. Does not set the descriptor, only returns it.
   */
  public ClassDescriptor convertToCastDescriptor(
      ClassDescriptor rootDescriptor, AbstractSession session) {
    isDowncast = Boolean.FALSE;
    if (castClass == null || rootDescriptor == null || rootDescriptor.getJavaClass() == castClass) {
      return rootDescriptor;
    }

    ClassDescriptor castDescriptor = session.getClassDescriptor(castClass);

    if (castDescriptor == null) {
      throw QueryException.couldNotFindCastDescriptor(castClass, getBaseExpression());
    }
    if (!castDescriptor.hasInheritance()) {
      throw QueryException.castMustUseInheritance(getBaseExpression());
    }
    ClassDescriptor parentDescriptor = castDescriptor.getInheritancePolicy().getParentDescriptor();
    while (parentDescriptor != null) {
      if (parentDescriptor == rootDescriptor) {
        isDowncast = Boolean.TRUE;
        return castDescriptor;
      }
      parentDescriptor = parentDescriptor.getInheritancePolicy().getParentDescriptor();
    }
    // is there value casting an emp to person in a query?
    ClassDescriptor childDescriptor = rootDescriptor;
    while (childDescriptor != null) {
      if (childDescriptor == castDescriptor) {
        return rootDescriptor;
      }
      childDescriptor = childDescriptor.getInheritancePolicy().getParentDescriptor();
    }

    throw QueryException.couldNotFindCastDescriptor(castClass, getBaseExpression());
  }