Alright, I've finished a first version of the patch for your
evaluation. This adds support for a more "C-like" handling of
string-type enumerations, by allowing values to be read and written
with a native enum structure.
Summary of changes:
src/org/apache/axis2/schema/writer/CStructWriter.java:
- Capitalize and normalize (i.e., remove invalid characters) the "id"
property in enumFacet tags
src/org/apache/axis2/schema/template/CADBBeanTemplateHeader.xsl:
- Generate enum declaration
- Generate declarations for specialized enum getter and setter
src/org/apache/axis2/schema/template/CADBBeanTemplateSource.xsl
- Generate specialized getter and setter; the data is still stored in
string format, these functions simply convert back and forth
I'll be happy to hear your comments!
Cheers,
Sérgio
---
On Thu, Apr 24, 2008 at 1:23 PM, Dimuthu Gamage <[EMAIL PROTECTED]> wrote:
> Yea you are right, For enumeration mostly the base type is a string. I
> wrote that schema part just to show you that you can handle the
> enumeration detection from the xslt.
>
> BTW I think I was wrong with the idea later one is better. It still
> make more sense, but thinking about the factors I think we better go
> with the 1st one.
>
> backward compatibility - as you suggested.
> strings have to be converted to a particular format to set them as
> members of an enum ( like capitalizing, removing spaces and other
> characters with underscores),
>
> So I think still there can be users who like to use the old API ( I
> mean just getters/setters for string), So it is better to keep them
> and add set_param_enum/get_param_enum functions separately.
>
> Thanks
> Dimuthu
>
>
>
>
> On Thu, Apr 24, 2008 at 5:22 PM, Sérgio Gomes <[EMAIL PROTECTED]> wrote:
> > Hi Dimuthu,
> >
> > Actually, the enumeration is defined as follows:
> >
> >
> > <simpleType name="DayOfWeek" >
> > <restriction base="xsd:string">
> > <enumeration value="Monday"/>
> > <enumeration value="Tuesday"/>
> > <enumeration value="Wednesday"/>
> > <enumeration value="Thursday"/>
> > <enumeration value="Friday"/>
> > <enumeration value="Saturday"/>
> > <enumeration value="Sunday"/>
> > </restriction>
> > </simpleType>
> >
> > Note the string base for the restriction. I guess it's what makes
> > sense and it is indeed consistent with what I've seen in other places,
> > since if you're defining string values, you'd expect the restriction
> > to be for them to be strings.
> >
> > This generates the following intermediate XML, however:
> >
> > <?xml version="1.0" encoding="UTF-8"?>
> > <class caps-name="DAYOFWEEK" name="DayOfWeek" nsprefix="ns1"
> > nsuri="https://adwords.google.com/api/adwords/v11"
> > originalName="DayOfWeek" simple="yes" unwrapped="yes">
> > <property caps-cname="DAYOFWEEK" caps-type="AXIS2_CHAR_T*"
> > cname="DayOfWeek" minOccurs="1" name="DayOfWeek" notattribute="yes"
> > nsuri="https://adwords.google.com/api/adwords/v11"
> > originalName="DayOfWeek" prefix="" restrictionBaseType="yes"
> > shorttypename="string" simple="yes" type="axis2_char_t*">
> > <enumFacet id="Monday" value="Monday"/>
> > <enumFacet id="Tuesday" value="Tuesday"/>
> > <enumFacet id="Wednesday" value="Wednesday"/>
> > <enumFacet id="Thursday" value="Thursday"/>
> > <enumFacet id="Friday" value="Friday"/>
> > <enumFacet id="Saturday" value="Saturday"/>
> > <enumFacet id="Sunday" value="Sunday"/>
> > </property>
> > </class>
> >
> > As you see, all the types are string-oriented here, which will affect
> > the code for the whole class, causing it to store the property as a
> > string:
> >
> > struct adb_DayOfWeek
> > {
> > axutil_qname_t* qname;
> > axis2_char_t* property_DayOfWeek;
> > axis2_bool_t is_valid_DayOfWeek;
> > };
> >
> > So in order to make enumerations store their properties as ints, I
> > guess I'd have to somehow smartly detect enumerations and handle them
> > as a special case in the intermediate XML generation code, or
> > otherwise fill the entire stylesheet with checks. The only other
> > option is to store the property as a string and do the string <-> int
> > conversion I had mentioned in my previous post (either via specialized
> > extra getters/setters for enums, or by recognizing an enum and
> > changing the code for its default setters/getters).
> >
> > I'm leaning towards the latter option (with modified default
> > getters/setters), but would be willing to do the former if you think
> > it makes more sense.
> >
> > Cheers,
> > Sérgio
> >
> > ---
> >
> >
> > On Thu, Apr 24, 2008 at 3:17 AM, Dimuthu Gamage <[EMAIL PROTECTED]> wrote:
> > > Hi Sérgio,
> > >
> > > See my inline comments.
> > >
> > >
> > > On Wed, Apr 23, 2008 at 7:23 PM, Sérgio Gomes <[EMAIL PROTECTED]>
> wrote:
> > > > Hi Dimuthu,
> > > >
> > > > I'm developing the patch right now (I'm now able to generate the
> enum
> > > > declaration) and I found that I have two options to proceed:
> > > >
> > > > 1 - Add specialized getters/setters for enumerations, while keeping
> > > > the base type as a string. They would be named something like
> > > > adb_<property>_get_<property>_enum and
> > > > adb_<property>_set_<property>_enum. I'd have to do the conversion
> > > > between the C enum struct and the stored string within the function
> > > > (basically with a big if/else chain). This solution would preserve
> > > > backwards compatibility and wouldn't require any changes to the java
> > > > code, just XSL changes.
> > > >
> > > > 2 - Completely change support for enumerations, by storing them as
> int
> > > > and changing the setters/getters to use the C enum structure
> instead.
> > > > This would break backwards compatibility and require java writer
> > > > changes (not exactly sure which files), but would be much more
> elegant
> > > > in terms of generated C code.
> > >
> > > I think I prefer this approach. Although this break the backward
> > > compatibility, this is the most elegant way to do it in C.
> > > And in fact this too doesn't require to change any of the java code,
> > > you will be able to handle it in xslt itself. That is the java writer
> > > will give us an intermediate xml which is something like this for that
> > > adb object corresponding to the a type like this.
> > >
> > > <xs:simpleType name="derivedType">
> > > <xs:restriction base="xs:int">
> > > <xs:enumeration value="test1"/>
> > > <xs:enumeration value="test2"/>
> > > </xs:restriction>
> > > </xs:simpleType>
> > >
> > > <class caps-name="DERIVEDTYPE" name="derivedType" nsprefix="ns1"
> > > nsuri="http://wso2.org/dyn/codegen/demo" originalName="derivedType"
> > > simple="yes" unwrapped="yes">
> > > <property caps-cname="DERIVEDTYPE" caps-type="INT"
> > > cname="derivedType" minOccurs="1" name="derivedType"
> > > notattribute="yes" nsuri="http://wso2.org/dyn/codegen/demo"
> > > originalName="derivedType" prefix="" p
> > > rimitive="yes" restrictionBaseType="yes" shorttypename="int"
> > > simple="yes" type="int">
> > > <enumFacet id="test1" value="test1"/><enumFacet id="test2"
> > > value="test2"/>
> > > </property>
> > > </class>
> > >
> > > There you can check whether the enumFacet element exists and if so
> > > change the method signature and the logic of the getters/setters
> > > itself from the xslt itself.
> > >
> > >
> > > Thanks
> > > Dimuthu
> > >
> > >
> > >
> > >
> > >
> > >
> > > >
> > > > Have you got any thoughts on this?
> > > >
> > > > Cheers,
> > > > Sérgio
> > > >
> > > > PS - I switched to my work email, that will make things easier for
> me.
> > > >
> > > > ---
> > > > On Sun, Apr 13, 2008 at 1:05 PM, Sérgio Gomes <[EMAIL PROTECTED]>
> wrote:
> > > > > Hi Dimuthu,
> > > > >
> > > > > Thanks for getting back to me. I'll give that patch a try next
> week,
> > > > > I'll let you know.
> > > > >
> > > > > Cheers,
> > > > > Sérgio
> > > > >
> > > > > ---
> > > > >
> > > > >
> > > > > On Fri, Apr 11, 2008 at 9:21 PM, Dimuthu Gamage <[EMAIL
> PROTECTED]> wrote:
> > > > > > Hi Sérgio,
> > > > > >
> > > > > > Yea, you are correct on this. We should be able to declare
> them in an
> > > > > > enum to provide interger constants in the API. It should be
> trivial.
> > > > > > Why not you try that and propose a patch?
> > > > > >
> > > > > > If you like to try you have to checkout the axis2/java source
> code
> > > > > > from
> https://svn.apache.org/repos/asf/webservices/axis2/trunk/java
> > > > > >
> > > > > > and you may need to edit following files
> > > > > > c adb templates from
> > > > > > modules/adb-codegen/src/org/apache/axis2/schema/template/ in
> the
> > > > > > source tree
> > > > > > c adb writer class from
> > > > > >
> modules/adb-codegen/src/org/apache/axis2/schema/writer/CStructWriter.java
> > > > > > in the source tree
> > > > > >
> > > > > > Thanks
> > > > > > Dimuthu
> > > > > >
> > > > > >
> > > > > >
> > > > > > On Wed, Apr 9, 2008 at 8:23 PM, Sérgio Gomes <[EMAIL
> PROTECTED]> wrote:
> > > > > > > Hi there,
> > > > > > >
> > > > > > > Yet another possible code generator issue. There's an
> enumeration in
> > > > > > > the WSDL I'm using:
> > > > > > >
> > > > > > > <simpleType name="DayOfWeek" >
> > > > > > > <restriction base="xsd:string">
> > > > > > > <enumeration value="Monday"/>
> > > > > > > <enumeration value="Tuesday"/>
> > > > > > > <enumeration value="Wednesday"/>
> > > > > > > <enumeration value="Thursday"/>
> > > > > > > <enumeration value="Friday"/>
> > > > > > > <enumeration value="Saturday"/>
> > > > > > > <enumeration value="Sunday"/>
> > > > > > > </restriction>
> > > > > > > </simpleType>
> > > > > > >
> > > > > > > And the setter that gets generated for it is:
> > > > > > >
> > > > > > > axis2_status_t AXIS2_CALL
> > > > > > > adb_DayOfWeek_set_DayOfWeek(
> > > > > > > adb_DayOfWeek_t* _DayOfWeek,
> > > > > > > const axutil_env_t *env,
> > > > > > > const axis2_char_t* arg_DayOfWeek);
> > > > > > >
> > > > > > > The setter is referencing a structure of the same type, so
> how can I
> > > > > > > create, say, a "Monday" object? Shouldn't the setter be
> receiving
> > > > > > > something like an integer instead, which you could get
> from a C enum
> > > > > > > with the several options?
> > > > > > >
> > > > > > > Cheers,
> > > > > > > Sérgio
> > > > > > >
> > > > > > >
> ---------------------------------------------------------------------
> > > > > > > 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]
> > > >
> > > >
> > >
> > > ---------------------------------------------------------------------
> > > 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]
>
>
Index: src/org/apache/axis2/schema/template/CADBBeanTemplateSource.xsl
===================================================================
--- src/org/apache/axis2/schema/template/CADBBeanTemplateSource.xsl (revision 655474)
+++ src/org/apache/axis2/schema/template/CADBBeanTemplateSource.xsl (working copy)
@@ -57,6 +57,14 @@
<xsl:variable name="simple"><xsl:value-of select="@simple"/></xsl:variable>
<xsl:variable name="choice"><xsl:value-of select="@choice"/></xsl:variable>
+ <!-- Check if this type is a supported enum -->
+ <xsl:variable name="isEnum">
+ <xsl:choose>
+ <xsl:when test="count(property)=1 and property/enumFacet and property/@type='axis2_char_t*'">1</xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
/**
* <xsl:value-of select="$axis2_name"/>.c
*
@@ -4582,6 +4590,79 @@
return AXIS2_SUCCESS;
}
+ <xsl:if test="$isEnum=1">
+ <xsl:variable name="enum">adb_<xsl:value-of select="$propertyName"/>_enum_t</xsl:variable>
+ /**
+ * specialized enum getter for <xsl:value-of select="$propertyName"/>.
+ */
+ <xsl:value-of select="$enum"/> AXIS2_CALL
+ <xsl:value-of select="$axis2_name"/>_get_<xsl:value-of select="$CName"/>_enum(
+ <xsl:value-of select="$axis2_name"/>_t* <xsl:value-of select="$name"/>,
+ const axutil_env_t *env)
+ {
+ AXIS2_ENV_CHECK(env, -1);
+ AXIS2_PARAM_CHECK(env->error, <xsl:value-of select="$name"/>, -1);
+
+ <xsl:for-each select="enumFacet">
+ if (axutil_strcmp(<xsl:value-of select="$name"/>->property_<xsl:value-of select="$CName"/>, "<xsl:value-of select="@value"/>") == 0)
+ return <xsl:value-of select="parent::node()/@caps-cname"/>_<xsl:value-of select="@id"/>;
+ </xsl:for-each>
+
+ // Error: none of the strings matched; invalid enum value
+ return -1;
+ }
+
+
+ /**
+ * specialized enum setter for <xsl:value-of select="$propertyName"/>.
+ */
+ axis2_status_t AXIS2_CALL
+ <xsl:value-of select="$axis2_name"/>_set_<xsl:value-of select="$CName"/>_enum(
+ <xsl:value-of select="$axis2_name"/>_t*<xsl:text> </xsl:text><xsl:value-of select="$name"/>,
+ const axutil_env_t *env,
+ <xsl:value-of select="$constValue"/><xsl:value-of select="$enum"/><xsl:text> </xsl:text> arg_<xsl:value-of select="$CName"/>)
+ {
+ <xsl:if test="@isarray">
+ int size = 0;
+ int i = 0;
+ axis2_bool_t non_nil_exists = AXIS2_FALSE;
+ </xsl:if>
+
+ AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
+ AXIS2_PARAM_CHECK(env->error, <xsl:value-of select="$name"/>, AXIS2_FAILURE);
+
+ <!-- first reset whatever already in there -->
+ <xsl:value-of select="$axis2_name"/>_reset_<xsl:value-of select="$CName"/>(<xsl:value-of select="$name"/>, env);
+
+ <xsl:value-of select="$name"/>->property_<xsl:value-of select="$CName"/> = (axis2_char_t *)axutil_strdup(env, (axis2_char_t *)arg_<xsl:value-of select="$CName"/>);
+
+ switch (arg_<xsl:value-of select="$CName"/>)
+ {
+ <xsl:for-each select="enumFacet">
+ case <xsl:value-of select="parent::node()/@caps-cname"/>_<xsl:value-of select="@id"/> :
+ <xsl:value-of select="$name"/>->property_<xsl:value-of select="$CName"/> = (axis2_char_t *)axutil_strdup(env, "<xsl:value-of select="@value"/>");
+ break;
+ </xsl:for-each>
+
+ default:
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error setting <xsl:value-of select="$propertyName"/>: undefined enum value");
+ return AXIS2_FAILURE;
+ }
+
+ if(NULL == <xsl:value-of select="$name"/>->property_<xsl:value-of select="$CName"/>)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error allocating memory for <xsl:value-of select="$propertyName"/>");
+ return AXIS2_FAILURE;
+ }
+ <xsl:value-of select="$name"/>->is_valid_<xsl:value-of select="$CName"/> = AXIS2_TRUE;
+
+ <xsl:if test="$choice">
+ <xsl:value-of select="$name"/>->current_choice = "<xsl:value-of select="@nsuri"/>:<xsl:value-of select="$propertyName"/>";
+ </xsl:if>
+ return AXIS2_SUCCESS;
+ }
+ </xsl:if>
+
<xsl:if test="@isarray">
/**
* Get ith element of <xsl:value-of select="$propertyName"/>.
Index: src/org/apache/axis2/schema/template/CADBBeanTemplateHeader.xsl
===================================================================
--- src/org/apache/axis2/schema/template/CADBBeanTemplateHeader.xsl (revision 655474)
+++ src/org/apache/axis2/schema/template/CADBBeanTemplateHeader.xsl (working copy)
@@ -132,6 +132,26 @@
#define ADB_DEFAULT_LIST_SEPERATOR " "
</xsl:if>
+ <!-- Check if this type is a supported enum -->
+ <xsl:variable name="isEnum">
+ <xsl:choose>
+ <xsl:when test="count(property)=1 and property/enumFacet and property/@type='axis2_char_t*'">1</xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:if test="$isEnum=1">
+ <xsl:variable name="enum">adb_<xsl:value-of select="property/@name"/>_enum_t</xsl:variable>
+ <xsl:variable name="propertyCapsCName" select="property/@caps-cname"/>
+ /* Enumeration for this type */
+ typedef enum {
+ <xsl:for-each select="property/enumFacet">
+ <xsl:text/><xsl:value-of select="$propertyCapsCName"/>_<xsl:value-of select="@id"/>
+ <xsl:if test="position()!=last()">,
+ </xsl:if>
+ </xsl:for-each> } <xsl:value-of select="$enum"/>;
+ </xsl:if>
+
/******************************* Create and Free functions *********************************/
/**
@@ -537,7 +557,49 @@
</xsl:for-each>
+ <xsl:if test="$isEnum=1">
+ <xsl:for-each select="property">
+ <xsl:variable name="propertyName"><xsl:value-of select="@name"></xsl:value-of></xsl:variable>
+ <xsl:variable name="CName"><xsl:value-of select="@cname"></xsl:value-of></xsl:variable>
+ <xsl:variable name="enum">adb_<xsl:value-of select="@name"/>_enum_t</xsl:variable>
+ <xsl:variable name="constValue">
+ <xsl:choose>
+ <xsl:when test="@isarray"></xsl:when>
+ <xsl:when test="@type='axis2_char_t*' or @type='unsigned short' or @type='uint64_t' or @type='unsigned int' or @type='unsigned char' or @type='short' or @type='char' or @type='int' or @type='float' or @type='double' or @type='int64_t'">const </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+
+ /************************** Getters and Setters For Enumerations ********************************/
+ /********************* Enumeration Specific Operations: get_enum, set_enum **********************/
+
+ /**
+ * Enum getter for <xsl:value-of select="$propertyName"/>.
+ * @param <xsl:text> _</xsl:text><xsl:value-of select="$name"/> <xsl:text> </xsl:text><xsl:value-of select="$axis2_name"/>_t object
+ * @param env pointer to environment struct
+ * @return <xsl:value-of select="$enum"/>; -1 on failure
+ */
+ <xsl:value-of select="$enum"/> AXIS2_CALL
+ <xsl:value-of select="$axis2_name"/>_get_<xsl:value-of select="$CName"/>_enum(
+ <xsl:value-of select="$axis2_name"/>_t*<xsl:text> _</xsl:text><xsl:value-of select="$name"/>,
+ const axutil_env_t *env);
+
+ /**
+ * Enum setter for <xsl:value-of select="$propertyName"/>.
+ * @param <xsl:text> _</xsl:text><xsl:value-of select="$name"/> <xsl:text> </xsl:text><xsl:value-of select="$axis2_name"/>_t object
+ * @param env pointer to environment struct
+ * @param arg_<xsl:value-of select="$CName"/><xsl:text> </xsl:text> <xsl:value-of select="$enum"/>
+ * @return AXIS2_SUCCESS on success, else AXIS2_FAILURE
+ */
+ axis2_status_t AXIS2_CALL
+ <xsl:value-of select="$axis2_name"/>_set_<xsl:value-of select="$CName"/>_enum(
+ <xsl:value-of select="$axis2_name"/>_t*<xsl:text> _</xsl:text><xsl:value-of select="$name"/>,
+ const axutil_env_t *env,
+ <xsl:value-of select="$constValue"/><xsl:value-of select="$enum"/><xsl:text> </xsl:text>arg_<xsl:value-of select="$CName"/>);
+
+ </xsl:for-each>
+ </xsl:if>
+
/******************************* Checking and Setting NIL values *********************************/
<xsl:if test="count([EMAIL PROTECTED])!=0">/* Use 'Checking and Setting NIL values for Arrays' to check and set nil for individual elements */</xsl:if>
Index: src/org/apache/axis2/schema/writer/CStructWriter.java
===================================================================
--- src/org/apache/axis2/schema/writer/CStructWriter.java (revision 655493)
+++ src/org/apache/axis2/schema/writer/CStructWriter.java (working copy)
@@ -893,10 +893,12 @@
String attribValue = (String) iterator.next();
XSLTUtils.addAttribute(model, "value", attribValue, enumFacet);
if (validJava) {
- XSLTUtils.addAttribute(model, "id", attribValue, enumFacet);
+ XSLTUtils.addAttribute(model, "id", attribValue.toUpperCase(), enumFacet);
} else {
id++;
- XSLTUtils.addAttribute(model, "id", "value" + id, enumFacet);
+ // Replace all invalid characters and append an id to avoid collisions
+ XSLTUtils.addAttribute(model, "id",
+ attribValue.toUpperCase().replaceAll("[^A-Z0-9]", "_") + "_" + id, enumFacet);
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]