From 0ff70b6bc99733271ba556d53515d176e08a13bd Mon Sep 17 00:00:00 2001 From: Andrii Nikitiuk Date: Tue, 9 Dec 2014 20:38:32 +0200 Subject: [PATCH] (CXF-6148) Added support for basic xsd:choice elements for JS generator. Covered with tests and improved tests. Added log message when not supported exception is raisen. --- .../cxf/javascript/JavascriptUtils.java | 12 ++++- .../apache/cxf/javascript/Messages.properties | 3 ++ .../apache/cxf/javascript/ParticleInfo.java | 48 ++++++++++++++++++- .../types/SchemaJavascriptBuilder.java | 28 +++++++++-- .../javascript/WSDLToJavaScriptTest.java | 18 ++++++- .../tools/wsdlto/javascript/hello_world.wsdl | 44 +++++++++++++++++ 6 files changed, 144 insertions(+), 9 deletions(-) diff --git a/rt/javascript/javascript-rt/src/main/java/org/apache/cxf/javascript/JavascriptUtils.java b/rt/javascript/javascript-rt/src/main/java/org/apache/cxf/javascript/JavascriptUtils.java index a1c4ad9f108..253e586b742 100755 --- a/rt/javascript/javascript-rt/src/main/java/org/apache/cxf/javascript/JavascriptUtils.java +++ b/rt/javascript/javascript-rt/src/main/java/org/apache/cxf/javascript/JavascriptUtils.java @@ -338,6 +338,13 @@ public static boolean mtomCandidateType(XmlSchemaType type) { public void generateCodeToSerializeElement(ParticleInfo elementInfo, String referencePrefix, SchemaCollection schemaCollection) { + if (elementInfo.isGroup()) { + for (ParticleInfo childElement : elementInfo.getChildren()) { + generateCodeToSerializeElement(childElement, referencePrefix, schemaCollection); + } + return; + } + XmlSchemaType type = elementInfo.getType(); boolean nillable = elementInfo.isNillable(); boolean optional = elementInfo.isOptional(); @@ -563,9 +570,10 @@ public static XmlSchemaParticle getObjectParticle(XmlSchemaObject object, QName contextName, object); } if (!(object instanceof XmlSchemaElement) - && !(object instanceof XmlSchemaAny)) { + && !(object instanceof XmlSchemaAny) + && !(object instanceof XmlSchemaChoice)) { unsupportedConstruct("GROUP_CHILD", - object.getClass().getSimpleName(), contextName, + object.getClass().getSimpleName(), contextName, object); } diff --git a/rt/javascript/javascript-rt/src/main/java/org/apache/cxf/javascript/Messages.properties b/rt/javascript/javascript-rt/src/main/java/org/apache/cxf/javascript/Messages.properties index 1c08adc5be4..120335ff13e 100644 --- a/rt/javascript/javascript-rt/src/main/java/org/apache/cxf/javascript/Messages.properties +++ b/rt/javascript/javascript-rt/src/main/java/org/apache/cxf/javascript/Messages.properties @@ -25,3 +25,6 @@ IMPOSSIBLE_GLOBAL_ITEM= JavaScript limitation: Element or xs:any at {0} used in MISSING_TYPE=Type {0} is missing from the WSDL schema for element {1}. {2} ELEMENT_DANGLING_REFERENCE= Element {0} refers to undefined element {1}. UNSUPPORTED_ATTRIBUTE_ITEM= Unsupported {0} in {1}. +GROUP_ELEMENT_MULTI_OCCURS=Limitation: unsupported group element construct {0} with maxOccours > 1 found. +GROUP_ELEMENT_ANY=Limitation: unsupported any element inside group element construct {0} +GROUP_CHILD=Limitation: unsupported construct {0} found in {1}. {2} diff --git a/rt/javascript/javascript-rt/src/main/java/org/apache/cxf/javascript/ParticleInfo.java b/rt/javascript/javascript-rt/src/main/java/org/apache/cxf/javascript/ParticleInfo.java index c8631bdc1b8..445cf96490c 100644 --- a/rt/javascript/javascript-rt/src/main/java/org/apache/cxf/javascript/ParticleInfo.java +++ b/rt/javascript/javascript-rt/src/main/java/org/apache/cxf/javascript/ParticleInfo.java @@ -19,6 +19,8 @@ package org.apache.cxf.javascript; +import java.util.List; +import java.util.LinkedList; import java.util.logging.Logger; import javax.xml.namespace.QName; @@ -29,6 +31,8 @@ import org.apache.cxf.common.xmlschema.XmlSchemaUtils; import org.apache.ws.commons.schema.XmlSchema; import org.apache.ws.commons.schema.XmlSchemaElement; +import org.apache.ws.commons.schema.XmlSchemaChoice; +import org.apache.ws.commons.schema.XmlSchemaChoiceMember; import org.apache.ws.commons.schema.XmlSchemaObject; import org.apache.ws.commons.schema.XmlSchemaParticle; import org.apache.ws.commons.schema.XmlSchemaType; @@ -47,6 +51,10 @@ public final class ParticleInfo implements ItemInfo { // in the RPC case, we can have a type and no element. private XmlSchemaType type; private boolean empty; + + private boolean isGroup; + private List children; + // These are exactly the same values as we find in the XmlSchemaElement. // there is no rationalization. But the accessors take care of business. private long minOccurs; @@ -149,6 +157,32 @@ public static ParticleInfo forLocalItem(XmlSchemaObject sequenceObject, XmlSchem elementInfo.global = true; } elementInfo.nillable = ((XmlSchemaElement)realParticle).isNillable(); + } else if (sequenceParticle instanceof XmlSchemaChoice) { + XmlSchemaChoice choice = (XmlSchemaChoice)sequenceParticle; + + if (sequenceParticle.getMaxOccurs() > 1) { + Message message = new Message("GROUP_ELEMENT_MULTI_OCCURS", LOG, sequenceParticle + .getClass().getSimpleName()); + throw new UnsupportedConstruct(message.toString()); + } + + elementInfo.children = new LinkedList<>(); + + List items = choice.getItems(); + for (XmlSchemaChoiceMember item : items) { + XmlSchemaObject schemaObject = (XmlSchemaObject)item; + ParticleInfo childParticle = ParticleInfo.forLocalItem(schemaObject, currentSchema, schemaCollection, + prefixAccumulator, contextName); + + if (childParticle.isAny()) { + Message message = new Message("GROUP_ELEMENT_ANY", LOG, sequenceParticle.getClass() + .getSimpleName()); + throw new UnsupportedConstruct(message.toString()); + } + + childParticle.minOccurs = 0; + elementInfo.children.add(childParticle); + } } elementInfo.minOccurs = sequenceParticle.getMinOccurs(); @@ -199,13 +233,17 @@ private static void factoryCommon(XmlSchemaParticle particle, XmlSchema currentS elementInfo.defaultValue = schemaDefaultValue; factorySetupType(element, schemaCollection, elementInfo); + + elementInfo.isGroup = false; + } else if (particle instanceof XmlSchemaChoice) { + elementInfo.isGroup = true; } else { // any elementInfo.any = true; elementInfo.xmlName = null; // unknown until runtime. // TODO: multiple 'any' elementInfo.javascriptName = "any"; elementInfo.type = null; // runtime for any. - + elementInfo.isGroup = false; } } @@ -325,6 +363,14 @@ public void setType(XmlSchemaType type) { this.type = type; } + public boolean isGroup() { + return isGroup; + } + + public List getChildren() { + return children; + } + public boolean isEmpty() { return empty; } diff --git a/rt/javascript/javascript-rt/src/main/java/org/apache/cxf/javascript/types/SchemaJavascriptBuilder.java b/rt/javascript/javascript-rt/src/main/java/org/apache/cxf/javascript/types/SchemaJavascriptBuilder.java index 403766a42be..3292672da20 100755 --- a/rt/javascript/javascript-rt/src/main/java/org/apache/cxf/javascript/types/SchemaJavascriptBuilder.java +++ b/rt/javascript/javascript-rt/src/main/java/org/apache/cxf/javascript/types/SchemaJavascriptBuilder.java @@ -156,6 +156,7 @@ public String generateCodeForSchema(XmlSchema schema) { domDeserializerFunction(element.getQName(), complexType); } } catch (UnsupportedConstruct usc) { + LOG.warning(usc.getMessage()); continue; // it could be empty, but the style checker // would complain. } @@ -189,7 +190,7 @@ public void complexTypeConstructorAndAccessors(QName name, XmlSchemaComplexType for (XmlSchemaObject thing : items) { ParticleInfo itemInfo = ParticleInfo.forLocalItem(thing, xmlSchema, xmlSchemaCollection, prefixAccumulator, type.getQName()); - constructOneItem(type, elementPrefix, typeObjectName, itemInfo); + constructItem(type, elementPrefix, typeObjectName, itemInfo); } for (XmlSchemaAnnotated thing : attrs) { @@ -202,6 +203,18 @@ public void complexTypeConstructorAndAccessors(QName name, XmlSchemaComplexType code.append(accessors.toString()); } + private void constructItem(XmlSchemaComplexType type, final String elementPrefix, + String typeObjectName, ParticleInfo itemInfo) { + if (!itemInfo.isGroup()) { + constructOneItem(type, elementPrefix, typeObjectName, itemInfo); + return; + } + + for (ParticleInfo childInfo : itemInfo.getChildren()) { + constructItem(type, elementPrefix, typeObjectName, childInfo); + } + } + private void constructOneItem(XmlSchemaComplexType type, final String elementPrefix, String typeObjectName, ItemInfo itemInfo) { @@ -396,7 +409,7 @@ public void domDeserializerFunction(QName name, XmlSchemaComplexType type) { } deserializeAny(type, itemInfo, nextItem); } else { - deserializeElement(type, contentElement); + deserializeElement(type, itemInfo); } } utils.appendLine("return newobject;"); @@ -528,9 +541,14 @@ private void deserializeAny(XmlSchemaComplexType type, ParticleInfo itemInfo, Pa utils.appendLine("newobject.setAny(anyHolder);"); } - private void deserializeElement(XmlSchemaComplexType type, XmlSchemaObject thing) { - ParticleInfo itemInfo = ParticleInfo.forLocalItem(thing, xmlSchema, xmlSchemaCollection, - prefixAccumulator, type.getQName()); + private void deserializeElement(XmlSchemaComplexType type, ParticleInfo itemInfo) { + if (itemInfo.isGroup()) { + for (ParticleInfo childElement : itemInfo.getChildren()) { + deserializeElement(type, childElement); + } + return; + } + XmlSchemaType itemType = itemInfo.getType(); boolean simple = itemType instanceof XmlSchemaSimpleType || JavascriptUtils.notVeryComplexType(itemType); diff --git a/tools/wsdlto/frontend/javascript/src/test/java/org/apache/cxf/tools/wsdlto/javascript/WSDLToJavaScriptTest.java b/tools/wsdlto/frontend/javascript/src/test/java/org/apache/cxf/tools/wsdlto/javascript/WSDLToJavaScriptTest.java index 15af8697b08..872661cc5f3 100644 --- a/tools/wsdlto/frontend/javascript/src/test/java/org/apache/cxf/tools/wsdlto/javascript/WSDLToJavaScriptTest.java +++ b/tools/wsdlto/frontend/javascript/src/test/java/org/apache/cxf/tools/wsdlto/javascript/WSDLToJavaScriptTest.java @@ -32,7 +32,17 @@ * */ public class WSDLToJavaScriptTest extends ProcessorTestBase { - + + public int countChar(String text, char symbol) { + int count = 0; + for (int i = 0; i < text.length(); i++) { + if (text.charAt(i) == symbol) { + count++; + } + } + return count; + } + // just run with a minimum of fuss. @Test public void testGeneration() throws Exception { @@ -52,6 +62,9 @@ public void testGeneration() throws Exception { FileInputStream fis = new FileInputStream(resultFile); String javascript = IOUtils.readStringFromStream(fis); assertTrue(javascript.contains("xmlns:murble='http://apache.org/hello_world_soap_http'")); + assertEquals("Number of '{' does not match number of '}' in generated JavaScript.", + countChar(javascript, '{'), + countChar(javascript, '}')); } @Test @@ -72,6 +85,9 @@ public void testCXF3891() throws Exception { FileInputStream fis = new FileInputStream(resultFile); String javascript = IOUtils.readStringFromStream(fis); assertTrue(javascript.contains("xmlns:murble='http://apache.org/hello_world_soap_http'")); + assertEquals("Number of '{' does not match number of '}' in generated JavaScript.", + countChar(javascript, '{'), + countChar(javascript, '}')); } } diff --git a/tools/wsdlto/frontend/javascript/src/test/resources/org/apache/cxf/tools/wsdlto/javascript/hello_world.wsdl b/tools/wsdlto/frontend/javascript/src/test/resources/org/apache/cxf/tools/wsdlto/javascript/hello_world.wsdl index 0378931dc8b..35c6baf2f17 100644 --- a/tools/wsdlto/frontend/javascript/src/test/resources/org/apache/cxf/tools/wsdlto/javascript/hello_world.wsdl +++ b/tools/wsdlto/frontend/javascript/src/test/resources/org/apache/cxf/tools/wsdlto/javascript/hello_world.wsdl @@ -154,6 +154,30 @@ under the License. + + + + + + + + + + + + + + + + + + + + + + + + @@ -207,6 +231,13 @@ under the License. + + + + + + + @@ -237,6 +268,10 @@ under the License. + + + + @@ -312,6 +347,15 @@ under the License. + + + + + + + + +