001: /*
002: * Copyright (C) 2004, 2005, 2006 Joe Walnes.
003: * Copyright (C) 2006, 2007 XStream Committers.
004: * All rights reserved.
005: *
006: * The software in this package is published under the terms of the BSD
007: * style license a copy of which has been included with this distribution in
008: * the LICENSE.txt file.
009: *
010: * Created on 15. March 2004 by Joe Walnes
011: */
012: package com.thoughtworks.xstream.core;
013:
014: import com.thoughtworks.xstream.XStreamException;
015: import com.thoughtworks.xstream.alias.ClassMapper;
016: import com.thoughtworks.xstream.converters.ConversionException;
017: import com.thoughtworks.xstream.converters.Converter;
018: import com.thoughtworks.xstream.converters.ConverterLookup;
019: import com.thoughtworks.xstream.converters.DataHolder;
020: import com.thoughtworks.xstream.converters.MarshallingContext;
021: import com.thoughtworks.xstream.core.util.ObjectIdDictionary;
022: import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
023: import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
024: import com.thoughtworks.xstream.mapper.Mapper;
025:
026: import java.util.Iterator;
027:
028: public class TreeMarshaller implements MarshallingContext {
029:
030: protected HierarchicalStreamWriter writer;
031: protected ConverterLookup converterLookup;
032: /**
033: * @deprecated As of 1.2, use {@link #mapper}
034: */
035: protected ClassMapper classMapper;
036: private Mapper mapper;
037: private ObjectIdDictionary parentObjects = new ObjectIdDictionary();
038: private DataHolder dataHolder;
039:
040: public TreeMarshaller(HierarchicalStreamWriter writer,
041: ConverterLookup converterLookup, Mapper mapper) {
042: this .writer = writer;
043: this .converterLookup = converterLookup;
044: this .mapper = mapper;
045: // TODO: Remove when deprecated ClassMapper goes away
046: if (mapper instanceof ClassMapper) {
047: classMapper = (ClassMapper) mapper;
048: }
049: }
050:
051: /**
052: * @deprecated As of 1.2, use
053: * {@link #TreeMarshaller(HierarchicalStreamWriter, ConverterLookup, Mapper)}
054: */
055: public TreeMarshaller(HierarchicalStreamWriter writer,
056: ConverterLookup converterLookup, ClassMapper classMapper) {
057: this (writer, converterLookup, (Mapper) classMapper);
058: }
059:
060: public void convertAnother(Object item) {
061: convertAnother(item, null);
062: }
063:
064: public void convertAnother(Object item, Converter converter) {
065: if (converter == null) {
066: converter = converterLookup.lookupConverterForType(item
067: .getClass());
068: } else {
069: if (!converter.canConvert(item.getClass())) {
070: ConversionException e = new ConversionException(
071: "Explicit selected converter cannot handle item");
072: e.add("item-type", item.getClass().getName());
073: e.add("converter-type", converter.getClass().getName());
074: throw e;
075: }
076: }
077: convert(item, converter);
078: }
079:
080: protected void convert(Object item, Converter converter) {
081: if (parentObjects.containsId(item)) {
082: throw new CircularReferenceException();
083: }
084: parentObjects.associateId(item, "");
085: converter.marshal(item, writer, this );
086: parentObjects.removeId(item);
087: }
088:
089: public void start(Object item, DataHolder dataHolder) {
090: this .dataHolder = dataHolder;
091: if (item == null) {
092: writer.startNode(mapper.serializedClass(null));
093: writer.endNode();
094: } else {
095: ExtendedHierarchicalStreamWriterHelper.startNode(writer,
096: mapper.serializedClass(item.getClass()), item
097: .getClass());
098: convertAnother(item);
099: writer.endNode();
100: }
101: }
102:
103: public Object get(Object key) {
104: lazilyCreateDataHolder();
105: return dataHolder.get(key);
106: }
107:
108: public void put(Object key, Object value) {
109: lazilyCreateDataHolder();
110: dataHolder.put(key, value);
111: }
112:
113: public Iterator keys() {
114: lazilyCreateDataHolder();
115: return dataHolder.keys();
116: }
117:
118: private void lazilyCreateDataHolder() {
119: if (dataHolder == null) {
120: dataHolder = new MapBackedDataHolder();
121: }
122: }
123:
124: protected Mapper getMapper() {
125: return this .mapper;
126: }
127:
128: public static class CircularReferenceException extends
129: XStreamException {
130: }
131: }
|