Ticket #18383: 18383.patch

File 18383.patch, 27.2 KB (added by taylor.smock, 5 years ago)

Create class for access tags

  • src/org/openstreetmap/josm/data/validation/tests/ConditionalKeys.java

     
    1616import org.openstreetmap.josm.data.validation.Severity;
    1717import org.openstreetmap.josm.data.validation.Test;
    1818import org.openstreetmap.josm.data.validation.TestError;
     19import org.openstreetmap.josm.tools.Access;
    1920import org.openstreetmap.josm.tools.LanguageInfo;
    2021import org.openstreetmap.josm.tools.Logging;
    2122import org.openstreetmap.josm.tools.SubclassFilteredCollection;
     
    3031    private static final Set<String> RESTRICTION_TYPES = new HashSet<>(Arrays.asList("oneway", "toll", "noexit", "maxspeed", "minspeed",
    3132            "maxstay", "maxweight", "maxaxleload", "maxheight", "maxwidth", "maxlength", "overtaking", "maxgcweight", "maxgcweightrating",
    3233            "fee", "restriction", "interval"));
    33     private static final Set<String> RESTRICTION_VALUES = new HashSet<>(Arrays.asList("yes", "official", "designated", "destination",
    34             "delivery", "customers", "permissive", "private", "agricultural", "forestry", "no"));
    35     private static final Set<String> TRANSPORT_MODES = new HashSet<>(Arrays.asList("access", "foot", "ski", "inline_skates", "ice_skates",
    36             "horse", "vehicle", "bicycle", "carriage", "trailer", "caravan", "motor_vehicle", "motorcycle", "moped", "mofa",
    37             "motorcar", "motorhome", "psv", "bus", "taxi", "tourist_bus", "goods", "hgv", "agricultural", "atv", "snowmobile",
    38             "hgv_articulated", "ski:nordic", "ski:alpine", "ski:telemark", "coach", "golf_cart"
    39             /*,"minibus","share_taxi","hov","car_sharing","emergency","hazmat","disabled"*/));
     34    private static final Set<String> RESTRICTION_VALUES = Access.getRestrictionValues();
     35    private static final Set<String> TRANSPORT_MODES = Access.getTransportModes();
    4036
    4137    private static final Pattern CONDITIONAL_PATTERN;
    4238    static {
  • src/org/openstreetmap/josm/tools/Access.java

     
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.tools;
     3
     4import java.util.ArrayList;
     5import java.util.Arrays;
     6import java.util.Collections;
     7import java.util.HashMap;
     8import java.util.HashSet;
     9import java.util.List;
     10import java.util.Map;
     11import java.util.Map.Entry;
     12import java.util.Objects;
     13import java.util.Set;
     14import java.util.stream.Collectors;
     15
     16/**
     17 * Access tag related utilities
     18 *
     19 * @see <a href="https://wiki.openstreetmap.org/wiki/Key:access">Key:access</a>
     20 *
     21 * @author Taylor Smock
     22 * @since xxx
     23 */
     24public class Access {
     25    /**
     26     * Holds access tags to avoid typos
     27     */
     28    public enum AccessTags {
     29        /**
     30         * @see <a href="https://wiki.openstreetmap.org/wiki/Key:access">Key:access</a>
     31         */
     32        ACCESS_KEY("access"),
     33
     34        // Access tag values
     35        /**
     36         * @see <a href=
     37         *      "https://wiki.openstreetmap.org/wiki/Tag:access%3Dyes">Tag:access%3Dyes</a>
     38         */
     39        YES("yes"),
     40        /**
     41         * @see <a href=
     42         *      "https://wiki.openstreetmap.org/wiki/Tag:access%3Dofficial">Tag:access%3Dofficial</a>
     43         */
     44        OFFICIAL("official"),
     45        /**
     46         * @see <a href=
     47         *      "https://wiki.openstreetmap.org/wiki/Tag:access%3Ddesignated">Tag:access%3Ddesignated</a>
     48         */
     49        DESIGNATED("designated"),
     50        /**
     51         * @see <a href=
     52         *      "https://wiki.openstreetmap.org/wiki/Tag:access%3Ddestination">Tag:access%3Ddestination</a>
     53         */
     54        DESTINATION("destination"),
     55        /**
     56         * @see <a href=
     57         *      "https://wiki.openstreetmap.org/wiki/Tag:access%3Ddelivery">Tag:access%3Ddelivery</a>
     58         */
     59        DELIVERY("delivery"),
     60        /**
     61         * @see <a href=
     62         *      "https://wiki.openstreetmap.org/wiki/Tag:access%3Dcustomers">Tag:access%3Dcustomers</a>
     63         */
     64        CUSTOMERS("customers"),
     65        /**
     66         * @see <a href=
     67         *      "https://wiki.openstreetmap.org/wiki/Tag:access%3Dpermissive">Tag:access%3Dpermissive</a>
     68         */
     69        PERMISSIVE("permissive"),
     70        /**
     71         * @see <a href=
     72         *      "https://wiki.openstreetmap.org/wiki/Tag:access%3Dagricultural">Tag:access%3Dagricultural</a>
     73         */
     74        AGRICULTURAL("agricultural"),
     75        /**
     76         * @see <a href=
     77         *      "https://wiki.openstreetmap.org/wiki/Tag:access%3Dforestry">Tag:access%3Dforestry</a>
     78         */
     79        FORESTRY("forestry"),
     80        /**
     81         * @see <a href=
     82         *      "https://wiki.openstreetmap.org/wiki/Tag:access%3Dprivate">Tag:access%3Dprivate</a>
     83         */
     84        PRIVATE("private"),
     85        /**
     86         * @see <a href=
     87         *      "https://wiki.openstreetmap.org/wiki/Tag:access%3Dno">Tag:access%3Dno</a>
     88         */
     89        NO("no"),
     90        /**
     91         * @see <a href=
     92         *      "https://wiki.openstreetmap.org/wiki/Tag:access%3Ddiscouraged">Tag:access%3Ddiscouraged</a>
     93         */
     94        DISCOURAGED("discouraged"),
     95        /**
     96         * @see <a href=
     97         *      "https://wiki.openstreetmap.org/wiki/Tag:access%3Duse_sidepath">Tag:access%3Duse_sidepath</a>
     98         */
     99        USE_SIDEPATH("use_sidepath"),
     100        /**
     101         * @see <a href=
     102         *      "https://wiki.openstreetmap.org/wiki/Tag:access%3Ddismount">Tag:access%3Ddismount</a>
     103         */
     104        DISMOUNT("dismount"),
     105        // Land
     106        /**
     107         * @see <a href=
     108         *      "https://wiki.openstreetmap.org/wiki/Key:vehicle">Key:vehicle</a>
     109         */
     110        VEHICLE("vehicle"),
     111        /**
     112         * @see <a href=
     113         *      "https://wiki.openstreetmap.org/wiki/Key:motor_vehicle">Key:motor_vehicle</a>
     114         */
     115        MOTOR_VEHICLE("motor_vehicle"),
     116        /**
     117         * @see <a href=
     118         *      "https://wiki.openstreetmap.org/wiki/Key:trailer">Key:trailer</a>
     119         */
     120        TRAILER("trailer"),
     121        /** @see <a href="https://wiki.openstreetmap.org/wiki/Key:foot">Key:foot</a> */
     122        FOOT("foot"),
     123        /** @see <a href="https://wiki.openstreetmap.org/wiki/Key:ski">Key:ski</a> */
     124        SKI("ski"),
     125        /**
     126         * @see <a href=
     127         *      "https://wiki.openstreetmap.org/wiki/Key:inline_skates">Key:inline_skates</a>
     128         */
     129        INLINE_SKATES("inline_skates"),
     130        /**
     131         * @see <a href=
     132         *      "https://wiki.openstreetmap.org/wiki/Key:ice_skates">Key:ice_skates</a>
     133         */
     134        ICE_SKATES("ice_skates"),
     135        /**
     136         * @see <a href="https://wiki.openstreetmap.org/wiki/Key:horse">Key:horse</a>
     137         */
     138        HORSE("horse"),
     139        /**
     140         * @see <a href=
     141         *      "https://wiki.openstreetmap.org/wiki/Key:bicycle">Key:bicycle</a>
     142         */
     143        BICYCLE("bicycle"),
     144        /**
     145         * @see <a href=
     146         *      "https://wiki.openstreetmap.org/wiki/Key:carriage">Key:carriage</a>
     147         */
     148        CARRIAGE("carriage"),
     149        /**
     150         * @see <a href=
     151         *      "https://wiki.openstreetmap.org/wiki/Key:caravan">Key:caravan</a>
     152         */
     153        CARAVAN("caravan"),
     154        /**
     155         * @see <a href=
     156         *      "https://wiki.openstreetmap.org/wiki/Key:motorcycle">Key:motorcycle</a>
     157         */
     158        MOTORCYCLE("motorcycle"),
     159        /**
     160         * @see <a href="https://wiki.openstreetmap.org/wiki/Key:moped">Key:moped</a>
     161         */
     162        MOPED("moped"),
     163        /** @see <a href="https://wiki.openstreetmap.org/wiki/Key:mofa">Key:mofa</a> */
     164        MOFA("mofa"),
     165        /**
     166         * @see <a href=
     167         *      "https://wiki.openstreetmap.org/wiki/Key:motorcar">Key:motorcar</a>
     168         */
     169        MOTORCAR("motorcar"),
     170        /**
     171         * @see <a href=
     172         *      "https://wiki.openstreetmap.org/wiki/Key:motorhome">Key:motorhome</a>
     173         */
     174        MOTORHOME("motorhome"),
     175        /** @see <a href="https://wiki.openstreetmap.org/wiki/Key:psv">Key:psv</a> */
     176        PSV("psv"),
     177        /** @see <a href="https://wiki.openstreetmap.org/wiki/Key:bus">Key:bus</a> */
     178        BUS("bus"),
     179        /** @see <a href="https://wiki.openstreetmap.org/wiki/Key:taxi">Key:taxi</a> */
     180        TAXI("taxi"),
     181        /**
     182         * @see <a href=
     183         *      "https://wiki.openstreetmap.org/wiki/Key:tourist_bus">Key:tourist_bus</a>
     184         */
     185        TOURIST_BUS("tourist_bus"),
     186        /**
     187         * @see <a href="https://wiki.openstreetmap.org/wiki/Key:goods">Key:goods</a>
     188         */
     189        GOODS("goods"),
     190        /** @see <a href="https://wiki.openstreetmap.org/wiki/Key:hgv">Key:hgv</a> */
     191        HGV("hgv"),
     192        /** @see <a href="https://wiki.openstreetmap.org/wiki/Key:atv">Key:atv</a> */
     193        ATV("atv"),
     194        /**
     195         * @see <a href=
     196         *      "https://wiki.openstreetmap.org/wiki/Key:snowmobile">Key:snowmobile</a>
     197         */
     198        SNOWMOBILE("snowmobile"),
     199        /**
     200         * @see <a href=
     201         *      "https://wiki.openstreetmap.org/wiki/Key:hgv_articulated">Key:hgv_articulated</a>
     202         */
     203        HGV_ARTICULATED("hgv_articulated"),
     204        /** @see <a href="https://wiki.openstreetmap.org/wiki/Key:ski">Key:ski</a> */
     205        SKI_NORDIC("ski:nordic"),
     206        /** @see <a href="https://wiki.openstreetmap.org/wiki/Key:ski">Key:ski</a> */
     207        SKI_ALPINE("ski:alpine"),
     208        /** @see <a href="https://wiki.openstreetmap.org/wiki/Key:ski">Key:ski</a> */
     209        SKI_TELEMARK("ski:telemark"),
     210        /**
     211         * @see <a href="https://wiki.openstreetmap.org/wiki/Key:coach">Key:coach</a>
     212         */
     213        COACH("coach"),
     214        /**
     215         * @see <a href=
     216         *      "https://wiki.openstreetmap.org/wiki/Key:golf_cart">Key:golf_cart</a>
     217         */
     218        GOLF_CART("golf_cart"),
     219        /**
     220         * @see <a href=
     221         *      "https://wiki.openstreetmap.org/wiki/Key:minibus">Key:minibus</a>
     222         */
     223        MINIBUS("minibus"),
     224        /**
     225         * @see <a href=
     226         *      "https://wiki.openstreetmap.org/wiki/Key:share_taxi">Key:share_taxi</a>
     227         */
     228        SHARE_TAXI("share_taxi"),
     229        /** @see <a href="https://wiki.openstreetmap.org/wiki/Key:hov">Key:hov</a> */
     230        HOV("hov"),
     231        /**
     232         * @see <a href=
     233         *      "https://wiki.openstreetmap.org/wiki/Key:car_sharing">Key:car_sharing</a>
     234         */
     235        CAR_SHARING("car_sharing"),
     236        /**
     237         * Routers should default to {@code yes}, regardless of higher access rules,
     238         * assuming it is navigatible by vehicle
     239         *
     240         * @see <a href=
     241         *      "https://wiki.openstreetmap.org/wiki/Key:emergency">Key:emergency</a>
     242         */
     243        EMERGENCY("emergency"),
     244        /**
     245         * @see <a href="https://wiki.openstreetmap.org/wiki/Key:hazmat">Key:hazmat</a>
     246         */
     247        HAZMAT("hazmat"),
     248        /**
     249         * @see <a href=
     250         *      "https://wiki.openstreetmap.org/wiki/Key:disabled">Key:disabled</a>
     251         */
     252        DISABLED("disabled"),
     253
     254        // Water
     255        /**
     256         * @see <a href=
     257         *      "https://wiki.openstreetmap.org/wiki/Key:swimming">Key:swimming</a>
     258         */
     259        SWIMMING("swimming"),
     260        /** @see <a href="https://wiki.openstreetmap.org/wiki/Key:boat">Key:boat</a> */
     261        BOAT("boat"),
     262        /**
     263         * @see <a href=
     264         *      "https://wiki.openstreetmap.org/wiki/Key:fishing_vessel">Key:fishing_vessel</a>
     265         */
     266        FISHING_VESSEL("fishing_vessel"),
     267        /** @see <a href="https://wiki.openstreetmap.org/wiki/Key:ship">Key:ship</a> */
     268        SHIP("ship"),
     269        /**
     270         * @see <a href=
     271         *      "https://wiki.openstreetmap.org/wiki/Key:motorboat">Key:motorboat</a>
     272         */
     273        MOTORBOAT("motorboat"),
     274        /**
     275         * @see <a href=
     276         *      "https://wiki.openstreetmap.org/wiki/Key:sailboat">Key:sailboat</a>
     277         */
     278        SAILBOAT("sailboat"),
     279        /**
     280         * @see <a href="https://wiki.openstreetmap.org/wiki/Key:canoe">Key:canoe</a>
     281         */
     282        CANOE("canoe"),
     283        /**
     284         * @see <a href=
     285         *      "https://wiki.openstreetmap.org/wiki/Key:passenger">Key:passenger</a>
     286         */
     287        PASSENGER("passenger"),
     288        /**
     289         * @see <a href="https://wiki.openstreetmap.org/wiki/Key:cargo">Key:cargo</a>
     290         */
     291        CARGO("cargo"),
     292        /** @see <a href="https://wiki.openstreetmap.org/wiki/Key:isps">Key:isps</a> */
     293        ISPS("isps"),
     294        /** @see <a href="https://wiki.openstreetmap.org/wiki/Key:bulk">Key:bulk</a> */
     295        BULK("bulk"),
     296        /**
     297         * @see <a href="https://wiki.openstreetmap.org/wiki/Key:tanker">Key:tanker</a>
     298         */
     299        TANKER("tanker"),
     300        /**
     301         * @see <a href=
     302         *      "https://wiki.openstreetmap.org/wiki/Key:container">Key:container</a>
     303         */
     304        CONTAINER("container"),
     305        /** @see <a href="https://wiki.openstreetmap.org/wiki/Key:imdg">Key:imdg</a> */
     306        IMDG("imdg"),
     307        /**
     308         * @see <a href="https://wiki.openstreetmap.org/wiki/Key:tanker">Key:tanker</a>
     309         */
     310        TANKER_GAS("tanker:gas"),
     311        /**
     312         * @see <a href="https://wiki.openstreetmap.org/wiki/Key:tanker">Key:tanker</a>
     313         */
     314        TANKER_OIL("tanker:oil"),
     315        /**
     316         * @see <a href="https://wiki.openstreetmap.org/wiki/Key:tanker">Key:tanker</a>
     317         */
     318        TANKER_CHEMICAL("tanker:chemical"),
     319        /**
     320         * @see <a href="https://wiki.openstreetmap.org/wiki/Key:tanker">Key:tanker</a>
     321         */
     322        TANKER_SINGLEHULL("tanker:singlehull"),
     323
     324        // Trains
     325        /**
     326         * @see <a href="https://wiki.openstreetmap.org/wiki/Key:train">Key:train</a>
     327         */
     328        TRAIN("train");
     329
     330        private String key;
     331
     332        AccessTags(String key) {
     333            this.key = key;
     334        }
     335
     336        /**
     337         * @return The key for the enum
     338         */
     339        public String getKey() {
     340            return key;
     341        }
     342    }
     343    /**
     344     * The key for children modes for the map, see {@link Access#getAccessMethods}
     345     */
     346    public static final String CHILDREN = "children";
     347    /** The key for parent modes for the map, see {@link Access#getAccessMethods} */
     348    public static final String PARENT = "parent";
     349    /** This set has keys that indicate that access is possible */
     350    private static final Set<String> POSITIVE_ACCESS = new HashSet<>(Arrays.asList(AccessTags.YES, AccessTags.OFFICIAL,
     351            AccessTags.DESIGNATED, AccessTags.DESTINATION, AccessTags.DELIVERY, AccessTags.CUSTOMERS,
     352            AccessTags.PERMISSIVE, AccessTags.AGRICULTURAL, AccessTags.FORESTRY).stream().map(AccessTags::getKey)
     353            .collect(Collectors.toSet()));
     354    /** This set has all basic restriction values (yes/no/permissive/private/...) */
     355    private static final Set<String> RESTRICTION_VALUES = new HashSet<>(
     356            Arrays.asList(AccessTags.PRIVATE, AccessTags.NO).stream().map(AccessTags::getKey)
     357                    .collect(Collectors.toSet()));
     358    /** This set has transport modes (access/foot/ski/motor_vehicle/vehicle/...) */
     359    private static final Set<String> TRANSPORT_MODES = new HashSet<>(
     360            Arrays.asList(AccessTags.ACCESS_KEY, AccessTags.FOOT, AccessTags.SKI, AccessTags.INLINE_SKATES,
     361                    AccessTags.ICE_SKATES, AccessTags.HORSE, AccessTags.VEHICLE, AccessTags.BICYCLE,
     362                    AccessTags.CARRIAGE, AccessTags.TRAILER, AccessTags.CARAVAN, AccessTags.MOTOR_VEHICLE,
     363                    AccessTags.MOTORCYCLE, AccessTags.MOPED, AccessTags.MOFA, AccessTags.MOTORCAR, AccessTags.MOTORHOME,
     364                    AccessTags.PSV, AccessTags.BUS, AccessTags.TAXI, AccessTags.TOURIST_BUS, AccessTags.GOODS,
     365                    AccessTags.HGV, AccessTags.AGRICULTURAL, AccessTags.ATV,
     366                    AccessTags.SNOWMOBILE, AccessTags.HGV_ARTICULATED, AccessTags.SKI_NORDIC, AccessTags.SKI_ALPINE,
     367                    AccessTags.SKI_TELEMARK, AccessTags.COACH, AccessTags.GOLF_CART
     368            /*
     369             * ,"minibus","share_taxi","hov","car_sharing","emergency","hazmat","disabled"
     370             */).stream().map(AccessTags::getKey).collect(Collectors.toSet()));
     371
     372    /** Map<Access Method, Map<Parent/Child, List<Access Methods>> */
     373    private static final Map<String, Map<String, List<String>>> accessMethods = new HashMap<>();
     374    static {
     375        RESTRICTION_VALUES.addAll(POSITIVE_ACCESS);
     376        defaultInheritance();
     377    }
     378
     379    private Access() {
     380        // Hide the constructor
     381    }
     382
     383    /**
     384     * Create the default access inheritance, as defined at
     385     * {@link "https://wiki.openstreetmap.org/wiki/Key:access#Transport_mode_restrictions"}
     386     */
     387    private static void defaultInheritance() {
     388        addMode(null, AccessTags.ACCESS_KEY);
     389
     390        // Land
     391        addModes(AccessTags.ACCESS_KEY, AccessTags.FOOT, AccessTags.SKI, AccessTags.INLINE_SKATES,
     392                AccessTags.ICE_SKATES, AccessTags.HORSE, AccessTags.VEHICLE);
     393        addModes(AccessTags.SKI, AccessTags.SKI_NORDIC, AccessTags.SKI_ALPINE, AccessTags.SKI_TELEMARK);
     394        addModes(AccessTags.VEHICLE, AccessTags.BICYCLE, AccessTags.CARRIAGE, AccessTags.TRAILER,
     395                AccessTags.MOTOR_VEHICLE);
     396        addModes(AccessTags.TRAILER, AccessTags.CARAVAN);
     397        addModes(AccessTags.MOTOR_VEHICLE, AccessTags.MOTORCYCLE, AccessTags.MOPED, AccessTags.MOFA,
     398                AccessTags.MOTORCAR, AccessTags.MOTORHOME, AccessTags.TOURIST_BUS, AccessTags.COACH, AccessTags.GOODS,
     399                AccessTags.HGV, AccessTags.AGRICULTURAL, AccessTags.GOLF_CART, AccessTags.ATV, AccessTags.SNOWMOBILE,
     400                AccessTags.PSV, AccessTags.HOV, AccessTags.CAR_SHARING, AccessTags.EMERGENCY, AccessTags.HAZMAT,
     401                AccessTags.DISABLED);
     402        addMode(AccessTags.HGV, AccessTags.HGV_ARTICULATED);
     403        addModes(AccessTags.PSV, AccessTags.BUS, AccessTags.MINIBUS, AccessTags.SHARE_TAXI, AccessTags.TAXI);
     404
     405        // Water
     406        addModes(AccessTags.ACCESS_KEY, AccessTags.SWIMMING, AccessTags.BOAT, AccessTags.FISHING_VESSEL,
     407                AccessTags.SHIP);
     408        addModes(AccessTags.BOAT, AccessTags.MOTORBOAT, AccessTags.SAILBOAT, AccessTags.CANOE);
     409        addModes(AccessTags.SHIP, AccessTags.PASSENGER, AccessTags.CARGO, AccessTags.ISPS);
     410        addModes(AccessTags.CARGO, AccessTags.BULK, AccessTags.TANKER, AccessTags.CONTAINER, AccessTags.IMDG);
     411        addModes(AccessTags.TANKER, AccessTags.TANKER_GAS, AccessTags.TANKER_OIL, AccessTags.TANKER_CHEMICAL,
     412                AccessTags.TANKER_SINGLEHULL);
     413
     414        // Rail
     415        addModes(AccessTags.ACCESS_KEY, AccessTags.TRAIN);
     416    }
     417
     418    /**
     419     * Add multiple modes with a common parent
     420     *
     421     * @param parent The parent of all the modes
     422     * @param modes  The modes to add
     423     */
     424    public static void addModes(AccessTags parent, AccessTags... modes) {
     425        for (AccessTags mode : modes) {
     426            addMode(parent, mode);
     427        }
     428    }
     429
     430    /**
     431     * Add modes to a list, modifying parents as needed
     432     *
     433     * @param mode   The mode to be added
     434     * @param parent The parent of the mode
     435     */
     436    public static void addMode(AccessTags parent, AccessTags mode) {
     437        Objects.requireNonNull(mode, "Mode must not be null");
     438        if (parent != null) {
     439            Map<String, List<String>> parentMap = accessMethods.getOrDefault(parent.getKey(), new HashMap<>());
     440            accessMethods.putIfAbsent(parent.getKey(), parentMap);
     441            List<String> parentChildren = parentMap.getOrDefault(CHILDREN, new ArrayList<>());
     442            if (!parentChildren.contains(mode.getKey()))
     443                parentChildren.add(mode.getKey());
     444            parentMap.putIfAbsent(CHILDREN, parentChildren);
     445        }
     446        Map<String, List<String>> modeMap = accessMethods.getOrDefault(mode.getKey(), new HashMap<>());
     447        accessMethods.putIfAbsent(mode.getKey(), modeMap);
     448        List<String> modeParent = modeMap.getOrDefault(PARENT,
     449                Collections.singletonList(parent == null ? null : parent.getKey()));
     450        modeMap.putIfAbsent(PARENT, modeParent);
     451    }
     452
     453    /**
     454     * Expand access modes to cover the children of that access mode (currently only
     455     * supports the default hierarchy)
     456     *
     457     * @param mode   The transport mode
     458     * @param access The access value (the children transport modes inherit this
     459     *               value)
     460     * @return A map of the mode and its children (does not include parents)
     461     */
     462    public static Map<String, String> expandAccessMode(String mode, String access) {
     463        Map<String, String> accessModes = new HashMap<>();
     464        accessModes.put(mode, access);
     465        if (accessMethods.containsKey(mode)) {
     466            for (String childrenMode : accessMethods.getOrDefault(mode, Collections.emptyMap()).getOrDefault(CHILDREN,
     467                    Collections.emptyList())) {
     468                accessModes.putAll(expandAccessMode(childrenMode, access));
     469            }
     470        }
     471        return accessModes;
     472    }
     473
     474    /**
     475     * Merge two access maps (more specific wins)
     476     *
     477     * @param map1 A map with access values (see {@link Access#expandAccessMode})
     478     * @param map2 A map with access values (see {@link Access#expandAccessMode})
     479     * @return The merged map
     480     */
     481    public static Map<String, String> mergeMaps(Map<String, String> map1, Map<String, String> map2) {
     482        Map<String, String> merged;
     483        if (map1.keySet().containsAll(map2.keySet())) {
     484            merged = new HashMap<>(map1);
     485            merged.putAll(map2);
     486        } else { // if they don't overlap or if map2 contains all of map1
     487            merged = new HashMap<>(map2);
     488            merged.putAll(map1);
     489        }
     490        return merged;
     491    }
     492
     493    /**
     494     * Get the set of values that can generally be considered to be accessible
     495     *
     496     * @return A set of values that can be used for routing purposes (unmodifiable)
     497     */
     498    public static Set<String> getPositiveAccessValues() {
     499        return Collections.unmodifiableSet(POSITIVE_ACCESS);
     500    }
     501
     502    /**
     503     * Get the valid restriction values ({@code unknown} is not included). See
     504     *
     505     * @return Valid values for restrictions (unmodifiable)
     506     * @see <a href=
     507     *      "https://wiki.openstreetmap.org/wiki/Key:access#List_of_possible_values">Key:access#List_of_possible_values</a>
     508     */
     509    public static Set<String> getRestrictionValues() {
     510        return Collections.unmodifiableSet(RESTRICTION_VALUES);
     511    }
     512
     513    /**
     514     * Get the valid transport modes. See
     515     *
     516     * @return Value transport modes (unmodifiable)
     517     * @see <a href=
     518     *      "https://wiki.openstreetmap.org/wiki/Key:access#Transport_mode_restrictions">Key:access#Transport_mode_restrictions</a>
     519     */
     520    public static Set<String> getTransportModes() {
     521        return Collections.unmodifiableSet(TRANSPORT_MODES);
     522    }
     523
     524    /**
     525     * Get the access method hierarchy.
     526     *
     527     * @return The hierarchy for access modes (unmodifiable)
     528     * @see <a href=
     529     *      "https://wiki.openstreetmap.org/wiki/Key:access#Transport_mode_restrictions">Key:access#Transport_mode_restrictions</a>
     530     */
     531    public static Map<String, Map<String, List<String>>> getAccessMethods() {
     532        Map<String, Map<String, List<String>>> map = new HashMap<>();
     533        for (Entry<String, Map<String, List<String>>> entry : map.entrySet()) {
     534            Map<String, List<String>> tMap = new HashMap<>();
     535            entry.getValue().forEach((key, list) -> tMap.put(key, Collections.unmodifiableList(list)));
     536            map.put(entry.getKey(), Collections.unmodifiableMap(tMap));
     537        }
     538        return Collections.unmodifiableMap(map);
     539    }
     540}
  • test/unit/org/openstreetmap/josm/tools/AccessTest.java

     
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.tools;
     3
     4import static org.junit.Assert.assertEquals;
     5
     6import java.util.Map;
     7
     8import org.junit.Test;
     9
     10/**
     11 * Test class for {@link Access}
     12 *
     13 * @author Taylor Smock
     14 * @since xxx
     15 */
     16public class AccessTest {
     17
     18    /**
     19     * Test that access tags inherit the expected values
     20     */
     21    @Test
     22    public void testInheritance() {
     23        assertEquals(Access.AccessTags.YES.getKey(),
     24                Access.expandAccessMode(Access.AccessTags.VEHICLE.getKey(), Access.AccessTags.YES.getKey())
     25                        .getOrDefault(Access.AccessTags.MOTOR_VEHICLE.getKey(), Access.AccessTags.NO.getKey()));
     26        assertEquals(Access.AccessTags.YES.getKey(),
     27                Access.expandAccessMode(Access.AccessTags.VEHICLE.getKey(), Access.AccessTags.YES.getKey())
     28                        .getOrDefault(Access.AccessTags.HGV.getKey(), Access.AccessTags.NO.getKey()));
     29        assertEquals(Access.AccessTags.YES.getKey(),
     30                Access.expandAccessMode(Access.AccessTags.VEHICLE.getKey(), Access.AccessTags.YES.getKey())
     31                        .getOrDefault(Access.AccessTags.HGV_ARTICULATED.getKey(), Access.AccessTags.NO.getKey()));
     32    }
     33
     34    /**
     35     * Test that access maps get merged properly ({@link Access#mergeMaps})
     36     */
     37    @Test
     38    public void testMergeMaps() {
     39        Map<String, String> mergedMaps = Access.mergeMaps(
     40                Access.expandAccessMode(Access.AccessTags.VEHICLE.getKey(), Access.AccessTags.YES.getKey()),
     41                Access.expandAccessMode(Access.AccessTags.HGV.getKey(), Access.AccessTags.DESIGNATED.getKey()));
     42        assertEquals(Access.AccessTags.YES.getKey(),
     43                mergedMaps.getOrDefault(Access.AccessTags.MOTORCAR.getKey(), Access.AccessTags.NO.getKey()));
     44        assertEquals(Access.AccessTags.DESIGNATED.getKey(),
     45                mergedMaps.getOrDefault(Access.AccessTags.HGV.getKey(), Access.AccessTags.NO.getKey()));
     46        assertEquals(Access.AccessTags.DESIGNATED.getKey(),
     47                mergedMaps.getOrDefault(Access.AccessTags.HGV_ARTICULATED.getKey(), Access.AccessTags.NO.getKey()));
     48
     49        mergedMaps = Access.mergeMaps(
     50                Access.expandAccessMode(Access.AccessTags.HGV.getKey(), Access.AccessTags.DESIGNATED.getKey()),
     51                Access.expandAccessMode(Access.AccessTags.VEHICLE.getKey(), Access.AccessTags.YES.getKey()));
     52        assertEquals(Access.AccessTags.YES.getKey(),
     53                mergedMaps.getOrDefault(Access.AccessTags.MOTORCAR.getKey(), Access.AccessTags.NO.getKey()));
     54        assertEquals(Access.AccessTags.DESIGNATED.getKey(),
     55                mergedMaps.getOrDefault(Access.AccessTags.HGV.getKey(), Access.AccessTags.NO.getKey()));
     56        assertEquals(Access.AccessTags.DESIGNATED.getKey(),
     57                mergedMaps.getOrDefault(Access.AccessTags.HGV_ARTICULATED.getKey(), Access.AccessTags.NO.getKey()));
     58    }
     59}