public void add( Class definedIn, String fieldName, String itemFieldName, Class itemType, String keyFieldName) { Field field = null; Class declaredIn = definedIn; while (declaredIn != Object.class) { try { field = declaredIn.getDeclaredField(fieldName); break; } catch (SecurityException e) { throw new InitializationException("Access denied for field with implicit collection", e); } catch (NoSuchFieldException e) { declaredIn = declaredIn.getSuperclass(); } } if (field == null) { throw new InitializationException("No field \"" + fieldName + "\" for implicit collection"); } else if (Map.class.isAssignableFrom(field.getType())) { if (itemFieldName == null && keyFieldName == null) { itemType = Map.Entry.class; } } else if (!Collection.class.isAssignableFrom(field.getType())) { Class fieldType = field.getType(); if (!fieldType.isArray()) { throw new InitializationException( "Field \"" + fieldName + "\" declares no collection or array"); } else { Class componentType = fieldType.getComponentType(); componentType = componentType.isPrimitive() ? Primitives.box(componentType) : componentType; if (itemType == null) { itemType = componentType; } else { itemType = itemType.isPrimitive() ? Primitives.box(itemType) : itemType; if (!componentType.isAssignableFrom(itemType)) { throw new InitializationException( "Field \"" + fieldName + "\" declares an array, but the array type is not compatible with " + itemType.getName()); } } } } ImplicitCollectionMapperForClass mapper = getOrCreateMapper(definedIn); mapper.add(new ImplicitCollectionMappingImpl(fieldName, itemType, itemFieldName, keyFieldName)); }
public Object doUnmarshal( final Object result, final HierarchicalStreamReader reader, final UnmarshallingContext context) { final SeenFields seenFields = new SeenFields(); Iterator it = reader.getAttributeNames(); // Remember outermost Saveable encountered, for reporting below if (result instanceof Saveable && context.get("Saveable") == null) context.put("Saveable", result); // Process attributes before recursing into child elements. while (it.hasNext()) { String attrAlias = (String) it.next(); String attrName = mapper.attributeForAlias(attrAlias); Class classDefiningField = determineWhichClassDefinesField(reader); boolean fieldExistsInClass = fieldDefinedInClass(result, attrName); if (fieldExistsInClass) { Field field = reflectionProvider.getField(result.getClass(), attrName); SingleValueConverter converter = mapper.getConverterFromAttribute(field.getDeclaringClass(), attrName, field.getType()); Class type = field.getType(); if (converter == null) { converter = mapper.getConverterFromItemType(type); } if (converter != null) { Object value = converter.fromString(reader.getAttribute(attrAlias)); if (type.isPrimitive()) { type = Primitives.box(type); } if (value != null && !type.isAssignableFrom(value.getClass())) { throw new ConversionException( "Cannot convert type " + value.getClass().getName() + " to type " + type.getName()); } reflectionProvider.writeField(result, attrName, value, classDefiningField); seenFields.add(classDefiningField, attrName); } } } Map implicitCollectionsForCurrentObject = null; while (reader.hasMoreChildren()) { reader.moveDown(); try { String fieldName = mapper.realMember(result.getClass(), reader.getNodeName()); boolean implicitCollectionHasSameName = mapper.getImplicitCollectionDefForFieldName(result.getClass(), reader.getNodeName()) != null; Class classDefiningField = determineWhichClassDefinesField(reader); boolean fieldExistsInClass = !implicitCollectionHasSameName && fieldDefinedInClass(result, fieldName); Class type = determineType(reader, fieldExistsInClass, result, fieldName, classDefiningField); final Object value; if (fieldExistsInClass) { Field field = reflectionProvider.getField(result.getClass(), fieldName); value = unmarshalField(context, result, type, field); // TODO the reflection provider should have returned the proper field in first place .... Class definedType = reflectionProvider.getFieldType(result, fieldName, classDefiningField); if (!definedType.isPrimitive()) { type = definedType; } } else { value = context.convertAnother(result, type); } if (value != null && !type.isAssignableFrom(value.getClass())) { LOGGER.warning( "Cannot convert type " + value.getClass().getName() + " to type " + type.getName()); // behave as if we didn't see this element } else { if (fieldExistsInClass) { reflectionProvider.writeField(result, fieldName, value, classDefiningField); seenFields.add(classDefiningField, fieldName); } else { implicitCollectionsForCurrentObject = writeValueToImplicitCollection( context, value, implicitCollectionsForCurrentObject, result, fieldName); } } } catch (NonExistentFieldException e) { LOGGER.log(WARNING, "Skipping a non-existent field " + e.getFieldName(), e); addErrorInContext(context, e); } catch (CannotResolveClassException e) { LOGGER.log(WARNING, "Skipping a non-existent type", e); addErrorInContext(context, e); } catch (LinkageError e) { LOGGER.log(WARNING, "Failed to resolve a type", e); addErrorInContext(context, e); } reader.moveUp(); } // Report any class/field errors in Saveable objects if (context.get("ReadError") != null && context.get("Saveable") == result) { OldDataMonitor.report((Saveable) result, (ArrayList<Throwable>) context.get("ReadError")); context.put("ReadError", null); } return result; }