Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright (c) 2006 Henri Sivonen
   * Copyright (c) 2007-2010 Mozilla Foundation
   *
   * Permission is hereby granted, free of charge, to any person obtaining a 
   * copy of this software and associated documentation files (the "Software"), 
   * to deal in the Software without restriction, including without limitation 
   * the rights to use, copy, modify, merge, publish, distribute, sublicense, 
   * and/or sell copies of the Software, and to permit persons to whom the 
  * Software is furnished to do so, subject to the following conditions:
  *
  * The above copyright notice and this permission notice shall be included in 
  * all copies or substantial portions of the Software.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
  * DEALINGS IN THE SOFTWARE.
  */
 
 package org.whattf.datatype;
 
 import java.util.List;
 import java.util.Map;
 

Author(s):
hsivonen
Version:
$Id$
 
 public final class Language extends AbstractDatatype {

    
The singleton instance.
 
     public static final Language THE_INSTANCE = new Language();
 
     private static final Pattern HYPHEN = Pattern.compile("-");
 
     private static final boolean WARN = System.getProperty(
             "org.whattf.datatype.warn""").equals("true") ? true : false;
 
     private static String[] languages = null;
 
     private static String[] extlangs = null;
 
     private static String[] scripts = null;
 
     private static String[] regions = null;
 
     private static String[] variants = null;
 
     private static String[] grandfathered = null;
 
     private static String[] redundant = null;
 
     private static String[] deprecated = null;
 
     private static String[] deprecatedLang = null;
 
     private static int[] suppressedScriptByLanguage = null;
 
     private static Map<StringStringpreferredValueByLanguageMap = new HashMap<StringString>();
 
     private static String[][][] prefixesByVariant = null;
 
     private static int[] prefixByExtlang = null;
 
     static {
         try {
             LanguageData data = new LanguageData();
              = data.getLanguages();
              = data.getExtlangs();
              = data.getScripts();
              = data.getRegions();
              = data.getVariants();
              = data.getGrandfathered();
              = data.getRedundant();
              = data.getDeprecated();
              = data.getDeprecatedLang();
              = data.getSuppressedScriptByLanguage();
              = data.getPrefixByExtlang();
              = data.getPrefixesByVariant();
         } catch (IOException e) {
             throw new RuntimeException(e);
         }
     }

    
Package-private constructor
    private Language() {
        super();
    }
    public void checkValid(CharSequence litthrows DatatypeException {
        String literal = lit.toString();
        if (literal.length() == 0) {
            throw newDatatypeException("The empty string is not a valid language tag.");
        }
        literal = toAsciiLowerCase(literal);
        if (isGrandfathered(literal)) {
            if (isDeprecated(literal) && ) {
                throw newDatatypeException("The grandfathered language tag ",
                        literal" is deprecated." + " Use \u201C"
                                + .get(literal)
                                + "\u201D instead.");
            }
            return;
        }
        if (isRedundant(literal)) {
            if (isDeprecated(literal) && ) {
                throw newDatatypeException("The language tag "lit.toString(),
                        " is deprecated." + " Use \u201C"
                                + .get(literal)
                                + "\u201D instead.");
            }
            return;
        }
        if (literal.startsWith("-")) {
            throw newDatatypeException("Language tag must not start with HYPHEN-MINUS.");
        }
        if (literal.endsWith("-")) {
            throw newDatatypeException("Language tag must not end with HYPHEN-MINUS.");
        }
        String[] subtags = .split(literal);
        for (int j = 0; j < subtags.lengthj++) {
            int len = subtags[j].length();
            if (len == 0) {
                throw newDatatypeException("Zero-length subtag.");
            } else if (len > 8) {
                throw newDatatypeException("Subtags must not exceed 8 characters in length.");
            }
        }
        // Language
        int i = 0;
        String subtag = subtags[i];
        int len = subtag.length();
        if ("x".equals(subtag)) {
            checkPrivateUse(isubtags);
            return;
        }
        if ((len == 2 || len == 3) && isLowerCaseAlpha(subtag)) {
            if (!isLanguage(subtag)) {
                throw newDatatypeException("The language subtag "subtag,
                        " is not a valid ISO language part of a language tag.");
            }
            if (isDeprecatedLang(subtag) && ) {
                throw newDatatypeException("The language subtag "subtag,
                        " is deprecated." + " Use \u201C"
                                + .get(literal)
                                + "\u201D instead.");
            }
            i++;
            if (i == subtags.length) {
                return;
            }
            subtag = subtags[i];
            len = subtag.length();
        } else if (len == 4 && isLowerCaseAlpha(subtag)) {
            throw newDatatypeException("Found reserved language tag: "subtag,
                    ".");
        } else if (len >= 5 && isLowerCaseAlpha(subtag)) {
            if (!isLanguage(subtag)) {
                throw newDatatypeException("The language subtag "subtag,
                        " is not a valid IANA language part of a language tag.");
            }
            if (isDeprecatedLang(subtag) && ) {
                throw newDatatypeException("The language subtag "subtag,
                        " is deprecated." + " Use \u201C"
                                + .get(literal)
                                + "\u201D instead.");
            }
            i++;
            if (i == subtags.length) {
                return;
            }
            subtag = subtags[i];
            len = subtag.length();
        } else {
            throw newDatatypeException("The language subtag "subtag,
                    " is not a valid language subtag.");
        }
        // extlang
        if ("x".equals(subtag)) {
            checkPrivateUse(isubtags);
            return;
        }
        if (subtag.length() == 3 && isLowerCaseAlpha(subtag)) {
            if (!isExtlang(subtag)) {
                throw newDatatypeException("Bad extlang subtag "subtag".");
            }
            if (!usesPrefixByExtlang(subtags[0], subtag)) {
                // IANA language tags are never correct prefixes.
                throw newDatatypeException("Extlang subtag "subtag,
                        " has an incorrect prefix.");
            }
            i++;
            if (i == subtags.length) {
                return;
            }
            subtag = subtags[i];
            len = subtag.length();
        }
        // Script?
        if ("x".equals(subtag)) {
            checkPrivateUse(isubtags);
            return;
        }
        if (subtag.length() == 4 & isLowerCaseAlpha(subtag)) {
            if (!isScript(subtag)) {
                throw newDatatypeException("Bad script subtag.");
            }
            if (isDeprecated(subtag) && ) {
                throw newDatatypeException("The script subtag "subtag,
                        " is deprecated." + " Use \u201C"
                                + .get(literal)
                                + "\u201D instead.");
            }
            if (shouldSuppressScript(subtags[0], subtag)) {
                throw newDatatypeException("Language tag should omit the default script for the language.");
            }
            i++;
            if (i == subtags.length) {
                return;
            }
            subtag = subtags[i];
            len = subtag.length();
        }
        // Region
        if ((len == 3 && isDigit(subtag))
                || (len == 2 && isLowerCaseAlpha(subtag))) {
            if (!isRegion(subtag)) {
                throw newDatatypeException("Bad region subtag.");
            }
            if (isDeprecated(subtag) && ) {
                throw newDatatypeException("The region subtag "subtag,
                        " is deprecated." + " Use \u201C"
                                + .get(literal)
                                + "\u201D instead.");
            }
            i++;
            if (i == subtags.length) {
                return;
            }
            subtag = subtags[i];
            len = subtag.length();
        }
        // Variant
        for (;;) {
            if ("x".equals(subtag)) {
                checkPrivateUse(isubtags);
                return;
            }
            // cutting corners here a bit since there are no extensions at this
            // time
            if (len == 1 && isLowerCaseAlphaNumeric(subtag)) {
                throw newDatatypeException("Unknown extension "subtag".");
            } else if ((len == 4 && isDigit(subtag.charAt(0)) && isLowerCaseAlphaNumeric(subtag))
                    || (len >= 5 && isLowerCaseAlphaNumeric(subtag))) {
                if (!isVariant(subtag)) {
                    throw newDatatypeException("Bad variant subtag "subtag".");
                }
                if (isDeprecated(subtag) && ) {
                    throw newDatatypeException("The variant subtag "subtag,
                            " is deprecated." + " Use \u201C"
                                    + .get(literal)
                                    + "\u201D instead.");
                }
                checkForValidPrefix(subtagsubtagsi);
            } else {
                throw newDatatypeException("The subtag "subtag,
                        " does not match the format for any permissible subtag type.");
            }
            i++;
            if (i == subtags.length) {
                return;
            }
            subtag = subtags[i];
            len = subtag.length();
        }
    }
    private void checkForValidPrefix(String subtagString[] subtagsint i)
            throws DatatypeException {
        String variant = subtags[i];
        int index = Arrays.binarySearch(variant);
        assert index >= 0;
        String[][] prefixes = [index];
        if (prefixes.length == 0) {
            return;
        }
        List<StringrecommendedPrefixes = new ArrayList<String>();
        for (int j = 0; j < prefixes.lengthj++) {
            String[] prefix = prefixes[j];
            for (int k = 0; k < prefix.lengthk++) {
                String prefixComponent = prefix[k];
                if (!subtagsContainPrefixComponent(prefixComponentsubtagsi)) {
                    recommendedPrefixes.add(prefixComponent);
                }
            }
            if (prefixMatches(prefixsubtagsi)) {
                return;
            }
        }
        if (recommendedPrefixes.size() == 0) {
            return;
        }
        int count = recommendedPrefixes.size();
        StringBuilder sb = new StringBuilder();
        if (recommendedPrefixes.size() > 1) {
            sb.append(" one of ");
        }
        for (String prefix : recommendedPrefixes) {
            if (count != recommendedPrefixes.size()) {
                sb.append(", ");
                if (count == 1) {
                    sb.append(" or ");
                }
            }
            sb.append("\u201C");
            sb.append(prefix);
            sb.append('\u201D');
            count--;
        }
        throw newDatatypeException("Variant "subtag,
                " lacks recommended prefix. Use " + sb + " instead.");
    }
    private boolean prefixMatches(String[] prefixString[] subtagsint limit) {
        for (int i = 0; i < prefix.lengthi++) {
            String prefixComponent = prefix[i];
            if (!subtagsContainPrefixComponent(prefixComponentsubtagslimit)) {
                return false;
            }
        }
        return true;
    }
    private boolean subtagsContainPrefixComponent(String prefixComponent,
            String[] subtagsint limit) {
        for (int i = 0; i < limiti++) {
            String subtag = subtags[i];
            if (subtag.equals(prefixComponent)) {
                return true;
            }
        }
        return false;
    }
    private boolean usesPrefixByExtlang(String languageString extlang) {
        int langIndex = Arrays.binarySearch(language);
        int extlangIndex = Arrays.binarySearch(extlang);
        assert langIndex > -1;
        int prefixExpected = [extlangIndex];
        return prefixExpected == langIndex;
    }
    private boolean shouldSuppressScript(String languageString script) {
        int langIndex = Arrays.binarySearch(language);
        assert langIndex > -1;
        int scriptIndex = [langIndex];
        if (scriptIndex < 0) {
            return false;
        } else {
            return [scriptIndex].equals(script);
        }
    }
    private boolean isVariant(String subtag) {
        return (Arrays.binarySearch(subtag) > -1);
    }
    private boolean isRegion(String subtag) {
        return (Arrays.binarySearch(subtag) > -1)
                || "aa".equals(subtag)
                || ("qm".compareTo(subtag) <= 0 && "qz".compareTo(subtag) >= 0)
                || ("xa".compareTo(subtag) <= 0 && "xz".compareTo(subtag) >= 0)
                || "zz".equals(subtag);
    }
    private boolean isScript(String subtag) {
        return (Arrays.binarySearch(subtag) > -1)
                || ("qaaa".compareTo(subtag) <= 0 && "qabx".compareTo(subtag) >= 0);
    }
    private boolean isExtlang(String subtag) {
        return (Arrays.binarySearch(subtag) > -1);
    }
    private boolean isLanguage(String subtag) {
        return (Arrays.binarySearch(subtag) > -1)
                || ("qaa".compareTo(subtag) <= 0 && "qtz".compareTo(subtag) >= 0);
    }
    private void checkPrivateUse(int iString[] subtags)
            throws DatatypeException {
        int len = subtags.length;
        i++;
        if (i == len) {
            throw newDatatypeException("No subtags in private use sequence.");
        }
        while (i < len) {
            String subtag = subtags[i];
            if (subtag.length() < 2) {
                throw newDatatypeException("Private use subtag "subtag" is too short.");                
            }
            if (!isLowerCaseAlphaNumeric(subtag)) {
                throw newDatatypeException("Bad character in private use subtag "subtag".");
            }
            i++;
        }
    }
    private final boolean isLowerCaseAlphaNumeric(char c) {
        return isLowerCaseAlpha(c) || isDigit(c);
    }
    private final boolean isLowerCaseAlphaNumeric(String str) {
        for (int i = 0; i < str.length(); i++) {
            if (!isLowerCaseAlphaNumeric(str.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    

Parameters:
c
Returns:
    private final boolean isDigit(char c) {
        return (c >= '0' && c <= '9');
    }
    private final boolean isDigit(String str) {
        for (int i = 0; i < str.length(); i++) {
            if (!isDigit(str.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    

Parameters:
c
Returns:
    private final boolean isLowerCaseAlpha(char c) {
        return (c >= 'a' && c <= 'z');
    }
    private final boolean isLowerCaseAlpha(String str) {
        for (int i = 0; i < str.length(); i++) {
            if (!isLowerCaseAlpha(str.charAt(i))) {
                return false;
            }
        }
        return true;
    }
    private boolean isGrandfathered(String literal) {
        return Arrays.binarySearch(literal) > -1;
    }
    private boolean isRedundant(String literal) {
        return Arrays.binarySearch(literal) > -1;
    }
    private boolean isDeprecated(String subtag) {
        return Arrays.binarySearch(subtag) > -1;
    }
    private boolean isDeprecatedLang(String subtag) {
        return Arrays.binarySearch(subtag) > -1;
    }
    @Override public String getName() {
        return "language tag";
    }
New to GrepCode? Check out our FAQ X