Package com.thoughtworks.xstream.converters.collections

Source Code of com.thoughtworks.xstream.converters.collections.TreeSetConverter

/*
* Copyright (C) 2004, 2005 Joe Walnes.
* Copyright (C) 2006, 2007, 2010, 2011 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.core.JVM;
import com.thoughtworks.xstream.core.util.PresortedSet;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.mapper.Mapper;

import java.lang.reflect.Field;
import java.util.AbstractList;
import java.util.Comparator;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
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 {
    private transient TreeMapConverter treeMapConverter; 
    private final static Field sortedMapField;
    static {
        Field smField = null;
        if (!JVM.hasOptimizedTreeSetAddAll()) {
            try {
                Field[] fields = TreeSet.class.getDeclaredFields();
                for (int i = 0; i < fields.length; i++ ) {
                    if (SortedMap.class.isAssignableFrom(fields[i].getType())) {
                        // take the fist member assignable to type "SortedMap"
                        smField = fields[i];
                        smField.setAccessible(true);
                        break;
                    }
                }
                if (smField == null) {
                    throw new ExceptionInInitializerError("Cannot detect field of backing map of TreeSet");
                }
   
            } catch (SecurityException ex) {
                // ignore, no access possible with current SecurityManager
            }
        }
        sortedMapField = smField;
    }

    public TreeSetConverter(Mapper mapper) {
        super(mapper);
        readResolve();
    }

    public boolean canConvert(Class type) {
        return type.equals(TreeSet.class);
    }

    public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
        TreeSet treeSet = (TreeSet) source;
        treeMapConverter.marshalComparator(treeSet.comparator(), writer, context);
        super.marshal(source, writer, context);
    }

    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
        TreeSet result = null;
        final TreeMap treeMap;
        Comparator unmarshalledComparator = treeMapConverter.unmarshalComparator(reader, context, null);
        boolean inFirstElement = unmarshalledComparator instanceof Mapper.Null;
        Comparator comparator = inFirstElement ? null : unmarshalledComparator;
        if (sortedMapField != null) {
            TreeSet possibleResult = comparator == null ? new TreeSet() : new TreeSet(comparator);
            Object backingMap = null;
            try {
                backingMap = sortedMapField.get(possibleResult);
            } catch (IllegalAccessException e) {
                throw new ConversionException("Cannot get backing map of TreeSet", e);
            }
            if (backingMap instanceof TreeMap) {
                treeMap = (TreeMap)backingMap;
                result = possibleResult;
            } else {
                treeMap = null;
            }
        } else {
            treeMap = null;
        }
        if (treeMap == null) {
            final PresortedSet set = new PresortedSet(comparator);
            result = comparator == null ? new TreeSet() : new TreeSet(comparator);
            if (inFirstElement) {
                // we are already within the first element
                addCurrentElementToCollection(reader, context, result, set);
                reader.moveUp();
            }
            populateCollection(reader, context, result, set);
            if (set.size() > 0) {
                result.addAll(set); // comparator will not be called if internally optimized
            }
        } else {
            treeMapConverter.populateTreeMap(reader, context, treeMap, unmarshalledComparator);
        }
        return result;
    }

    private Object readResolve() {
        treeMapConverter = new TreeMapConverter(mapper()) {

            protected void populateMap(HierarchicalStreamReader reader,
                UnmarshallingContext context, Map map, final Map target) {
                populateCollection(reader, context, new AbstractList() {
                    public boolean add(Object object) {
                        return target.put(object, object) != null;
                    }

                    public Object get(int location) {
                        return null;
                    }

                    public int size() {
                        return target.size();
                    }
                });
            }

            protected void putCurrentEntryIntoMap(HierarchicalStreamReader reader, UnmarshallingContext context,
                Map map, Map target) {
                Object key = readItem(reader, context, map);
                target.put(key, key);
            }
        };
        return this;
    }
}
TOP

Related Classes of com.thoughtworks.xstream.converters.collections.TreeSetConverter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.