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