CookXml Tutorial: Tag Extension


 

 

Support This Project

 

stats counter

 

Logo SourceForge.net Logo IntelliJ IDEA

Introduction

CookXml core component itself does not provide any tag libraries, but rather the interfaces and some generic functional objects for use with extensions. The common component defines some commonly used tags and converters for projects like CookSwing and CookSwt to use.

CookXml core component defines a simple TagLibrary, while the common component extends it such that it is possible to have tag inheritance, which we will discuss below.

Some Definitions

A TagLibrary is a collection of function/factory objects that creates and manipulate objects.

A Creator is a factory object which generates an object of the interest for a given element.

A Setter is a function object which sets an attribute of a object.

An Adder is a function object which adds a child object to the object.

A Converter is a function object which converts a string to an data type corresponding to the target class.

Creators, Setters, Adders and Converters make up a TagLibrary. As for tag inheritance, the child (in terms of inheritance hierarchy) tag inherits all the adders and setters of the parent tag. Multiple inheritance is allowed in the common component's InheritableTagLibrary.

Below are the guides of creating the components of a TagLibrary.

Creator

All tags must have a Creator. Some can be easily created, while some are not.

The Simplest Case

For classes that have a default constructor and the objects that can be modified later, CookXml provides a DefaultCreator that can be used to add a new tag element to the tag library. For example:

	tagLibrary.setCreator ("menu", DefaultCreator.getCreator (JMenu.class));

Here, a new tag menu is created. Whenever an XML document contains a <menu> tag, this Creator object is called and a new JMenu object is created.

There are certain traps, however, which you may encounter occasionally. By default, as soon as an object is created and its setters are called, it is added to the parent object, without considering the descendent nodes. As the result, if the parent node process the object immediately, it may not see a full picture. In those cases, it is necessary to delay the addition of the object to its parent. For example:

	tagLibrary.setCreator ("vector", DefaultCreator.getCreator(Vector.class, true));

No Default Constructor?

Some classes, such as BoxLayout, which does not have a default constructor that takes no parameters, it is necessary to have a custom Creator which takes the constructor tag value and determine parameters for the object constructors. Here is an actual code for the BoxLayoutCreator class. Many classes, notably immutable object classes such as Boolean, Integer, etc, can be created using this approach. However, it can be unintuitive for the author of the XML document to use the constructor tag.

Helper Needed

Sometimes, there can be too many fields need to be setup before an actual object could be generated. In these cases, helper objects are needed to temporarily collect the attribute settings done before actually creating the object. A good example is TitledBorderHelper, which is used by BorderCreator.

Setter

Generally, one does not need to write a setter for a class, as the default setter automatically searches for the appropriate variables/setter functions that can handle the attribute.

Constant Setter

It is often preferred to use names such as "VERTICAL" rather than the hard coded value 1 to assign attribute values. In those cases, ConstantSetter comes handy.

	ConstantSetter swingConstantsSetter = new ConstantSetter (SwingConstants.class);
	tagLibrary.setSetter ("toolbar", "orientation", swingConstantsSetter);

In the above example, the first line creates a setter which will lookup names in the static field of SwingConstants. The second line tells CookXml to hook the setter to the attribute name of "orientation" for the "toolbar" tag.

Adder

By default, there is a DefaultAdder which looks up public functions with the name add and the appropriate parameter class type for the object. Thus, if there are functions add (String title) and add (Icon icon) and the current object is a string, then the first function is called. In many cases, the function you want to call may be different from add, so it is desirable (but not required, since you can use the "func" attribute in the object to specify the function to be called) to have an adder for the task, making it easier for the author of the XML document. A simple example is ComboBoxAdder.

While CookXml only provides a setAdder function which can only associate one Adder with a class, the InheritableTagLibrary also provides addAdder function so that multiple adders could be composed together to function as one.

Converter

The main purpose of using Converter is to simplify writing the XML document. For example, even though we can set the rows of a grid layout using

	<gridlayout>
		<int setas="rows" value="2">
		<int setas="columns" value="2">

. The following approach is so much simpler and more intuitive.

	<gridlayout rows="2" columns="2">

Writing a Converter is really easy, as evidented by the IntConverter..

(c) Copyright 2004-2007 Heng Yuan. All rights reserved.

Valid XHTML 1.0! Valid CSS!