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}