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