/*
* Copyright (C) 2004, 2005, 2006 Joe Walnes.
* Copyright (C) 2006, 2007 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
* style license a copy of which has been included with this distribution in
* the LICENSE.txt file.
*
* Created on 15. March 2004 by Joe Walnes
*/
package com.thoughtworks.xstream.core;
import com.thoughtworks.xstream.XStreamException;
import com.thoughtworks.xstream.alias.ClassMapper;
import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.ConverterLookup;
import com.thoughtworks.xstream.converters.DataHolder;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.core.util.ObjectIdDictionary;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
import com.thoughtworks.xstream.mapper.Mapper;
import java.util.Iterator;
public class TreeMarshaller implements MarshallingContext {
protected HierarchicalStreamWriter writer;
protected ConverterLookup converterLookup;
/**
* @deprecated As of 1.2, use {@link #mapper}
*/
protected ClassMapper classMapper;
private Mapper mapper;
private ObjectIdDictionary parentObjects = new ObjectIdDictionary();
private DataHolder dataHolder;
public TreeMarshaller(
HierarchicalStreamWriter writer, ConverterLookup converterLookup, Mapper mapper) {
this.writer = writer;
this.converterLookup = converterLookup;
this.mapper = mapper;
// TODO: Remove when deprecated ClassMapper goes away
if (mapper instanceof ClassMapper) {
classMapper = (ClassMapper)mapper;
}
}
/**
* @deprecated As of 1.2, use
* {@link #TreeMarshaller(HierarchicalStreamWriter, ConverterLookup, Mapper)}
*/
public TreeMarshaller(
HierarchicalStreamWriter writer, ConverterLookup converterLookup,
ClassMapper classMapper) {
this(writer, converterLookup, (Mapper)classMapper);
}
public void convertAnother(Object item) {
convertAnother(item, null);
}
public void convertAnother(Object item, Converter converter) {
if (converter == null) {
converter = converterLookup.lookupConverterForType(item.getClass());
} else {
if (!converter.canConvert(item.getClass())) {
ConversionException e = new ConversionException(
"Explicit selected converter cannot handle item");
e.add("item-type", item.getClass().getName());
e.add("converter-type", converter.getClass().getName());
throw e;
}
}
convert(item, converter);
}
protected void convert(Object item, Converter converter) {
if (parentObjects.containsId(item)) {
throw new CircularReferenceException();
}
parentObjects.associateId(item, "");
converter.marshal(item, writer, this);
parentObjects.removeId(item);
}
public void start(Object item, DataHolder dataHolder) {
this.dataHolder = dataHolder;
if (item == null) {
writer.startNode(mapper.serializedClass(null));
writer.endNode();
} else {
ExtendedHierarchicalStreamWriterHelper.startNode(writer, mapper
.serializedClass(item.getClass()), item.getClass());
convertAnother(item);
writer.endNode();
}
}
public Object get(Object key) {
lazilyCreateDataHolder();
return dataHolder.get(key);
}
public void put(Object key, Object value) {
lazilyCreateDataHolder();
dataHolder.put(key, value);
}
public Iterator keys() {
lazilyCreateDataHolder();
return dataHolder.keys();
}
private void lazilyCreateDataHolder() {
if (dataHolder == null) {
dataHolder = new MapBackedDataHolder();
}
}
protected Mapper getMapper() {
return this.mapper;
}
public static class CircularReferenceException extends XStreamException {
}
}