/**
* Copyright 2013 SmartBear Software, Inc.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.smartbear.swagger4j.impl;
import com.smartbear.swagger4j.SwaggerFormat;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import javax.json.JsonArray;
import javax.json.JsonNumber;
import javax.json.JsonObject;
import javax.json.JsonString;
import javax.json.JsonValue;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.IOException;
import java.io.Reader;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
/**
* Utility class for abstraction of reading actual format, since json and xml are read in the same way
*/
public abstract class SwaggerParser {
public abstract String getString(String name);
public abstract List<SwaggerParser> getChildren(String name);
public abstract boolean getBoolean(String name);
public abstract String getString();
public abstract SwaggerFormat getFormat();
public abstract int getInteger(String name);
public abstract Number getNumber(String name);
public abstract List<String> getArray(String name);
public abstract SwaggerParser getChild(String name);
public abstract String[] getChildNames();
/**
* Builder for a SwaggerParser that can read XML
*/
public static SwaggerParser newXmlParser(Reader reader) throws IOException {
return new SwaggerXmlParser(reader);
}
/**
* Builder for a SwaggerParser that can read json
*/
public static SwaggerParser newJsonParser(Reader reader) {
return new SwaggerJsonParser(reader);
}
/**
* Builder for a SwaggerParser for one of the supported formats
*/
public static SwaggerParser newParser(Reader reader, SwaggerFormat format) throws IOException {
switch (format) {
case json:
return SwaggerParser.newJsonParser(reader);
case xml:
return SwaggerParser.newXmlParser(reader);
}
throw new RuntimeException("Unknown format: " + format);
}
/**
* SwaggerParser implementation that reads XML
*/
public static class SwaggerXmlParser extends SwaggerParser {
private final Element elm;
private SwaggerXmlParser(Element elm) {
this.elm = elm;
}
private SwaggerXmlParser(Reader reader) throws IOException {
assert reader != null;
try {
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(reader));
elm = document.getDocumentElement();
} catch (Exception e) {
throw new IOException(e);
}
}
@Override
public String getString(String name) {
NodeList nl = elm.getElementsByTagName(name);
if (nl.getLength() > 0) {
return nl.item(0).getTextContent();
}
return null;
}
@Override
public List<SwaggerParser> getChildren(String name) {
List<SwaggerParser> result = new ArrayList<SwaggerParser>();
NodeList nl = elm.getElementsByTagName(name);
for (int c = 0; c < nl.getLength(); c++) {
result.add(new SwaggerXmlParser((Element) nl.item(c)));
}
return result;
}
@Override
public boolean getBoolean(String name) {
return Boolean.getBoolean(getString(name));
}
@Override
public String getString() {
return elm.getTextContent();
}
@Override
public SwaggerFormat getFormat() {
return SwaggerFormat.xml;
}
@Override
public int getInteger(String name) {
return Integer.parseInt(getString(name));
}
@Override
public Number getNumber(String name) {
String stringValue = getString(name);
return stringValue == null || stringValue.isEmpty()
? null
: new BigDecimal(stringValue);
}
@Override
public List<String> getArray(String name) {
List<String> result = new ArrayList<String>();
NodeList nl = elm.getElementsByTagName(name);
for (int c = 0; c < nl.getLength(); c++) {
result.add(nl.item(c).getTextContent());
}
return result;
}
@Override
public SwaggerParser getChild(String name) {
NodeList nl = elm.getElementsByTagName(name);
if (nl.getLength() > 0) {
return new SwaggerXmlParser((Element) nl.item(0));
}
return null;
}
@Override
public String[] getChildNames() {
List<String> names = new ArrayList<String>();
NodeList nl = elm.getChildNodes();
for (int c = 0; c < nl.getLength(); c++) {
Node n = nl.item(c);
if (n.getNodeType() == Node.ELEMENT_NODE) {
names.add(n.getNodeName());
}
}
return names.toArray(new String[names.size()]);
}
}
/**
* SwaggerParser implementation that reads JSON
*/
public static class SwaggerJsonParser extends SwaggerParser {
private final JsonObject jsonObject;
private SwaggerJsonParser(JsonObject jsonObject) {
this.jsonObject = jsonObject;
}
private SwaggerJsonParser(Reader reader) {
final javax.json.JsonReader jsonReader = javax.json.Json.createReader(reader);
jsonObject = jsonReader.readObject();
}
@Override
public String getString(String name) {
try {
return jsonObject.getString(name, null);
} catch (RuntimeException e) {
Swagger4jExceptionHandler.get().onException(e);
return null;
}
}
@Override
public List<SwaggerParser> getChildren(String name) {
List<SwaggerParser> result = new ArrayList<SwaggerParser>();
if (!jsonObject.containsKey(name) || jsonObject.isNull(name)) {
return result;
}
JsonArray jsonArray = jsonObject.getJsonArray(name);
for (int c = 0; jsonArray != null && c < jsonArray.size(); c++) {
result.add(new SwaggerJsonParser(jsonArray.getJsonObject(c)));
}
return result;
}
@Override
public boolean getBoolean(String name) {
assert name != null : "name can not be null";
JsonValue value = jsonObject.get(name);
return value == null ? false : Boolean.valueOf(value.toString());
}
@Override
public String getString() {
return jsonObject.toString();
}
@Override
public SwaggerFormat getFormat() {
return SwaggerFormat.json;
}
@Override
public int getInteger(String name) {
JsonValue value = jsonObject.get(name);
return Integer.parseInt(value.toString());
}
@Override
public Number getNumber(String name) {
JsonValue value = jsonObject.get(name);
if (value == null) {
return null;
}
switch (value.getValueType()) {
case NUMBER:
return ((JsonNumber) value).bigDecimalValue();
case STRING:
return new BigDecimal(((JsonString) value).getString());
default:
throw new IllegalArgumentException("not a number");
}
}
@Override
public List<String> getArray(String name) {
List<String> result = new ArrayList<String>();
if (!jsonObject.containsKey(name) || jsonObject.isNull(name)) {
return result;
}
JsonArray jsonArray = jsonObject.getJsonArray(name);
if (jsonArray != null) {
for (int c = 0; c < jsonArray.size(); c++) {
result.add(jsonArray.getString(c));
}
}
return result;
}
@Override
public SwaggerParser getChild(String name) {
JsonValue value = jsonObject.get(name);
if (value == JsonValue.NULL) {
return null;
}
JsonObject child = (JsonObject) value;
return child == null ? null : new SwaggerJsonParser(child);
}
@Override
public String[] getChildNames() {
return jsonObject.keySet().toArray(new String[jsonObject.size()]);
}
}
}