Coverage Report - org.crosswire.common.util.Languages
 
Classes in this File Line Coverage Branch Coverage Complexity
Languages
0%
0/26
0%
0/8
2.75
Languages$AllLanguages
0%
0/12
0%
0/4
2.75
Languages$RtoL
0%
0/16
0%
0/4
2.75
 
 1  
 /**
 2  
  * Distribution License:
 3  
  * JSword is free software; you can redistribute it and/or modify it under
 4  
  * the terms of the GNU Lesser General Public License, version 2.1 or later
 5  
  * as published by the Free Software Foundation. This program is distributed
 6  
  * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
 7  
  * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 8  
  * See the GNU Lesser General Public License for more details.
 9  
  *
 10  
  * The License is available on the internet at:
 11  
  *      http://www.gnu.org/copyleft/lgpl.html
 12  
  * or by writing to:
 13  
  *      Free Software Foundation, Inc.
 14  
  *      59 Temple Place - Suite 330
 15  
  *      Boston, MA 02111-1307, USA
 16  
  *
 17  
  * © CrossWire Bible Society, 2005 - 2016
 18  
  *
 19  
  */
 20  
 package org.crosswire.common.util;
 21  
 
 22  
 import java.io.IOException;
 23  
 import java.net.URL;
 24  
 import java.util.HashMap;
 25  
 import java.util.HashSet;
 26  
 import java.util.Locale;
 27  
 import java.util.Map;
 28  
 import java.util.MissingResourceException;
 29  
 import java.util.ResourceBundle;
 30  
 import java.util.Set;
 31  
 
 32  
 import org.crosswire.jsword.book.Books;
 33  
 import org.crosswire.jsword.internationalisation.LocaleProviderManager;
 34  
 import org.slf4j.Logger;
 35  
 import org.slf4j.LoggerFactory;
 36  
 
 37  
 /**
 38  
  * A utility class that converts bcp-47 codes as supported by {@link Language} to their
 39  
  * localized language name.
 40  
  * 
 41  
  * @see gnu.lgpl.License The GNU Lesser General Public License for details.
 42  
  * @author DM Smith
 43  
  */
 44  
 public final class Languages {
 45  
 
 46  
     /**
 47  
      * Make the class a true utility class by having a private constructor.
 48  
      */
 49  0
     private Languages() {
 50  0
     }
 51  
 
 52  
     /**
 53  
      * Get the language name for the BCP-47 specification of the language.
 54  
      * 
 55  
      * @param code the BCP-47 specification for the language
 56  
      * @return the name of the language
 57  
      */
 58  
     public static String getName(String code) {
 59  
         // Returning the code is the fallback for lookup
 60  0
         String name = code;
 61  
         try {
 62  0
             ResourceBundle langs = getLocalisedCommonLanguages();
 63  0
             if (langs != null) {
 64  0
                 name = langs.getString(code);
 65  
             }
 66  0
         } catch (MissingResourceException e) {
 67  
             // This is allowed
 68  0
         }
 69  0
         return name;
 70  
     }
 71  
 
 72  
     /**
 73  
      * Gets the localised common languages. Caching here, is done to prevent extra logging 
 74  
      * happening every time we miss the iso639 ResourceBundle
 75  
      * and end up having to lookup the iso639full
 76  
      * 
 77  
      * @return the localised common languages
 78  
      */
 79  
     private static ResourceBundle getLocalisedCommonLanguages() {
 80  0
         Locale locale = LocaleProviderManager.getLocale();
 81  0
         ResourceBundle langs = localisedCommonLanguages.get(locale);
 82  0
         if (langs == null) {
 83  0
             synchronized (Languages.class) {
 84  0
                 langs = localisedCommonLanguages.get(locale);
 85  0
                 if (langs == null) {
 86  0
                     langs = initLanguages(locale);
 87  0
                     if (langs != null) {
 88  0
                         localisedCommonLanguages.put(locale, langs);
 89  
                     }
 90  
                 }
 91  0
             }
 92  
         }
 93  0
         return langs;
 94  
     }
 95  
 
 96  
     private static ResourceBundle initLanguages(Locale locale) {
 97  
         try {
 98  0
             return ResourceBundle.getBundle("iso639", locale, CWClassLoader.instance());
 99  0
         } catch (MissingResourceException e) {
 100  0
             log.info("Unable to find language in iso639 bundle", e);
 101  
         }
 102  0
         return null;
 103  
     }
 104  
 
 105  
     /**
 106  
      * Provide a fallback lookup against a huge list of all languages.
 107  
      * The basic list has a few hundred languages. The full list has
 108  
      * over 7000. As a fallback, this file is not internationalized.
 109  
      */
 110  
     public static final class AllLanguages {
 111  
         /**
 112  
          * This is a singleton class. Do not allow construction.
 113  
          */
 114  0
         private AllLanguages() { }
 115  
 
 116  
         /**
 117  
          * Get the language name for the code. If the language name is not known
 118  
          * then return the code.
 119  
          * 
 120  
          * @param languageCode the language code
 121  
          * @return the name for the language.
 122  
          */
 123  
         public static String getName(String languageCode) {
 124  0
             if (instance != null) {
 125  0
                 String name = instance.get(languageCode);
 126  0
                 if (name != null) {
 127  0
                     return name;
 128  
                 }
 129  
             }
 130  0
             return languageCode;
 131  
         }
 132  
 
 133  
         /**
 134  
          * Do lazy loading of the huge file of languages.
 135  
          * Note: It is OK for it not to be present.
 136  
          */
 137  
         private static PropertyMap instance;
 138  
         static {
 139  
             try {
 140  0
                 instance = ResourceUtil.getProperties("iso639full");
 141  0
                 log.debug("Loading iso639full.properties file");
 142  0
             } catch (IOException e) {
 143  0
                 log.info("Unable to load iso639full.properties", e);
 144  0
             }
 145  0
         }
 146  
     }
 147  
 
 148  
     /**
 149  
      * Provide a fallback lookup against a huge list of all languages.
 150  
      * The basic list has a few hundred languages. The full list has
 151  
      * over 7000. As a fallback, this file is not internationalized.
 152  
      */
 153  
     public static final class RtoL {
 154  
         /**
 155  
          * This is a singleton class. Do not allow construction.
 156  
          */
 157  0
         private RtoL() { }
 158  
 
 159  
         /**
 160  
          * Determine whether this language is a Left-to-Right or a Right-to-Left
 161  
          * language. If the language has a script, it is used for the determination.
 162  
          * Otherwise, check the language.
 163  
          * <p>
 164  
          * Note: This is problematic. Languages do not have direction.
 165  
          * Scripts do. Further, there are over 7000 living languages, many of which
 166  
          * are written in Right-to-Left scripts and are not listed here.
 167  
          * </p>
 168  
          * 
 169  
          * @param script the iso15924 script code, must be in Title case
 170  
          * @param lang the iso639 language code, must be lower case
 171  
          * @return true if the language is Right-to-Left
 172  
          */
 173  
         public static boolean isRtoL(String script, String lang) {
 174  0
             if (script != null) {
 175  0
                 return rtol.contains(script);
 176  
             }
 177  0
             if (lang != null) {
 178  0
                 return rtol.contains(lang);
 179  
             }
 180  0
             return false;
 181  
         }
 182  
 
 183  
         /**
 184  
          * Do lazy loading of the huge file of languages.
 185  
          * Note: It is OK for it not to be present.
 186  
          */
 187  0
         private static Set rtol = new HashSet();
 188  
         /**
 189  
          * load RtoL data
 190  
          */
 191  
         static {
 192  
             try {
 193  0
                 URL index = ResourceUtil.getResource(Translations.class, "rtol.txt");
 194  0
                 String[] list = NetUtil.listByIndexFile(NetUtil.toURI(index));
 195  0
                 log.debug("Loading iso639full.properties file");
 196  0
                 for (int i = 0; i < list.length; i++) {
 197  0
                     rtol.add(list[i]);
 198  
                 }
 199  0
             } catch (IOException ex) {
 200  0
                 log.info("Unable to load rtol.txt", ex);
 201  0
             }
 202  0
         }
 203  
     }
 204  
 
 205  0
     private static Map<Locale, ResourceBundle> localisedCommonLanguages = new HashMap<Locale, ResourceBundle>();
 206  
 
 207  
     /**
 208  
      * The log stream
 209  
      */
 210  0
     protected static final Logger log = LoggerFactory.getLogger(Books.class);
 211  
 }