001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.data.osm; 003 004import java.util.Arrays; 005import java.util.Collection; 006import java.util.Map; 007import java.util.Objects; 008 009/** 010 * Objects implement Tagged if they provide a map of key/value pairs. 011 * 012 * @since 2115 013 */ 014// FIXME: better naming? setTags(), getTags(), getKeys() instead of keySet() ? 015// 016public interface Tagged { 017 018 /** 019 * The maximum tag length allowed by OSM API 020 * @since 13414 021 */ 022 int MAX_TAG_LENGTH = 255; 023 024 /** 025 * Sets the map of key/value pairs 026 * 027 * @param keys the map of key value pairs. If null, reset to the empty map. 028 */ 029 void setKeys(Map<String, String> keys); 030 031 /** 032 * Replies the map of key/value pairs. Never null, but may be the empty map. 033 * 034 * @return the map of key/value pairs 035 */ 036 Map<String, String> getKeys(); 037 038 /** 039 * Calls the visitor for every key/value pair. 040 * 041 * @param visitor The visitor to call. 042 * @see #getKeys() 043 * @since 13668 044 */ 045 default void visitKeys(KeyValueVisitor visitor) { 046 getKeys().forEach((k, v) -> visitor.visitKeyValue(this, k, v)); 047 } 048 049 /** 050 * Sets a key/value pairs 051 * 052 * @param key the key 053 * @param value the value. If null, removes the key/value pair. 054 */ 055 void put(String key, String value); 056 057 /** 058 * Sets a key/value pairs 059 * 060 * @param tag The tag to set. 061 * @since 10736 062 */ 063 default void put(Tag tag) { 064 put(tag.getKey(), tag.getValue()); 065 } 066 067 /** 068 * Replies the value of the given key; null, if there is no value for this key 069 * 070 * @param key the key 071 * @return the value 072 */ 073 String get(String key); 074 075 /** 076 * Removes a given key/value pair 077 * 078 * @param key the key 079 */ 080 void remove(String key); 081 082 /** 083 * Replies true, if there is at least one key/value pair; false, otherwise 084 * 085 * @return true, if there is at least one key/value pair; false, otherwise 086 */ 087 boolean hasKeys(); 088 089 /** 090 * Replies true if there is a tag with key <code>key</code>. 091 * The value could however be empty. See {@link #hasTag(String)} to check for non-empty tags. 092 * 093 * @param key the key 094 * @return true, if there is a tag with key <code>key</code> 095 * @see #hasTag(String) 096 * @since 11608 097 */ 098 default boolean hasKey(String key) { 099 return get(key) != null; 100 } 101 102 /** 103 * Replies true if there is a non-empty tag with key <code>key</code>. 104 * 105 * @param key the key 106 * @return true, if there is a non-empty tag with key <code>key</code> 107 * @see Tagged#hasKey(String) 108 * @since 13430 109 */ 110 default boolean hasTag(String key) { 111 String v = get(key); 112 return v != null && !v.isEmpty(); 113 } 114 115 /** 116 * Tests whether this primitive contains a tag consisting of {@code key} and {@code value}. 117 * @param key the key forming the tag. 118 * @param value value forming the tag. 119 * @return true if primitive contains a tag consisting of {@code key} and {@code value}. 120 * @since 13668 121 */ 122 default boolean hasTag(String key, String value) { 123 return Objects.equals(value, get(key)); 124 } 125 126 /** 127 * Tests whether this primitive contains a tag consisting of {@code key} and any of {@code values}. 128 * @param key the key forming the tag. 129 * @param values one or many values forming the tag. 130 * @return true if primitive contains a tag consisting of {@code key} and any of {@code values}. 131 * @since 13668 132 */ 133 default boolean hasTag(String key, String... values) { 134 return hasTag(key, Arrays.asList(values)); 135 } 136 137 /** 138 * Tests whether this primitive contains a tag consisting of {@code key} and any of {@code values}. 139 * @param key the key forming the tag. 140 * @param values one or many values forming the tag. 141 * @return true if primitive contains a tag consisting of {@code key} and any of {@code values}. 142 * @since 13668 143 */ 144 default boolean hasTag(String key, Collection<String> values) { 145 return values.contains(get(key)); 146 } 147 148 /** 149 * Tests whether this primitive contains a tag consisting of {@code key} and a value different from {@code value}. 150 * @param key the key forming the tag. 151 * @param value value not forming the tag. 152 * @return true if primitive contains a tag consisting of {@code key} and a value different from {@code value}. 153 * @since 13668 154 */ 155 default boolean hasTagDifferent(String key, String value) { 156 String v = get(key); 157 return v != null && !v.equals(value); 158 } 159 160 /** 161 * Tests whether this primitive contains a tag consisting of {@code key} and none of {@code values}. 162 * @param key the key forming the tag. 163 * @param values one or many values forming the tag. 164 * @return true if primitive contains a tag consisting of {@code key} and none of {@code values}. 165 * @since 13668 166 */ 167 default boolean hasTagDifferent(String key, String... values) { 168 return hasTagDifferent(key, Arrays.asList(values)); 169 } 170 171 /** 172 * Tests whether this primitive contains a tag consisting of {@code key} and none of {@code values}. 173 * @param key the key forming the tag. 174 * @param values one or many values forming the tag. 175 * @return true if primitive contains a tag consisting of {@code key} and none of {@code values}. 176 * @since 13668 177 */ 178 default boolean hasTagDifferent(String key, Collection<String> values) { 179 String v = get(key); 180 return v != null && !values.contains(v); 181 } 182 183 /** 184 * Replies the set of keys 185 * 186 * @return the set of keys 187 */ 188 Collection<String> keySet(); 189 190 /** 191 * Gets the number of keys 192 * @return The number of keys set for this tagged object. 193 * @since 13625 194 */ 195 int getNumKeys(); 196 197 /** 198 * Removes all tags 199 */ 200 void removeAll(); 201}