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}