This is an automated email from the ASF dual-hosted git repository. robertlazarski pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/axis-axis2-java-core.git
The following commit(s) were added to refs/heads/master by this push: new 16e832e71e AXIS2-6081 JSON with XML Stream API, support XML attributes in XmlNodeGenerator 16e832e71e is described below commit 16e832e71ef809ddd85de386b43719575d0a7b7c Author: Robert Lazarski <robertlazar...@gmail.com> AuthorDate: Thu Feb 27 05:31:44 2025 -1000 AXIS2-6081 JSON with XML Stream API, support XML attributes in XmlNodeGenerator --- .../axis2/json/factory/XmlNodeGenerator.java | 63 ++++++++++++++++- .../axis2/json/moshi/MoshiXMLStreamReader.java | 79 +++++++++++++++++----- 2 files changed, 123 insertions(+), 19 deletions(-) diff --git a/modules/json/src/org/apache/axis2/json/factory/XmlNodeGenerator.java b/modules/json/src/org/apache/axis2/json/factory/XmlNodeGenerator.java index 7c65d2b7fe..c125e4d01b 100644 --- a/modules/json/src/org/apache/axis2/json/factory/XmlNodeGenerator.java +++ b/modules/json/src/org/apache/axis2/json/factory/XmlNodeGenerator.java @@ -22,7 +22,12 @@ package org.apache.axis2.json.factory; import org.apache.axis2.AxisFault; import org.apache.ws.commons.schema.utils.XmlSchemaRef; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import org.apache.ws.commons.schema.XmlSchema; +import org.apache.ws.commons.schema.XmlSchemaAttribute; +import org.apache.ws.commons.schema.XmlSchemaAttributeOrGroupRef; import org.apache.ws.commons.schema.XmlSchemaComplexType; import org.apache.ws.commons.schema.XmlSchemaElement; import org.apache.ws.commons.schema.XmlSchemaParticle; @@ -32,12 +37,15 @@ import org.apache.ws.commons.schema.XmlSchemaSimpleType; import org.apache.ws.commons.schema.XmlSchemaType; import javax.xml.namespace.QName; +import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Queue; public class XmlNodeGenerator { + private static final Log log = LogFactory.getLog(XmlNodeGenerator.class); + List<XmlSchema> xmlSchemaList; QName elementQname; @@ -45,6 +53,7 @@ public class XmlNodeGenerator { private XmlNode mainXmlNode; Queue<JsonObject> queue = new LinkedList<JsonObject>(); + Queue<JsonObject> attribute_queue = new LinkedList<JsonObject>(); public XmlNodeGenerator(List<XmlSchema> xmlSchemaList, QName elementQname) { this.xmlSchemaList = xmlSchemaList; @@ -84,6 +93,7 @@ public class XmlNodeGenerator { } private void processElement(XmlSchemaElement element, XmlNode parentNode , XmlSchema schema) throws AxisFault { + log.debug("XmlNodeGenerator.processElement() found parentNode node name: " + parentNode.getName() + " , isAttribute: " + parentNode.isAttribute() + " , element name: " + element.getName()); String targetNamespace = schema.getTargetNamespace(); XmlNode xmlNode; QName schemaTypeName = element.getSchemaTypeName(); @@ -147,6 +157,48 @@ public class XmlNodeGenerator { } } } + /* + TODO: attribute support Proof of Concept (POC) by adding currency attribute to: + + samples/quickstartadb/resources/META-INF/StockQuoteService.wsdl: + + <xs:element name="getPrice"> + <xs:complexType> + <xs:sequence> + <xs:element name="symbol" nillable="true" type="xs:string"/> + </xs:sequence> + <xs:attribute name="currency" type="xs:string" use="required"/> + </xs:complexType> + </xs:element> + + resulting in this SOAP Envelope: + + <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Header/><soapenv:Body><ns1:getPrice xmlns:ns1="http://quickstart.samples/xsd" ns1:currency="USD"><ns1:symbol>ABC</ns1:symbol></ns1:getPrice></soapenv:Body></soapenv:Envelope> + + Below, add complexType.getAttributes() code to support this JSON: + + { "getPrice" : {"symbol": "IBM","currency":USD}} + + Possibly using @ as @currency to flag a variable name as as attribute. + + One thing to note is XmlNode has isAttribute() but was never used + */ + if (complexType.getAttributes() != null && complexType.getAttributes().size() > 0) { + log.debug("XmlNodeGenerator.processSchemaType() found attribute size from complexType: " + complexType.getAttributes().size()); + List<XmlSchemaAttributeOrGroupRef> list = complexType.getAttributes(); + for (XmlSchemaAttributeOrGroupRef ref : list) { + XmlSchemaAttribute xsa = (XmlSchemaAttribute)ref; + String name = xsa.getName(); + QName schemaTypeName = xsa.getSchemaTypeName(); + if (schema != null && schema.getTargetNamespace() != null && schemaTypeName != null && schemaTypeName.getLocalPart() != null) { + log.debug("XmlNodeGenerator.processSchemaType() found attribute name from complexType: " + name + " , adding it to parentNode"); + XmlNode xmlNode = new XmlNode(name, schema.getTargetNamespace(), true, false, schemaTypeName.getLocalPart()); + parentNode.addChildToList(xmlNode); + } else { + log.debug("XmlNodeGenerator.processSchemaType() found attribute name from complexType: " + name + " , however could not resolve namespace and localPart"); + } + } + } }else if (xmlSchemaType instanceof XmlSchemaSimpleType) { // nothing to do with simpleType } @@ -163,6 +215,11 @@ public class XmlNodeGenerator { } private void generateQueue(XmlNode node) { + log.debug("XmlNodeGenerator.generateQueue() found node name: " + node.getName() + " , isAttribute: " + node.isAttribute()); + if (node.isAttribute()) { + attribute_queue.add(new JsonObject(node.getName(), JSONType.OBJECT , node.getValueType() , node.getNamespaceUri())); + return; + } if (node.isArray()) { if (node.getChildrenList().size() > 0) { queue.add(new JsonObject(node.getName(), JSONType.NESTED_ARRAY, node.getValueType() , node.getNamespaceUri())); @@ -186,7 +243,6 @@ public class XmlNodeGenerator { } } - public XmlNode getMainXmlNode() throws AxisFault { if (mainXmlNode == null) { try { @@ -203,4 +259,9 @@ public class XmlNodeGenerator { return queue; } + // need to invoke getQueue() before getAttributeQueue() + public Queue<JsonObject> getAttributeQueue() { + return attribute_queue; + } + } diff --git a/modules/json/src/org/apache/axis2/json/moshi/MoshiXMLStreamReader.java b/modules/json/src/org/apache/axis2/json/moshi/MoshiXMLStreamReader.java index 67009026a4..ad5994ea3c 100644 --- a/modules/json/src/org/apache/axis2/json/moshi/MoshiXMLStreamReader.java +++ b/modules/json/src/org/apache/axis2/json/moshi/MoshiXMLStreamReader.java @@ -74,6 +74,10 @@ public class MoshiXMLStreamReader implements XMLStreamReader { private Queue<JsonObject> queue = new LinkedList<JsonObject>(); + private Queue<JsonObject> attribute_queue = new LinkedList<JsonObject>(); + + private List<Attribute> attributes; + private XmlNodeGenerator xmlNodeGenerator; private Stack<JsonObject> stackObj = new Stack<JsonObject>(); @@ -134,6 +138,17 @@ public class MoshiXMLStreamReader implements XMLStreamReader { newNodeMap.put(elementQname, mainXmlNode); configContext.setProperty(JsonConstant.XMLNODES, newNodeMap); } + log.debug("MoshiXMLStreamReader.process() completed on queue size: " + queue.size()); + // XML Elements + for (JsonObject jsonobject : queue) { + log.debug("moshixmlstreamreader.process() found Element to process as jsonobject name: " + jsonobject.getName() + " , type: " + jsonobject.getType()); + } + + // XML attributes + attribute_queue = xmlNodeGenerator.getAttributeQueue(); + for (JsonObject jsonobject : attribute_queue) { + log.debug("moshixmlstreamreader.process() found Attribute to process as jsonobject name: " + jsonobject.getName() + " , type: " + jsonobject.getType()); + } isProcessed = true; log.debug("MoshiXMLStreamReader.process() completed"); } @@ -231,12 +246,9 @@ public class MoshiXMLStreamReader implements XMLStreamReader { } - public String getAttributeValue(String namespaceURI, String localName) { - throw new UnsupportedOperationException("Method is not implemented"); - } - - public int getAttributeCount() { + // TODO populate the List of the class Attributes here by readName() + // and using the attribute_queue instead of queue if attribute_queue not empty if (isStartElement()) { return 0; // don't support attributes on tags in JSON convention } else { @@ -245,38 +257,60 @@ public class MoshiXMLStreamReader implements XMLStreamReader { } - public QName getAttributeName(int index) { - throw new UnsupportedOperationException("Method is not implemented"); + public String getAttributeLocalName(int index) { + if ((null == attributes) || (index >= attributes.size())) { + throw new IndexOutOfBoundsException(); + } + return attributes.get(index).name.getLocalPart(); } - public String getAttributeNamespace(int index) { - throw new UnsupportedOperationException("Method is not implemented"); + public QName getAttributeName(int index) { + return attributes.get(index).name; } - public String getAttributeLocalName(int index) { - throw new UnsupportedOperationException("Method is not implemented"); + public String getAttributePrefix(int index) { + if ((null == attributes) || (index >= attributes.size())) { + throw new IndexOutOfBoundsException(); + } + return null; } - public String getAttributePrefix(int index) { - throw new UnsupportedOperationException("Method is not implemented"); + public String getAttributeType(int index) { + return null; } - public String getAttributeType(int index) { - throw new UnsupportedOperationException("Method is not implemented"); + public String getAttributeNamespace(int index) { + return null; } public String getAttributeValue(int index) { - throw new UnsupportedOperationException("Method is not implemented"); + if ((null == attributes) || (index >= attributes.size())) { + throw new IndexOutOfBoundsException(); + } + return attributes.get(index).value; + } + + + public String getAttributeValue(String namespaceURI, String localName) { + if ((null == attributes) || (null == localName) || ("".equals(localName))) { + throw new NoSuchElementException(); + } + for (Attribute a : attributes) { + if (localName.equals(a.name.getLocalPart())) { + return a.value; + } + } + throw new NoSuchElementException(); } public boolean isAttributeSpecified(int index) { - throw new UnsupportedOperationException("Method is not implemented"); + return (null != attributes) && (attributes.size() >= index); } @@ -542,7 +576,6 @@ public class MoshiXMLStreamReader implements XMLStreamReader { localName = ""; } } else { - System.out.println("stackObj is empty"); throw new XMLStreamException("Error while processing input JSON stream, JSON request may not valid ," + " it may has more end object characters "); } @@ -736,4 +769,14 @@ public class MoshiXMLStreamReader implements XMLStreamReader { EndObjectBeginObject_START, EndObjectEndDocument, } + + private static class Attribute { + private final QName name; + private final String value; + + Attribute(QName name, String value) { + this.name = name; + this.value = value; + } + } }