Example #1
0
        /// <summary>
        /// Unregister a factory. The first matching registered factory will be
        /// removed from the list. Returns true if a matching factory was removed.
        /// </summary>
        ///
        public bool UnregisterFactory(ICUService.Factory factory)
        {
            if (factory == null)
            {
                throw new NullReferenceException();
            }

            bool result = false;

            try {
                factoryLock.AcquireWrite();
                if (ILOG.J2CsMapping.Collections.Collections.Remove(factories, factory))
                {
                    result = true;
                    ClearCaches();
                }
            } finally {
                factoryLock.ReleaseWrite();
            }

            if (result)
            {
                NotifyChanged();
            }
            return(result);
        }
Example #2
0
        /// <summary>
        /// Return a snapshot of the mapping from display names to visible IDs for
        /// this service. This set will not change as factories are added or removed,
        /// but the supported ids will, so there is no guarantee that all and only
        /// the ids in the returned map will be visible and supported by the service
        /// in subsequent calls, nor is there any guarantee that the current display
        /// names match those in the set. The display names are sorted based on the
        /// comparator provided.
        /// </summary>
        ///
        public SortedList GetDisplayNames(ULocale locale, IComparer com,
                                          String matchID)
        {
            SortedList dncache = null;

            ICUService.LocaleRef xref = dnref;

            if (xref != null)
            {
                dncache = xref.Get(locale, com);
            }

            while (dncache == null)
            {
                lock (this) {
                    if (xref == dnref || dnref == null)
                    {
                        dncache = new SortedList(com);                 // sorted

                        IDictionary m  = GetVisibleIDMap();
                        IIterator   ei = new ILOG.J2CsMapping.Collections.IteratorAdapter(m.GetEnumerator());
                        while (ei.HasNext())
                        {
                            DictionaryEntry    e    = (DictionaryEntry)ei.Next();
                            String             id_0 = (String)((DictionaryEntry)e).Key;
                            ICUService.Factory f    = (ICUService.Factory)((DictionaryEntry)e).Value;
                            ILOG.J2CsMapping.Collections.Collections.Put(dncache, f.GetDisplayName(id_0, locale), id_0);
                        }

                        dncache = /*ILOG.J2CsMapping.Collections.Generics.Collections.UnmodifiableSortedMap(*/ dncache /*)*/;
                        dnref   = new ICUService.LocaleRef(dncache, locale, com);
                    }
                    else
                    {
                        xref    = dnref;
                        dncache = xref.Get(locale, com);
                    }
                }
            }

            ICUService.Key matchKey = CreateKey(matchID);
            if (matchKey == null)
            {
                return(dncache);
            }

            SortedList result = new SortedList(dncache);
            IIterator  iter   = new ILOG.J2CsMapping.Collections.IteratorAdapter(result.GetEnumerator());

            while (iter.HasNext())
            {
                DictionaryEntry e_1 = (DictionaryEntry)iter.Next();
                if (!matchKey.IsFallbackOf((String)((DictionaryEntry)e_1).Value))
                {
                    iter.Remove();
                }
            }
            return(result);
        }
Example #3
0
 /// <summary>
 /// Register a Factory. Returns the factory if the service accepts the
 /// factory, otherwise returns null. The default implementation accepts all
 /// factories.
 /// </summary>
 ///
 public ICUService.Factory  RegisterFactory(ICUService.Factory factory)
 {
     if (factory == null)
     {
         throw new NullReferenceException();
     }
     try {
         factoryLock.AcquireWrite();
         factories.Insert(0, factory);
         ClearCaches();
     } finally {
         factoryLock.ReleaseWrite();
     }
     NotifyChanged();
     return(factory);
 }
Example #4
0
        /// <summary>
        /// Return a map from visible ids to factories.
        /// </summary>
        ///
        private IDictionary GetVisibleIDMap()
        {
            IDictionary   idcache = null;
            WeakReference xref    = idref;

            if (xref != null)
            {
                idcache = (IDictionary)xref.Target;
            }
            while (idcache == null)
            {
                lock (this) {      // or idref-only lock?
                    if (xref == idref || idref == null)
                    {
                        // no other thread updated idref before we got the lock, so
                        // grab the factory list and update it ourselves
                        try {
                            factoryLock.AcquireRead();
                            idcache = new Hashtable();
                            IListIterator lIter = new ILOG.J2CsMapping.Collections.ArrayListIterator(factories, factories.Count);
                            while (lIter.HasPrevious())
                            {
                                ICUService.Factory f = (ICUService.Factory)lIter.Previous();
                                f.UpdateVisibleIDs(idcache);
                            }
                            idcache = ILOG.J2CsMapping.Collections.Collections.UnmodifiableMap(idcache);
                            idref   = new WeakReference(idcache);
                        } finally {
                            factoryLock.ReleaseRead();
                        }
                    }
                    else
                    {
                        // another thread updated idref, but gc may have stepped
                        // in and undone its work, leaving idcache null. If so,
                        // retry.
                        xref    = idref;
                        idcache = (IDictionary)xref.Target;
                    }
                }
            }

            return(idcache);
        }
Example #5
0
        /// <summary>
        /// Given a visible id, return the display name in the requested locale. If
        /// there is no directly supported id corresponding to this id, return null.
        /// </summary>
        ///
        public String GetDisplayName(String id_0, ULocale locale)
        {
            IDictionary m = GetVisibleIDMap();

            ICUService.Factory f = (ICUService.Factory)ILOG.J2CsMapping.Collections.Collections.Get(m, id_0);
            if (f != null)
            {
                return(f.GetDisplayName(id_0, locale));
            }

            ICUService.Key key = CreateKey(id_0);
            while (key.Fallback())
            {
                f = (ICUService.Factory)ILOG.J2CsMapping.Collections.Collections.Get(m, key.CurrentID());
                if (f != null)
                {
                    return(f.GetDisplayName(id_0, locale));
                }
            }

            return(null);
        }
Example #6
0
        // debugging
        // Map hardRef;

        public Object GetKey(ICUService.Key key, String[] actualReturn, ICUService.Factory factory)
        {
            if (factories.Count == 0)
            {
                return(HandleDefault(key, actualReturn));
            }

            if (DEBUG)
            {
                System.Console.Out.WriteLine("Service: " + name + " key: "
                                             + key.CanonicalID());
            }

            ICUService.CacheEntry result = null;
            if (key != null)
            {
                try {
                    // The factory list can't be modified until we're done,
                    // otherwise we might update the cache with an invalid result.
                    // The cache has to stay in synch with the factory list.
                    factoryLock.AcquireRead();

                    IDictionary   cache = null;
                    WeakReference cref  = cacheref;    // copy so we don't need to sync
                                                       // on this
                    if (cref != null)
                    {
                        if (DEBUG)
                        {
                            System.Console.Out.WriteLine("Service " + name + " ref exists");
                        }
                        cache = (IDictionary)cref.Target;
                    }
                    if (cache == null)
                    {
                        if (DEBUG)
                        {
                            System.Console.Out.WriteLine("Service " + name
                                                         + " cache was empty");
                        }
                        // synchronized since additions and queries on the cache
                        // must be atomic
                        // they can be interleaved, though
                        cache = ILOG.J2CsMapping.Collections.Generics.Collections.SynchronizedMap(new Hashtable());
                        // hardRef = cache; // debug
                        cref = new WeakReference(cache);
                    }

                    String    currentDescriptor   = null;
                    ArrayList cacheDescriptorList = null;
                    bool      putInCache          = false;

                    int NDebug = 0;

                    int  startIndex  = 0;
                    int  limit       = factories.Count;
                    bool cacheResult = true;
                    if (factory != null)
                    {
                        for (int i = 0; i < limit; ++i)
                        {
                            if ((Object)factory == factories[i])
                            {
                                startIndex = i + 1;
                                break;
                            }
                        }
                        if (startIndex == 0)
                        {
                            throw new InvalidOperationException("Factory " + factory
                                                                + "not registered with service: " + this);
                        }
                        cacheResult = false;
                    }

                    outer : {
                        do
                        {
                            currentDescriptor = key.CurrentDescriptor();
                            if (DEBUG)
                            {
                                System.Console.Out.WriteLine(name + "[" + NDebug++
                                                             + "] looking for: " + currentDescriptor);
                            }
                            result = (ICUService.CacheEntry)ILOG.J2CsMapping.Collections.Collections.Get(cache, currentDescriptor);
                            if (result != null)
                            {
                                if (DEBUG)
                                {
                                    System.Console.Out.WriteLine(name
                                                                 + " found with descriptor: "
                                                                 + currentDescriptor);
                                }
                                goto gotoouter;
                            }
                            else
                            {
                                if (DEBUG)
                                {
                                    System.Console.Out.WriteLine("did not find: "
                                                                 + currentDescriptor + " in cache");
                                }
                            }

                            // first test of cache failed, so we'll have to update
                            // the cache if we eventually succeed-- that is, if we're
                            // going to update the cache at all.
                            putInCache = cacheResult;

                            // int n = 0;
                            int index = startIndex;
                            while (index < limit)
                            {
                                ICUService.Factory f = (ICUService.Factory)factories[index++];
                                if (DEBUG)
                                {
                                    System.Console.Out.WriteLine("trying factory[" + (index - 1)
                                                                 + "] " + f.ToString());
                                }
                                Object service = f.Create(key, this);
                                if (service != null)
                                {
                                    result = new ICUService.CacheEntry(currentDescriptor, service);
                                    if (DEBUG)
                                    {
                                        System.Console.Out.WriteLine(name
                                                                     + " factory supported: "
                                                                     + currentDescriptor + ", caching");
                                    }
                                    goto gotoouter;
                                }
                                else
                                {
                                    if (DEBUG)
                                    {
                                        System.Console.Out.WriteLine("factory did not support: "
                                                                     + currentDescriptor);
                                    }
                                }
                            }

                            // prepare to load the cache with all additional ids that
                            // will resolve to result, assuming we'll succeed. We
                            // don't want to keep querying on an id that's going to
                            // fallback to the one that succeeded, we want to hit the
                            // cache the first time next goaround.
                            if (cacheDescriptorList == null)
                            {
                                cacheDescriptorList = new ArrayList(5);
                            }
                            ILOG.J2CsMapping.Collections.Generics.Collections.Add(cacheDescriptorList, currentDescriptor);
                        } while (key.Fallback());
                    }
gotoouter:
                    ;

                    if (result != null)
                    {
                        if (putInCache)
                        {
                            if (DEBUG)
                            {
                                System.Console.Out.WriteLine("caching '"
                                                             + result.actualDescriptor + "'");
                            }
                            ILOG.J2CsMapping.Collections.Collections.Put(cache, result.actualDescriptor, result);
                            if (cacheDescriptorList != null)
                            {
                                IIterator iter = new ILOG.J2CsMapping.Collections.IteratorAdapter(cacheDescriptorList.GetEnumerator());
                                while (iter.HasNext())
                                {
                                    String desc = (String)iter.Next();
                                    if (DEBUG)
                                    {
                                        System.Console.Out.WriteLine(name
                                                                     + " adding descriptor: '" + desc
                                                                     + "' for actual: '"
                                                                     + result.actualDescriptor + "'");
                                    }

                                    ILOG.J2CsMapping.Collections.Collections.Put(cache, desc, result);
                                }
                            }
                            // Atomic update. We held the read lock all this time
                            // so we know our cache is consistent with the factory
                            // list.
                            // We might stomp over a cache that some other thread
                            // rebuilt, but that's the breaks. They're both good.
                            cacheref = cref;
                        }

                        if (actualReturn != null)
                        {
                            // strip null prefix
                            if (result.actualDescriptor.IndexOf("/") == 0)
                            {
                                actualReturn[0] = result.actualDescriptor.Substring(1);
                            }
                            else
                            {
                                actualReturn[0] = result.actualDescriptor;
                            }
                        }

                        if (DEBUG)
                        {
                            System.Console.Out.WriteLine("found in service: " + name);
                        }

                        return(result.service);
                    }
                } finally {
                    factoryLock.ReleaseRead();
                }
            }

            if (DEBUG)
            {
                System.Console.Out.WriteLine("not found in service: " + name);
            }

            return(HandleDefault(key, actualReturn));
        }