Skip to content

Commit

Permalink
Added Retriever injection
Browse files Browse the repository at this point in the history
  • Loading branch information
Zomis committed Sep 19, 2014
1 parent 253f036 commit 03bfcf8
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package net.zomis.cardshifter.ecs.base;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(value = RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Retriever {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package net.zomis.cardshifter.ecs.base;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(value = RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface RetrieverSingleton {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package net.zomis.cardshifter.ecs.base;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Set;

public class Retrievers {

public static <T extends Component> ComponentRetriever<T> component(Class<T> clazz) {
return new ComponentRetriever<>(clazz);
}

public static <T extends Component> ComponentRetriever<T> singleton(Class<T> class1) {
return new ComponentRetriever<T>(null) {

@Override
public boolean has(Entity entity) {
return get(entity) != null;
}

@Override
public T get(Entity entity) {
return singleton(entity.getGame(), class1);
}

};
}

public static <T extends Component> T singleton(ECSGame game, Class<T> class1) {
Set<Entity> all = game.getEntitiesWithComponent(class1);
if (all.size() != 1) {
throw new IllegalStateException("Expected to find exactly one " + class1.getSimpleName() + ", found " + all.size());
}
return all.iterator().next().getComponent(class1);
}

public static void inject(Object object, ECSGame game) {
Field[] fields = object.getClass().getDeclaredFields();
Arrays.stream(fields).filter(field -> field.getAnnotation(Retriever.class) != null).forEach(field -> injectField(object, field, game));
Arrays.stream(fields).filter(field -> field.getAnnotation(RetrieverSingleton.class) != null).forEach(field -> injectSingleton(object, field, game));
}

private static void injectSingleton(Object obj, Field field, ECSGame game) {
Class<? extends Component> clazz = field.getType().asSubclass(Component.class);
field.setAccessible(true);
try {
field.set(obj, Retrievers.singleton(game, clazz));
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}

private static void injectField(Object obj, Field field, ECSGame game) {
if (field.getType() != ComponentRetriever.class) {
throw new RuntimeException(field.getType() + " is not a ComponentRetriever");
}

Type genericFieldType = field.getGenericType();

if(genericFieldType instanceof ParameterizedType){
ParameterizedType aType = (ParameterizedType) genericFieldType;
Type[] fieldArgTypes = aType.getActualTypeArguments();
Class<?> fieldArgClass = (Class<?>) fieldArgTypes[0];
try {
field.setAccessible(true);
field.set(obj, Retrievers.component(fieldArgClass.asSubclass(Component.class)));
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package net.zomis.cardshifter.ecs;

import static org.junit.Assert.*;
import net.zomis.cardshifter.ecs.base.ComponentRetriever;
import net.zomis.cardshifter.ecs.base.ECSGame;
import net.zomis.cardshifter.ecs.base.Entity;
import net.zomis.cardshifter.ecs.base.Retriever;
import net.zomis.cardshifter.ecs.base.RetrieverSingleton;
import net.zomis.cardshifter.ecs.base.Retrievers;
import net.zomis.cardshifter.ecs.components.PlayerComponent;
import net.zomis.cardshifter.ecs.phase.Phase;
import net.zomis.cardshifter.ecs.phase.PhaseController;

import org.junit.Test;

public class InjectionTest {

@RetrieverSingleton
private PhaseController phases;

@Retriever
private ComponentRetriever<PlayerComponent> playerData;

@Test
public void inject() {
ECSGame game = new ECSGame();
PhaseController phase = new PhaseController();
phase.addPhase(new Phase(null, "Main"));
game.newEntity().addComponent(phase);
Entity player = game.newEntity().addComponent(new PlayerComponent(42, "Tester"));

Retrievers.inject(this, game);

assertEquals(42, playerData.get(player).getIndex());
assertEquals(phase, phases);
assertEquals("Main", phases.getCurrentPhase().getName());
}

}

0 comments on commit 03bfcf8

Please sign in to comment.