1/* GENERATED SOURCE. DO NOT MODIFY. */
2// © 2017 and later: Unicode, Inc. and others.
3// License & terms of use: http://www.unicode.org/copyright.html#License
4package android.icu.impl.locale;
5
6import java.io.BufferedReader;
7import java.io.File;
8import java.io.InputStream;
9import java.io.InputStreamReader;
10import java.net.URL;
11import java.nio.charset.Charset;
12import java.util.Arrays;
13import java.util.Collection;
14import java.util.Collections;
15import java.util.HashMap;
16import java.util.HashSet;
17import java.util.Iterator;
18import java.util.LinkedHashMap;
19import java.util.LinkedHashSet;
20import java.util.List;
21import java.util.Map;
22import java.util.Map.Entry;
23import java.util.Set;
24import java.util.TreeMap;
25import java.util.TreeSet;
26import java.util.regex.Matcher;
27import java.util.regex.Pattern;
28
29import android.icu.util.ICUException;
30import android.icu.util.ICUUncheckedIOException;
31
32/**
33 * Stub class to make migration easier until we get either Guava or a higher level of Java.
34 * @hide Only a subset of ICU is exposed in Android
35 */
36public class XCldrStub {
37
38    public static class Multimap<K, V> {
39        private final Map<K,Set<V>> map;
40        private final Class<Set<V>> setClass;
41
42        @SuppressWarnings("unchecked")
43        private Multimap(Map<K,Set<V>> map, Class<?> setClass) {
44            this.map = map;
45            this.setClass = (Class<Set<V>>) (setClass != null
46                    ? setClass
47                            : HashSet.class);
48        }
49        public Multimap<K, V> putAll(K key, V... values) {
50            if (values.length != 0) {
51                createSetIfMissing(key).addAll(Arrays.asList(values));
52            }
53            return this;
54        }
55        public void putAll(K key, Collection<V> values) {
56            if (!values.isEmpty()) {
57                createSetIfMissing(key).addAll(values);
58            }
59        }
60        public void putAll(Collection<K> keys, V value) {
61            for (K key : keys) {
62                put(key, value);
63            }
64        }
65        public void putAll(Multimap<K, V> source) {
66            for (Entry<K, Set<V>> entry : source.map.entrySet()) {
67                putAll(entry.getKey(), entry.getValue());
68            }
69        }
70        public void put(K key, V value) {
71            createSetIfMissing(key).add(value);
72        }
73        private Set<V> createSetIfMissing(K key) {
74            Set<V> old = map.get(key);
75            if (old == null) {
76                map.put(key, old = getInstance());
77            }
78            return old;
79        }
80        private Set<V> getInstance() {
81            try {
82                return setClass.newInstance();
83            } catch (Exception e) {
84                throw new ICUException(e);
85            }
86        }
87        public Set<V> get(K key) {
88            Set<V> result = map.get(key);
89            return result; //  == null ? Collections.<V>emptySet() : result;
90        }
91        public Set<K> keySet() {
92            return map.keySet();
93        }
94        public Map<K, Set<V>> asMap() {
95            return map;
96        }
97        public Set<V> values() {
98            Collection<Set<V>> values = map.values();
99            if (values.size() == 0) {
100                return Collections.<V>emptySet();
101            }
102            Set<V> result = getInstance();
103            for ( Set<V> valueSet : values) {
104                result.addAll(valueSet);
105            }
106            return result;
107        }
108        public int size() {
109            return map.size();
110        }
111        public Iterable<Entry<K, V>> entries() {
112            return new MultimapIterator<K, V>(map);
113        }
114        @Override
115        public boolean equals(Object obj) {
116            return this == obj ||
117                    (obj != null
118                    && obj.getClass() == this.getClass()
119                    && map.equals(((Multimap<?,?>) obj).map));
120        }
121
122        @Override
123        public int hashCode() {
124            return map.hashCode();
125        }
126    }
127
128    public static class Multimaps {
129        public static <K, V, R extends Multimap<K, V>> R invertFrom(Multimap<V, K> source, R target) {
130            for (Entry<V, Set<K>> entry : source.asMap().entrySet()) {
131                target.putAll(entry.getValue(), entry.getKey());
132            }
133            return target;
134        }
135        public static <K, V, R extends Multimap<K, V>> R invertFrom(Map<V, K> source, R target) {
136            for (Entry<V, K> entry : source.entrySet()) {
137                target.put(entry.getValue(), entry.getKey());
138            }
139            return target;
140        }
141        /**
142         * Warning, not functionally the same as Guava; only for use in invertFrom.
143         */
144        public static <K, V> Map<K,V> forMap(Map<K,V> map) {
145            return map;
146        }
147    }
148
149    private static class MultimapIterator<K,V> implements Iterator<Entry<K,V>>, Iterable<Entry<K,V>> {
150        private final Iterator<Entry<K, Set<V>>> it1;
151        private Iterator<V> it2 = null;
152        private final ReusableEntry<K,V> entry = new ReusableEntry<K,V>();
153
154        private MultimapIterator(Map<K,Set<V>> map) {
155            it1 = map.entrySet().iterator();
156        }
157        @Override
158        public boolean hasNext() {
159            return it1.hasNext() || it2 != null && it2.hasNext();
160        }
161        @Override
162        public Entry<K, V> next() {
163            if (it2 != null && it2.hasNext()) {
164                entry.value = it2.next();
165            } else {
166                Entry<K, Set<V>> e = it1.next();
167                entry.key = e.getKey();
168                it2 = e.getValue().iterator();
169            }
170            return entry;
171        }
172        @Override
173        public Iterator<Entry<K, V>> iterator() {
174            return this;
175        }
176        @Override
177        public void remove() {
178            throw new UnsupportedOperationException();
179        }
180    }
181
182    private static class ReusableEntry<K,V> implements Entry<K,V> {
183        K key;
184        V value;
185        @Override
186        public K getKey() {
187            return key;
188        }
189        @Override
190        public V getValue() {
191            return value;
192        }
193        @Override
194        public V setValue(V value) {
195            throw new UnsupportedOperationException();
196        }
197    }
198
199    public static class HashMultimap<K, V> extends Multimap<K, V> {
200        private HashMultimap() {
201            super(new HashMap<K, Set<V>>(), HashSet.class);
202        }
203        public static <K, V> HashMultimap<K, V> create() {
204            return new HashMultimap<K, V>();
205        }
206    }
207
208    public static class TreeMultimap<K, V> extends Multimap<K, V> {
209        private TreeMultimap() {
210            super(new TreeMap<K, Set<V>>(), TreeSet.class);
211        }
212        public static <K, V> TreeMultimap<K, V> create() {
213            return new TreeMultimap<K, V>();
214        }
215    }
216
217    public static class LinkedHashMultimap<K, V> extends Multimap<K, V> {
218        private LinkedHashMultimap() {
219            super(new LinkedHashMap<K, Set<V>>(), LinkedHashSet.class);
220        }
221        public static <K, V> LinkedHashMultimap<K, V> create() {
222            return new LinkedHashMultimap<K, V>();
223        }
224    }
225
226
227    //    public static class Counter<T> implements Iterable<T>{
228    //        private Map<T,Long> data;
229    //        @Override
230    //        public Iterator<T> iterator() {
231    //            return data.keySet().iterator();
232    //        }
233    //        public long get(T s) {
234    //            Long result = data.get(s);
235    //            return result != null ? result : 0L;
236    //        }
237    //        public void add(T item, int count) {
238    //            Long result = data.get(item);
239    //            data.put(item, result == null ? count : result + count);
240    //        }
241    //    }
242
243    public static <T> String join(T[] source, String separator) {
244        StringBuilder result = new StringBuilder();
245        for (int i = 0; i < source.length; ++i) {
246            if (i != 0) result.append(separator);
247            result.append(source[i]);
248        }
249        return result.toString();
250    }
251
252    public static <T> String join(Iterable<T> source, String separator) {
253        StringBuilder result = new StringBuilder();
254        boolean first = true;
255        for (T item : source) {
256            if (!first) result.append(separator);
257            else first = false;
258            result.append(item.toString());
259        }
260        return result.toString();
261    }
262
263    public static class CollectionUtilities {
264        public static <T, U extends Iterable<T>> String join(U source, String separator) {
265            return XCldrStub.join(source, separator);
266        }
267    }
268
269    public static class Joiner {
270        private final String separator;
271        private Joiner(String separator) {
272            this.separator = separator;
273        }
274        public static final Joiner on(String separator) {
275            return new Joiner(separator);
276        }
277        public <T> String join(T[] source) {
278            return XCldrStub.join(source, separator);
279        }
280        public <T> String join(Iterable<T> source) {
281            return XCldrStub.join(source, separator);
282        }
283    }
284
285    public static class Splitter {
286        Pattern pattern;
287        boolean trimResults = false;
288        public Splitter(char c) {
289            this(Pattern.compile("\\Q" + c + "\\E"));
290        }
291        public Splitter(Pattern p) {
292            pattern = p;
293        }
294        public static Splitter on(char c) {
295            return new Splitter(c);
296        }
297        public static Splitter on(Pattern p) {
298            return new Splitter(p);
299        }
300        public List<String> splitToList(String input) {
301            String[] items = pattern.split(input);
302            if (trimResults) {
303                for (int i = 0; i < items.length; ++i) {
304                    items[i] = items[i].trim();
305                }
306            }
307            return Arrays.asList(items);
308        }
309        public Splitter trimResults() {
310            trimResults = true;
311            return this;
312        }
313        public Iterable<String> split(String input) {
314            return splitToList(input);
315        }
316    }
317
318    public static class ImmutableSet {
319        public static <T> Set<T> copyOf(Set<T> values) {
320            return Collections.unmodifiableSet(new LinkedHashSet<T>(values)); // copy set for safety, preserve order
321        }
322    }
323    public static class ImmutableMap {
324        public static <K,V> Map<K,V> copyOf(Map<K,V> values) {
325            return Collections.unmodifiableMap(new LinkedHashMap<K,V>(values)); // copy set for safety, preserve order
326        }
327    }
328    public static class ImmutableMultimap {
329        public static <K,V> Multimap<K,V> copyOf(Multimap<K,V> values) {
330            LinkedHashMap<K, Set<V>> temp = new LinkedHashMap<K,Set<V>>(); // semi-deep copy, preserve order
331            for (Entry<K, Set<V>> entry : values.asMap().entrySet()) {
332                Set<V> value = entry.getValue();
333                temp.put(entry.getKey(), value.size() == 1
334                        ? Collections.singleton(value.iterator().next())
335                                : Collections.unmodifiableSet(new LinkedHashSet<V>(value)));
336            }
337            return new Multimap<K,V>(Collections.unmodifiableMap(temp), null);
338        }
339    }
340
341    public static class FileUtilities {
342        public static final Charset UTF8 = Charset.forName("utf-8");
343
344        public static BufferedReader openFile(Class<?> class1, String file) {
345            return openFile(class1, file, UTF8);
346        }
347
348        public static BufferedReader openFile(Class<?> class1, String file, Charset charset) {
349            // URL path = null;
350            // String externalForm = null;
351            try {
352                final InputStream resourceAsStream = class1.getResourceAsStream(file);
353                if (charset == null) {
354                    charset = UTF8;
355                }
356                InputStreamReader reader = new InputStreamReader(resourceAsStream, charset);
357                BufferedReader bufferedReader = new BufferedReader(reader, 1024 * 64);
358                return bufferedReader;
359            } catch (Exception e) {
360                String className = class1 == null ? null : class1.getCanonicalName();
361                String canonicalName = null;
362                try {
363                    String relativeFileName = getRelativeFileName(class1, "../util/");
364                    canonicalName = new File(relativeFileName).getCanonicalPath();
365                } catch (Exception e1) {
366                    throw new ICUUncheckedIOException("Couldn't open file: " + file + "; relative to class: "
367                            + className, e);
368                }
369                throw new ICUUncheckedIOException("Couldn't open file " + file + "; in path " + canonicalName + "; relative to class: "
370                        + className, e);
371            }
372        }
373        public static String getRelativeFileName(Class<?> class1, String filename) {
374            URL resource = class1 == null ?
375                    FileUtilities.class.getResource(filename) : class1.getResource(filename);
376                    String resourceString = resource.toString();
377                    if (resourceString.startsWith("file:")) {
378                        return resourceString.substring(5);
379                    } else if (resourceString.startsWith("jar:file:")) {
380                        return resourceString.substring(9);
381                    } else {
382                        throw new ICUUncheckedIOException("File not found: " + resourceString);
383                    }
384        }
385    }
386
387    static public class RegexUtilities {
388        public static int findMismatch(Matcher m, CharSequence s) {
389            int i;
390            for (i = 1; i < s.length(); ++i) {
391                boolean matches = m.reset(s.subSequence(0, i)).matches();
392                if (!matches && !m.hitEnd()) {
393                    break;
394                }
395            }
396            return i - 1;
397        }
398        public static String showMismatch(Matcher m, CharSequence s) {
399            int failPoint = findMismatch(m, s);
400            String show = s.subSequence(0, failPoint) + "☹" + s.subSequence(failPoint, s.length());
401            return show;
402        }
403    }
404
405    public interface Predicate<T> {
406        /**
407         * Evaluates this predicate on the given argument.
408         *
409         * @param t the input argument
410         * @return {@code true} if the input argument matches the predicate,
411         * otherwise {@code false}
412         */
413        boolean test(T t);
414    }
415}