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.tools.AlphanumComparator; 013 014/** 015 * Comparators for comparing primitives. 016 */ 017public final class OsmPrimitiveComparator { 018 019 /** 020 * Returns a comparator comparing primitives by their name using {@link DefaultNameFormatter}. 021 * 022 * {@linkplain DefaultNameFormatter#format(IPrimitive) Formatted names} are cached. 023 * 024 * @return a comparator comparing primitives by their name using {@link DefaultNameFormatter} 025 */ 026 public static Comparator<OsmPrimitive> comparingNames() { 027 final Comparator<String> digitsLast = comparing(str -> !str.isEmpty() && Character.isDigit(str.charAt(0)) ? 1 : 0); 028 return comparing(memoize(DefaultNameFormatter.getInstance()::format), 029 digitsLast.thenComparing(AlphanumComparator.getInstance())); 030 } 031 032 /** 033 * Returns a comparator comparing primitives by their {@linkplain OsmPrimitive#getUniqueId unique id}. 034 * 035 * @return a comparator comparing primitives by their {@linkplain OsmPrimitive#getUniqueId unique id}. 036 */ 037 public static Comparator<OsmPrimitive> comparingUniqueId() { 038 return comparing(OsmPrimitive::getUniqueId); 039 } 040 041 /** 042 * Returns a comparator ordering the primitives by type in the order NODE, WAY, RELATION 043 * 044 * @return a comparator ordering the primitives by type in the order NODE, WAY, RELATION 045 */ 046 public static Comparator<OsmPrimitive> orderingNodesWaysRelations() { 047 return comparingInt(osm -> osm.getType().ordinal()); 048 } 049 050 /** 051 * Returns a comparator ordering the primitives by type in the order WAY, RELATION, NODE 052 * 053 * @return a comparator ordering the primitives by type in the order WAY, RELATION, NODE 054 */ 055 public static Comparator<OsmPrimitive> orderingWaysRelationsNodes() { 056 return comparingInt(osm -> { 057 switch (osm.getType()) { 058 case WAY: 059 return 1; 060 case RELATION: 061 return 2; 062 case NODE: 063 return 3; 064 default: 065 throw new IllegalStateException(); 066 } 067 }); 068 } 069 070 /** 071 * Returns a comparator ordering the primitives by type in the order RELATION, WAY, NODE 072 * 073 * @return a comparator ordering the primitives by type in the order RELATION, WAY, NODE 074 * @since 11679 075 */ 076 public static Comparator<OsmPrimitive> orderingRelationsWaysNodes() { 077 return comparingInt(osm -> { 078 switch (osm.getType()) { 079 case RELATION: 080 return 1; 081 case WAY: 082 return 2; 083 case NODE: 084 return 3; 085 default: 086 throw new IllegalStateException(); 087 } 088 }); 089 } 090 091 private static <T, R> Function<T, R> memoize(Function<T, R> base) { 092 final Map<T, R> cache = new HashMap<>(); 093 return t -> cache.computeIfAbsent(t, base); 094 } 095 096 private OsmPrimitiveComparator() { 097 } 098}