/*
 * Copyright (C) 2013 salesforce.com, inc.
 *
 * 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 org.auraframework.impl.util.json;

import com.google.common.collect.ImmutableMap;
import org.auraframework.adapter.JsonSerializerAdapter;
import org.auraframework.annotations.Annotations.ServiceComponent;
import org.auraframework.util.json.JsonSerializer;
import org.auraframework.util.json.JsonSerializerFactory;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import java.util.Collection;
import java.util.Map;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * Retrieves Json Serializers
 */
@ServiceComponent
public class AuraJsonSerializerFactory implements JsonSerializerFactory {

    private static Map<String, JsonSerializer<?>> SERIALIZERS_LOOKUP_MAP;
    private static Map<Class<?>, JsonSerializer<?>> SERIALIZERS_INSTANCE_MAP;
    private static final ConcurrentMap<String, JsonSerializer<?>> cache = new ConcurrentHashMap<>();
    private static final Object lock = new Object();

    @Inject
    private Collection<JsonSerializerAdapter> jsonSerializerAdapters;

    @PostConstruct
    private void initSerializerMaps() {
        synchronized (lock) {
            if (SERIALIZERS_LOOKUP_MAP != null) {
                return;
            }
            ImmutableMap.Builder<String, JsonSerializer<?>> b = ImmutableMap.builder();
            ImmutableMap.Builder<Class<?>, JsonSerializer<?>> b2 = ImmutableMap.builder();
            for (JsonSerializerAdapter a : jsonSerializerAdapters) {
                b.putAll(a.lookupSerializers());
                b2.putAll(a.instanceofSerializers());
            }
            SERIALIZERS_LOOKUP_MAP = b.build();
            SERIALIZERS_INSTANCE_MAP = b2.build();
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public <T> JsonSerializer<T> getSerializer(T o) {
        Class<?> c = o.getClass();
        JsonSerializer<T> s = (JsonSerializer<T>) cache.get(c.getName());
        if (s != null) {
            return s;
        }

        if (SERIALIZERS_INSTANCE_MAP == null) {
            initSerializerMaps();
        }

        String className = c.getName();
        s = (JsonSerializer<T>) SERIALIZERS_LOOKUP_MAP.get(className);
        if (s != null) {
            cache.putIfAbsent(className, s);
            return s;
        }

        for (Map.Entry<Class<?>, JsonSerializer<?>> e : SERIALIZERS_INSTANCE_MAP.entrySet()) {
            if (e.getKey().isAssignableFrom(c)) {
                s = (JsonSerializer<T>) e.getValue();
                cache.putIfAbsent(className, s);
                return s;
            }
        }
        return null;
    }
}

@@ -659,47 +659,210 @@
 ort 
-com.google.common.collect.ImmutableMap;
+java.util.Collection;%0Aimport java.util.Map;%0Aimport java.util.concurrent.ConcurrentHashMap;%0Aimport java.util.concurrent.ConcurrentMap;%0A%0Aimport javax.annotation.PostConstruct;%0Aimport javax.inject.Inject;%0A
 %0Aimp
@@ -981,16 +981,123 @@
 ponent;%0A
+import org.auraframework.service.LoggingService;%0Aimport org.auraframework.util.json.DefaultJsonSerializer;%0A
 import o
@@ -1209,205 +1209,43 @@
 ort 
-javax.annotation.PostConstruct;%0Aimport javax.inject.Inject;%0Aimport java.util.Collection;%0Aimport java.util.Map;%0A%0Aimport java.util.concurrent.ConcurrentHashMap;%0Aimport java.util.concurrent.Concurrent
+com.google.common.collect.Immutable
 Map;
@@ -1659,36 +1659,177 @@
 nal 
-Object lock = new Object();%0A
+JsonSerializer NOT_FOUND = new DefaultJsonSerializer();%0A    private static final Object lock = new Object();%0A%0A    @Inject%0A    private LoggingService loggingService;%0A    
 %0A   
@@ -2700,24 +2700,64 @@
 getClass();%0A
+        String className = c.getName();%0A
         Json
@@ -2805,26 +2805,24 @@
 he.get(c
-.get
+lass
 Name
-()
 );%0A     
@@ -2852,33 +2852,58 @@
          return 
-s
+(s != NOT_FOUND)? s : null
 ;%0A        %7D%0A%0A   
@@ -2996,48 +2996,8 @@
  %7D%0A%0A
-        String className = c.getName();%0A
     
@@ -3455,32 +3455,155 @@
      %7D%0A        %7D
+%0A%0A        cache.putIfAbsent(className, NOT_FOUND);%0A        loggingService.info(%22no JsonSerializer found for:%22 + className);
 %0A        return 

Optimize AuraJsonSerializerFactory.java @bug W-3502874@ @rev goliver@