private void processComplexAttributeWithSimpleOrMixedContent(
      CQLAttribute attribute,
      StringBuilder hql,
      List<java.lang.Object> parameters,
      Stack<CQLAssociatedObject> associationStack,
      List<CqlDataBucket> typesProcessingList)
      throws QueryTranslationException {
    LOG.debug("Processing complex attribute with simple or mixed content");
    // determine the number of levels to back up to find a "standard" datatype
    int levels = determineLevelsRemovedFromStandardDatatype(typesProcessingList);

    // determine if this value is mapped to a constant
    java.lang.Object constantValue =
        constantValueResolver.getConstantValue(
            typesProcessingList.get(typesProcessingList.size() - levels).clazz,
            getAttributePathList(typesProcessingList, attribute.getName(), levels - 1));
    if (constantValue == null) {
      LOG.debug("Attribute was not mapped to a constant");
      // append the path to the attribute itself
      if (caseInsensitive) {
        hql.append("lower(");
      }
      String path = getAttributePath(typesProcessingList, attribute.getName(), levels);
      if (path.startsWith("join ")) {
        // throw away the "where" part of the existing query
        if (hql.toString().endsWith("where ")) {
          removeLastWhereStatement(hql);
        }
      }
      hql.append(path);
      if (caseInsensitive) {
        hql.append(')');
      }
    } else {
      // the value has been mapped to a constant.  Hibernate can't query
      // against these, but we can substitute the value into the query directly
      LOG.debug("Attribute mapped to a constant; appending that constant to the HQL parameters");
      hql.append('?');
      parameters.add(constantValue);
    }
    // get one level back's query object
    appendPredicateAndValue(attribute, hql, parameters, associationStack.peek());
  }
  private void processComplexAttributeWithCollectionOfComplexAttributesWithSimpleContent(
      CQLAttribute attribute,
      StringBuilder hql,
      List<java.lang.Object> parameters,
      Stack<CQLAssociatedObject> associationStack,
      List<CqlDataBucket> typesProcessingList)
      throws QueryTranslationException {
    LOG.debug("Processing complex attribute collection of attributes with simple content");
    int levels = determineLevelsRemovedFromStandardDatatype(typesProcessingList);
    System.out.println("Levels: " + levels);
    if (levels == 2) {
      // we're probably processing an enum value of the most recent association class
      List<String> attribPath = getAttributePathList(typesProcessingList, attribute.getName(), 1);
      // determine if this value is mapped to a constant
      java.lang.Object constantValue =
          constantValueResolver.getConstantValue(
              typesProcessingList.get(typesProcessingList.size() - levels).clazz, attribPath);
      if (constantValue == null) {
        LOG.debug("Attribute was not mapped to a constant");
        // append the path to the attribute itself
        if (caseInsensitive) {
          hql.append("lower(");
        }
        String path = getAttributePath(typesProcessingList, attribute.getName(), levels);
        if (path.startsWith("join ")) {
          // throw away the "where" part of the existing query
          if (hql.toString().endsWith("where ")) {
            removeLastWhereStatement(hql);
          }
        }
        hql.append(path);
        if (caseInsensitive) {
          hql.append(')');
        }
      } else {
        // the value has been mapped to a constant.  Hibernate can't query
        // against these, but we can substitute the value into the query directly
        LOG.debug("Attribute mapped to a constant; appending that constant to the HQL parameters");
        hql.append('?');
        parameters.add(constantValue);
      }
      // get one level back's query object
      appendPredicateAndValue(attribute, hql, parameters, associationStack.peek());
    } else {
      // some nested component path
      // build the query path with a place holder for the part names
      String componentNamePlaceholder = "---placeholder---";
      int listSize = typesProcessingList.size();
      int endIndex = listSize - 3;
      StringBuffer buf = new StringBuffer();
      for (int i = endIndex; i < listSize; i++) {
        if (i == listSize - 1) {
          buf.append(componentNamePlaceholder);
        } else {
          buf.append(typesProcessingList.get(i).aliasOrRoleName);
        }
        buf.append('.');
      }
      buf.append(attribute.getName());

      // get the part names out of the types information
      List<String> componentNames =
          typesInformationResolver.getInnerComponentNames(
              typesProcessingList.get(typesProcessingList.size() - 3).clazz,
              typesProcessingList.get(typesProcessingList.size() - 2).aliasOrRoleName,
              typesProcessingList.get(typesProcessingList.size() - 1).aliasOrRoleName);
      Iterator<String> nameIter = componentNames.iterator();

      // build the query fragment
      hql.append("(");
      while (nameIter.hasNext()) {
        if (caseInsensitive) {
          hql.append("lower(");
        }
        String fragment = buf.toString().replace(componentNamePlaceholder, nameIter.next());
        hql.append(fragment);
        if (caseInsensitive) {
          hql.append(")");
        }
        appendPredicateAndValue(attribute, hql, parameters, associationStack.peek());
        if (nameIter.hasNext()) {
          hql.append(" or ");
        }
      }
      hql.append(")");
    }
  }