Browse Source

HPCC-22357 ESDL WSDL scapps compatibility

Change ESDL generated WSDLs to more closely match those generated by scapps.
This aids in our migration of scapps services to DESDL.

 - Output xml declaration
 - Set root of soapAction to service name
 - When explicitly requesting XSD or WSDL, turn off annotations that are used
   only for rendering web form. Per-transaction custom XSL transform parameter
   values can override the default values set in the EsdlDefinitionHelper.
 - Remove unused string element

Signed-off-by: Terrence Asselin <terrence.asselin@lexisnexisrisk.com>
Terrence Asselin 4 years ago
parent
commit
79ea353aab

+ 34 - 0
esp/esdllib/esdl_def.cpp

@@ -1689,6 +1689,40 @@ void EsdlDefinition::walkDefinitionDepthFirst( AddedObjs& foundByName, EsdlDefOb
     const char* name = esdlObj->queryName();
     IMapping* found = foundByName.find( name );
 
+    // The found object may be an ESPstruct that is used as an array element
+    // in two ways- first with an Item Tag (ItemName) like so:
+    //
+    //    ESParray<ESPstruct ItemStruct, ItemName> BreaksIfFirst;
+    //
+    // Then second without an Item Tag, like so:
+    //
+    //    ESParray<ESPstruct ItemStruct> Works;
+    //
+    // When the Item Tag instance is added to the dependencies first, the
+    // second instance never triggers the setting of the DEPFLAG_ARRAYOF
+    // so the WSDL will be missing the ArrayOfItemStruct element defn
+    //
+    // Reduce the iteration of this array as much as possible by limiting it
+    // to just the situations we need to update the wrapper flag.
+    //
+    //    - 'state' indicates if the ecm definition requires an ArrayOf
+    //      entry based on the shouldGenerateArrayOf() return value
+    //    - 'flags' parameter indicates if the caller wants ArrayOf
+    //      entries generated
+    //    - Finally, only EsdlTypeStruct objects used as array items need
+    //      ArrayOf element definitions.
+    if (found && (state & DEPFLAG_ARRAYOF) && (flags & DEPFLAG_ARRAYOF) && EsdlTypeStruct == esdlType)
+    {
+        ForEachItemIn(i, dependencies)
+        {
+            EsdlDefObjectWrapper* wrapper=dependencies[i];
+            if (strcmp(wrapper->queryObject().queryName(), name) == 0)
+            {
+                wrapper->setFlag(DEPFLAG_ARRAYOF);
+            }
+        }
+    }
+
     // If the current esdlObject has already been added to the list of dependencies,
     // then just exit now - there is no need to traverse it's children or it's
     // ancestors- they've already been added.

+ 35 - 14
esp/esdllib/esdl_def_helper.cpp

@@ -69,12 +69,12 @@ public:
 
     virtual void toXML( IEsdlDefObjectIterator &objs, StringBuffer &xml, double version, IProperties *opts, unsigned requestedFlags=0 );
 
-    virtual void toXSD( IEsdlDefObjectIterator &objs, StringBuffer &xsd, EsdlXslTypeId xslId, double version, IProperties *opts, const char *ns=NULL, unsigned flags=0 );
-    virtual void toXSD( IEsdlDefObjectIterator &objs, StringBuffer &xsd, StringBuffer &xslt, double version, IProperties *opts, const char *ns=NULL, unsigned flags=0 );
-    virtual void toWSDL( IEsdlDefObjectIterator &objs, StringBuffer &xsd, EsdlXslTypeId xslId, double version, IProperties *opts, const char *ns=NULL, unsigned flags=0 );
-    virtual void toMicroService( IEsdlDefObjectIterator& objs, StringBuffer &content, EsdlXslTypeId classType, IProperties *opts, unsigned flags);
+    virtual void toXSD( IEsdlDefObjectIterator &objs, StringBuffer &xsd, EsdlXslTypeId xslId, double version, IProperties *opts, const char *ns=NULL, unsigned flags=0, IProperties* overrideParams=nullptr );
+    virtual void toXSD( IEsdlDefObjectIterator &objs, StringBuffer &xsd, StringBuffer &xslt, double version, IProperties *opts, const char *ns=NULL, unsigned flags=0, IProperties* overrideParams=nullptr );
+    virtual void toWSDL( IEsdlDefObjectIterator &objs, StringBuffer &xsd, EsdlXslTypeId xslId, double version, IProperties *opts, const char *ns=NULL, unsigned flags=0, IProperties* overrideParams=nullptr );
+    virtual void toMicroService( IEsdlDefObjectIterator& objs, StringBuffer &content, EsdlXslTypeId classType, IProperties *opts, unsigned flags, IProperties* overrideParams=nullptr);
 
-    void loadTransformParams( EsdlXslTypeId xslId );
+    void loadTransformParams( EsdlXslTypeId xslId, IProperties* overrideParams=nullptr );
 
 
 };
@@ -238,13 +238,13 @@ void EsdlDefinitionHelper::toXML( IEsdlDefObjectIterator& objs, StringBuffer &xm
     return;
 }
 
-void EsdlDefinitionHelper::toXSD( IEsdlDefObjectIterator &objs, StringBuffer &xsd, EsdlXslTypeId xslId, double version, IProperties *opts, const char *ns, unsigned flags)
+void EsdlDefinitionHelper::toXSD( IEsdlDefObjectIterator &objs, StringBuffer &xsd, EsdlXslTypeId xslId, double version, IProperties *opts, const char *ns, unsigned flags, IProperties* overrideParams)
 {
     StringBuffer xml;
     int xmlLen = 0;
     IXslTransform* trans = *( transforms.getValue( xslId ) );
 
-    this->loadTransformParams( xslId );
+    this->loadTransformParams( xslId, overrideParams );
 
     if( trans )
     {
@@ -271,13 +271,13 @@ void EsdlDefinitionHelper::toXSD( IEsdlDefObjectIterator &objs, StringBuffer &xs
     return;
 }
 
-void EsdlDefinitionHelper::toWSDL( IEsdlDefObjectIterator &objs, StringBuffer &xsd, EsdlXslTypeId xslId, double version, IProperties *opts, const char *ns, unsigned flags)
+void EsdlDefinitionHelper::toWSDL( IEsdlDefObjectIterator &objs, StringBuffer &xsd, EsdlXslTypeId xslId, double version, IProperties *opts, const char *ns, unsigned flags, IProperties* overrideParams )
 {
     StringBuffer xml;
     int xmlLen = 0;
     IXslTransform* trans = *( transforms.getValue( xslId ) );
 
-    this->loadTransformParams( xslId );
+    this->loadTransformParams( xslId, overrideParams );
 
     if( trans )
     {
@@ -300,12 +300,12 @@ void EsdlDefinitionHelper::toWSDL( IEsdlDefObjectIterator &objs, StringBuffer &x
 }
 
 
-void EsdlDefinitionHelper::toXSD( IEsdlDefObjectIterator& objs, StringBuffer &xml, StringBuffer &xslt, double version, IProperties *opts, const char *ns, unsigned flags)
+void EsdlDefinitionHelper::toXSD( IEsdlDefObjectIterator& objs, StringBuffer &xml, StringBuffer &xslt, double version, IProperties *opts, const char *ns, unsigned flags, IProperties* overrideParams )
 {
     return;
 }
 
-void EsdlDefinitionHelper::loadTransformParams( EsdlXslTypeId xslId)
+void EsdlDefinitionHelper::loadTransformParams( EsdlXslTypeId xslId, IProperties* overrideParams )
 {
     IXslTransform* trans = *( transforms.getValue(xslId) );
     IProperties* params = *( parameters.getValue(xslId) );
@@ -315,6 +315,13 @@ void EsdlDefinitionHelper::loadTransformParams( EsdlXslTypeId xslId)
         throw (MakeStringException( 0, "Unable to find transform for EsdlXslTypeId=%d", xslId ));
     }
 
+    // All setParameter() calls are bare- no implicit quoting-
+    // allowing us to set values as expressions. Previously
+    // they were quoted which lead to some subtle bugs in the
+    // transforms assuming that string values were bool, when
+    // it wasn't in fact even possible to set a bool value.
+
+    // Set (default) params associated with the transform in the helper
     if( params )
     {
         Owned<IPropertyIterator> it = params->getIterator();
@@ -323,18 +330,32 @@ void EsdlDefinitionHelper::loadTransformParams( EsdlXslTypeId xslId)
             const char *key = it->getPropKey();
             //set parameter in the XSL transform skipping over the @ prefix, if any
             const char* paramName = *key == '@' ? key+1 : key;
-            trans->setParameter(paramName, StringBuffer().append('\'').append(params->queryProp(key)).append('\'').str());
+            trans->setParameter(paramName, params->queryProp(key));
+        }
+    }
+
+    // Set overrides if any. Could be new params or just new values for
+    // params set above.
+    if( overrideParams )
+    {
+        Owned<IPropertyIterator> it = overrideParams->getIterator();
+        for (it->first(); it->isValid(); it->next())
+        {
+            const char *key = it->getPropKey();
+            //set parameter in the XSL transform skipping over the @ prefix, if any
+            const char* paramName = *key == '@' ? key+1 : key;
+            trans->setParameter(paramName, overrideParams->queryProp(key));
         }
     }
 }
 
-void EsdlDefinitionHelper::toMicroService( IEsdlDefObjectIterator& objs, StringBuffer &content, EsdlXslTypeId implType, IProperties *opts, unsigned flags)
+void EsdlDefinitionHelper::toMicroService( IEsdlDefObjectIterator& objs, StringBuffer &content, EsdlXslTypeId implType, IProperties *opts, unsigned flags, IProperties* overrideParams )
 {
     StringBuffer xml;
     int xmlLen = 0;
     IXslTransform* trans = *( transforms.getValue( implType ) );
 
-    this->loadTransformParams( implType );
+    this->loadTransformParams( implType, overrideParams );
 
     if( trans )
     {

+ 4 - 4
esp/esdllib/esdl_def_helper.hpp

@@ -47,10 +47,10 @@ interface IEsdlDefinitionHelper : extends IInterface
     virtual void setTransformParams( EsdlXslTypeId xslId, IProperties *params )=0;
 
     virtual void toXML( IEsdlDefObjectIterator& objs, StringBuffer &xml, double version=0, IProperties *opts=NULL, unsigned flags=0 )=0;
-    virtual void toXSD( IEsdlDefObjectIterator& objs, StringBuffer &xsd, EsdlXslTypeId xslId, double version=0, IProperties *opts=NULL, const char *ns=NULL, unsigned flags=0 )=0;
-    virtual void toXSD( IEsdlDefObjectIterator& objs, StringBuffer &xsd, StringBuffer& xslt, double version=0, IProperties *opts=NULL, const char *ns=NULL, unsigned flags=0 )=0;
-    virtual void toWSDL( IEsdlDefObjectIterator& objs, StringBuffer &wsdl, EsdlXslTypeId xslId, double version=0, IProperties *opts=NULL, const char *ns=NULL, unsigned flags=0 )=0;
-    virtual void toMicroService( IEsdlDefObjectIterator& objs, StringBuffer &content, EsdlXslTypeId implType, IProperties *opts=NULL, unsigned flags=0 )=0;
+    virtual void toXSD( IEsdlDefObjectIterator& objs, StringBuffer &xsd, EsdlXslTypeId xslId, double version=0, IProperties *opts=NULL, const char *ns=NULL, unsigned flags=0, IProperties* overrideParams=nullptr )=0;
+    virtual void toXSD( IEsdlDefObjectIterator& objs, StringBuffer &xsd, StringBuffer& xslt, double version=0, IProperties *opts=NULL, const char *ns=NULL, unsigned flags=0, IProperties* overrideParams=nullptr )=0;
+    virtual void toWSDL( IEsdlDefObjectIterator& objs, StringBuffer &wsdl, EsdlXslTypeId xslId, double version=0, IProperties *opts=NULL, const char *ns=NULL, unsigned flags=0, IProperties* overrideParams=nullptr )=0;
+    virtual void toMicroService( IEsdlDefObjectIterator& objs, StringBuffer &content, EsdlXslTypeId implType, IProperties *opts=NULL, unsigned flags=0, IProperties* overrideParams=nullptr )=0;
 };
 
 esdl_decl void removeEclHidden(IPropertyTree *depTree, bool cloneGetDataFrom);

+ 12 - 5
esp/services/esdl_svc_engine/esdl_binding.cpp

@@ -1958,14 +1958,17 @@ void EsdlBindingImpl::initEsdlServiceInfo(IEsdlDefService &srvdef)
     //superclass binding sets up wsdladdress
     //setWsdlAddress(bndcfg->queryProp("@wsdlServiceAddress"));
 
+    // XSL Parameters are added as expressions, so any string
+    // values must be quoted when setting the property value
+
     IProperties *xsdparams = createProperties(false);
-    xsdparams->setProp( "all_annot_Param", 1 );
+    xsdparams->setProp( "all_annot_Param", "true()" );
     m_xsdgen->setTransformParams(EsdlXslToXsd, xsdparams);
 
     IProperties *wsdlparams = createProperties(false);
-    wsdlparams->setProp( "location", getWsdlAddress());
+    wsdlparams->setProp( "location", StringBuffer().append('\'').append(getWsdlAddress()).append('\'').str() );
     wsdlparams->setProp( "create_wsdl", "true()");
-    wsdlparams->setProp( "all_annot_Param", 1 );
+    wsdlparams->setProp( "all_annot_Param", "true()" );
     m_xsdgen->setTransformParams(EsdlXslToWsdl, wsdlparams);
 
     StringBuffer xsltpath(getCFD());
@@ -2644,6 +2647,8 @@ int EsdlBindingImpl::onGetXsd(IEspContext &context,
     if (!serviceName || !*serviceName)
         serviceName = m_espServiceName.get();
 
+    context.queryXslParameters()->setProp("all_annot_Param", "false()");
+
     if (!getSchema(out, context, request, serviceName, methodName, false))
     {
         response->setStatus(HTTP_STATUS_INTERNAL_SERVER_ERROR);
@@ -2686,7 +2691,9 @@ int EsdlBindingImpl::onGetWsdl(IEspContext &context,
         try
         {
             Owned<IEsdlDefObjectIterator> it = m_esdl->getDependencies(serviceName, methodName, context.getClientVersion(), context.queryRequestParameters(), ESDLDEP_FLAGS);
-            m_xsdgen->toWSDL( *it, out, EsdlXslToWsdl, context.getClientVersion(), context.queryRequestParameters(), ns.str(), ESDLDEP_FLAGS);
+            IProperties* overrideParams = context.queryXslParameters();
+            overrideParams->setProp("all_annot_Param", "false()");
+            m_xsdgen->toWSDL( *it, out, EsdlXslToWsdl, context.getClientVersion(), context.queryRequestParameters(), ns.str(), ESDLDEP_FLAGS, overrideParams);
         }
         catch (...)
         {
@@ -2719,7 +2726,7 @@ bool EsdlBindingImpl::getSchema(StringBuffer& schema,
     generateNamespace(ctx, req, service, method, ns);
 
     Owned<IEsdlDefObjectIterator> it = m_esdl->getDependencies(service, method, ctx.getClientVersion(), ctx.queryRequestParameters(), ESDLDEP_FLAGS);
-    m_xsdgen->toXSD( *it, schema, EsdlXslToXsd, ctx.getClientVersion(), ctx.queryRequestParameters(), ns.str(), ESDLDEP_FLAGS);
+    m_xsdgen->toXSD( *it, schema, EsdlXslToXsd, ctx.getClientVersion(), ctx.queryRequestParameters(), ns.str(), ESDLDEP_FLAGS, ctx.queryXslParameters());
     ESPLOG(LogMax,"EsdlBindingImpl::getSchema schema: %s", schema.str());
     return true;
 }

+ 3 - 2
esp/xslt/esxdl2xsd.xslt

@@ -18,7 +18,7 @@
 -->
 
 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
-    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="yes"/>
+    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
     <xsl:param name="create_wsdl" select="false()"/>
     <xsl:param name="location" select="'http://localhost:8000/WsService?ver_=0'"/>
     <xsl:param name="tnsParam" select="/esxdl/@ns_uri"/>
@@ -388,6 +388,7 @@
             </xsl:for-each>
         </wsdl:portType>
         <wsdl:binding>
+            <xsl:variable name="serviceName" select="@name"/>
             <xsl:attribute name="name"><xsl:value-of select="@name"/>ServiceSoap</xsl:attribute>
             <xsl:attribute name="type">tns:<xsl:value-of select="@name"/>ServiceSoap</xsl:attribute>
             <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
@@ -395,7 +396,7 @@
                 <wsdl:operation>
                     <xsl:attribute name="name"><xsl:value-of select="@name"/></xsl:attribute>
                     <soap:operation style="document">
-                        <xsl:attribute name="soapAction"><xsl:value-of select="../@name"/>/<xsl:value-of select="@name"/>?ver_=<xsl:value-of select="$version"/></xsl:attribute>
+                        <xsl:attribute name="soapAction"><xsl:value-of select="$serviceName"/>/<xsl:value-of select="@name"/>?ver_=<xsl:value-of select="$version"/></xsl:attribute>
                     </soap:operation>
                     <wsdl:input>
                         <soap:body use="literal"/>