Skip to content

Commit 16e832e

Browse files
AXIS2-6081 JSON with XML Stream API, support XML attributes in XmlNodeGenerator
1 parent 176de35 commit 16e832e

File tree

2 files changed

+123
-19
lines changed

2 files changed

+123
-19
lines changed

modules/json/src/org/apache/axis2/json/factory/XmlNodeGenerator.java

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,12 @@
2222
import org.apache.axis2.AxisFault;
2323
import org.apache.ws.commons.schema.utils.XmlSchemaRef;
2424

25+
import org.apache.commons.logging.Log;
26+
import org.apache.commons.logging.LogFactory;
27+
2528
import org.apache.ws.commons.schema.XmlSchema;
29+
import org.apache.ws.commons.schema.XmlSchemaAttribute;
30+
import org.apache.ws.commons.schema.XmlSchemaAttributeOrGroupRef;
2631
import org.apache.ws.commons.schema.XmlSchemaComplexType;
2732
import org.apache.ws.commons.schema.XmlSchemaElement;
2833
import org.apache.ws.commons.schema.XmlSchemaParticle;
@@ -32,19 +37,23 @@
3237
import org.apache.ws.commons.schema.XmlSchemaType;
3338

3439
import javax.xml.namespace.QName;
40+
import java.util.ArrayList;
3541
import java.util.LinkedList;
3642
import java.util.List;
3743
import java.util.Queue;
3844

3945
public class XmlNodeGenerator {
4046

47+
private static final Log log = LogFactory.getLog(XmlNodeGenerator.class);
48+
4149
List<XmlSchema> xmlSchemaList;
4250

4351
QName elementQname;
4452

4553
private XmlNode mainXmlNode;
4654

4755
Queue<JsonObject> queue = new LinkedList<JsonObject>();
56+
Queue<JsonObject> attribute_queue = new LinkedList<JsonObject>();
4857

4958
public XmlNodeGenerator(List<XmlSchema> xmlSchemaList, QName elementQname) {
5059
this.xmlSchemaList = xmlSchemaList;
@@ -84,6 +93,7 @@ private void processSchemaList() throws AxisFault {
8493
}
8594

8695
private void processElement(XmlSchemaElement element, XmlNode parentNode , XmlSchema schema) throws AxisFault {
96+
log.debug("XmlNodeGenerator.processElement() found parentNode node name: " + parentNode.getName() + " , isAttribute: " + parentNode.isAttribute() + " , element name: " + element.getName());
8797
String targetNamespace = schema.getTargetNamespace();
8898
XmlNode xmlNode;
8999
QName schemaTypeName = element.getSchemaTypeName();
@@ -147,6 +157,48 @@ private void processSchemaType(XmlSchemaType xmlSchemaType , XmlNode parentNode
147157
}
148158
}
149159
}
160+
/*
161+
TODO: attribute support Proof of Concept (POC) by adding currency attribute to:
162+
163+
samples/quickstartadb/resources/META-INF/StockQuoteService.wsdl:
164+
165+
<xs:element name="getPrice">
166+
<xs:complexType>
167+
<xs:sequence>
168+
<xs:element name="symbol" nillable="true" type="xs:string"/>
169+
</xs:sequence>
170+
<xs:attribute name="currency" type="xs:string" use="required"/>
171+
</xs:complexType>
172+
</xs:element>
173+
174+
resulting in this SOAP Envelope:
175+
176+
<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>
177+
178+
Below, add complexType.getAttributes() code to support this JSON:
179+
180+
{ "getPrice" : {"symbol": "IBM","currency":USD}}
181+
182+
Possibly using @ as @currency to flag a variable name as as attribute.
183+
184+
One thing to note is XmlNode has isAttribute() but was never used
185+
*/
186+
if (complexType.getAttributes() != null && complexType.getAttributes().size() > 0) {
187+
log.debug("XmlNodeGenerator.processSchemaType() found attribute size from complexType: " + complexType.getAttributes().size());
188+
List<XmlSchemaAttributeOrGroupRef> list = complexType.getAttributes();
189+
for (XmlSchemaAttributeOrGroupRef ref : list) {
190+
XmlSchemaAttribute xsa = (XmlSchemaAttribute)ref;
191+
String name = xsa.getName();
192+
QName schemaTypeName = xsa.getSchemaTypeName();
193+
if (schema != null && schema.getTargetNamespace() != null && schemaTypeName != null && schemaTypeName.getLocalPart() != null) {
194+
log.debug("XmlNodeGenerator.processSchemaType() found attribute name from complexType: " + name + " , adding it to parentNode");
195+
XmlNode xmlNode = new XmlNode(name, schema.getTargetNamespace(), true, false, schemaTypeName.getLocalPart());
196+
parentNode.addChildToList(xmlNode);
197+
} else {
198+
log.debug("XmlNodeGenerator.processSchemaType() found attribute name from complexType: " + name + " , however could not resolve namespace and localPart");
199+
}
200+
}
201+
}
150202
}else if (xmlSchemaType instanceof XmlSchemaSimpleType) {
151203
// nothing to do with simpleType
152204
}
@@ -163,6 +215,11 @@ private XmlSchema getXmlSchema(QName qName) {
163215
}
164216

165217
private void generateQueue(XmlNode node) {
218+
log.debug("XmlNodeGenerator.generateQueue() found node name: " + node.getName() + " , isAttribute: " + node.isAttribute());
219+
if (node.isAttribute()) {
220+
attribute_queue.add(new JsonObject(node.getName(), JSONType.OBJECT , node.getValueType() , node.getNamespaceUri()));
221+
return;
222+
}
166223
if (node.isArray()) {
167224
if (node.getChildrenList().size() > 0) {
168225
queue.add(new JsonObject(node.getName(), JSONType.NESTED_ARRAY, node.getValueType() , node.getNamespaceUri()));
@@ -186,7 +243,6 @@ private void processXmlNodeChildren(List<XmlNode> childrenNodes) {
186243
}
187244
}
188245

189-
190246
public XmlNode getMainXmlNode() throws AxisFault {
191247
if (mainXmlNode == null) {
192248
try {
@@ -203,4 +259,9 @@ public Queue<JsonObject> getQueue(XmlNode node) {
203259
return queue;
204260
}
205261

262+
// need to invoke getQueue() before getAttributeQueue()
263+
public Queue<JsonObject> getAttributeQueue() {
264+
return attribute_queue;
265+
}
266+
206267
}

modules/json/src/org/apache/axis2/json/moshi/MoshiXMLStreamReader.java

Lines changed: 61 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ public class MoshiXMLStreamReader implements XMLStreamReader {
7474

7575
private Queue<JsonObject> queue = new LinkedList<JsonObject>();
7676

77+
private Queue<JsonObject> attribute_queue = new LinkedList<JsonObject>();
78+
79+
private List<Attribute> attributes;
80+
7781
private XmlNodeGenerator xmlNodeGenerator;
7882

7983
private Stack<JsonObject> stackObj = new Stack<JsonObject>();
@@ -134,6 +138,17 @@ private void process() throws AxisFault {
134138
newNodeMap.put(elementQname, mainXmlNode);
135139
configContext.setProperty(JsonConstant.XMLNODES, newNodeMap);
136140
}
141+
log.debug("MoshiXMLStreamReader.process() completed on queue size: " + queue.size());
142+
// XML Elements
143+
for (JsonObject jsonobject : queue) {
144+
log.debug("moshixmlstreamreader.process() found Element to process as jsonobject name: " + jsonobject.getName() + " , type: " + jsonobject.getType());
145+
}
146+
147+
// XML attributes
148+
attribute_queue = xmlNodeGenerator.getAttributeQueue();
149+
for (JsonObject jsonobject : attribute_queue) {
150+
log.debug("moshixmlstreamreader.process() found Attribute to process as jsonobject name: " + jsonobject.getName() + " , type: " + jsonobject.getType());
151+
}
137152
isProcessed = true;
138153
log.debug("MoshiXMLStreamReader.process() completed");
139154
}
@@ -231,12 +246,9 @@ public boolean isWhiteSpace() {
231246
}
232247

233248

234-
public String getAttributeValue(String namespaceURI, String localName) {
235-
throw new UnsupportedOperationException("Method is not implemented");
236-
}
237-
238-
239249
public int getAttributeCount() {
250+
// TODO populate the List of the class Attributes here by readName()
251+
// and using the attribute_queue instead of queue if attribute_queue not empty
240252
if (isStartElement()) {
241253
return 0; // don't support attributes on tags in JSON convention
242254
} else {
@@ -245,38 +257,60 @@ public int getAttributeCount() {
245257
}
246258

247259

248-
public QName getAttributeName(int index) {
249-
throw new UnsupportedOperationException("Method is not implemented");
260+
public String getAttributeLocalName(int index) {
261+
if ((null == attributes) || (index >= attributes.size())) {
262+
throw new IndexOutOfBoundsException();
263+
}
264+
return attributes.get(index).name.getLocalPart();
250265
}
251266

252267

253-
public String getAttributeNamespace(int index) {
254-
throw new UnsupportedOperationException("Method is not implemented");
268+
public QName getAttributeName(int index) {
269+
return attributes.get(index).name;
255270
}
256271

257272

258-
public String getAttributeLocalName(int index) {
259-
throw new UnsupportedOperationException("Method is not implemented");
273+
public String getAttributePrefix(int index) {
274+
if ((null == attributes) || (index >= attributes.size())) {
275+
throw new IndexOutOfBoundsException();
276+
}
277+
return null;
260278
}
261279

262280

263-
public String getAttributePrefix(int index) {
264-
throw new UnsupportedOperationException("Method is not implemented");
281+
public String getAttributeType(int index) {
282+
return null;
265283
}
266284

267285

268-
public String getAttributeType(int index) {
269-
throw new UnsupportedOperationException("Method is not implemented");
286+
public String getAttributeNamespace(int index) {
287+
return null;
270288
}
271289

272290

273291
public String getAttributeValue(int index) {
274-
throw new UnsupportedOperationException("Method is not implemented");
292+
if ((null == attributes) || (index >= attributes.size())) {
293+
throw new IndexOutOfBoundsException();
294+
}
295+
return attributes.get(index).value;
296+
}
297+
298+
299+
public String getAttributeValue(String namespaceURI, String localName) {
300+
if ((null == attributes) || (null == localName) || ("".equals(localName))) {
301+
throw new NoSuchElementException();
302+
}
303+
for (Attribute a : attributes) {
304+
if (localName.equals(a.name.getLocalPart())) {
305+
return a.value;
306+
}
307+
}
308+
throw new NoSuchElementException();
275309
}
276310

277311

278312
public boolean isAttributeSpecified(int index) {
279-
throw new UnsupportedOperationException("Method is not implemented");
313+
return (null != attributes) && (attributes.size() >= index);
280314
}
281315

282316

@@ -542,7 +576,6 @@ private void removeStackObj() throws XMLStreamException {
542576
localName = "";
543577
}
544578
} else {
545-
System.out.println("stackObj is empty");
546579
throw new XMLStreamException("Error while processing input JSON stream, JSON request may not valid ," +
547580
" it may has more end object characters ");
548581
}
@@ -736,4 +769,14 @@ public enum JsonState {
736769
EndObjectBeginObject_START,
737770
EndObjectEndDocument,
738771
}
772+
773+
private static class Attribute {
774+
private final QName name;
775+
private final String value;
776+
777+
Attribute(QName name, String value) {
778+
this.name = name;
779+
this.value = value;
780+
}
781+
}
739782
}

0 commit comments

Comments
 (0)