XStream
  1. XStream
  2. XSTR-482

CLONE -TreeUnmarshaller does not correctly implement currentObject()

    Details

    • Type: Bug Bug
    • Status: Closed Closed
    • Resolution: Won't Fix
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: None
    • Labels:
      None

      Description

      TreeUnmarshaller does not currently implement the currentObject() method. It always returns "root" (which is always null...) It should keep a stack of objects, so that when users call

      Object newChild = context.convertAnother(thisParent, valueType);

      in the "parent" unmarshaller, the child unmarshaller can do the following:

      Object myParent = context.currentObject();

      Have fixed this, however. This required creating a new class (ObjectStack - it is identical to ClassStack, but substituting type Object for type Class), and then adding the stack operations to TreeUnmarshaller.

      The new class is included here:
      =====================================================================
      package com.thoughtworks.xstream.core.util;

      public final class ObjectStack {

      private Object[] stack;
      private int pointer;

      public ObjectStack(int initialCapacity)

      { stack = new Object[initialCapacity]; }

      public void push(Object value) {
      if (pointer + 1 >= stack.length)

      { resizeStack(stack.length * 2); }

      stack[pointer++] = value;
      }

      public void popSilently()

      { pointer--; }

      public Object pop()

      { return stack[--pointer]; }

      public Object peek()

      { return pointer == 0 ? null : stack[pointer - 1]; }

      public int size()

      { return pointer; }

      public Object get(int i)

      { return stack[i]; }

      private void resizeStack(int newCapacity)

      { Object[] newStack = new Object[newCapacity]; System.arraycopy(stack, 0, newStack, 0, Math.min(stack.length, newCapacity)); stack = newStack; }

      }

      =====================================================================

      The MODIFIED version of TreeUnmarshaller is included here (sorry, no diff)
      =====================================================================
      package com.thoughtworks.xstream.core;

      import com.thoughtworks.xstream.alias.ClassMapper;
      import com.thoughtworks.xstream.converters.*;
      import com.thoughtworks.xstream.core.util.ClassStack;
      import com.thoughtworks.xstream.core.util.ObjectStack;
      import com.thoughtworks.xstream.io.HierarchicalStreamReader;

      public class TreeUnmarshaller implements UnmarshallingContext {

      private Object root;
      protected HierarchicalStreamReader reader;
      private ConverterLookup converterLookup;
      private ClassMapper classMapper;
      private String classAttributeIdentifier;
      private ClassStack types = new ClassStack(16);

      private ObjectStack currentObjects = new ObjectStack(16);

      public TreeUnmarshaller(Object root, HierarchicalStreamReader reader,
      ConverterLookup converterLookup, ClassMapper classMapper,
      String classAttributeIdentifier)

      { this.root = root; this.reader = reader; this.converterLookup = converterLookup; this.classMapper = classMapper; this.classAttributeIdentifier = classAttributeIdentifier; }

      public Object convertAnother(Object current, Class type) {
      try

      { Converter converter = converterLookup.lookupConverterForType(type); types.push(type); currentObjects.push(current); Object result = converter.unmarshal(reader, this); currentObjects.popSilently(); types.popSilently(); return result; }

      catch (ConversionException conversionException)

      { addInformationTo(conversionException, type); throw conversionException; }

      catch (RuntimeException e)

      { ConversionException conversionException = new ConversionException(e); addInformationTo(conversionException, type); throw conversionException; }

      }

      private void addInformationTo(ErrorWriter errorWriter, Class type)

      { errorWriter.add("class", type.getName()); errorWriter.add("required-type", getRequiredType().getName()); reader.appendErrors(errorWriter); }

      public Object currentObject()

      { return currentObjects.peek(); }

      public Class getRequiredType()

      { return types.peek(); }

      public Object start() {
      String classAttribute = reader.getAttribute(classAttributeIdentifier);
      Class type;
      if (classAttribute == null)

      { type = classMapper.lookupType(reader.getNodeName()); }

      else

      { type = classMapper.lookupType(classAttribute); }

      return convertAnother(root, type);
      }

      }
      =====================================================================

        Issue Links

          People

          • Assignee:
            Jörg Schaible
            Reporter:
            Hervé MENGA
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: