commons-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Geronimo Ma. Hernandez" <>
Subject Re: [Digester] question about parent-parameter-access
Date Tue, 02 Sep 2003 11:03:57 GMT
Thanks for your reply, Simon!

Simon wrote:
> It's still not clear to me what your data model is.

Well, "my" data model started as a 1:1 view of a database, where a table is an 
entity and a column of a table is an attribute...
Now I advanced a bit in abstaction and you could think of an entity is just a 
set of attributes. This can be a 1:1 view of a database table, this could be 
a part of a table or this could be a set of selected columns of selected 
tables. So you could think of an entity as a dynabean.

An application consists of many different dynabeans and if you want to create 
different dynabeans with the same factory, you need some rules on how to 
create a dynabean.
From my point of view, such a dynabean is just an "invisible link" between UI 
and database, so to abstract this connection, you need some additional 
information/rules for each side of the connection.

Well, that additional information about each side combined with some rules is 
"my" model, and the config-file I process, is somewhat similar like a 
model-file for torque.
Ah, I think one difficulity of "my" model could be, that I try to scan the 
definition of the classes I actual use for the meta-model. It's a logical 
circular reference. 
Anyway, you could replace the names in your mind.

Ok, the mail will get somewhat big, but I try to include the code skeletons.
First of all, the model, the XML-file I gonna transform (explanation after the 

<?xml version="1.0" encoding="ISO-8859-1" ?>
	<map name="DBTypes">
		<entry value="1" lable="postgres"/>
		<entry value="2" lable="Oracle"/>
		<entry value="3" lable="DB/2"/>
		<entry value="4" lable="mySQL"/>
	<map name="TableTypes">
		<entry value="1" lable="normal"/>
		<entry value="2" lable="fast"/>
		<entry value="3" lable="secure"/>
		<entry value="4" lable="temporary"/>
	<map name="FldTypes">
		<entry value="1" lable="boolean"/>
		<entry value="2" lable="date"/>
		<entry value="3" lable="datetime"/>
		<entry value="4" lable="decimal"/>
		<entry value="5" lable="foreignkey"/>
		<entry value="6" lable="integer"/>
		<entry value="7" label="rowid"/>
		<entry value="8" lable="text"/>
		<entry value="9" lable="time"/>
		<text name="dbname" length="40" visLength="30"/>
		<text name="dbprefix" length="4" visLength="4"/>
		<text name="tsname" length="30" visLength="30"/>
		<text name="tblname" length="30" visLength="30"/>
		<text name="fldname" length="30" visLength="30"/>
		<reference name="dbid" references="Database"/>
		<reference name="tsid" references="Tablespace"/>
		<reference name="tblid" references="Table"/>
		<reference name="fldid" references="Field"/>
		<reference name="dbtype" references="DBTypes" property="value"/>
		<reference name="ttype" references="TableTypes" property="value"/>
		<reference name="ftype" references="FldTypes" property="value"/>
		<text name="path"/>
		<text name="value"/>
		<text name="stduser" length="25" visLength="15"/>
		<text name="ipcre" length="30" visLength="30"/>
		<text name="ipmod" length="30" visLength="30"/>
		<datetime name="dtimecre"/>
		<datetime name="dtimemod"/>
		<integer name="modcnt"/>
		<integer name="bsize" minValue="0"/>
		<integer name="esize" minValue="0"/>
		<integer name="flen" length="4" visLength="5" minValue="1" maxValue="2000"/>
		<integer name="dlen" length="1" visLength="2" minValue="0" maxValue="9"/>
		<integer name="vlen" length="2" visLength="3" minValue="0" maxValue="99"/>
		<boolean name="flauto"/>
		<boolean name="flmand"/>

	<entity name="Database">
		<addAttribute	name="rowid"/>
		<addAttribute	name="dbname">
                  <unique-index idx_number="1" idx_order="1"/>
		<addAttribute	name="dbprefix"/>
		<addAttribute	name="dbtype"/>
		<addAttribute	name="path"/>
		<addAttribute	name="stduser"/>
		<addAttribute	name="ipcre"/>
		<addAttribute	name="ipmod"/>
		<addAttribute	name="dtimecre"/>
		<addAttribute	name="dtimemod"/>
		<addAttribute	name="modcnt"/>
	<entity name="Tablespace">
		<addAttribute	name="rowid"/>
		<addAttribute	name="bsize"/>
		<addAttribute	name="esize"/>
		<addAttribute	name="dbid"/>
		<addAttribute	name="flauto"/>
		<addAttribute	name="path"/>
		<addAttribute	name="tsname"/>
		<addAttribute	name="ipcre"/>
		<addAttribute	name="ipmod"/>
		<addAttribute	name="dtimecre"/>
		<addAttribute	name="dtimemod"/>
		<addAttribute	name="modcnt"/>
	<entity name="Table">
		<addAttribute	name="rowid"/>
		<addAttribute	name="bsize"/>
		<addAttribute	name="esize"/>
		<addAttribute	name="dbid">
                  <unique-index idx_number="1" idx_order="1"/>
		<addAttribute	name="tblname">
                  <unique-index idx_number="1" idx_order="2"/>
		<addAttribute	name="tsid"/>
		<addAttribute	name="ttype"/>
		<addAttribute	name="ipcre"/>
		<addAttribute	name="ipmod"/>
		<addAttribute	name="dtimecre"/>
		<addAttribute	name="dtimemod"/>
		<addAttribute	name="modcnt"/>
	<entity name="Field">
		<addAttribute	name="rowid"/>
		<addAttribute	name="fldname"/>
		<addAttribute	name="ftype"/>
		<addAttribute	name="tblid"/>
		<addAttribute	name="flmand"/>
		<addAttribute	name="value"/>
		<addAttribute	name="flen"/>
		<addAttribute	name="dlen"/>
		<addAttribute	name="vlen"/>
		<addAttribute	name="ipcre"/>
		<addAttribute	name="ipmod"/>
		<addAttribute	name="dtimecre"/>
		<addAttribute	name="dtimemod"/>
		<addAttribute	name="modcnt"/>

Ok, lets move to the object/rules part step by step:
All definitions of the meta-model are added to a Catalog-instance, which is 
created as a "DefinitionRoot" by the factory, before starting the scanner. 
The Catalog also is the first instance added to the digester-stack.

class Catalog {
  public void addSelectList(Map);
  public void addEntityDefinition(EntityDefinition);
  public void addAttributeDefinition(AbstractAttributeDefinition);	
  public void putDefinition(Definition definition){
    if(definition instanceof EntityDefinition)
    else if(definition instanceof(AbstractAttributeDefinition))

The first subpattern is the map. A map is a list of items to satisfy a 
foreignkey without a target table (will be displayed in a dropdown combo).

digester.addFactoryCreate(MAP_NODE, "MapDefinitionCreateFactory");
digester.addCallMethod(MAP_ENTRY_NODE, "put", 2, 
		new String[] { "java.lang.Integer", "java.lang.String" });
digester.addSetNext(MAP_NODE, "addSelectList", MAP_CLASS);

Next subpattern is the attribute-section. (In my model, an attribute 
definition does not depend on a surrounding entity-definition.)
Each (supported) attribute-type has a different pattern and creates another 
AttributeDefinitionClass - Subclass of AbstractAttributeDefinition.

digester.addObjectCreate(BOOLEAN_NODE, BOOLEAN_CLASS);
digester.addSetNext(BOOLEAN_NODE, "addAttributeDefinition", ATTRIBUTE_CLASS);

The AttributeDefinition is quite a fat class, with all properties, that could 
be used in certain situation. As each type needs different information to 
build an entry on a dynabean, a select- or an insert-statement or on the 
UI-side, each AttributeDefinition-subclass holds the needed information.
All AttributeDefinitions are just beans.

At least the entity-definitions are processed. The entity just contains 
references to the real attribute-definition and - for me - the 
index-information is no property of the attribute, but of the entity. For me 
the same attribute may be part of different entities and in one entity this 
attribute is part on an index, but in the other entities it is not.
The rules for the entity-processing are as follows (with CallAncestorParamRule 
being my own written rule-class):

digester.addCallMethod(ADD_ATTRIBUTE_NODE, "addAttribute", 1
		, new String[] { "java.lang.String" });
digester.addCallMethod(UINDEX_NODE, "putUniqueIndex", 3
	, new String[] { "java.lang.Integer"
		, "java.lang.Integer"
		, "java.lang.String"});
digester.addCallParam(UINDEX_NODE, 0, "idx_number");
digester.addCallParam(UINDEX_NODE, 1, "idx_order");
digester.addRule(UINDEX_NODE, new CallAncestorParamRule(2, 1, 0));
digester.addSetNext(ENTITY_NODE, "putDefinition", ENTITY_CLASS);

With the EntityDefinitionCreateFactory I create an Entity with the parent 
(Catalog) already set before any other processing takes place.

class EntityDefinition {
  public void addAttribute(String attributeName) throws DefinitionException;
  public void putUniqueIndex(Integer idxNr, Integer idxOrder, String

The addAttribute-method of the Entity queries the AttributeDefinition from the 
Catalog. If found, the attribute is added to the entity, otherwise an 
Exception is thrown. 
The benefit of checking the existence of the attribute-definition at addition 
and not with a separate function-call at the end of the entity-processing is, 
that I get a line-number of the error-attribute with the digester-exception.

Finally the EntityDefinition is added to the Catalog with a call to 

Hope, I could clarify, what "my" model is and also hope, that the size of the 
mail is not a problem.

regards Gero

View raw message