License     Codehaus     OpenEJB     OpenJMS     OpenORB     Tyrex     
 

Main
  Home
  About
  Features
  Download
  Maven 2 support
  API
  DTD & Schemas
  Recent changes
  RSS news feed

Development/Support
  Mailing Lists
  SVN/JIRA
  Contributing
  Support
  Prof. services

Related projects
  Spring ORM support
  Spring XML factories

XML
  Using XML
  XML Mapping
  XML FAQ
  XML HOW-TOs
  Custom Handlers
  Best practice

XML Code Generator
  Code Generator
  Properties
  Custom bindings
  Ant task
  Schema Support
  Example

JDO
  Introduction
  Using JDO
  JDO Config
  Types
  JDO Mapping
  JDO FAQ
  JDO Examples
  JDO HOW-TOs
  Other Features
  JDO sample JAR

Advanced JDO
  Caching
  OQL
  Trans. & Locks
  Design
  KeyGen
  Long Trans.
  Nested Attrs.
  Pooling Examples
  LOBs
  Best practice

More
  Presentations
  The Examples
  3rd Party Tools
  JDO Tests
  XML Tests
  Configuration
  Tips & Tricks
  Full JavaDoc
  CastorWiki
 
 

About
  License
  Contributors
  Marketplace
  Status, Todo
  Changelog
  Library
  Contact
  Project Name

  



Example using the Castor XML code generator

Documentation Author(s):
Werner Guttmann

API Reference: The XML code generator API


Introduction
The schema file
Running the XMl code generator
The generated code
    The Item.java class
    The PriceType.java class
    The Invoice.java class


Introduction

In this section we illustrate the use of the Source Generator by explaining the generated classes from a given XML schema. The XML code generator is going to be used with the “java class mapping” property set to element (default value).

The schema file

The input file is the schema file given with the XML code generator example in the distribution of Castor (under /src/examples/SourceGenerator/invoice.xsd).

<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	targetNamespace="http://castor.exolab.org/Test/Invoice">

	<xsd:annotation>
		<xsd:documentation>
			This is a test XML Schema for Castor XML.
		</xsd:documentation>
	</xsd:annotation>

	<!--
		A simple representation of an invoice. This is simply an example
		and not meant to be an exact or even complete representation of an invoice.
	-->
	<xsd:element name="invoice">
		<xsd:annotation>
			<xsd:documentation>
				A simple representation of an invoice
			</xsd:documentation>
		</xsd:annotation>

		<xsd:complexType>
			<xsd:sequence>
				<xsd:element name="ship-to">
					<xsd:complexType>
						<xsd:group ref="customer" />
					</xsd:complexType>
				</xsd:element>
				<xsd:element ref="item"
					maxOccurs="unbounded" minOccurs="1" />
				<xsd:element ref="shipping-method" />
				<xsd:element ref="shipping-date" />
			</xsd:sequence>
		</xsd:complexType>
	</xsd:element>

	<!-- Description of a customer -->
	<xsd:group name="customer">
		<xsd:sequence>
			<xsd:element name="name" type="xsd:string" />
			<xsd:element ref="address" />
			<xsd:element name="phone"
				type="TelephoneNumberType" />
		</xsd:sequence>
	</xsd:group>

	<!-- Description of an item -->
	<xsd:element name="item">
		<xsd:complexType>
			<xsd:sequence>
				<xsd:element name="Quantity"
					type="xsd:integer" minOccurs="1" maxOccurs="1" />
				<xsd:element name="Price" type="PriceType"
					minOccurs="1" maxOccurs="1" />
			</xsd:sequence>
			<xsd:attributeGroup ref="ItemAttributes" />
		</xsd:complexType>
	</xsd:element>

	<!-- Shipping Method -->
	<xsd:element name="shipping-method">
		<xsd:complexType>
			<xsd:sequence>
				<xsd:element name="carrier"
					type="xsd:string" />
				<xsd:element name="option"
					type="xsd:string" />
				<xsd:element name="estimated-delivery"
					type="xsd:duration" />
			</xsd:sequence>
		</xsd:complexType>
	</xsd:element>

	<!-- Shipping date -->
	<xsd:element name="shipping-date">
		<xsd:complexType>
			<xsd:sequence>
				<xsd:element name="date" type="xsd:date" />
				<xsd:element name="time" type="xsd:time" />
			</xsd:sequence>
		</xsd:complexType>
	</xsd:element>

	<!-- A simple U.S. based Address structure -->
	<xsd:element name="address">
		<xsd:annotation>
			<xsd:documentation>
				Represents a U.S. Address
			</xsd:documentation>
		</xsd:annotation>

		<xsd:complexType>
			<xsd:sequence>
				<!-- street address 1 -->
				<xsd:element name="street1"
					type="xsd:string" />
				<!-- optional street address 2 -->
				<xsd:element name="street2"
					type="xsd:string" minOccurs="0" />
				<!-- city-->
				<xsd:element name="city" type="xsd:string" />
				<!-- state code -->
				<xsd:element name="state"
					type="stateCodeType" />
				<!-- zip-code -->
				<xsd:element ref="zip-code" />
			</xsd:sequence>
		</xsd:complexType>
	</xsd:element>

	<!-- A U.S. Zip Code -->
	<xsd:element name="zip-code">
		<xsd:simpleType>
			<xsd:restriction base="xsd:string">
				<xsd:pattern value="[0-9]{5}(-[0-9]{4})?" />
			</xsd:restriction>
		</xsd:simpleType>
	</xsd:element>

	<!-- State Code
		obviously not a valid state code....but this is just
		an example and I don't feel like creating all the valid
		ones.
	-->
	<xsd:simpleType name="stateCodeType">
		<xsd:restriction base="xsd:string">
			<xsd:pattern value="[A-Z]{2}" />
		</xsd:restriction>
	</xsd:simpleType>

	<!-- Telephone Number -->
	<xsd:simpleType name="TelephoneNumberType">
		<xsd:restriction base="xsd:string">
			<xsd:length value="12" />
			<xsd:pattern value="[0-9]{3}-[0-9]{3}-[0-9]{4}" />
		</xsd:restriction>
	</xsd:simpleType>

	<!-- Cool price type -->
	<xsd:simpleType name="PriceType">
		<xsd:restriction base="xsd:decimal">
			<xsd:fractionDigits value="2" />
			<xsd:totalDigits value="5" />
			<xsd:minInclusive value="1" />
			<xsd:maxInclusive value="100" />
		</xsd:restriction>
	</xsd:simpleType>

	<!-- The attributes for an Item -->
	<xsd:attributeGroup name="ItemAttributes">
		<xsd:attribute name="Id" type="xsd:ID" minOccurs="1"
			maxOccurs="1" />
		<xsd:attribute name="InStock" type="xsd:boolean"
			default="false" />
		<xsd:attribute name="Category" type="xsd:string"
			use="required" />
	</xsd:attributeGroup>
</xsd:schema>

The structure of this schema is simple: it is composed of a top-level element which is a complexType with references to other elements inside. This schema represents a simple invoice: an invoice is a customer (customer top-level group), an article (item element), a shipping method (shipping-method element) and a shipping date (shipping-date element). Notice that the ship-to element uses a reference to an address element. This address element is a top-level element that contains a reference to a non-top-level element (the zip-cod element). At the end of the schema we have two simpleTypes for representing a telephone number and a price. The Source Generator is used with the element property set for class creation so a class is going to be generated for all top-level elements. No classes are going to be generated for complexTypes and simpleTypes since the simpleType is not an enumeration.

To summarize, we can expect 7 classes : Invoice, Customer, Address, Item, ShipTo, ShippingMethod and ShippingDate and the 7 corresponding class descriptors. Note that a class is generated for the top-level group customer

Running the XMl code generator

To run the source generator and create the source from the invoice.xsd file in a package test, we just call in the command line:

java -cp %CP% org.exolab.castor.builder.SourceGenerator -i invoice.xsd -package test 

The generated code

The Item.java class

To simplify this example we now focus on the item element.

<!-- Description of an item -->
<xsd:element name="item">
  <xsd:complexType>
    <xsd:sequence>
      <xsd:element name="Quantity" type="xsd:integer"
                   minOccurs="1" maxOccurs="1" />
      <xsd:element name="Price" type="PriceType"
                   minOccurs="1" maxOccurs="1" />
    </xsd:sequence>
    <xsd:attributeGroup ref="ItemAttributes" />
  </xsd:complexType>
</xsd:element>

<!-- Cool price type -->
<xsd:simpleType name="PriceType">
  <xsd:restriction base="xsd:decimal">
    <xsd:fractionDigits value="2" />
    <xsd:totalDigits value="5" />
    <xsd:minInclusive value="1" />
    <xsd:maxInclusive value="100" />
  </xsd:restriction>
</xsd:simpleType>

<!-- The attributes for an Item -->
<xsd:attributeGroup name="ItemAttributes">
  <xsd:attribute name="Id" type="xsd:ID" minOccurs="1" maxOccurs="1" />
  <xsd:attribute name="InStock" type="xsd:boolean" default="false" />
  <xsd:attribute name="Category" type="xsd:string" use="required" />
</xsd:attributeGroup>

To represent an Item object, we need to know its Id, the Quantity ordered and the Price for one item. So we can expect to find a least three private variables: a string for the Id element, an int for the quantity element (see the section on XML Schema support if you want to see the mapping between a W3C XML Schema type and a java type), but what type for the Price element?

While processing the Price element, Castor is going to process the type of Price i.e. the simpleType PriceType which base is decimal. Since derived types are automatically mapped to parent types and W3C XML Schema decimal type is mapped to a java.math.BigDecimal, the price element will be a java.math.BigDecimal. Another private variable is created for quantity: quantity is mapped to a primitive java type, so a boolean has_quantity is created for monitoring the state of the quantity variable. The rest of the code is the getter/setter methods and the Marshalling framework specific methods. Please find below the complete Item class (with Javadoc comments stripped off):

/** 
 * This class was automatically generated with 
 * Castor 1.0.4,
 * using an XML Schema.
 */

package test;

public class Item implements java.io.Serializable {

   //--------------------------/ 
   //- Class/Member Variables -/
   //--------------------------/

   private java.lang.String _id; 

   private int _quantity;

   /** 
    * keeps track of state for field: _quantity 
    */ 
   private boolean _has_quantity;

   private java.math.BigDecimal _price;

   //----------------/ 
   //- Constructors -/ 
   //----------------/

   public Item() { 
      super(); 
   } //-- test.Item()


   //-----------/ 
   //- Methods -/ 
   //-----------/

   public java.lang.String getId() { 
      return this._id; $
   } //-- java.lang.String getId()

   public java.math.BigDecimal getPrice() { 
      return this._price;
   } //-- java.math.BigDecimal getPrice()

   public int getQuantity() {
      return this._quantity;
   } //-- int getQuantity()

   public boolean hasQuantity() { 
	  return this._has_quantity;
   } //-- boolean hasQuantity()

   public boolean isValid() {
      try { 
         validate();
      } catch (org.exolab.castor.xml.ValidationException vex) { 
         return false;
      }
      return true;
   } //-- boolean isValid()

   public void marshal(java.io.Writer out) 
   throws org.exolab.castor.xml.MarshalException,org.exolab.castor.xml.ValidationException {
      Marshaller.marshal(this, out);
   } //-- void marshal(java.io.Writer)

   public void marshal(org.xml.sax.DocumentHandler handler) 
   throws org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException {
      Marshaller.marshal(this, handler);
   } //-- void marshal(org.xml.sax.DocumentHandler)

   public void setId(java.lang.String _id) {
      this._id = _id;
   } //-- void setId(java.lang.String)

   public void setPrice(java.math.BigDecimal _price) {
      this._price = _price;
   } //-- void setPrice(java.math.BigDecimal)

   public void setQuantity(int _quantity) {
      this._quantity = _quantity;
      this._has_quantity = true;
   } //-- void setQuantity(int)

   public static test.Item unmarshal(java.io.Reader reader) 
   throws org.exolab.castor.xml.MarshalException,org.exolab.castor.xml.ValidationException {
      return (test.Item) Unmarshaller.unmarshal(test.Item.class, reader);
   } //-- test.Item unmarshal(java.io.Reader)

   public void validate() 
   throws org.exolab.castor.xml.ValidationException {
      org.exolab.castor.xml.Validator.validate(this, null);
   } //-- void validate()

}

The ItemDescriptor class is a bit more complex. This class is containing inner classes which are the XML field descriptors for the different components of an ‘Item’ element i.e. id, quantity and price.

The PriceType.java class

TODO ...

The Invoice.java class

In this section, we focus on the 'invoice' element as shown again below:

<xsd:element name="invoice">
   <xsd:complexType>
      <xsd:sequence>
         <xsd:element name="ship-to">
            <xsd:complexType>
               <xsd:group ref="customer" />
            </xsd:complexType>
         </xsd:element>
         <xsd:element ref="item"	minOccurs="1" maxOccurs="unbounded" />
         <xsd:element ref="shipping-method" />
         <xsd:element ref="shipping-date" />
      </xsd:sequence>
   </xsd:complexType>
</xsd:element>

Amongst other things, an <invoice> is made up of at least one, but potentially many <item> elements. The Castor XML code generator creates a Java collection named 'itemList' for this unbounded element declaration, of type java.util.List if the scode generator is used with the 'arraylist' field factory.

    private java.util.List _itemList;

If the 'j1' field factory is used, this will be replaced with ...

    private java.util.Vector _itemList;

The complete class as generated (with irrelevant code parts removed) in 'j2' (aka 'arraylist') mode is shown below:

public class Invoice implements java.io.Serializable {


    ...
    
    private java.util.List _itemList;
    
    ...

    public Invoice() 
     {
        super();
        this._itemList = new java.util.ArrayList();
    } //-- xml.c1677.invoice.generated.Invoice()

	...

    public void addItem(xml.c1677.invoice.generated.Item vItem)
        throws java.lang.IndexOutOfBoundsException
    {
        this._itemList.add(vItem);
    } //-- void addItem(xml.c1677.invoice.generated.Item) 

    public void addItem(int index, xml.c1677.invoice.generated.Item vItem)
        throws java.lang.IndexOutOfBoundsException
    {
        this._itemList.add(index, vItem);
    } //-- void addItem(int, xml.c1677.invoice.generated.Item) 

    public java.util.Enumeration enumerateItem()
    {
        return java.util.Collections.enumeration(this._itemList);
    } //-- java.util.Enumeration enumerateItem() 

    public xml.c1677.invoice.generated.Item getItem(int index)
        throws java.lang.IndexOutOfBoundsException
    {
        // check bounds for index
        if (index < 0 || index >= this._itemList.size()) {
            throw new IndexOutOfBoundsException("getItem: Index value '" + index 
               + "' not in range [0.." + (this._itemList.size() - 1) + "]");
        }
        
        return (xml.c1677.invoice.generated.Item) _itemList.get(index);
    } //-- xml.c1677.invoice.generated.Item getItem(int) 

    public xml.c1677.invoice.generated.Item[] getItem()
    {
        int size = this._itemList.size();
        xml.c1677.invoice.generated.Item[] array = new xml.c1677.invoice.generated.Item[size];
        for (int index = 0; index < size; index++){
            array[index] = (xml.c1677.invoice.generated.Item) _itemList.get(index);
        }
        
        return array;
    } //-- xml.c1677.invoice.generated.Item[] getItem() 

    public int getItemCount()
    {
        return this._itemList.size();
    } //-- int getItemCount() 

    public java.util.Iterator iterateItem()
    {
        return this._itemList.iterator();
    } //-- java.util.Iterator iterateItem() 

    public void removeAllItem()
    {
        this._itemList.clear();
    } //-- void removeAllItem() 

    public boolean removeItem(xml.c1677.invoice.generated.Item vItem)
    {
        boolean removed = _itemList.remove(vItem);
        return removed;
    } //-- boolean removeItem(xml.c1677.invoice.generated.Item) 

    public xml.c1677.invoice.generated.Item removeItemAt(int index)
    {
        Object obj = this._itemList.remove(index);
        return (xml.c1677.invoice.generated.Item) obj;
    } //-- xml.c1677.invoice.generated.Item removeItemAt(int) 

    public void setItem(int index, xml.c1677.invoice.generated.Item vItem)
        throws java.lang.IndexOutOfBoundsException
    {
        // check bounds for index
        if (index < 0 || index >= this._itemList.size()) {
            throw new IndexOutOfBoundsException("setItem: Index value '" 
               + index + "' not in range [0.." + (this._itemList.size() - 1) + "]");
        }
        
        this._itemList.set(index, vItem);
    } //-- void setItem(int, xml.c1677.invoice.generated.Item) 

    public void setItem(xml.c1677.invoice.generated.Item[] vItemArray)
    {
        //-- copy array
        _itemList.clear();
        
        for (int i = 0; i < vItemArray.length; i++) {
                this._itemList.add(vItemArray[i]);
        }
    } //-- void setItem(xml.c1677.invoice.generated.Item) 

}

 
   
  
   
 


Copyright © 1999-2005 ExoLab Group, Intalio Inc., and Contributors. All rights reserved.
 
Java, EJB, JDBC, JNDI, JTA, Sun, Sun Microsystems are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and in other countries. XML, XML Schema, XSLT and related standards are trademarks or registered trademarks of MIT, INRIA, Keio or others, and a product of the World Wide Web Consortium. All other product names mentioned herein are trademarks of their respective owners.