* index than the second. */ protected static int compareIndices(Map indexMap, Object obj1, Object obj2, Integer fallbackIndex) { Integer index1 = (Integer)indexMap.get(obj1); Integer index2 = (Integer)indexMap.get(obj2); if (index1 == null) { index1 = fallbackIndex; } if (index2 == null) { index2 = fallbackIndex; } return index1.compareTo(index2); } /** * Helper method to compare two objects by their Long indices in the * given map. If the map doesn't contain an entry for either of the * objects, the fallback index will be used for the object instead. * * @param indexMap the map which maps objects into Long indexes. * @param obj1 the first object to be compared. * @param obj2 the second object to be compared. * @param fallbackIndex the Long to be used as a fallback index. * @return a negative integer, zero, or a positive integer as the * first object is mapped to a less, equal to, or greater * index than the second. */ protected static int compareLongs(Map indexMap, Object obj1, Object obj2, Long fallbackIndex) { Long index1 = (Long)indexMap.get(obj1); Long index2 = (Long)indexMap.get(obj2); if (index1 == null) { index1 = fallbackIndex; } if (index2 == null) { index2 = fallbackIndex; } return index1.compareTo(index2); } } /** * An IndexedComparator which compares two String charsets. The comparison * follows the rules outlined in DataFlavor.selectBestTextFlavor. In order * to ensure that non-Unicode, non-ASCII, non-default charsets are sorted * in alphabetical order, charsets are not automatically converted to their * canonical forms. */ public static class CharsetComparator extends IndexedComparator { private static final Map charsets; private static String defaultEncoding; private static final Integer DEFAULT_CHARSET_INDEX = Integer.valueOf(2); private static final Integer OTHER_CHARSET_INDEX = Integer.valueOf(1); private static final Integer WORST_CHARSET_INDEX = Integer.valueOf(0); private static final Integer UNSUPPORTED_CHARSET_INDEX = Integer.valueOf(Integer.MIN_VALUE); private static final String UNSUPPORTED_CHARSET = "UNSUPPORTED"; static { HashMap charsetsMap = new HashMap(8, 1.0f); // we prefer Unicode charsets charsetsMap.put(canonicalName("UTF-16LE"), Integer.valueOf(4)); charsetsMap.put(canonicalName("UTF-16BE"), Integer.valueOf(5)); charsetsMap.put(canonicalName("UTF-8"), Integer.valueOf(6)); charsetsMap.put(canonicalName("UTF-16"), Integer.valueOf(7)); // US-ASCII is the worst charset supported charsetsMap.put(canonicalName("US-ASCII"), WORST_CHARSET_INDEX); String defEncoding = DataTransferer.canonicalName (DataTransferer.getDefaultTextCharset()); if (charsetsMap.get(defaultEncoding) == null) { charsetsMap.put(defaultEncoding, DEFAULT_CHARSET_INDEX); } charsetsMap.put(UNSUPPORTED_CHARSET, UNSUPPORTED_CHARSET_INDEX); charsets = Collections.unmodifiableMap(charsetsMap); } public CharsetComparator() { this(SELECT_BEST); } public CharsetComparator(boolean order) { super(order); } /** * Compares two String objects. Returns a negative integer, zero, * or a positive integer as the first charset is worse than, equal to, * or better than the second. * * @param obj1 the first charset to be compared * @param obj2 the second charset to be compared * @return a negative integer, zero, or a positive integer as the * first argument is worse, equal to, or better than the * second. * @throws ClassCastException if either of the arguments is not * instance of String * @throws NullPointerException if either of the arguments is * <code>null</code>. */ public int compare(Object obj1, Object obj2) { String charset1 = null; String charset2 = null; if (order == SELECT_BEST) { charset1 = (String)obj1; charset2 = (String)obj2; } else { charset1 = (String)obj2; charset2 = (String)obj1; } return compareCharsets(charset1, charset2); } /** * Compares charsets. Returns a negative integer, zero, or a positive * integer as the first charset is worse than, equal to, or better than * the second. * <p> * Charsets are ordered according to the following rules: * <ul> * <li>All unsupported charsets are equal. * <li>Any unsupported charset is worse than any supported charset. * <li>Unicode charsets, such as "UTF-16", "UTF-8", "UTF-16BE" and * "UTF-16LE", are considered best. * <li>After them, platform default charset is selected. * <li>"US-ASCII" is the worst of supported charsets. * <li>For all other supported charsets, the lexicographically less * one is considered the better. * </ul> * * @param charset1 the first charset to be compared * @param charset2 the second charset to be compared. * @return a negative integer, zero, or a positive integer as the * first argument is worse, equal to, or better than the * second. */ protected int compareCharsets(String charset1, String charset2) { charset1 = getEncoding(charset1); charset2 = getEncoding(charset2); int comp = compareIndices(charsets, charset1, charset2, OTHER_CHARSET_INDEX); if (comp == 0) { return charset2.compareTo(charset1); } return comp; } /** * Returns encoding for the specified charset according to the * following rules: * <ul> * <li>If the charset is <code>null</code>, then <code>null</code> will * be returned. * <li>Iff the charset specifies an encoding unsupported by this JRE, * <code>UNSUPPORTED_CHARSET</code> will be returned. * <li>If the charset specifies an alias name, the corresponding * canonical name will be returned iff the charset is a known * Unicode, ASCII, or default charset. * </ul> * * @param charset the charset. * @return an encoding for this charset. */ protected static String getEncoding(String charset) { if (charset == null) { return null; } else if (!DataTransferer.isEncodingSupported(charset)) { return UNSUPPORTED_CHARSET; } else { // Only convert to canonical form if the charset is one // of the charsets explicitly listed in the known charsets // map. This will happen only for Unicode, ASCII, or default // charsets. String canonicalName = DataTransferer.canonicalName(charset); return (charsets.containsKey(canonicalName)) ? canonicalName : charset; } } } /** * An IndexedComparator which compares two DataFlavors. For text flavors, * the comparison follows the rules outlined in * DataFlavor.selectBestTextFlavor. For non-text flavors, unknown * application MIME types are preferred, followed by known * application/x-java-* MIME types. Unknown application types are preferred * because if the user provides his own data flavor, it will likely be the * most descriptive one. For flavors which are otherwise equal, the * flavors' native formats are compared, with greater long values * taking precedence. */ public static class DataFlavorComparator extends IndexedComparator { protected final Map flavorToFormatMap; private final CharsetComparator charsetComparator; private static final Map exactTypes; private static final Map primaryTypes; private static final Map nonTextRepresentations; private static final Map textTypes; private static final Map decodedTextRepresentations; private static final Map encodedTextRepresentations; private static final Integer UNKNOWN_OBJECT_LOSES = Integer.valueOf(Integer.MIN_VALUE); private static final Integer UNKNOWN_OBJECT_WINS = Integer.valueOf(Integer.MAX_VALUE); private static final Long UNKNOWN_OBJECT_LOSES_L = Long.valueOf(Long.MIN_VALUE); private static final Long UNKNOWN_OBJECT_WINS_L = Long.valueOf(Long.MAX_VALUE); static { { HashMap exactTypesMap = new HashMap(4, 1.0f); // application/x-java-* MIME types exactTypesMap.put("application/x-java-file-list", Integer.valueOf(0)); exactTypesMap.put("application/x-java-serialized-object", Integer.valueOf(1)); exactTypesMap.put("application/x-java-jvm-local-objectref", Integer.valueOf(2)); exactTypesMap.put("application/x-java-remote-object", Integer.valueOf(3)); exactTypes = Collections.unmodifiableMap(exactTypesMap); } { HashMap primaryTypesMap = new HashMap(1, 1.0f); primaryTypesMap.put("application", Integer.valueOf(0)); primaryTypes = Collections.unmodifiableMap(primaryTypesMap); } { HashMap nonTextRepresentationsMap = new HashMap(3, 1.0f); nonTextRepresentationsMap.put(java.io.InputStream.class, Integer.valueOf(0)); nonTextRepresentationsMap.put(java.io.Serializable.class, Integer.valueOf(1)); Class<?> remoteClass = RMI.remoteClass(); if (remoteClass != null) { nonTextRepresentationsMap.put(remoteClass, Integer.valueOf(2)); } nonTextRepresentations = Collections.unmodifiableMap(nonTextRepresentationsMap); } { HashMap textTypesMap = new HashMap(16, 1.0f); // plain text textTypesMap.put("text/plain", Integer.valueOf(0)); // stringFlavor textTypesMap.put("application/x-java-serialized-object", Integer.valueOf(1)); // misc textTypesMap.put("text/calendar", Integer.valueOf(2)); textTypesMap.put("text/css", Integer.valueOf(3)); textTypesMap.put("text/directory", Integer.valueOf(4)); textTypesMap.put("text/parityfec", Integer.valueOf(5)); textTypesMap.put("text/rfc822-headers", Integer.valueOf(6)); textTypesMap.put("text/t140", Integer.valueOf(7)); textTypesMap.put("text/tab-separated-values", Integer.valueOf(8)); textTypesMap.put("text/uri-list", Integer.valueOf(9)); // enriched textTypesMap.put("text/richtext", Integer.valueOf(10)); textTypesMap.put("text/enriched", Integer.valueOf(11)); textTypesMap.put("text/rtf", Integer.valueOf(12)); // markup textTypesMap.put("text/html", Integer.valueOf(13)); textTypesMap.put("text/xml", Integer.valueOf(14)); textTypesMap.put("text/sgml", Integer.valueOf(15)); textTypes = Collections.unmodifiableMap(textTypesMap); } { HashMap decodedTextRepresentationsMap = new HashMap(4, 1.0f); decodedTextRepresentationsMap.put (DataTransferer.charArrayClass, Integer.valueOf(0)); decodedTextRepresentationsMap.put (java.nio.CharBuffer.class, Integer.valueOf(1)); decodedTextRepresentationsMap.put (java.lang.String.class, Integer.valueOf(2)); decodedTextRepresentationsMap.put (java.io.Reader.class, Integer.valueOf(3)); decodedTextRepresentations = Collections.unmodifiableMap(decodedTextRepresentationsMap); } { HashMap encodedTextRepresentationsMap = new HashMap(3, 1.0f); encodedTextRepresentationsMap.put (DataTransferer.byteArrayClass, Integer.valueOf(0)); encodedTextRepresentationsMap.put (java.nio.ByteBuffer.class, Integer.valueOf(1)); encodedTextRepresentationsMap.put (java.io.InputStream.class, Integer.valueOf(2)); encodedTextRepresentations = Collections.unmodifiableMap(encodedTextRepresentationsMap); } } public DataFlavorComparator() { this(SELECT_BEST); } public DataFlavorComparator(boolean order) { super(order); charsetComparator = new CharsetComparator(order); flavorToFormatMap = Collections.EMPTY_MAP; } public DataFlavorComparator(Map map) { this(map, SELECT_BEST); } public DataFlavorComparator(Map map, boolean order) { super(order); charsetComparator = new CharsetComparator(order); HashMap hashMap = new HashMap(map.size()); hashMap.putAll(map); flavorToFormatMap = Collections.unmodifiableMap(hashMap); } public int compare(Object obj1, Object obj2) { DataFlavor flavor1 = null; DataFlavor flavor2 = null; if (order == SELECT_BEST) { flavor1 = (DataFlavor)obj1; flavor2 = (DataFlavor)obj2; } else { flavor1 = (DataFlavor)obj2; flavor2 = (DataFlavor)obj1; } if (flavor1.equals(flavor2)) { return 0; } int comp = 0; String primaryType1 = flavor1.getPrimaryType(); String subType1 = flavor1.getSubType(); String mimeType1 = primaryType1 + "/" + subType1; Class class1 = flavor1.getRepresentationClass(); String primaryType2 = flavor2.getPrimaryType(); String subType2 = flavor2.getSubType(); String mimeType2 = primaryType2 + "/" + subType2; Class class2 = flavor2.getRepresentationClass(); if (flavor1.isFlavorTextType() && flavor2.isFlavorTextType()) { // First, compare MIME types comp = compareIndices(textTypes, mimeType1, mimeType2, UNKNOWN_OBJECT_LOSES); if (comp != 0) { return comp; } // Only need to test one flavor because they both have the // same MIME type. Also don't need to worry about accidentally // passing stringFlavor because either // 1. Both flavors are stringFlavor, in which case the // equality test at the top of the function succeeded. // 2. Only one flavor is stringFlavor, in which case the MIME // type comparison returned a non-zero value. if (doesSubtypeSupportCharset(flavor1)) { // Next, prefer the decoded text representations of Reader, // String, CharBuffer, and [C, in that order. comp = compareIndices(decodedTextRepresentations, class1, class2, UNKNOWN_OBJECT_LOSES); if (comp != 0) { return comp; } // Next, compare charsets comp = charsetComparator.compareCharsets (DataTransferer.getTextCharset(flavor1), DataTransferer.getTextCharset(flavor2)); if (comp != 0) { return comp; } } // Finally, prefer the encoded text representations of // InputStream, ByteBuffer, and [B, in that order. comp = compareIndices(encodedTextRepresentations, class1, class2, UNKNOWN_OBJECT_LOSES); if (comp != 0) { return comp; } } else { // First, prefer application types. comp = compareIndices(primaryTypes, primaryType1, primaryType2, UNKNOWN_OBJECT_LOSES); if (comp != 0) { return comp; } // Next, look for application/x-java-* types. Prefer unknown // MIME types because if the user provides his own data flavor, // it will likely be the most descriptive one. comp = compareIndices(exactTypes, mimeType1, mimeType2, UNKNOWN_OBJECT_WINS); if (comp != 0) { return comp; } // Finally, prefer the representation classes of Remote, // Serializable, and InputStream, in that order. comp = compareIndices(nonTextRepresentations, class1, class2, UNKNOWN_OBJECT_LOSES); if (comp != 0) { return comp; } } // As a last resort, take the DataFlavor with the greater integer // format. return compareLongs(flavorToFormatMap, flavor1, flavor2, UNKNOWN_OBJECT_LOSES_L); } } /* * Given the Map that maps objects to Integer indices and a boolean value, * this Comparator imposes a direct or reverse order on set of objects. * <p> * If the specified boolean value is SELECT_BEST, the Comparator imposes the * direct index-based order: an object A is greater than an object B if and * only if the index of A is greater than the index of B. An object that * doesn't have an associated index is less or equal than any other object. * <p> * If the specified boolean value is SELECT_WORST, the Comparator imposes the * reverse index-based order: an object A is greater than an object B if and * only if A is less than B with the direct index-based order. */ public static class IndexOrderComparator extends IndexedComparator { private final Map indexMap; private static final Integer FALLBACK_INDEX = Integer.valueOf(Integer.MIN_VALUE); public IndexOrderComparator(Map indexMap) { super(SELECT_BEST); this.indexMap = indexMap; } public IndexOrderComparator(Map indexMap, boolean order) { super(order); this.indexMap = indexMap; } public int compare(Object obj1, Object obj2) { if (order == SELECT_WORST) { return -compareIndices(indexMap, obj1, obj2, FALLBACK_INDEX); } else { return compareIndices(indexMap, obj1, obj2, FALLBACK_INDEX); } } } /**Lines 2501–3000 of 3090. Previous lines Load more
* index than the second. */ protected static int compareIndices(Map indexMap, Object obj1, Object obj2, Integer fallbackIndex) { Integer index1 = (Integer)indexMap.get(obj1); Integer index2 = (Integer)indexMap.get(obj2); if (index1 == null) { index1 = fallbackIndex; } if (index2 == null) { index2 = fallbackIndex; } return index1.compareTo(index2); } /** * Helper method to compare two objects by their Long indices in the * given map. If the map doesn't contain an entry for either of the * objects, the fallback index will be used for the object instead. * * @param indexMap the map which maps objects into Long indexes. * @param obj1 the first object to be compared. * @param obj2 the second object to be compared. * @param fallbackIndex the Long to be used as a fallback index. * @return a negative integer, zero, or a positive integer as the * first object is mapped to a less, equal to, or greater * index than the second. */ protected static int compareLongs(Map indexMap, Object obj1, Object obj2, Long fallbackIndex) { Long index1 = (Long)indexMap.get(obj1); Long index2 = (Long)indexMap.get(obj2); if (index1 == null) { index1 = fallbackIndex; } if (index2 == null) { index2 = fallbackIndex; } return index1.compareTo(index2); } } /** * An IndexedComparator which compares two String charsets. The comparison * follows the rules outlined in DataFlavor.selectBestTextFlavor. In order * to ensure that non-Unicode, non-ASCII, non-default charsets are sorted * in alphabetical order, charsets are not automatically converted to their * canonical forms. */ public static class CharsetComparator extends IndexedComparator { private static final Map charsets; private static String defaultEncoding; private static final Integer DEFAULT_CHARSET_INDEX = Integer.valueOf(2); private static final Integer OTHER_CHARSET_INDEX = Integer.valueOf(1); private static final Integer WORST_CHARSET_INDEX = Integer.valueOf(0); private static final Integer UNSUPPORTED_CHARSET_INDEX = Integer.valueOf(Integer.MIN_VALUE); private static final String UNSUPPORTED_CHARSET = "UNSUPPORTED"; static { HashMap charsetsMap = new HashMap(8, 1.0f); // we prefer Unicode charsets charsetsMap.put(canonicalName("UTF-16LE"), Integer.valueOf(4)); charsetsMap.put(canonicalName("UTF-16BE"), Integer.valueOf(5)); charsetsMap.put(canonicalName("UTF-8"), Integer.valueOf(6)); charsetsMap.put(canonicalName("UTF-16"), Integer.valueOf(7)); // US-ASCII is the worst charset supported charsetsMap.put(canonicalName("US-ASCII"), WORST_CHARSET_INDEX); String defEncoding = DataTransferer.canonicalName (DataTransferer.getDefaultTextCharset()); if (charsetsMap.get(defaultEncoding) == null) { charsetsMap.put(defaultEncoding, DEFAULT_CHARSET_INDEX); } charsetsMap.put(UNSUPPORTED_CHARSET, UNSUPPORTED_CHARSET_INDEX); charsets = Collections.unmodifiableMap(charsetsMap); } public CharsetComparator() { this(SELECT_BEST); } public CharsetComparator(boolean order) { super(order); } /** * Compares two String objects. Returns a negative integer, zero, * or a positive integer as the first charset is worse than, equal to, * or better than the second. * * @param obj1 the first charset to be compared * @param obj2 the second charset to be compared * @return a negative integer, zero, or a positive integer as the * first argument is worse, equal to, or better than the * second. * @throws ClassCastException if either of the arguments is not * instance of String * @throws NullPointerException if either of the arguments is * <code>null</code>. */ public int compare(Object obj1, Object obj2) { String charset1 = null; String charset2 = null; if (order == SELECT_BEST) { charset1 = (String)obj1; charset2 = (String)obj2; } else { charset1 = (String)obj2; charset2 = (String)obj1; } return compareCharsets(charset1, charset2); } /** * Compares charsets. Returns a negative integer, zero, or a positive * integer as the first charset is worse than, equal to, or better than * the second. * <p> * Charsets are ordered according to the following rules: * <ul> * <li>All unsupported charsets are equal. * <li>Any unsupported charset is worse than any supported charset. * <li>Unicode charsets, such as "UTF-16", "UTF-8", "UTF-16BE" and * "UTF-16LE", are considered best. * <li>After them, platform default charset is selected. * <li>"US-ASCII" is the worst of supported charsets. * <li>For all other supported charsets, the lexicographically less * one is considered the better. * </ul> * * @param charset1 the first charset to be compared * @param charset2 the second charset to be compared. * @return a negative integer, zero, or a positive integer as the * first argument is worse, equal to, or better than the * second. */ protected int compareCharsets(String charset1, String charset2) { charset1 = getEncoding(charset1); charset2 = getEncoding(charset2); int comp = compareIndices(charsets, charset1, charset2, OTHER_CHARSET_INDEX); if (comp == 0) { return charset2.compareTo(charset1); } return comp; } /** * Returns encoding for the specified charset according to the * following rules: * <ul> * <li>If the charset is <code>null</code>, then <code>null</code> will * be returned. * <li>Iff the charset specifies an encoding unsupported by this JRE, * <code>UNSUPPORTED_CHARSET</code> will be returned. * <li>If the charset specifies an alias name, the corresponding * canonical name will be returned iff the charset is a known * Unicode, ASCII, or default charset. * </ul> * * @param charset the charset. * @return an encoding for this charset. */ protected static String getEncoding(String charset) { if (charset == null) { return null; } else if (!DataTransferer.isEncodingSupported(charset)) { return UNSUPPORTED_CHARSET; } else { // Only convert to canonical form if the charset is one // of the charsets explicitly listed in the known charsets // map. This will happen only for Unicode, ASCII, or default // charsets. String canonicalName = DataTransferer.canonicalName(charset); return (charsets.containsKey(canonicalName)) ? canonicalName : charset; } } } /** * An IndexedComparator which compares two DataFlavors. For text flavors, * the comparison follows the rules outlined in * DataFlavor.selectBestTextFlavor. For non-text flavors, unknown * application MIME types are preferred, followed by known * application/x-java-* MIME types. Unknown application types are preferred * because if the user provides his own data flavor, it will likely be the * most descriptive one. For flavors which are otherwise equal, the * flavors' native formats are compared, with greater long values * taking precedence. */ public static class DataFlavorComparator extends IndexedComparator { protected final Map flavorToFormatMap; private final CharsetComparator charsetComparator; private static final Map exactTypes; private static final Map primaryTypes; private static final Map nonTextRepresentations; private static final Map textTypes; private static final Map decodedTextRepresentations; private static final Map encodedTextRepresentations; private static final Integer UNKNOWN_OBJECT_LOSES = Integer.valueOf(Integer.MIN_VALUE); private static final Integer UNKNOWN_OBJECT_WINS = Integer.valueOf(Integer.MAX_VALUE); private static final Long UNKNOWN_OBJECT_LOSES_L = Long.valueOf(Long.MIN_VALUE); private static final Long UNKNOWN_OBJECT_WINS_L = Long.valueOf(Long.MAX_VALUE); static { { HashMap exactTypesMap = new HashMap(4, 1.0f); // application/x-java-* MIME types exactTypesMap.put("application/x-java-file-list", Integer.valueOf(0)); exactTypesMap.put("application/x-java-serialized-object", Integer.valueOf(1)); exactTypesMap.put("application/x-java-jvm-local-objectref", Integer.valueOf(2)); exactTypesMap.put("application/x-java-remote-object", Integer.valueOf(3)); exactTypes = Collections.unmodifiableMap(exactTypesMap); } { HashMap primaryTypesMap = new HashMap(1, 1.0f); primaryTypesMap.put("application", Integer.valueOf(0)); primaryTypes = Collections.unmodifiableMap(primaryTypesMap); } { HashMap nonTextRepresentationsMap = new HashMap(3, 1.0f); nonTextRepresentationsMap.put(java.io.InputStream.class, Integer.valueOf(0)); nonTextRepresentationsMap.put(java.io.Serializable.class, Integer.valueOf(1)); Class<?> remoteClass = RMI.remoteClass(); if (remoteClass != null) { nonTextRepresentationsMap.put(remoteClass, Integer.valueOf(2)); } nonTextRepresentations = Collections.unmodifiableMap(nonTextRepresentationsMap); } { HashMap textTypesMap = new HashMap(16, 1.0f); // plain text textTypesMap.put("text/plain", Integer.valueOf(0)); // stringFlavor textTypesMap.put("application/x-java-serialized-object", Integer.valueOf(1)); // misc textTypesMap.put("text/calendar", Integer.valueOf(2)); textTypesMap.put("text/css", Integer.valueOf(3)); textTypesMap.put("text/directory", Integer.valueOf(4)); textTypesMap.put("text/parityfec", Integer.valueOf(5)); textTypesMap.put("text/rfc822-headers", Integer.valueOf(6)); textTypesMap.put("text/t140", Integer.valueOf(7)); textTypesMap.put("text/tab-separated-values", Integer.valueOf(8)); textTypesMap.put("text/uri-list", Integer.valueOf(9)); // enriched textTypesMap.put("text/richtext", Integer.valueOf(10)); textTypesMap.put("text/enriched", Integer.valueOf(11)); textTypesMap.put("text/rtf", Integer.valueOf(12)); // markup textTypesMap.put("text/html", Integer.valueOf(13)); textTypesMap.put("text/xml", Integer.valueOf(14)); textTypesMap.put("text/sgml", Integer.valueOf(15)); textTypes = Collections.unmodifiableMap(textTypesMap); } { HashMap decodedTextRepresentationsMap = new HashMap(4, 1.0f); decodedTextRepresentationsMap.put (DataTransferer.charArrayClass, Integer.valueOf(0)); decodedTextRepresentationsMap.put (java.nio.CharBuffer.class, Integer.valueOf(1)); decodedTextRepresentationsMap.put (java.lang.String.class, Integer.valueOf(2)); decodedTextRepresentationsMap.put (java.io.Reader.class, Integer.valueOf(3)); decodedTextRepresentations = Collections.unmodifiableMap(decodedTextRepresentationsMap); } { HashMap encodedTextRepresentationsMap = new HashMap(3, 1.0f); encodedTextRepresentationsMap.put (DataTransferer.byteArrayClass, Integer.valueOf(0)); encodedTextRepresentationsMap.put (java.nio.ByteBuffer.class, Integer.valueOf(1)); encodedTextRepresentationsMap.put (java.io.InputStream.class, Integer.valueOf(2)); encodedTextRepresentations = Collections.unmodifiableMap(encodedTextRepresentationsMap); } } public DataFlavorComparator() { this(SELECT_BEST); } public DataFlavorComparator(boolean order) { super(order); charsetComparator = new CharsetComparator(order); flavorToFormatMap = Collections.EMPTY_MAP; } public DataFlavorComparator(Map map) { this(map, SELECT_BEST); } public DataFlavorComparator(Map map, boolean order) { super(order); charsetComparator = new CharsetComparator(order); HashMap hashMap = new HashMap(map.size()); hashMap.putAll(map); flavorToFormatMap = Collections.unmodifiableMap(hashMap); } public int compare(Object obj1, Object obj2) { DataFlavor flavor1 = null; DataFlavor flavor2 = null; if (order == SELECT_BEST) { flavor1 = (DataFlavor)obj1; flavor2 = (DataFlavor)obj2; } else { flavor1 = (DataFlavor)obj2; flavor2 = (DataFlavor)obj1; } if (flavor1.equals(flavor2)) { return 0; } int comp = 0; String primaryType1 = flavor1.getPrimaryType(); String subType1 = flavor1.getSubType(); String mimeType1 = primaryType1 + "/" + subType1; Class class1 = flavor1.getRepresentationClass(); String primaryType2 = flavor2.getPrimaryType(); String subType2 = flavor2.getSubType(); String mimeType2 = primaryType2 + "/" + subType2; Class class2 = flavor2.getRepresentationClass(); if (flavor1.isFlavorTextType() && flavor2.isFlavorTextType()) { // First, compare MIME types comp = compareIndices(textTypes, mimeType1, mimeType2, UNKNOWN_OBJECT_LOSES); if (comp != 0) { return comp; } // Only need to test one flavor because they both have the // same MIME type. Also don't need to worry about accidentally // passing stringFlavor because either // 1. Both flavors are stringFlavor, in which case the // equality test at the top of the function succeeded. // 2. Only one flavor is stringFlavor, in which case the MIME // type comparison returned a non-zero value. if (doesSubtypeSupportCharset(flavor1)) { // Next, prefer the decoded text representations of Reader, // String, CharBuffer, and [C, in that order. comp = compareIndices(decodedTextRepresentations, class1, class2, UNKNOWN_OBJECT_LOSES); if (comp != 0) { return comp; } // Next, compare charsets comp = charsetComparator.compareCharsets (DataTransferer.getTextCharset(flavor1), DataTransferer.getTextCharset(flavor2)); if (comp != 0) { return comp; } } // Finally, prefer the encoded text representations of // InputStream, ByteBuffer, and [B, in that order. comp = compareIndices(encodedTextRepresentations, class1, class2, UNKNOWN_OBJECT_LOSES); if (comp != 0) { return comp; } } else { // First, prefer application types. comp = compareIndices(primaryTypes, primaryType1, primaryType2, UNKNOWN_OBJECT_LOSES); if (comp != 0) { return comp; } // Next, look for application/x-java-* types. Prefer unknown // MIME types because if the user provides his own data flavor, // it will likely be the most descriptive one. comp = compareIndices(exactTypes, mimeType1, mimeType2, UNKNOWN_OBJECT_WINS); if (comp != 0) { return comp; } // Finally, prefer the representation classes of Remote, // Serializable, and InputStream, in that order. comp = compareIndices(nonTextRepresentations, class1, class2, UNKNOWN_OBJECT_LOSES); if (comp != 0) { return comp; } } // As a last resort, take the DataFlavor with the greater integer // format. return compareLongs(flavorToFormatMap, flavor1, flavor2, UNKNOWN_OBJECT_LOSES_L); } } /* * Given the Map that maps objects to Integer indices and a boolean value, * this Comparator imposes a direct or reverse order on set of objects. * <p> * If the specified boolean value is SELECT_BEST, the Comparator imposes the * direct index-based order: an object A is greater than an object B if and * only if the index of A is greater than the index of B. An object that * doesn't have an associated index is less or equal than any other object. * <p> * If the specified boolean value is SELECT_WORST, the Comparator imposes the * reverse index-based order: an object A is greater than an object B if and * only if A is less than B with the direct index-based order. */ public static class IndexOrderComparator extends IndexedComparator { private final Map indexMap; private static final Integer FALLBACK_INDEX = Integer.valueOf(Integer.MIN_VALUE); public IndexOrderComparator(Map indexMap) { super(SELECT_BEST); this.indexMap = indexMap; } public IndexOrderComparator(Map indexMap, boolean order) { super(order); this.indexMap = indexMap; } public int compare(Object obj1, Object obj2) { if (order == SELECT_WORST) { return -compareIndices(indexMap, obj1, obj2, FALLBACK_INDEX); } else { return compareIndices(indexMap, obj1, obj2, FALLBACK_INDEX); } } } /**