// Copyright 2011 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.hughes.android.dictionary.engine;

import com.ibm.icu.text.Transliterator;

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

import com.hughes.util.LRUCacheMap;

public class TransliteratorManager {

    private static boolean starting = false;
    private static boolean ready = false;
    private static LRUCacheMap<String, Transliterator> cache = new LRUCacheMap<String, Transliterator>(4);

    // Whom to notify when we're all set up and ready to go.
    private static List<Callback> callbacks = new ArrayList<TransliteratorManager.Callback>();

    public static synchronized Transliterator get(String rules) {
        Transliterator result = cache.get(rules);
        if (result == null) {
            result = Transliterator.createFromRules("", rules, Transliterator.FORWARD);
            cache.put(rules, result);
        }
        return result;
    }

    public static synchronized boolean init(final Callback callback) {
        if (ready) {
            return true;
        }
        if (callback != null) {
            callbacks.add(callback);
        }
        if (!starting) {
            starting = true;
            new Thread(init).start();
        }
        return false;
    }

    private static final Runnable init = new Runnable() {
        @Override
        public void run() {
            System.out.println("Starting Transliterator load.");
            final String transliterated = get(Language.en.getDefaultNormalizerRules()).transliterate("Îñţérñåţîöñåļîžåţîờñ");
            if (!"internationalization".equals(transliterated)) {
                System.out.println("Wrong transliteration: " + transliterated);
            }

            final List<Callback> callbacks = new ArrayList<TransliteratorManager.Callback>();
            synchronized (TransliteratorManager.class) {
                callbacks.addAll(TransliteratorManager.callbacks);
                ready = true;
            }
            for (final Callback callback : callbacks) {
                callback.onTransliteratorReady();
            }
        }
    };

    public interface Callback {
        void onTransliteratorReady();
    }

}

@@ -1192,78 +1192,352 @@
 tic 
-synchronized Transliterator get(String rules) %7B%0A        Transliterator
+Transliterator get(String rules) %7B%0A        // DO NOT make the method synchronized!%0A        // synchronizing on the class would break the whole%0A        // asynchronous init concept, since the runnable%0A        // then holds the same lock as the init function needs.%0A        Transliterator result = null;%0A        synchronized (cache) %7B%0A           
  res
@@ -1556,24 +1556,28 @@
 get(rules);%0A
+    
         if (
@@ -1598,32 +1598,36 @@
 ) %7B%0A            
+  
+  
 result = Transli
@@ -1698,16 +1698,20 @@
         
+    
 cache.pu
@@ -1728,16 +1728,30 @@
 esult);%0A
+            %7D%0A
         

Fix too course locking that broke startup optimization.