1 /* 2 * Entreri, an entity-component framework in Java 3 * 4 * Copyright (c) 2013, Michael Ludwig 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without modification, 8 * are permitted provided that the following conditions are met: 9 * 10 * Redistributions of source code must retain the above copyright notice, 11 * this list of conditions and the following disclaimer. 12 * Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 23 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 package com.lhkbob.entreri.impl; 28 29 import com.lhkbob.entreri.Component; 30 31 import java.util.HashMap; 32 import java.util.Map; 33 34 /** 35 * CachingDelegatingFactoryProvider implements the ComponentFactoryProvider interface to 36 * delegate to a list of factory providers and caches their created factories in a thread 37 * safe manner so that actual implementations can be implemented simpler. 38 * 39 * @author Michael Ludwig 40 */ 41 public class CachingDelegatingFactoryProvider extends ComponentFactoryProvider { 42 private final Map<Class<? extends Component>, Factory<?>> cachedFactories; 43 44 private final CompiledFactoryProvider compiledFactoryProvider; 45 46 private final Object lock; 47 48 public CachingDelegatingFactoryProvider() { 49 cachedFactories = new HashMap<Class<? extends Component>, Factory<? extends Component>>(); 50 compiledFactoryProvider = new CompiledFactoryProvider(); 51 52 lock = new Object(); 53 } 54 55 @Override 56 @SuppressWarnings("unchecked") 57 public <T extends Component> Factory<T> getFactory(Class<T> componentType) { 58 // blocking synchronization is easiest to do and it shouldn't be a high contention 59 // point because factories are only gotten when the component repository is created 60 // the first time for a system and type 61 synchronized (lock) { 62 Factory<?> cached = cachedFactories.get(componentType); 63 if (cached != null) { 64 return (Factory<T>) cached; 65 } 66 67 Factory<T> precompiled = compiledFactoryProvider.getFactory(componentType); 68 if (precompiled != null) { 69 cachedFactories.put(componentType, precompiled); 70 return precompiled; 71 } 72 } 73 74 throw new UnsupportedOperationException( 75 "Unable to find or generate a component implementation for " + 76 componentType); 77 } 78 }