01: /*
02: * Copyright (C) 2006, 2007 XStream Committers.
03: * All rights reserved.
04: *
05: * The software in this package is published under the terms of the BSD
06: * style license a copy of which has been included with this distribution in
07: * the LICENSE.txt file.
08: *
09: * Created on 15. March 2007 by Joerg Schaible
10: */
11: package com.thoughtworks.xstream.core;
12:
13: import java.util.HashMap;
14: import java.util.Map;
15:
16: import com.thoughtworks.xstream.converters.Converter;
17: import com.thoughtworks.xstream.converters.ConverterLookup;
18: import com.thoughtworks.xstream.core.util.FastStack;
19: import com.thoughtworks.xstream.io.HierarchicalStreamReader;
20: import com.thoughtworks.xstream.mapper.Mapper;
21:
22: /**
23: * Abstract base class for a TreeUnmarshaller, that resolves refrences.
24: *
25: * @author Joe Walnes
26: * @author Jörg Schaible
27: * @author Mauro Talevi
28: * @since 1.2
29: */
30: public abstract class AbstractReferenceUnmarshaller extends
31: TreeUnmarshaller {
32:
33: private Map values = new HashMap();
34: private FastStack parentStack = new FastStack(16);
35:
36: public AbstractReferenceUnmarshaller(Object root,
37: HierarchicalStreamReader reader,
38: ConverterLookup converterLookup, Mapper mapper) {
39: super (root, reader, converterLookup, mapper);
40: }
41:
42: protected Object convert(Object parent, Class type,
43: Converter converter) {
44: if (parentStack.size() > 0) { // handles circular references
45: Object parentReferenceKey = parentStack.peek();
46: if (parentReferenceKey != null) {
47: if (!values.containsKey(parentReferenceKey)) { // see AbstractCircularReferenceTest.testWeirdCircularReference()
48: values.put(parentReferenceKey, parent);
49: }
50: }
51: }
52: String reference = reader.getAttribute(getMapper()
53: .aliasForAttribute("reference"));
54: if (reference != null) {
55: return values.get(getReferenceKey(reference));
56: } else {
57: Object currentReferenceKey = getCurrentReferenceKey();
58: parentStack.push(currentReferenceKey);
59: Object result = super .convert(parent, type, converter);
60: if (currentReferenceKey != null) {
61: values.put(currentReferenceKey, result);
62: }
63: parentStack.popSilently();
64: return result;
65: }
66: }
67:
68: protected abstract Object getReferenceKey(String reference);
69:
70: protected abstract Object getCurrentReferenceKey();
71: }
|