7 Replies Latest reply on Jan 30, 2006 7:05 AM by aloubyansky

    WildcardBinding (not RtElementHandler)

      Is this supported?

      I have the following in my schema:

       <xsd:complexType name="factoryType">
       <xsd:choice minOccurs="0">
       <xsd:any namespace="##other" processContents="strict"/>
       </xsd:choice>
       <xsd:attribute name="bean" type="xsd:string" use="optional"/>
       <xsd:attribute name="property" type="xsd:string" use="optional"/>
       <xsd:attribute name="state" type="controllerStateType" use="optional"/>
       </xsd:complexType>
      


      Which is aiming to differentiate:
      <factory bean="blah"/>


      from
       <factory>
       <javabean xmlns="urn:jboss:javabean:1.0" class="org.jboss.test.kernel.config.support.SimpleBeanFactory"/>
       </factory>
      


      But the use of the choice binding means that although it constructs the javabean
      SimpleBeanFactory, "skip" is true.

      Even if I force skip to false,
       TypeBinding factoryType = schemaBinding.getType(factoryTypeQName);
       factoryType.getParticle().getTerm().setSkip(Boolean.FALSE);
      

      I get a message about needing ClassMetaData for the model group???

        • 1. Re: WildcardBinding (not RtElementHandler)

          To try the failing test:

          cd kernel
          ./build.sh -f build-test.xml one-test -Dtest=org.jboss.test.kernel.config.test.FactoryXMLTestCase
          


          • 2. Re: WildcardBinding (not RtElementHandler)
            aloubyansky

             

            "adrian" wrote:
            Is this supported?

            What exactly? So far, what I see is what I would expect.

            Skip works only for the component it is defined on and does not affect its children.

            Why choice? Why not just
            <xsd:any namespace="##other" processContents="strict" minOccurs='0'/>
            ?

            The exception I see running the test is
            java.lang.IllegalArgumentException: Null name
             at org.jboss.dependency.plugins.AbstractController.getContext(AbstractController.java:101)
             at org.jboss.kernel.plugins.dependency.AbstractKernelController.getContext(AbstractKernelController.java:94)
             at org.jboss.dependency.plugins.AbstractDependencyItem.resolve(AbstractDependencyItem.java:117)
             at org.jboss.dependency.plugins.AbstractDependencyInfo.resolveDependencies(AbstractDependencyInfo.java:128)
             at org.jboss.dependency.plugins.AbstractController.resolveContexts(AbstractController.java:476)
             at org.jboss.dependency.plugins.AbstractController.resolveContexts(AbstractController.java:419)
             at org.jboss.dependency.plugins.AbstractController.resolveContexts(AbstractController.java:379)
             at org.jboss.dependency.plugins.AbstractController.install(AbstractController.java:225)
             at org.jboss.dependency.plugins.AbstractController.install(AbstractController.java:151)
             at org.jboss.kernel.plugins.deployment.AbstractKernelDeployer.deployBean(AbstractKernelDeployer.java:291)
             at org.jboss.kernel.plugins.deployment.AbstractKernelDeployer.deployBeans(AbstractKernelDeployer.java:261)
             at org.jboss.kernel.plugins.deployment.AbstractKernelDeployer.deploy(AbstractKernelDeployer.java:117)
             at org.jboss.kernel.plugins.deployment.xml.BeanXMLDeployer.deploy(BeanXMLDeployer.java:95)
             at org.jboss.test.kernel.config.support.XMLUtil.<init>(XMLUtil.java:76)
             at org.jboss.test.kernel.config.test.AbstractKernelConfigTest.bootstrapXML(AbstractKernelConfigTest.java:69)
             at org.jboss.test.kernel.config.test.FactoryXMLTestCase.simpleInstantiateFromFactory(FactoryXMLTestCase.java:53)
             at org.jboss.test.kernel.config.test.FactoryTestCase.testSimpleInstantiateFromFactory(FactoryTestCase.java:62)
             at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
             at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
             at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
             at junit.extensions.TestDecorator.basicRun(TestDecorator.java:22)
             at junit.extensions.TestSetup$1.protect(TestSetup.java:19)
             at junit.extensions.TestSetup.run(TestSetup.java:23)
            


            • 3. Re: WildcardBinding (not RtElementHandler)

               

              "alex.loubyansky@jboss.com" wrote:

              Why choice?


              Because it reproduces the same problem that already exists for valueGroup
              (and it is related to other WildcardWrapper problem anyway).

              The problem is due to it using javabean element handler to setParent().
              Since this is a top level element in the included schema, it can have no idea
              how to setParent() on a different schema's object.

              I added the following to TRACE logging to DefaultElementHandler
              and you can see this is being logged.
              
               public void setParent(Object parent, Object o, QName qName, ElementBinding element, ElementBinding parentElement)
               {
               if (log.isTraceEnabled())
               log.trace("Not setting " + o + " on " + parent + " for " + qName);
               }
              


              The error message is caused by it still having an
              uninitialized AbstractDependencyValueMetadata in the holder
              which should have been replaced by the javabean.

              • 4. Re: WildcardBinding (not RtElementHandler)

                I have a temporary solution to the problem, which I am going to commit.
                It is fully backwards compatible because you have to explicitly use it
                for it to take affect.

                Basically, I allow a WildcardHandler to be added to a type's wildcard.

                If there are no registered interceptors for the parent and there is a wildcard
                handler on the parent type's wildcard,
                it passes the setParent to the wildcard handler instead of the child's handler.

                
                 //
                 // setParent
                 //
                
                 i = interceptors.size();
                 // todo yack...
                 if(i == 0)
                 {
                + ParticleHandler wildcardHandler = null;
                
                 ParticleBinding parentParticle = null;
                 for(int j = 0; j < stack.size(); ++j)
                 {
                 StackItem item = (StackItem) stack.peek(j);
                 ParticleBinding peeked = item.particle;
                 if(peeked != null && peeked.getTerm() instanceof ElementBinding)
                 {
                 parentParticle = peeked;
                + WildcardBinding wildcard = ((ElementBinding) parentParticle.getTerm()).getType().getWildcard();
                + if (wildcard != null)
                + wildcardHandler = wildcard.getWildcardHandler();
                 break;
                 }
                 }
                
                 if(parent != null)
                 {
                 /*if(o == null)
                 {
                 throw new JBossXBRuntimeException(endName + " is null!");
                 } */
                + if (wildcardHandler != null)
                + wildcardHandler.setParent(parent, o, endName, particle, parentParticle);
                + else
                 handler.setParent(parent, o, endName, particle, parentParticle);
                 }
                


                I think a better solution would be allow an interceptor to be registered against
                a wildcard? But this achieves the same thing as my solution????

                 // wildcard
                 parentType.pushWildcardInterceptor(new DefaultElementInterceptor()
                 {
                 public void add(Object parent, Object child, QName name)
                 {
                ...
                 }
                 });
                


                This fixes the WildcardWrapper test and the property with a wildcard
                in the testsuite, e.g. ContainerInitalizer
                
                 public SchemaBinding init(SchemaBinding schema)
                 {
                 ClassMetaData classMetaData = new ClassMetaData();
                 classMetaData.setImpl(Container.class.getName());
                
                 PropertyMetaData property = new PropertyMetaData();
                 property.setName("value");
                
                 ElementBinding containerStrict = schema.getElement(containerStrictQName);
                 containerStrict.setClassMetaData(classMetaData);
                 containerStrict.getType().getWildcard().setWildcardHandler(wildcardHandler);
                 ElementBinding containerLax = schema.getElement(containerLaxQName);
                 containerLax.setClassMetaData(classMetaData);
                 containerStrict.getType().getWildcard().setWildcardHandler(wildcardHandler);
                 ElementBinding containerSkip = schema.getElement(containerSkipQName);
                 containerSkip.setClassMetaData(classMetaData);
                 containerStrict.getType().getWildcard().setWildcardHandler(wildcardHandler);
                
                 return schema;
                 }
                
                 private static class ContainerWildcardHandler extends DefaultWildcardHandler
                 {
                 public void setParent(Object parent, Object o, QName elementName, ElementBinding element, ElementBinding parentElement)
                 {
                 Container container = (Container) parent;
                 container.setValue(o);
                 }
                 }
                


                I don't know how this will map to annotations?
                i.e. where you want to do something other than setXXX() in setParent.

                • 5. Re: WildcardBinding (not RtElementHandler)
                  aloubyansky

                   

                  "adrian@jboss.org" wrote:
                  The problem is due to it using javabean element handler to setParent().
                  Since this is a top level element in the included schema, it can have no idea
                  how to setParent() on a different schema's object.


                  Don't annotations on the wildcard work? e.g. property, addMethod, putMethod? It's not RtElementHandler but you can get access to the metadata in DefaultElementHandler.

                  OTOH, wildcard handler seems to make sense to me.

                  • 6. Re: WildcardBinding (not RtElementHandler)

                    I don't think the addMethod, putMethod will work because it is looking at the child
                    element handler.
                    The child knows nothing about the parent schema.

                    It will probably work with annotations?

                    • 7. Re: WildcardBinding (not RtElementHandler)
                      aloubyansky

                      I meant on the wildcard which is in the target schema. You definetely can set metadata on the wildcard but, actually, I am not sure that anything other than property currently works.