You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@commons.apache.org by Marc Gemis <ma...@agfa.com> on 2003/11/06 14:17:21 UTC

[Digester] XML-file set-root-rule (follow-up + solution)

Simon Kitching asked me to post a follow-up on my problems regarding 
the 'set-root-rule'

Well it seems that this functionality is not implemented in Digester 
1.5 During the parsing of my rules I get

2003-11-06 10:32:50,759 DEBUG Digester -   New 
match='digester-rules/pattern/set-root-rule'
2003-11-06 10:32:50,759 DEBUG Digester -   No rules found matching 
'digester-rules/pattern/set-root-rule'.
2003-11-06 10:32:50,759 DEBUG sax - endElement(,,set-root-rule)
2003-11-06 10:32:50,760 DEBUG Digester -   
match='digester-rules/pattern/set-root-rule'
2003-11-06 10:32:50,760 DEBUG Digester -   bodyText=''
2003-11-06 10:32:50,762 DEBUG Digester -   No rules found matching 
'digester-rules/pattern/set-root-rule'.
2003-11-06 10:32:50,763 DEBUG Digester -   Popping body text '

I have the following method defining my rules

	public JmfParserUsingDigesterSourceConfig()
	throws JmfParserException
	{
		digester = new Digester();
		digester.setValidating(false);
		
		digester.addObjectCreate("JMF", JmfMessage.class);
		digester.addSetProperties("JMF", new String[] {"xmlns", "Version", 
"SenderID", "TimeStamp"},
				new String[] { "namespace", "jmfVersion", "senderId", "timeStamp" 
});
		digester.addSetNext("JMF", "setJmfMessage");
		
		digester.addFactoryCreate("JMF/Command", 
JmfParserCommandFactory.class);
		digester.addSetProperties("JMF/Command", new String[] {"ID", "Type"}, 
new String[] {"id", "type"});
		digester.addSetTop("JMF/Command", "setJmfMessage");
		digester.addSetRoot("JMF/Command", "setJdfProcessorForClient");
		digester.addSetNext("JMF/Command", "setJmfCommand");
		
		digester.addObjectCreate("JMF/Command/QueueSubmissionParams", 
QueueSubmissionParams.class);
		digester.addSetProperties("JMF/Command/QueueSubmissionParam",
				new String[] {"URL"}, new String[] {"jdfUrl"});
		digester.addSetNext("JMF/Command/QueueSubmissionParams", 
"addParameter");
	
		digester.push(new DocumentRoot());

	}

or similarly in XML

<?xml version="1.0" encoding="UTF-8"?>
<!-- <!DOCTYPE digester-rules SYSTEM "digester-rules.dtd"> -->
<digester-rules>
	<!-- this description assumes that the Digester has an object on its 
stack with the
		 methods
		    - setJmfMessage(JmfMessage)
		    - setJdfProcessor(JdfProcessorClient)
		 This object has to be placed on the stack prior to start parsing.
       -->
	<pattern value="JMF">
		<object-create-rule classname="com.agfa.delano.jdf.jmf.JmfMessage"/>
		<set-properties-rule>
			<alias attr-name="xmlns" prop-name="namespace"/>
			<alias attr-name="Version" prop-name="jmfVersion"/>
			<alias attr-name="SenderID" prop-name="senderId"/>
			<alias attr-name="TimeStamp" prop-name="timeStamp"/>
		</set-properties-rule>
		<set-next-rule methodname="setJmfMessage"/>
	</pattern>
	
		<pattern value="JMF/Command">
			<factory-create-rule 
classname="com.agfa.delano.jdf.jmf.parser.JmfParserCommandFactory"/>
			<set-properties-rule>
				<alias attr-name="ID" prop-name="id"/>
				<alias attr-name="Type" prop-name="type"/>
			</set-properties-rule>
			<set-top-rule methodname="setJmfMessage"/>
			<set-root-rule methodname="setJdfProcessorForClient"/>
			<set-next-rule methodname="setJmfCommand"/>
		
			<pattern value="QueueSubmissionParams">
				<object-create-rule 
classname="com.agfa.delano.jdf.jmf.command.QueueSubmissionParams"/>
				<set-properties-rule>
					<alias attr-name="URL" prop-name="jdfUrl"/>
				</set-properties-rule>
				<set-next-rule methodname="addParameter"/>

			</pattern>	
		</pattern>
	
</digester-rules>



I decided to dive into the code (guided by the docs) and came up with 
the following patch.

digester-rules.dtd

15c15
<                    set-properties-rule | set-property-rule | 
set-top-rule |
---
 >                    set-properties-rule | set-property-rule | 
set-top-rule | set-root-rule |
19c19
< <!ELEMENT digester-rules (pattern | include | 
bean-property-setter-rule | call-method-rule | call-param-rule | 
factory-create-rule | object-create-rule | set-properties-rule | 
set-property-rule | set-top-rule | set-next-rule )*>
---
 > <!ELEMENT digester-rules (pattern | include | 
bean-property-setter-rule | call-method-rule | call-param-rule | 
factory-create-rule | object-create-rule | set-properties-rule | 
set-property-rule | set-top-rule | set-root-rule | set-next-rule )*>
39c39
<                    set-properties-rule | set-property-rule | 
set-top-rule |
---
 >                    set-properties-rule | set-property-rule | 
set-top-rule | set-root-rule |
136a137,143
 >     pattern    CDATA #IMPLIED
 >     methodname CDATA #REQUIRED
 >     paramtype  CDATA #IMPLIED>
 >
 > <!-- SetRootRule -->
 > <!ELEMENT set-root-rule EMPTY>
 > <!ATTLIST set-root-rule

DigesterRuleParser.java

84a85
 > import org.apache.commons.digester.SetRootRule;
273a275,278
 >               digester.addFactoryCreate("*/set-root-rule", new 
SetRootRuleFactory());
 >               digester.addRule("*/set-root-rule", new 
PatternRule("pattern"));
 >               digester.addSetNext("*/set-root-rule", "add", 
ruleClassName);
 >
662a668,681
 >       /**
 >        * Factory for creating a SetRootRuleFactory
 >        */
 >       protected class SetRootRuleFactory extends 
AbstractObjectCreationFactory {
 >               public Object createObject(Attributes attributes) {
 >                       String methodName = 
attributes.getValue("methodname");
 >                       String paramType = 
attributes.getValue("paramtype");
 >                       return (paramType == null || paramType.length() 
== 0) ?
 >                               new SetRootRule( methodName)
 >                               :
 >                               new SetRootRule( methodName, paramType);
 >               }
 >       }
 >
675a695
 >


This works for me. I hope that this is useful to somebody else

regards

m.