01: /*
02: * Copyright (C) 2003, 2004, 2005 Joe Walnes.
03: * Copyright (C) 2006, 2007 XStream Committers.
04: * All rights reserved.
05: *
06: * The software in this package is published under the terms of the BSD
07: * style license a copy of which has been included with this distribution in
08: * the LICENSE.txt file.
09: *
10: * Created on 26. September 2003 by Joe Walnes
11: */
12: package com.thoughtworks.xstream.converters.collections;
13:
14: import com.thoughtworks.xstream.converters.ConversionException;
15: import com.thoughtworks.xstream.converters.Converter;
16: import com.thoughtworks.xstream.converters.MarshallingContext;
17: import com.thoughtworks.xstream.converters.UnmarshallingContext;
18: import com.thoughtworks.xstream.io.HierarchicalStreamReader;
19: import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
20: import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
21: import com.thoughtworks.xstream.mapper.Mapper;
22:
23: /**
24: * Base helper class for converters that need to handle
25: * collections of items (arrays, Lists, Maps, etc).
26: * <p/>
27: * <p>Typically, subclasses of this will converter the outer
28: * structure of the collection, loop through the contents and
29: * call readItem() or writeItem() for each item.</p>
30: *
31: * @author Joe Walnes
32: */
33: public abstract class AbstractCollectionConverter implements Converter {
34:
35: private final Mapper mapper;
36:
37: public abstract boolean canConvert(Class type);
38:
39: public AbstractCollectionConverter(Mapper mapper) {
40: this .mapper = mapper;
41: }
42:
43: protected Mapper mapper() {
44: return mapper;
45: }
46:
47: public abstract void marshal(Object source,
48: HierarchicalStreamWriter writer, MarshallingContext context);
49:
50: public abstract Object unmarshal(HierarchicalStreamReader reader,
51: UnmarshallingContext context);
52:
53: protected void writeItem(Object item, MarshallingContext context,
54: HierarchicalStreamWriter writer) {
55: // PUBLISHED API METHOD! If changing signature, ensure backwards compatability.
56: if (item == null) {
57: // todo: this is duplicated in TreeMarshaller.start()
58: String name = mapper().serializedClass(null);
59: writer.startNode(name);
60: writer.endNode();
61: } else {
62: String name = mapper().serializedClass(item.getClass());
63: ExtendedHierarchicalStreamWriterHelper.startNode(writer,
64: name, item.getClass());
65: context.convertAnother(item);
66: writer.endNode();
67: }
68: }
69:
70: protected Object readItem(HierarchicalStreamReader reader,
71: UnmarshallingContext context, Object current) {
72: // PUBLISHED API METHOD! If changing signature, ensure backwards compatability.
73: String classAttribute = reader.getAttribute(mapper()
74: .aliasForAttribute("class"));
75: Class type;
76: if (classAttribute == null) {
77: type = mapper().realClass(reader.getNodeName());
78: } else {
79: type = mapper().realClass(classAttribute);
80: }
81: return context.convertAnother(current, type);
82: }
83:
84: protected Object createCollection(Class type) {
85: Class defaultType = mapper().defaultImplementationOf(type);
86: try {
87: return defaultType.newInstance();
88: } catch (InstantiationException e) {
89: throw new ConversionException("Cannot instantiate "
90: + defaultType.getName(), e);
91: } catch (IllegalAccessException e) {
92: throw new ConversionException("Cannot instantiate "
93: + defaultType.getName(), e);
94: }
95: }
96: }
|