Finished OpenAPIWriter
This commit is contained in:
parent
02e91a38e9
commit
bb8d6a93b4
10 changed files with 215 additions and 107 deletions
|
|
@ -72,14 +72,14 @@ public class ClassUtil {
|
||||||
* @return if the given class is a wrapper for a primitive
|
* @return if the given class is a wrapper for a primitive
|
||||||
*/
|
*/
|
||||||
public static boolean isWrapper(Class<?> type){
|
public static boolean isWrapper(Class<?> type){
|
||||||
return wrappers.contains( type );
|
return wrappers.contains(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return if the given class is a primitive including String
|
* @return if the given class is a primitive including String
|
||||||
*/
|
*/
|
||||||
public static boolean isPrimitive(Class<?> type){
|
public static boolean isPrimitive(Class<?> type){
|
||||||
return primitives.contains( type );
|
return primitives.contains(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -184,13 +184,26 @@ public class ClassUtil {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param c a array class
|
* @param c a array class
|
||||||
* @return the base class the array is based on, if the input is not an array then the input is returned.
|
* @return the base class the array is based on, if the input is not an array then the input is returned.
|
||||||
*/
|
*/
|
||||||
public static Class<?> getArrayClass(Class<?> c) {
|
public static Class<?> getArrayClass(Class<?> c) {
|
||||||
|
return getArrayClass(c, Integer.MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param c a array class
|
||||||
|
* @param depth the number of times the method should recurse into array. Value of zero will return the input value.
|
||||||
|
* @return the base class the array is based on, if the input is not an array then the input is returned.
|
||||||
|
*/
|
||||||
|
public static Class<?> getArrayClass(Class<?> c, int depth) {
|
||||||
|
if (depth <= 0) // Stop recursion
|
||||||
|
return c;
|
||||||
|
|
||||||
if (c != null && c.isArray()) {
|
if (c != null && c.isArray()) {
|
||||||
return getArrayClass(c.getComponentType());
|
return getArrayClass(c.getComponentType(), depth-1);
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -141,13 +141,9 @@ public class UPnPContentDirectory implements UPnPService, HttpPage, WSInterface
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
public class BrowseRetObj extends WSReturnObject{
|
public class BrowseRetObj extends WSReturnObject{
|
||||||
@WSParamName("Result")
|
|
||||||
public String Result;
|
public String Result;
|
||||||
@WSParamName("NumberReturned")
|
|
||||||
public int NumberReturned;
|
public int NumberReturned;
|
||||||
@WSParamName("TotalMatches")
|
|
||||||
public int TotalMatches;
|
public int TotalMatches;
|
||||||
@WSParamName("UpdateID")
|
|
||||||
public int UpdateID;
|
public int UpdateID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -122,7 +122,7 @@ public interface WSInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method will be used in the header.
|
* This method will be used in the SOAP header.
|
||||||
*/
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.METHOD)
|
@Target(ElementType.METHOD)
|
||||||
|
|
@ -146,7 +146,7 @@ public interface WSInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a specific path for the method overriding the auto generated path.
|
* Sets a specific URL path for the method overriding the auto generated path.
|
||||||
*/
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.METHOD)
|
@Target(ElementType.METHOD)
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,10 @@ public class WSMethodDef {
|
||||||
* A List of return parameters of the method
|
* A List of return parameters of the method
|
||||||
**/
|
**/
|
||||||
private ArrayList<WSParameterDef> outputs;
|
private ArrayList<WSParameterDef> outputs;
|
||||||
|
/**
|
||||||
|
* The object type of output object
|
||||||
|
**/
|
||||||
|
private Class<?> outputClass;
|
||||||
/**
|
/**
|
||||||
* A List of exceptions that this method throws
|
* A List of exceptions that this method throws
|
||||||
**/
|
**/
|
||||||
|
|
@ -112,68 +116,58 @@ public class WSMethodDef {
|
||||||
else
|
else
|
||||||
namespace = wsDef.getNamespace() + "?#" + name;
|
namespace = wsDef.getNamespace() + "?#" + name;
|
||||||
|
|
||||||
// Hnadle Exceptions
|
// ------------------------------------------------
|
||||||
|
// Handle inputs
|
||||||
Collections.addAll(exceptions, method.getExceptionTypes());
|
// ------------------------------------------------
|
||||||
|
|
||||||
// Handle input parameter names
|
|
||||||
|
|
||||||
Annotation[][] paramAnnotation = method.getParameterAnnotations();
|
Annotation[][] paramAnnotation = method.getParameterAnnotations();
|
||||||
Class<?>[] inputTypes = method.getParameterTypes();
|
Class<?>[] inputTypes = method.getParameterTypes();
|
||||||
|
|
||||||
for (int i = 0; i < paramAnnotation.length; i++) {
|
for (int i = 0; i < paramAnnotation.length; i++) {
|
||||||
WSParameterDef param = new WSParameterDef(this);
|
WSParameterDef param = new WSParameterDef(this, inputTypes[i], paramAnnotation[i]);
|
||||||
for (Annotation annotation : paramAnnotation[i]) {
|
|
||||||
if (annotation instanceof WSInterface.WSParamName) {
|
// if no name was found then generate one
|
||||||
WSInterface.WSParamName paramName = (WSInterface.WSParamName) annotation;
|
|
||||||
param.setName(paramName.value());
|
|
||||||
param.setOptional(paramName.optional());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
param.setParamClass(inputTypes[i]);
|
|
||||||
// if no name was found then use default
|
|
||||||
if (param.getName() == null)
|
if (param.getName() == null)
|
||||||
param.setName("args" + i);
|
param.setName("args" + i);
|
||||||
|
|
||||||
inputs.add(param);
|
inputs.add(param);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle return parameter names
|
// ------------------------------------------------
|
||||||
|
// Handle outputs
|
||||||
|
// ------------------------------------------------
|
||||||
|
|
||||||
WSInterface.WSReturnName returnNameAnnotation = method.getAnnotation(WSInterface.WSReturnName.class);
|
this.outputClass = method.getReturnType();
|
||||||
if (WSReturnObject.class.isAssignableFrom(method.getReturnType())) {
|
if (WSReturnObject.class.isAssignableFrom(outputClass)) {
|
||||||
Class<?> retClass = method.getReturnType();
|
Field[] fields = outputClass.getFields();
|
||||||
Field[] fields = retClass.getFields();
|
|
||||||
|
|
||||||
for (Field field : fields) {
|
for (Field field : fields) {
|
||||||
WSParameterDef ret_param = new WSParameterDef(this);
|
WSParameterDef ret_param = new WSParameterDef(this, field.getType(), field.getAnnotations());
|
||||||
|
|
||||||
WSInterface.WSParamName paramNameAnnotation = field.getAnnotation(WSInterface.WSParamName.class);
|
if (ret_param.getName() == null)
|
||||||
if (paramNameAnnotation != null)
|
|
||||||
ret_param.setName(paramNameAnnotation.value());
|
|
||||||
else
|
|
||||||
ret_param.setName(field.getName());
|
ret_param.setName(field.getName());
|
||||||
|
|
||||||
WSInterface.WSDocumentation documentationAnnotation = field.getAnnotation(WSInterface.WSDocumentation.class);
|
|
||||||
if (documentationAnnotation != null)
|
|
||||||
ret_param.setDocumentation(documentationAnnotation.value());
|
|
||||||
|
|
||||||
ret_param.setParamClass(field.getType());
|
|
||||||
outputs.add(ret_param);
|
outputs.add(ret_param);
|
||||||
}
|
}
|
||||||
} else if (method.getReturnType() != void.class) {
|
} else if (outputClass != void.class) {
|
||||||
WSParameterDef ret_param = new WSParameterDef(this);
|
WSInterface.WSReturnName returnNameAnnotation = method.getAnnotation(WSInterface.WSReturnName.class);
|
||||||
|
WSParameterDef ret_param = new WSParameterDef(this, method.getReturnType(), new Annotation[]{returnNameAnnotation});
|
||||||
|
|
||||||
if (returnNameAnnotation != null)
|
if (ret_param.getName() == null)
|
||||||
ret_param.setName(returnNameAnnotation.value());
|
|
||||||
else
|
|
||||||
ret_param.setName("return");
|
ret_param.setName("return");
|
||||||
|
|
||||||
ret_param.setParamClass(method.getReturnType());
|
|
||||||
outputs.add(ret_param);
|
outputs.add(ret_param);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------
|
||||||
|
// Handle Exceptions
|
||||||
|
// ------------------------------------------------
|
||||||
|
|
||||||
|
Collections.addAll(exceptions, method.getExceptionTypes());
|
||||||
|
|
||||||
|
// ------------------------------------------------
|
||||||
// Handle the request type
|
// Handle the request type
|
||||||
|
// ------------------------------------------------
|
||||||
|
|
||||||
WSRequestType requestTypeAnnotation = method.getAnnotation(WSRequestType.class);
|
WSRequestType requestTypeAnnotation = method.getAnnotation(WSRequestType.class);
|
||||||
if (requestTypeAnnotation != null) {
|
if (requestTypeAnnotation != null) {
|
||||||
|
|
@ -193,7 +187,9 @@ public class WSMethodDef {
|
||||||
this.requestType = WSInterface.RequestType.GET;
|
this.requestType = WSInterface.RequestType.GET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------
|
||||||
// Handle endpoint path
|
// Handle endpoint path
|
||||||
|
// ------------------------------------------------
|
||||||
|
|
||||||
WSPath pathAnnotation = method.getAnnotation(WSPath.class);
|
WSPath pathAnnotation = method.getAnnotation(WSPath.class);
|
||||||
if (pathAnnotation != null)
|
if (pathAnnotation != null)
|
||||||
|
|
@ -240,6 +236,13 @@ public class WSMethodDef {
|
||||||
return outputs;
|
return outputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the class of the output object
|
||||||
|
*/
|
||||||
|
public Class<?> getOutputClass() {
|
||||||
|
return outputClass;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return documentation of the method if one exists or else null
|
* @return documentation of the method if one exists or else null
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@
|
||||||
|
|
||||||
package zutil.net.ws;
|
package zutil.net.ws;
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a web service parameter definition class
|
* This is a web service parameter definition class
|
||||||
*
|
*
|
||||||
|
|
@ -39,21 +41,35 @@ public class WSParameterDef {
|
||||||
/** Developer documentation **/
|
/** Developer documentation **/
|
||||||
private String documentation;
|
private String documentation;
|
||||||
/** If this parameter is optional **/
|
/** If this parameter is optional **/
|
||||||
private boolean optional;
|
private boolean optional = false;
|
||||||
|
|
||||||
|
|
||||||
protected WSParameterDef(WSMethodDef mDef){
|
protected WSParameterDef(WSMethodDef mDef, Class<?> paramClass, Annotation[] annotations){
|
||||||
this.mDef = mDef;
|
this.mDef = mDef;
|
||||||
this.optional = false;
|
this.paramClass = paramClass;
|
||||||
|
|
||||||
|
for (Annotation annotation : annotations) {
|
||||||
|
if (annotation == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (annotation instanceof WSInterface.WSParamName) {
|
||||||
|
WSInterface.WSParamName paramNameAnnotation = (WSInterface.WSParamName) annotation;
|
||||||
|
this.name = paramNameAnnotation.value();
|
||||||
|
this.optional = paramNameAnnotation.optional();
|
||||||
|
} else if (annotation instanceof WSInterface.WSReturnName) {
|
||||||
|
WSInterface.WSReturnName returnAnnotation = (WSInterface.WSReturnName) annotation;
|
||||||
|
this.name = returnAnnotation.value();
|
||||||
|
} else if (annotation instanceof WSInterface.WSDocumentation) {
|
||||||
|
WSInterface.WSDocumentation documentationAnnotation = (WSInterface.WSDocumentation) annotation;
|
||||||
|
this.documentation = documentationAnnotation.value();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Class<?> getParamClass() {
|
public Class<?> getParamClass() {
|
||||||
return paramClass;
|
return paramClass;
|
||||||
}
|
}
|
||||||
protected void setParamClass(Class<?> paramClass) {
|
|
||||||
this.paramClass = paramClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
|
|
|
||||||
|
|
@ -24,10 +24,6 @@
|
||||||
|
|
||||||
package zutil.net.ws;
|
package zutil.net.ws;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,18 @@
|
||||||
package zutil.net.ws.openapi;
|
package zutil.net.ws.openapi;
|
||||||
|
|
||||||
|
import zutil.ClassUtil;
|
||||||
import zutil.log.LogUtil;
|
import zutil.log.LogUtil;
|
||||||
import zutil.net.ws.WSMethodDef;
|
import zutil.net.ws.*;
|
||||||
import zutil.net.ws.WSParameterDef;
|
|
||||||
import zutil.net.ws.WebServiceDef;
|
|
||||||
import zutil.parser.DataNode;
|
import zutil.parser.DataNode;
|
||||||
import zutil.parser.json.JSONWriter;
|
import zutil.parser.json.JSONWriter;
|
||||||
|
|
||||||
|
import javax.xml.crypto.Data;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.util.ArrayList;
|
import java.lang.reflect.Field;
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -22,6 +20,7 @@ import java.util.logging.Logger;
|
||||||
*
|
*
|
||||||
* @see <a href="https://swagger.io/specification/">OpenAPI Specification</a>
|
* @see <a href="https://swagger.io/specification/">OpenAPI Specification</a>
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
public class OpenAPIWriter {
|
public class OpenAPIWriter {
|
||||||
private static final Logger logger = LogUtil.getLogger();
|
private static final Logger logger = LogUtil.getLogger();
|
||||||
|
|
||||||
|
|
@ -60,14 +59,14 @@ public class OpenAPIWriter {
|
||||||
|
|
||||||
public String write() {
|
public String write() {
|
||||||
if (cache == null) {
|
if (cache == null) {
|
||||||
Map<String, List<WSParameterDef>> schemas = new HashMap<>();
|
List<Class> objSchemas = new ArrayList<>();
|
||||||
|
|
||||||
DataNode root = new DataNode(DataNode.DataType.Map);
|
DataNode root = new DataNode(DataNode.DataType.Map);
|
||||||
root.set("openapi", OPENAPI_VERSION);
|
root.set("openapi", OPENAPI_VERSION);
|
||||||
root.set("info", generateInfo());
|
root.set("info", generateInfo());
|
||||||
root.set("servers", generateServers());
|
root.set("servers", generateServers());
|
||||||
root.set("paths", generatePaths(schemas));
|
root.set("paths", generatePaths(objSchemas));
|
||||||
root.set("components", generateComponents(schemas));
|
root.set("components", generateComponents(objSchemas));
|
||||||
|
|
||||||
this.cache = JSONWriter.toString(root);
|
this.cache = JSONWriter.toString(root);
|
||||||
}
|
}
|
||||||
|
|
@ -77,9 +76,11 @@ public class OpenAPIWriter {
|
||||||
private DataNode generateInfo() {
|
private DataNode generateInfo() {
|
||||||
DataNode infoRoot = new DataNode(DataNode.DataType.Map);
|
DataNode infoRoot = new DataNode(DataNode.DataType.Map);
|
||||||
infoRoot.set("title", ws.getName());
|
infoRoot.set("title", ws.getName());
|
||||||
infoRoot.set("description", ws.getDocumentation());
|
|
||||||
infoRoot.set("version", "");
|
infoRoot.set("version", "");
|
||||||
|
|
||||||
|
if (ws.getDocumentation() != null)
|
||||||
|
infoRoot.set("description", ws.getDocumentation());
|
||||||
|
|
||||||
// Not implemented properties
|
// Not implemented properties
|
||||||
// "termsOfService": xxx,
|
// "termsOfService": xxx,
|
||||||
// "contact": {"name": xxx,"url": xxx,"email": xxx},
|
// "contact": {"name": xxx,"url": xxx,"email": xxx},
|
||||||
|
|
@ -99,27 +100,33 @@ public class OpenAPIWriter {
|
||||||
return serversRoot;
|
return serversRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataNode generatePaths(Map<String, List<WSParameterDef>> schemas) {
|
private DataNode generatePaths(List<Class> objSchemas) {
|
||||||
DataNode pathsRoot = new DataNode(DataNode.DataType.Map);
|
DataNode pathsRoot = new DataNode(DataNode.DataType.Map);
|
||||||
|
|
||||||
for (WSMethodDef methodDef : ws.getMethods()) {
|
for (WSMethodDef methodDef : ws.getMethods()) {
|
||||||
DataNode pathNode = pathsRoot.set(methodDef.getPath(), DataNode.DataType.Map);
|
DataNode pathNode = pathsRoot.set(methodDef.getPath(), DataNode.DataType.Map);
|
||||||
|
|
||||||
DataNode typeNode = pathNode.set(methodDef.getRequestType().toString().toLowerCase(), DataNode.DataType.Map);
|
DataNode typeNode = pathNode.set(methodDef.getRequestType().toString().toLowerCase(), DataNode.DataType.Map);
|
||||||
typeNode.set("description", methodDef.getDocumentation());
|
|
||||||
|
if (methodDef.getDocumentation() != null)
|
||||||
|
typeNode.set("description", methodDef.getDocumentation());
|
||||||
|
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// Inputs
|
// Inputs
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
|
|
||||||
DataNode parameterNode = typeNode.set("parameters", DataNode.DataType.Map);
|
DataNode parametersNode = typeNode.set("parameters", DataNode.DataType.List);
|
||||||
for (WSParameterDef parameterDef : methodDef.getInputs()) {
|
for (WSParameterDef parameterDef : methodDef.getInputs()) {
|
||||||
|
DataNode parameterNode = parametersNode.add(DataNode.DataType.Map);
|
||||||
parameterNode.set("name", parameterDef.getName());
|
parameterNode.set("name", parameterDef.getName());
|
||||||
parameterNode.set("description", parameterDef.getDocumentation());
|
|
||||||
parameterNode.set("in", "query");
|
parameterNode.set("in", "query");
|
||||||
parameterNode.set("required", parameterDef.isOptional());
|
parameterNode.set("required", !parameterDef.isOptional());
|
||||||
|
|
||||||
parameterNode.set("schema", "");
|
if (parameterDef.getDocumentation() != null)
|
||||||
|
parameterNode.set("description", parameterDef.getDocumentation());
|
||||||
|
|
||||||
|
DataNode schemaNode = parameterNode.set("schema", DataNode.DataType.Map);
|
||||||
|
generateSchema(schemaNode, parameterDef.getParamClass(), true, objSchemas);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
|
|
@ -127,31 +134,104 @@ public class OpenAPIWriter {
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
|
|
||||||
DataNode responseNode = typeNode.set("responses", DataNode.DataType.Map);
|
DataNode responseNode = typeNode.set("responses", DataNode.DataType.Map);
|
||||||
DataNode schemaNode = responseNode.set("200", DataNode.DataType.Map)
|
DataNode successNode = responseNode.set("200", DataNode.DataType.Map);
|
||||||
.set("content", DataNode.DataType.Map)
|
successNode.set("description", "A successful response.");
|
||||||
.set("application/json", DataNode.DataType.Map)
|
|
||||||
.set("schema", DataNode.DataType.Map);
|
|
||||||
|
|
||||||
String retName = methodDef.getName() + "Return";
|
|
||||||
schemas.put("retName", methodDef.getOutputs());
|
|
||||||
schemaNode.set("$ref", "#/components/schemas/" + retName);
|
|
||||||
|
|
||||||
|
if (methodDef.getOutputClass() != void.class) {
|
||||||
|
DataNode schemaNode = successNode.set("content", DataNode.DataType.Map)
|
||||||
|
.set("application/json", DataNode.DataType.Map)
|
||||||
|
.set("schema", DataNode.DataType.Map);
|
||||||
|
generateSchema(schemaNode, methodDef.getOutputClass(), true, objSchemas);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return pathsRoot;
|
return pathsRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataNode generateComponents(Map<String, List<WSParameterDef>> schemas) {
|
private DataNode generateComponents(List<Class> objSchemas) {
|
||||||
DataNode componentsRoot = new DataNode(DataNode.DataType.Map);
|
DataNode componentsRoot = new DataNode(DataNode.DataType.Map);
|
||||||
DataNode schemasNode = new DataNode(DataNode.DataType.Map);
|
DataNode schemasNode = componentsRoot.set("schemas", DataNode.DataType.Map);
|
||||||
componentsRoot.set("schemas", schemasNode);
|
|
||||||
|
|
||||||
// Generate schemas
|
// Generate schemas
|
||||||
|
|
||||||
|
for (int i=0; i<objSchemas.size(); i++) {
|
||||||
|
Class clazz = objSchemas.get(i);
|
||||||
|
|
||||||
|
DataNode objectNode = schemasNode.set(clazz.getSimpleName(), DataNode.DataType.Map);
|
||||||
|
generateSchema(objectNode, clazz, false, objSchemas);
|
||||||
|
}
|
||||||
|
|
||||||
return componentsRoot;
|
return componentsRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void generateSchema(DataNode parent, Class<?> clazz, boolean reference, List<Class> objSchemas) {
|
||||||
|
if (clazz == void.class)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ClassUtil.isPrimitive(clazz) || ClassUtil.isWrapper(clazz)) {
|
||||||
|
parent.set("type", getOpenAPIType(clazz));
|
||||||
|
|
||||||
|
if (clazz == byte.class || clazz == Byte.class)
|
||||||
|
parent.set("format", "byte");
|
||||||
|
} else if (clazz.isArray() || Collection.class.isAssignableFrom(clazz)) {
|
||||||
|
parent.set("type", "array");
|
||||||
|
|
||||||
|
DataNode itemsNode = parent.set("items", DataNode.DataType.Map);
|
||||||
|
generateSchema(itemsNode, ClassUtil.getArrayClass(clazz, 1), reference, objSchemas);
|
||||||
|
} else {
|
||||||
|
parent.set("type", "object");
|
||||||
|
|
||||||
|
if (reference) {
|
||||||
|
if (!objSchemas.contains(clazz))
|
||||||
|
objSchemas.add(clazz);
|
||||||
|
parent.set("$ref", "#/components/schemas/" + clazz.getSimpleName());
|
||||||
|
} else {
|
||||||
|
if (WSReturnObject.class.isAssignableFrom(clazz)) {
|
||||||
|
DataNode propertiesNode = parent.set("properties", DataNode.DataType.Map);
|
||||||
|
for (Field field : clazz.getFields()) {
|
||||||
|
String fieldName = field.getName();
|
||||||
|
|
||||||
|
WSInterface.WSParamName paramNameAnnotation = field.getAnnotation(WSInterface.WSParamName.class);
|
||||||
|
if (paramNameAnnotation != null)
|
||||||
|
fieldName = paramNameAnnotation.value();
|
||||||
|
|
||||||
|
DataNode parameterNode = propertiesNode.set(fieldName, DataNode.DataType.Map);
|
||||||
|
generateSchema(parameterNode, field.getType(), false, objSchemas);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String getOpenAPIType(Class<?> clazz) {
|
||||||
|
switch (clazz.getName()) {
|
||||||
|
case "int":
|
||||||
|
case "java.lang.Integer":
|
||||||
|
return "integer";
|
||||||
|
|
||||||
|
case "float":
|
||||||
|
case "java.lang.Float":
|
||||||
|
case "double":
|
||||||
|
case "java.lang.Double":
|
||||||
|
return "number";
|
||||||
|
|
||||||
|
case "byte":
|
||||||
|
case "java.lang.Byte":
|
||||||
|
case "java.lang.String":
|
||||||
|
return "string";
|
||||||
|
|
||||||
|
case "boolean":
|
||||||
|
case "java.lang.Boolean":
|
||||||
|
return "boolean";
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class containing Target API server information.
|
||||||
|
*/
|
||||||
protected static class ServerData {
|
protected static class ServerData {
|
||||||
String url;
|
String url;
|
||||||
String description;
|
String description;
|
||||||
|
|
|
||||||
|
|
@ -373,6 +373,7 @@ public class SOAPHttpPage implements HttpPage{
|
||||||
*/
|
*/
|
||||||
public static String getSOAPClassName(Class<?> c) {
|
public static String getSOAPClassName(Class<?> c) {
|
||||||
Class<?> cTmp = ClassUtil.getArrayClass(c);
|
Class<?> cTmp = ClassUtil.getArrayClass(c);
|
||||||
|
|
||||||
if (byte[].class.isAssignableFrom(c)) {
|
if (byte[].class.isAssignableFrom(c)) {
|
||||||
return "base64Binary";
|
return "base64Binary";
|
||||||
} else if (WSReturnObject.class.isAssignableFrom(cTmp)) {
|
} else if (WSReturnObject.class.isAssignableFrom(cTmp)) {
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,6 @@ public class OpenAPIWriterTest {
|
||||||
OpenAPIWriter writer = new OpenAPIWriter(new WebServiceDef(SOAPTest.MainSOAPClass.class));
|
OpenAPIWriter writer = new OpenAPIWriter(new WebServiceDef(SOAPTest.MainSOAPClass.class));
|
||||||
writer.addServer("example.com", "Main Server");
|
writer.addServer("example.com", "Main Server");
|
||||||
|
|
||||||
assertEquals("", writer.write());
|
assertEquals("{\"components\": {\"schemas\": {\"SpecialReturnClass\": {\"type\": \"object\", \"properties\": {\"b\": {\"type\": \"array\", \"items\": {\"format\": \"byte\", \"type\": \"string\"}}, \"otherValue1\": {\"type\": \"string\"}, \"otherName2\": {\"type\": \"string\"}, \"inner\": {\"type\": \"object\", \"properties\": {\"innerClassParam2\": {\"type\": \"string\"}, \"innerClassParam1\": {\"type\": \"string\"}}}}}, \"SimpleReturnClass\": {\"type\": \"object\", \"properties\": {\"otherParam1\": {\"type\": \"string\"}, \"param2\": {\"type\": \"string\"}}}}}, \"servers\": [{\"description\": \"Main Server\", \"url\": \"example.com\"}], \"openapi\": \"3.0.1\", \"paths\": {\"/simpleReturnClassMethod\": {\"get\": {\"responses\": {\"200\": {\"description\": \"A successful response.\", \"content\": {\"application/json\": {\"schema\": {\"type\": \"object\", \"$ref\": \"#/components/schemas/SimpleReturnClass\"}}}}}, \"parameters\": [{\"schema\": {\"type\": \"string\"}, \"in\": \"query\", \"name\": \"byte\", \"required\": true}]}}, \"/exceptionMethod\": {\"get\": {\"description\": \"Documentation of method exceptionMethod()\", \"responses\": {\"200\": {\"description\": \"A successful response.\"}}, \"parameters\": [{\"schema\": {\"type\": \"integer\"}, \"in\": \"query\", \"name\": \"otherParam1\", \"required\": false}, {\"schema\": {\"type\": \"integer\"}, \"in\": \"query\", \"name\": \"otherParam2\", \"required\": false}]}}, \"/specialReturnMethod\": {\"get\": {\"responses\": {\"200\": {\"description\": \"A successful response.\", \"content\": {\"application/json\": {\"schema\": {\"type\": \"array\", \"items\": {\"type\": \"object\", \"$ref\": \"#/components/schemas/SpecialReturnClass\"}}}}}}, \"parameters\": [{\"schema\": {\"type\": \"string\"}, \"in\": \"query\", \"name\": \"StringName2\", \"required\": true}]}}, \"/stringArrayMethod\": {\"get\": {\"responses\": {\"200\": {\"description\": \"A successful response.\", \"content\": {\"application/json\": {\"schema\": {\"type\": \"array\", \"items\": {\"type\": \"array\", \"items\": {\"type\": \"string\"}}}}}}}, \"parameters\": [{\"schema\": {\"type\": \"string\"}, \"in\": \"query\", \"name\": \"StringName\", \"required\": true}]}}, \"/voidMethod\": {\"get\": {\"responses\": {\"200\": {\"description\": \"A successful response.\"}}, \"parameters\": []}}}, \"info\": {\"description\": \"\", \"title\": \"MainSOAPClass\", \"version\": \"\"}}", writer.write());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -84,29 +84,6 @@ public class SOAPTest {
|
||||||
// TEST CLASSES
|
// TEST CLASSES
|
||||||
// ----------------------------------------------------
|
// ----------------------------------------------------
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public static class SpecialReturnClass extends WSReturnObject{
|
|
||||||
@WSParamName("otherValue1")
|
|
||||||
public String param1 = "otherValue1";
|
|
||||||
@WSParamName("otherName2")
|
|
||||||
public String param2 = "otherValue2";
|
|
||||||
public byte[] b = new byte[]{0x12, 0x23};
|
|
||||||
public InnerClass inner = new InnerClass();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public static class InnerClass extends WSReturnObject{
|
|
||||||
public String innerClassParam1 = "innerClass1";
|
|
||||||
public String innerClassParam2 = "innerClass2";
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public static class SimpleReturnClass extends WSReturnObject{
|
|
||||||
@WSParamName("otherParam1")
|
|
||||||
public String param1 = "param1";
|
|
||||||
public String param2 = "param2";
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@WSNamespace("http://test.se:8080/")
|
@WSNamespace("http://test.se:8080/")
|
||||||
public static class MainSOAPClass implements WSInterface{
|
public static class MainSOAPClass implements WSInterface{
|
||||||
|
|
@ -157,4 +134,30 @@ public class SOAPTest {
|
||||||
|
|
||||||
private void privateMethod(){ }
|
private void privateMethod(){ }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public static class SpecialReturnClass extends WSReturnObject{
|
||||||
|
@WSParamName("otherValue1")
|
||||||
|
public String param1 = "otherValue1";
|
||||||
|
@WSParamName("otherName2")
|
||||||
|
public String param2 = "otherValue2";
|
||||||
|
public byte[] b = new byte[]{0x12, 0x23};
|
||||||
|
public InnerClass inner = new InnerClass();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public static class InnerClass extends WSReturnObject{
|
||||||
|
public String innerClassParam1 = "innerClass1";
|
||||||
|
public String innerClassParam2 = "innerClass2";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public static class SimpleReturnClass extends WSReturnObject{
|
||||||
|
@WSParamName("otherParam1")
|
||||||
|
public String param1 = "param1";
|
||||||
|
public String param2 = "param2";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue