You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2015/12/11 11:28:13 UTC
[05/11] isis git commit: ISIS-1237: factoring out helper methods.
Also changing order of select drop-down in swagger-ui html,
deleting commented out code.
ISIS-1237: factoring out helper methods. Also changing order of select drop-down in swagger-ui html, deleting commented out code.
Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/f9a0b43a
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/f9a0b43a
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/f9a0b43a
Branch: refs/heads/master
Commit: f9a0b43af8ee1d43498f787ef0bc40deb48e22fc
Parents: 1b202fe
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Wed Dec 9 18:56:57 2015 +0000
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Wed Dec 9 18:56:57 2015 +0000
----------------------------------------------------------------------
.../swagger/internal/SwaggerSpecGenerator.java | 494 +++++++++++--------
.../webapp/src/main/webapp/api-docs/index.html | 13 +-
2 files changed, 279 insertions(+), 228 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/isis/blob/f9a0b43a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/internal/SwaggerSpecGenerator.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/internal/SwaggerSpecGenerator.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/internal/SwaggerSpecGenerator.java
index fb40928..07673d3 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/internal/SwaggerSpecGenerator.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/internal/SwaggerSpecGenerator.java
@@ -70,32 +70,91 @@ public class SwaggerSpecGenerator {
swagger.basePath("/restful");
swagger.info(new Info()
.version("1.0.0")
- .title("Restful Objects"))
- .path("/",
- new Path()
- .get(new Operation()
- .description(roSpec("5.1"))
- .produces("application/json")
- .produces("application/json;profile=urn:org.restfulobjects:repr-types/home-page")
- .response(200,
- newResponse(Caching.NON_EXPIRING)
- .description("OK")
- .schema(new RefProperty("#/definitions/home-page"))
- )))
+ .title("Restful Objects"));
+
+ appendBoilerplate(swagger);
+ appendLinkDefinitions(swagger);
+
+ final Collection<ObjectSpecification> allSpecs = specificationLoader.allSpecifications();
+ for (ObjectSpecification serviceSpec : allSpecs) {
+ final DomainServiceFacet domainServiceFacet = serviceSpec.getFacet(DomainServiceFacet.class);
+ if (domainServiceFacet == null) {
+ continue;
+ }
+ if (!isVisible(visibility, domainServiceFacet)) {
+ continue;
+ }
+
+ List<ActionType> actionTypes = actionTypesFor(visibility);
+ List<ObjectAction> serviceActions = serviceSpec.getObjectActions(
+ actionTypes, Contributed.EXCLUDED, Filters.<ObjectAction>any());
+ if(serviceActions.isEmpty()) {
+ continue;
+ }
+
+ final String serviceId = serviceIdFor(serviceSpec);
+
+ final ObjectProperty serviceMembers = appendServicePath(swagger, serviceId);
+
+ for (final ObjectAction serviceAction : serviceActions) {
+ appendActionTo(serviceMembers, serviceAction);
+
+ if(false) {
+ appendPromptPaths(swagger, serviceAction);
+ }
+
+ appendInvokePath(swagger, serviceAction);
+ }
+ }
+
+ switch (format) {
+ case JSON:
+ return Json.pretty(swagger);
+ case YAML:
+ try {
+ return Yaml.pretty().writeValueAsString(swagger);
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException(e);
+ }
+ default:
+ throw new IllegalArgumentException("Unrecognized format: " + format);
+ }
+ }
+
+ void appendBoilerplate(final Swagger swagger) {
+ appendBoilerplatePaths(swagger);
+ appendBoilerplateDefinitions(swagger);
+ }
+
+ void appendBoilerplatePaths(final Swagger swagger) {
+ swagger.path("/",
+ new Path()
+ .get(new Operation()
+ .tag("boilerplate")
+ .description(roSpec("5.1"))
+ .produces("application/json")
+ .produces("application/json;profile=urn:org.restfulobjects:repr-types/home-page")
+ .response(200,
+ newResponse(Caching.NON_EXPIRING)
+ .description("OK")
+ .schema(new RefProperty("#/definitions/home-page"))
+ )))
.path("/user",
new Path()
- .get(new Operation()
- .description(roSpec("6.1"))
- .produces("application/json")
- .produces("application/json;profile=urn:org.restfulobjects:repr-types/user")
- .response(200,
- newResponse(Caching.USER_INFO)
- .description("OK")
- .schema(new RefProperty("#/definitions/user"))
- )))
+ .get(new Operation()
+ .tag("boilerplate")
+ .description(roSpec("6.1"))
+ .produces("application/json")
+ .produces("application/json;profile=urn:org.restfulobjects:repr-types/user")
+ .response(200,
+ newResponse(Caching.USER_INFO)
+ .description("OK")
+ .schema(new RefProperty("#/definitions/user"))
+ )))
.path("/services",
new Path()
.get(new Operation()
+ .tag("boilerplate")
.description(roSpec("7.1"))
.produces("application/json")
.produces("application/json;profile=urn:org.restfulobjects:repr-types/services")
@@ -107,50 +166,56 @@ public class SwaggerSpecGenerator {
.path("/version",
new Path()
- .get(new Operation()
- .description(roSpec("8.1"))
- .produces("application/json")
- .produces("application/json;profile=urn:org.restfulobjects:repr-types/version")
- .response(200,
- newResponse(Caching.NON_EXPIRING)
- .description("OK")
- .schema(new RefProperty("#/definitions/version"))
- )));
+ .get(new Operation()
+ .tag("boilerplate")
+ .description(roSpec("8.1"))
+ .produces("application/json")
+ .produces("application/json;profile=urn:org.restfulobjects:repr-types/version")
+ .response(200,
+ newResponse(Caching.NON_EXPIRING)
+ .description("OK")
+ .schema(new RefProperty("#/definitions/version"))
+ )));
+ }
+ void appendBoilerplateDefinitions(final Swagger swagger) {
swagger.addDefinition("home-page",
newModel(roSpec("5.2")));
swagger.addDefinition("user",
newModel(roSpec("6.2"))
- .property("userName", stringProperty())
- .property("roles", arrayOfStrings())
- .property("links", arrayOfLinksGetOnly())
- .required("userName")
- .required("roles")
- );
+ .property("userName", stringProperty())
+ .property("roles", arrayOfStrings())
+ .property("links", arrayOfLinksGetOnly())
+ .required("userName")
+ .required("roles")
+ );
swagger.addDefinition("services",
newModel(roSpec("7.2"))
- .property("value", arrayOfLinksGetOnly())
- .required("userName")
- .required("roles")
- );
+ .property("value", arrayOfLinksGetOnly())
+ .required("userName")
+ .required("roles")
+ );
swagger.addDefinition("version",
newModel(roSpec("8.2"))
- .property("specVersion", stringProperty())
- .property("implVersion", stringProperty())
- .property("optionalCapabilities",
- new ObjectProperty()
- .property("blobsClobs", stringProperty())
- .property("deleteObjects", stringProperty())
- .property("domainModel", stringProperty())
- .property("validateOnly", stringProperty())
- .property("protoPersistentObjects", stringProperty())
- )
- .required("userName")
- .required("roles")
- );
+ .property("specVersion", stringProperty())
+ .property("implVersion", stringProperty())
+ .property("optionalCapabilities",
+ new ObjectProperty()
+ .property("blobsClobs", stringProperty())
+ .property("deleteObjects", stringProperty())
+ .property("domainModel", stringProperty())
+ .property("validateOnly", stringProperty())
+ .property("protoPersistentObjects", stringProperty())
+ )
+ .required("userName")
+ .required("roles")
+ );
+ }
+
+ void appendLinkDefinitions(final Swagger swagger) {
swagger.addDefinition("link",
new ModelImpl()
@@ -178,195 +243,192 @@ public class SwaggerSpecGenerator {
.required("href")
.required("method")
);
+ }
+ void appendActionTo(final ObjectProperty serviceMembers, final ObjectAction serviceAction) {
+ String serviceActionId = serviceAction.getId();
+
+ // within the services representation itself
+ serviceMembers.property(serviceActionId,
+ new ObjectProperty()
+ .property("id", stringPropertyEnum(serviceActionId))
+ .property("memberType", stringPropertyEnum("action"))
+ .property("links",
+ new ObjectProperty()
+ .property("rel", stringPropertyEnum( String.format(
+ "urn:org.restfulobjects:rels/details;action=%s", serviceActionId)))
+ .property("href", stringPropertyEnum(String.format(
+ "actions/%s", serviceActionId))))
+ .property("method", stringPropertyEnum("GET"))
+ .property("type", stringPropertyEnum(
+ "application/json;profile=urn:org.restfulobjects:repr-types/object-action"))
+ );
+ }
- final Collection<ObjectSpecification> allSpecs = specificationLoader.allSpecifications();
- for (ObjectSpecification serviceSpec : allSpecs) {
- final DomainServiceFacet domainServiceFacet = serviceSpec.getFacet(DomainServiceFacet.class);
- if (domainServiceFacet == null) {
- continue;
- }
- if (!isVisible(visibility, domainServiceFacet)) {
- continue;
- }
-
- List<ObjectAction> serviceActions = serviceSpec
- .getObjectActions(actionTypesFor(visibility), Contributed.EXCLUDED, Filters.<ObjectAction>any());
- if(serviceActions.isEmpty()) {
- continue;
- }
+ ObjectProperty appendServicePath(
+ final Swagger swagger,
+ final String serviceId) {
- String serviceId = serviceIdFor(serviceSpec);
- final String serviceDefinitionId = "service-" + serviceId;
+ final String serviceDefinitionId = "service-" + serviceId;
+ final String servicePathStr = "/services/" + serviceId;
- final Path servicePath = new Path();
- final String servicePathStr = "/services/" + serviceId;
- swagger.path(servicePathStr, servicePath);
+ final Path servicePath = new Path();
+ swagger.path(servicePathStr, servicePath);
- servicePath.get(
- new Operation()
+ servicePath.get(
+ new Operation()
+ .tag(serviceId)
.description(roSpec("15.1"))
.produces("application/json")
.produces("application/json;profile=urn:org.restfulobjects:repr-types/object")
.response(200,
newResponse(Caching.TRANSACTIONAL)
- .description("OK")
- .schema(new RefProperty("#/definitions/"
- + serviceDefinitionId)))
- );
+ .description("OK")
+ .schema(new RefProperty("#/definitions/"
+ + serviceDefinitionId)))
+ );
- final ObjectProperty serviceMembers = new ObjectProperty();
- ModelImpl serviceRepr =
- newModel(roSpec("15.1.2") + ": representation of " + serviceId)
- .property("title", stringProperty())
- .property("serviceId", stringProperty()._default(serviceId))
- .property("members", serviceMembers);
+ final ObjectProperty serviceMembers = new ObjectProperty();
+ ModelImpl serviceRepr =
+ newModel(roSpec("15.1.2") + ": representation of " + serviceId)
+ .property("title", stringProperty())
+ .property("serviceId", stringProperty()._default(serviceId))
+ .property("members", serviceMembers);
- swagger.addDefinition(serviceDefinitionId, serviceRepr);
+ swagger.addDefinition(serviceDefinitionId, serviceRepr);
+ return serviceMembers;
+ }
- for (final ObjectAction serviceAction : serviceActions) {
- String serviceActionId = serviceAction.getId();
-
- // within the services representation itself
- final String serviceActionPromptPathRelStr = "actions/" + serviceActionId;
- serviceMembers.property(serviceActionId,
- new ObjectProperty()
- .property("id", stringPropertyEnum(serviceActionId))
- .property("memberType", stringPropertyEnum("action"))
- .property("links",
- new ObjectProperty()
- .property("rel", stringPropertyEnum("urn:org.restfulobjects:rels/details;action=" + serviceActionId + ""))
- .property("href", stringPropertyEnum(serviceActionPromptPathRelStr)))
- .property("method", stringPropertyEnum("GET"))
- .property("type", stringPropertyEnum("application/json;profile=urn:org.restfulobjects:repr-types/object-action"))
- );
+ void appendPromptPaths(
+ final Swagger swagger,
+ final ObjectAction serviceAction) {
+
+ final ObjectSpecification serviceSpec = serviceAction.getOnType();
+ final String serviceId = serviceIdFor(serviceSpec);
+ final String servicePathStr = "/services/" + serviceId;
+ final String serviceActionId = serviceAction.getId();
+ final String serviceActionPromptPathRelStr = "actions/" + serviceActionId;
+
+ final ObjectProperty actionParametersRepr = new ObjectProperty();
+ swagger.path(servicePathStr + "/" + serviceActionPromptPathRelStr,
+ new Path()
+ .get(
+ new Operation()
+ .tag(serviceId)
+ .description(roSpec("18.1") + ": (prompt) resource for " + serviceId + "#" + serviceActionId)
+ .produces("application/json")
+ .produces("application/json;profile=urn:org.restfulobjects:repr-types/object-action")
+ .response(200,
+ new Response()
+ .description(roSpec("18.2") + ": (prompt) representation of " + serviceId + "#" + serviceActionId)
+ .schema(new ObjectProperty()
+ .property("id",
+ stringPropertyEnum(serviceActionId))
+ .property("memberType",
+ stringPropertyEnum("action"))
+ .property("links", arrayOfLinksGetOnly())
+ .property("parameters", actionParametersRepr)
+ ))));
+ final List<ObjectActionParameter> parameters = serviceAction.getParameters();
+
+ int i = 0;
+ for (final ObjectActionParameter parameter : parameters) {
+ final String parameterId = parameter.getId();
+ actionParametersRepr.property(parameterId,
+ new ObjectProperty()
+ .property("num", new IntegerProperty()._default(i++))
+ .property("id", stringPropertyEnum(parameterId))
+ .property("name", stringPropertyEnum(parameter.getName()))
+ .property("description", stringPropertyEnum(parameter.getDescription()))
+ );
+ }
+ }
- // and for the service action's own resources (prompt and invoke)
- final ObjectProperty actionParametersRepr = new ObjectProperty();
- swagger.path(servicePathStr + "/" + serviceActionPromptPathRelStr,
- new Path()
- .get(
- new Operation()
- .description(roSpec("18.1") + ": (prompt) resource for " + serviceId + "#" + serviceActionId)
- .produces("application/json")
- .produces("application/json;profile=urn:org.restfulobjects:repr-types/object-action")
- .response(200,
- new Response()
- .description(roSpec("18.2") + ": (prompt) representation of " + serviceId + "#" + serviceActionId)
- .schema(new ObjectProperty()
- .property("id",
- stringPropertyEnum(serviceActionId))
- .property("memberType",
- stringPropertyEnum("action"))
- .property("links", arrayOfLinksGetOnly())
- .property("parameters", actionParametersRepr)
- ))));
- final List<ObjectActionParameter> parameters = serviceAction.getParameters();
-
- int i = 0;
- for (final ObjectActionParameter parameter : parameters) {
- final String parameterId = parameter.getId();
- actionParametersRepr.property(parameterId,
- new ObjectProperty()
- .property("num", new IntegerProperty()._default(i++))
- .property("id", stringPropertyEnum(parameterId))
- .property("name", stringPropertyEnum(parameter.getName()))
- .property("description", stringPropertyEnum(parameter.getDescription()))
- );
- }
+ void appendInvokePath(
+ final Swagger swagger,
+ final ObjectAction serviceAction) {
- // invoke path
- final Path serviceActionInvokePath = new Path();
- swagger.path( servicePathStr + "/" + serviceActionPromptPathRelStr + "/invoke", serviceActionInvokePath);
-
- final Operation invokeOperation =
- new Operation()
- .description(roSpec("19.1") + ": (invoke) resource of " + serviceId + "#" + serviceActionId)
- .produces("application/json")
- .produces("application/json;profile=urn:org.restfulobjects:repr-types/action-result")
- .produces("application/json;profile=urn:org.apache.isis/v1")
- .produces("application/json;profile=urn:org.apache.isis/v1;suppress=true");
-
- final ActionSemantics.Of semantics = serviceAction.getSemantics();
- if(semantics.isSafeInNature()) {
- serviceActionInvokePath.get(invokeOperation);
-
- for (final ObjectActionParameter parameter : parameters) {
- invokeOperation
- .parameter(
- new QueryParameter()
- .name(parameter.getId())
- .description(roSpec("2.9.1") + (!Strings.isNullOrEmpty(parameter.getDescription())? (": " + parameter.getDescription()) : ""))
- .required(false)
- .type("string")
- );
- }
- if(!parameters.isEmpty()) {
- invokeOperation.parameter(new QueryParameter()
- .name("x-isis-querystring")
- .description(roSpec("2.10") + ": all (formal) arguments as base64 encoded string")
- .required(false)
- .type("string"));
- }
-
- } else {
- if (semantics.isIdempotentInNature()) {
- serviceActionInvokePath.put(invokeOperation);
- } else {
- serviceActionInvokePath.post(invokeOperation);
- }
-
- final ModelImpl bodyParam =
- new ModelImpl()
- .type("object");
- for (final ObjectActionParameter parameter : parameters) {
-
- final Property valueProperty;
- // TODO: need to switch on parameter's type and create appopriate impl of valueProperty
- // if(parameter.getSpecification().isValue()) ...
- valueProperty = stringProperty();
-
- bodyParam
- .property(parameter.getId(),
- new ObjectProperty()
- .property("value", valueProperty)
- );
- }
-
- invokeOperation
- .consumes("application/json")
- .parameter(
- new BodyParameter()
- .name("body")
- .schema(bodyParam));
+ final ObjectSpecification serviceSpec = serviceAction.getOnType();
+ final String serviceId = serviceIdFor(serviceSpec);
+ final String serviceActionId = serviceAction.getId();
- }
+ final List<ObjectActionParameter> parameters = serviceAction.getParameters();
+ final Path serviceActionInvokePath = new Path();
+ swagger.path(String.format("/services/%s/actions/%s/invoke", serviceId, serviceActionId), serviceActionInvokePath);
+ final Operation invokeOperation =
+ new Operation()
+ .tag(serviceId)
+ .description(roSpec("19.1") + ": (invoke) resource of " + serviceId + "#" + serviceActionId)
+ .produces("application/json")
+ .produces("application/json;profile=urn:org.restfulobjects:repr-types/action-result")
+ .produces("application/json;profile=urn:org.apache.isis/v1")
+ .produces("application/json;profile=urn:org.apache.isis/v1;suppress=true");
+
+ final ActionSemantics.Of semantics = serviceAction.getSemantics();
+ if(semantics.isSafeInNature()) {
+ serviceActionInvokePath.get(invokeOperation);
+ for (final ObjectActionParameter parameter : parameters) {
invokeOperation
- .response(
- 200, new Response()
- .description(roSpecForResponseOf(serviceAction) + ": (invoke) representation of " + serviceId + "#" + serviceActionId)
- .schema(new ObjectProperty())
+ .parameter(
+ new QueryParameter()
+ .name(parameter.getId())
+ .description(roSpec("2.9.1") + (!Strings.isNullOrEmpty(parameter.getDescription())? (": " + parameter.getDescription()) : ""))
+ .required(false)
+ .type("string")
);
}
+ if(!parameters.isEmpty()) {
+ invokeOperation.parameter(new QueryParameter()
+ .name("x-isis-querystring")
+ .description(roSpec("2.10") + ": all (formal) arguments as base64 encoded string")
+ .required(false)
+ .type("string"));
+ }
- }
+ } else {
+ if (semantics.isIdempotentInNature()) {
+ serviceActionInvokePath.put(invokeOperation);
+ } else {
+ serviceActionInvokePath.post(invokeOperation);
+ }
+
+ final ModelImpl bodyParam =
+ new ModelImpl()
+ .type("object");
+ for (final ObjectActionParameter parameter : parameters) {
+
+ final Property valueProperty;
+ // TODO: need to switch on parameter's type and create appopriate impl of valueProperty
+ // if(parameter.getSpecification().isValue()) ...
+ valueProperty = stringProperty();
+
+ bodyParam
+ .property(parameter.getId(),
+ new ObjectProperty()
+ .property("value", valueProperty)
+ );
+ }
+
+ invokeOperation
+ .consumes("application/json")
+ .parameter(
+ new BodyParameter()
+ .name("body")
+ .schema(bodyParam));
- switch (format) {
- case JSON:
- return Json.pretty(swagger);
- case YAML:
- try {
- return Yaml.pretty().writeValueAsString(swagger);
- } catch (JsonProcessingException e) {
- throw new RuntimeException(e);
- }
- default:
- throw new IllegalArgumentException("Unrecognized format: " + format);
}
+
+ invokeOperation
+ .response(
+ 200, new Response()
+ .description(roSpecForResponseOf(serviceAction) + ": (invoke) representation of " + serviceId + "#" + serviceActionId)
+ .schema(new ObjectProperty())
+ );
}
+
private String roSpecForResponseOf(final ObjectAction action) {
final ActionSemantics.Of semantics = action.getSemantics();
switch (semantics) {
http://git-wip-us.apache.org/repos/asf/isis/blob/f9a0b43a/example/application/simpleapp/webapp/src/main/webapp/api-docs/index.html
----------------------------------------------------------------------
diff --git a/example/application/simpleapp/webapp/src/main/webapp/api-docs/index.html b/example/application/simpleapp/webapp/src/main/webapp/api-docs/index.html
index d7e3f47..7ecbcb1 100644
--- a/example/application/simpleapp/webapp/src/main/webapp/api-docs/index.html
+++ b/example/application/simpleapp/webapp/src/main/webapp/api-docs/index.html
@@ -30,14 +30,6 @@
<script type="text/javascript">
$(function () {
- /*
- var url = window.location.search.match(/url=([^&]+)/);
- if (url && url.length > 1) {
- url = decodeURIComponent(url[1]);
- } else {
- url = "/restful/swagger/private"
- }
- */
var url = document.getElementById("input_baseUrl").selectedOptions[0].value;
// Pre load translate...
@@ -113,13 +105,10 @@
<form id='api_selector'>
<div class='input'>
<select id="input_baseUrl" name="baseUrl">
- <option id="public" label="public" value="/restful/swagger/public"/>
<option id="private" label="private" value="/restful/swagger/private"/>
+ <option id="public" label="public" value="/restful/swagger/public"/>
<option id="prototyping" label="prototyping" value="/restful/swagger/prototyping"/>
</select>
-<!--
- <input placeholder="http://example.com/api" id="input_baseUrl" name="baseUrl" type="text" value="/restful/swagger/public">
--->
</div>
<div class='input' style="display:none;"><input placeholder="api_key" id="input_apiKey" name="apiKey" type="text"/></div>
<div class='input'><a id="explore" href="#" data-sw-translate>Explore</a></div>