001package com.nimbusds.langtag; 002 003 004import java.util.*; 005 006 007/** 008 * Language tag utilities. 009 */ 010public final class LangTagUtils { 011 012 013 /** 014 * Strips the language tag, if any is found, from the specified string. 015 * This method is {@code null} safe. 016 * 017 * <p>Example: 018 * 019 * <pre> 020 * "name#bg-BG" => "name" 021 * "name" => "name" 022 * </pre> 023 * 024 * @param s The string. May contain a language tag. May be 025 * {@code null}. 026 * 027 * @return The string with no language tag. 028 */ 029 public static String strip(final String s) { 030 031 if (s == null) 032 return null; 033 034 final int pos = s.indexOf('#'); 035 036 if (pos < 0) 037 return s; 038 039 return s.substring(0, pos); 040 } 041 042 043 /** 044 * Strips the language tags, if any are found, from the specified 045 * string set. This method is {@code null} safe. 046 * 047 * <p>Example: 048 * 049 * <pre> 050 * "name#bg-BG" => "name" 051 * "name" => "name" 052 * </pre> 053 * 054 * @param set The string set. May contain strings with language tags. 055 * May be {@code null}. 056 * 057 * @return The string set with no language tags. 058 */ 059 public static Set<String> strip(final Set<String> set) { 060 061 if (set == null) 062 return null; 063 064 Set<String> out = new HashSet<String>(); 065 066 for (String s: set) 067 out.add(strip(s)); 068 069 return out; 070 } 071 072 073 /** 074 * Strips the language tags, if any are found, from the specified 075 * string list. This method is {@code null} safe. 076 * 077 * <p>Example: 078 * 079 * <pre> 080 * "name#bg-BG" => "name" 081 * "name" => "name" 082 * </pre> 083 * 084 * @param list The string list. May contain strings with language tags. 085 * May be {@code null}. 086 * 087 * @return The string list with no language tags. 088 */ 089 public static List<String> strip(final List<String> list) { 090 091 if (list == null) 092 return null; 093 094 List<String> out = new ArrayList<String>(list.size()); 095 096 for (String s: list) 097 out.add(strip(s)); 098 099 return out; 100 } 101 102 103 /** 104 * Extracts the language tag, if any is found, from the specified 105 * string. 106 * 107 * <p>Example: 108 * 109 * <pre> 110 * "name#bg-BG" => "bg-BG" 111 * "name#" => null 112 * "name" => null 113 * </pre> 114 * 115 * @param s The string. May contain a language tag. May be 116 * {@code null}. 117 * 118 * @return The extracted language tag, {@code null} if not found. 119 * 120 * @throws LangTagException If the language tag is invalid. 121 */ 122 public static LangTag extract(final String s) 123 throws LangTagException { 124 125 if (s == null) 126 return null; 127 128 final int pos = s.indexOf('#'); 129 130 if (pos < 0 || s.length() < pos + 1) 131 return null; 132 133 return LangTag.parse(s.substring(pos + 1)); 134 } 135 136 137 /** 138 * Finds all language-tagged entries with the specified base name. 139 * Entries with invalid language tags will be skipped. 140 * 141 * <p>Example: 142 * 143 * <p>Map to search for base name "month": 144 * 145 * <pre> 146 * "month" => "January" 147 * "month#de" => "Januar" 148 * "month#fr" => "janvier" 149 * "month#pt" => "janeiro" 150 * </pre> 151 * 152 * <p>Result: 153 * 154 * <pre> 155 * null => "January" 156 * "de" => "Januar" 157 * "fr" => "janvier" 158 * "pt" => "janeiro" 159 * </pre> 160 * 161 * @param baseName The base name to look for (without a language tag) 162 * in the map keys. Must not be {@code null}. 163 * @param map The map to search. Must not be {@code null}. 164 * 165 * @return A map of all language-tagged entries with the specified 166 * base name. A {@code null} keyed entry will indicate no 167 * language tag (base name only). 168 */ 169 public static <T> Map<LangTag,T> find(final String baseName, final Map<String,T> map) { 170 171 Map<LangTag,T> result = new HashMap<LangTag,T>(); 172 173 // Walk through each map entry, checking for entry keys that 174 // start with "baseName" 175 for (Map.Entry<String,T> entry: map.entrySet()) { 176 177 T value; 178 179 try { 180 value = entry.getValue(); 181 182 } catch (ClassCastException e) { 183 184 continue; // skip 185 } 186 187 if (entry.getKey().equals(baseName)) { 188 189 // Claim name matches, no tag 190 result.put(null, value); 191 } 192 else if (entry.getKey().startsWith(baseName + '#')) { 193 194 // Claim name matches, has tag 195 String[] parts = entry.getKey().split("#", 2); 196 197 LangTag langTag = null; 198 199 if (parts.length == 2) { 200 201 try { 202 langTag = LangTag.parse(parts[1]); 203 204 } catch (LangTagException e) { 205 206 // ignore 207 } 208 } 209 210 result.put(langTag, value); 211 } 212 } 213 214 return result; 215 } 216 217 218 /** 219 * Returns a string list representation of the specified language tags 220 * collection. 221 * 222 * @param langTags The language tags list. May be {@code null}. 223 * 224 * @return The string list, or {@code null} if the original list is 225 * {@code null}. 226 */ 227 public static List<String> toStringList(final Collection<LangTag> langTags) { 228 229 if (langTags == null) 230 return null; 231 232 List<String> out = new ArrayList<String>(langTags.size()); 233 234 for (LangTag lt: langTags) { 235 out.add(lt.toString()); 236 } 237 238 return out; 239 } 240 241 242 /** 243 * Returns a string array representation of the specified language tags 244 * collection. 245 * 246 * @param langTags The language tags list. May be {@code null}. 247 * 248 * @return The string list, or {@code null} if the original list is 249 * {@code null}. 250 */ 251 public static String[] toStringArray(final Collection<LangTag> langTags) { 252 253 if (langTags == null) 254 return null; 255 256 String[] out = new String[langTags.size()]; 257 258 int i=0; 259 260 for (LangTag lt: langTags) { 261 out[i++] = lt.toString(); 262 } 263 264 return out; 265 } 266 267 268 /** 269 * Parses a language tag list from the specified string collection. 270 * 271 * @param collection The string collection. May be {@code null}. 272 * 273 * @return The language tag list, or {@code null} if the parsed string 274 * collection is null. 275 * 276 * @throws LangTagException If parsing failed. 277 */ 278 public static List<LangTag> parseLangTagList(final Collection<String> collection) 279 throws LangTagException { 280 281 if (collection == null) 282 return null; 283 284 List<LangTag> out = new ArrayList<LangTag>(collection.size()); 285 286 for (String s: collection) { 287 out.add(LangTag.parse(s)); 288 } 289 290 return out; 291 } 292 293 294 /** 295 * Parses a language tag list from the specified string values. 296 * 297 * @param values The string values. May be {@code null}. 298 * 299 * @return The language tag list, or {@code null} if the parsed string 300 * array is null. 301 * 302 * @throws LangTagException If parsing failed. 303 */ 304 public static List<LangTag> parseLangTagList(final String ... values) 305 throws LangTagException { 306 307 if (values == null) 308 return null; 309 310 List<LangTag> out = new ArrayList<LangTag>(values.length); 311 312 for (String s: values) { 313 out.add(LangTag.parse(s)); 314 } 315 316 return out; 317 } 318 319 320 /** 321 * Parses a language tag array from the specified string values. 322 * 323 * @param values The string values. May be {@code null}. 324 * 325 * @return The language tag array, or {@code null} if the parsed string 326 * array is null. 327 * 328 * @throws LangTagException If parsing failed. 329 */ 330 public static LangTag[] parseLangTagArray(final String ... values) 331 throws LangTagException { 332 333 if (values == null) 334 return null; 335 336 LangTag[] out = new LangTag[values.length]; 337 338 for (int i=0; i < values.length; i++) { 339 out[i] = LangTag.parse(values[i]); 340 } 341 342 return out; 343 } 344 345 346 /** 347 * Prevents public instantiation. 348 */ 349 private LangTagUtils() { } 350}