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.List;
026: import java.util.SortedSet;
027: import java.util.TreeSet;
028:
029: /**
030: * Converts a java.util.TreeSet to XML, and serializes
031: * the associated java.util.Comparator. The converter
032: * assumes that the elements in the XML are already sorted
033: * according the comparator.
034: *
035: * @author Joe Walnes
036: * @author Jörg Schaible
037: */
038: public class TreeSetConverter extends CollectionConverter {
039:
040: public TreeSetConverter(Mapper mapper) {
041: super (mapper);
042: }
043:
044: public boolean canConvert(Class type) {
045: return type.equals(TreeSet.class);
046: }
047:
048: public void marshal(Object source, HierarchicalStreamWriter writer,
049: MarshallingContext context) {
050: TreeSet treeSet = (TreeSet) source;
051: Comparator comparator = treeSet.comparator();
052: if (comparator == null) {
053: writer.startNode("no-comparator");
054: writer.endNode();
055: } else {
056: writer.startNode("comparator");
057: writer.addAttribute("class", mapper().serializedClass(
058: comparator.getClass()));
059: context.convertAnother(comparator);
060: writer.endNode();
061: }
062: super .marshal(source, writer, context);
063: }
064:
065: public Object unmarshal(HierarchicalStreamReader reader,
066: UnmarshallingContext context) {
067: reader.moveDown();
068: final SortedSet sortedSet;
069: final TreeSet result;
070: if (reader.getNodeName().equals("comparator")) {
071: String comparatorClass = reader.getAttribute("class");
072: Comparator comparator = (Comparator) context
073: .convertAnother(null, mapper().realClass(
074: comparatorClass));
075: sortedSet = new PresortedSet(comparator);
076: result = new TreeSet(comparator);
077: } else if (reader.getNodeName().equals("no-comparator")) {
078: sortedSet = new PresortedSet();
079: result = new TreeSet();
080: } else {
081: throw new ConversionException(
082: "TreeSet does not contain <comparator> element");
083: }
084: reader.moveUp();
085: super .populateCollection(reader, context, sortedSet);
086: result.addAll(sortedSet); // internal optimization will not call comparator
087: return result;
088: }
089:
090: private static class PresortedSet implements SortedSet {
091: private final List list = new ArrayList();
092: private final Comparator comparator;
093:
094: PresortedSet() {
095: this (null);
096: }
097:
098: PresortedSet(Comparator comparator) {
099: this .comparator = comparator;
100: }
101:
102: public boolean add(Object e) {
103: return this .list.add(e);
104: }
105:
106: public boolean addAll(Collection c) {
107: return this .list.addAll(c);
108: }
109:
110: public void clear() {
111: this .list.clear();
112: }
113:
114: public boolean contains(Object o) {
115: return this .list.contains(o);
116: }
117:
118: public boolean containsAll(Collection c) {
119: return this .list.containsAll(c);
120: }
121:
122: public boolean equals(Object o) {
123: return this .list.equals(o);
124: }
125:
126: public int hashCode() {
127: return this .list.hashCode();
128: }
129:
130: public boolean isEmpty() {
131: return this .list.isEmpty();
132: }
133:
134: public Iterator iterator() {
135: return this .list.iterator();
136: }
137:
138: public boolean remove(Object o) {
139: return this .list.remove(o);
140: }
141:
142: public boolean removeAll(Collection c) {
143: return this .list.removeAll(c);
144: }
145:
146: public boolean retainAll(Collection c) {
147: return this .list.retainAll(c);
148: }
149:
150: public int size() {
151: return this .list.size();
152: }
153:
154: public List subList(int fromIndex, int toIndex) {
155: return this .list.subList(fromIndex, toIndex);
156: }
157:
158: public Object[] toArray() {
159: return this .list.toArray();
160: }
161:
162: public Object[] toArray(Object[] a) {
163: return this .list.toArray(a);
164: }
165:
166: public Comparator comparator() {
167: return comparator;
168: }
169:
170: public Object first() {
171: return list.isEmpty() ? null : list.get(0);
172: }
173:
174: public SortedSet headSet(Object toElement) {
175: throw new UnsupportedOperationException();
176: }
177:
178: public Object last() {
179: return list.isEmpty() ? null : list.get(list.size() - 1);
180: }
181:
182: public SortedSet subSet(Object fromElement, Object toElement) {
183: throw new UnsupportedOperationException();
184: }
185:
186: public SortedSet tailSet(Object fromElement) {
187: throw new UnsupportedOperationException();
188: }
189: }
190: }
|