package org.javarosa.core.services;

import org.javarosa.core.util.externalizable.CannotCreateObjectException;
import org.javarosa.core.util.externalizable.PrototypeFactory;

import java.util.HashSet;

public class PrototypeManager {
    private static final HashSet<String> prototypes = new HashSet<>();
    private static PrototypeFactory staticDefault;

    public static void registerPrototype(String className) {
        prototypes.add(className);

        try {
            PrototypeFactory.getInstance(Class.forName(className));
        } catch (ClassNotFoundException e) {
            throw new CannotCreateObjectException(className + ": not found");
        }
        rebuild();
    }

    public static void registerPrototypes(String[] classNames) {
        for (String className : classNames) {
            registerPrototype(className);
        }
    }

    public static PrototypeFactory getDefault() {
        if (staticDefault == null) {
            rebuild();
        }
        return staticDefault;
    }

    private static void rebuild() {
        if (staticDefault == null) {
            staticDefault = new PrototypeFactory(prototypes);
            return;
        }
        synchronized (staticDefault) {
            staticDefault = new PrototypeFactory(prototypes);
        }
    }

}

@@ -268,17 +268,23 @@
 String%3E 
-p
+globalP
 rototype
@@ -300,24 +300,25 @@
 ashSet%3C%3E();%0A
+%0A
     private 
@@ -328,39 +328,476 @@
 tic 
-PrototypeFactory staticDefault;
+final ThreadLocal%3CPrototypeFactory%3E threadLocalPrototypeFactory = new ThreadLocal%3CPrototypeFactory%3E()%7B%0A        @Override%0A        protected PrototypeFactory initialValue()%0A        %7B%0A            return null;%0A        %7D%0A    %7D;%0A%0A    private static PrototypeFactory globalStaticDefault;%0A%0A    private static boolean useThreadLocalStrategy = false;%0A%0A    public static void useThreadLocalStrategy(boolean useThreadLocal) %7B%0A        useThreadLocalStrategy = useThreadLocal;%0A    %7D
 %0A%0A  
@@ -863,17 +863,23 @@
         
-p
+globalP
 rototype
@@ -1300,32 +1300,261 @@
        %7D%0A    %7D%0A%0A
+    private static PrototypeFactory getCurrentStaticFactory() %7B%0A        if(useThreadLocalStrategy) %7B%0A            return threadLocalPrototypeFactory.get();%0A        %7D else %7B%0A            return globalStaticDefault;%0A        %7D%0A    %7D%0A%0A
     public stati
@@ -1595,37 +1595,49 @@
         if (
-staticDefault
+getCurrentStaticFactory()
  == null) %7B%0A
@@ -1684,29 +1684,41 @@
  return 
-staticDefault
+getCurrentStaticFactory()
 ;%0A    %7D%0A
@@ -1766,50 +1766,318 @@
     
-if (staticDefault == null) %7B%0A            s
+PrototypeFactory currentStaticFactory = getCurrentStaticFactory();%0A        if (currentStaticFactory == null) %7B%0A            if(useThreadLocalStrategy) %7B%0A                threadLocalPrototypeFactory.set(new PrototypeFactory((HashSet%3CString%3E)globalPrototypes.clone()));%0A            %7D else %7B%0A                globalS
 tati
@@ -2100,33 +2100,39 @@
 rototypeFactory(
-p
+globalP
 rototypes);%0A    
@@ -2119,32 +2119,46 @@
 balPrototypes);%0A
+            %7D%0A
             retu
@@ -2197,38 +2197,231 @@
 ed (
-staticDefault) %7B%0A            s
+currentStaticFactory) %7B%0A            if(useThreadLocalStrategy) %7B%0A                threadLocalPrototypeFactory.set(new PrototypeFactory((HashSet%3CString%3E)globalPrototypes.clone()));%0A            %7D else %7B%0A                globalS
 tati
@@ -2452,17 +2452,23 @@
 Factory(
-p
+globalP
 rototype
@@ -2463,32 +2463,46 @@
 balPrototypes);%0A
+            %7D%0A
         %7D%0A    %7D%0A
@@ -2503,9 +2503,8 @@
     %7D%0A%0A%7D
-%0A

Enable a thread local strategy for the prototype manager