All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ibm.fhir.model.lang.util.LanguageRegistryUtil Maven / Gradle / Ivy

/*
 * (C) Copyright IBM Corp. 2020
 *
 * SPDX-License-Identifier: Apache-2.0
 */

package com.ibm.fhir.model.lang.util;

import java.util.ArrayList;
import java.util.List;

/**
 * Utility class for language registry.
 */
public class LanguageRegistryUtil {

    private LanguageRegistryUtil() {
    }

    /**
     * Loads the class in the classloader in order to initialize static members in LanguageRegistry.
     * Call this before using the class in order to avoid a slight performance hit on first use.
     */
    public static void init() {
        LanguageRegistry.init();
    }

    /**
     * Determines if the tag is a valid language tag registered with BCP-47.
     * If the tag contains any extensions or private-use subtags, it is not considered valid.
     * 
     * @param tag
     *            the tag
     * @return true or false
     */
    public static boolean isValidLanguageTag(String tag) {

        // Check that only valid characters are used
        if (tag == null || tag.isEmpty() || tag.indexOf("--") > -1 || !tag.matches("^[a-zA-Z0-9-]+$")) {
            return false;
        }

        // Convert to lowercase since language tags are case insensitive and LanguageRegistry contains them in lower case
        tag = tag.toLowerCase();
        
        // Check if the tag is a grandfathered tag
        if (LanguageRegistry.isGrandfatheredTag(tag)) {
            return true;
        }

        // Check if the tag contains an extension or private use subtag
        if (containsExtensionOrPrivateUseSubtags(tag)) {
            return false;
        }

        String[] subtags = tag.split("-");
        if (subtags.length < 1) {
            return false;
        }

        // Check the language subtag
        String language = subtags[0];
        if (!LanguageRegistry.isLanguageSubtag(language)) {
            return false;
        }

        // Check the other subtags (which are optional)
        if (subtags.length > 1) {
            String extlangFound = null;
            String scriptFound = null;
            String regionFound = null;
            List variantWithPrefixesFound = new ArrayList<>();
            List variantsWithoutPrefixesFound = new ArrayList<>();
            for (int i = 1; i < subtags.length; i++) {
                String subtag = subtags[i];

                if (LanguageRegistry.isExtlangSubtag(subtag)) {
                    // Multiple extlang not allowed, and must be before script, region, and variant subtags
                    if (extlangFound != null || scriptFound != null || regionFound != null || !variantWithPrefixesFound.isEmpty()
                            || !variantWithPrefixesFound.isEmpty()) {
                        return false;
                    }
                    extlangFound = subtag;
                } else if (LanguageRegistry.isScriptSubtag(subtag)) {
                    // Multiple scripts not allowed, and must be before region and variant subtags
                    if (scriptFound != null || regionFound != null || !variantWithPrefixesFound.isEmpty() || !variantWithPrefixesFound.isEmpty()) {
                        return false;
                    }
                    scriptFound = subtag;
                } else if (LanguageRegistry.isRegionSubtag(subtag)) {
                    // Multiple regions not allowed, and must be before variant subtags
                    if (regionFound != null || !variantWithPrefixesFound.isEmpty() || !variantWithPrefixesFound.isEmpty()) {
                        return false;
                    }
                    regionFound = subtag;
                } else if (LanguageRegistry.isVariantSubtag(subtag)) {
                    // Duplicate variants not allowed
                    if (variantWithPrefixesFound.contains(subtag) || variantsWithoutPrefixesFound.contains(subtag)) {
                        return false;
                    }
                    // Variants with prefixes defined must come before variants without prefixes defined
                    List variantPrefixes = LanguageRegistry.getVariantPrefixes(subtag);
                    if (!variantPrefixes.isEmpty()) {
                        if (!variantsWithoutPrefixesFound.isEmpty()) {
                            return false;
                        }
                        // Check prefixes against tag so far (with and without region subtag)
                        StringBuilder prefixToCheck1Sb = new StringBuilder(language);
                        StringBuilder prefixToCheck2Sb = new StringBuilder(language);
                        if (extlangFound != null) {
                            prefixToCheck1Sb.append("-").append(extlangFound);
                            prefixToCheck2Sb.append("-").append(extlangFound);
                        }
                        if (scriptFound != null) {
                            prefixToCheck1Sb.append("-").append(scriptFound);
                            prefixToCheck2Sb.append("-").append(scriptFound);
                        }
                        if (regionFound != null) {
                            prefixToCheck1Sb.append("-").append(regionFound);
                        }
                        for (String variantWithPrefixFound : variantWithPrefixesFound) {
                            prefixToCheck1Sb.append("-").append(variantWithPrefixFound);
                            prefixToCheck2Sb.append("-").append(variantWithPrefixFound);
                        }
                        if (!variantPrefixes.contains(prefixToCheck1Sb.toString()) && !variantPrefixes.contains(prefixToCheck2Sb.toString())) {
                            return false;
                        }
                        variantWithPrefixesFound.add(subtag);
                    } else {
                        variantsWithoutPrefixesFound.add(subtag);
                    }
                } else {
                    return false;
                }
            }
        }

        return true;
    }

    /**
     * Determines if the tag contains an extension or private use subtag.
     * 
     * @param tag
     *            the tag
     * @return true or false
     */
    private static boolean containsExtensionOrPrivateUseSubtags(String tag) {
        return tag.matches("^.-") || tag.matches("-.-");
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy