5 Replies Latest reply on Oct 10, 2006 11:29 AM by aloubyansky

    SundayContentHandler: Don't add collections into collections

    aloubyansky

      Why not?

      Modified: jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/SundayContentHandler.java
      ===================================================================
      --- jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/SundayContentHandler.java 2006-10-10 12:16:10 UTC (rev 2114)
      +++ jbossxb/trunk/src/main/java/org/jboss/xb/binding/sunday/unmarshalling/SundayContentHandler.java 2006-10-10 12:16:40 UTC (rev 2115)
      @@ -652,6 +652,7 @@
      StackItem item = stack.peek();
      if(item.o != null &&
      !(item.o instanceof GenericValueContainer) &&
      + (item.o instanceof Collection == false) &&
      term.getAddMethodMetaData() == null &&
      term.getMapEntryMetaData() == null &&
      term.getPutMethodMetaData() == null)

        • 1. Re: SundayContentHandler: Don't add collections into collect

          I was seeing error messages like:

          java.lang.ClassCastExeption: ArrayList
          at myCollecton.add
          ...

          i.e. It was creating a new ArrayList, then trying to add it
          into the parent collection instead of using the parent collection as a collection.

          I tracked the problem down to where the ValueList always created a new ArrayList. Avoiding constructing of the ValueList meant it uses
          my collection as a collection.

          NOTE: This was a generic (it checks the types on add hence the ClassCast)
          custom collection.

          • 2. Re: SundayContentHandler: Don't add collections into collect
            aloubyansky

            I am not sure it's the right place to fix this. If you have a testcase I would like to look into it.

            • 3. Re: SundayContentHandler: Don't add collections into collect

              I found it while I was doing the new java annotation stuff.

              I found it back on Sunday, so I'm not sure if I can remember the details?

              But the XSD model was similar to the DescriptionGroup in javaee_5.xsd,
              with a java model like - I only show description(s) and this is pseudo code

              // Mapped to the group
              public class DescriptionGroup
              {
               Descritpions descritpions;
              }
              
              public class Descriptions implements Collection<Description>
              {
              }
              
              public class Description
              {
               String lang; // xml:lang attribute
               String value; // the description
              }
              


              It was trying to do:
              Descriptions.add(ArrayList)

              It completed ignored the fact that the parent/owner (Descriptions)
              was already a collection.

              • 4. Re: SundayContentHandler: Don't add collections into collect

                It might also have been related to my attempt to implement
                holders using a custom particle handler (I can't remember?)
                but the code was below.

                This basically replaced the original parent and reverted the
                object at the end. It didn't do anything with the setParent()
                though obviously it would use the replaced parent.

                /*
                * JBoss, Home of Professional Open Source
                * Copyright 2006, JBoss Inc., and individual contributors as indicated
                * by the @authors tag. See the copyright.txt in the distribution for a
                * full listing of individual contributors.
                *
                * This is free software; you can redistribute it and/or modify it
                * under the terms of the GNU Lesser General Public License as
                * published by the Free Software Foundation; either version 2.1 of
                * the License, or (at your option) any later version.
                *
                * This software is distributed in the hope that it will be useful,
                * but WITHOUT ANY WARRANTY; without even the implied warranty of
                * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
                * Lesser General Public License for more details.
                *
                * You should have received a copy of the GNU Lesser General Public
                * License along with this software; if not, write to the Free
                * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
                * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
                */
                package org.jboss.xb.binding.builder.runtime;
                
                import java.lang.reflect.InvocationTargetException;
                import java.util.HashMap;
                import java.util.Map;
                
                import javax.xml.namespace.NamespaceContext;
                import javax.xml.namespace.QName;
                
                import org.jboss.util.Strings;
                import org.jboss.util.collection.WeakIdentityHashMap;
                import org.jboss.xb.binding.builder.properties.Property;
                import org.jboss.xb.binding.sunday.unmarshalling.ParticleBinding;
                import org.jboss.xb.binding.sunday.unmarshalling.ParticleHandler;
                import org.jboss.xb.binding.sunday.unmarshalling.impl.runtime.RtElementHandler;
                import org.xml.sax.Attributes;
                
                /**
                 * HolderParticleHandler.
                 *
                 * @author <a href="adrian@jboss.com">Adrian Brock</a>
                 * @version $Revision: 1.1 $
                 */
                public class HolderParticleHandler implements ParticleHandler
                {
                 /** The delegate */
                 private ParticleHandler delegate = RtElementHandler.INSTANCE;
                
                 /** The holders */
                 private Map<QName, Property> holders = new HashMap<QName, Property>();
                
                 /** Interposed objects TODO This is a hack! */
                 private ThreadLocal<WeakIdentityHashMap> interposed = new ThreadLocal<WeakIdentityHashMap>();
                
                 /**
                 * Add a holder
                 *
                 * @param qName the qualified name to hold
                 * @param property the property
                 * @throws IllegalArgumentException for a null qName, property, or the property has no read method
                 */
                 public void addHolder(QName qName, Property property)
                 {
                 if (qName == null)
                 throw new IllegalArgumentException("Null qName");
                 if (property == null)
                 throw new IllegalArgumentException("Null property");
                 if (property.getRead() == null)
                 throw new IllegalArgumentException("Property has no getter " + property);
                 holders.put(qName, property);
                 }
                
                 public Object startParticle(Object parent, QName elementName, ParticleBinding particle, Attributes attrs, NamespaceContext nsCtx)
                 {
                 Object result = delegate.startParticle(parent, elementName, particle, attrs, nsCtx);
                 Object original = result;
                 if (result != null)
                 {
                 Property property = holders.get(elementName);
                 if (property != null)
                 {
                 try
                 {
                 result = property.getRead().invoke(original, null);
                 }
                 catch (InvocationTargetException e)
                 {
                 throw new RuntimeException("Error retrieving holder " + property.getRead().getName() + " for " + Strings.defaultToString(original), e.getCause());
                 }
                 catch (Exception e)
                 {
                 throw new RuntimeException("Error retrieving holder " + property.getRead().getName() + " for " + Strings.defaultToString(original), e);
                 }
                 if (result == null)
                 {
                 if (property.getWrite() == null)
                 throw new IllegalStateException("Unable to retrieve holder " + property.getRead().getName() + " for " + Strings.defaultToString(original) + " and the there is not setter method.");
                 try
                 {
                 result = property.getPropertyImpl().newInstance();
                 }
                 catch (Exception e)
                 {
                 throw new RuntimeException("Error instantiating new holder " + property.getPropertyImpl().getName(), e);
                 }
                 }
                 Object[] arguments = { result };
                 try
                 {
                 property.getWrite().invoke(original, arguments);
                 }
                 catch (InvocationTargetException e)
                 {
                 throw new RuntimeException("Error setting holder " + property.getWrite().getName() + " for " + Strings.defaultToString(original) + " with " + Strings.defaultToString(result), e.getCause());
                 }
                 catch (Exception e)
                 {
                 throw new RuntimeException("Error setting holder " + property.getWrite().getName() + " for " + Strings.defaultToString(original) + " with " + Strings.defaultToString(result), e);
                 }
                
                 if (result != original)
                 {
                 WeakIdentityHashMap map = interposed.get();
                 if (map == null)
                 {
                 map = new WeakIdentityHashMap();
                 interposed.set(map);
                 }
                 map.put(result, original);
                 }
                 }
                 }
                 return result;
                 }
                
                 public Object endParticle(Object o, QName elementName, ParticleBinding particle)
                 {
                 WeakIdentityHashMap map = interposed.get();
                 if (map != null)
                 {
                 Object object = map.remove(o);
                 if (object != null)
                 o = object;
                 }
                 return delegate.endParticle(o, elementName, particle);
                 }
                
                 public void setParent(Object parent, Object o, QName elementName, ParticleBinding particle, ParticleBinding parentParticle)
                 {
                 delegate.setParent(parent, o, elementName, particle, parentParticle);
                 }
                }
                


                • 5. Re: SundayContentHandler: Don't add collections into collect
                  aloubyansky

                  Ok, thanks for the info.