/// <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); }
// 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)); }