All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.artemis.injection.CachedInjector Maven / Gradle / Ivy

There is a newer version: 2.3.0
Show newest version
package com.artemis.injection;

import com.artemis.*;
import com.artemis.utils.reflect.ClassReflection;
import com.artemis.utils.reflect.Field;
import com.artemis.utils.reflect.ReflectionException;

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

/**
 * By default, injects {@link ComponentMapper}, {@link BaseSystem} and {@link Manager} types into systems and
 * managers. Can also inject arbitrary types if registered through {@link WorldConfiguration#register}.
 *
 * Caches all type-information.
 *
 * 

* For greater control over the dependency-resolution, provide a {@link FieldHandler} to {@link #setFieldHandler(FieldHandler)}, * which will be used to resolve dependency values instead. *

* * @author Arni Arent * @author Snorre E. Brekke * @see com.artemis.injection.FieldHandler */ public final class CachedInjector implements Injector { private InjectionCache cache = InjectionCache.sharedCache.get(); private FieldHandler fieldHandler; private Map injectables; @Override public Injector setFieldHandler(FieldHandler fieldHandler) { this.fieldHandler = fieldHandler; return this; } @Override public T getRegistered(String id) { return (T) injectables.get(id); } @Override public T getRegistered(Class id) { return getRegistered(id.getName()); } @Override public void initialize(World world, Map injectables) { this.injectables = injectables; if (fieldHandler == null) { fieldHandler = new FieldHandler(cache); } fieldHandler.initialize(world, injectables); } @Override public boolean isInjectable(Object target) { try { CachedClass cachedClass = cache.getCachedClass(target.getClass()); return cachedClass.wireType == WireType.WIRE; } catch (ReflectionException e) { throw new MundaneWireException("Error while wiring", e); } } @Override public void inject(Object target) throws RuntimeException { try { Class clazz = target.getClass(); CachedClass cachedClass = cache.getCachedClass(clazz); if (cachedClass.wireType == WireType.WIRE) { injectValidFields(target, cachedClass); } else { injectAnnotatedFields(target, cachedClass); } } catch (RuntimeException e ) { throw new MundaneWireException("Error while wiring " + target.getClass().getName(), e); } catch (ReflectionException e) { throw new MundaneWireException("Error while wiring " + target.getClass().getName(), e); } } private void injectValidFields(Object target, CachedClass cachedClass) throws ReflectionException { Field[] declaredFields = getAllInjectableFields(cachedClass); for (int i = 0, s = declaredFields.length; s > i; i++) { injectField(target, declaredFields[i], cachedClass.failOnNull); } } private Field[] getAllInjectableFields(CachedClass cachedClass) { Field[] declaredFields = cachedClass.allFields; if (declaredFields == null) { List fieldList = new ArrayList(); Class clazz = cachedClass.clazz; collectDeclaredInjectableFields(fieldList, clazz); while (cachedClass.injectInherited && (clazz = clazz.getSuperclass()) != Object.class) { collectDeclaredInjectableFields(fieldList, clazz); } cachedClass.allFields = declaredFields = fieldList.toArray(new Field[fieldList.size()]); } return declaredFields; } private void collectDeclaredInjectableFields(List fieldList, Class clazz) { try { if (cache.getCachedClass(clazz).wireType != WireType.SKIPWIRE) { Field[] classFields = ClassReflection.getDeclaredFields(clazz); for (int i = 0; i < classFields.length; i++) { if (isWireable(classFields[i])) { fieldList.add(classFields[i]); } } } } catch (ReflectionException e) { throw new MundaneWireException("Error while wiring", e); } } private boolean isWireable(Field field) { return cache.getCachedField(field).wireType != WireType.SKIPWIRE; } private void injectAnnotatedFields(Object target, CachedClass cachedClass) throws ReflectionException { injectClass(target, cachedClass); } @SuppressWarnings("deprecation") private void injectClass(Object target, CachedClass cachedClass) throws ReflectionException { Field[] declaredFields = getAllInjectableFields(cachedClass); for (int i = 0, s = declaredFields.length; s > i; i++) { Field field = declaredFields[i]; CachedField cachedField = cache.getCachedField(field); if (cachedField.wireType != WireType.IGNORED) { injectField(target, field, cachedField.wireType == WireType.WIRE); } } } @SuppressWarnings("unchecked") private void injectField(Object target, Field field, boolean failOnNotInjected) throws ReflectionException { Class fieldType; try { fieldType = field.getType(); } catch (RuntimeException ignore) { // Swallow exception caused by missing typedata on gwt platfString.format("Failed to inject %s into %s: // %s not registered with world.")orm. // @todo Workaround, awaiting junkdog-ification. Silently failing injections might be undesirable for // users failing to add systems/components to gwt reflection inclusion config. return; } Object resolve = fieldHandler.resolve(fieldType, field); if (resolve != null) { setField(target, field, resolve); } if (resolve == null && failOnNotInjected && cache.getFieldClassType(fieldType) != ClassType.CUSTOM) { throw onFailedInjection(fieldType.getSimpleName(), field); } } private void setField(Object target, Field field, Object fieldValue) throws ReflectionException { field.setAccessible(true); field.set(target, fieldValue); } private MundaneWireException onFailedInjection(String typeName, Field failedInjection) { String error = "Failed to inject " + failedInjection.getType().getName() + " into " + failedInjection.getDeclaringClass().getName() + ": " + typeName + " not registered with world."; return new MundaneWireException(error); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy