示例#1
0
        /** Reads
         *  keyInfo{
         *      deprecated{
         *                  kh{"true"}
         *                  vt{"true"}
         *      }
         *      valueType{
         *                  ca{"incremental"}
         *                  h0{"single"}
         *                  kr{"multiple"}
         *                  vt{"multiple"}
         *                  x0{"any"}
         *      }
         *  }
         */
        private static void GetKeyInfo(UResourceBundle keyInfoRes)
        {
            ISet <string> _deprecatedKeys = new JCG.HashSet <string>();
            IDictionary <string, KeyTypeDataValueType> _valueTypes = new JCG.LinkedDictionary <string, KeyTypeDataValueType>();

            foreach (var keyInfoEntry in keyInfoRes)
            {
                string      key     = keyInfoEntry.Key;
                KeyInfoType keyInfo = (KeyInfoType)Enum.Parse(typeof(KeyInfoType), key, true);
                foreach (var keyInfoEntry2 in keyInfoEntry)
                {
                    string key2   = keyInfoEntry2.Key;
                    string value2 = keyInfoEntry2.GetString();
                    switch (keyInfo)
                    {
                    case KeyInfoType.deprecated:
                        _deprecatedKeys.Add(key2);
                        break;

                    case KeyInfoType.valueType:
                        _valueTypes[key2] = (KeyTypeDataValueType)Enum.Parse(typeof(KeyTypeDataValueType), value2, true);
                        break;
                    }
                }
            }
            DEPRECATED_KEYS = _deprecatedKeys.AsReadOnly();
            VALUE_TYPES     = _valueTypes.AsReadOnly();
        }
示例#2
0
        /** Reads:
         *  typeInfo{
         *      deprecated{
         *                  co{
         *                      direct{"true"}
         *                  }
         *                  tz{
         *                      camtr{"true"}
         *                  }
         *      }
         *  }
         */
        private static void GetTypeInfo(UResourceBundle typeInfoRes)
        {
            IDictionary <string, ISet <string> > _deprecatedKeyTypes = new JCG.LinkedDictionary <string, ISet <string> >();

            foreach (var keyInfoEntry in typeInfoRes)
            {
                string       key      = keyInfoEntry.Key;
                TypeInfoType typeInfo = (TypeInfoType)Enum.Parse(typeof(TypeInfoType), key, true);
                foreach (var keyInfoEntry2 in keyInfoEntry)
                {
                    string        key2             = keyInfoEntry2.Key;
                    ISet <string> _deprecatedTypes = new JCG.LinkedHashSet <string>();
                    foreach (var keyInfoEntry3 in keyInfoEntry2)
                    {
                        string key3 = keyInfoEntry3.Key;
                        switch (typeInfo)
                        { // allow for expansion
                        case TypeInfoType.deprecated:
                            _deprecatedTypes.Add(key3);
                            break;
                        }
                    }
                    _deprecatedKeyTypes[key2] = _deprecatedTypes.AsReadOnly();
                }
            }
            DEPRECATED_KEY_TYPES = _deprecatedKeyTypes.AsReadOnly();
        }
示例#3
0
        /// <summary>
        /// Reloads the internal SPI list.
        /// Changes to the service list are visible after the method ends, all
        /// iterators (e.g, from <see cref="AvailableServices"/>,...) stay consistent.
        ///
        /// <para/><b>NOTE:</b> Only new service providers are added, existing ones are
        /// never removed or replaced.
        ///
        /// <para/><em>this method is expensive and should only be called for discovery
        /// of new service providers on the given classpath/classloader!</em>
        /// </summary>
        public void Reload()
        {
            UninterruptableMonitor.Enter(this);
            try
            {
                IDictionary <string, Type> services = new JCG.LinkedDictionary <string, Type>(this.services);
                SPIClassIterator <S>       loader   = SPIClassIterator <S> .Get();

                foreach (var service in loader)
                {
                    string clazzName = service.Name;
                    string name      = null;
                    foreach (string suffix in suffixes)
                    {
                        if (clazzName.EndsWith(suffix, StringComparison.Ordinal))
                        {
                            name = clazzName.Substring(0, clazzName.Length - suffix.Length).ToLowerInvariant();
                            break;
                        }
                    }

                    if (name is null)
                    {
                        throw ServiceConfigurationError.Create("The class name " + service.Name +
                                                               " has wrong suffix, allowed are: " + Arrays.ToString(suffixes));
                    }
                    // only add the first one for each name, later services will be ignored
                    // this allows to place services before others in classpath to make
                    // them used instead of others
                    //
                    // TODO: Should we disallow duplicate names here?
                    // Allowing it may get confusing on collisions, as different packages
                    // could contain same factory class, which is a naming bug!
                    // When changing this be careful to allow reload()!
                    if (!services.ContainsKey(name))
                    {
                        services.Add(name, service);
                    }
                }
                this.services = services.AsReadOnly();
            }
            finally
            {
                UninterruptableMonitor.Exit(this);
            }
        }
示例#4
0
        private static void InitFromResourceBundle()
        {
            UResourceBundle keyTypeDataRes = UResourceBundle.GetBundleInstance(
                ICUData.IcuBaseName,
                "keyTypeData",
                ICUResourceBundle.IcuDataAssembly);

            GetKeyInfo(keyTypeDataRes.Get("keyInfo"));
            GetTypeInfo(keyTypeDataRes.Get("typeInfo"));

            UResourceBundle keyMapRes  = keyTypeDataRes.Get("keyMap");
            UResourceBundle typeMapRes = keyTypeDataRes.Get("typeMap");

            // alias data is optional
            UResourceBundle typeAliasRes    = null;
            UResourceBundle bcpTypeAliasRes = null;

            try
            {
                typeAliasRes = keyTypeDataRes.Get("typeAlias");
            }
            catch (MissingManifestResourceException)
            {
                // fall through
            }

            try
            {
                bcpTypeAliasRes = keyTypeDataRes.Get("bcpTypeAlias");
            }
            catch (MissingManifestResourceException)
            {
                // fall through
            }

            // iterate through keyMap resource
            using (UResourceBundleEnumerator keyMapItr = keyMapRes.GetEnumerator())
            {
                IDictionary <string, ISet <string> > _Bcp47Keys = new JCG.LinkedDictionary <string, ISet <string> >(); // ICU4N NOTE: As long as we don't delete, Dictionary keeps insertion order the same as LinkedHashMap

                while (keyMapItr.MoveNext())
                {
                    UResourceBundle keyMapEntry = keyMapItr.Current;
                    string          legacyKeyId = keyMapEntry.Key;
                    string          bcpKeyId    = keyMapEntry.GetString();

                    bool hasSameKey = false;
                    if (bcpKeyId.Length == 0)
                    {
                        // Empty value indicates that BCP key is same with the legacy key.
                        bcpKeyId   = legacyKeyId;
                        hasSameKey = true;
                    }
                    ISet <string> _bcp47Types = new JCG.LinkedHashSet <string>();
                    _Bcp47Keys[bcpKeyId] = _bcp47Types.AsReadOnly();

                    bool isTZ = legacyKeyId.Equals("timezone");

                    // reverse type alias map
                    IDictionary <string, ISet <string> > typeAliasMap = null;
                    if (typeAliasRes != null)
                    {
                        UResourceBundle typeAliasResByKey = null;
                        try
                        {
                            typeAliasResByKey = typeAliasRes.Get(legacyKeyId);
                        }
                        catch (MissingManifestResourceException)
                        {
                            // fall through
                        }
                        if (typeAliasResByKey != null)
                        {
                            typeAliasMap = new Dictionary <string, ISet <string> >();
                            using (UResourceBundleEnumerator typeAliasResItr = typeAliasResByKey.GetEnumerator())
                            {
                                while (typeAliasResItr.MoveNext())
                                {
                                    UResourceBundle typeAliasDataEntry = typeAliasResItr.Current;
                                    string          from = typeAliasDataEntry.Key;
                                    string          to   = typeAliasDataEntry.GetString();
                                    if (isTZ)
                                    {
                                        from = from.Replace(':', '/');
                                    }
                                    if (!typeAliasMap.TryGetValue(to, out ISet <string> aliasSet) || aliasSet == null)
                                    {
                                        aliasSet         = new JCG.HashSet <string>();
                                        typeAliasMap[to] = aliasSet;
                                    }
                                    aliasSet.Add(from);
                                }
                            }
                        }
                    }

                    // reverse bcp type alias map
                    IDictionary <string, ISet <string> > bcpTypeAliasMap = null;
                    if (bcpTypeAliasRes != null)
                    {
                        UResourceBundle bcpTypeAliasResByKey = null;
                        try
                        {
                            bcpTypeAliasResByKey = bcpTypeAliasRes.Get(bcpKeyId);
                        }
                        catch (MissingManifestResourceException)
                        {
                            // fall through
                        }
                        if (bcpTypeAliasResByKey != null)
                        {
                            bcpTypeAliasMap = new Dictionary <string, ISet <string> >();
                            using (UResourceBundleEnumerator bcpTypeAliasResItr = bcpTypeAliasResByKey.GetEnumerator())
                            {
                                while (bcpTypeAliasResItr.MoveNext())
                                {
                                    UResourceBundle bcpTypeAliasDataEntry = bcpTypeAliasResItr.Current;
                                    string          from = bcpTypeAliasDataEntry.Key;
                                    string          to   = bcpTypeAliasDataEntry.GetString();
                                    if (!bcpTypeAliasMap.TryGetValue(to, out ISet <string> aliasSet) || aliasSet == null)
                                    {
                                        aliasSet            = new JCG.HashSet <string>();
                                        bcpTypeAliasMap[to] = aliasSet;
                                    }
                                    aliasSet.Add(from);
                                }
                            }
                        }
                    }

                    IDictionary <string, Type> typeDataMap    = new Dictionary <string, Type>();
                    ISet <SpecialType>         specialTypeSet = null;

                    // look up type map for the key, and walk through the mapping data
                    UResourceBundle typeMapResByKey = null;
                    try
                    {
                        typeMapResByKey = typeMapRes.Get(legacyKeyId);
                    }
                    catch (MissingManifestResourceException)
                    {
                        // type map for each key must exist
                        Debug.Assert(false);
                    }
                    if (typeMapResByKey != null)
                    {
                        using (UResourceBundleEnumerator typeMapResByKeyItr = typeMapResByKey.GetEnumerator())
                            while (typeMapResByKeyItr.MoveNext())
                            {
                                UResourceBundle typeMapEntry = typeMapResByKeyItr.Current;
                                string          legacyTypeId = typeMapEntry.Key;
                                string          bcpTypeId    = typeMapEntry.GetString();

                                // special types
                                char first         = legacyTypeId[0];
                                bool isSpecialType = '9' < first && first < 'a' && bcpTypeId.Length == 0;
                                if (isSpecialType)
                                {
                                    if (specialTypeSet == null)
                                    {
                                        specialTypeSet = new JCG.HashSet <SpecialType>();
                                    }
                                    specialTypeSet.Add((SpecialType)Enum.Parse(typeof(SpecialType), legacyTypeId, true));
                                    _bcp47Types.Add(legacyTypeId);
                                    continue;
                                }

                                if (isTZ)
                                {
                                    // a timezone key uses a colon instead of a slash in the resource.
                                    // e.g. America:Los_Angeles
                                    legacyTypeId = legacyTypeId.Replace(':', '/');
                                }

                                bool hasSameType = false;
                                if (bcpTypeId.Length == 0)
                                {
                                    // Empty value indicates that BCP type is same with the legacy type.
                                    bcpTypeId   = legacyTypeId;
                                    hasSameType = true;
                                }
                                _bcp47Types.Add(bcpTypeId);

                                // Note: legacy type value should never be
                                // equivalent to bcp type value of a different
                                // type under the same key. So we use a single
                                // map for lookup.
                                Type t = new Type(legacyTypeId, bcpTypeId);
                                typeDataMap[AsciiUtil.ToLower(legacyTypeId)] = t;
                                if (!hasSameType)
                                {
                                    typeDataMap[AsciiUtil.ToLower(bcpTypeId)] = t;
                                }

                                // Also put aliases in the map
                                if (typeAliasMap != null)
                                {
                                    if (typeAliasMap.TryGetValue(legacyTypeId, out ISet <string> typeAliasSet) && typeAliasSet != null)
                                    {
                                        foreach (string alias in typeAliasSet)
                                        {
                                            typeDataMap[AsciiUtil.ToLower(alias)] = t;
                                        }
                                    }
                                }
                                if (bcpTypeAliasMap != null)
                                {
                                    if (bcpTypeAliasMap.TryGetValue(bcpTypeId, out ISet <string> bcpTypeAliasSet) && bcpTypeAliasSet != null)
                                    {
                                        foreach (string alias in bcpTypeAliasSet)
                                        {
                                            typeDataMap[AsciiUtil.ToLower(alias)] = t;
                                        }
                                    }
                                }
                            }
                    }

                    KeyData keyData = new KeyData(legacyKeyId, bcpKeyId, typeDataMap, specialTypeSet);

                    KEYMAP[AsciiUtil.ToLower(legacyKeyId)] = keyData;
                    if (!hasSameKey)
                    {
                        KEYMAP[AsciiUtil.ToLower(bcpKeyId)] = keyData;
                    }
                }

                BCP47_KEYS = _Bcp47Keys.AsReadOnly();
            }
        }