001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.data.osm; 003 004import static java.util.Comparator.comparing; 005import static java.util.Comparator.comparingInt; 006 007import java.util.Comparator; 008import java.util.HashMap; 009import java.util.Map; 010import java.util.function.Function; 011 012import org.openstreetmap.josm.gui.DefaultNameFormatter; 013import org.openstreetmap.josm.tools.AlphanumComparator; 014 015/** 016 * Comparators for comparing primitives. 017 */ 018public final class OsmPrimitiveComparator { 019 020 /** 021 * Returns a comparator comparing primitives by their name using {@link DefaultNameFormatter}. 022 * 023 * {@linkplain DefaultNameFormatter#format(OsmPrimitive) Formatted names} are cached. 024 * 025 * @return a comparator comparing primitives by their name using {@link DefaultNameFormatter} 026 */ 027 public static Comparator<OsmPrimitive> comparingNames() { 028 final Comparator<String> digitsLast = comparing(str -> Character.isDigit(str.charAt(0)) ? 1 : 0); 029 return comparing(memoize(DefaultNameFormatter.getInstance()::format), 030 digitsLast.thenComparing(AlphanumComparator.getInstance())); 031 } 032 033 /** 034 * Returns a comparator comparing primitives by their {@linkplain OsmPrimitive#getUniqueId unique id}. 035 * 036 * @return a comparator comparing primitives by their {@linkplain OsmPrimitive#getUniqueId unique id}. 037 */ 038 public static Comparator<OsmPrimitive> comparingUniqueId() { 039 return comparing(OsmPrimitive::getUniqueId); 040 } 041 042 /** 043 * Returns a comparator ordering the primitives by type in the order NODE, WAY, RELATION 044 * 045 * @return a comparator ordering the primitives by type in the order NODE, WAY, RELATION 046 */ 047 public static Comparator<OsmPrimitive> orderingNodesWaysRelations() { 048 return comparingInt(osm -> osm.getType().ordinal()); 049 } 050 051 /** 052 * Returns a comparator ordering the primitives by type in the order WAY, RELATION, NODE 053 * 054 * @return a comparator ordering the primitives by type in the order WAY, RELATION, NODE 055 */ 056 public static Comparator<OsmPrimitive> orderingWaysRelationsNodes() { 057 return comparingInt(osm -> { 058 switch (osm.getType()) { 059 case WAY: 060 return 1; 061 case RELATION: 062 return 2; 063 case NODE: 064 return 3; 065 default: 066 throw new IllegalStateException(); 067 } 068 }); 069 } 070 071 private static <T, R> Function<T, R> memoize(Function<T, R> base) { 072 final Map<T, R> cache = new HashMap<>(); 073 return t -> cache.computeIfAbsent(t, base); 074 } 075 076 private OsmPrimitiveComparator() { 077 } 078}