/* * Copyright (C) 2004, 2005 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 08. May 2004 by Joe Walnes */ package com.thoughtworks.xstream.converters.collections; import com.thoughtworks.xstream.converters.ConversionException; import com.thoughtworks.xstream.converters.MarshallingContext; import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; import com.thoughtworks.xstream.mapper.Mapper; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; /** * Converts a java.util.TreeSet to XML, and serializes * the associated java.util.Comparator. The converter * assumes that the elements in the XML are already sorted * according the comparator. * * @author Joe Walnes * @author Jörg Schaible */ public class TreeSetConverter extends CollectionConverter { public TreeSetConverter(Mapper mapper) { super(mapper); } public boolean canConvert(Class type) { return type.equals(TreeSet.class); } public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { TreeSet treeSet = (TreeSet) source; Comparator comparator = treeSet.comparator(); if (comparator == null) { writer.startNode("no-comparator"); writer.endNode(); } else { writer.startNode("comparator"); writer.addAttribute("class", mapper().serializedClass(comparator.getClass())); context.convertAnother(comparator); writer.endNode(); } super.marshal(source, writer, context); } public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { reader.moveDown(); final SortedSet sortedSet; final TreeSet result; if (reader.getNodeName().equals("comparator")) { String comparatorClass = reader.getAttribute("class"); Comparator comparator = (Comparator) context.convertAnother(null, mapper().realClass(comparatorClass)); sortedSet = new PresortedSet(comparator); result = new TreeSet(comparator); } else if (reader.getNodeName().equals("no-comparator")) { sortedSet = new PresortedSet(); result = new TreeSet(); } else { throw new ConversionException("TreeSet does not contain <comparator> element"); } reader.moveUp(); super.populateCollection(reader, context, sortedSet); result.addAll(sortedSet); // internal optimization will not call comparator return result; } private static class PresortedSet implements SortedSet { private final List list = new ArrayList(); private final Comparator comparator; PresortedSet() { this(null); } PresortedSet(Comparator comparator) { this.comparator = comparator; } public boolean add(Object e) { return this.list.add(e); } public boolean addAll(Collection c) { return this.list.addAll(c); } public void clear() { this.list.clear(); } public boolean contains(Object o) { return this.list.contains(o); } public boolean containsAll(Collection c) { return this.list.containsAll(c); } public boolean equals(Object o) { return this.list.equals(o); } public int hashCode() { return this.list.hashCode(); } public boolean isEmpty() { return this.list.isEmpty(); } public Iterator iterator() { return this.list.iterator(); } public boolean remove(Object o) { return this.list.remove(o); } public boolean removeAll(Collection c) { return this.list.removeAll(c); } public boolean retainAll(Collection c) { return this.list.retainAll(c); } public int size() { return this.list.size(); } public List subList(int fromIndex, int toIndex) { return this.list.subList(fromIndex, toIndex); } public Object[] toArray() { return this.list.toArray(); } public Object[] toArray(Object[] a) { return this.list.toArray(a); } public Comparator comparator() { return comparator; } public Object first() { return list.isEmpty() ? null : list.get(0); } public SortedSet headSet(Object toElement) { throw new UnsupportedOperationException(); } public Object last() { return list.isEmpty() ? null : list.get(list.size() - 1); } public SortedSet subSet(Object fromElement, Object toElement) { throw new UnsupportedOperationException(); } public SortedSet tailSet(Object fromElement) { throw new UnsupportedOperationException(); } } }