GReadWrite interface
The GreadWrite Interface
GENIUS proposes a simply way to read and write into files, consistent with the display:
- By calling the GReadWrite interface
- By definition of the read() and write() methods calling the put() method, the mechanism being the same as for display (for example, using if/switch for conditionality).
Thus, if we consider that the data must be read or written with the same logic/order as for the display, we will put all inside the generic() method and the display(), read() and write() methods will only have to call the generic() one !
public class MyContainer extends GContainer implements GDisplay, GReadWrite {
GEntryReal valR;
GEntryInt valI;
GEntryString valS;
public MyContainer () {
valR = new GEntryReal("Real value" , 0.);
valI = new GEntryInt("Integer value", 0);
valS = new GEntryString("Chain", "");
}
public void generic() throws GException {
put(valR);
put(valI);
if ( valI.getValue() > 0 ) {
put(valS);
}
}
public void display() throws GException { generic(); }
public void read() throws GException { generic(); }
public void write() throws Gexception { generic(); }
}
So, in this example above:
- the widget valS will be displayed only if the value of valI is strictly positive.
- Moreover, the value of valS will be read only if the value of valI is strictly positive.
- Again, the value of valS will be written into a file only if the value of valI is strictly positive.
We see that all have been centralized in the same code bloc.
On the contrary, if the logic is different for reading, writing and displaying data, we allways have the possibility to dissociate the treatments, coding them respectively inside the read(), write() and display() methods.
In the example below, for reading and writing, all data will be respectively read and written as, for display, valS will only be shown if the value of valI is strictly positive.
public class MyContainer extends GContainer implements GDisplay, GReadWrite {
GEntryReal valR;
GEntryInt valI;
GEntryString valS;
public MyContainer () {
valR = new GEntryReal("Real value" , 0.);
valI = new GEntryInt("Integer value", 0);
valS = new GEntryString("Chain", "");
}
public void generic() throws GException {
put(valR);
put(valI);
put(valS);
}
public void read() throws GException { generic(); }
public void write() throws Gexception { generic(); }
public void display() throws GException {
put(valR);
put(valI);
if ( valI.getValue() > 0 ) {
put(valS);
}
}
}
Data file management
To read (or write) using GENIUS tools, we only need to open a file and store inside the GENIUS corresponding object the data contained in this file. To do it:
- We use static methods from class GFileManipulation
- The file will be in XML MADONA format
Remark #1 : the GENIUS object may contain itself other GENIUS objects and so on …
Remark #2 : in that example, the flag set for the last argument of these methods is to tell to GENIUS to add a "*" character after reading (if values changed) and to remove it after writing the configuration. For more details about modified data, see specific Modified data topic.
MyGeniusObject obj = new MyGeniusObject (…); // Must implement the GReadWrite interface
GFileManipulation.readConfig (fileName, XMLRootName, obj, false );
GFileManipulation.writeConfig (fileName, XMLRootName, obj, true );
It is possible to differentiate the label displayed on the screen and the XML variable name using method setNameInConfigFile().
valR.setNameInConfigFile("nomXML");
It is also possible to have data structures, using beginOfElement() and endOfElement() methods:
public void generic() {
beginOfElement("typeOfStruct", "nameOfStruct");
put(valR);
put(valI);
put(valS);
endOfElement(); }
public void read() { generic(); }
public void write() { generic(); }
Note that the first argument of beginOfElement() may be an enum (implementing GItemTypeInterface) rather than a string which could be more robust:
public enum StructType implements GItemTypeInterface {
Orbit,
Potential,
Atmosphere,
Maneuver,
Attitude;
}
At the end, the format of the file will be something like that:
<Potential name=Earth">
<Real name="mu" unit="km^3/s^2">398600.64</Real>
<Real name="g0" unit="m/s^2">9.80665</Real>
<Real name="rt" unit="km">6378.139</Real>
<Real name="ze" unit="km">120.0</Real>
<Real name="wt" unit="deg/s">0.004178071267451</Real>
</Potential>
Missing data
From 1.4 version there is the possibility to read such files even if some data are missing. Indeed, this may occur when you want to read files from a previous version of your tool when these data where not initially foreseen.
The way to do it is very simple. In fact, you have just to call for the setDefaultValue method. For example:
valG0 = new GEntryReal("G0" , 9.80665);
valG0.setDefaultValue(9.80665);
}
So, in that case, we will be able to read this file even if g0 does not appear !
<Potential name=Earth">
<Real name="mu" unit="km^3/s^2">398600.64</Real>
<Real name="rt" unit="km">6378.139</Real>
<Real name="ze" unit="km">120.0</Real>
<Real name="wt" unit="deg/s">0.004178071267451</Real>
</Potential>
Multiple search
First, let us consider such a data structure as shown in this XML file :
<?xml version="1.0" encoding="UTF-8"?>
<data>
<Vehicle name="vehicle">
<!--Dry mass:-->
<Real name="dryMass" unit="kg">1.0E0</Real>
<!--Ergol mass:-->
<Real name="ergMass" unit="kg">2.0E0</Real>
<!--Reference surface:-->
<Real name="sref" unit="m^2">3.0E0</Real>
</Vehicle>
<SubData name="subdata">
<Vehicle name="vehicle">
<!--Dry mass:-->
<Real name="dryMass" unit="kg">11.0E0</Real>
<!--Ergol mass:-->
<Real name="ergMass" unit="kg">22.0E0</Real>
<!--Reference surface:-->
<Real name="sref" unit="m^2">33.0E0</Real>
</Vehicle>
</SubData>
</data>
We see that the Vehicle structure, including three real data (drymass, ergmass and sref) is existing in both places in the file. The code to create such an object is the following one:
public class VehicleData extends GPanel implements GReadWrite {
public static final GUnit[] UNITS_MASS = {new GMetricUnit("kg"), new GMetricUnit("t")};
public static final GUnit[] UNITS_SURFACE = {new GMetricUnit("m^2")};
private final GEntryReal dryMass;
private final GEntryReal ergMass;
private final GEntryReal sref;
public VehicleData () {
super();
dryMass = new GEntryReal("Dry mass:", 0., UNITS_MASS);
dryMass.setNameInConfigFile("dryMass");
ergMass = new GEntryReal("Ergol mass:", 0., UNITS_MASS);
ergMass.setNameInConfigFile("ergMass");
sref = new GEntryReal("Reference surface:", 0., UNITS_SURFACE);
sref.setNameInConfigFile("sref");
this.setNameAndCommentInConfigFile("vehicle");
}
@Override
public void generic() throws GException {
beginOfElement("Vehicle", "vehicle");
put(dryMass);
put(ergMass);
put(sref);
endOfElement();
}
@Override
public void display() throws GException { generic(); }
@Override
public void read() throws GException { generic(); }
@Override
public void write() throws GException { generic(); }
}
The idea is to know how many Vehicle (or how many dryMass, ...) we may have in the file. To do it, we have several possibilities ...
Using searchCompatibleComponents() method
With this solution, we have to call for the searchCompatibleComponents() method like below:
final List<GComponent> list = GFileManipulation.searchCompatibleComponents(fileName, new VehicleData(), true);
... where:
- the first argument, "fileName" is the name of the file
- the second argument is an object of the same type to search. Note that it is mandatory that this object owns a constructor without arguments (to be able to duplicate it).
- the last argument is a boolean to indicate if the filter will consider the name of the object (if true) and not only itstype. Note that is the reason why, we have added the following line in order to initialize (when the constructor is called) correctly this name ...
this.setNameAndCommentInConfigFile("vehicle");
Calling this method will return a list of GComponent that could be treated for example like this:
System.out.println("Amount of compatible components: " + list.size());
for ( GComponent comp : list ) {
System.out.println(comp.getGClassName());
System.out.println(comp.getPathInConfigFile());
}
Using the GMultipleStructureChoice widget
With this solution, we have to create such a widget as is:
final GMultipleStructureChoice msc = new GMultipleStructureChoice(fileName, new VehicleData(), true);
The widget will be displayed like that:
After selecting one of the found objects, user will have the possibility to copy it (in the clipboard) or to display it ...
Display option will open a pop up window displaynig the object as it has been defined internally:
TBW ...