com.artemis.injection.FieldHandler Maven / Gradle / Ivy
Show all versions of artemis-odb Show documentation
package com.artemis.injection;
import com.artemis.InjectionException;
import com.artemis.World;
import com.artemis.utils.Bag;
import com.artemis.utils.reflect.ClassReflection;
import com.artemis.utils.reflect.Field;
import java.util.Map;
/**
* FieldHandler provides dependency-values to an {@link com.artemis.injection.Injector}
* by sequentially iterating over a list of registered {@link FieldResolver}.
*
* The method {@link #resolve(Class, Field)} will return the first non-null value provided by
* {@link FieldResolver#resolve(Class, Field)}, or null if no resolver returned a valid value.
*
*
* During {@link World} construction, after systems and managers have been created, {@link #initialize(World)}
* will be called for each registered {@link FieldResolver}
*
*
* If {@link FieldResolver} implements {@link UseInjectionCache}, {@link UseInjectionCache#setCache(InjectionCache)}
* will be called prior to {@link FieldResolver#initialize(World)} being called, availing the {@link InjectionCache}
* used by this handler.
*
*
* @author Snorre E. Brekke
*/
public class FieldHandler {
private InjectionCache cache;
protected Bag fieldResolvers;
/**
* Constructs a new FieldHandler with the provided fieldResolvers. This constructor should be used when full
* control over the {@link FieldResolver} order is required.
*
* For Artemis to function correctly, {@link ArtemisFieldResolver} should be added somewhere in the bag, or
* added via {@link #addFieldResolver(FieldResolver)} prior to world construction.
*
*
* @param cache used for better reflection-speed.
* @param fieldResolvers bag of fieldresolver this FieldHandler should use.
* @see ArtemisFieldResolver
*/
public FieldHandler(InjectionCache cache, Bag fieldResolvers) {
this.cache = cache;
this.fieldResolvers = fieldResolvers;
}
/**
* Constructs a ned FieldHandler with an {@link ArtemisFieldResolver} and {@link WiredFieldResolver}
* already registered, which can resolve {@link com.artemis.ComponentMapper}, {@link com.artemis.BaseSystem}
* and {@link com.artemis.Manager} types registered in the {@link World}
* {@link com.artemis.annotations.Wire}.
*
* @param cache used for better reflection-speed.
* @see ArtemisFieldResolver
*/
public FieldHandler(InjectionCache cache) {
this.fieldResolvers = new Bag(FieldResolver.class);
this.cache = cache;
addFieldResolver(new ArtemisFieldResolver());
addFieldResolver(new AspectFieldResolver());
addFieldResolver(new WiredFieldResolver());
}
/**
* During {@link World} construction, after systems and managers have been created, {@link #initialize(World)}
* will be called for each registered {@link FieldResolver}
*
*
* If {@link FieldResolver} implements {@link UseInjectionCache}, {@link UseInjectionCache#setCache(InjectionCache)}
* will be called prior to {@link FieldResolver#initialize(World)} being called, availing the {@link InjectionCache}
* used by this handler.
*
* @param world the world this FieldHandler is being used for
* @throws com.artemis.WorldConfigurationException when injector has no way to deal with injectables.
*/
public void initialize(World world, Map injectables) {
boolean fieldResolverFound = false;
for (int i = 0, s = fieldResolvers.size(); i < s; i++) {
FieldResolver fieldResolver = fieldResolvers.get(i);
if (ClassReflection.isInstance(UseInjectionCache.class, fieldResolver)) {
((UseInjectionCache) fieldResolver).setCache(cache);
}
if (ClassReflection.isInstance(PojoFieldResolver.class, fieldResolver)) {
((PojoFieldResolver) fieldResolver).setPojos(injectables);
fieldResolverFound = true;
}
fieldResolver.initialize(world);
}
if ( injectables != null && !injectables.isEmpty() && !fieldResolverFound )
{
throw new InjectionException("FieldHandler lacks resolver capable of dealing with your custom injectables. Register a WiredFieldResolver or PojoFieldResolver with your FieldHandler.");
}
}
/**
* Returns the first non-null value provided by
* {@link FieldResolver#resolve(Class, Field)}, or null if no resolver returned a valid value.
*
* @param fieldType class of the field
* @param field field for which a value should be resolved
* @return a non-null value if any {@link FieldResolver} could provide an instance
* for the {@code field}, null if the {@code field} could not be resolved
*/
public Object resolve(Class> fieldType, Field field) {
for (int i = 0, s = fieldResolvers.size(); i < s; i++) {
Object resolved = fieldResolvers.get(i).resolve(fieldType, field);
if (resolved != null) {
return resolved;
}
}
return null;
}
/**
* Adds a {@link FieldResolver} to this handler. Resolvers added first, will be used first for resolving fields,
* so the order of add operations is significant.
*
* @param fieldResolver is added to this FieldHandler fieldresolver-list
*/
public final void addFieldResolver(FieldResolver fieldResolver) {
fieldResolvers.add(fieldResolver);
}
public Bag getFieldResolvers() {
return fieldResolvers;
}
}