Dims and Ajith,

I took Dims' advice and created the attached patch to modules/codegen/src of Axis2 0.94.  This may not be the best implementation of <choice> but it is very simple and meets my use cases.  The idea is this.  A <choice> is treated just like an <all> where each enclosed element has minOccurs=0, except that in the generated code setting any constituent element automatically unsets all the others.  Thus, whatever choice you set last is the choice you get and you only get one.  (The code does not enforce what happens if you don't set any; this, additional error checking, and accessors to fully determine the state of what has been chosen, could all be improved.)

I'm just starting to work with it so have not tested it much yet, but the generated code looks right to me.  It's very simple because it reuses all the code that is already there and makes just a few mods.

I haven't tried complex nesting cases to see if they all work, and probably wont' because I only need <choice> of <element>'s, although in principle any nesting that <all> handles, choice should too.

I noticed in doing this that none of the particles handle the <element ref=...> construction.  This is somewhat painful, but livable.  If I had more time, I'd try to fix that.  It looks like it might be more complex than this hack due to the way the names are used in the data structures.

I'd appreciate if you guys would add this to axis2 so I don't have to patch future releases.  If it is not deemed suitable, please let me know why as perhaps I could fix it, or just fix it!

Thanks,

Chuck


Davanum Srinivas <[EMAIL PROTECTED]> wrote on 01/24/2006 05:19:41 AM:

OR help implement choice in ADB :) i highly recommend that because
i've seen some perf issues with xmlbeans (check xmlbeans jira)

-- dims

On 1/24/06, Ajith Ranabahu <[EMAIL PROTECTED]> wrote:
  
Hi Chuck,
 The choice element is not handled in the ADB schema compiler yet (at least
we are not sure what is the best way to deal with it). Right now we do not
throw any exceptions but silently skip that (that is why the empty class)
 Please use XMLBeans if you need the support for choice for  now.


On 1/24/06, Chuck Williams <[EMAIL PROTECTED]> wrote:
    
I have a complexType that contains a <choice> of two alternative
elements, like this:

<xsd:complexType name="AorB">
    <xsd:choice>
        <xsd:element name="A" type="xsd:string"/>
        <xsd:element name="B" type="xsd:string"/>
    </xsd:choice>
</xsd:complexType>

and a reponse message that contains a value of this type:

<message name="respmessage">
    <part name="resp" type="asxsd:AorB"/>
</message>

and a portType with an operation that returns the response message:

<portType name="FooPortType">
    <operation name="Bar">
        <input .../>
        <output message="as:respmessage"/>
    </operation>
</portType>

WSDL2Java generates a class  AorB and requires it as content of the
respmessage to be returned from the Bar() method in the generated
FooPortTypeSkeleton.  However, AorB has no setters or getters, so there
is no way to give it the A or B element to return.  Also, A and B do not
extend AorB so there is no way to pass either of them directly.

How is this supposed to work?

Thanks for any help,

Chuck


      

--
Ajith Ranabahu
    


--
Davanum Srinivas : http://wso2.com/blogs/
  

diff -ur codegen.src.orig/org/apache/axis2/schema/BeanWriterMetaInfoHolder.java codegen.src.new/org/apache/axis2/schema/BeanWriterMetaInfoHolder.java
--- codegen.src.orig/org/apache/axis2/schema/BeanWriterMetaInfoHolder.java	2006-01-24 18:14:07.000000000 -1000
+++ codegen.src.new/org/apache/axis2/schema/BeanWriterMetaInfoHolder.java	2006-01-24 18:13:26.000000000 -1000
@@ -32,6 +32,7 @@
 
 
     private boolean ordered = false;
+    private boolean choice = false;
     private boolean anonymous = false;
     private boolean extension = false;
     private String extensionClassName = "";
@@ -115,6 +116,24 @@
     public void setOrdered(boolean ordered) {
         this.ordered = ordered;
     }
+        
+    /**
+     * Gets the choice status.
+     *
+     * @return Returns boolean.
+     */
+    public boolean isChoice() {
+        return choice;
+    }
+
+    /**
+     * Sets the choice flag. 
+     *
+     * @param choice
+     */
+    public void setChoice(boolean choice) {
+        this.choice = choice;
+    }
 
     /**
      * Registers a mapping.
diff -ur codegen.src.orig/org/apache/axis2/schema/SchemaCompiler.java codegen.src.new/org/apache/axis2/schema/SchemaCompiler.java
--- codegen.src.orig/org/apache/axis2/schema/SchemaCompiler.java	2006-01-24 18:14:07.000000000 -1000
+++ codegen.src.new/org/apache/axis2/schema/SchemaCompiler.java	2006-01-24 18:13:26.000000000 -1000
@@ -497,7 +497,9 @@
             XmlSchemaObjectCollection items = ((XmlSchemaAll) particle).getItems();
             process(items, metainfHolder, false);
         } else if (particle instanceof XmlSchemaChoice) {
-            //put the code here to handle the choice!
+            XmlSchemaObjectCollection items = ((XmlSchemaChoice) particle).getItems();
+            metainfHolder.setChoice(true);
+            process(items, metainfHolder, false);
         }
     }
 
diff -ur codegen.src.orig/org/apache/axis2/schema/template/ADBBeanTemplate.xsl codegen.src.new/org/apache/axis2/schema/template/ADBBeanTemplate.xsl
--- codegen.src.orig/org/apache/axis2/schema/template/ADBBeanTemplate.xsl	2006-01-24 18:14:07.000000000 -1000
+++ codegen.src.new/org/apache/axis2/schema/template/ADBBeanTemplate.xsl	2006-01-24 18:13:26.000000000 -1000
@@ -32,6 +32,8 @@
     <xsl:template match="bean">
 
         <xsl:variable name="name"><xsl:value-of select="@name"/></xsl:variable>
+        <xsl:variable name="choice"><xsl:value-of select="@choice"/></xsl:variable>
+        
     <!-- write the class header. this should be done only when unwrapped -->
 
         <xsl:if test="not(not(@unwrapped) or (@skip-write))">
@@ -64,8 +66,18 @@
 
             </xsl:otherwise>
         </xsl:choose>
-
-
+        
+        <xsl:if test="$choice">
+            /** Whenever a new property is set ensure all others are unset
+             *  There can be only one choice and the last one wins
+             */
+            private void clearAllSettingTrackers() {
+            <xsl:for-each select="property">
+                local<xsl:value-of select="@javaname"/>Tracker = false;
+            </xsl:for-each>
+            }
+        </xsl:if>
+        
         <xsl:for-each select="property">
             <xsl:variable name="propertyType"><xsl:value-of select="@type"></xsl:value-of></xsl:variable>
             <xsl:variable name="propertyName"><xsl:value-of select="@name"></xsl:value-of></xsl:variable>
@@ -81,7 +93,7 @@
             private <xsl:value-of select="$propertyType"/><xsl:text> </xsl:text><xsl:value-of select="$varName" /> ;
             <!-- Generate a tracker only if the min occurs is zero, which means if the user does
                  not bother to set that value, we do not send it -->
-            <xsl:if test="$min=0">
+            <xsl:if test="($min=0) or $choice">
             /*  This tracker boolean wil be used to detect whether the user called the set method
                 for this attribute. It will be used to determine whether to include this field
                 in the serialized XML
@@ -115,8 +127,9 @@
                     }
                 </xsl:if>
             </xsl:if>
-             <xsl:if test="$min=0">
+             <xsl:if test="($min=0) or $choice">
              //update the setting tracker
+             clearAllSettingTrackers();
              <xsl:value-of select="$settingTracker"/> = true;
              </xsl:if>
             this.<xsl:value-of select="$varName"/>=param;
@@ -143,7 +156,7 @@
                     <xsl:variable name="settingTracker">local<xsl:value-of select="@javaname"/>Tracker</xsl:variable>
 
 
-                    <xsl:if test="$min=0"> if (<xsl:value-of select="$settingTracker"/>){</xsl:if>
+                    <xsl:if test="($min=0) or $choice"> if (<xsl:value-of select="$settingTracker"/>){</xsl:if>
                     <xsl:choose>
                         <xsl:when test="@ours or @any">
                             elementList.add(new javax.xml.namespace.QName("<xsl:value-of select="$namespace"/>",
@@ -160,7 +173,7 @@
                              elementList.add(org.apache.axis2.databinding.utils.ConverterUtil.convertToString(<xsl:value-of select="$varName"/>));
                         </xsl:otherwise>
                     </xsl:choose>
-                    <xsl:if test="$min=0">}</xsl:if>
+                    <xsl:if test="($min=0) or $choice">}</xsl:if>
                 </xsl:for-each>
 
                 <xsl:for-each select="[EMAIL PROTECTED]">
diff -ur codegen.src.orig/org/apache/axis2/schema/writer/JavaBeanWriter.java codegen.src.new/org/apache/axis2/schema/writer/JavaBeanWriter.java
--- codegen.src.orig/org/apache/axis2/schema/writer/JavaBeanWriter.java	2006-01-24 18:14:07.000000000 -1000
+++ codegen.src.new/org/apache/axis2/schema/writer/JavaBeanWriter.java	2006-01-24 18:13:26.000000000 -1000
@@ -342,6 +342,11 @@
         if (metainf.isExtension()) {
             XSLTUtils.addAttribute(model, "extension", metainf.getExtensionClassName(), rootElt);
         }
+        
+        if (metainf.isChoice()) {
+            XSLTUtils.addAttribute(model, "choice", "yes", rootElt);
+        }
+        
         // go in the loop and add the part elements
         QName[] qNames;
         if (metainf.isOrdered()) {

Reply via email to