Example #1
0
 private static Object parseValue(Type valueType, List<Type> context, String value) {
   valueType = Data.resolveWildcardTypeOrTypeVariable(context, valueType);
   if (valueType == Double.class || valueType == double.class) {
     if (value.equals("INF")) {
       return new Double(Double.POSITIVE_INFINITY);
     }
     if (value.equals("-INF")) {
       return new Double(Double.NEGATIVE_INFINITY);
     }
   }
   if (valueType == Float.class || valueType == float.class) {
     if (value.equals("INF")) {
       return Float.POSITIVE_INFINITY;
     }
     if (value.equals("-INF")) {
       return Float.NEGATIVE_INFINITY;
     }
   }
   return Data.parsePrimitiveValue(valueType, value);
 }
Example #2
0
 /**
  * Returns whether the customize parser has requested to stop or reached end of document.
  * Otherwise, identical to {@link #parseElement(XmlPullParser, Object, XmlNamespaceDictionary,
  * CustomizeParser)} .
  */
 private static boolean parseElementInternal(
     XmlPullParser parser,
     ArrayList<Type> context,
     Object destination,
     Type valueType,
     XmlNamespaceDictionary namespaceDictionary,
     CustomizeParser customizeParser)
     throws IOException, XmlPullParserException {
   // TODO(yanivi): method is too long; needs to be broken down into smaller methods and comment
   // better
   GenericXml genericXml = destination instanceof GenericXml ? (GenericXml) destination : null;
   @SuppressWarnings("unchecked")
   Map<String, Object> destinationMap =
       genericXml == null && destination instanceof Map<?, ?> ? Map.class.cast(destination) : null;
   ClassInfo classInfo =
       destinationMap != null || destination == null ? null : ClassInfo.of(destination.getClass());
   if (parser.getEventType() == XmlPullParser.START_DOCUMENT) {
     parser.next();
   }
   parseNamespacesForElement(parser, namespaceDictionary);
   // generic XML
   if (genericXml != null) {
     genericXml.namespaceDictionary = namespaceDictionary;
     String name = parser.getName();
     String namespace = parser.getNamespace();
     String alias = namespaceDictionary.getNamespaceAliasForUriErrorOnUnknown(namespace);
     genericXml.name = alias.length() == 0 ? name : alias + ":" + name;
   }
   // attributes
   if (destination != null) {
     int attributeCount = parser.getAttributeCount();
     for (int i = 0; i < attributeCount; i++) {
       // TODO(yanivi): can have repeating attribute values, e.g. "@a=value1 @a=value2"?
       String attributeName = parser.getAttributeName(i);
       String attributeNamespace = parser.getAttributeNamespace(i);
       String attributeAlias =
           attributeNamespace.length() == 0
               ? ""
               : namespaceDictionary.getNamespaceAliasForUriErrorOnUnknown(attributeNamespace);
       String fieldName = getFieldName(true, attributeAlias, attributeNamespace, attributeName);
       Field field = classInfo == null ? null : classInfo.getField(fieldName);
       parseAttributeOrTextContent(
           parser.getAttributeValue(i),
           field,
           valueType,
           context,
           destination,
           genericXml,
           destinationMap,
           fieldName);
     }
   }
   Field field;
   ArrayValueMap arrayValueMap = new ArrayValueMap(destination);
   boolean isStopped = false;
   // TODO(yanivi): support Void type as "ignore" element/attribute
   main:
   while (true) {
     int event = parser.next();
     switch (event) {
       case XmlPullParser.END_DOCUMENT:
         isStopped = true;
         break main;
       case XmlPullParser.END_TAG:
         isStopped =
             customizeParser != null
                 && customizeParser.stopAfterEndTag(parser.getNamespace(), parser.getName());
         break main;
       case XmlPullParser.TEXT:
         // parse text content
         if (destination != null) {
           field = classInfo == null ? null : classInfo.getField(TEXT_CONTENT);
           parseAttributeOrTextContent(
               parser.getText(),
               field,
               valueType,
               context,
               destination,
               genericXml,
               destinationMap,
               TEXT_CONTENT);
         }
         break;
       case XmlPullParser.START_TAG:
         if (customizeParser != null
             && customizeParser.stopBeforeStartTag(parser.getNamespace(), parser.getName())) {
           isStopped = true;
           break main;
         }
         if (destination == null) {
           parseTextContentForElement(parser, context, true, null);
         } else {
           // element
           parseNamespacesForElement(parser, namespaceDictionary);
           String namespace = parser.getNamespace();
           String alias = namespaceDictionary.getNamespaceAliasForUriErrorOnUnknown(namespace);
           String fieldName = getFieldName(false, alias, namespace, parser.getName());
           field = classInfo == null ? null : classInfo.getField(fieldName);
           Type fieldType = field == null ? valueType : field.getGenericType();
           fieldType = Data.resolveWildcardTypeOrTypeVariable(context, fieldType);
           // field type is now class, parameterized type, or generic array type
           // resolve a parameterized type to a class
           Class<?> fieldClass = fieldType instanceof Class<?> ? (Class<?>) fieldType : null;
           if (fieldType instanceof ParameterizedType) {
             fieldClass = Types.getRawClass((ParameterizedType) fieldType);
           }
           boolean isArray = Types.isArray(fieldType);
           // text content
           boolean ignore = field == null && destinationMap == null && genericXml == null;
           if (ignore || Data.isPrimitive(fieldType)) {
             int level = 1;
             while (level != 0) {
               switch (parser.next()) {
                 case XmlPullParser.END_DOCUMENT:
                   isStopped = true;
                   break main;
                 case XmlPullParser.START_TAG:
                   level++;
                   break;
                 case XmlPullParser.END_TAG:
                   level--;
                   break;
                 case XmlPullParser.TEXT:
                   if (!ignore && level == 1) {
                     parseAttributeOrTextContent(
                         parser.getText(),
                         field,
                         valueType,
                         context,
                         destination,
                         genericXml,
                         destinationMap,
                         fieldName);
                   }
                   break;
                 default:
                   break;
               }
             }
           } else if (fieldType == null
               || fieldClass != null && Types.isAssignableToOrFrom(fieldClass, Map.class)) {
             // store the element as a map
             Map<String, Object> mapValue = Data.newMapInstance(fieldClass);
             int contextSize = context.size();
             if (fieldType != null) {
               context.add(fieldType);
             }
             Type subValueType =
                 fieldType != null && Map.class.isAssignableFrom(fieldClass)
                     ? Types.getMapValueParameter(fieldType)
                     : null;
             subValueType = Data.resolveWildcardTypeOrTypeVariable(context, subValueType);
             isStopped =
                 parseElementInternal(
                     parser,
                     context,
                     mapValue,
                     subValueType,
                     namespaceDictionary,
                     customizeParser);
             if (fieldType != null) {
               context.remove(contextSize);
             }
             if (destinationMap != null) {
               // map but not GenericXml: store as ArrayList of elements
               @SuppressWarnings("unchecked")
               Collection<Object> list = (Collection<Object>) destinationMap.get(fieldName);
               if (list == null) {
                 list = new ArrayList<Object>(1);
                 destinationMap.put(fieldName, list);
               }
               list.add(mapValue);
             } else if (field != null) {
               // not a map: store in field value
               FieldInfo fieldInfo = FieldInfo.of(field);
               if (fieldClass == Object.class) {
                 // field is an Object: store as ArrayList of element maps
                 @SuppressWarnings("unchecked")
                 Collection<Object> list = (Collection<Object>) fieldInfo.getValue(destination);
                 if (list == null) {
                   list = new ArrayList<Object>(1);
                   fieldInfo.setValue(destination, list);
                 }
                 list.add(mapValue);
               } else {
                 // field is a Map: store as a single element map
                 fieldInfo.setValue(destination, mapValue);
               }
             } else {
               // GenericXml: store as ArrayList of elements
               GenericXml atom = (GenericXml) destination;
               @SuppressWarnings("unchecked")
               Collection<Object> list = (Collection<Object>) atom.get(fieldName);
               if (list == null) {
                 list = new ArrayList<Object>(1);
                 atom.set(fieldName, list);
               }
               list.add(mapValue);
             }
           } else if (isArray || Types.isAssignableToOrFrom(fieldClass, Collection.class)) {
             // TODO(yanivi): some duplicate code here; isolate into reusable methods
             FieldInfo fieldInfo = FieldInfo.of(field);
             Object elementValue = null;
             Type subFieldType =
                 isArray
                     ? Types.getArrayComponentType(fieldType)
                     : Types.getIterableParameter(fieldType);
             Class<?> rawArrayComponentType =
                 Types.getRawArrayComponentType(context, subFieldType);
             subFieldType = Data.resolveWildcardTypeOrTypeVariable(context, subFieldType);
             Class<?> subFieldClass =
                 subFieldType instanceof Class<?> ? (Class<?>) subFieldType : null;
             if (subFieldType instanceof ParameterizedType) {
               subFieldClass = Types.getRawClass((ParameterizedType) subFieldType);
             }
             if (Data.isPrimitive(subFieldType)) {
               elementValue = parseTextContentForElement(parser, context, false, subFieldType);
             } else if (subFieldType == null
                 || subFieldClass != null
                     && Types.isAssignableToOrFrom(subFieldClass, Map.class)) {
               elementValue = Data.newMapInstance(subFieldClass);
               int contextSize = context.size();
               if (subFieldType != null) {
                 context.add(subFieldType);
               }
               Type subValueType =
                   subFieldType != null && Map.class.isAssignableFrom(subFieldClass)
                       ? Types.getMapValueParameter(subFieldType)
                       : null;
               subValueType = Data.resolveWildcardTypeOrTypeVariable(context, subValueType);
               isStopped =
                   parseElementInternal(
                       parser,
                       context,
                       elementValue,
                       subValueType,
                       namespaceDictionary,
                       customizeParser);
               if (subFieldType != null) {
                 context.remove(contextSize);
               }
             } else {
               elementValue = Types.newInstance(rawArrayComponentType);
               int contextSize = context.size();
               context.add(fieldType);
               isStopped =
                   parseElementInternal(
                       parser, context, elementValue, null, namespaceDictionary, customizeParser);
               context.remove(contextSize);
             }
             if (isArray) {
               // array field: add new element to array value map
               if (field == null) {
                 arrayValueMap.put(fieldName, rawArrayComponentType, elementValue);
               } else {
                 arrayValueMap.put(field, rawArrayComponentType, elementValue);
               }
             } else {
               // collection: add new element to collection
               @SuppressWarnings("unchecked")
               Collection<Object> collectionValue =
                   (Collection<Object>)
                       (field == null
                           ? destinationMap.get(fieldName)
                           : fieldInfo.getValue(destination));
               if (collectionValue == null) {
                 collectionValue = Data.newCollectionInstance(fieldType);
                 setValue(
                     collectionValue, field, destination, genericXml, destinationMap, fieldName);
               }
               collectionValue.add(elementValue);
             }
           } else {
             // not an array/iterable or a map, but we do have a field
             Object value = Types.newInstance(fieldClass);
             int contextSize = context.size();
             context.add(fieldType);
             isStopped =
                 parseElementInternal(
                     parser, context, value, null, namespaceDictionary, customizeParser);
             context.remove(contextSize);
             setValue(value, field, destination, genericXml, destinationMap, fieldName);
           }
         }
         if (isStopped || parser.getEventType() == XmlPullParser.END_DOCUMENT) {
           isStopped = true;
           break main;
         }
         break;
     }
   }
   arrayValueMap.setValues();
   return isStopped;
 }