5.2 GAME Framework: Implementation Details and Standard Modules
5.2.2 Defining GAME modules
All modules in GAME have some common properties, which permit them to be con- figured and serialized in the same way. All modules must implement the standard Java interfaces Cloneable and then provide a public clone method, with deep copy implementation. They must also implement Serializable, in order to be saved and reloaded with the standard Java serialization API. Other custom interfaces required to GAME modules are:
5.2 GAME Framework: Implementation Details and Standard Modules
Figure 5.4: The main configuration window of GAME. It permits to define and run experiments.
key-value properties. The method getOptions gives the map of key-values, getOption returns a value for a key, setOptions and setOption allow to modify the configuration.
• XMLConfigurable. Defines getXMLSettings, which returns an XML descriptor of the configuration, and loadSettingsFromXML, which can load the configuration from an XML descriptor. In addition, methods for default configuration loading and saving are defined.
• XMLLoadable. Defines methods for XML serialization.
Although configuration and serialization may seem redundant definitions at first they are two very distinct concepts: configuration is thought to be user-friendly and defines the initial state of an object (for example, before a training process), while serialization can define any state.
Different implementation may be given which satisfy all the listed requirements, the simple one being to inherit from the class GAMEModule. Almost all the standard
modules inherit, directly or indirectly, from it1.
A GAMEModule object considers all its public fields as part of the configuration (i.e. values of the map returned by getOptions), and implements all the constraints cited above without the need of any further configuration. All the standard types and modules are handled through automatic introspection of the fields. XML config- uration is implemented with a recursive approach, while XML serialization uses the external library XStream2. The method clone is implemented resorting to Java se- rialization. The method getDocumentation automatically builds the documentation for the module. The method getClassDescription can be overridden to specify a general description for a module, while the annotation Description on a parameter field permits to add a documentation for that parameter.
Another way to provide the documentation, together with safe validation controls, to a configuration value is to define it as a Value Holder. Value holders are wrappers of simple and more complex types which wrap a value. The value can be set only with a specific method, which can perform all the validation controls needed.
A further requirement which is requested to some modules is to be inside a specific package; in particular, modules which could be substituted each other should be in the same package. Standard packages are fixed for the standard modules, but one could define her hierarchy of replaceable modules and choose the package for that modules at her own will. If all the requirement are followed when implementing a module, the graphical user interface of GAME includes it in the list of selectable modules, permits to read the documentation provided and automatically generates a configuration panel, with facilities to load and save the configuration for that module.
Let us see an example code:
public class MyModule extends GAMEModule {
@Description(description="My first parameter") public int par1 = 0;
public boolean par2 = true;
public InstanceData par3 = new CSVData(); private double hiddenState = 0;
1
In most of the rest of the document the inheritance from GAMEModule and the implementation of the cited interfaces is not indicated for the sake of clarity.
5.2 GAME Framework: Implementation Details and Standard Modules
@Override
protected String getClassDescription() { return "My first module";
} }
The above code is all it’s needed to create a documented module named MyMod- ule, with three parameters par1, par2, par3, and with an additional variable defining the state. The framework automatically creates a configuration and a documentation window for that module, both displayed in Figure 5.5. That window is opened auto-
Figure 5.5: Screenshot of an automatically generated configuration and documentation windows for a GAME module.
matically at need if the module is part of the configuration of a module recognized by the system; otherwise, it can be displayed with the statement new OptionsDialog(new MyModule()).setVisible(true). From the menu file of the configuration window is possible to save and load the state and the configuration. The XML configuration descriptor for MyModule is:
<mymodule class="game.MyModule" > <par1>0</par1>
<par2>true</par2> <par3>
<csvdata class="game.datahandling.dataenvelopes.CSVData" > </csvdata>
</par3> </mymodule>
While the XML configuration descriptor is: <object-stream>
<game.MyModule> <par1>0</par1> <par2>true</par2>
<par3 class="game.datahandling.dataenvelopes.CSVData"> <id>NOT-INITIALIZED</id>
<input class="game.datahandling.dataenvelopes.base.VectorData"> <encoder>
<size>-1</size> </encoder>
<value class="double-array"/> </input>
<target class="game.datahandling.dataenvelopes.base.VectorData"> <encoder>
<size>-1</size> </encoder>
<value class="double-array"/> </target>
</par3>
<hiddenState>0.0</hiddenState> </game.MyModule>
</object-stream>