Пример #1
0
 private boolean isAssociationToIsoType(ClassAssociation ca) throws QueryTranslationException {
   Class<?> clazz = null;
   try {
     clazz = Class.forName(ca.getClassName());
   } catch (ClassNotFoundException ex) {
     throw new QueryTranslationException("Error loading class " + ca.getClassName());
   }
   DatatypeFlavor flavor = DatatypeFlavor.getFlavorOfClass(clazz);
   return !flavor.equals(DatatypeFlavor.STANDARD);
 }
Пример #2
0
  /**
   * Processes a CQL query attribute into HQL
   *
   * @param attribute The CQL attribute
   * @param hql The HQL statement fragment
   * @param parameters The positional parameters list
   * @param associationTrace The trace of associations
   * @param objectClassName The class name of the object to which this association belongs
   * @throws QueryTranslationException
   */
  private void processAttribute(
      CQLAttribute attribute,
      StringBuilder hql,
      List<java.lang.Object> parameters,
      CQLObject queryObject,
      String queryObjectAlias,
      Stack<CQLAssociatedObject> associationStack,
      List<CqlDataBucket> typesProcessingList)
      throws QueryTranslationException {
    LOG.debug("Processing attribute " + queryObject.getClassName() + "." + attribute.getName());

    // determine what the flavor of this attribute is
    DatatypeFlavor flavor = typesProcessingList.get(typesProcessingList.size() - 1).datatypeFlavor;
    LOG.debug("Datatype flavor is " + flavor.name());
    // DSET<Ii>, (and TEL and CD) ends up as "COMPLEX_WITH_SIMPLE_CONTENT" because it's modeled as
    // an
    // association to DSET, then to Ii, which is that type.  Appears to work OK.
    // FIXME: DSET<Ad> doesn't work because I can't get the information about the part names inside
    // the AD
    // out of the Hibernate configuration object API.  Interestingly, AD by itself is fine.
    switch (flavor) {
      case STANDARD:
      case ENUMERATION:
        processStandardAttribute(attribute, hql, parameters, queryObject, queryObjectAlias);
        break;
      case COMPLEX_WITH_SIMPLE_CONTENT:
        processComplexAttributeWithSimpleOrMixedContent(
            attribute, hql, parameters, associationStack, typesProcessingList);
        break;
      case COMPLEX_WITH_MIXED_CONTENT:
        processComplexAttributeWithSimpleOrMixedContent(
            attribute, hql, parameters, associationStack, typesProcessingList);
        break;
      case COMPLEX_WITH_COLLECTION_OF_COMPLEX:
        if (currentlyWrappedByDset(typesProcessingList)) {
          processDsetOfComplexDatatypeWithCollectionOfComplexAttributesWithSimpleContent(
              attribute, hql, parameters, associationStack, typesProcessingList);
        } else {
          processComplexAttributeWithCollectionOfComplexAttributesWithSimpleContent(
              attribute, hql, parameters, associationStack, typesProcessingList);
        }
        break;
      case COLLECTION_OF_COMPLEX_WITH_SIMPLE_CONTENT:
        processComplexAttributeWithSimpleOrMixedContent(
            attribute, hql, parameters, associationStack, typesProcessingList);
        break;
      case COLLECTION_OF_COMPLEX_WITH_COLLECTION_OF_COMPLEX_WITH_SIMPLE_CONTENT:
        // gah
        break;
    }
  }
Пример #3
0
 private Object getAttributeValueObject(Class<?> fieldType, AttributeValue value)
     throws QueryTranslationException {
   Object actualValue = null;
   // handle a couple special cases
   if (DatatypeFlavor.getFlavorOfClass(fieldType) == DatatypeFlavor.ENUMERATION) {
     // 1) ISO 21090enumerations (NullFlavor, AddressPartType, etc)
     String enumValue = value.getStringValue();
     LOG.debug("Field type is an Enumeration");
     try {
       Method factoryMethod = fieldType.getMethod("valueOf", String.class);
       actualValue = factoryMethod.invoke(null, enumValue);
     } catch (Exception ex) {
       throw new QueryTranslationException(
           "Error converting " + enumValue + " to its enumeration value: " + ex.getMessage(), ex);
     }
   } else if (Character.class.equals(fieldType)) {
     // 2) Character
     String stringVal = value.getStringValue();
     if (stringVal.length() == 1) {
       actualValue = Character.valueOf(stringVal.charAt(0));
     } else {
       throw new QueryTranslationException(
           "The string value \""
               + value
               + "\" of length "
               + stringVal.length()
               + " is not a valid character (should be length 1)");
     }
   } else if (URI.class.equals(fieldType)) {
     // 3) URI
     actualValue = URI.create(value.getStringValue());
   } else {
     if (value.getStringValue() != null) {
       actualValue = value.getStringValue();
     } else if (value.getBooleanValue() != null) {
       actualValue = value.getBooleanValue();
     } else if (value.getDateValue() != null) {
       actualValue = value.getDateValue();
     } else if (value.getDoubleValue() != null) {
       actualValue = value.getDoubleValue();
     } else if (value.getIntegerValue() != null) {
       actualValue = value.getIntegerValue();
     } else if (value.getLongValue() != null) {
       actualValue = value.getLongValue();
     } else if (value.getTimeValue() != null) {
       actualValue = value.getTimeValue().toString();
     }
   }
   return actualValue;
 }
Пример #4
0
 private void addTypeProcessingInformation(
     List<CqlDataBucket> typesProcessingList, String className, String aliasOrRoleName)
     throws QueryTranslationException {
   DatatypeFlavor flavor = null;
   try {
     flavor = DatatypeFlavor.getFlavorOfClass(Class.forName(stripGeneric(className)));
   } catch (Exception ex) {
     throw new QueryTranslationException(
         "Error determining datatype flavor of " + className + ": " + ex.getMessage(), ex);
   }
   CqlDataBucket bucket = new CqlDataBucket();
   bucket.clazz = className;
   bucket.aliasOrRoleName = aliasOrRoleName;
   bucket.datatypeFlavor = flavor;
   typesProcessingList.add(bucket);
 }
Пример #5
0
  /**
   * Processes CQL associations into HQL
   *
   * @param association The CQL association
   * @param hql The HQL fragment which will be edited
   * @param parameters The positional HQL query parameters
   * @param associationTrace The trace of associations
   * @param sourceClassName The class name of the type to which this association belongs
   * @throws QueryTranslationException
   */
  private void processAssociation(
      CQLAssociatedObject association,
      StringBuilder hql,
      List<java.lang.Object> parameters,
      Stack<CQLAssociatedObject> associationStack,
      List<CqlDataBucket> typesProcessingList,
      CQLObject sourceQueryObject,
      String sourceAlias)
      throws QueryTranslationException {
    LOG.debug(
        "Processing association "
            + sourceQueryObject.getClassName()
            + " to "
            + association.getClassName());

    // get the association's role name
    String roleName = association.getEndName();
    if (roleName == null) {
      try {
        roleName =
            typesInformationResolver.getRoleName(
                sourceQueryObject.getClassName(), association.getClassName());
      } catch (TypesInformationException ex) {
        throw new QueryTranslationException(ex.getMessage(), ex);
      }
    }
    if (roleName == null) {
      // still null?? no association to the object!
      throw new QueryTranslationException(
          "No role name for an association between "
              + sourceQueryObject.getClassName()
              + " and "
              + association.getClassName()
              + " cound be determined.  Maybe the association doesn't exist?");
    }
    LOG.debug("Role name determined to be " + roleName);

    // determine the alias for this association
    String alias =
        getAssociationAlias(sourceQueryObject.getClassName(), association.getClassName(), roleName);
    LOG.debug("Association alias determined to be " + alias);

    // add this association to the stack
    associationStack.push(association);
    DatatypeFlavor flavor = null;
    try {
      flavor =
          DatatypeFlavor.getFlavorOfClass(Class.forName(stripGeneric(association.getClassName())));
    } catch (ClassNotFoundException ex) {
      throw new QueryTranslationException(
          "Error determining datatype flavor of "
              + association.getClassName()
              + ": "
              + ex.getMessage(),
          ex);
    }
    addTypeProcessingInformation(
        typesProcessingList,
        association.getClassName(),
        flavor == DatatypeFlavor.STANDARD ? alias : roleName);

    if (DatatypeFlavor.STANDARD.equals(flavor)) {
      // flag indicates the query is only verifying the association is populated
      boolean simpleNullCheck = true;
      if (association.getCQLAttribute() != null) {
        simpleNullCheck = false;
        hql.append(sourceAlias).append('.').append(roleName);
        hql.append(".id in (select ").append(alias).append(".id from ");
        hql.append(association.getClassName()).append(" as ").append(alias).append(" where ");
        processAttribute(
            association.getCQLAttribute(),
            hql,
            parameters,
            association,
            alias,
            associationStack,
            typesProcessingList);
        hql.append(") ");
      }
      if (association.getCQLAssociatedObject() != null) {
        simpleNullCheck = false;
        // add clause to select things from this association
        hql.append(sourceAlias).append('.').append(roleName);
        hql.append(".id in (select ").append(alias).append(".id from ");
        hql.append(association.getClassName()).append(" as ").append(alias).append(" where ");
        processAssociation(
            association.getCQLAssociatedObject(),
            hql,
            parameters,
            associationStack,
            typesProcessingList,
            association,
            alias);
        hql.append(") ");
      }
      if (association.getCQLGroup() != null) {
        simpleNullCheck = false;
        hql.append(sourceAlias).append('.').append(roleName);
        hql.append(".id in (select ").append(alias).append(".id from ");
        hql.append(association.getClassName()).append(" as ").append(alias).append(" where ");
        processGroup(
            association.getCQLGroup(),
            hql,
            parameters,
            associationStack,
            typesProcessingList,
            association,
            alias);
        hql.append(") ");
      }
      if (simpleNullCheck) {
        // query is checking for the association to exist and be non-null
        hql.append(sourceAlias).append('.').append(roleName).append(".id is not null ");
      }
    } else {
      // complex datatype association (modeled as an attribute, so saying "Person.AD is not null"
      // doesn't make sense...
      // "Person.AD.NullFlavor = NullFlavor.NI, however, is fine
      // FIXME: have to handle complex types here
      boolean simpleNullCheck = true;
      if (association.getCQLAssociatedObject() != null) {
        simpleNullCheck = false;
        // continue processing
        // TODO: does alias need to be role name?
        processAssociation(
            association.getCQLAssociatedObject(),
            hql,
            parameters,
            associationStack,
            typesProcessingList,
            association,
            alias);
      }
      if (association.getCQLGroup() != null) {
        simpleNullCheck = false;
        // continue processing
        // TODO: does alias need to be role name?
        processGroup(
            association.getCQLGroup(),
            hql,
            parameters,
            associationStack,
            typesProcessingList,
            association,
            alias);
      }
      if (association.getCQLAttribute() != null) {
        simpleNullCheck = false;
        // TODO: does sourceAlias need to be roleName??
        processAttribute(
            association.getCQLAttribute(),
            hql,
            parameters,
            sourceQueryObject,
            sourceAlias,
            associationStack,
            typesProcessingList);
      }
      if (simpleNullCheck) {
        // checking for the type not to be null, but .id doesn't work....
        // depending on the sequence of datatype flavors leading to this point
        // we have to construct the HQL in different ways

        String path = getAssociationNavigationPath(typesProcessingList, 4);
        if (path.startsWith("join ")) {
          // throw away the "where" part of the existing query
          if (hql.toString().endsWith("where ")) {
            removeLastWhereStatement(hql);
          }
        }
        hql.append(path).append(" is not null");
      }
    }

    // pop this association off the stack
    associationStack.pop();
    clipTypeProcessingInformation(typesProcessingList);
    LOG.debug(associationStack.size() + " associations remain on the stack");
  }