/* * Copyright (C) 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 10. April 2007 by Guilherme Silveira */ package com.thoughtworks.xstream.converters.reflection; import com.thoughtworks.xstream.core.util.OrderRetainingMap; import com.thoughtworks.xstream.io.StreamException; import java.util.Arrays; import java.util.Comparator; import java.util.Map; import java.util.WeakHashMap; /** * The default implementation for sorting fields. Invoke registerFieldOrder in * order to set the field order for an specific type. * * @author Guilherme Silveira * @since 1.2.2 */ public class SortableFieldKeySorter implements FieldKeySorter { private final Map map = new WeakHashMap(); public Map sort(Class type, Map keyedByFieldKey) { if (map.containsKey(type)) { Map result = new OrderRetainingMap(); FieldKey[] fieldKeys = (FieldKey[]) keyedByFieldKey.keySet() .toArray(new FieldKey[keyedByFieldKey.size()]); Arrays.sort(fieldKeys, (Comparator) map.get(type)); for (int i = 0; i < fieldKeys.length; i++) { result.put(fieldKeys[i], keyedByFieldKey.get(fieldKeys[i])); } return result; } else { return keyedByFieldKey; } } /** * Registers the field order to use for a specific type. This will not * affect any of the type's super or sub classes. If you skip a field which * will be serialized, XStream will thrown an StreamException during the * serialization process. * * @param type * the type * @param fields * the field order */ public void registerFieldOrder(Class type, String[] fields) { map.put(type, new FieldComparator(fields)); } private class FieldComparator implements Comparator { private final String[] fieldOrder; public FieldComparator(String[] fields) { this.fieldOrder = fields; } public int compare(String first, String second) { int firstPosition = -1, secondPosition = -1; for (int i = 0; i < fieldOrder.length; i++) { if (fieldOrder[i].equals(first)) { firstPosition = i; } if (fieldOrder[i].equals(second)) { secondPosition = i; } } if (firstPosition == -1 || secondPosition == -1) { // field not defined!!! throw new StreamException( "You have not given XStream a list of all fields to be serialized."); } return firstPosition - secondPosition; } public int compare(Object firstObject, Object secondObject) { FieldKey first = (FieldKey) firstObject, second = (FieldKey) secondObject; Class definedIn = first.getDeclaringClass(); return compare(first.getFieldName(), second.getFieldName()); } } }