The Core of ModelDesigner


Table of Contents
1. Introduction
1.1. Purpose of the document
2. Modeling a biological sequence
2.1. General concepts
2.2. Modeling a biological sequence with objects
2.3. The ModelEntity descriptors
2.4. The ModelDesigner configuration file
2.5. The ModelDesigner basic UI
3. Programming with the ModelDesigner Core API
3.1. Creating a simple BioPolymereModel
3.2. Changing ModelEntity properties
3.3. Creating a BioPolymereModel with a Motif
3.4. Saving/reading a BioPolymereModel on/from disk
3.5. Displaying a BioPolymereModel
List of Tables
3-1. LEFT descriptor properties
3-2. RIGHT descriptor properties
3-3. TAG descriptor properties
3-4. GAP descriptor properties
3-5. STRING_VARIABLE descriptor properties
3-6. TERMINAL descriptor properties
3-7. FAMILY descriptor properties
3-8. MOTIF descriptor properties
3-9. MODEL descriptor properties
3-10. Common Properties
List of Figures
2-1. A BioPolymereModel.
3-1. A Motif.

Chapter 1. Introduction

1.1. Purpose of the document

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.


Chapter 2. Modeling a biological sequence

2.1. General concepts

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.


2.2. Modeling a biological sequence with objects

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.

Figure 2-1. A BioPolymereModel.

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.


2.3. The ModelEntity descriptors

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.


2.4. The ModelDesigner configuration file

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.


2.5. The ModelDesigner basic UI

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.

Those two graph data structures are associated with the two UI components:

  • 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.


Chapter 3. Programming with the ModelDesigner Core API

3.1. Creating a simple BioPolymereModel

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.


3.2. Changing ModelEntity properties

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

PropertyDescriptionTypeDefault valueEditable
_TYPE_The descriptor type.java.lang.StringLEFTno
_NAME_The name of the entity.java.lang.StringNH2 (protein), 5' (nucleic)no
_GLOBALNAME_Name of the entity when used in the main BioPolymereModel.java.lang.StringNH2 (protein), 5' (nucleic)no
_LOCALNAME_Name of the entity when used in the sub-BioPolymereModel (MODEL, MOTIF).java.lang.Stringbeginno

Table 3-2. RIGHT descriptor properties

PropertyDescriptionTypeDefault valueEditable
_TYPE_The descriptor type.java.lang.StringRIGHTno
_NAME_The name of the entity.java.lang.StringCOOH (protein), 3' (nucleic)no
_GLOBALNAME_Name of the entity when used in the main BioPolymereModel.java.lang.StringCOOH (protein), 3' (nucleic)no
_LOCALNAME_Name of the entity when used in the sub-BioPolymereModel (MODEL, MOTIF).java.lang.Stringendno

Table 3-3. TAG descriptor properties

PropertyDescriptionTypeDefault valueEditable
_TYPE_The descriptor type.java.lang.StringTAGno
_TAG_LABEL_The label of the tagjava.lang.StringTagyes
_TAG_NAME_The name of the tagjava.lang.StringTagyes
_TAG_POS_VALUE_Positional valuejava.lang.Integer >= 00yes
_TAG_POS_OPERATOR_Positional operatorjava.lang.String: ["+","-"," "]+yes

Table 3-4. GAP descriptor properties

PropertyDescriptionTypeDefault valueEditable
_TYPE_The descriptor type.java.lang.StringGAPno
_NAME_The name of the gap.java.lang.String[_SIZE_FROM_.._SIZE_TO_]yes
_SIZE_FROM_Minimal size of the gap.java.lang.Integer0yes
_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]smalleryes

Table 3-5. STRING_VARIABLE descriptor properties

PropertyDescriptionTypeDefault valueEditable
_TYPE_The descriptor type.java.lang.StringSTRING_VARIABLEno
_NAME_The name of the string variable. Must be any string of characters starting with an upper-case characterjava.lang.StringXyes
_MISMATCH_FROM_Minimal number of mismatches.java.lang.Integer0yes
_MISMATCH_TO_Maximal number of mismatches.java.lang.Integer0yes
_SIZE_FROM_Minimal size of the string that can be attached to the variable.java.lang.Integer0yes
_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]smalleryes

The following tables list the properties of descriptors TERMINAL, FAMILY, MOTIF and MODEL:

Table 3-6. TERMINAL descriptor properties

PropertyDescriptionTypeDefault valueEditable
_TYPE_The descriptor type.java.lang.StringTERMINALno
_CONTENT_The content of the Terminal: single letter or a string of several letters. Letters are from a valid alphabet.java.lang.StringAyes
_MISMATCH_FROM_Minimal number of mismatches.java.lang.Integer0yes
_MISMATCH_TO_aximal number of mismatches.java.lang.Integer0yes

Table 3-7. FAMILY descriptor properties

PropertyDescriptionTypeDefault valueEditable
_TYPE_The descriptor type.java.lang.StringFAMILYno
_Name_The name of the family.java.lang.StringN/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.StringA,Gyes

Table 3-8. MOTIF descriptor properties

PropertyDescriptionTypeDefault valueEditable
_TYPE_The descriptor type.java.lang.StringMOTIFno
_CONTENT_The content of the Motif: a graph.model.SGraph.SGraphnullyes
_NAME_The name of the motif.java.lang.StringMotifyes
_MISMATCH_FROM_Minimal number of mismatches.java.lang.Integer0yes
_MISMATCH_TO_Maximal number of mismatches.java.lang.Integer0yes
_SIZE_FROM_Minimal size of the motif.java.lang.Integer0yes
_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]smalleryes

Table 3-9. MODEL descriptor properties

PropertyDescriptionTypeDefault valueEditable
_TYPE_The descriptor type.java.lang.StringMODELno
_CONTENT_The content of the Model.model.molecule.BioPolymereModelnullyes
_NAME_The name of the modeljava.lang.StringModelyes
_MISMATCH_FROM_Minimal number of mismatches.java.lang.Integer0yes
_MISMATCH_TO_Maximal number of mismatches.java.lang.Integer0yes
_SIZE_FROM_Minimal size of the modeljava.lang.Integer0yes
_SIZE_TO_Maximal size of the modeljava.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]smalleryes

The following table list the properties common to all descriptors:

Table 3-10. Common Properties

PropertyDescriptionTypeDefault valueEditable
_BACKGROUND_A graphical property that defines the background color of the GUI element associated to a ModelEntity.java.awt.ColorN/A (descriptor dependent)yes
_FOREGROUND_A graphical property that defines the foreground (text) color of the GUI element associated to a ModelEntity.java.awt.ColorN/A (descriptor dependent)yes
_BORDER_A graphical property that defines the border style of the GUI element associated to a ModelEntity.javax.swing.border.BorderN/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.StringN/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.FontN/A (OS dependent, set by ModelDesigner at startup)yes

3.3. Creating a BioPolymereModel with a Motif

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).

Figure 3-1. A Motif.

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.


3.4. Saving/reading a BioPolymereModel on/from disk

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()); 
} 


3.5. Displaying a BioPolymereModel

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'.