示例#1
0
  /**
   * Binds data from reference model instance to XML binding classes
   *
   * @param obj
   * @return
   * @throws XMLBindingException
   */
  public Object bindToXML(Object obj) throws XMLBindingException {
    if (obj == null) {
      return null;
    }
    String className = obj.getClass().getSimpleName();
    Method[] methods = obj.getClass().getMethods();

    try {
      Class xmlClass = Class.forName(XML_BINDING_PACKAGE + className.toUpperCase());

      // debug code only
      if (xmlClass.getClasses().length != 1) {
        log.debug("XMLBinding: bindToXML(): xmlClass.getClass()=" + xmlClass.getClass());
        log.debug("XMLBinding: bindToXML(): xmlClass.toString()=" + xmlClass.toString());
        for (Class clazz : xmlClass.getClasses()) {
          log.debug("\t clazz.getClass()=" + clazz.getClass());
          log.debug("\t clazz.toString()=" + clazz.toString());
        }
      }

      Class factoryClass = xmlClass.getClasses()[0];

      // ES modification: Add xmlOptions containing openehr (default) and xsi namespaces

      // Method factoryMethod = factoryClass.getMethod(NEW_INSTANCE, null);
      // Changed to pick the method with an XmlOptions parameter instead
      Method factoryMethod = factoryClass.getMethod(NEW_INSTANCE, XmlOptions.class);

      // First prameter null because it's a static method, see:
      // http://java.sun.com/docs/books/tutorial/reflect/member/methodInvocation.html
      // Second parameter should be the parameter of XmlObject.Factory.newInstance(XmlOptions
      // options)
      // see:
      // http://xmlbeans.apache.org/docs/2.2.0/reference/org/apache/xmlbeans/XmlObject.Factory.html
      //
      // Previous code was: Object xmlObj = factoryMethod.invoke(null, null);
      Object xmlObj = factoryMethod.invoke(null, xopt);

      Map<String, Class> attributes = builder.retrieveAttribute(className);
      Set<String> attributeNames = attributes.keySet();
      Object attributeValue = null;
      Method setterMethod = null;

      for (Method method : methods) {
        String name = method.getName();

        // cause dead-loop
        if ("getParent".equals(name)) {
          continue; //
        }

        if (isGetter(name, attributeNames)) {

          log.debug("getter: " + name);

          if (method.getParameterTypes().length > 0) {
            continue;
          }

          attributeValue = method.invoke(obj, null);

          if (attributeValue == null) {
            continue;
          }

          log.debug("value.class: " + attributeValue.getClass());

          boolean isList = false;

          if (attributeValue.getClass().isArray()) {
            Object[] array = (Object[]) attributeValue;
            if (array.length == 0) {
              continue;
            }
            Object[] done = new Object[array.length];
            for (int i = 0; i < array.length; i++) {
              done[i] = bindToXML(array[i]);
            }
            attributeValue = done;

          } else if (ProportionKind.class.equals(attributeValue.getClass())) {

            ProportionKind kind = (ProportionKind) attributeValue;
            attributeValue = BigInteger.valueOf(kind.getValue());

          } else if (isOpenEHRRMClass(attributeValue)) {

            attributeValue = bindToXML(attributeValue);

          } else if (List.class.isAssignableFrom(attributeValue.getClass())) {

            isList = true;
            List list = (List) attributeValue;

            log.debug("list.size: " + list.size());

            String attributeName = getAttributeNameFromGetter(name);
            setterMethod = findSetter(attributeName, xmlClass, isList);

            Method addNew = findAddNew(attributeName, xmlClass);

            log.debug("setter: " + setterMethod.getName() + ", xmlClass: " + xmlClass);

            for (int i = 0, j = list.size() - 1; i <= j; i++) {
              Object value = list.get(i);

              Object[] array = new Object[2];

              addNew.invoke(xmlObj, null);

              array[0] = new Integer(i);
              array[1] = bindToXML(value);
              setterMethod.invoke(xmlObj, array);

              log.debug("list.member value set!!!!");
            }
          }

          if (!isList) {
            String attributeName = getAttributeNameFromGetter(name);

            log.debug(
                "attribute: "
                    + attributeName
                    + ", value("
                    + attributeValue
                    + "), "
                    + "type: "
                    + attributeValue.getClass());

            // TODO fix for mismatched attribute name in XSD and RM
            if ("nullFlavor".equals(attributeName)) {
              attributeName = "nullFlavour";
            }

            // skip function according to specs
            if ("isMerged".equals(attributeName)) {
              continue;
            }

            setterMethod = findSetter(attributeName, xmlClass, isList);

            if (setterMethod == null) {
              log.error(
                  "failed to find setterMethod for attribute: "
                      + attributeName
                      + " with type: "
                      + xmlClass);
              continue;
            }

            // special handling deals with 'real' typed
            // attributes in specs but typed 'float' in xsd
            String setter = setterMethod.getName();
            if ("setAccuracy".equals(setter)
                || "setDenominator".equals(setter)
                || "setNumerator".equals(setter)) {

              Double d = (Double) attributeValue;
              attributeValue = d.floatValue();
            }

            log.debug(
                "setter: "
                    + setterMethod.getName()
                    + ", xmlClass: "
                    + xmlClass
                    + ", attributeValue: "
                    + attributeValue
                    + ", attributeValue.class: "
                    + attributeValue.getClass());

            setterMethod.invoke(xmlObj, attributeValue);
          }
        }
      }

      return xmlObj;

    } catch (Exception e) {
      e.printStackTrace();
      throw new XMLBindingException(
          "exception caught when bind obj to " + className + ", " + e.getMessage());
    }
  }
示例#2
0
  /**
   * Construct an instance of RM class of given name and values.
   *
   * <p>If the input is a string, and the required attribute is some other types (integer, double
   * etc), it will be converted into right type. if there is any error during conversion,
   * AttributeFormatException will be thrown.
   *
   * @param rmClassName
   * @param valueMap
   * @return created instance
   * @throws RMObjectBuildingException
   */
  public RMObject construct(String rmClassName, Map<String, Object> valueMap)
      throws RMObjectBuildingException {

    Class rmClass = retrieveRMType(rmClassName);

    // replace underscore separated names with camel case
    Map<String, Object> filteredMap = new HashMap<String, Object>();
    for (String name : valueMap.keySet()) {
      filteredMap.put(toCamelCase(name), valueMap.get(name));
    }
    Constructor constructor = fullConstructor(rmClass);
    Map<String, Class> typeMap = attributeType(rmClass);
    Map<String, Integer> indexMap = attributeIndex(rmClass);
    Map<String, Attribute> attributeMap = attributeMap(rmClass);
    Object[] valueArray = new Object[indexMap.size()];

    for (String name : typeMap.keySet()) {

      Object value = filteredMap.get(name);

      if (!typeMap.containsKey(name) || !attributeMap.containsKey(name)) {
        throw new RMObjectBuildingException("unknown attribute " + name);
      }

      Class type = typeMap.get(name);
      Integer index = indexMap.get(name);

      Attribute attribute = attributeMap.get(name);
      if (index == null || type == null) {
        throw new RMObjectBuildingException("unknown attribute \"" + name + "\"");
      }

      // system supplied value
      if (attribute.system()) {
        SystemValue sysvalue = SystemValue.fromId(name);
        if (sysvalue == null) {
          throw new RMObjectBuildingException("unknonw system value" + "\"" + name + "\"");
        }
        value = systemValues.get(sysvalue);
        if (value == null) {
          throw new AttributeMissingException(
              "missing value for "
                  + "system attribute \""
                  + name
                  + "\" in class: "
                  + rmClass
                  + ", with valueMap: "
                  + valueMap);
        }
      }

      // check required attributes
      if (value == null && attribute.required()) {
        log.info(attribute);
        throw new AttributeMissingException(
            "missing value for "
                + "required attribute \""
                + name
                + "\" of type "
                + type
                + " while constructing "
                + rmClass
                + " with valueMap: "
                + valueMap);
      }

      // enum
      else if (type.isEnum() && !value.getClass().isEnum()) {
        // OG added
        if (type.equals(ProportionKind.class))
          value = ProportionKind.fromValue(Integer.parseInt(value.toString()));
        else value = Enum.valueOf(type, value.toString());
      }

      // in case of null, create a default value
      else if (value == null) {
        value = defaultValue(type);
      }

      // in case of string value, convert to right type if necessary
      else if (value instanceof String) {
        String str = (String) value;
        try {

          // for DvCount
          if (type.equals(int.class)) {
            value = Integer.parseInt(str);

            // for DvQuantity
          } else if (type.equals(double.class)) {
            value = Double.parseDouble(str);

            // for DvProportion.precision
          } else if (type.equals(Integer.class)) {
            value = new Integer(str);
          }

        } catch (NumberFormatException e) {
          throw new AttributeFormatException(
              "wrong format of " + "attribute " + name + ", expect " + type);
        }

        // deal with mismatch between array and list
      } else if (type.isAssignableFrom(List.class) && value.getClass().isArray()) {

        Object[] array = (Object[]) value;
        List list = new ArrayList();
        for (Object o : array) {
          list.add(o);
        }
        value = list;

        // deal with mismatch between array and set
      } else if (type.isAssignableFrom(Set.class) && value.getClass().isArray()) {

        Object[] array = (Object[]) value;
        Set set = new HashSet();
        for (Object o : array) {
          set.add(o);
        }
        value = set;
      }
      // check type
      else if (value != null && !type.isPrimitive()) {
        try {
          type.cast(value);
        } catch (ClassCastException e) {
          throw new RMObjectBuildingException(
              "Failed to construct: "
                  + rmClassName
                  + ", value for attribute '"
                  + name
                  + "' has wrong type, expected \""
                  + type
                  + "\", but got \""
                  + value.getClass()
                  + "\"");
        }
      }
      valueArray[index] = value;
    }

    Object ret = null;
    try {
      // OG added hack
      if (rmClassName.equalsIgnoreCase("DVCOUNT")) {
        log.debug("Fixing DVCOUNT...");
        for (int i = 0; i < valueArray.length; i++) {
          Object value = valueArray[i];
          if (value != null && value.getClass().equals(Float.class))
            valueArray[i] = Double.parseDouble(value.toString());
          else if (value != null && value.getClass().equals(Long.class))
            valueArray[i] = Integer.parseInt(value.toString());
        }
      }
      ret = constructor.newInstance(valueArray);
    } catch (Exception e) {

      if (log.isDebugEnabled()) {
        e.printStackTrace();
      }

      log.debug("failed in constructor.newInstance()", e);

      if (stringParsingTypes.contains(rmClassName)) {
        throw new AttributeFormatException("wrong format for type " + rmClassName);
      }

      throw new RMObjectBuildingException(
          "failed to create new instance of  "
              + rmClassName
              + " with valueMap: "
              + toString(valueMap)
              + ", cause: "
              + e.getMessage());
    }
    return (RMObject) ret;
  }