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:16 UTC
[08/11] isis git commit: ISIS-1237: renamed api-docs/index.html to
swagger-ui/index.htm; updated about/index.html;
refactoring and extending the main service
ISIS-1237: renamed api-docs/index.html to swagger-ui/index.htm; updated about/index.html; refactoring and extending the main service
Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/3d9f8fe0
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/3d9f8fe0
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/3d9f8fe0
Branch: refs/heads/master
Commit: 3d9f8fe035822d8cb0ad81bca1b5d7538fbdcb76
Parents: 53ead49
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Thu Dec 10 14:30:24 2015 +0000
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Thu Dec 10 14:30:24 2015 +0000
----------------------------------------------------------------------
.../isis/applib/annotation/NatureOfService.java | 22 +-
.../services/i18n/TranslatableString.java | 1 +
.../services/swagger/SwaggerServiceDefault.java | 24 +-
.../services/swagger/internal/Caching.java | 48 ++
.../swagger/internal/SwaggerSpecGenerator.java | 472 ++++++++---------
.../services/swagger/internal/Util.java | 164 ++++++
.../services/swagger/internal/example.json | 515 -------------------
.../webapp/src/main/webapp/about/index.html | 13 +-
.../webapp/src/main/webapp/api-docs/index.html | 122 -----
.../src/main/webapp/swagger-ui/index.html | 122 +++++
10 files changed, 592 insertions(+), 911 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/isis/blob/3d9f8fe0/core/applib/src/main/java/org/apache/isis/applib/annotation/NatureOfService.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/NatureOfService.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/NatureOfService.java
index b37c2bc..0502d80 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/NatureOfService.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/NatureOfService.java
@@ -56,6 +56,26 @@ public enum NatureOfService {
* Equivalent to annotating all actions with both (the now deprecated) {@link org.apache.isis.applib.annotation.NotInServiceMenu} and {@link org.apache.isis.applib.annotation.NotContributed} annotations).
* </p>
*/
- DOMAIN
+ DOMAIN;
+
+ boolean isViewRestOnly() {
+ return this == VIEW_REST_ONLY;
+ }
+ boolean isView() {
+ return this == VIEW;
+ }
+ boolean isViewMenuOnly() {
+ return this == VIEW_MENU_ONLY;
+ }
+ boolean isViewContributionsOnly() {
+ return this == VIEW_CONTRIBUTIONS_ONLY;
+ }
+ boolean isDomain() {
+ return this == DOMAIN;
+ }
+
+ boolean isViewOrViewMenuOnly() {
+ return isView() || isViewMenuOnly();
+ }
}
http://git-wip-us.apache.org/repos/asf/isis/blob/3d9f8fe0/core/applib/src/main/java/org/apache/isis/applib/services/i18n/TranslatableString.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/i18n/TranslatableString.java b/core/applib/src/main/java/org/apache/isis/applib/services/i18n/TranslatableString.java
index 5509eb5..515a2b7 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/i18n/TranslatableString.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/i18n/TranslatableString.java
@@ -200,6 +200,7 @@ public final class TranslatableString {
* {@link Exception#getMessage() message} when only a translatable message has been provided.
* </p>
*/
+ @Programmatic
public String getPattern() {
return !isPluralForm() || number == 1 ? getSingularText() : getPluralText();
}
http://git-wip-us.apache.org/repos/asf/isis/blob/3d9f8fe0/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/SwaggerServiceDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/SwaggerServiceDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/SwaggerServiceDefault.java
index c447788..c6ac0e8 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/SwaggerServiceDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/SwaggerServiceDefault.java
@@ -18,6 +18,10 @@
*/
package org.apache.isis.core.metamodel.services.swagger;
+import java.util.Map;
+
+import javax.annotation.PostConstruct;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -36,13 +40,31 @@ public class SwaggerServiceDefault implements SwaggerService, SpecificationLoade
@SuppressWarnings("unused")
private final static Logger LOG = LoggerFactory.getLogger(SwaggerServiceDefault.class);
+ public static final String KEY_RESTFUL_BASE_PATH = "isis.services.swagger.restfulBasePath";
+ public static final String KEY_RESTFUL_BASE_PATH_DEFAULT = "/restful";
+
+ private String basePath;
+
+ @PostConstruct
+ public void init(final Map<String,String> properties) {
+ this.basePath = getPropertyElse(properties, KEY_RESTFUL_BASE_PATH, KEY_RESTFUL_BASE_PATH_DEFAULT);
+ }
+
+ static String getPropertyElse(final Map<String, String> properties, final String key, final String dflt) {
+ String basePath = properties.get(key);
+ if(basePath == null) {
+ basePath = dflt;
+ }
+ return basePath;
+ }
+
@Override
public String generateSwaggerSpec(
final Visibility visibility,
final Format format) {
final SwaggerSpecGenerator swaggerSpecGenerator = new SwaggerSpecGenerator(specificationLoader);
- final String swaggerSpec = swaggerSpecGenerator.generate(visibility, format);
+ final String swaggerSpec = swaggerSpecGenerator.generate(basePath, visibility, format);
return swaggerSpec;
}
http://git-wip-us.apache.org/repos/asf/isis/blob/3d9f8fe0/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/internal/Caching.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/internal/Caching.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/internal/Caching.java
new file mode 100644
index 0000000..55eb624
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/internal/Caching.java
@@ -0,0 +1,48 @@
+package org.apache.isis.core.metamodel.services.swagger.internal;
+
+import io.swagger.models.Response;
+import io.swagger.models.properties.IntegerProperty;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ */
+enum Caching {
+ TRANSACTIONAL {
+ @Override public void withHeaders(final Response response) {
+
+ }
+ },
+ USER_INFO {
+ @Override public void withHeaders(final Response response) {
+ response
+ .header("Cache-Control",
+ new IntegerProperty()
+ ._default(3600));
+ }
+ },
+ NON_EXPIRING {
+ @Override public void withHeaders(final Response response) {
+ response
+ .header("Cache-Control",
+ new IntegerProperty()
+ ._default(86400).description(Util.roSpec("2.13")));
+ }
+ };
+
+ public abstract void withHeaders(final Response response);
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/3d9f8fe0/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 896d4f0..f1ca3e5 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
@@ -27,19 +27,18 @@ import com.google.common.base.Strings;
import org.apache.isis.applib.annotation.ActionSemantics;
import org.apache.isis.applib.annotation.NatureOfService;
-import org.apache.isis.applib.filter.Filters;
import org.apache.isis.applib.services.swagger.SwaggerService;
import org.apache.isis.core.commons.factory.InstanceUtil;
-import org.apache.isis.core.metamodel.facets.actcoll.typeof.TypeOfFacet;
import org.apache.isis.core.metamodel.facets.object.domainservice.DomainServiceFacet;
+import org.apache.isis.core.metamodel.facets.object.mixin.MixinFacet;
import org.apache.isis.core.metamodel.facets.object.objectspecid.ObjectSpecIdFacet;
import org.apache.isis.core.metamodel.services.ServiceUtil;
-import org.apache.isis.core.metamodel.spec.ActionType;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
import org.apache.isis.core.metamodel.spec.SpecificationLoader;
-import org.apache.isis.core.metamodel.spec.feature.Contributed;
import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
+import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
import io.swagger.models.Info;
import io.swagger.models.ModelImpl;
@@ -51,7 +50,6 @@ import io.swagger.models.parameters.BodyParameter;
import io.swagger.models.parameters.PathParameter;
import io.swagger.models.parameters.QueryParameter;
import io.swagger.models.properties.ArrayProperty;
-import io.swagger.models.properties.IntegerProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.ObjectProperty;
import io.swagger.models.properties.Property;
@@ -68,16 +66,39 @@ public class SwaggerSpecGenerator {
this.specificationLoader = specificationLoader;
}
- public String generate(final SwaggerService.Visibility visibility, final SwaggerService.Format format) {
+ public String generate(
+ final String basePath,
+ final SwaggerService.Visibility visibility,
+ final SwaggerService.Format format) {
+
final Swagger swagger = new Swagger();
- swagger.basePath("/restful");
+ swagger.basePath(basePath);
swagger.info(new Info()
- .version("1.0.0")
- .title("Restful Objects"));
+ //.version("1.0.0") // TODO: provide some way of passing the name, version etc (some sort of SPI service?)
+ .title(visibility.name() + " API")
+ );
+
+ appendRestfulObjectsSupportingPathsAndDefinitions(swagger);
+ appendLinkModelDefinition(swagger);
- appendBoilerplate(swagger);
- appendLinkDefinitions(swagger);
+ appendServicePathsAndDefinitions(swagger, visibility);
+ appendObjectPathsAndDefinitions(swagger, visibility);
+
+ 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 appendServicePathsAndDefinitions(final Swagger swagger, final SwaggerService.Visibility visibility) {
final Collection<ObjectSpecification> allSpecs = specificationLoader.allSpecifications();
for (final ObjectSpecification serviceSpec : allSpecs) {
@@ -94,146 +115,131 @@ public class SwaggerSpecGenerator {
continue;
}
- final List<ActionType> actionTypes = actionTypesFor(visibility);
- final List<ObjectAction> serviceActions = serviceSpec.getObjectActions(
- actionTypes, Contributed.EXCLUDED, Filters.<ObjectAction>any());
- if (serviceActions.isEmpty()) {
+ final List<ObjectAction> serviceActions = Util.actionsOf(serviceSpec, visibility);
+ if(serviceActions.isEmpty()) {
continue;
}
-
- final ObjectProperty serviceMembers = appendServicePath(swagger, serviceSpec);
+ appendServicePath(swagger, serviceSpec);
for (final ObjectAction serviceAction : serviceActions) {
- if (visibility.isPublic() && !isVisibleForPublic(serviceAction)) {
- continue;
- }
- appendActionTo(serviceMembers, serviceAction);
appendServiceActionInvokePath(swagger, serviceAction);
}
}
+ }
+ void appendObjectPathsAndDefinitions(final Swagger swagger, final SwaggerService.Visibility visibility) {
+ final Collection<ObjectSpecification> allSpecs = specificationLoader.allSpecifications();
for (final ObjectSpecification objectSpec : allSpecs) {
final DomainServiceFacet domainServiceFacet = objectSpec.getFacet(DomainServiceFacet.class);
if (domainServiceFacet != null) {
continue;
}
-
+ final MixinFacet mixinFacet = objectSpec.getFacet(MixinFacet.class);
+ if (mixinFacet != null) {
+ continue;
+ }
+ if(visibility.isPublic() && !Util.isVisibleForPublic(objectSpec)) {
+ continue;
+ }
if(objectSpec.isAbstract()) {
continue;
}
+ if(objectSpec.isValue()) {
+ continue;
+ }
+
+ final List<OneToOneAssociation> objectProperties = Util.propertiesOf(objectSpec, visibility);
+ final List<OneToManyAssociation> objectCollections = Util.collectionsOf(objectSpec, visibility);
+ final List<ObjectAction> objectActions = Util.actionsOf(objectSpec, visibility);
- final List<ActionType> actionTypes = actionTypesFor(visibility);
- final List<ObjectAction> objectActions = objectSpec.getObjectActions(
- actionTypes, Contributed.INCLUDED, Filters.<ObjectAction>any());
- if (objectActions.isEmpty()) {
+ if(objectProperties.isEmpty() && objectCollections.isEmpty()) {
continue;
}
+ final ModelImpl isisModel = appendObjectPathAndModelDefinitions(swagger, objectSpec);
+ appendObjectModel(isisModel, objectProperties, objectCollections);
- final ObjectProperty objectMembers = appendObjectPath(swagger, objectSpec);
+ for (final OneToManyAssociation objectCollection : objectCollections) {
+ appendCollectionTo(swagger, objectCollection);
+ }
for (final ObjectAction objectAction : objectActions) {
- if (visibility.isPublic() && !isVisibleForPublic(objectAction)) {
- continue;
- }
- appendActionTo(objectMembers, objectAction);
appendObjectActionInvokePath(swagger, objectAction);
}
}
-
- 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 appendRestfulObjectsSupportingPathsAndDefinitions(final Swagger swagger) {
+
+ final String tag = "> restful objects supporting resources";
- void appendBoilerplatePaths(final Swagger swagger) {
swagger.path("/",
new Path()
.get(new Operation()
- .tag("boilerplate")
- .description(roSpec("5.1"))
+ .tag(tag)
+ .description(Util.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()
- .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",
+ .schema(new RefProperty("#/definitions/RestfulObjectsSupportingHomePageModel"))
+ )));
+ swagger.addDefinition("RestfulObjectsSupportingHomePageModel",
+ newModel(Util.roSpec("5.2")));
+
+ swagger.path("/user",
+ new Path()
+ .get(new Operation()
+ .tag(tag)
+ .description(Util.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/RestfulObjectsSupportingUserModel"))
+ )));
+ swagger.addDefinition("RestfulObjectsSupportingUserModel",
+ newModel(Util.roSpec("6.2"))
+ .property("userName", stringProperty())
+ .property("roles", arrayOfStrings())
+ .property("links", arrayOfLinks())
+ .required("userName")
+ .required("roles"));
+
+ swagger.path("/services",
new Path()
.get(new Operation()
- .tag("boilerplate")
- .description(roSpec("7.1"))
+ .tag(tag)
+ .description(Util.roSpec("7.1"))
.produces("application/json")
.produces("application/json;profile=urn:org.restfulobjects:repr-types/services")
.response(200,
newResponse(Caching.USER_INFO)
.description("OK")
- .schema(new RefProperty("#/definitions/services"))
- )))
+ .schema(new RefProperty("#/definitions/RestfulObjectsSupportingServicesModel"))
+ )));
+ swagger.addDefinition("RestfulObjectsSupportingServicesModel",
+ newModel(Util.roSpec("7.2"))
+ .property("value", arrayOfLinks())
+ .required("userName")
+ .required("roles"));
- .path("/version",
+ swagger.path("/version",
new Path()
.get(new Operation()
- .tag("boilerplate")
- .description(roSpec("8.1"))
+ .tag(tag)
+ .description(Util.roSpec("8.1"))
.produces("application/json")
- .produces("application/json;profile=urn:org.restfulobjects:repr-types/version")
+ .produces("application/json;profile=urn:org.restfulobjects:repr-types/RestfulObjectsSupportingServicesModel")
.response(200,
newResponse(Caching.NON_EXPIRING)
.description("OK")
- .schema(new RefProperty("#/definitions/version"))
+ .schema(new ObjectProperty())
)));
- }
-
- 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")
- );
-
- swagger.addDefinition("services",
- newModel(roSpec("7.2"))
- .property("value", arrayOfLinksGetOnly())
- .required("userName")
- .required("roles")
- );
-
- swagger.addDefinition("version",
- newModel(roSpec("8.2"))
+ swagger.addDefinition("RestfulObjectsSupportingServicesModel",
+ newModel(Util.roSpec("8.2"))
.property("specVersion", stringProperty())
.property("implVersion", stringProperty())
.property("optionalCapabilities",
@@ -245,13 +251,11 @@ public class SwaggerSpecGenerator {
.property("protoPersistentObjects", stringProperty())
)
.required("userName")
- .required("roles")
- );
+ .required("roles"));
}
- void appendLinkDefinitions(final Swagger swagger) {
-
- swagger.addDefinition("link",
+ void appendLinkModelDefinition(final Swagger swagger) {
+ swagger.addDefinition("LinkModel",
new ModelImpl()
.type("object")
.property("rel", stringProperty())
@@ -265,105 +269,109 @@ public class SwaggerSpecGenerator {
.required("method")
);
- swagger.addDefinition("link-get-only",
- new ModelImpl()
- .type("object")
- .property("rel", stringProperty())
- .property("href", stringProperty())
- .property("title", stringProperty())
- .property("method", stringPropertyEnum("GET"))
- .property("type", stringProperty())
- .required("rel")
- .required("href")
- .required("method")
- );
}
- ObjectProperty appendServicePath(final Swagger swagger, final ObjectSpecification objectSpec) {
+ void appendServicePath(final Swagger swagger, final ObjectSpecification objectSpec) {
final String serviceId = serviceIdFor(objectSpec);
final Path path = new Path();
swagger.path(String.format("/services/%s", serviceId), path);
+ final String serviceModelDefinition = serviceId + "Model";
path.get(
new Operation()
.tag(serviceId)
- .description(roSpec("15.1"))
+ .description(Util.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/service-" + serviceId)))
+ .schema(new RefProperty("#/definitions/" + serviceModelDefinition)))
);
- final ObjectProperty serviceMembers = new ObjectProperty();
- final ModelImpl serviceRepr =
- newModel(roSpec("15.1.2") + ": representation of " + serviceId)
+ final ModelImpl model =
+ newModel(Util.roSpec("15.1.2") + ": representation of " + serviceId)
.property("title", stringProperty())
.property("serviceId", stringProperty()._default(serviceId))
- .property("members", serviceMembers);
+ .property("members", new ObjectProperty());
- swagger.addDefinition("service-" + serviceId, serviceRepr);
- return serviceMembers;
+ swagger.addDefinition(serviceModelDefinition, model);
}
- ObjectProperty appendObjectPath(final Swagger swagger, final ObjectSpecification objectSpec) {
+ ModelImpl appendObjectPathAndModelDefinitions(final Swagger swagger, final ObjectSpecification objectSpec) {
final String objectType = objectTypeFor(objectSpec);
final Path path = new Path();
swagger.path(String.format("/objects/%s/{objectId}", objectType), path);
+ final String isisModelDefinition = objectType + "Model";
+ final String restfulObjectsModelDefinition = objectType + "RestfulObjectsModel";
+ final String tag = objectType.startsWith("org.apache.isis")? "> apache isis internals": objectType;
+ final Operation operation = new Operation();
path.get(
- new Operation()
- .tag(objectType)
- .description(roSpec("14.1"))
- .parameter(
- new PathParameter()
- .name("objectId")
- .type("string"))
- .produces("application/json")
- .produces("application/json;profile=urn:org.restfulobjects:repr-types/object")
- .produces("application/json;profile=urn:org.apache.isis/v1")
- .produces("application/json;profile=urn:org.apache.isis/v1;suppress=true")
- .response(200,
- newResponse(Caching.TRANSACTIONAL)
- .description("OK")
- .schema(new RefProperty("#/definitions/object-" + objectType)))
- );
+ operation);
+ operation
+ .tag(tag)
+ .description(Util.roSpec("14.1"))
+ .parameter(
+ new PathParameter()
+ .name("objectId")
+ .type("string"))
+ .produces("application/json;profile=urn:org.apache.isis/v1")
+ .produces("application/json;profile=urn:org.apache.isis/v1;suppress=true")
+ .produces("application/json;profile=urn:org.restfulobjects:repr-types/object");
+
+
+ // per https://github.com/swagger-api/swagger-spec/issues/146, swagger 2.0 doesn't support multiple
+ // modelled representations per path and response code;
+ // in particular cannot associate representation/model with Accept header ('produces(...) method)
+ if (false) {
+ operation.response(200,
+ newResponse(Caching.TRANSACTIONAL)
+ .description("if Accept: application/json;profile=urn:org.restfulobjects:repr-types/object")
+ .schema(new RefProperty("#/definitions/" + restfulObjectsModelDefinition)));
+
+ final ModelImpl roSpecModel =
+ newModel(Util.roSpec("14.4") + ": representation of " + objectType)
+ .property("title", stringProperty())
+ .property("domainType", stringProperty()._default(objectType))
+ .property("instanceId", stringProperty())
+ .property("members", new ObjectProperty());
+ swagger.addDefinition(restfulObjectsModelDefinition, roSpecModel);
+ }
- final ObjectProperty serviceMembers = new ObjectProperty();
- final ModelImpl serviceRepr =
- newModel(roSpec("14.4") + ": representation of " + objectType)
- .property("title", stringProperty())
- .property("domainType", stringProperty()._default(objectType))
- .property("instanceId", stringProperty())
- .property("members", serviceMembers);
+ operation
+ .response(200,
+ newResponse(Caching.TRANSACTIONAL)
+ .description("if Accept: application/json;profile=urn:org.apache.isis/v1")
+ .schema(new RefProperty("#/definitions/"
+ + isisModelDefinition)));
- swagger.addDefinition("object-" + objectType, serviceRepr);
- return serviceMembers;
- }
- private String objectTypeFor(final ObjectSpecification objectSpec) {
- return objectSpec.getFacet(ObjectSpecIdFacet.class).value().asString();
+ final ModelImpl isisModel = new ModelImpl();
+ swagger.addDefinition(isisModelDefinition, isisModel);
+
+ // return so can be appended to
+ return isisModel;
}
- void appendActionTo(final ObjectProperty serviceMembers, final ObjectAction serviceAction) {
- String serviceActionId = serviceAction.getId();
+ // UNUSED
+ void appendServiceActionPromptTo(final ObjectProperty serviceMembers, final ObjectAction action) {
+ String actionId = action.getId();
- // within the services representation itself
- serviceMembers.property(serviceActionId,
+ serviceMembers.property(actionId,
new ObjectProperty()
- .property("id", stringPropertyEnum(serviceActionId))
+ .property("id", stringPropertyEnum(actionId))
.property("memberType", stringPropertyEnum("action"))
.property("links",
new ObjectProperty()
.property("rel", stringPropertyEnum( String.format(
- "urn:org.restfulobjects:rels/details;action=%s", serviceActionId)))
+ "urn:org.restfulobjects:rels/details;action=%s", actionId)))
.property("href", stringPropertyEnum(String.format(
- "actions/%s", serviceActionId))))
+ "actions/%s", actionId))))
.property("method", stringPropertyEnum("GET"))
.property("type", stringPropertyEnum(
"application/json;profile=urn:org.restfulobjects:repr-types/object-action"))
@@ -385,11 +393,11 @@ public class SwaggerSpecGenerator {
final Operation invokeOperation =
new Operation()
.tag(serviceId)
- .description(roSpec("19.1") + ": (invoke) resource of " + serviceId + "#" + actionId)
- .produces("application/json")
- .produces("application/json;profile=urn:org.restfulobjects:repr-types/action-result")
+ .description(Util.roSpec("19.1") + ": (invoke) resource of " + serviceId + "#" + actionId)
.produces("application/json;profile=urn:org.apache.isis/v1")
- .produces("application/json;profile=urn:org.apache.isis/v1;suppress=true");
+ .produces("application/json;profile=urn:org.apache.isis/v1;suppress=true")
+ .produces("application/json;profile=urn:org.restfulobjects:repr-types/action-result")
+ ;
final ActionSemantics.Of semantics = serviceAction.getSemantics();
if(semantics.isSafeInNature()) {
@@ -400,7 +408,7 @@ public class SwaggerSpecGenerator {
.parameter(
new QueryParameter()
.name(parameter.getId())
- .description(roSpec("2.9.1") + (!Strings.isNullOrEmpty(parameter.getDescription())? (": " + parameter.getDescription()) : ""))
+ .description(Util.roSpec("2.9.1") + (!Strings.isNullOrEmpty(parameter.getDescription())? (": " + parameter.getDescription()) : ""))
.required(false)
.type("string")
);
@@ -408,7 +416,7 @@ public class SwaggerSpecGenerator {
if(!parameters.isEmpty()) {
invokeOperation.parameter(new QueryParameter()
.name("x-isis-querystring")
- .description(roSpec("2.10") + ": all (formal) arguments as base64 encoded string")
+ .description(Util.roSpec("2.10") + ": all (formal) arguments as base64 encoded string")
.required(false)
.type("string"));
}
@@ -469,15 +477,14 @@ public class SwaggerSpecGenerator {
final Operation invokeOperation =
new Operation()
.tag(objectType)
- .description(roSpec("19.1") + ": (invoke) resource of " + objectType + "#" + actionId)
+ .description(Util.roSpec("19.1") + ": (invoke) resource of " + objectType + "#" + actionId)
.parameter(
new PathParameter()
.name("objectId")
.type("string"))
- .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");
+ .produces("application/json;profile=urn:org.apache.isis/v1;suppress=true")
+ .produces("application/json;profile=urn:org.restfulobjects:repr-types/action-result");
final ActionSemantics.Of semantics = objectAction.getSemantics();
if(semantics.isSafeInNature()) {
@@ -488,7 +495,7 @@ public class SwaggerSpecGenerator {
.parameter(
new QueryParameter()
.name(parameter.getId())
- .description(roSpec("2.9.1") + (!Strings.isNullOrEmpty(parameter.getDescription())? (": " + parameter.getDescription()) : ""))
+ .description(Util.roSpec("2.9.1") + (!Strings.isNullOrEmpty(parameter.getDescription())? (": " + parameter.getDescription()) : ""))
.required(false)
.type("string")
);
@@ -496,7 +503,7 @@ public class SwaggerSpecGenerator {
if(!parameters.isEmpty()) {
invokeOperation.parameter(new QueryParameter()
.name("x-isis-querystring")
- .description(roSpec("2.10") + ": all (formal) arguments as base64 encoded string")
+ .description(Util.roSpec("2.10") + ": all (formal) arguments as base64 encoded string")
.required(false)
.type("string"));
}
@@ -542,8 +549,17 @@ public class SwaggerSpecGenerator {
);
}
+ void appendCollectionTo(final Swagger members, final OneToManyAssociation serviceAction) {
- private String roSpecForResponseOf(final ObjectAction action) {
+ }
+
+ void appendObjectModel(
+ final ModelImpl swagger,
+ final List<OneToOneAssociation> objectProperties, final List<OneToManyAssociation> objectCollections) {
+
+ }
+
+ static String roSpecForResponseOf(final ObjectAction action) {
final ActionSemantics.Of semantics = action.getSemantics();
switch (semantics) {
case SAFE_AND_REQUEST_CACHEABLE:
@@ -557,62 +573,31 @@ public class SwaggerSpecGenerator {
}
}
- private boolean isVisibleForPublic(final ObjectAction objectAction) {
- final ObjectSpecification specification = objectAction.getReturnType();
- boolean visible = isVisibleForPublic(specification);
- if(!visible) {
- return false;
- }
- List<ObjectSpecification> parameterTypes = objectAction.getParameterTypes();
- for (ObjectSpecification parameterType : parameterTypes) {
- boolean paramVisible = isVisibleForPublic(parameterType);
- if(!paramVisible) {
- return false;
- }
- }
- return true;
- }
-
- private boolean isVisibleForPublic(final ObjectSpecification specification) {
- if (specification == null) {
- return true;
- }
- if(specification.isViewModel()) {
- return true;
- }
- if(specification.isValue()) {
- return true;
- }
- if(specification.isParentedOrFreeCollection()) {
- TypeOfFacet typeOfFacet = specification.getFacet(TypeOfFacet.class);
- ObjectSpecification elementSpec = typeOfFacet.valueSpec();
- return isVisibleForPublic(elementSpec);
- }
- final Class<?> correspondingClass = specification.getCorrespondingClass();
- return correspondingClass == void.class || correspondingClass == Void.class;
- }
-
- private ModelImpl newModel(final String description) {
+ static ModelImpl newModel(final String description) {
return new ModelImpl()
.description(description)
.type("object")
- .property("links", arrayOfLinksGetOnly())
+ .property("links", arrayOfLinks())
.property("extensions", new MapProperty())
.required("links")
.required("extensions");
}
// TODO: this is horrid, there ought to be a facet we can call instead...
- String serviceIdFor(final ObjectSpecification serviceSpec) {
+ static String serviceIdFor(final ObjectSpecification serviceSpec) {
Object tempServiceInstance = InstanceUtil.createInstance(serviceSpec.getCorrespondingClass());
return ServiceUtil.id(tempServiceInstance);
}
- StringProperty stringProperty() {
+ static String objectTypeFor(final ObjectSpecification objectSpec) {
+ return objectSpec.getFacet(ObjectSpecIdFacet.class).value().asString();
+ }
+
+ static StringProperty stringProperty() {
return new StringProperty();
}
- StringProperty stringPropertyEnum(String... enumValues) {
+ static StringProperty stringPropertyEnum(String... enumValues) {
StringProperty stringProperty = stringProperty();
stringProperty._enum(Arrays.asList(enumValues));
if(enumValues.length >= 1) {
@@ -621,66 +606,17 @@ public class SwaggerSpecGenerator {
return stringProperty;
}
- ArrayProperty arrayOfLinksGetOnly() {
+ static ArrayProperty arrayOfLinks() {
return new ArrayProperty()
- .items(new RefProperty("#/definitions/link-get-only"));
+ .items(new RefProperty("#/definitions/LinkModel"));
}
- ArrayProperty arrayOfStrings() {
+ static ArrayProperty arrayOfStrings() {
return new ArrayProperty().items(stringProperty());
}
- private Response newResponse(final Caching caching) {
- return withCachingHeaders(new Response(), caching);
+ static Response newResponse(final Caching caching) {
+ return Util.withCachingHeaders(new Response(), caching);
}
- enum Caching {
- TRANSACTIONAL {
- @Override public void withHeaders(final Response response) {
-
- }
- },
- USER_INFO {
- @Override public void withHeaders(final Response response) {
- response
- .header("Cache-Control",
- new IntegerProperty()
- ._default(3600));
- }
- },
- NON_EXPIRING {
- @Override public void withHeaders(final Response response) {
- response
- .header("Cache-Control",
- new IntegerProperty()
- ._default(86400).description(roSpec("2.13")));
- }
- };
-
- public abstract void withHeaders(final Response response);
- }
-
- private static String roSpec(final String section) {
- return "RO Spec v1.0, section " + section;
- }
-
- private Response withCachingHeaders(final Response response, final Caching caching) {
- caching.withHeaders(response);
-
- return response;
- }
-
- private List<ActionType> actionTypesFor(final SwaggerService.Visibility visibility) {
- switch (visibility) {
- case PUBLIC:
- return Arrays.asList(ActionType.USER);
- case PRIVATE:
- return Arrays.asList(ActionType.USER);
- case PRIVATE_WITH_PROTOTYPING:
- return Arrays.asList(ActionType.USER, ActionType.EXPLORATION, ActionType.PROTOTYPE, ActionType.DEBUG);
- }
- throw new IllegalArgumentException("Unrecognized type '" + visibility + "'");
- }
-
-
}
http://git-wip-us.apache.org/repos/asf/isis/blob/3d9f8fe0/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/internal/Util.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/internal/Util.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/internal/Util.java
new file mode 100644
index 0000000..4ab66e2
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/internal/Util.java
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 org.apache.isis.core.metamodel.services.swagger.internal;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.isis.applib.filter.Filter;
+import org.apache.isis.applib.filter.Filters;
+import org.apache.isis.applib.services.swagger.SwaggerService;
+import org.apache.isis.core.metamodel.facets.actcoll.typeof.TypeOfFacet;
+import org.apache.isis.core.metamodel.spec.ActionType;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.Contributed;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+
+import io.swagger.models.Response;
+
+public final class Util {
+
+ private Util(){}
+
+ static boolean isVisibleForPublic(final ObjectAction objectAction) {
+ final ObjectSpecification specification = objectAction.getReturnType();
+ boolean visible = isVisibleForPublic(specification);
+ if(!visible) {
+ return false;
+ }
+ List<ObjectSpecification> parameterTypes = objectAction.getParameterTypes();
+ for (ObjectSpecification parameterType : parameterTypes) {
+ boolean paramVisible = isVisibleForPublic(parameterType);
+ if(!paramVisible) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ static boolean isVisibleForPublic(final ObjectAssociation objectAssociation) {
+ final ObjectSpecification specification = objectAssociation.getSpecification();
+ return isVisibleForPublic(specification);
+ }
+
+ static boolean isVisibleForPublic(final ObjectSpecification specification) {
+ if (specification == null) {
+ return true;
+ }
+ if(specification.isViewModel()) {
+ return true;
+ }
+ if(specification.isValue()) {
+ return true;
+ }
+ if(specification.isParentedOrFreeCollection()) {
+ TypeOfFacet typeOfFacet = specification.getFacet(TypeOfFacet.class);
+ if(typeOfFacet != null) {
+ ObjectSpecification elementSpec = typeOfFacet.valueSpec();
+ return isVisibleForPublic(elementSpec);
+ }
+ }
+
+ final Class<?> correspondingClass = specification.getCorrespondingClass();
+ return Collection.class.isAssignableFrom(correspondingClass) ||
+ correspondingClass.isArray() ||
+ correspondingClass == void.class ||
+ correspondingClass == Void.class;
+ }
+
+ static Filter<ObjectAssociation> associationsWith(final SwaggerService.Visibility visibility) {
+ return new Filter<ObjectAssociation>() {
+ @Override
+ public boolean accept(final ObjectAssociation objectAssociation) {
+ return !visibility.isPublic() || isVisibleForPublic(objectAssociation);
+ }
+ };
+ }
+
+ static List<OneToOneAssociation> propertiesOf(
+ final ObjectSpecification objectSpecification,
+ final SwaggerService.Visibility visibility) {
+ return associationsOf(objectSpecification, ObjectAssociation.Filters.PROPERTIES, visibility);
+ }
+
+ static List<OneToManyAssociation> collectionsOf(
+ final ObjectSpecification objectSpecification,
+ final SwaggerService.Visibility visibility) {
+ return associationsOf(objectSpecification, ObjectAssociation.Filters.COLLECTIONS, visibility);
+ }
+
+ static <T extends ObjectAssociation> List<T> associationsOf(
+ final ObjectSpecification objectSpecification,
+ final Filter<ObjectAssociation> associationFilter, final SwaggerService.Visibility visibility) {
+ @SuppressWarnings("rawtypes")
+ final List<ObjectAssociation> list =
+ objectSpecification.getAssociations(
+ Contributed.INCLUDED,
+ Filters.and(
+ associationFilter,
+ associationsWith(visibility)
+ ));
+
+ return cast(list);
+ }
+
+ @SuppressWarnings("unchecked")
+ static <T> List<T> cast(final List list) {
+ return list;
+ }
+
+ static List<ObjectAction> actionsOf(
+ final ObjectSpecification objectSpec,
+ final SwaggerService.Visibility visibility) {
+ final List<ActionType> actionTypes = actionTypesFor(visibility);
+
+ return objectSpec.getObjectActions(actionTypes, Contributed.INCLUDED, new Filter<ObjectAction>() {
+ @Override
+ public boolean accept(final ObjectAction objectAction) {
+ return !visibility.isPublic() || isVisibleForPublic(objectAction);
+ }
+ });
+ }
+
+ static String roSpec(final String section) {
+ return "RO Spec v1.0, section " + section;
+ }
+
+ static Response withCachingHeaders(final Response response, final Caching caching) {
+ caching.withHeaders(response);
+
+ return response;
+ }
+
+ static List<ActionType> actionTypesFor(final SwaggerService.Visibility visibility) {
+ switch (visibility) {
+ case PUBLIC:
+ return Arrays.asList(ActionType.USER);
+ case PRIVATE:
+ return Arrays.asList(ActionType.USER);
+ case PRIVATE_WITH_PROTOTYPING:
+ return Arrays.asList(ActionType.USER, ActionType.EXPLORATION, ActionType.PROTOTYPE, ActionType.DEBUG);
+ }
+ throw new IllegalArgumentException("Unrecognized type '" + visibility + "'");
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/3d9f8fe0/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/internal/example.json
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/internal/example.json b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/internal/example.json
deleted file mode 100644
index 7036c06..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/internal/example.json
+++ /dev/null
@@ -1,515 +0,0 @@
-{
- "swagger": "2.0",
- "info": {
- "version": "1.0.0",
- "title": "Restful Objects"
- },
- "paths": {
- "/": {
- "get": {
- "description": "Home page",
- "produces": [
- "application/json"
- ],
- "responses": {
- "200": {
- "description": "OK",
- "schema": {
- "type": "object",
- "required": [
- "links"
- ],
- "properties": {
- "links": {
- "type": "array",
- "items": {
- "$ref": "#/definitions/LinkRepresentation"
- }
- }
- }
- }
- }
- }
- }
- },
- "/services": {
- "get": {
- "description": "Services",
- "produces": [
- "application/json"
- ],
- "responses": {
- "200": {
- "description": "OK",
- "schema": {
- "type": "object",
- "required": [
- "value",
- "links"
- ],
- "properties": {
- "value": {
- "type": "array",
- "items": {
- "$ref": "#/definitions/LinkRepresentation"
- }
- },
- "links": {
- "type": "array",
- "items": {
- "$ref": "#/definitions/LinkRepresentation"
- }
- }
- }
- }
- }
- }
- }
- },
- "/services/SimpleObjects": {
- "get": {
- "description": "SimpleObjects service",
- "produces": [
- "application/json"
- ],
- "responses": {
- "200": {
- "description": "OK",
- "schema": {
- "$ref": "#/definitions/ServiceRepresentation"
- }
- }
- }
- }
- },
- "/services/SimpleObjects/actions/findByName": {
- "get": {
- "description": "SimpleObjects findByName action",
- "produces": [
- "application/json"
- ],
- "responses": {
- "200": {
- "description": "OK",
- "schema": {
- "$ref": "#/definitions/ActionPromptRepresentation"
- }
- }
- }
- }
- },
- "/services/SimpleObjects/actions/findByName/invoke": {
- "get": {
- "description": "SimpleObjects findByName invocation result",
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json;profile=\"urn:org.restfulobjects/repr-types/action-result\"",
- "application/json;profile=\"urn:org.apache.isis/v1\"",
- "application/json;profile=\"urn:org.apache.isis/v1\";suppress=\"true\""
- ],
- "responses": {
- "200": {
- "description": "All objects matching name",
- "schema": {
- "$ref": "#/definitions/ActionInvocationRepresentationOfList"
- }
- }
- }
- }
- },
- "/objects/simple.SimpleObject/{id}": {
- "get": {
- "description": "representation of simple.SimpleObject",
- "parameters": [
- {
- "in": "path",
- "name": "id",
- "required": true,
- "type": "string"
- }
- ],
- "produces": [
- "application/json;profile=\"urn:org.restfulobjects/repr-types/object\"",
- "application/json;profile=\"urn:org.apache.isis/v1\";repr-type=\"object\""
- ],
- "responses": {
- "200": {
- "description": "OK",
- "schema": {
- "$ref": "#/definitions/ObjectRepresentation"
- }
- }
- }
- }
- }
- },
- "definitions": {
- "ServiceRepresentation": {
- "type": "object",
- "required": [
- "links",
- "extensions",
- "title",
- "serviceId"
- ],
- "properties": {
- "links": {
- "type": "array",
- "items": {
- "$ref": "#/definitions/LinkRepresentation"
- }
- },
- "extensions": {
- "$ref": "#/definitions/ServiceOrObjectExtensionsRepresentation"
- },
- "title": {
- "type": "string"
- },
- "serviceId": {
- "type": "string"
- },
- "members": {
- "type": "object",
- "required": [
- "listAll",
- "findByName",
- "create"
- ],
- "properties": {
- "listAll": {
- "$ref": "#/definitions/ActionRepresentation"
- },
- "findByName": {
- "$ref": "#/definitions/ActionRepresentation"
- },
- "create": {
- "$ref": "#/definitions/ActionRepresentation"
- }
- }
- }
- }
- },
- "ObjectRepresentation": {
- "type": "object",
- "required": [
- "links",
- "extensions",
- "title",
- "domainType",
- "instanceId",
- "members"
- ],
- "properties": {
- "links": {
- "type": "array",
- "items": {
- "$ref": "#/definitions/LinkRepresentation"
- }
- },
- "extensions": {
- "$ref": "#/definitions/ServiceOrObjectExtensionsRepresentation"
- },
- "title": {
- "type": "string"
- },
- "domainType": {
- "type": "string"
- },
- "instanceId": {
- "type": "string"
- },
- "members": {
- "type": "object",
- "required": [
- "name",
- "versionSequence",
- "downloadJdoMetadata",
- "updateName"
- ],
- "properties": {
- "name": {
- "type": "object",
- "required": [
- "id",
- "memberType",
- "links",
- "value",
- "extensions"
- ],
- "properties": {
- "id": {
- "type": "string"
- },
- "memberType": {
- "type": "string",
- "default": "property"
- },
- "links": {
- "type": "array",
- "items": {
- "$ref": "#/definitions/LinkRepresentation"
- }
- },
- "value": {
- "type": "string"
- },
- "disabledReason": {
- "type": "string"
- },
- "extensions": {
- "type": "object"
- }
- }
- },
- "versionSequence": {
- "type": "object",
- "required": [
- "id",
- "memberType",
- "links",
- "value",
- "format",
- "extensions"
- ],
- "properties": {
- "id": {
- "type": "string"
- },
- "memberType": {
- "type": "string",
- "default": "property"
- },
- "links": {
- "type": "array",
- "items": {
- "$ref": "#/definitions/LinkRepresentation"
- }
- },
- "value": {
- "type": "integer"
- },
- "format": {
- "type": "string"
- },
- "disabledReason": {
- "type": "string"
- },
- "extensions": {
- "type": "object"
- }
- }
- },
- "downloadJdoMetadata": {
- "$ref": "#/definitions/ActionRepresentation"
- },
- "updateName": {
- "$ref": "#/definitions/ActionRepresentation"
- }
- }
- }
- }
- },
- "ActionPromptRepresentation": {
- "type": "object",
- "required": [
- "id",
- "memberType",
- "links",
- "extensions",
- "parameters"
- ],
- "properties": {
- "id": {
- "type": "string"
- },
- "memberType": {
- "type": "string"
- },
- "links": {
- "type": "array",
- "items": {
- "$ref": "#/definitions/LinkRepresentation"
- }
- },
- "extensions": {
- "type": "object",
- "required": [
- "actionType",
- "actionSemantics"
- ],
- "properties": {
- "actionType": {
- "type": "string"
- },
- "actionSemantics": {
- "type": "string",
- "enum": [
- "safe",
- "idempotent",
- "non_idempotent"
- ]
- }
- }
- },
- "parameters": {
- "type": "object",
- "required": [
- "name"
- ],
- "properties": {
- "name": {
- "$ref": "#/definitions/ActionParameterRepresentation"
- }
- }
- }
- }
- },
- "ServiceOrObjectExtensionsRepresentation": {
- "type": "object",
- "required": [
- "oid",
- "isService",
- "isPersistent"
- ],
- "properties": {
- "oid": {
- "type": "string"
- },
- "isService": {
- "type": "boolean"
- },
- "isPersistent": {
- "type": "boolean"
- }
- }
- },
- "ActionRepresentation": {
- "type": "object",
- "required": [
- "id",
- "memberType",
- "links"
- ],
- "properties": {
- "id": {
- "type": "string"
- },
- "memberType": {
- "type": "string",
- "default": "action"
- },
- "links": {
- "type": "array",
- "items": {
- "$ref": "#/definitions/LinkRepresentation"
- }
- }
- }
- },
- "ActionParameterRepresentation": {
- "type": "object",
- "required": [
- "num",
- "id",
- "name",
- "description"
- ],
- "properties": {
- "num": {
- "type": "integer"
- },
- "id": {
- "type": "string"
- },
- "name": {
- "type": "string"
- },
- "description": {
- "type": "string"
- }
- }
- },
- "ActionInvocationRepresentationOfList": {
- "type": "object",
- "required": [
- "links",
- "resulttype",
- "result"
- ],
- "properties": {
- "links": {
- "type": "array",
- "items": {
- "$ref": "#/definitions/LinkRepresentation"
- }
- },
- "resulttype": {
- "type": "string",
- "default": "list"
- },
- "result": {
- "type": "object",
- "required": [
- "value",
- "links",
- "extensions"
- ],
- "properties": {
- "value": {
- "type": "array",
- "items": {
- "$ref": "#/definitions/LinkRepresentation"
- }
- },
- "links": {
- "type": "array",
- "items": {
- "$ref": "#/definitions/LinkRepresentation"
- }
- },
- "extensions": {
- "type": "object"
- }
- }
- }
- }
- },
- "LinkRepresentation": {
- "type": "object",
- "required": [
- "rel",
- "href",
- "method"
- ],
- "properties": {
- "rel": {
- "type": "string",
- "description": "relationship of this Link"
- },
- "href": {
- "type": "string"
- },
- "title": {
- "type": "string"
- },
- "method": {
- "type": "string",
- "enum": [
- "GET",
- "POST",
- "PUT",
- "DELETE"
- ]
- },
- "type": {
- "type": "string"
- },
- "arguments": {
- "type": "object"
- }
- }
- }
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/3d9f8fe0/example/application/simpleapp/webapp/src/main/webapp/about/index.html
----------------------------------------------------------------------
diff --git a/example/application/simpleapp/webapp/src/main/webapp/about/index.html b/example/application/simpleapp/webapp/src/main/webapp/about/index.html
index 070651a..b14a4b3 100644
--- a/example/application/simpleapp/webapp/src/main/webapp/about/index.html
+++ b/example/application/simpleapp/webapp/src/main/webapp/about/index.html
@@ -81,13 +81,18 @@ th, td {
<li>
<p>
<b>
- <a href="restful/">restful/</a>
+ <a href="swagger-ui/index.html">swagger-ui/</a>
</b>
</p>
<p>
- provides access to a RESTful API conformant with the
- <a href="http://restfulobjects.org">Restful Objects</a> spec</td>. This is part of Apache Isis Core. The
- implementation technology is JBoss RestEasy.
+ provides the Swagger UI access to RESTful API, consuming dynamically generated Swagger
+ specification files. There are three versions of this API: <a href="restful/swagger/public">public</a> (third-party) use, for <a href="restful/swagger/private">private</a> (internal) use, and extended version of the private API
+ that includes <a href="restful/swagger/prototyping">prototyping</a> actions.
+ </p>
+ <p>The RESTful API can return both simple representations (suitable for use within custom apps),
+ and also a richer hypermedia API conformant with the
+ <a href="http://restfulobjects.org">Restful Objects</a> spec. The HTTP <code>Accept</code> header
+ is used to select which representation is required.
</p>
</li>
</ul>
http://git-wip-us.apache.org/repos/asf/isis/blob/3d9f8fe0/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
deleted file mode 100644
index 7ecbcb1..0000000
--- a/example/application/simpleapp/webapp/src/main/webapp/api-docs/index.html
+++ /dev/null
@@ -1,122 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <meta charset="UTF-8">
- <base href="../webjars/swagger-ui/2.1.3/"/>
- <title>Swagger UI</title>
- <link rel="icon" type="image/png" href="images/favicon-32x32.png" sizes="32x32" />
- <link rel="icon" type="image/png" href="images/favicon-16x16.png" sizes="16x16" />
- <link href='css/typography.css' media='screen' rel='stylesheet' type='text/css'/>
- <link href='css/reset.css' media='screen' rel='stylesheet' type='text/css'/>
- <link href='css/screen.css' media='screen' rel='stylesheet' type='text/css'/>
- <link href='css/reset.css' media='print' rel='stylesheet' type='text/css'/>
- <link href='css/print.css' media='print' rel='stylesheet' type='text/css'/>
- <script src='lib/jquery-1.8.0.min.js' type='text/javascript'></script>
- <script src='lib/jquery.slideto.min.js' type='text/javascript'></script>
- <script src='lib/jquery.wiggle.min.js' type='text/javascript'></script>
- <script src='lib/jquery.ba-bbq.min.js' type='text/javascript'></script>
- <script src='lib/handlebars-2.0.0.js' type='text/javascript'></script>
- <script src='lib/underscore-min.js' type='text/javascript'></script>
- <script src='lib/backbone-min.js' type='text/javascript'></script>
- <script src='swagger-ui.js' type='text/javascript'></script>
- <script src='lib/highlight.7.3.pack.js' type='text/javascript'></script>
- <script src='lib/marked.js' type='text/javascript'></script>
- <script src='lib/swagger-oauth.js' type='text/javascript'></script>
-
- <!-- Some basic translations -->
- <!-- <script src='lang/translator.js' type='text/javascript'></script> -->
- <!-- <script src='lang/ru.js' type='text/javascript'></script> -->
- <!-- <script src='lang/en.js' type='text/javascript'></script> -->
-
- <script type="text/javascript">
- $(function () {
- var url = document.getElementById("input_baseUrl").selectedOptions[0].value;
-
- // Pre load translate...
- if(window.SwaggerTranslator) {
- window.SwaggerTranslator.translate();
- }
- window.swaggerUi = new SwaggerUi({
- url: url,
- dom_id: "swagger-ui-container",
- supportedSubmitMethods: ['get', 'post', 'put', 'delete', 'patch'],
- onComplete: function(swaggerApi, swaggerUi){
- if(typeof initOAuth == "function") {
- initOAuth({
- clientId: "your-client-id",
- clientSecret: "your-client-secret-if-required",
- realm: "your-realms",
- appName: "your-app-name",
- scopeSeparator: ","
- });
- }
-
- if(window.SwaggerTranslator) {
- window.SwaggerTranslator.translate();
- }
-
- $('pre code').each(function(i, e) {
- hljs.highlightBlock(e)
- });
-
- addApiKeyAuthorization();
- },
- onFailure: function(data) {
- log("Unable to Load SwaggerUI");
- },
- docExpansion: "none",
- apisSorter: "alpha",
- defaultModelRendering: 'schema',
- showRequestHeaders: false
- });
-
- function addApiKeyAuthorization(){
- var key = encodeURIComponent($('#input_apiKey')[0].value);
- if(key && key.trim() != "") {
- var apiKeyAuth = new SwaggerClient.ApiKeyAuthorization("api_key", key, "query");
- window.swaggerUi.api.clientAuthorizations.add("api_key", apiKeyAuth);
- log("added key " + key);
- }
- }
-
- $('#input_apiKey').change(addApiKeyAuthorization);
-
- // if you have an apiKey you would like to pre-populate on the page for demonstration purposes...
- /*
- var apiKey = "myApiKeyXXXX123456789";
- $('#input_apiKey').val(apiKey);
- */
-
- window.swaggerUi.load();
-
- function log() {
- if ('console' in window) {
- console.log.apply(console, arguments);
- }
- }
- });
- </script>
-</head>
-
-<body class="swagger-section">
-<div id='header'>
- <div class="swagger-ui-wrap">
- <a id="logo" href="http://swagger.io">swagger</a>
- <form id='api_selector'>
- <div class='input'>
- <select id="input_baseUrl" name="baseUrl">
- <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>
- </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>
- </form>
- </div>
-</div>
-
-<div id="message-bar" class="swagger-ui-wrap" data-sw-translate> </div>
-<div id="swagger-ui-container" class="swagger-ui-wrap"></div>
-</body>
-</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/3d9f8fe0/example/application/simpleapp/webapp/src/main/webapp/swagger-ui/index.html
----------------------------------------------------------------------
diff --git a/example/application/simpleapp/webapp/src/main/webapp/swagger-ui/index.html b/example/application/simpleapp/webapp/src/main/webapp/swagger-ui/index.html
new file mode 100644
index 0000000..fc4d3a4
--- /dev/null
+++ b/example/application/simpleapp/webapp/src/main/webapp/swagger-ui/index.html
@@ -0,0 +1,122 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="UTF-8">
+ <base href="../webjars/swagger-ui/2.1.3/"/>
+ <title>Swagger UI</title>
+ <link rel="icon" type="image/png" href="images/favicon-32x32.png" sizes="32x32" />
+ <link rel="icon" type="image/png" href="images/favicon-16x16.png" sizes="16x16" />
+ <link href='css/typography.css' media='screen' rel='stylesheet' type='text/css'/>
+ <link href='css/reset.css' media='screen' rel='stylesheet' type='text/css'/>
+ <link href='css/screen.css' media='screen' rel='stylesheet' type='text/css'/>
+ <link href='css/reset.css' media='print' rel='stylesheet' type='text/css'/>
+ <link href='css/print.css' media='print' rel='stylesheet' type='text/css'/>
+ <script src='lib/jquery-1.8.0.min.js' type='text/javascript'></script>
+ <script src='lib/jquery.slideto.min.js' type='text/javascript'></script>
+ <script src='lib/jquery.wiggle.min.js' type='text/javascript'></script>
+ <script src='lib/jquery.ba-bbq.min.js' type='text/javascript'></script>
+ <script src='lib/handlebars-2.0.0.js' type='text/javascript'></script>
+ <script src='lib/underscore-min.js' type='text/javascript'></script>
+ <script src='lib/backbone-min.js' type='text/javascript'></script>
+ <script src='swagger-ui.js' type='text/javascript'></script>
+ <script src='lib/highlight.7.3.pack.js' type='text/javascript'></script>
+ <script src='lib/marked.js' type='text/javascript'></script>
+ <script src='lib/swagger-oauth.js' type='text/javascript'></script>
+
+ <!-- Some basic translations -->
+ <!-- <script src='lang/translator.js' type='text/javascript'></script> -->
+ <!-- <script src='lang/ru.js' type='text/javascript'></script> -->
+ <!-- <script src='lang/en.js' type='text/javascript'></script> -->
+
+ <script type="text/javascript">
+ $(function () {
+ var url = document.getElementById("input_baseUrl").selectedOptions[0].value;
+
+ // Pre load translate...
+ if(window.SwaggerTranslator) {
+ window.SwaggerTranslator.translate();
+ }
+ window.swaggerUi = new SwaggerUi({
+ url: url,
+ dom_id: "swagger-ui-container",
+ supportedSubmitMethods: ['get', 'post', 'put', 'delete', 'patch'],
+ onComplete: function(swaggerApi, swaggerUi){
+ if(typeof initOAuth == "function") {
+ initOAuth({
+ clientId: "your-client-id",
+ clientSecret: "your-client-secret-if-required",
+ realm: "your-realms",
+ appName: "your-app-name",
+ scopeSeparator: ","
+ });
+ }
+
+ if(window.SwaggerTranslator) {
+ window.SwaggerTranslator.translate();
+ }
+
+ $('pre code').each(function(i, e) {
+ hljs.highlightBlock(e)
+ });
+
+ addApiKeyAuthorization();
+ },
+ onFailure: function(data) {
+ log("Unable to Load SwaggerUI");
+ },
+ docExpansion: "none",
+ apisSorter: "alpha",
+ defaultModelRendering: 'schema',
+ showRequestHeaders: false
+ });
+
+ function addApiKeyAuthorization(){
+ var key = encodeURIComponent($('#input_apiKey')[0].value);
+ if(key && key.trim() != "") {
+ var apiKeyAuth = new SwaggerClient.ApiKeyAuthorization("api_key", key, "query");
+ window.swaggerUi.api.clientAuthorizations.add("api_key", apiKeyAuth);
+ log("added key " + key);
+ }
+ }
+
+ $('#input_apiKey').change(addApiKeyAuthorization);
+
+ // if you have an apiKey you would like to pre-populate on the page for demonstration purposes...
+ /*
+ var apiKey = "myApiKeyXXXX123456789";
+ $('#input_apiKey').val(apiKey);
+ */
+
+ window.swaggerUi.load();
+
+ function log() {
+ if ('console' in window) {
+ console.log.apply(console, arguments);
+ }
+ }
+ });
+ </script>
+</head>
+
+<body class="swagger-section">
+<div id='header'>
+ <div class="swagger-ui-wrap">
+ <a id="logo" href="http://swagger.io">swagger</a>
+ <form id='api_selector'>
+ <div class='input'>
+ <select id="input_baseUrl" name="baseUrl">
+ <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>
+ </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>Reload</a></div>
+ </form>
+ </div>
+</div>
+
+<div id="message-bar" class="swagger-ui-wrap" data-sw-translate> </div>
+<div id="swagger-ui-container" class="swagger-ui-wrap"></div>
+</body>
+</html>
\ No newline at end of file