Changeset 11177 in josm


Ignore:
Timestamp:
2016-10-27T00:32:55+02:00 (3 years ago)
Author:
simon04
Message:

Refactor OsmPrimitiveComparator

Replace one big comparator with functions to obtain specific simple comparators.

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/APIDataSet.java

    r11176 r11177  
    2121import org.openstreetmap.josm.data.osm.Node;
    2222import org.openstreetmap.josm.data.osm.OsmPrimitive;
     23import org.openstreetmap.josm.data.osm.OsmPrimitiveComparator;
    2324import org.openstreetmap.josm.data.osm.PrimitiveId;
    2425import org.openstreetmap.josm.data.osm.Relation;
     
    7677            }
    7778        }
    78         final Comparator<OsmPrimitive> orderingNodesWaysRelations = Comparator.comparingInt(osm -> osm.getType().ordinal());
    79         final Comparator<OsmPrimitive> byUniqueId = Comparator.comparing(OsmPrimitive::getUniqueId);
     79        final Comparator<OsmPrimitive> orderingNodesWaysRelations = OsmPrimitiveComparator.orderingNodesWaysRelations();
     80        final Comparator<OsmPrimitive> byUniqueId = OsmPrimitiveComparator.comparingUniqueId();
    8081        toAdd.sort(orderingNodesWaysRelations.thenComparing(byUniqueId));
    8182        toUpdate.sort(orderingNodesWaysRelations.thenComparing(byUniqueId));
  • trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitiveComparator.java

    r9929 r11177  
    22package org.openstreetmap.josm.data.osm;
    33
    4 import java.io.Serializable;
     4import static java.util.Comparator.comparing;
     5import static java.util.Comparator.comparingInt;
     6
    57import java.util.Comparator;
    68import java.util.HashMap;
     9import java.util.Map;
     10import java.util.function.Function;
    711
    812import org.openstreetmap.josm.gui.DefaultNameFormatter;
     13import org.openstreetmap.josm.tools.AlphanumComparator;
    914
    1015/**
    11  * Comparator, comparing pritimives by:<ul>
    12  * <li>type and ids in "quick" mode</li>
    13  * <li>type and objects display names instead</li>
    14  * </ul>
    15  * @since 4113
     16 * Comparators for comparing primitives.
    1617 */
    17 public class OsmPrimitiveComparator implements Comparator<OsmPrimitive>, Serializable {
    18 
    19     private static final long serialVersionUID = 1L;
    20 
    21     private final HashMap<OsmPrimitive, String> cache = new HashMap<>();
    22     private final boolean relationsFirst;
    23     private final boolean quick;
     18public final class OsmPrimitiveComparator {
    2419
    2520    /**
    26      * Constructs a new {@code OsmPrimitiveComparator}.
     21     * Returns a comparator comparing primitives by their name using {@link DefaultNameFormatter}.
     22     *
     23     * {@linkplain DefaultNameFormatter#format(OsmPrimitive) Formatted names} are cached.
     24     *
     25     * @return a comparator comparing primitives by their name using {@link DefaultNameFormatter}
    2726     */
    28     public OsmPrimitiveComparator() {
    29         this(false, false);
     27    public static Comparator<OsmPrimitive> comparingNames() {
     28        final Comparator<String> digitsLast = comparing(str -> Character.isDigit(str.charAt(0)) ? 1 : 0);
     29        return comparing(memoize(DefaultNameFormatter.getInstance()::format),
     30                digitsLast.thenComparing(AlphanumComparator.getInstance()));
    3031    }
    3132
    3233    /**
    33      * Constructs a new {@code OsmPrimitiveComparator}.
    34      * @param quick if {@code true}, sorts by type and ids (fast), otherwise sort by type and display names (slower)
    35      * @param relationsFirst if {@code true}, always list relations first
     34     * Returns a comparator comparing primitives by their {@linkplain OsmPrimitive#getUniqueId unique id}.
     35     *
     36     * @return a comparator comparing primitives by their {@linkplain OsmPrimitive#getUniqueId unique id}.
    3637     */
    37     public OsmPrimitiveComparator(boolean quick, boolean relationsFirst) {
    38         this.quick = quick;
    39         this.relationsFirst = relationsFirst;
     38    public static Comparator<OsmPrimitive> comparingUniqueId() {
     39        return comparing(OsmPrimitive::getUniqueId);
    4040    }
    4141
    42     private String cachedName(OsmPrimitive p) {
    43         String name = cache.get(p);
    44         if (name == null) {
    45             name = p.getDisplayName(DefaultNameFormatter.getInstance());
    46             cache.put(p, name);
    47         }
    48         return name;
     42    /**
     43     * Returns a comparator ordering the primitives by type in the order NODE, WAY, RELATION
     44     *
     45     * @return a comparator ordering the primitives by type in the order NODE, WAY, RELATION
     46     */
     47    public static Comparator<OsmPrimitive> orderingNodesWaysRelations() {
     48        return comparingInt(osm -> osm.getType().ordinal());
    4949    }
    5050
    51     private int compareName(OsmPrimitive a, OsmPrimitive b) {
    52         String an = cachedName(a);
    53         String bn = cachedName(b);
    54         // make sure display names starting with digits are the end of the list
    55         if (Character.isDigit(an.charAt(0)) && Character.isDigit(bn.charAt(0)))
    56             return an.compareTo(bn);
    57         else if (Character.isDigit(an.charAt(0)) && !Character.isDigit(bn.charAt(0)))
    58             return 1;
    59         else if (!Character.isDigit(an.charAt(0)) && Character.isDigit(bn.charAt(0)))
    60             return -1;
    61         return an.compareTo(bn);
     51    /**
     52     * Returns a comparator ordering the primitives by type in the order WAY, RELATION, NODE
     53     *
     54     * @return a comparator ordering the primitives by type in the order WAY, RELATION, NODE
     55     */
     56    public static Comparator<OsmPrimitive> orderingWaysRelationsNodes() {
     57        return comparingInt(osm -> {
     58            switch (osm.getType()) {
     59                case WAY:
     60                    return 1;
     61                case RELATION:
     62                    return 2;
     63                case NODE:
     64                    return 3;
     65                default:
     66                    throw new IllegalStateException();
     67            }
     68        });
    6269    }
    6370
    64     private static int compareId(OsmPrimitive a, OsmPrimitive b) {
    65         long idA = a.getUniqueId();
    66         long idB = b.getUniqueId();
    67         if (idA < idB) return -1;
    68         if (idA > idB) return 1;
    69         return 0;
     71    private static <T, R> Function<T, R> memoize(Function<T, R> base) {
     72        final Map<T, R> cache = new HashMap<>();
     73        return t -> cache.computeIfAbsent(t, base);
    7074    }
    7175
    72     private int compareType(OsmPrimitive a, OsmPrimitive b) {
    73         if (relationsFirst) {
    74             // show relations before ways, then nodes
    75             if (a.getType().equals(OsmPrimitiveType.RELATION)) return -1;
    76             if (a.getType().equals(OsmPrimitiveType.NODE)) return 1;
    77             // a is a way
    78             if (b.getType().equals(OsmPrimitiveType.RELATION)) return 1;
    79             // b is a node
    80         } else {
    81             // show ways before relations, then nodes
    82             if (a.getType().equals(OsmPrimitiveType.WAY)) return -1;
    83             if (a.getType().equals(OsmPrimitiveType.NODE)) return 1;
    84             // a is a relation
    85             if (b.getType().equals(OsmPrimitiveType.WAY)) return 1;
    86             // b is a node
    87         }
    88         return -1;
    89     }
    90 
    91     @Override
    92     public int compare(OsmPrimitive a, OsmPrimitive b) {
    93         if (a.getType().equals(b.getType()))
    94             return quick ? compareId(a, b) : compareName(a, b);
    95         return compareType(a, b);
     76    private OsmPrimitiveComparator() {
    9677    }
    9778}
  • trunk/src/org/openstreetmap/josm/gui/dialogs/InspectPrimitiveDialog.java

    r10694 r11177  
    107107    protected static String buildDataText(OsmDataLayer layer, List<OsmPrimitive> primitives) {
    108108        InspectPrimitiveDataText dt = new InspectPrimitiveDataText(layer);
    109         primitives.sort(new OsmPrimitiveComparator());
    110         for (OsmPrimitive o : primitives) {
    111             dt.addPrimitive(o);
    112         }
     109        primitives.stream()
     110                .sorted(OsmPrimitiveComparator.orderingWaysRelationsNodes().thenComparing(OsmPrimitiveComparator.comparingNames()))
     111                .forEachOrdered(dt::addPrimitive);
    113112        return dt.toString();
    114113    }
  • trunk/src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java

    r11100 r11177  
    659659            if (selection.size() <= Main.pref.getInteger("selection.no_sort_above", 100_000)) {
    660660                boolean quick = selection.size() > Main.pref.getInteger("selection.fast_sort_above", 10_000);
    661                 selection.sort(new OsmPrimitiveComparator(quick, false));
     661                selection.sort(OsmPrimitiveComparator.orderingWaysRelationsNodes().thenComparing(quick
     662                        ? OsmPrimitiveComparator.comparingUniqueId()
     663                        : OsmPrimitiveComparator.comparingNames()));
    662664            }
    663665        }
  • trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java

    r11033 r11177  
    646646         * (Only works if the data layer has not been saved to and been loaded from an osm file before.)
    647647         */
    648         final List<Way> sortedWays = new ArrayList<>(ways);
    649         sortedWays.sort(new OsmPrimitiveComparator(true, false)); // sort by OsmPrimitive#getUniqueId ascending
    650         Collections.reverse(sortedWays); // sort by OsmPrimitive#getUniqueId descending
    651         for (Way w : sortedWays) {
     648        ways.stream()
     649                .sorted(OsmPrimitiveComparator.comparingUniqueId().reversed())
     650                .forEachOrdered(w -> {
    652651            if (!w.isUsable()) {
    653                 continue;
     652                return;
    654653            }
    655654            Collection<Collection<WayPoint>> trk = new ArrayList<>();
     
    677676
    678677            gpxData.tracks.add(new ImmutableGpxTrack(trk, trkAttr));
    679         }
     678        });
    680679    }
    681680
  • trunk/test/unit/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialogTest.java

    r10962 r11177  
    3434    private static String createSearchSetting(DataSet ds, boolean sameType) {
    3535        List<OsmPrimitive> sel = new ArrayList<>(ds.allPrimitives());
    36         Collections.sort(sel, new OsmPrimitiveComparator(true, false));
     36        Collections.sort(sel, OsmPrimitiveComparator.comparingUniqueId());
    3737        return PropertiesDialog.createSearchSetting("foo", sel, sameType).text;
    3838    }
Note: See TracChangeset for help on using the changeset viewer.