1 package cz.cuni.amis.pogamut.usar2004.agent.module.master;
2
3 import cz.cuni.amis.pogamut.usar2004.agent.module.datatypes.MessageDescriptor;
4 import cz.cuni.amis.pogamut.usar2004.agent.module.datatypes.SensorsContainer;
5 import cz.cuni.amis.pogamut.base.agent.module.SensorModule;
6 import cz.cuni.amis.pogamut.base.communication.worldview.IWorldView;
7 import cz.cuni.amis.pogamut.base.communication.worldview.event.IWorldEventListener;
8 import cz.cuni.amis.pogamut.usar2004.agent.USAR2004Bot;
9 import cz.cuni.amis.pogamut.usar2004.agent.module.datatypes.SensorType;
10 import cz.cuni.amis.pogamut.usar2004.agent.module.sensor.SuperSensor;
11 import cz.cuni.amis.pogamut.usar2004.communication.messages.usarinfomessages.SensorMessage;
12 import java.util.HashMap;
13 import java.util.List;
14
15 /**
16 * Master module for gathering every sensor message server sends. They are saved
17 * respectively by their type and than name. There is a listener for SEN
18 * messages that updates data in SensorContainer. Note that this is equvalent
19 * with SensorsContainerQueued. The difference is that the non queued version
20 * throws out records as soon as new comes along. It writes them over. This is
21 * needed when we do not care about precision - when we want to know what is
22 * happening right now!
23 *
24 * @author vejmanm
25 */
26 public class SensorMasterModule extends SensorModule<USAR2004Bot>
27 {
28 protected SensorMessageListener sensorListener;
29 protected static SensorMasterModule singleton = null;
30 //DataStructure representing the list of all availible SensorTypes, each is listed by its name.
31 protected SensorsContainer sensorModules;
32
33 /**
34 * Private ctor
35 *
36 * @param bot USAR2004Bot variable for creating instance of each new record
37 * in sensorModules(due to inheritance)
38 */
39 public SensorMasterModule(USAR2004Bot bot)
40 {
41 super(bot);
42 sensorModules = new SensorsContainer();
43 sensorListener = new SensorMessageListener(worldView);
44 }
45
46 /**
47 * Method for obtaining the singleton.
48 *
49 * @param bot USAR2004Bot parameter for creation of the singleton instance
50 * when called for the first time.
51 * @return Returns singleton instance.
52 */
53 public static SensorMasterModule getModuleInstance(USAR2004Bot bot)
54 {
55 if(singleton == null)
56 {
57 singleton = new SensorMasterModule(bot);
58 }
59 return singleton;
60 }
61
62 /**
63 * Collection of sensor data check.
64 *
65 * @return Returns false if either sensor collection is empty or null;
66 */
67 public Boolean isReady()
68 {
69 return (sensorModules != null && !sensorModules.isEmpty());
70 }
71
72 /**
73 * Gets sensor message representatives from local hashmap. Returns null if
74 * none matches or this hash map is empty.
75 *
76 * @param type String representing the type of sensor to return.
77 * @return Returns List of specified type of Sensor module.
78 */
79 public List<SuperSensor> getSensorsByType(String type)
80 {
81 if(type == null)
82 {
83 return null;
84 }
85 return sensorModules.getSensorsByType(type.toLowerCase());
86 }
87
88 /**
89 * Iterates through local hashmap values and seeks match. Returns null if
90 * this hash map is empty. Note, that if <B>type</B> = UNKNOWN_SENSOR it
91 * returns all unknown sensors.
92 *
93 * @param type SensorType representing the type of sensor to return.
94 * @return Returns List of all sensors that suit input SensorType.
95 */
96 public List<SuperSensor> getSensorsBySensorType(SensorType type)
97 {
98 return sensorModules.getSensorsBySensorType(type);
99 }
100
101 /**
102 * Iterates through local hashmap values and seeks match. Returns null if
103 * this hash map is empty. Note, that if <B>type</B> = UNKNOWN_SENSOR it
104 * returns all unknown sensors.
105 *
106 * @param type SensorType representing the type of sensor to return.
107 * @return Returns List of all sensors that suit input SensorType.
108 */
109 public boolean isSensorReady(SensorType type)
110 {
111 return sensorModules.getSensorsBySensorType(type).size() > 0;
112 }
113
114 /**
115 * Adds every object that can be casted to initial class to the output list.
116 * Note that if You feed this method with SuperClass it will return all
117 * available submodules.
118 *
119 * @param c Class representing the type of which the return list should be
120 * @return Returns a list of eligible objects, that can be casted to Class c
121 */
122 public List<SuperSensor> getSensorsByClass(Class c)
123 {
124 return sensorModules.getSensorsByClass(c);
125 }
126
127 /**
128 * Gets sensor message representatives from local hashmap specified by type
129 * and by name. Returns null if none matches or this hash map is empty.
130 *
131 * @param type String representing the type of sensor to return.
132 * @param name String representing the name of sensor to return.
133 * @return Returns List of specified type of Sensor module.
134 */
135 public SuperSensor getSensorByTypeName(String type, String name)
136 {
137 if(type == null || name == null)
138 {
139 return null;
140 }
141 return (SuperSensor) sensorModules.getSensorByTypeName(type.toLowerCase(), name.toLowerCase());
142 }
143
144 /**
145 * For each type of sensor it adds all individuals to the returnee List as a
146 * couple (Type, Name)
147 *
148 * @return returns Map of couples (Type/Name) of non empty sensor
149 * representatives.
150 */
151 public List<MessageDescriptor> getNonEmptyDescripton()
152 {
153 return sensorModules.getNonEmptyDescription();
154 }
155
156 /**
157 * Asks SensorType enum if it knows SensorType represented by string
158 * <B>type</B>. If it does, it also contains Class reference. This reference
159 * is then instantiated and returned. If it does not, it returns instance of
160 * base class SuperSensor which is represented by SensorType.UNKNOWN_SENSOR.
161 *
162 * @param type String representing possible valid SensorType.
163 * @return Returns Class instance relevant to input String.
164 */
165 protected SuperSensor createNewSensor(SensorMessage message)
166 {
167 return ModuleInstanceProvider.getSensorInstanceByType(message.getType());
168 }
169
170 /**
171 * Returns a flag that indicates if sensorUpdate was successful.
172 *
173 * @param message new SensorMessage object.
174 * @return Return false if this message type with this name does not exist.
175 * yet.
176 */
177 protected boolean updateSensorCollection(SensorMessage message)
178 {
179 if(!sensorModules.containsKey(message.getType().toLowerCase()))
180 {
181 return false;
182 }
183 if(sensorModules.get(message.getType().toLowerCase()).isEmpty())
184 {
185 return false;
186 }
187 if(!sensorModules.get(message.getType().toLowerCase()).containsKey(message.getName().toLowerCase()))
188 {
189 return false;
190 }
191 sensorModules.get(message.getType().toLowerCase()).get(message.getName().toLowerCase()).updateMessage(message);
192 return true;
193 }
194
195 /**
196 * Updates previous State on genuine Sensor or creates a new Record.
197 *
198 * @param message This ought to be SensorMessage caught by listener.
199 */
200 protected void fileMessage(SensorMessage message)
201 {
202 if(updateSensorCollection(message))
203 {
204 return;
205 }
206 if(!sensorModules.containsKey(message.getType().toLowerCase()))
207 {
208 sensorModules.put(message.getType().toLowerCase(), new HashMap<String, SuperSensor>());
209 }
210 if(sensorModules.get(message.getType().toLowerCase()).isEmpty() || !sensorModules.get(message.getType().toLowerCase()).containsKey(message.getName().toLowerCase()))
211 {
212 SuperSensor newSensor = createNewSensor(message);
213 if(newSensor == null)
214 {
215 System.out.println("This sensor is not supported! " + message.getName());
216 return;
217 }
218 String type = message.getType().toLowerCase();
219 String name = message.getName().toLowerCase();
220 newSensor.updateMessage(message);//fill the object
221 sensorModules.get(type).put(name, newSensor);
222 }
223 }
224
225 @Override
226 protected void cleanUp()
227 {
228 super.cleanUp();
229 sensorListener = null;
230 sensorModules = null;
231 singleton = null;
232 }
233
234 private class SensorMessageListener implements IWorldEventListener<SensorMessage>
235 {
236 @Override
237 public void notify(SensorMessage event)
238 {
239 fileMessage(event);
240 }
241
242 public SensorMessageListener(IWorldView worldView)
243 {
244 worldView.addEventListener(SensorMessage.class, this);
245 }
246 }
247 }