package cz.agents.agentpolis.tools.geovisio.spy.proxy; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javassist.util.proxy.MethodFilter; import javassist.util.proxy.MethodHandler; import javassist.util.proxy.ProxyFactory; import org.apache.log4j.Logger; import com.google.inject.Injector; import cz.agents.agentpolis.siminfrastructure.planner.trip.Trip; import cz.agents.agentpolis.siminfrastructure.planner.trip.Trips; import cz.agents.agentpolis.simmodel.agent.Agent; import cz.agents.agentpolis.simulator.creator.initializator.AgentInitFactory; import cz.agents.agentpolis.tools.geovisio.spy.agentpolis.agentstate.AgentState; import cz.agents.agentpolis.tools.geovisio.spy.agentpolis.agentstate.AgentState.AgentStateType; import cz.agents.agentpolis.tools.geovisio.spy.agentpolis.agentstate.AgentStateStorage; import eu.superhub.wp4.model.siminfrastructure.citizen.activityscheduler.dayplansheduler.Activity; import eu.superhub.wp4.model.siminfrastructure.citizen.activityscheduler.dayplansheduler.LocationActivity; import eu.superhub.wp4.model.siminfrastructure.citizen.activityscheduler.dayplansheduler.TravelActivity; import eu.superhub.wp4.model.siminfrastructure.citizen.activityscheduler.dayplansheduler.WaitingActivity; /** * * @author Marek Cuchy * */ public class AgentProxyFactory implements AgentInitFactory { private static final Logger logger = Logger.getLogger(AgentProxyFactory.class); private final AgentInitFactory agentInit; private ProxyFactory factory = new ProxyFactory(); private AgentStateStorage agentStateStorage; public AgentProxyFactory(AgentInitFactory agentInit) { this.agentInit = agentInit; } public List<Agent> initAllAgentLifeCycles(Injector injector) { agentStateStorage = injector.getInstance(AgentStateStorage.class); List<Agent> agents = agentInit.initAllAgentLifeCycles(injector); List<Agent> proxyAgents; try { proxyAgents = createProxyAgents(agents); } catch (NoSuchMethodException | IllegalArgumentException | InstantiationException | IllegalAccessException | InvocationTargetException e) { logger.error("Proxy agents not created. Returned empty list.", e); proxyAgents = Collections.emptyList(); } return proxyAgents; } private List<Agent> createProxyAgents(List<Agent> agents) throws NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException { List<Agent> proxyAgents = new ArrayList<Agent>(agents.size()); for (Agent agent : agents) { Agent proxyAgent = createProxyAgent(agent); proxyAgents.add(proxyAgent); } return proxyAgents; } private Agent createProxyAgent(final Agent agent) throws NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException { Class<? extends Agent> clazz = agent.getClass(); Constructor<?> constructor = clazz.getConstructors()[0]; Class<?>[] parameterTypes = constructor.getParameterTypes(); // reflectionFactory = new ProxyFactory(); factory.setSuperclass(clazz); factory.setFilter(new MethodFilter() { public boolean isHandled(Method m) { if(m.getName().equals("visitActivity")){ return true; } return false; } }); Object[] params = createParameters(agent, constructor); Agent proxyAgent = (Agent) factory.create(parameterTypes, params, createMethodHandler(agent)); clone(agent,proxyAgent,clazz); return proxyAgent; } private <T> void clone(T source, T target, Class<? extends T> clazz) throws IllegalArgumentException, IllegalAccessException { for (Field field : clazz.getDeclaredFields()) { // field. if(Modifier.isStatic(field.getModifiers())) continue; field.setAccessible(true); Object fieldValue= field.get(source); field.set(target, fieldValue); } } private MethodHandler createMethodHandler(final Agent agent) { return new MethodHandler() { Agent sourceAgent = agent; @Override public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable { // logger.debug(thisMethod.getName()); // logger.debug(Arrays.toString(args)); Object object = args[0]; Activity activity = (Activity) object; AgentStateType state = null; Timestamp duration = new Timestamp(activity.getDurationInMillisDayRange()); Timestamp startTime = new Timestamp(activity.getStarTimeInMillisDayRange()); Timestamp endTime = new Timestamp(activity.getEndTimeInMillisDayRange()); String description = ""; if(activity instanceof TravelActivity){ Trips clone = ((TravelActivity) activity).getTrips().clone(); while(clone.hasTrip()){ Trip<?> trip = clone.getAndRemoveFirstTrip(); description+=trip.getClass().getSimpleName()+", "; } state = AgentStateType.TRAVEL; }else if(object instanceof WaitingActivity){ state = AgentStateType.WAITING; }else if(object instanceof LocationActivity){ state = AgentStateType.LOCATION; } Agent a = (Agent) self; agentStateStorage.setState(a.getId(), new AgentState(state, startTime, endTime, duration, description)); // System.out.println(self); // System.out.println(Arrays.toString(args)); // if (!thisMethod.getName().equals("getType") && !thisMethod.getName().equals("getId")) { // logger.debug(thisMethod.getName()); // } return proceed.invoke(self, args); } }; } private Object[] createParameters(Agent agent, Constructor<?> constructor) { Class<?>[] parameterTypes = constructor.getParameterTypes(); Object[] parameters = new Object[parameterTypes.length]; int i = 0; parameters[i++] = agent.getId(); parameters[i++] = agent.getType(); // return parameters; } }