View Javadoc

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