package org.nuunframework.ensemble;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.List;
import org.fest.util.Collections;
import org.nuunframework.ensemble.engine.Actor;
import org.nuunframework.ensemble.engine.EnsemblePlayer;
import org.nuunframework.ensemble.engine.EnsembleRecording;
import org.nuunframework.ensemble.engine.Role;
import org.nuunframework.ensemble.engine.TypeTuple;
import org.nuunframework.ensemble.util.Assert;
import org.nuunframework.ensemble.util.Types;
public class Conductor
{
@SuppressWarnings("rawtypes")
Map<TypeTuple, Ensemble> tuples;
public Conductor()
{
tuples = new HashMap<TypeTuple, Ensemble>();
}
public boolean addEnsemble(Ensemble ensemble)
{
TypeTuple key = TypeTuple.of(ensemble.roleClasses()).build();
tuples.put(key, ensemble);
return (Boolean) true;
}
@SuppressWarnings("rawtypes")
public <D> void conduct(Object... inputs) {
// Get input types
Class<?> types[] = new Class[inputs.length];
for (int i = 0 ; i < inputs.length ; i ++)
{
if (! (inputs[i] instanceof Class))
{
types[i] = inputs[i].getClass();
}
else
{
types[i] = (Class<?>) inputs[i];
}
}
// Retrieve the ensemble from this key/combination
TypeTuple key = TypeTuple.of( types ).build();
Ensemble ensemble = tuples.get(key);
Assert.notNull(ensemble, "No ensemble for this formation");
// Let's listen the ensemble play
Method methodForConfigure = Types.methodFor(Ensemble.class, "play");
methodForConfigure.setAccessible(true);
try
{
methodForConfigure.invoke(ensemble); // ensemble.play()
}
catch (Exception e)
{
throw new IllegalStateException("Error when configuring Ensemble", e);
}
// Compute the set of actors (role + instance)
Role[] roles = ensemble.roles();
Set<Actor> actors = new HashSet<Actor>();
for (int i = 0 ; i < inputs.length ; i++)
{
Actor actor = new Actor(roles[i], inputs[i]);
actors.add(actor);
}
EnsemblePlayer player = new EnsemblePlayer(ensemble , actors );
player.run();
}
}