public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {

    Object obj = context.currentObject();
    if (obj == null) {
      try {
        obj = context.getRequiredType().newInstance();
      } catch (Exception e) {
        throw new ObjectAccessException(
            "Cannot construct " + context.getRequiredType().getName(), e);
      }
    }

    Iterator attNames = reader.getAttributeNames();
    while (attNames.hasNext()) {
      String attName = (String) attNames.next();
      if (attName.equals(textName)) {
        continue;
      }

      try {
        Field field = obj.getClass().getDeclaredField(mapper.realMember(obj.getClass(), attName));
        if (!field.isAccessible()) {
          field.setAccessible(true);
        }
        String v = reader.getAttribute(attName);
        if (null == v || "".equals(v)) {
          continue;
        }
        Class fieldType = field.getType();
        Constructor strnum = fieldType.getDeclaredConstructor(String.class);
        field.set(obj, strnum.newInstance(v));
      } catch (Exception e) {
        e.printStackTrace();
        throw new ObjectAccessException("Cannot construct " + obj.getClass(), e);
      }
    }
    String value = reader.getValue();
    if (null != value && !"".equals(value)) {
      try {
        Field field = obj.getClass().getDeclaredField(mapper.realMember(obj.getClass(), textName));
        if (!field.isAccessible()) {
          field.setAccessible(true);
        }
        field.set(obj, value);
      } catch (Exception e) {
        e.printStackTrace();
        throw new ObjectAccessException("Cannot construct " + obj.getClass(), e);
      }
    }
    return obj;
  }
  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;
  }