ICUService.java 12 KB
/*
 * Decompiled with CFR 0_118.
 */
package com.adobe.agl.impl;

import com.adobe.agl.impl.ICUDebug;
import com.adobe.agl.impl.ICUNotifier;
import com.adobe.agl.impl.ICURWLock;
import com.adobe.agl.util.ULocale;

import java.lang.ref.SoftReference;
import java.util.*;

public class ICUService
extends ICUNotifier {
    protected final String name;
    private static final boolean DEBUG = ICUDebug.enabled("service");
    private final ICURWLock factoryLock = new ICURWLock();
    private final List factories = new ArrayList();
    private int defaultSize = 0;
    private SoftReference cacheref;
    private SoftReference idref;
    private LocaleRef dnref;

    public ICUService(String name) {
        this.name = name;
    }

    public Object getKey(Key key) {
        return this.getKey(key, null);
    }

    public Object getKey(Key key, String[] actualReturn) {
        return this.getKey(key, actualReturn, null);
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    public Object getKey(Key key, String[] actualReturn, Factory factory) {
        if (this.factories.size() == 0) {
            return this.handleDefault(key, actualReturn);
        }
        if (DEBUG) {
            System.out.println("Service: " + this.name + " key: " + key.canonicalID());
        }
        CacheEntry result = null;
        if (key != null) {
            try {
                this.factoryLock.acquireRead();
                Map<String, CacheEntry> cache = null;
                SoftReference cref = this.cacheref;
                if (cref != null) {
                    if (DEBUG) {
                        System.out.println("Service " + this.name + " ref exists");
                    }
                    cache = (Map<String, CacheEntry>)cref.get();
                }
                if (cache == null) {
                    if (DEBUG) {
                        System.out.println("Service " + this.name + " cache was empty");
                    }
                    cache = Collections.synchronizedMap(new HashMap());
                    cref = new SoftReference(cache);
                }
                String currentDescriptor = null;
                ArrayList<String> cacheDescriptorList = null;
                boolean putInCache = false;
                int NDebug = 0;
                int startIndex = 0;
                int limit = this.factories.size();
                boolean cacheResult = true;
                if (factory != null) {
                    for (int i = 0; i < limit; ++i) {
                        if (factory != this.factories.get(i)) continue;
                        startIndex = i + 1;
                        break;
                    }
                    if (startIndex == 0) {
                        throw new IllegalStateException("Factory " + factory + "not registered with service: " + this);
                    }
                    cacheResult = false;
                }
                block4 : do {
                    currentDescriptor = key.currentDescriptor();
                    if (DEBUG) {
                        System.out.println(this.name + "[" + NDebug++ + "] looking for: " + currentDescriptor);
                    }
                    if ((result = (CacheEntry)cache.get(currentDescriptor)) != null) {
                        if (!DEBUG) break;
                        System.out.println(this.name + " found with descriptor: " + currentDescriptor);
                        break;
                    }
                    if (DEBUG) {
                        System.out.println("did not find: " + currentDescriptor + " in cache");
                    }
                    putInCache = cacheResult;
                    int index = startIndex;
                    while (index < limit) {
                        Object service;
                        Factory f = (Factory)this.factories.get(index++);
                        if (DEBUG) {
                            System.out.println("trying factory[" + (index - 1) + "] " + f.toString());
                        }
                        if ((service = f.create(key, this)) != null) {
                            result = new CacheEntry(currentDescriptor, service);
                            if (!DEBUG) break block4;
                            System.out.println(this.name + " factory supported: " + currentDescriptor + ", caching");
                            break block4;
                        }
                        if (!DEBUG) continue;
                        System.out.println("factory did not support: " + currentDescriptor);
                    }
                    if (cacheDescriptorList == null) {
                        cacheDescriptorList = new ArrayList<String>(5);
                    }
                    cacheDescriptorList.add(currentDescriptor);
                } while (key.fallback());
                if (result != null) {
                    if (putInCache) {
                        if (DEBUG) {
                            System.out.println("caching '" + result.actualDescriptor + "'");
                        }
                        cache.put(result.actualDescriptor, result);
                        if (cacheDescriptorList != null) {
                            Iterator iter = cacheDescriptorList.iterator();
                            while (iter.hasNext()) {
                                String desc = (String)iter.next();
                                if (DEBUG) {
                                    System.out.println(this.name + " adding descriptor: '" + desc + "' for actual: '" + result.actualDescriptor + "'");
                                }
                                cache.put(desc, result);
                            }
                        }
                        this.cacheref = cref;
                    }
                    if (actualReturn != null) {
                        actualReturn[0] = result.actualDescriptor.indexOf("/") == 0 ? result.actualDescriptor.substring(1) : result.actualDescriptor;
                    }
                    if (DEBUG) {
                        System.out.println("found in service: " + this.name);
                    }
                    Object iter = result.service;
                    return iter;
                }
            }
            finally {
                this.factoryLock.releaseRead();
            }
        }
        if (DEBUG) {
            System.out.println("not found in service: " + this.name);
        }
        return this.handleDefault(key, actualReturn);
    }

    protected Object handleDefault(Key key, String[] actualIDReturn) {
        return null;
    }

    public Set getVisibleIDs() {
        return this.getVisibleIDs(null);
    }

    public Set getVisibleIDs(String matchID) {
        Set result = this.getVisibleIDMap().keySet();
        Key fallbackKey = this.createKey(matchID);
        if (fallbackKey != null) {
            HashSet temp = new HashSet(result.size());
            Iterator iter = result.iterator();
            while (iter.hasNext()) {
                String id = (String)iter.next();
                if (!fallbackKey.isFallbackOf(id)) continue;
                temp.add((String)id);
            }
            result = temp;
        }
        return result;
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    private Map getVisibleIDMap() {
        Map idcache = null;
        SoftReference ref = this.idref;
        if (ref != null) {
            idcache = (HashMap)ref.get();
        }
        while (idcache == null) {
            ICUService iCUService = this;
            synchronized (iCUService) {
                if (ref == this.idref || this.idref == null) {
                    try {
                        this.factoryLock.acquireRead();
                        idcache = new HashMap();
                        ListIterator lIter = this.factories.listIterator(this.factories.size());
                        while (lIter.hasPrevious()) {
                            Factory f = (Factory)lIter.previous();
                            f.updateVisibleIDs(idcache);
                        }
                        idcache = Collections.unmodifiableMap(idcache);
                        this.idref = new SoftReference(idcache);
                    }
                    finally {
                        this.factoryLock.releaseRead();
                    }
                }
                ref = this.idref;
                idcache = (Map)ref.get();
                continue;
            }
        }
        return idcache;
    }

    public String getDisplayName(String id, ULocale locale) {
        Map m = this.getVisibleIDMap();
        Factory f = (Factory)m.get(id);
        if (f != null) {
            return f.getDisplayName(id, locale);
        }
        Key key = this.createKey(id);
        while (key.fallback()) {
            f = (Factory)m.get(key.currentID());
            if (f == null) continue;
            return f.getDisplayName(id, locale);
        }
        return null;
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    public final Factory registerFactory(Factory factory) {
        if (factory == null) {
            throw new NullPointerException();
        }
        try {
            this.factoryLock.acquireWrite();
            this.factories.add(0, factory);
            this.clearCaches();
        }
        finally {
            this.factoryLock.releaseWrite();
        }
        this.notifyChanged();
        return factory;
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    public final boolean unregisterFactory(Factory factory) {
        boolean result;
        if (factory == null) {
            throw new NullPointerException();
        }
        result = false;
        try {
            this.factoryLock.acquireWrite();
            if (this.factories.remove(factory)) {
                result = true;
                this.clearCaches();
            }
        }
        finally {
            this.factoryLock.releaseWrite();
        }
        if (result) {
            this.notifyChanged();
        }
        return result;
    }

    public boolean isDefault() {
        return this.factories.size() == this.defaultSize;
    }

    protected void markDefault() {
        this.defaultSize = this.factories.size();
    }

    public Key createKey(String id) {
        return id == null ? null : new Key(id);
    }

    protected void clearCaches() {
        this.cacheref = null;
        this.idref = null;
        this.dnref = null;
    }

    protected void clearServiceCache() {
        this.cacheref = null;
    }

    protected void notifyListener(EventListener l) {
        ((ServiceListener)l).serviceChanged(this);
    }

    public String toString() {
        return Object.super.toString() + "{" + this.name + "}";
    }

    public static interface ServiceListener
    extends EventListener {
        public void serviceChanged(ICUService var1);
    }

    private static class LocaleRef {
    }

    private static final class CacheEntry {
        final String actualDescriptor;
        final Object service;

        CacheEntry(String actualDescriptor, Object service) {
            this.actualDescriptor = actualDescriptor;
            this.service = service;
        }
    }

    public static interface Factory {
        public Object create(Key var1, ICUService var2);

        public void updateVisibleIDs(Map var1);

        public String getDisplayName(String var1, ULocale var2);
    }

    public static class Key {
        private final String id;

        public Key(String id) {
            this.id = id;
        }

        public String canonicalID() {
            return this.id;
        }

        public String currentID() {
            return this.canonicalID();
        }

        public String currentDescriptor() {
            return "/" + this.currentID();
        }

        public boolean fallback() {
            return false;
        }

        public boolean isFallbackOf(String idToCheck) {
            return this.canonicalID().equals(idToCheck);
        }
    }

}