commons-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Glenn Goldenberg" <ggoldenb...@Initiatesystems.com>
Subject RE: [betwixt] AddDefaultsRule bug in 0.7RC2
Date Mon, 11 Jul 2005 21:22:57 GMT
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:robertburrelldonkin@blueyonder.co.uk]
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: commons-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-user-help@jakarta.apache.org
> 
> 


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


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


Mime
View raw message