/*******************************************************************************
* TurtleKit 3 - Agent Based and Artificial Life Simulation Platform
* Copyright (C) 2011-2014 Fabien Michel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
/*
* Copyright 1997-2011 Fabien Michel, Olivier Gutknecht, Jacques Ferber
*
* This file is part of MadKit.
*
* MadKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MadKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with MadKit. If not, see <http://www.gnu.org/licenses/>.
*/
package turtlekit.kernel;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import madkit.kernel.Activator;
import madkit.simulation.SimulationException;
import turtlekit.agr.TKOrganization;
/**
* The turtle activator : allow to make the turtles work like finite state automata.
*
* @author Fabien Michel
* @version 1.1
*
*/
public class TurtleActivator extends Activator<Turtle>
{
private final static ConcurrentHashMap<Class<? extends Turtle>,Map<String,Method>> methodTable = new ConcurrentHashMap<>();
public TurtleActivator(String community) {
this(community, TKOrganization.TURTLES_GROUP, TKOrganization.TURTLE_ROLE);
}
public TurtleActivator(String community, String role) {
this(community, TKOrganization.TURTLES_GROUP, role);
}
public TurtleActivator(String community, String group, String role) {
super(community, group, role);
useMulticore(Runtime.getRuntime().availableProcessors()); //TODO add the options
}
// @SuppressWarnings("unchecked")
// public void initialize() {
// for (Turtle t : getCurrentAgentsList()) {
// methodTable.put((Class<Turtle>) t.getClass(), new HashMap<String, Method>());
// }
// }
@SuppressWarnings("unchecked")
@Override
protected void adding(Turtle agent) {
final Class<? extends Turtle> c = agent.getClass();
if(methodTable.get(c) == null){
methodTable.put(c, new HashMap<String,Method>());
}
}
public void execute(final List<Turtle> agents, Object... args) {
// Collections.shuffle(agents);
for (Turtle t : agents) // TODO shuffle or not !!
{
if (t.getPatch() == null) // killed by another before its turn
return;
String nextMethod = null;
final Method nextAction = t.getNextAction();
try {
nextMethod = (String) nextAction.invoke(t);
} catch (NullPointerException e) {
throw new SimulationException(t.getClass()+"'s initial behavior not set", null);
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
if(! (cause instanceof ThreadDeath)){
System.err.println("Can't invoke: " + nextAction + "\n");//let the others go on running : no global exception
cause.printStackTrace();
}
}
catch (Exception e) {
System.err.println("Can't invoke: " + nextAction + "\n");//let the others go on running : no global exception
e.printStackTrace();
} catch(AssertionError e){
throw e;
}
if (nextMethod != null) {
if (nextMethod.equals(nextAction.getName())) {
t.incrementBehaviorCount();
continue;
} else {
t.setCurrentBehaviorCount(0);
}
t.setNextMethod(getMethodOnTurtle(t.getClass(),nextMethod));
} else {
if (t.isAlive()) {
// t.setNextAction(null);
t.killAgent(t);
}
}
}
}
private static <T extends Turtle> Method getMethodOnTurtle(Class<T> agentClass, final String methodName) {
Method m = methodTable.get(agentClass).get(methodName);
if (m == null) {
try {
m = Activator.findMethodOn(agentClass, methodName);
methodTable.get(agentClass).put(methodName, m);
} catch (NoSuchMethodException | SecurityException e) {
System.err.println("Can't use method: " + methodName);
e.printStackTrace();
}
}
return m;
}
}