The submitted patch enables XStream to handle XML with unknown nodes, i.e. nodes that were not mapped to fields within my classes.
The features of this patch are:
1. Any XML can be unmarshaled to classes - unknown nodes/attributes (ones that do not map to fields in classes) will not produce any error.
2. Such unknown nodes will be internally stored (some restrictions apply).
3. When marshaling objects tree back to XML, stored unknown nodes will be also written. This will produce XML where unknown parts will not be touched.
How this patch works:
1. In case of unknown nodes DefaultMapper (which is the last in line of mappers) throws an CannotResolveClassException. Patch changes this so that DefaultMapper instead returns UnknownNode class.
2. Since UnknownNode class does not have it's own converter, it will be ultimately handled by AbstractReflectionConverter. ARC's methods doMarshal/doUnmarshal are changed so that when unknown nodes are detected they get saved to node storage.
3. For handling unknown nodes inside lists, CollectionConverter and AbstractCollectionConverter are enhanced.
4. New classes NodeStorage and NodeTree implement a mechanism for storing/retrieving trees of nodes and attributes. NodeStorage remembers (via weak references) which unmarshaled objects had unknown attributes/subnodes and saves references in an internal map.
5. Custom facade XStreamCaching binds above mentioned classes together. XSC holds a reference to NodeStorage instance, and passes it via custom constructors to those classes.
A. NodeStorage uses object references to remember which unknown saved nodes belong to which (unmarshaled) objects. Restoring unknown nodes only works for objects that were created via unmarshaling (fromXML()). If objects are created from scratch or existing objects are changed in a way that changes their references (copied?), marshaling unknown nodes will do nothing (it will behave as plain XStream). This could be handled by by some kind of unknownAlias(Object original Object changed) method that would add a new reference to the map. Any thoughts?
B. At the moment only collections handled by CollectionConverter (ArrayList, LinkedList, HashSet, Vector, LinkedHashSet) are suported. Support for other collections (array, Map, TreeMap, etc..) will be added in a week or so.
C. Unknown nodes (and attributes) are only detected when they are inside users classes (or if their parent is also unknown node) handled via AbstractCollectionConverter. If there is a node that is handled by any of the built in converters, for example StringConverter, the unknown subnodes and attributes will not be detected. Handling this cases would require changing all existing converters in XStream. Can anybody think of a way that this could be handled in a more general way?