Coverage Report - org.apache.commons.codec.language.bm.Languages
 
Classes in this File Line Coverage Branch Coverage Complexity
Languages
100%
28/28
100%
12/12
1.516
Languages$1
28%
2/7
N/A
1.516
Languages$2
85%
6/7
N/A
1.516
Languages$LanguageSet
100%
2/2
100%
2/2
1.516
Languages$SomeLanguages
90%
18/20
87%
7/8
1.516
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  *
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 
 18  
 package org.apache.commons.codec.language.bm;
 19  
 
 20  
 import java.io.InputStream;
 21  
 import java.util.Collections;
 22  
 import java.util.EnumMap;
 23  
 import java.util.HashSet;
 24  
 import java.util.Map;
 25  
 import java.util.NoSuchElementException;
 26  
 import java.util.Scanner;
 27  
 import java.util.Set;
 28  
 
 29  
 /**
 30  
  * Language codes.
 31  
  * <p>
 32  
  * Language codes are typically loaded from resource files. These are UTF-8 encoded text files. They are
 33  
  * systematically named following the pattern:
 34  
  * <blockquote>org/apache/commons/codec/language/bm/${{@link NameType#getName()} languages.txt</blockquote>
 35  
  * <p>
 36  
  * The format of these resources is the following:
 37  
  * <ul>
 38  
  * <li><b>Language:</b> a single string containing no whitespace</li>
 39  
  * <li><b>End-of-line comments:</b> Any occurrence of '//' will cause all text following on that line to be
 40  
  * discarded as a comment.</li>
 41  
  * <li><b>Multi-line comments:</b> Any line starting with '/*' will start multi-line commenting mode.
 42  
  * This will skip all content until a line ending in '*' and '/' is found.</li>
 43  
  * <li><b>Blank lines:</b> All blank lines will be skipped.</li>
 44  
  * </ul>
 45  
  * <p>
 46  
  * Ported from language.php
 47  
  * <p>
 48  
  * This class is immutable and thread-safe.
 49  
  *
 50  
  * @since 1.6
 51  
  * @version $Id$
 52  
  */
 53  
 public class Languages {
 54  
     // Iimplementation note: This class is divided into two sections. The first part is a static factory interface that
 55  
     // exposes org/apache/commons/codec/language/bm/%s_languages.txt for %s in NameType.* as a list of supported
 56  
     // languages, and a second part that provides instance methods for accessing this set fo supported languages.
 57  
 
 58  
     /**
 59  
      * A set of languages.
 60  
      */
 61  71578
     public static abstract class LanguageSet {
 62  
 
 63  
         public static LanguageSet from(Set<String> langs) {
 64  119978
             return langs.isEmpty() ? NO_LANGUAGES : new SomeLanguages(langs);
 65  
         }
 66  
 
 67  
         public abstract boolean contains(String language);
 68  
 
 69  
         public abstract String getAny();
 70  
 
 71  
         public abstract boolean isEmpty();
 72  
 
 73  
         public abstract boolean isSingleton();
 74  
 
 75  
         public abstract LanguageSet restrictTo(LanguageSet other);
 76  
     }
 77  
 
 78  
     /**
 79  
      * Some languages, explicitly enumerated.
 80  
      */
 81  71576
     public static final class SomeLanguages extends LanguageSet {
 82  
         private final Set<String> languages;
 83  
 
 84  71576
         private SomeLanguages(Set<String> languages) {
 85  71576
             this.languages = Collections.unmodifiableSet(languages);
 86  71576
         }
 87  
 
 88  
         @Override
 89  
         public boolean contains(String language) {
 90  16
             return this.languages.contains(language);
 91  
         }
 92  
 
 93  
         @Override
 94  
         public String getAny() {
 95  372
             return this.languages.iterator().next();
 96  
         }
 97  
 
 98  
         public Set<String> getLanguages() {
 99  0
             return this.languages;
 100  
         }
 101  
 
 102  
         @Override
 103  
         public boolean isEmpty() {
 104  126053
             return this.languages.isEmpty();
 105  
         }
 106  
 
 107  
         @Override
 108  
         public boolean isSingleton() {
 109  134236
             return this.languages.size() == 1;
 110  
         }
 111  
 
 112  
         @Override
 113  
         public LanguageSet restrictTo(LanguageSet other) {
 114  173742
             if (other == NO_LANGUAGES) {
 115  0
                 return other;
 116  173742
             } else if (other == ANY_LANGUAGE) {
 117  119505
                 return this;
 118  
             } else {
 119  54237
                 SomeLanguages sl = (SomeLanguages) other;
 120  54237
                 if (sl.languages.containsAll(languages)) {
 121  2042
                     return this;
 122  
                 } else {
 123  52195
                     Set<String> ls = new HashSet<String>(this.languages);
 124  52195
                     ls.retainAll(sl.languages);
 125  52195
                     return from(ls);
 126  
                 }
 127  
             }
 128  
         }
 129  
 
 130  
         @Override
 131  
         public String toString() {
 132  16
             return "Languages(" + languages.toString() + ")";
 133  
         }
 134  
 
 135  
     }
 136  
 
 137  
     public static final String ANY = "any";
 138  
 
 139  1
     private static final Map<NameType, Languages> LANGUAGES = new EnumMap<NameType, Languages>(NameType.class);
 140  
 
 141  
     static {
 142  4
         for (NameType s : NameType.values()) {
 143  3
             LANGUAGES.put(s, getInstance(langResourceName(s)));
 144  
         }
 145  
     }
 146  
 
 147  
     public static Languages getInstance(NameType nameType) {
 148  13
         return LANGUAGES.get(nameType);
 149  
     }
 150  
 
 151  
     public static Languages getInstance(String languagesResourceName) {
 152  
         // read languages list
 153  4
         Set<String> ls = new HashSet<String>();
 154  4
         InputStream langIS = Languages.class.getClassLoader().getResourceAsStream(languagesResourceName);
 155  
 
 156  4
         if (langIS == null) {
 157  1
             throw new IllegalArgumentException("Unable to resolve required resource: " + languagesResourceName);
 158  
         }
 159  
 
 160  3
         Scanner lsScanner = new Scanner(langIS, ResourceConstants.ENCODING);
 161  3
         boolean inExtendedComment = false;
 162  90
         while (lsScanner.hasNextLine()) {
 163  87
             String line = lsScanner.nextLine().trim();
 164  87
             if (inExtendedComment) {
 165  45
                 if (line.endsWith(ResourceConstants.EXT_CMT_END)) {
 166  3
                     inExtendedComment = false;
 167  
                 }
 168  
             } else {
 169  42
                 if (line.startsWith(ResourceConstants.EXT_CMT_START)) {
 170  3
                     inExtendedComment = true;
 171  39
                 } else if (line.length() > 0) {
 172  36
                     ls.add(line);
 173  
                 }
 174  
             }
 175  87
         }
 176  
 
 177  3
         return new Languages(Collections.unmodifiableSet(ls));
 178  
     }
 179  
 
 180  
     private static String langResourceName(NameType nameType) {
 181  3
         return String.format("org/apache/commons/codec/language/bm/%s_languages.txt", nameType.getName());
 182  
     }
 183  
 
 184  
     private final Set<String> languages;
 185  
 
 186  
     /**
 187  
      * No languages at all.
 188  
      */
 189  1
     public static final LanguageSet NO_LANGUAGES = new LanguageSet() {
 190  
         @Override
 191  
         public boolean contains(String language) {
 192  0
             return false;
 193  
         }
 194  
 
 195  
         @Override
 196  
         public String getAny() {
 197  0
             throw new NoSuchElementException("Can't fetch any language from the empty language set.");
 198  
         }
 199  
 
 200  
         @Override
 201  
         public boolean isEmpty() {
 202  48350
             return true;
 203  
         }
 204  
 
 205  
         @Override
 206  
         public boolean isSingleton() {
 207  0
             return false;
 208  
         }
 209  
 
 210  
         @Override
 211  
         public LanguageSet restrictTo(LanguageSet other) {
 212  0
             return this;
 213  
         }
 214  
 
 215  
         @Override
 216  
         public String toString() {
 217  0
             return "NO_LANGUAGES";
 218  
         }
 219  
     };
 220  
 
 221  
     /**
 222  
      * Any/all languages.
 223  
      */
 224  1
     public static final LanguageSet ANY_LANGUAGE = new LanguageSet() {
 225  
         @Override
 226  
         public boolean contains(String language) {
 227  2
             return true;
 228  
         }
 229  
 
 230  
         @Override
 231  
         public String getAny() {
 232  0
             throw new NoSuchElementException("Can't fetch any language from the any language set.");
 233  
         }
 234  
 
 235  
         @Override
 236  
         public boolean isEmpty() {
 237  1434
             return false;
 238  
         }
 239  
 
 240  
         @Override
 241  
         public boolean isSingleton() {
 242  100
             return false;
 243  
         }
 244  
 
 245  
         @Override
 246  
         public LanguageSet restrictTo(LanguageSet other) {
 247  2095
             return other;
 248  
         }
 249  
 
 250  
         @Override
 251  
         public String toString() {
 252  2
             return "ANY_LANGUAGE";
 253  
         }
 254  
     };
 255  
 
 256  3
     private Languages(Set<String> languages) {
 257  3
         this.languages = languages;
 258  3
     }
 259  
 
 260  
     public Set<String> getLanguages() {
 261  67171
         return this.languages;
 262  
     }
 263  
 }