001: /*
002: * Copyright (C) 2004, 2005 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 08. May 2004 by Joe Walnes
011: */
012: package com.thoughtworks.xstream.converters.collections;
013:
014: import com.thoughtworks.xstream.converters.ConversionException;
015: import com.thoughtworks.xstream.converters.MarshallingContext;
016: import com.thoughtworks.xstream.converters.UnmarshallingContext;
017: import com.thoughtworks.xstream.io.HierarchicalStreamReader;
018: import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
019: import com.thoughtworks.xstream.mapper.Mapper;
020:
021: import java.util.ArrayList;
022: import java.util.Collection;
023: import java.util.Comparator;
024: import java.util.Iterator;
025: import java.util.Map;
026: import java.util.Set;
027: import java.util.SortedMap;
028: import java.util.TreeMap;
029:
030: /**
031: * Converts a java.util.TreeMap to XML, and serializes
032: * the associated java.util.Comparator. The converter
033: * assumes that the entries in the XML are already sorted
034: * according the comparator.
035: *
036: * @author Joe Walnes
037: * @author Jörg Schaible
038: */
039: public class TreeMapConverter extends MapConverter {
040:
041: public TreeMapConverter(Mapper mapper) {
042: super (mapper);
043: }
044:
045: public boolean canConvert(Class type) {
046: return type.equals(TreeMap.class);
047: }
048:
049: public void marshal(Object source, HierarchicalStreamWriter writer,
050: MarshallingContext context) {
051: TreeMap treeMap = (TreeMap) source;
052: Comparator comparator = treeMap.comparator();
053: if (comparator == null) {
054: writer.startNode("no-comparator");
055: writer.endNode();
056: } else {
057: writer.startNode("comparator");
058: writer.addAttribute("class", mapper().serializedClass(
059: comparator.getClass()));
060: context.convertAnother(comparator);
061: writer.endNode();
062: }
063: super .marshal(source, writer, context);
064: }
065:
066: public Object unmarshal(HierarchicalStreamReader reader,
067: UnmarshallingContext context) {
068: reader.moveDown();
069: SortedMap sortedMap;
070: TreeMap result;
071: if (reader.getNodeName().equals("comparator")) {
072: String comparatorClass = reader.getAttribute("class");
073: Comparator comparator = (Comparator) context
074: .convertAnother(null, mapper().realClass(
075: comparatorClass));
076: sortedMap = new PresortedMap(comparator);
077: result = new TreeMap(comparator);
078: } else if (reader.getNodeName().equals("no-comparator")) {
079: sortedMap = new PresortedMap();
080: result = new TreeMap();
081: } else {
082: throw new ConversionException(
083: "TreeMap does not contain <comparator> element");
084: }
085: reader.moveUp();
086: super .populateMap(reader, context, sortedMap);
087: result.putAll(sortedMap); // // internal optimization will not call comparator
088: return result;
089: }
090:
091: private static class PresortedMap implements SortedMap {
092:
093: private static class ArraySet extends ArrayList implements Set {
094: }
095:
096: private final ArraySet set = new ArraySet();
097: private final Comparator comparator;
098:
099: PresortedMap() {
100: this (null);
101: }
102:
103: PresortedMap(Comparator comparator) {
104: this .comparator = comparator;
105: }
106:
107: public Comparator comparator() {
108: return comparator;
109: }
110:
111: public Set entrySet() {
112: return set;
113: }
114:
115: public Object firstKey() {
116: throw new UnsupportedOperationException();
117: }
118:
119: public SortedMap headMap(Object toKey) {
120: throw new UnsupportedOperationException();
121: }
122:
123: public Set keySet() {
124: Set keySet = new ArraySet();
125: for (final Iterator iterator = set.iterator(); iterator
126: .hasNext();) {
127: final Entry entry = (Entry) iterator.next();
128: keySet.add(entry.getKey());
129: }
130: return keySet;
131: }
132:
133: public Object lastKey() {
134: throw new UnsupportedOperationException();
135: }
136:
137: public SortedMap subMap(Object fromKey, Object toKey) {
138: throw new UnsupportedOperationException();
139: }
140:
141: public SortedMap tailMap(Object fromKey) {
142: throw new UnsupportedOperationException();
143: }
144:
145: public Collection values() {
146: Set values = new ArraySet();
147: for (final Iterator iterator = set.iterator(); iterator
148: .hasNext();) {
149: final Entry entry = (Entry) iterator.next();
150: values.add(entry.getValue());
151: }
152: return values;
153: }
154:
155: public void clear() {
156: throw new UnsupportedOperationException();
157: }
158:
159: public boolean containsKey(Object key) {
160: return false;
161: }
162:
163: public boolean containsValue(Object value) {
164: throw new UnsupportedOperationException();
165: }
166:
167: public Object get(Object key) {
168: throw new UnsupportedOperationException();
169: }
170:
171: public boolean isEmpty() {
172: return set.isEmpty();
173: }
174:
175: public Object put(final Object key, final Object value) {
176: set.add(new Entry() {
177:
178: public Object getKey() {
179: return key;
180: }
181:
182: public Object getValue() {
183: return value;
184: }
185:
186: public Object setValue(Object value) {
187: throw new UnsupportedOperationException();
188: }
189: });
190: return null;
191: }
192:
193: public void putAll(Map m) {
194: for (final Iterator iter = m.entrySet().iterator(); iter
195: .hasNext();) {
196: set.add(iter.next());
197: }
198: }
199:
200: public Object remove(Object key) {
201: throw new UnsupportedOperationException();
202: }
203:
204: public int size() {
205: return set.size();
206: }
207:
208: }
209: }
|