View Javadoc

1   package nl.tudelft.goal.ut2004.agent.module;
2   
3   import java.lang.reflect.InvocationTargetException;
4   import java.lang.reflect.Method;
5   import java.util.ArrayList;
6   import java.util.Collection;
7   import java.util.HashMap;
8   import java.util.List;
9   import java.util.Map;
10  import java.util.Map.Entry;
11  
12  import nl.tudelft.goal.EIS2Java.annotation.AsPercept;
13  import nl.tudelft.goal.EIS2Java.util.EIS2JavaUtil;
14  import cz.cuni.amis.pogamut.base.agent.module.SensorModule;
15  import cz.cuni.amis.pogamut.ut2004.bot.IUT2004BotController;
16  import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004Bot;
17  import cz.cuni.amis.utils.exception.PogamutException;
18  import eis.exceptions.EntityException;
19  
20  /**
21   * Module that prepares a batch of percepts after each update of the world view.
22   * Percepts are gathered based on {@link AsPercept} annotations in the
23   * controller.
24   * 
25   * A batch can be collected using {@link PerceptModule#getAllPercepts()}.
26   * 
27   * @author mpkorstanje
28   * 
29   */
30  @SuppressWarnings("rawtypes")
31  public class PerceptModule extends SensorModule<UT2004Bot> {
32  
33  	// /**
34  	// * {@link BeginMessage} listener.
35  	// */
36  	// private class EndMessageListener implements
37  	// IWorldEventListener<EndMessage> {
38  	// @Override
39  	// public void notify(EndMessage event) {
40  	// updatePercepts();
41  	// }
42  	//
43  	// /**
44  	// * Constructor. Registers itself on the given WorldView object.
45  	// *
46  	// * @param worldView
47  	// * WorldView object to listen to.
48  	// */
49  	// public EndMessageListener(IWorldView worldView) {
50  	// worldView.addEventListener(EndMessage.class, this);
51  	// }
52  	// }
53  
54  	// /** {@link BeginMessage} listener */
55  	// @SuppressWarnings("unused")
56  	// private EndMessageListener endMessageListener;
57  
58  	/**
59  	 * Methods that provide the percepts.
60  	 */
61  	private Map<String, Method> perceptProviders = new HashMap<String, Method>();
62  
63  	/**
64  	 * Percepts pulled from bot.
65  	 */
66  	private Map<String, Object> perceptBatch = new HashMap<String, Object>();
67  
68  	/**
69  	 * Event percepts pulled from bot.
70  	 */
71  	private Map<String, List<Object>> eventPerceptBatch = new HashMap<String, List<Object>>();
72  
73  	public PerceptModule(UT2004Bot agent) {
74  		super(agent);
75  
76  		// Setup end message listener
77  		// endMessageListener = new EndMessageListener(worldView);
78  
79  		// Setup percept providers.
80  		try {
81  			Class<? extends IUT2004BotController> controllerClass = agent.getController().getClass();
82  			perceptProviders = EIS2JavaUtil.processPerceptAnnotations(controllerClass);
83  		} catch (EntityException e) {
84  			throw new PogamutException("Could not proccess all annotations", e);
85  		}
86  	}
87  
88  	/**
89  	 * Calls all percept providers and puts the result in a new batch.
90  	 */
91  	public synchronized void updatePercepts() {
92  
93  		perceptBatch = new HashMap<String, Object>();
94  
95  		for (Entry<String, Method> entry : perceptProviders.entrySet()) {
96  			String perceptName = entry.getKey();
97  			Method method = entry.getValue();
98  			AsPercept annotation = method.getAnnotation(AsPercept.class);
99  			Object percept;
100 			try {
101 				percept = method.invoke(agent.getController());
102 			} catch (IllegalArgumentException e) {
103 				throw new PogamutException("Unable to update " + perceptName, e);
104 			} catch (IllegalAccessException e) {
105 				throw new PogamutException("Unable to update " + perceptName, e);
106 			} catch (InvocationTargetException e) {
107 				throw new PogamutException("Unable to update " + perceptName, e);
108 			}
109 
110 			// Percept is event based, needs special handling.
111 			if (annotation.event()) {
112 				if (!eventPerceptBatch.containsKey(perceptName)) {
113 					eventPerceptBatch.put(perceptName, new ArrayList<Object>());
114 				}
115 
116 				List<Object> events = eventPerceptBatch.get(perceptName);
117 
118 				// Percept provides multiple items, add them independently.
119 				if (!annotation.multiplePercepts()) {
120 					throw new PogamutException("Unable to update " + perceptName
121 							+ " event percept must have multiplePercepts.", this);
122 				}
123 
124 				if (!(percept instanceof Collection<?>)) {
125 					throw new PogamutException("Unable to update " + perceptName
126 							+ " return value must be a collection.", this);
127 				}
128 
129 				events.addAll((Collection<?>) percept);
130 
131 			}
132 			// Regular percept
133 			else {
134 				perceptBatch.put(perceptName, percept);
135 			}
136 		}
137 
138 		perceptBatch.putAll(eventPerceptBatch);
139 	}
140 
141 	public synchronized Map<String, Object> getAllPercepts() {
142 		// We can clear outstanding events. They'll be exported now.
143 		eventPerceptBatch.clear();
144 		return perceptBatch;
145 	}
146 }