001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data.osm;
003
004import java.util.Comparator;
005import java.util.HashMap;
006import java.util.Map;
007
008import org.openstreetmap.josm.gui.DefaultNameFormatter;
009
010/** Comparator, comparing by type and objects display names */
011public class OsmPrimitiveComparator implements Comparator<OsmPrimitive> {
012    final private Map<OsmPrimitive, String> cache= new HashMap<OsmPrimitive, String>();
013    final private DefaultNameFormatter df = DefaultNameFormatter.getInstance();
014    public boolean relationsFirst = false;
015
016    private String cachedName(OsmPrimitive p) {
017        String name = cache.get(p);
018        if (name == null) {
019            name = p.getDisplayName(df);
020            cache.put(p, name);
021        }
022        return name;
023    }
024
025    private int compareName(OsmPrimitive a, OsmPrimitive b) {
026        String an = cachedName(a);
027        String bn = cachedName(b);
028        // make sure display names starting with digits are the end of the
029        // list
030        if (Character.isDigit(an.charAt(0)) && Character.isDigit(bn.charAt(0)))
031            return an.compareTo(bn);
032        else if (Character.isDigit(an.charAt(0)) && !Character.isDigit(bn.charAt(0)))
033            return 1;
034        else if (!Character.isDigit(an.charAt(0)) && Character.isDigit(bn.charAt(0)))
035            return -1;
036        return an.compareTo(bn);
037    }
038
039    private int compareType(OsmPrimitive a, OsmPrimitive b) {
040        if(relationsFirst) {
041            // show relations before ways, then nodes
042            if (a.getType().equals(OsmPrimitiveType.RELATION)) return -1;
043            if (a.getType().equals(OsmPrimitiveType.NODE)) return 1;
044            // a is a way
045            if (b.getType().equals(OsmPrimitiveType.RELATION)) return 1;
046            // b is a node
047        } else {
048            // show ways before relations, then nodes
049            if (a.getType().equals(OsmPrimitiveType.WAY)) return -1;
050            if (a.getType().equals(OsmPrimitiveType.NODE)) return 1;
051            // a is a relation
052            if (b.getType().equals(OsmPrimitiveType.WAY)) return 1;
053            // b is a node
054        }
055        return -1;
056    }
057
058    @Override
059    public int compare(OsmPrimitive a, OsmPrimitive b) {
060        if (a.getType().equals(b.getType()))
061            return compareName(a, b);
062        return compareType(a, b);
063    }
064}