Chapter 2: Understanding the DataBean Framework  Chapter 3: Using the Message Bridge GUI

Chapter 2: Understanding the DataBean Framework

Binding framework

Individual DataBeans rely on an underlying binding framework that allows the components of a document to be mapped to in-memory objects reflecting the document’s structure. These objects can then be consumed, manipulated, and possibly serialized back into a document. The runtime classes making up the binding framework provide the implementation of all get() and set() methods exposed for access to class instances, attributes, and data. They also handle deserialization (parsing a document into a set of related classes), serialization (generating a document from the data stored in the related classes) and validation.


DataBean object graph

It is important to understand the DataBean object graph in order to access these features correctly. When a schema is imported into Message Bridge, a root element is identified directly by Message Bridge itself, or is selected by the user. When code is generated, Message Bridge creates two types of DataBeans::

Both Root and Element DataBeans expose various types of get() and set() methods that are used to navigate through objects in the object graph and to access or modify the content of those objects. All DataBeans extend class DataBeanElement.

Figure 2-1: DataBean object graph

Root DataBeans expose additional methods for interacting with the main document they represent. This main document is an instance of a document that conforms to a schema and has a given root. All Root DataBeans extend class DataBeanOpaque, which itself extends class DataBeanElement.


DataBean method summary

All DataBeans expose the following methods:

Root DataBeans also expose the following additional methods:


Names and identifiers

The set of strings allowed in schemas is much larger than the set of valid Java class identifiers. Therefore, Message Bridge will change the names of schema components when generating DataBeans, according to the following approach. Message Bridge:


An example

A good way to illustrate DataBean is to work through an example. In this example, Message Bridge generates bindings for a Recipe schema defined in the following DTD:


Recipe DTD schema

The following DTD, called Recipe, is mapped to Java classes described in Table 2-1.

XML document instances conforming to this DTD can have two potential roots: recipe and comments. In this example, recipe is the root.

<!ELEMENT Recipe (#PCDATA | IndexCard | IngredientList StepList)* >
<!ELEMENT IndexCard (Name, Description, Source) >
<!ELEMENT Name (#PCDATA)>
<!ELEMENT Description (#PCDATA)>
<!ELEMENT Source (#PCDATA)>
<!ELEMENT IngredientList (Ingredient+)>
<!ATTLIST IngredientList serves CDATA #REQUIRED>
<!ELEMENT Ingredient (Food,Quantity) >
<!ELEMENT Food (#PCDATA)>
<!ELEMENT Quantity (#PCDATA)>
<!ELEMENT StepList (Step+) >
<!ELEMENT Step (#PCDATA)>
<!ELEMENT Comments (#PCDATA)>

Schema to class mappings

A summary of how schemas are mapped to classes follows:

The following table shows some highlights of the DataBeans generated for the Recipe DTD:

Table 2-1: DTD to Java class mapping

DTD element

Generated Java class

An element containing only text.

<!ELEMENT Name (#PCDATA)>

A single Java class representing the element, with public accessor and mutator methods for the text.

Class: Name

Methods:

 public String getData()
 public void setData( String data )

An element containing child elements.

<!ELEMENT Ingredient (Food, Quantity)

A Java class representing the parent element, with public accessor and mutator methods for the child element.

Class: Ingredient

Methods:

 public Food getFood()
 public Food setFood()
 public Quantity getQuantity()
 public Quantity setQuantity()

An element containing a repeating child and attributes.

<!ELEMENT IngredientList (Ingredient+)>

<!ATTLIST IngredientList serves CDATA #REQUIRED>

A Java class representing the parent element, with public methods for accessing and modifying the list of children.

Class: IngredientList

Methods:

public Ingredient setIngredient( int index )
public Ingredient getIngredient( int index )
java.lang.Object (getint index)
java.util.List get Ingredient()
void set Ingredient (Ingredient instance, int index)
java.lang.String getAttributeServes(java.lang.String attrValue)

An element containing child elements and text. Recipe is the root.

<!ELEMENT Recipe (#PCDATA | IndexCard | IngredientList | StepList )*>

A Java class representing the parent with accessor and mutator methods for each child, for the text data, and for the object. The get object method is for any element that has more than one child and enables you to retrieve the children in the order they were originally specified.

Class: Recipe

Methods:

public java.util.List getIndexCard()
public IndexCard getIndexCard(int index)
public void setIndexCard(IndexCard instance,    int index)
public IndexCard setIndexCard(int index)
public java.util.List getIngredientList()
public IngredientList getIngredientList(int    index)
public void setIngredientList(IngredientList    instance, int index)
public IngredientList setIngredientList(int    index)
public java.util.List getStepList()
public StepList getStepList(int index)
public void setStepList(StepList instance, int    index)
public StepList setStepList(int index)
public Data getData( int index )
public Data setData( String data, int index )
public Object get( int index )
public void setMainDocument
   ( com.sybase.DataBean.serializable.
   DataBeanSerializable mainDocument )
public void validate()
public void serializeXML
   ( java.io.OutputStream ostrm )
public void deserializeXML
   ( java.io.InputStream istrm, boolean    validate )

Using the generated DataBeans

This section contains examples of code written using generated DataBeans from the previous Recipe DTD.


Constructing instances of classes from an XML document

The following example illustrates constructing instances of Recipe classes from an XML document. In this example, false means there is no validation against a DTD document.

FileInputStream fiStream = new FileInputStream    xmlFileName);

Recipe iRecipe = new Recipe(fiStream, false);

or

FileInputStream fiStream = new FileInputStream    xmlFileName);

Recipe iRecipe = new Recipe();

iRecipe.deserializeXML(fiStream, false);


Getting the IngredientList from the Recipe

IngredientList ingList = iRecipe.getIngredientList();


Using getAttribute to get the number of servings

String serves = ingList.getAttributeServes();


Getting the ingredient elements from the IngredientList

To get the first ingredient:

     Ingredient ing = ingList.getIngredient(0);

     if( !ing.hasValidElement())

  {

       // We are at the end of the list of Ingredients         ing=null;

       break;

   }

To target all ingredients:

java.util.List ings=ingList.getIngredients();


Constructing a new instance of Recipe from scratch (a new Recipe XML document)

Recipe oRecipe = new Recipe();


Setting the food and quantity of an Ingredient in a Recipe

oRecipe.setIngredientList(0).setIngredient(0).    setFood().setData(“Onions”);

oRecipe.setIngredientList(0).setIngredient(0).    setQuantity().setData(“2”)


Creating an XML document from instances of Recipe class

FileOutputStream foStream = new FileOutputStream    (xmlFileName);

oRecipe.serializeXML(foStream);


Using DataBeanOpaque to get DTD name prior to choosing binding classes

FileInputStream fiStream =    new FileInputStream(xmlFileName);

DataBeanOpaque recipeVersionUnknown =    new DataBeanOpaque(fiStream, false);

String dtdName = recipeVersionUnknown.    getDocTypeSystemID();

if (dtdName.equals("recipe.dtd"))

{

     // Do something with version 1 recipes.

      com.cooksmart.v1.Recipe = new     com.cooksmart.v1.Recipe(recipeVersionUnknown,     true);

.

.

}

else

{

     if (dtdName.equals("recipe_v2.dtd"))

  {

      // Do something with version 2 recipes.

      com.cooksmart.v2.Recipe = new    com.cooksmart.v2.Recipe(recipeVersionUnknown,    true);

.

.

  }

}





Copyright © 2005. Sybase Inc. All rights reserved. Chapter 3: Using the Message Bridge GUI