View Javadoc

1   package cz.cuni.amis.pogamut.usar2004.agent.module.master;
2   
3   import cz.cuni.amis.pogamut.base.agent.module.SensomotoricModule;
4   import cz.cuni.amis.pogamut.base.communication.worldview.IWorldView;
5   import cz.cuni.amis.pogamut.base.communication.worldview.event.IWorldEventListener;
6   import cz.cuni.amis.pogamut.usar2004.agent.USAR2004Bot;
7   import cz.cuni.amis.pogamut.usar2004.agent.module.datatypes.GeometryContainer;
8   import cz.cuni.amis.pogamut.usar2004.agent.module.datatypes.GeometryType;
9   import cz.cuni.amis.pogamut.usar2004.agent.module.datatypes.MessageDescriptor;
10  import cz.cuni.amis.pogamut.usar2004.agent.module.geometry.SuperGeometry;
11  import cz.cuni.amis.pogamut.usar2004.communication.messages.usarcommands.GetGeo;
12  import cz.cuni.amis.pogamut.usar2004.communication.messages.usarinfomessages.GeometryMessage;
13  import java.util.HashMap;
14  import java.util.List;
15  
16  /**
17   * GeometryMasterModule provides methods for querying messages to server and
18   * methods for reading answers to those queries. Please note, that You have to
19   * produce suitable query before reading any data. Query methods: starts with
20   * query* Module methods: starts with get* Data at each module updates every
21   * time You call query method again.
22   *
23   * @author vejmanm
24   */
25  public class GeometryMasterModule extends SensomotoricModule<USAR2004Bot>
26  {
27      //Quest: Some GeoTypes such as "Robot" are theoretically useless as long as we wont happen to INIT more than one bot within one USAR2004Bot. So..Do we need List for one Item then?
28      protected GeometryMessageListener geoListener;
29      protected static GeometryMasterModule singleton = null;
30      //DataStructure representing the list of all availible SensorTypes, each is listed by name.
31      protected GeometryContainer geometryModules;
32  
33      /**
34       * Private ctor
35       *
36       * @param bot USAR2004Bot variable for creating instance of each new record
37       * in geometryModules(due to inheritance)
38       */
39      public GeometryMasterModule(USAR2004Bot bot)
40      {
41          super(bot);
42          geometryModules = new GeometryContainer();
43          geoListener = new GeometryMessageListener(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 GeometryMasterModule getModuleInstance(USAR2004Bot bot)
54      {
55          if(singleton == null)
56          {
57              singleton = new GeometryMasterModule(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 (geometryModules != null && !geometryModules.isEmpty());
70      }
71  
72      /**
73       * Adds every object that can be casted to initial class to the output list.
74       * Note that if You feed this method with SuperClass it will return all
75       * available submodules.
76       *
77       * @param c Class representing the type of which the return list should be
78       * @return Returns a list of eligible objects, that can be casted to Class c
79       */
80      public List<SuperGeometry> getGeometriesByClass(Class clazz)
81      {
82          return geometryModules.getGeometriesByClass(clazz);
83      }
84  
85      /**
86       *
87       * @param type String representing the type of Geometry to return
88       * @return Returns List of specified type of Geometry module.
89       */
90      public List<SuperGeometry> getGeometriesByType(String type)
91      {
92          if(type == null)
93          {
94              return null;
95          }
96          return geometryModules.getGeometriesByType(type.toLowerCase());
97      }
98  
99      /**
100      * Note, that if <B>type</B> = UNKNOWN it returns all unknown Geometries.
101      *
102      * @param type GeometryType representing the type of Geometry to return
103      * @return Returns List of all Geometries that suit input GeometryType.
104      */
105     public List<SuperGeometry> getGeometriesByGeometryType(GeometryType type)
106     {
107         return geometryModules.getGeometriesByGeometryType(type);
108     }
109 
110     /**
111      * Gets geometry message representatives from local hashmap specified by
112      * type and by name. Returns null if none matches or this hash map is empty.
113      *
114      * @param type String representing the type of geometry to return.
115      * @param name String representing the name of geometry to return.
116      * @return Returns List of specified type of Geometry representative.
117      */
118     public SuperGeometry getGeometryByTypeName(String type, String name)
119     {
120         if(type == null || name == null)
121         {
122             return null;
123         }
124         return geometryModules.getGeometryByTypeName(type.toLowerCase(), name.toLowerCase());//name can be null, but we cant put null to lowerCase!
125     }
126 
127     /**
128      * For each type of Geometry it adds all individuals to the returnee List as
129      * a couple (Type, Name)
130      *
131      * @return returns Map of couples (Type/Name) of non empty Geometries
132      */
133     public List<MessageDescriptor> getNonEmptyDescription()
134     {
135         return geometryModules.getNonEmptyDescription();
136     }
137 
138     /**
139      * Sends GETGEO message with specified type. If the type is genuine, this
140      * module will acquire geometry data of all sensors/effecters specified by
141      * <B>type</B>.
142      *
143      * @param type type of geometry data we want to know about. For example :
144      * Sonar, MisPkg, Robot, Effecter, etc..
145      */
146     public void queryGeometryByType(String type)
147     {
148         queryGeometryByTypeName(type, null);
149     }
150 
151     /**
152      * Sends GETGEO message with specified type and name. This module then ought
153      * to acquire data from server matching requirements.
154      *
155      * @param type type of geometry data we want to know about. For example :
156      * Sonar, MisPkg, Robot, Effecter, etc..
157      * @param name of sensor/effecter. Can be omitted.
158      */
159     public void queryGeometryByTypeName(String type, String name)
160     {
161         this.act.act(new GetGeo(type, name));
162     }
163 
164     /**
165      * Asks GeometryType enum if it knows GeometryType represented by string
166      * <B>type</B>. If it does, it also contains Class reference. This reference
167      * is then instantiated and returned. If it does not, it returns instance of
168      * base class SuperGeometry which is represented by
169      * GeometryType.SENSOR_EFFECTER.
170      *
171      * @param type String representing possible valid GeometryType.
172      * @return Returns Class instance relevant to input String.
173      */
174     protected SuperGeometry createNewSensor(GeometryMessage message)
175     {
176         return ModuleInstanceProvider.getGeometryInstanceByType(message.getType());
177     }
178 
179     /**
180      * Returns a flag that indicates if sensorUpdate was successful.
181      *
182      * @param message
183      * @return Return false if this message type with this name does not exist
184      * yet.
185      */
186     protected boolean updateSensorCollection(GeometryMessage message)
187     {
188         if(!geometryModules.containsKey(message.getType().toLowerCase()))
189         {
190             return false;
191         }
192         if(geometryModules.get(message.getType().toLowerCase()).isEmpty())
193         {
194             return false;
195         }
196         if(!geometryModules.get(message.getType().toLowerCase()).containsKey(message.getName().toLowerCase()))
197         {
198             return false;
199         }
200         //sensorModules.get(message.getType().toLowerCase()).get(message.getName().toLowerCase()).updateMessage(message);
201         return true;
202     }
203 
204     /**
205      * Updates previous State on genuine Sensor or creates a new Record.
206      *
207      * @param message This ought to be SensorMessage caught by listener.
208      */
209     protected void fileMessage(GeometryMessage message)
210     {
211         if(updateSensorCollection(message))
212         {
213             return;
214         }
215         if(!geometryModules.containsKey(message.getType().toLowerCase()))
216         {
217             geometryModules.put(message.getType().toLowerCase(), new HashMap<String, SuperGeometry>());
218         }
219         if(geometryModules.get(message.getType().toLowerCase()).isEmpty() || !geometryModules.get(message.getType().toLowerCase()).containsKey(message.getName().toLowerCase()))
220         {
221             SuperGeometry newSensor = createNewSensor(message);
222             if(newSensor == null)
223             {
224                 System.out.println("This geometry message is not supported! " + message.getName());
225                 return;
226             }
227             String type = message.getType().toLowerCase();
228             String name = message.getName().toLowerCase();
229             newSensor.updateMessage(message);//fill the object
230             geometryModules.get(type).put(name, newSensor);
231         }
232     }
233 
234     @Override
235     protected void cleanUp()
236     {
237         super.cleanUp();
238         geoListener = null;
239         geometryModules = null;
240         singleton = null;
241     }
242 
243     private class GeometryMessageListener implements IWorldEventListener<GeometryMessage>
244     {
245         @Override
246         public void notify(GeometryMessage event)
247         {
248             fileMessage(event);
249         }
250 
251         public GeometryMessageListener(IWorldView worldView)
252         {
253             worldView.addEventListener(GeometryMessage.class, this);
254         }
255     }
256 }