The present document aims at explaining how the Core API (application programming interface) of ModelDesigner is organized. It explains how a model of a biological sequence (either DNA, RNA or protein) is handled in the system both on conceptual and programming sides.
A model of a biological sequence (DNA, RNA or protein), called biopolymere within ModelDesigner, can be understood as a description of a family where all the members satisfy the model. The model describes the biopolymere with two levels of details. The first level is called 'view': a model contains n>=1 view(s), where each view gives a particular description of the biopolymere. The second level is called 'entity': a 'view' is made of m>=1 entity(ies). What really describes a biopolymere is the entity: it is that element that contains the details. For example, an entity can be a letter (nucleotide for DNA and RNA, amino acid for proteins), a gap, a motif, etc.
The simplest biopolymere contains a single view, which contains a single entity.
More complex biopolymeres can be created since it is possible to 'link' a biopolymere with an entity. This property gives access to the notion of recursion: one can model a biopolymere with biopolymere(s).
Finally, on each entity, it is possible to apply some constraints such as position, mismatches, size and repetition.
To represent those concepts using objects, we have chosen to expose to the real world only interfaces. Real implementation is hidden.
There are four basic interfaces: BioPolymereModel, SimpleModel, ModelEntity and ModelProperties.
BioPolymereModel, SimpleModel and ModelEntity represents the elements of a model of a molecule: a biopolymere, a view and an entity, respectively. If you take a look at the API of those interfaces, you can see that there is no setter/getter methods for any attributes, which could represent the properties of the elements of a model.
To ensure an easy evolution of the modeling system, and its independance (regarding DNA, RNA or protein), the properties of biopolymere, view and entity are stored in tables handling key/value pairs. Such a table is accessible through the ModelProperties interface from which BioPolymereModel, SimpleModel and ModelEntity inherit. In that way, adding properties is as easy as adding a key/value pair to an element of the model.
It is worth noting that adding properties to BioPolymereModel and SimpleModel is not really important since the semantic of the model is carried out by the ModelEntities. This is the reason why a ModelEntity is always associated to a ModelEntityDescriptor which gives the definition of an entity: its name, molecular type and set of properties. This set gives the name of the properties (the keys) and the associated value type.
As we said above, the real implementation of the interfaces BioPolymereModel, SimpleModel, ModelEntity and ModelProperties is hidden. This is the reason why there are some factories: BioPolymereModelFactory, SimpleModelFactory and ModelEntityFactory. To facilitate the creation of model elements, BioPolymereModeler interface inherits from all the factory interfaces. In other words, BioPolymereModeler is the single entry point to instanciate BioPolymereModel, SimpleModel and ModelEntity objects.
To ensure the evolution of the system quite easily, the BioPolymereModeler is embedded into the class BioPolymereSystem which also has the responsibility to load the configuration file of ModelDesigner modeling system. Such a file defines the molecular type (DNA, RNA or protein), the corresponding alphabet and the set of descriptors for model entities.
Interfaces BioPolymereModel, SimpleModel, ModelEntity, ModelProperties and BioPolymereModeler are located in the package 'model.molecule'. The abstract class BioPolymereSystem is located in the package 'model.molecule.sys'.
Well, if you are curious and if you want to have to see the real implementations of the modeling interfaces BioPolymereModel, SimpleModel, ModelEntity, ModelProperties and BioPolymereModeler, have a look at the package 'model.molecule.ir'. But be aware that you CANNOT use directly those classes in your code NEITHER you can modify them to add particular code of yours! IN YOUR CODE, YOU MUST USE THE 'model.molecule' INTERFACES/FACTORIES.
As stated above, a BioPolymereModel is fully described by a set of ModelEntities, each of them being fully described by what we call a descriptor. A descriptor defines the following:
the name of the descriptor,
a set of properties. They are stored as key/value pairs. The key define the name of the property, whereas the value defines the Class of the value (String, Integer, ...).
a set of initial values for the properties. The key define the name of the property, whereas the value defines a default value that must respect the Class defined in the set of properties. When a new ModelEntity is created, the set of initial values is used by ModelDesigner to automatically configure the new ModelEntity.
a cloner which is responsible for creating a copy of a model entity,
a set of editors that allow interactive modification of a model entity,
a set of codecs (coder-decoder). They allow ModelDesigner to encode/decode well-formatted (SVG, XML) model entity.
Within ModelDesigner, descriptors are represented by the interface ModelDescriptor (its real implementation is not exposed to the developper), located in the package 'model.molecule'.
Some descriptors are reserved to ModelDesigner: STRING_VARIABLE, TAG, GAP, LEFT and RIGHT. Those names must not be used to define new user-defined descriptors. The STRING_VARIABLE descriptor allows you to put string variables into a model. The TAG descriptor can be used in a model to put position constraints. The GAP descriptor, as the name implied, can be used to put gaps in a model. Finally, LEFT and RIGHT descriptors must be used in every model you define: they mark the starting and ending point of a model.
Some property keys are reserved to ModelDesigner:
_ID_, _MOL_TYPE_, _DESCRIPTOR_, _ME_CONTENT_: these properties are for internal use of ModelDesigner,
_LABEL_KEY_, _BORDER_, _FOREGROUND_, _BACKGROUND_ and _FONT_: they are used to associate graphical properties to ModelEntities,
_TAG_NAME_, _TAG_POS_OPERATOR_, _TAG_POS_VALUE_ and _TAG_LABEL_: they are used to apply a positional constraint (TAG) to a ModelEntity,
_REPEAT_OPE_, _REPEAT_NB_, _REPEAT_UNIT_, _REPEAT_DMIN_ and _REPEAT_LOOKAHEAD_: they are used to apply a repetition constraint to a ModelEntity,
_MISMATCH_FROM_ and _MISMATCH_TO_: they are used to apply a mismatch constraint to a ModelEntity,
_SIZE_FROM_, _SIZE_TO_, _SIZE_PRIORITY_: they are used to apply a size constraint to a ModelEntity,
Those names must not be used to define new user-defined properties. More on properties will be found in the next chapter.
ModelDesigner uses a particular file, loaded at startup, used to define the type of biological sequence that can be modelled. Such a file contains four sections:
the list of available graphical ModelEntity editors,
the name of the modeler and the molecular type (protein, RNA or DNA),
the alphabet (amino/nucleic acids),
the set of required TAG, GAP, LEFT and RIGHT descriptors. It is completed by an additional set of particular descriptors, depending on the molecular type.
As an example of a real configuration file, here is the ModelDesigner configuration file to model proteins. In addition to the required TAG, GAP, LEFT and RIGHT descriptors, that configuration file defines the descriptors for TERMINAL, FAMILY, MODEL and MOTIF. A TERMINAL desriptor can be used to add a fixed string of amino/nucleic acids in your model. A FAMILY descriptor can be used to add a local choice in your model. Such a choice concerns the possibility to have a choice of amino/nucleic acids at a particular position in your model. A MODEL descriptor can be used to define a model from other models. Finally, the MOTIF descriptor can be used to add complex choice in your model. Such a Motif may be viewed as an oriented graph of ModelEntities.
The ModelDesigner Core contains the basic UIC (User Interface Components) allowing the visualization/edition of BioPolymereModels. As every Swing component, ModelDesigner basic UIC are divided into two parts: one part representing the data, and a second part representing the UI itself.
To allow flexible visualization, ModelDesigner uses a graph to represent a BioPolymereModel. The classes handling those visualization graphs are located in the package 'model.molecule.graph'. Two kinds of graph are available:
BPMGraphModel: represent the graph structure of a BioPolymereModel
MotifGraphModel: represent the graph structure of complex choice, such as Motif.
JBPMGraph: the Swing component aims at displaying a BPMGraphModel.
JMotifGraph: the Swing component aims at displaying a MotifGraphModel.
The other classes from the package 'model.molecule.graph', as well as the classes from the accompaniing package 'model.molecule.graph.event' are support classes for the JBPMGraph/BPMGraphModel and JMotifGraph/MotifGraphModel pairs.
As stated above, there are several types of ModelEntity available in ModelDesigner. They are identified by a descriptor, such as TERMINAL and STRING_VARIABLE. Of course, for the end-user, there is a need to provide him/her with UICs allowing the simple (mouse-driven) edition of ModelEntity properties. This is the purpose of the package 'model.ui': it contains the UIC for viewer/editor of ModelEntities. Among them, there is one editor that is quite powerfull: ModelEditor. It allows the visualization/edition of an entire BioPolymereModel by providing a JBPMGraph capable viewer associated with contextual menus and automatic handling of mouse actions. Through the contextual menus, ModelEditor gives access to the whole set of ModelEntity editors (TERMINAL, STRING_VARIABLE, etc).
A ModelEntity is responsible for editing its set of properties. When considering a particular ModelEntity you have By default, the package 'model.ui' provides the following editors:
JBPMGraph: the Swing component aims at displaying a BPMGraphModel.
JMotifGraph: the Swing component aims at displaying a MotifGraphModel.
More on the ModelDesigner basic UICs and will be presented in the next chapter.
Here is an example that creates a simple model with only one terminal (we suppose that ModelDesigner is configured with the Protein configuration file):
ModelEntityDescriptor desc;
BioPolymereModeler bpm;
BioPolymereModel model;
SimpleModel view;
ModelEntity me;
String modelerName, molType;
//gets the current modeler name
modelerName = BioPolymereSystem.getCurrentModelerName();
//gets the current molecular type
molType = bpm.getMolType();
//gets the modeler
bpm = BioPolymereSystem.getModeler(modelerName);
//creates the BioPolymereModel
model = bpm.createPolymere(molType);
//creates the SimpleModel
view = bpm.createModel(molType);
//add the SimpleModel to the BioPolymereModel
model.addModel(view);
//creates the left part
desc = bpm.getModelEntityDescriptor("LEFT");
me = bpm.createEntity(molType,desc);
//adds the LEFT ModelEntity to the SimpleModel
view.addEntity(me);
//creates the Terminal
desc = bpm.getModelEntityDescriptor("TERMINAL");
me = bpm.createEntity(molType,desc);
//adds the TERMINAL ModelEntity to the SimpleModel
view.addEntity(me);
//creates the right part
desc = bpm.getModelEntityDescriptor("RIGHT");
me = bpm.createEntity(molType,desc);
//adds the RIGHT ModelEntity to the SimpleModel
view.addEntity(me);
It is worth noting that LEFT and RIGHT ModelEntities are required in the definition of a SimpleModel. Also be aware that it is stricly forbidden to add a same ModelEntity object more than one times in a same BioPolymereModel. As an example, if you have to add two entities representing the same TERMINAL, you must instanciate two ModelEntity objects, then add them to your BioPolymereModel.
The line creating the Terminal ModelEntity automatically configures that Terminal with default values for its properties. If you have a look at the Protein configuration file, you can see those default values in the table 'initPolicy' within the descriptor of TERMINAL. The next section will give you more hints on how to change properties values.
As explained in the previous chapter, a ModelEntity is always associated to a descriptor. Among other things, such a descriptor defines the set of properties associated to the ModelEntity: that set fully defines a particular ModelEntity.
The Protein configuration file used in the previous example contains the descriptors for TERMINAL, FAMILY, MODEL and MOTIF. All of them defines a particular property, namely _CONTENT_. The value associated to that content is:
a String for TERMINAL, FAMILY,
a BioPolymereModel for MODEL,
a SGraph for MOTIF.
Such a content is related to the semantic information attached to the various ModelEntities of a BioPolymereModel. For a TERMINAL, the String value can be a single or a string of several letters. Those letters must be the ones define by the Alphabet section of the configuration file of ModelDesigner. For a FAMILY, the String value must be a list of letters (again those letters must be the ones define by the Alphabet section of the configuration file of ModelDesigner) separated by a comma. An example of a FAMILY content is 'V,I,L,F'.
The following code snapshot shows how to change the value of the _CONTENT_ property for a TERMINAL and a FAMILY (we suppose that ModelDesigner is configured with the Protein configuration file):
//creates a Terminal ModelEntity for a Valine
desc = bpm.getModelEntityDescriptor("TERMINAL");
me = bpm.createEntity(molType,desc);
me.setProperty("_CONTENT_","V");
//creates a Family ModelEntity for some hydrophobic aa
desc = bpm.getModelEntityDescriptor("FAMILY");
me = bpm.createEntity(molType,desc);
me.setProperty("_CONTENT_","V,I,L,F");
In that example, the letters assigned to the TERMINAL and the FAMILY content must come from the alphabet defined in the configuration file.
The following tables list the properties of descriptors LEFT, RIGHT, TAG, GAP and STRING_VARIABLE:
Table 3-1. LEFT descriptor properties
| Property | Description | Type | Default value | Editable |
|---|---|---|---|---|
| _TYPE_ | The descriptor type. | java.lang.String | LEFT | no |
| _NAME_ | The name of the entity. | java.lang.String | NH2 (protein), 5' (nucleic) | no |
| _GLOBALNAME_ | Name of the entity when used in the main BioPolymereModel. | java.lang.String | NH2 (protein), 5' (nucleic) | no |
| _LOCALNAME_ | Name of the entity when used in the sub-BioPolymereModel (MODEL, MOTIF). | java.lang.String | begin | no |
Table 3-2. RIGHT descriptor properties
| Property | Description | Type | Default value | Editable |
|---|---|---|---|---|
| _TYPE_ | The descriptor type. | java.lang.String | RIGHT | no |
| _NAME_ | The name of the entity. | java.lang.String | COOH (protein), 3' (nucleic) | no |
| _GLOBALNAME_ | Name of the entity when used in the main BioPolymereModel. | java.lang.String | COOH (protein), 3' (nucleic) | no |
| _LOCALNAME_ | Name of the entity when used in the sub-BioPolymereModel (MODEL, MOTIF). | java.lang.String | end | no |
Table 3-3. TAG descriptor properties
| Property | Description | Type | Default value | Editable |
|---|---|---|---|---|
| _TYPE_ | The descriptor type. | java.lang.String | TAG | no |
| _TAG_LABEL_ | The label of the tag | java.lang.String | Tag | yes |
| _TAG_NAME_ | The name of the tag | java.lang.String | Tag | yes |
| _TAG_POS_VALUE_ | Positional value | java.lang.Integer >= 0 | 0 | yes |
| _TAG_POS_OPERATOR_ | Positional operator | java.lang.String: ["+","-"," "] | + | yes |
Table 3-4. GAP descriptor properties
| Property | Description | Type | Default value | Editable |
|---|---|---|---|---|
| _TYPE_ | The descriptor type. | java.lang.String | GAP | no |
| _NAME_ | The name of the gap. | java.lang.String | [_SIZE_FROM_.._SIZE_TO_] | yes |
| _SIZE_FROM_ | Minimal size of the gap. | java.lang.Integer | 0 | yes |
| _SIZE_TO_ | Maximal size of the gap. | java.lang.Integer | -1 (i.e. the size of the sequence being analyzed) | yes |
| _SIZE_PRIORITY_ | How to get the gap smaller of larger first ? | java.lang.Sting: [smaller, larger] | smaller | yes |
Table 3-5. STRING_VARIABLE descriptor properties
| Property | Description | Type | Default value | Editable |
|---|---|---|---|---|
| _TYPE_ | The descriptor type. | java.lang.String | STRING_VARIABLE | no |
| _NAME_ | The name of the string variable. Must be any string of characters starting with an upper-case character | java.lang.String | X | yes |
| _MISMATCH_FROM_ | Minimal number of mismatches. | java.lang.Integer | 0 | yes |
| _MISMATCH_TO_ | Maximal number of mismatches. | java.lang.Integer | 0 | yes |
| _SIZE_FROM_ | Minimal size of the string that can be attached to the variable. | java.lang.Integer | 0 | yes |
| _SIZE_TO_ | Maximal size of the string that can be attached to the variable. | java.lang.Integer | -1 (i.e. the size of the sequence being analyzed) | yes |
| _SIZE_PRIORITY_ | How to get the string: smaller of larger first ? | java.lang.Sting: [smaller, larger] | smaller | yes |
The following tables list the properties of descriptors TERMINAL, FAMILY, MOTIF and MODEL:
Table 3-6. TERMINAL descriptor properties
| Property | Description | Type | Default value | Editable |
|---|---|---|---|---|
| _TYPE_ | The descriptor type. | java.lang.String | TERMINAL | no |
| _CONTENT_ | The content of the Terminal: single letter or a string of several letters. Letters are from a valid alphabet. | java.lang.String | A | yes |
| _MISMATCH_FROM_ | Minimal number of mismatches. | java.lang.Integer | 0 | yes |
| _MISMATCH_TO_ | aximal number of mismatches. | java.lang.Integer | 0 | yes |
Table 3-7. FAMILY descriptor properties
| Property | Description | Type | Default value | Editable |
|---|---|---|---|---|
| _TYPE_ | The descriptor type. | java.lang.String | FAMILY | no |
| _Name_ | The name of the family. | java.lang.String | N/A (molecular type dependent) | yes |
| _CONTENT_ | The content of the Family: a list of letters (those letters are from a valid alphabet) separated by a comma. | java.lang.String | A,G | yes |
Table 3-8. MOTIF descriptor properties
| Property | Description | Type | Default value | Editable |
|---|---|---|---|---|
| _TYPE_ | The descriptor type. | java.lang.String | MOTIF | no |
| _CONTENT_ | The content of the Motif: a graph. | model.SGraph.SGraph | null | yes |
| _NAME_ | The name of the motif. | java.lang.String | Motif | yes |
| _MISMATCH_FROM_ | Minimal number of mismatches. | java.lang.Integer | 0 | yes |
| _MISMATCH_TO_ | Maximal number of mismatches. | java.lang.Integer | 0 | yes |
| _SIZE_FROM_ | Minimal size of the motif. | java.lang.Integer | 0 | yes |
| _SIZE_TO_ | Maximal size of the motif. | java.lang.Integer | -1 (i.e. the size of the sequence being analyzed) | yes |
| _SIZE_PRIORITY_ | How to get the motif: smaller of larger first ? | java.lang.Sting: [smaller, larger] | smaller | yes |
Table 3-9. MODEL descriptor properties
| Property | Description | Type | Default value | Editable |
|---|---|---|---|---|
| _TYPE_ | The descriptor type. | java.lang.String | MODEL | no |
| _CONTENT_ | The content of the Model. | model.molecule.BioPolymereModel | null | yes |
| _NAME_ | The name of the model | java.lang.String | Model | yes |
| _MISMATCH_FROM_ | Minimal number of mismatches. | java.lang.Integer | 0 | yes |
| _MISMATCH_TO_ | Maximal number of mismatches. | java.lang.Integer | 0 | yes |
| _SIZE_FROM_ | Minimal size of the model | java.lang.Integer | 0 | yes |
| _SIZE_TO_ | Maximal size of the model | java.lang.Integer | -1 (i.e. the size of the sequence being analyzed) | yes |
| _SIZE_PRIORITY_ | How to get the model smaller of larger first ? | java.lang.Sting: [smaller, larger] | smaller | yes |
The following table list the properties common to all descriptors:
Table 3-10. Common Properties
| Property | Description | Type | Default value | Editable |
|---|---|---|---|---|
| _BACKGROUND_ | A graphical property that defines the background color of the GUI element associated to a ModelEntity. | java.awt.Color | N/A (descriptor dependent) | yes |
| _FOREGROUND_ | A graphical property that defines the foreground (text) color of the GUI element associated to a ModelEntity. | java.awt.Color | N/A (descriptor dependent) | yes |
| _BORDER_ | A graphical property that defines the border style of the GUI element associated to a ModelEntity. | javax.swing.border.Border | N/A (descriptor dependent) | yes |
| _LABEL_KEY_ | A graphical property that defines which property key has to be used to display a label in the GUI element associated to a ModelEntity. | java.lang.String | N/A (descriptor dependent) | yes |
| _FONT_ | A graphical property that defines the font to be used to display the GUI element associated to a ModelEntity. | java.awt.Font | N/A (OS dependent, set by ModelDesigner at startup) | yes |
A Motif can be created by instanciating a ModelEntity with the MOTIF descriptor. To model the content of a Motif we have chosen to use a graph structure. As every graph, the Motif graph is made of nodes and edges. In the context of ModelDesigner, the Motif graph's nodes are decorated with ModelEntity objects: the graph itself forms the topology of the Motif, whereas nodes' content (i.e. ModelEntities) forms its semantic.
The ModelDesigner Core API contains the package 'model.SGraph' which can be used to describe a Motif. The package is quite simple since it only contains three clases: SGraph, SNode and SEdge.
The following code snapshot creates a model of a sequence with a single Motif:
ModelEntityDescriptor desc;
BioPolymereModeler bpm;
BioPolymereModel model;
SimpleModel view;
ModelEntity me, motif;
String modelerName, molType;
SGraph graph;
SNode source, target, node;
SEdge edge;
//gets the current modeler name
modelerName = BioPolymereSystem.getCurrentModelerName();
//gets the current molecular type
molType = bpm.getMolType();
//gets the modeler
bpm = BioPolymereSystem.getModeler(modelerName);
//creates the BioPolymereModel
model = bpm.createPolymere(molType);
//creates the SimpleModel
view = bpm.createModel(molType);
//add the SimpleModel to the BioPolymereModel
model.addModel(view);
//creates the left part
desc = bpm.getModelEntityDescriptor("LEFT");
me = bpm.createEntity(molType,desc);
//adds the LEFT ModelEntity to the SimpleModel
view.addEntity(me);
//creates the Motif
desc = bpm.getModelEntityDescriptor("MOTIF");
motif = bpm.createEntity(molType,desc);
//adds the Motif ModelEntity to the SimpleModel
view.addEntity(motif);
//creates the right part
desc = bpm.getModelEntityDescriptor("RIGHT");
me = bpm.createEntity(molType,desc);
//adds the RIGHT ModelEntity to the SimpleModel
view.addEntity(me);
In that example, we have created a Motif ModelEntity, but the Motif is still empty: we now have to create the SGraph that model the Motif. The following code snapshot shows the minimal SGraph modeling the basic structure of a Motif (the following code continues the previous one):
//creates an empty graph
sgraph = new SGraph();
//creates the left part of the Motif
desc = bpm.getModelEntityDescriptor("LEFT");
me = bpm.createEntity(molType,desc);
source = new SNode(me);
//adds the left node to the graph
sgraph.addNode(source);
//creates the right part of the Motif
desc = bpm.getModelEntityDescriptor("RIGHT");
me = bpm.createEntity(molType,desc);
target = new SNode(me);
//adds the right node to the graph
sgraph.addNode(target);
It is very important to note that a Motif must start with a node containing a LEFT ModelEntity and must end with a node containing a RIGHT ModelEntity. The rest of the Motif has to be inserted between those two nodes. For the purpose of our example, our Motif has to model a choice between a string variable 'X' and the terminal "AVTG" (we consider working with Protein molecular type).
Here is the code that does that (the following code continues the previous one):
//creates the string variable
desc = bpm.getModelEntityDescriptor("STRING_VARIABLE");
me = bpm.createEntity(molType,desc);
//create the SNode representation of the string variable
node = new SNode(me);
//adds the new node to the graph
sgraph.addNode(node);
//link the left node to the new node
edge = new SEdge(source, node);
sGraph.addEdge(edge);
//link the new node to the right node
edge = new SEdge(node, target);
sGraph.addEdge(edge);
//creates the terminal
desc = bpm.getModelEntityDescriptor("TERMINAL");
me = bpm.createEntity(molType,desc);
me.setProperty("_CONTENT_","AVTG");
//create the SNode representation of the terminal
node = new SNode(me);
//adds the new node to the graph
sgraph.addNode(node);
//link the left node to the new node
edge = new SEdge(source, node);
sGraph.addEdge(edge);
//link the new node to the right node
edge = new SEdge(node, target);
sGraph.addEdge(edge);
Be carefull when creating edges: a SGraph is oriented, it cannot contains cycles, it has to be a single connected component and it has to be walked through from the left node to the right node.
A BioPolymereModel can be saved on disk in a XML formatted file. In order to avoid the design of a specific DTD (or XML schema) to handle a file format for BioPolymereModels, we haven chosen to use the JavaBeans XML Codec (java.beans.XMLEncoder and java.beans.XMLDecoder). Since the model.molecule package does not expose the real implementations of the interfaces used to represent a model (i.e. a BioPolymereModel), we have designed a set of classes that are real beans. Those classes contain the code to 'encode' a BioPolymereModel into such a bean, as well as the code to do the decode operation, i.e. converting a bean into a BioPolymereModel.
The ModelDesigner package 'model.molecule.codec.xml' proposes the class CDCBioPolymereModel that contains two methods: encode() and decode().
Here is a code snapshot to encode a BioPolymereModel in XML and save it in the file aFile.xml:
FileOutputStream fos;
BufferedOutputStream bos;
XMLEncoder e;
CDCBioPolymereModel cdcBpm;
try {
//open a file in write mode
fos = new FileOutputStream("aFile.xml");
//wrap this file into a buffered stream (not required, but
//recommanded for performance issue)
bos = new BufferedOutputStream(fos);
//creates an instance of an XMLEncoder
e = new XMLEncoder(bos);
//convert a BioPolymereModel instance (bpm)
cdcBpm = CDCBioPolymereModel.encode(bpm);
//serialize cdcBpm
e.writeObject(cdcBpm);
//close the file stream
e.close();
}
catch (Exception ex){
System.err.println("Error: "+ex.toString());
}
Now, given an XML file created with the above code, you just need to do the following to create the BioPolemereModel data structure:
FileInputStream fis;
BufferedInputStream bis;
XMLDecoder d;
CDCBioPolymereModel cdcBpm;
BioPolymereModel bpm;
try {
//open a file in read mode
fis = new FileInputStream("aFile.xml");
//wrap this file into a buffered stream (not required, but
//recommanded for performance issue)
bis = new BufferedInputStream(fis);
//creates an instance of an XMLDecoder
d = new XMLDecoder(bis);
//read the file content, which results in creating
//an instance of CDCBioPolymereModel
cdcBpm = (CDCBioPolymereModel) d.readObject();
//create a BioPolymereModel instance from cdcBpm
bpm = CDCBioPolymereModel.decode(cdcBpm);
//close the file stream
d.close();
}
catch (Exception ex){
System.err.println("Error: "+ex.toString());
}
As stated in the previous chapter, ModelDesigner provides basic UICs to display a BioPolymereModel. The following code snapshot shows how to create a BioPolymereModel viewer:
BioPolymereModel bpm; BPMGraphModel model; JBPMGraph view; //creates a BioPymereModel: bpm //... see previous examples //creates the graph model of bpm model = new BPMGraphModel(bpm, true); //creates the graph model viewer view = JBPMGraph(model);
The JBPMGraph instance is a Swing component, so you can put it anywhere within another Swing GUI (such as a JPanel, JFrame). It is worth noting that JBPMGraph does not provide a scroll: if you need one, just put the JBPMGraph instance within a JScrollPane.
Both JBPMGraph and BPMGraphModel implement an event notification system to prevent any modifications made on a BioPolymereModel. More precisely, BPMGraphModel implements two event systems. The first one sends notification messages when the structure of the BioPolymereModel has been updated (addition/removal of SimpleModels/ModelEntities). The second one sends messages when the properties attached to ModelEntities have been updated. Concerning JBPMGraph, it just provides a mechanism sending notification messages when the user selects ModelEntity(ies). In summary, if you need to deal with BioPolymereModel edition, register a listener on the BPMGraphModel, and if you want to deal with selection, register a listener on JBPMGraph.
Here is a code snapshot showing how to add listeners on BPMGraphModel and JBPMGraph:
BioPolymereModel bpm; BPMGraphModel model; JBPMGraph view; MyModelChangeListener mcl; MyPropertyChangeListener pcl; MyMDGraphSelectionListener gsl; //creates a BioPymereModel: bpm //... see previous examples //creates the graph model of bpm model = new BPMGraphModel(bpm, true); //creates a listener for BioPymereModel edition. //We suppose here that class MyModelChangeListener is a user-defined //class implementing model.molecule.event.ModelChangeListener interface. mcl = new MyModelChangeListener(); //adds the listener for edition model.addModelChangeListener(mcl); //creates a listener for property edition. //We suppose here that class MyPropertyChangeListener is a user-defined //class implementing java.beans.PropertyChangeListener interface. pcl = new MyPropertyChangeListener(); //adds the listener for property model.addPropertyChangeListener(pcl); //creates the graph model viewer view = JBPMGraph(model); //creates a listener for entity selection. //We suppose here that class MyPropertyChangeListener is a user-defined //class implementing java.beans.PropertyChangeListener interface. gsl = new MyMDGraphSelectionListener(); //adds the listener for selection view.addMDGraphSelectionListener(gsl);
Please, refer to the Java documentation of classes BPMGraphModel and JBPMGraph (package 'model.molecule.graph') for more details. In addition, package 'model.molecule.graph.event' contains the code relating to MDGraphSelection listener/event, and package 'model.molecule.event' contains the code relating to ModelChange listener/event. Regarding PropertyChange listener/event, you have to refer to package 'java.beans'.