Hey robert:

After fixing the "add-adder" bug, I ran into an issue using "updater" in the 
ElementRule for a property of type Map and another issue with "add-adder" and 
mixed Collection property types.

The first issue with a Map property is illustrated by this 
TestBetwixtMapUpdater test case that follows.  The issue is that if "add-adder" 
is false then the "updater" that is specified for a Map property is ignored.  
This issue can't been seen without applying the previous fix for honoring the 
"add-adder" attribute.  I debugged into the ElementRule class and there was no 
logic to handle adding a Map "updater".  I was able to path this with the 
following changes:

in XMLIntrospector, line 959, change visibility of setMapAdder() to public:
        public void setMapAdder(

in ElementRule, line 237, update configureProperty() in two places to handle 
Map adders:
        ...
                if ( updateMethodName.equals( method.getName() ) ) {
                    // we have a matching name
                    
                    // updater should have one parameter unless type is Map
                    int numParams = 1;
                    if (Map.class.isAssignableFrom(type)) {
                        // updater for Map should have two parameters
                        numParams = 2;
                    }
                    
                    if (methods[i].getParameterTypes().length == numParams) {
                        // we'll use first match
                        updateMethod = methods[i];
                        if ( log.isTraceEnabled() ) {
                            log.trace("Matched method:" + updateMethod);
                        } 
                        // done since we're using the first match
                        break;
                    }
                }
        ...
                if (updateMethod == null) {
                if ( log.isInfoEnabled() ) {
                    
                    log.info("No method with name '" + updateMethodName + "' 
found for update");
                }
            } else {
                        // assign updater to elementDescriptor
                                if (Map.class.isAssignableFrom(type)) {
                                        Map elementsByPropertyName = new 
HashMap();
                                        
elementsByPropertyName.put(propertyDescriptor.getName(), elementDescriptor);
                                        
                                        
getXMLIntrospector().setMapAdder(elementsByPropertyName, updateMethod);
                                        
                                } else {
                        elementDescriptor.setUpdater( new MethodUpdater( 
updateMethod ) );
                        elementDescriptor.setSingularPropertyType( 
updateMethod.getParameterTypes()[0] );
                        if ( log.isTraceEnabled() ) {
                            log.trace( "Set custom updater on " + 
elementDescriptor);
                        }
                    }
            }

With these changes, the TestBetwixtMapUpdater test passes (along with all other 
tests).  It seemed easy to change the visibility of setMapAdder() and reuse 
that logic in the ElementRule, but I don't know if that is the best solution...

The other issue is that using addDefaults in a class where you want to display 
a mixed collection causes the mixed collection elements to not display 
properly.  It seems that if an ElementRule is specified with no name attribute 
and a mixed Collection property, than the output XML only has element tags 
based on the collection object class type if "add-adders" is false.  It looks 
like when adding default Adders, betwixt overwrites the settings for mixed 
collection properties somehow.  If you comment out the addChildBean() method, 
then "add-adders='true'" works, but the beanReader won't be able to convert the 
xml back into the bean.  Here is the result from TestBetwixtMixedCollection 
which is included below as well:

with <addDefaults add-properties='true' add-adders='true'/>:
 <?xml version="1.0"?>
  <parentBean stuff="stuff" id="1">
    <childBeans>
      <childBean/>
      <childBean/>
    </childBeans>
  </parentBean>

with <addDefaults add-properties='true' add-adders='false'/>:
 <?xml version="1.0"?>
  <parentBean id="1">
    <childBeans>
      <childBean1/>
      <childBean2/>
    </childBeans>
  </parentBean>

Please let me know if I'm missing something around these two issues...

Thanks,
glenn

*********************************************************************************************

package random;

import java.io.StringReader;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.betwixt.io.BeanReader;
import org.apache.commons.betwixt.io.BeanWriter;
import org.xml.sax.InputSource;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

public class TestBetwixtMapUpdater extends TestCase
{

        public TestBetwixtMapUpdater(String name)
        {
        super(name);
    }
    
    public static Test suite()
    {
        TestSuite suite = new TestSuite(TestBetwixtMapUpdater.class);
        
        return suite;
    }
    
    public void testMapUpdater()
    {
        String config = 
                "<?xml version='1.0'?>" +
                "<betwixt-config primitiveTypes='attribute'>" +
                "    <class name='random.TestBetwixtMapUpdater$ParentBean'>" +
                "        <element name='parentBean'>" +
                "            <element name='pairs'>" +
                "                <element property='pairs' updater='addPair'/>" 
+
                "            </element>" +
                "            <addDefaults add-properties='true' 
add-adders='false'/>" +
                "        </element>" +
                "    </class>" +
                "</betwixt-config>";
        
        String result = 
            "<?xml version=\"1.0\"?>\n" +
            "  <parentBean id=\"1\">\n" +
            "    <pairs>\n" +
            "      <entry id=\"2\">\n" +
            "        <key>key</key>\n" +
            "        <value>value</value>\n" +
            "      </entry>\n" +
            "    </pairs>\n" +
            "  </parentBean>\n";
        
        try
        {
                ParentBean pb = new ParentBean();;
                pb.getPairs().put("key", "value");
                
                StringWriter writer = new StringWriter();
                BeanWriter beanWriter = new BeanWriter(writer);
            beanWriter.enablePrettyPrint();
                beanWriter.getXMLIntrospector().register(new InputSource(new 
StringReader(config)));
                beanWriter.writeXmlDeclaration("<?xml version=\"1.0\"?>");
                beanWriter.write(pb);
                
                System.out.println(writer.toString());
                
                assertEquals(result, writer.toString());
                
                BeanReader beanReader  = new BeanReader();
                        beanReader.registerMultiMapping(new InputSource(new 
StringReader(config)));
                        
                        
                        ParentBean pbRead = (ParentBean)beanReader.parse(new 
StringReader(writer.toString()));
                                
                        StringWriter writer2 = new StringWriter();
                BeanWriter beanWriter2 = new BeanWriter(writer2);
            beanWriter2.enablePrettyPrint();
                beanWriter2.getXMLIntrospector().register(new InputSource(new 
StringReader(config)));
                beanWriter2.writeXmlDeclaration("<?xml version=\"1.0\"?>");
                beanWriter2.write(pbRead);
                
                System.out.println(writer2.toString());
                
                assertEquals(result, writer2.toString());
        }
        catch (Exception e)
        {
                fail(e.getMessage());
        }
    }
    
    public static class ParentBean
    {
        private Map pairs = new HashMap();

                public Map getPairs()
                {
                        return pairs;
                }

                public void setPairs(Map pairs)
                {
                        this.pairs = pairs;
                }
                
                public void addPair(String key, String value)
                {
                        pairs.put(key, value);
                }
        
    }
    
}

*********************************************************************************************

package random;

import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.betwixt.io.BeanWriter;
import org.xml.sax.InputSource;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

public class TestBetwixtMixedCollection extends TestCase
{

        public TestBetwixtMixedCollection(String name)
        {
        super(name);
    }
    
    public static Test suite()
    {
        TestSuite suite = new TestSuite(TestBetwixtMixedCollection.class);
        
        return suite;
    }
    
    public void testWithDefaults()
    {
        toXml(true);
    }
    
    public void testWithoutDefaults()
    {
        toXml(false);
    }
    
    protected void toXml(boolean addAdders)
    {           
        StringReader configReader = new StringReader(
                "<?xml version='1.0' ?>" +
                "<betwixt-config primitiveTypes='attribute'>" +
                "    <class 
name='random.TestBetwixtMixedCollection$ParentBean'>" +
                "        <element name='parentBean'>" +
                "            <element name='childBeans'>" +
                "                <element property='childBeans'/>" +
                "            </element>" +
                "            <addDefaults add-properties='true' add-adders='" + 
addAdders + "'/>" + 
                "        </element>" +
                "    </class>" +
                "    <class 
name='random.TestBetwixtMixedCollection$ChildBean1'>" +
                "        <element name='childBean1'>" +
                "            <addDefaults/>"  +
                "        </element>" +
                "    </class>" +
                "    <class 
name='random.TestBetwixtMixedCollection$ChildBean2'>" +
                "        <element name='childBean2'>" +
                "            <addDefaults/>"  +
                "        </element>" +
                "    </class>" +
                "</betwixt-config>");
        
        try
        {
                ParentBean pb = new ParentBean();
                pb.setStuff("stuff");
                ChildBean1 cb1 = new ChildBean1();
                pb.getChildBeans().add(cb1);
                ChildBean2 cb2 = new ChildBean2();
                pb.getChildBeans().add(cb2);
                
                StringWriter writer = new StringWriter();
                BeanWriter beanWriter = new BeanWriter(writer);
            beanWriter.enablePrettyPrint();
                beanWriter.getXMLIntrospector().register(new 
InputSource(configReader));
                beanWriter.writeXmlDeclaration("<?xml version=\"1.0\"?>");
                beanWriter.write(pb);
                
                System.out.println(writer.toString());
                
        }
        catch (Exception e)
        {
                fail(e.getMessage());
        }
    }
    
    public static class ParentBean
    {
        private List childBeans = new ArrayList();
        private String stuff = null;
        
        public List getChildBeans()
        {
                return childBeans;
        }
        
        public void setChildBeans(List childBeans)
        {
                this.childBeans = childBeans;
        }
        
        public void addChildBean(ChildBean childBean)
        {
                getChildBeans().add(childBean);
        }

                public String getStuff()
                {
                        return stuff;
                }

                public void setStuff(String stuff)
                {
                        this.stuff = stuff;
                }
    }
    
    public static abstract class ChildBean
    {
    }
    
    public static class ChildBean1 extends ChildBean
    {
    }
    
    public static class ChildBean2 extends ChildBean
    {
    }
    
}

*********************************************************************************************

-----Original Message-----
From: robert burrell donkin
[mailto:[EMAIL PROTECTED]
Sent: Monday, July 11, 2005 1:30 PM
To: Jakarta Commons Users List
Subject: Re: [betwixt] AddDefaultsRule bug in 0.7RC2


hi glenn

add-adder is indeed buggy. the unit tests seemed half written for this
feature :-/ 

i'm a little unsure how to proceed. either, the fix put into head or the
current release vote could be cancelled and this fix rolled into a fresh
release candidate. 

opinions?

- robert

On Thu, 2005-07-07 at 14:52 -0500, Glenn Goldenberg wrote:
> I think there may be a bug in the 
> org.apache.commons.betwixt.digester.AddDefaultsRule class.  I was testing the 
> "add-adders" and "add-properties" flags on the <addDefaults> element in the 
> .betwixt file.  The flags didn't seem to work correctly, so I debugged into 
> AddDefaultsRule and saw on line 69:
> 
>       addProperties = Boolean.valueOf(addAddersAttributeValue).booleanValue();
> 
> I changed this to:
> 
>       addAdders = Boolean.valueOf(addAddersAttributeValue).booleanValue();
> 
> and things worked as expected.
> 
> thanks,
> glenn
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
> 
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to