You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by Daniel Rall <dl...@finemaltcoding.com> on 2003/08/12 02:16:53 UTC

[Betwixt] Extending BeanRuleSet

I'm looking for a way of using Digester's addRule(FactoryCreateRule)
method [1] with Betwixt's BeanReader to extend the processing used to
create an instance to "perform other setup processing" [2].  I want to
retain the existing recursive XML -> JavaBean processing behavior of
BeanReader, and set another instance field using some contextual
information which isn't available from my XML.

<scarab-issues>
    <import-type>create-different-db</import-type>
    <module>
        ...
    </module>
    ...
</scarab-issues>

When beginning processing the <scarab-issues> element, I'd like to set
the instance field.  Other than that, I'd like things to act like I'm
using a vanilla BeanReader.  I've tried simply making an extra
BeanReader.addRule() call (inheritted from its Digester superclass),
but when I attempt to access children of <scarab-issues> when
processing using my additional rule, they're null.  Here's a brief
synopsis of the code in question (or is that questionable code? ;)

        ...
        BeanReader reader = new BeanReader();
        reader.setXMLIntrospector(createXMLIntrospector());
        reader.registerBeanClass(ScarabIssues.class);
        reader.addRule("scarab-issues",
                       new FactoryCreateRule(new ScarabIssuesFactory()));
        reader.setErrorHandler(this);
        return reader;
    }

    /**
     * An ObjectCreationFactory which sets the ImportErrors instance
     * used by a ScarabIssues instance.
     */
    class ScarabIssuesFactory extends AbstractObjectCreationFactory
    {
        public Object createObject(Attributes attributes)
        {
            ScarabIssues si = new ScarabIssues();
            si.importErrors = this.importErrors;
            LOG.info("DLR: Called createObject(" + attributes + ')');
            return si;
        }
    }
}


Spare a clue?
-- 

Daniel Rall

[1] http://jakarta.apache.org/commons/digester/apidocs/org/apache/commons/digester/FactoryCreateRule.html
[2] http://jakarta.apache.org/commons/digester/apidocs/org/apache/commons/digester/package-summary.html#doc.Rules

Re: [Betwixt] Using NameMapper

Posted by Daniel Rall <dl...@finemaltcoding.com>.
Robert, using BeanDescriptor.getName() worked well, enabling me to
remove the custom parsing code from ImportIssues -- was that what you
had in mind?  I didn't notice the new test case, and wrote this along
the way.  Something I should check in?


Index: TestHyphenatedNameMapper.java
===================================================================
RCS file: /home/cvs/jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/strategy/TestHyphenatedNameMapper.java,v
retrieving revision 1.5
diff -u -u -r1.5 TestHyphenatedNameMapper.java
--- TestHyphenatedNameMapper.java	30 Dec 2002 18:16:48 -0000	1.5
+++ TestHyphenatedNameMapper.java	15 Aug 2003 18:48:47 -0000
@@ -62,6 +62,7 @@
 
 package org.apache.commons.betwixt.strategy;
 
+import java.beans.BeanDescriptor;
 import java.util.ArrayList;
 
 import junit.framework.Test;
@@ -93,6 +94,13 @@
         assertEquals("foo-bar", result);
     }
     
+    public void testLowerCaseViaBeanDescriptor() {
+        HyphenatedNameMapper mapper = new HyphenatedNameMapper(false, "_");
+        BeanDescriptor bd = new BeanDescriptor(getClass());
+        String result = mapper.mapTypeToElementName(bd.getName());
+        assertEquals("test_hyphenated_name_mapper", result);
+    }
+
     public void testUpperCase()  {
         HyphenatedNameMapper mapper = new HyphenatedNameMapper(true, "_");
         String result = mapper.mapTypeToElementName("FooBar");


robert burrell donkin <rd...@apache.org> writes:

> hi daniel
> 
> i've taken a look into this (and even added another test case to
> convince myself that i'm right). the BeanDescriptor name is passed to
> the name mapper to create the element. i'm pretty sure that this
> should be the class name without the package. (it is on my machine at
> least).
> 
> 
> it is possible that this is an issue with the alpha1 release that has
> resolved itself since then.
> 
> 
> - robert
> 
> On Wednesday, August 13, 2003, at 07:53 PM, Daniel Rall wrote:
> 
> > Daniel Rall <dl...@finemaltcoding.com> writes:
> > ...
> >> is it possible to use HyphenatedNameMapper's
> >> mapTypeToElementName(String typeName) (or something of the sort) to
> >> transform ScarabIssues.class into the String "scarab-issues" (to
> >> obviate the hard-coding of magic strings)?
> >
> > To answer my own quesiton, it is possible:
> >
> > http://scarab.tigris.org/source/browse/scarab/src/java/org/tigris/scarab/
> > util/xmlissues/ImportIssues.java.diff?r1=1.25&r2=1.26
> >
> > You'll notice that I had to add a local mapTypeToElementName(Class,
> > NameMapper) method which strips the package name off of the class name
> > before handing off to HyphenatedNameMapper for resolution to a XML
> > element.  This same code must be present somewhere within Betwixt, and
> > I would prefer to take advantage of it rather than re-implementing it
> > in Scarab's ImportIssues class.  It may be only a few trivial lines,
> > but I feel that my inclusion of it infringes on ideal encapsulation
> > (even with my update of Betwixt's JavaDoc).  A possible improvement
> > would be to loosen the API of NameMapper to accept Object rather than
> > String, then use "instanceof Class" inside of HyphenatedNameMapper to
> > detemine whether a package name should be stripped off of the input.
> > This would shift all mapping responsibility out of elsewhere in
> > Betwixt (called from somewhere in BeanReader, I assume) down into
> > NameMapper implementations.  Perhaps not what is wanted, of course --
> > just a suggestion.

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [Betwixt] Using NameMapper

Posted by Daniel Rall <dl...@finemaltcoding.com>.
Robert, using BeanDescriptor.getName() worked well, enabling me to
remove the custom parsing code from ImportIssues -- was that what you
had in mind?  I didn't notice the new test case, and wrote this along
the way.  Something I should check in?


Index: TestHyphenatedNameMapper.java
===================================================================
RCS file: /home/cvs/jakarta-commons/betwixt/src/test/org/apache/commons/betwixt/strategy/TestHyphenatedNameMapper.java,v
retrieving revision 1.5
diff -u -u -r1.5 TestHyphenatedNameMapper.java
--- TestHyphenatedNameMapper.java	30 Dec 2002 18:16:48 -0000	1.5
+++ TestHyphenatedNameMapper.java	15 Aug 2003 18:48:47 -0000
@@ -62,6 +62,7 @@
 
 package org.apache.commons.betwixt.strategy;
 
+import java.beans.BeanDescriptor;
 import java.util.ArrayList;
 
 import junit.framework.Test;
@@ -93,6 +94,13 @@
         assertEquals("foo-bar", result);
     }
     
+    public void testLowerCaseViaBeanDescriptor() {
+        HyphenatedNameMapper mapper = new HyphenatedNameMapper(false, "_");
+        BeanDescriptor bd = new BeanDescriptor(getClass());
+        String result = mapper.mapTypeToElementName(bd.getName());
+        assertEquals("test_hyphenated_name_mapper", result);
+    }
+
     public void testUpperCase()  {
         HyphenatedNameMapper mapper = new HyphenatedNameMapper(true, "_");
         String result = mapper.mapTypeToElementName("FooBar");


robert burrell donkin <rd...@apache.org> writes:

> hi daniel
> 
> i've taken a look into this (and even added another test case to
> convince myself that i'm right). the BeanDescriptor name is passed to
> the name mapper to create the element. i'm pretty sure that this
> should be the class name without the package. (it is on my machine at
> least).
> 
> 
> it is possible that this is an issue with the alpha1 release that has
> resolved itself since then.
> 
> 
> - robert
> 
> On Wednesday, August 13, 2003, at 07:53 PM, Daniel Rall wrote:
> 
> > Daniel Rall <dl...@finemaltcoding.com> writes:
> > ...
> >> is it possible to use HyphenatedNameMapper's
> >> mapTypeToElementName(String typeName) (or something of the sort) to
> >> transform ScarabIssues.class into the String "scarab-issues" (to
> >> obviate the hard-coding of magic strings)?
> >
> > To answer my own quesiton, it is possible:
> >
> > http://scarab.tigris.org/source/browse/scarab/src/java/org/tigris/scarab/
> > util/xmlissues/ImportIssues.java.diff?r1=1.25&r2=1.26
> >
> > You'll notice that I had to add a local mapTypeToElementName(Class,
> > NameMapper) method which strips the package name off of the class name
> > before handing off to HyphenatedNameMapper for resolution to a XML
> > element.  This same code must be present somewhere within Betwixt, and
> > I would prefer to take advantage of it rather than re-implementing it
> > in Scarab's ImportIssues class.  It may be only a few trivial lines,
> > but I feel that my inclusion of it infringes on ideal encapsulation
> > (even with my update of Betwixt's JavaDoc).  A possible improvement
> > would be to loosen the API of NameMapper to accept Object rather than
> > String, then use "instanceof Class" inside of HyphenatedNameMapper to
> > detemine whether a package name should be stripped off of the input.
> > This would shift all mapping responsibility out of elsewhere in
> > Betwixt (called from somewhere in BeanReader, I assume) down into
> > NameMapper implementations.  Perhaps not what is wanted, of course --
> > just a suggestion.

Re: [Betwixt] Using NameMapper

Posted by robert burrell donkin <rd...@apache.org>.
hi daniel

i've taken a look into this (and even added another test case to convince 
myself that i'm right). the BeanDescriptor name is passed to the name 
mapper to create the element. i'm pretty sure that this should be the 
class name without the package. (it is on my machine at least).

it is possible that this is an issue with the alpha1 release that has 
resolved itself since then.

- robert

On Wednesday, August 13, 2003, at 07:53 PM, Daniel Rall wrote:

> Daniel Rall <dl...@finemaltcoding.com> writes:
> ...
>> is it possible to use HyphenatedNameMapper's
>> mapTypeToElementName(String typeName) (or something of the sort) to
>> transform ScarabIssues.class into the String "scarab-issues" (to
>> obviate the hard-coding of magic strings)?
>
> To answer my own quesiton, it is possible:
>
> http://scarab.tigris.org/source/browse/scarab/src/java/org/tigris/scarab/
> util/xmlissues/ImportIssues.java.diff?r1=1.25&r2=1.26
>
> You'll notice that I had to add a local mapTypeToElementName(Class,
> NameMapper) method which strips the package name off of the class name
> before handing off to HyphenatedNameMapper for resolution to a XML
> element.  This same code must be present somewhere within Betwixt, and
> I would prefer to take advantage of it rather than re-implementing it
> in Scarab's ImportIssues class.  It may be only a few trivial lines,
> but I feel that my inclusion of it infringes on ideal encapsulation
> (even with my update of Betwixt's JavaDoc).  A possible improvement
> would be to loosen the API of NameMapper to accept Object rather than
> String, then use "instanceof Class" inside of HyphenatedNameMapper to
> detemine whether a package name should be stripped off of the input.
> This would shift all mapping responsibility out of elsewhere in
> Betwixt (called from somewhere in BeanReader, I assume) down into
> NameMapper implementations.  Perhaps not what is wanted, of course --
> just a suggestion.
>
>  - Dan
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@scarab.tigris.org
> For additional commands, e-mail: dev-help@scarab.tigris.org
>


Re: [Betwixt] Using NameMapper

Posted by robert burrell donkin <rd...@apache.org>.
hi daniel

i've taken a look into this (and even added another test case to convince 
myself that i'm right). the BeanDescriptor name is passed to the name 
mapper to create the element. i'm pretty sure that this should be the 
class name without the package. (it is on my machine at least).

it is possible that this is an issue with the alpha1 release that has 
resolved itself since then.

- robert

On Wednesday, August 13, 2003, at 07:53 PM, Daniel Rall wrote:

> Daniel Rall <dl...@finemaltcoding.com> writes:
> ...
>> is it possible to use HyphenatedNameMapper's
>> mapTypeToElementName(String typeName) (or something of the sort) to
>> transform ScarabIssues.class into the String "scarab-issues" (to
>> obviate the hard-coding of magic strings)?
>
> To answer my own quesiton, it is possible:
>
> http://scarab.tigris.org/source/browse/scarab/src/java/org/tigris/scarab/
> util/xmlissues/ImportIssues.java.diff?r1=1.25&r2=1.26
>
> You'll notice that I had to add a local mapTypeToElementName(Class,
> NameMapper) method which strips the package name off of the class name
> before handing off to HyphenatedNameMapper for resolution to a XML
> element.  This same code must be present somewhere within Betwixt, and
> I would prefer to take advantage of it rather than re-implementing it
> in Scarab's ImportIssues class.  It may be only a few trivial lines,
> but I feel that my inclusion of it infringes on ideal encapsulation
> (even with my update of Betwixt's JavaDoc).  A possible improvement
> would be to loosen the API of NameMapper to accept Object rather than
> String, then use "instanceof Class" inside of HyphenatedNameMapper to
> detemine whether a package name should be stripped off of the input.
> This would shift all mapping responsibility out of elsewhere in
> Betwixt (called from somewhere in BeanReader, I assume) down into
> NameMapper implementations.  Perhaps not what is wanted, of course --
> just a suggestion.
>
>  - Dan
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@scarab.tigris.org
> For additional commands, e-mail: dev-help@scarab.tigris.org
>


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [Betwixt] Using NameMapper

Posted by Daniel Rall <dl...@finemaltcoding.com>.
Daniel Rall <dl...@finemaltcoding.com> writes:
...
> is it possible to use HyphenatedNameMapper's
> mapTypeToElementName(String typeName) (or something of the sort) to
> transform ScarabIssues.class into the String "scarab-issues" (to
> obviate the hard-coding of magic strings)?

To answer my own quesiton, it is possible:

http://scarab.tigris.org/source/browse/scarab/src/java/org/tigris/scarab/util/xmlissues/ImportIssues.java.diff?r1=1.25&r2=1.26

You'll notice that I had to add a local mapTypeToElementName(Class,
NameMapper) method which strips the package name off of the class name
before handing off to HyphenatedNameMapper for resolution to a XML
element.  This same code must be present somewhere within Betwixt, and
I would prefer to take advantage of it rather than re-implementing it
in Scarab's ImportIssues class.  It may be only a few trivial lines,
but I feel that my inclusion of it infringes on ideal encapsulation
(even with my update of Betwixt's JavaDoc).  A possible improvement
would be to loosen the API of NameMapper to accept Object rather than
String, then use "instanceof Class" inside of HyphenatedNameMapper to
detemine whether a package name should be stripped off of the input.
This would shift all mapping responsibility out of elsewhere in
Betwixt (called from somewhere in BeanReader, I assume) down into
NameMapper implementations.  Perhaps not what is wanted, of course --
just a suggestion.

 - Dan

Re: [Betwixt] Using NameMapper

Posted by Daniel Rall <dl...@finemaltcoding.com>.
Daniel Rall <dl...@finemaltcoding.com> writes:
...
> is it possible to use HyphenatedNameMapper's
> mapTypeToElementName(String typeName) (or something of the sort) to
> transform ScarabIssues.class into the String "scarab-issues" (to
> obviate the hard-coding of magic strings)?

To answer my own quesiton, it is possible:

http://scarab.tigris.org/source/browse/scarab/src/java/org/tigris/scarab/util/xmlissues/ImportIssues.java.diff?r1=1.25&r2=1.26

You'll notice that I had to add a local mapTypeToElementName(Class,
NameMapper) method which strips the package name off of the class name
before handing off to HyphenatedNameMapper for resolution to a XML
element.  This same code must be present somewhere within Betwixt, and
I would prefer to take advantage of it rather than re-implementing it
in Scarab's ImportIssues class.  It may be only a few trivial lines,
but I feel that my inclusion of it infringes on ideal encapsulation
(even with my update of Betwixt's JavaDoc).  A possible improvement
would be to loosen the API of NameMapper to accept Object rather than
String, then use "instanceof Class" inside of HyphenatedNameMapper to
detemine whether a package name should be stripped off of the input.
This would shift all mapping responsibility out of elsewhere in
Betwixt (called from somewhere in BeanReader, I assume) down into
NameMapper implementations.  Perhaps not what is wanted, of course --
just a suggestion.

 - Dan

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [Betwixt] Extending BeanRuleSet

Posted by Daniel Rall <dl...@finemaltcoding.com>.
robert burrell donkin <rd...@apache.org> writes:

> hi daniel
> 
> i'm a little ill at the moment so you'll have to forgive me if i'm a
> little slow today

Heya Robert, sorry to hear that -- get well soon.

> On Tuesday, August 12, 2003, at 01:16 AM, Daniel Rall wrote:
...
> > <scarab-issues>
> >     <import-type>create-different-db</import-type>
> >     <module>
> >         ...
> >     </module>
> >     ...
> > </scarab-issues>
> >
> > When beginning processing the <scarab-issues> element, I'd like to set
> > the instance field.  Other than that, I'd like things to act like I'm
> > using a vanilla BeanReader.  I've tried simply making an extra
> > BeanReader.addRule() call (inheritted from its Digester superclass),
> > but when I attempt to access children of <scarab-issues> when
> > processing using my additional rule, they're null.
> 
> i trust that you're using CVS HEAD (the integration of digester and
> betwixt has been improved since the last release).

Sorry I left that tidbit out -- using 1.0 alpha 1.  I don't mind using
an unreleased version so long as there is a tag on the CVS repo so
that I can later match up the exact source code to the library
included in Scarab.  Alpha 1 is working well for me, is there
compelling reason to upgrade?

> > Here's a brief synopsis of the code in question (or is that
> > questionable code? ;)
> 
> >         ...
> >         BeanReader reader = new BeanReader();
> >         reader.setXMLIntrospector(createXMLIntrospector());
> >         reader.registerBeanClass(ScarabIssues.class);
> >         reader.addRule("scarab-issues",
> >                        new FactoryCreateRule(new ScarabIssuesFactory()));
> >         reader.setErrorHandler(this);
> >         return reader;
> >     }
> >
> >     /**
> >      * An ObjectCreationFactory which sets the ImportErrors instance
> >      * used by a ScarabIssues instance.
> >      */
> >     class ScarabIssuesFactory extends AbstractObjectCreationFactory
> >     {
> >         public Object createObject(Attributes attributes)
> >         {
> >             ScarabIssues si = new ScarabIssues();
> >             si.importErrors = this.importErrors;
> >             LOG.info("DLR: Called createObject(" + attributes + ')');
> >             return si;
> >         }
> >     }
> > }
...
> the first problem is that importErrors really is a field (as opposed
> to a property). at the moment, betwixt and digester only really deal
> with properties out of the box.

Yes, I figured I simply needed to hook some custom logic into the
processing.

> the second problem is that digester rules are additive. when the
> scarab-issues element is encountered, the betwixt rule will create an
> instance of ScarabIssues and push it onto the main digester stack and
> then the object create rule will create an instance of ScarabIssues
> and push it also onto the stack. the property setting rules work on
> the top element on the stack - the one created by the object create
> rule. betwixt will return the bean that it has created.

*nod*  To clarify for me, Betwixt will not return the bean that my
ObjectCreateRule created, though that bean is the one which has all
the properties set on it?

> i've got a lot of half finished betwixt code sitting around here, some
> of which would provide an elegant solution to your problem. it would
> allow you to register a custom factory (with betwixt) to create
> ScarabIssues beans. unfortunately, it may be a while before that makes
> it into the betwixt codebase.

That sounds delicious.  If there's any code I can try out for you, I'm
game.

> for the moment, i'd suggest replacing the object create rule with a
> custom Rule implementation something like:
> 
> 
> SetFieldRule extends Rule {
> 	public void begin (java.lang.String namespace,
> 	java.lang,String name, org.sax.Attributes attributes){
> 
> 		ScarabIssues issues = (ScarabIssues) getDigester().peek();
> 		issues.importErrors = this.importErrors;
> 	}
> }
> 
> registered with the same matching path.
> 
> hope that helps.

That worked perfectly.

http://scarab.tigris.org/source/browse/scarab/src/java/org/tigris/scarab/util/xmlissues/ImportIssues.java.diff?r1=1.24&r2=1.25



Unrelated question: is it possible to use HyphenatedNameMapper's
mapTypeToElementName(String typeName) (or something of the sort) to
transform ScarabIssues.class into the String "scarab-issues" (to
obviate the hard-coding of magic strings)?
-- 

Daniel Rall

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [Betwixt] Extending BeanRuleSet

Posted by Daniel Rall <dl...@finemaltcoding.com>.
robert burrell donkin <rd...@apache.org> writes:

> hi daniel
> 
> i'm a little ill at the moment so you'll have to forgive me if i'm a
> little slow today

Heya Robert, sorry to hear that -- get well soon.

> On Tuesday, August 12, 2003, at 01:16 AM, Daniel Rall wrote:
...
> > <scarab-issues>
> >     <import-type>create-different-db</import-type>
> >     <module>
> >         ...
> >     </module>
> >     ...
> > </scarab-issues>
> >
> > When beginning processing the <scarab-issues> element, I'd like to set
> > the instance field.  Other than that, I'd like things to act like I'm
> > using a vanilla BeanReader.  I've tried simply making an extra
> > BeanReader.addRule() call (inheritted from its Digester superclass),
> > but when I attempt to access children of <scarab-issues> when
> > processing using my additional rule, they're null.
> 
> i trust that you're using CVS HEAD (the integration of digester and
> betwixt has been improved since the last release).

Sorry I left that tidbit out -- using 1.0 alpha 1.  I don't mind using
an unreleased version so long as there is a tag on the CVS repo so
that I can later match up the exact source code to the library
included in Scarab.  Alpha 1 is working well for me, is there
compelling reason to upgrade?

> > Here's a brief synopsis of the code in question (or is that
> > questionable code? ;)
> 
> >         ...
> >         BeanReader reader = new BeanReader();
> >         reader.setXMLIntrospector(createXMLIntrospector());
> >         reader.registerBeanClass(ScarabIssues.class);
> >         reader.addRule("scarab-issues",
> >                        new FactoryCreateRule(new ScarabIssuesFactory()));
> >         reader.setErrorHandler(this);
> >         return reader;
> >     }
> >
> >     /**
> >      * An ObjectCreationFactory which sets the ImportErrors instance
> >      * used by a ScarabIssues instance.
> >      */
> >     class ScarabIssuesFactory extends AbstractObjectCreationFactory
> >     {
> >         public Object createObject(Attributes attributes)
> >         {
> >             ScarabIssues si = new ScarabIssues();
> >             si.importErrors = this.importErrors;
> >             LOG.info("DLR: Called createObject(" + attributes + ')');
> >             return si;
> >         }
> >     }
> > }
...
> the first problem is that importErrors really is a field (as opposed
> to a property). at the moment, betwixt and digester only really deal
> with properties out of the box.

Yes, I figured I simply needed to hook some custom logic into the
processing.

> the second problem is that digester rules are additive. when the
> scarab-issues element is encountered, the betwixt rule will create an
> instance of ScarabIssues and push it onto the main digester stack and
> then the object create rule will create an instance of ScarabIssues
> and push it also onto the stack. the property setting rules work on
> the top element on the stack - the one created by the object create
> rule. betwixt will return the bean that it has created.

*nod*  To clarify for me, Betwixt will not return the bean that my
ObjectCreateRule created, though that bean is the one which has all
the properties set on it?

> i've got a lot of half finished betwixt code sitting around here, some
> of which would provide an elegant solution to your problem. it would
> allow you to register a custom factory (with betwixt) to create
> ScarabIssues beans. unfortunately, it may be a while before that makes
> it into the betwixt codebase.

That sounds delicious.  If there's any code I can try out for you, I'm
game.

> for the moment, i'd suggest replacing the object create rule with a
> custom Rule implementation something like:
> 
> 
> SetFieldRule extends Rule {
> 	public void begin (java.lang.String namespace,
> 	java.lang,String name, org.sax.Attributes attributes){
> 
> 		ScarabIssues issues = (ScarabIssues) getDigester().peek();
> 		issues.importErrors = this.importErrors;
> 	}
> }
> 
> registered with the same matching path.
> 
> hope that helps.

That worked perfectly.

http://scarab.tigris.org/source/browse/scarab/src/java/org/tigris/scarab/util/xmlissues/ImportIssues.java.diff?r1=1.24&r2=1.25



Unrelated question: is it possible to use HyphenatedNameMapper's
mapTypeToElementName(String typeName) (or something of the sort) to
transform ScarabIssues.class into the String "scarab-issues" (to
obviate the hard-coding of magic strings)?
-- 

Daniel Rall

Re: [Betwixt] Extending BeanRuleSet

Posted by robert burrell donkin <rd...@apache.org>.
hi daniel

i'm a little ill at the moment so you'll have to forgive me if i'm a 
little slow today

On Tuesday, August 12, 2003, at 01:16 AM, Daniel Rall wrote:

> I'm looking for a way of using Digester's addRule(FactoryCreateRule)
> method [1] with Betwixt's BeanReader to extend the processing used to
> create an instance to "perform other setup processing" [2].  I want to
> retain the existing recursive XML -> JavaBean processing behavior of
> BeanReader, and set another instance field using some contextual
> information which isn't available from my XML.

ok, sounds reasonable.

> <scarab-issues>
>     <import-type>create-different-db</import-type>
>     <module>
>         ...
>     </module>
>     ...
> </scarab-issues>
>
> When beginning processing the <scarab-issues> element, I'd like to set
> the instance field.  Other than that, I'd like things to act like I'm
> using a vanilla BeanReader.  I've tried simply making an extra
> BeanReader.addRule() call (inheritted from its Digester superclass),
> but when I attempt to access children of <scarab-issues> when
> processing using my additional rule, they're null.

i trust that you're using CVS HEAD (the integration of digester and 
betwixt has been improved since the last release).

> Here's a brief
> synopsis of the code in question (or is that questionable code? ;)

>         ...
>         BeanReader reader = new BeanReader();
>         reader.setXMLIntrospector(createXMLIntrospector());
>         reader.registerBeanClass(ScarabIssues.class);
>         reader.addRule("scarab-issues",
>                        new FactoryCreateRule(new ScarabIssuesFactory()));
>         reader.setErrorHandler(this);
>         return reader;
>     }
>
>     /**
>      * An ObjectCreationFactory which sets the ImportErrors instance
>      * used by a ScarabIssues instance.
>      */
>     class ScarabIssuesFactory extends AbstractObjectCreationFactory
>     {
>         public Object createObject(Attributes attributes)
>         {
>             ScarabIssues si = new ScarabIssues();
>             si.importErrors = this.importErrors;
>             LOG.info("DLR: Called createObject(" + attributes + ')');
>             return si;
>         }
>     }
> }
>
>
> Spare a clue?

i think i understand your problem and can offer a possible solution. i'll 
also try to explain why the above doesn't work.

the first problem is that importErrors really is a field (as opposed to a 
property). at the moment, betwixt and digester only really deal with 
properties out of the box.

the second problem is that digester rules are additive. when the 
scarab-issues element is encountered, the betwixt rule will create an 
instance of ScarabIssues and push it onto the main digester stack and then 
the object create rule will create an instance of ScarabIssues and push it 
also onto the stack. the property setting rules work on the top element on 
the stack - the one created by the object create rule. betwixt will return 
the bean that it has created.

i've got a lot of half finished betwixt code sitting around here, some of 
which would provide an elegant solution to your problem. it would allow 
you to register a custom factory (with betwixt) to create ScarabIssues 
beans. unfortunately, it may be a while before that makes it into the 
betwixt codebase.

for the moment, i'd suggest replacing the object create rule with a custom 
Rule implementation something like:

SetFieldRule extends Rule {
	public void begin (java.lang.String namespace, java.lang,String name, 
org.sax.Attributes attributes){
		ScarabIssues issues = (ScarabIssues) getDigester().peek();
		issues.importErrors = this.importErrors;
	}
}

registered with the same matching path.

hope that helps.

- robert


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [Betwixt] Extending BeanRuleSet

Posted by robert burrell donkin <rd...@apache.org>.
hi daniel

i'm a little ill at the moment so you'll have to forgive me if i'm a 
little slow today

On Tuesday, August 12, 2003, at 01:16 AM, Daniel Rall wrote:

> I'm looking for a way of using Digester's addRule(FactoryCreateRule)
> method [1] with Betwixt's BeanReader to extend the processing used to
> create an instance to "perform other setup processing" [2].  I want to
> retain the existing recursive XML -> JavaBean processing behavior of
> BeanReader, and set another instance field using some contextual
> information which isn't available from my XML.

ok, sounds reasonable.

> <scarab-issues>
>     <import-type>create-different-db</import-type>
>     <module>
>         ...
>     </module>
>     ...
> </scarab-issues>
>
> When beginning processing the <scarab-issues> element, I'd like to set
> the instance field.  Other than that, I'd like things to act like I'm
> using a vanilla BeanReader.  I've tried simply making an extra
> BeanReader.addRule() call (inheritted from its Digester superclass),
> but when I attempt to access children of <scarab-issues> when
> processing using my additional rule, they're null.

i trust that you're using CVS HEAD (the integration of digester and 
betwixt has been improved since the last release).

> Here's a brief
> synopsis of the code in question (or is that questionable code? ;)

>         ...
>         BeanReader reader = new BeanReader();
>         reader.setXMLIntrospector(createXMLIntrospector());
>         reader.registerBeanClass(ScarabIssues.class);
>         reader.addRule("scarab-issues",
>                        new FactoryCreateRule(new ScarabIssuesFactory()));
>         reader.setErrorHandler(this);
>         return reader;
>     }
>
>     /**
>      * An ObjectCreationFactory which sets the ImportErrors instance
>      * used by a ScarabIssues instance.
>      */
>     class ScarabIssuesFactory extends AbstractObjectCreationFactory
>     {
>         public Object createObject(Attributes attributes)
>         {
>             ScarabIssues si = new ScarabIssues();
>             si.importErrors = this.importErrors;
>             LOG.info("DLR: Called createObject(" + attributes + ')');
>             return si;
>         }
>     }
> }
>
>
> Spare a clue?

i think i understand your problem and can offer a possible solution. i'll 
also try to explain why the above doesn't work.

the first problem is that importErrors really is a field (as opposed to a 
property). at the moment, betwixt and digester only really deal with 
properties out of the box.

the second problem is that digester rules are additive. when the 
scarab-issues element is encountered, the betwixt rule will create an 
instance of ScarabIssues and push it onto the main digester stack and then 
the object create rule will create an instance of ScarabIssues and push it 
also onto the stack. the property setting rules work on the top element on 
the stack - the one created by the object create rule. betwixt will return 
the bean that it has created.

i've got a lot of half finished betwixt code sitting around here, some of 
which would provide an elegant solution to your problem. it would allow 
you to register a custom factory (with betwixt) to create ScarabIssues 
beans. unfortunately, it may be a while before that makes it into the 
betwixt codebase.

for the moment, i'd suggest replacing the object create rule with a custom 
Rule implementation something like:

SetFieldRule extends Rule {
	public void begin (java.lang.String namespace, java.lang,String name, 
org.sax.Attributes attributes){
		ScarabIssues issues = (ScarabIssues) getDigester().peek();
		issues.importErrors = this.importErrors;
	}
}

registered with the same matching path.

hope that helps.

- robert