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.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 }