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.configuration.SuperConfiguration;
8   import cz.cuni.amis.pogamut.usar2004.agent.module.datatypes.MessageDescriptor;
9   import cz.cuni.amis.pogamut.usar2004.agent.module.datatypes.ConfigContainer;
10  import cz.cuni.amis.pogamut.usar2004.agent.module.datatypes.ConfigType;
11  import cz.cuni.amis.pogamut.usar2004.communication.messages.usarcommands.GetConf;
12  import cz.cuni.amis.pogamut.usar2004.communication.messages.usarinfomessages.ConfigurationMessage;
13  import java.util.HashMap;
14  import java.util.List;
15  
16  /**
17   * ConfigurationMasterModule provides methods for querying messages to server
18   * and methods for reading answers to those queries. Please note, that You have
19   * to 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 ConfigMasterModule extends SensomotoricModule<USAR2004Bot>
26  {
27      //Quest: Some ConfigTypes 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      //Quest: Should unite With GeoMasterModule, cause its just copy/paste thing going on here...
29      protected ConfigurationMessageListener confListener;
30      protected static ConfigMasterModule singleton = null;
31      //DataStructure representing the list of all availible SensorTypes, each is listed by name.
32      protected ConfigContainer configModules;
33  
34      /**
35       * Private ctor
36       *
37       * @param bot USAR2004Bot variable for creating instance of each new record
38       * in configModules(due to inheritance)
39       */
40      private ConfigMasterModule(USAR2004Bot bot)
41      {
42          super(bot);
43          configModules = new ConfigContainer();
44          confListener = new ConfigurationMessageListener(worldView);
45      }
46  
47      /**
48       * Method for obtaining the singleton.
49       *
50       * @param bot USAR2004Bot parameter for creation of the singleton instance
51       * when called for the first time.
52       * @return Returns singleton instance.
53       */
54      public static ConfigMasterModule getModuleInstance(USAR2004Bot bot)
55      {
56          if(singleton == null)
57          {
58              singleton = new ConfigMasterModule(bot);
59          }
60          return singleton;
61      }
62  
63      /**
64       * Collection of sensor data check.
65       *
66       * @return Returns false if either sensor collection is empty or null;
67       */
68      public Boolean isReady()
69      {
70          return (configModules != null && !configModules.isEmpty());
71      }
72  
73      /**
74       * Adds every object that can be casted to initial class to the output list.
75       * Note that if You feed this method with SuperClass it will return all
76       * available submodules.
77       *
78       * @param c Class representing the type of which the return list should be
79       * @return Returns a list of eligible objects, that can be casted to Class c
80       */
81      public List<SuperConfiguration> getConfigurationsByClass(Class clazz)
82      {
83          return configModules.getConfigurationsByClass(clazz);
84      }
85  
86      /**
87       *
88       * @param type String representing the type of Configuration to return
89       * @return Returns List of specified type of Configuration module.
90       */
91      public List<SuperConfiguration> getConfigurationsByType(String type)
92      {
93          if(type == null)
94          {
95              return null;
96          }
97          return configModules.getConfigurationsByType(type.toLowerCase());
98      }
99  
100     /**
101      * Note, that if <B>type</B> = UNKNOWN it returns all unknown
102      * Configurations.
103      *
104      * @param type ConfigurationType representing the type of Configuration to
105      * return
106      * @return Returns List of all Configurations that suit input
107      * ConfigurationType.
108      */
109     public List<SuperConfiguration> getConfigurationsByConfigType(ConfigType type)
110     {
111         return configModules.getConfigurationsByConfigType(type);
112     }
113 
114     /**
115      * Gets configuration message representatives from local hashmap specified
116      * by type and by name. Returns null if none matches or this hash map is
117      * empty.
118      *
119      * @param type String representing the type of configuration to return.
120      * @param name String representing the name of configuration to return.
121      * @return Returns List of specified type of Configuration representative.
122      */
123     public SuperConfiguration getConfigurationByTypeName(String type, String name)
124     {
125         if(type == null || name == null)
126         {
127             return null;
128         }
129         return configModules.getConfigurationByTypeName(type.toLowerCase(), name.toLowerCase());//name can be null, but we cant put null to lowerCase!
130     }
131 
132     /**
133      * For each type of Configuration it adds all individuals to the returnee
134      * List as a couple (Type, Name)
135      *
136      * @return returns Map of couples (Type/Name) of non empty Configurations
137      */
138     public List<MessageDescriptor> getNonEmptyDescription()
139     {
140         return configModules.getNonEmptyDescription();
141     }
142 
143     /**
144      * Sends GETCONF message with specified type. If the type is genuine, this
145      * module will acquire Configuration data of all sensors/effecters specified
146      * by <B>type</B>.
147      *
148      * @param type type of Configuration data we want to know about. For example
149      * : Sonar, MisPkg, Robot, Effecter, etc..
150      */
151     public void queryConfigurationByType(String type)
152     {
153         queryConfigurationByTypeName(type, null);
154     }
155 
156     /**
157      * Sends GETCONF message with specified type and name. This module then
158      * ought to acquire data from server matching requirements.
159      *
160      * @param type type of Configuration data we want to know about. For example
161      * : Sonar, MisPkg, Robot, Effecter, etc..
162      * @param name of sensor/effecter. Can be omitted.
163      */
164     public void queryConfigurationByTypeName(String type, String name)
165     {
166         this.act.act(new GetConf(type, name));
167     }
168 
169     /**
170      * Asks ConfigType enum if it knows ConfigType represented by string
171      * <B>type</B>. If it does, it also contains Class reference. This reference
172      * is then instantiated and returned. If it does not, it returns instance of
173      * base class SuperConfiguration which is represented by ConfigType.SENSOR.
174      *
175      * @param type String representing possible valid ConfigType.
176      * @return Returns Class instance relevant to input String.
177      */
178     protected SuperConfiguration createNewSensor(ConfigurationMessage message)
179     {
180         return ModuleInstanceProvider.getConfigInstanceByType(message.getType());
181     }
182 
183     /**
184      * Returns a flag that indicates if sensorUpdate was successful.
185      *
186      * @param message
187      * @return Return false if this message type with this name does not exist
188      * yet.
189      */
190     protected boolean updateSensorCollection(ConfigurationMessage message)
191     {
192         if(!configModules.containsKey(message.getType().toLowerCase()))
193         {
194             return false;
195         }
196         if(configModules.get(message.getType().toLowerCase()).isEmpty())
197         {
198             return false;
199         }
200         if(!configModules.get(message.getType().toLowerCase()).containsKey(message.getName().toLowerCase()))
201         {
202             return false;
203         }
204         //sensorModules.get(message.getType().toLowerCase()).get(message.getName().toLowerCase()).updateMessage(message);
205         return true;
206     }
207 
208     /**
209      * Updates previous State on genuine Sensor or creates a new Record.
210      *
211      * @param message This ought to be SensorMessage caught by listener.
212      */
213     protected void fileMessage(ConfigurationMessage message)
214     {
215         if(updateSensorCollection(message))
216         {
217             return;
218         }
219         if(!configModules.containsKey(message.getType().toLowerCase()))
220         {
221             configModules.put(message.getType().toLowerCase(), new HashMap<String, SuperConfiguration>());
222         }
223         if(configModules.get(message.getType().toLowerCase()).isEmpty() || !configModules.get(message.getType().toLowerCase()).containsKey(message.getName().toLowerCase()))
224         {
225             SuperConfiguration newSensor = createNewSensor(message);
226             if(newSensor == null)
227             {
228                 System.out.println("This Configuration message is not supported! " + message.getName());
229                 return;
230             }
231             String type = message.getType().toLowerCase();
232             String name = message.getName().toLowerCase();
233             newSensor.updateMessage(message);//fill the object
234             configModules.get(type).put(name, newSensor);
235         }
236     }
237 
238     @Override
239     protected void cleanUp()
240     {
241         super.cleanUp();
242         confListener = null;
243         configModules = null;
244         singleton = null;
245     }
246 
247     private class ConfigurationMessageListener implements IWorldEventListener<ConfigurationMessage>
248     {
249         @Override
250         public void notify(ConfigurationMessage event)
251         {
252             fileMessage(event);
253         }
254 
255         public ConfigurationMessageListener(IWorldView worldView)
256         {
257             worldView.addEventListener(ConfigurationMessage.class, this);
258         }
259     }
260 }