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/10 18:08:54 UTC
isis git commit: ISIS-1237: now generates models for object,
object collection and actions
Repository: isis
Updated Branches:
refs/heads/ISIS-1237 3d9f8fe03 -> 4502dc10a
ISIS-1237: now generates models for object, object collection and actions
Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/4502dc10
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/4502dc10
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/4502dc10
Branch: refs/heads/ISIS-1237
Commit: 4502dc10a89c039d8350cb02b3437de1f0477ad6
Parents: 3d9f8fe
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Thu Dec 10 17:08:43 2015 +0000
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Thu Dec 10 17:08:43 2015 +0000
----------------------------------------------------------------------
.../_migration-notes_1.10.0-to-1.11.0.adoc | 27 +++
.../swagger/internal/SwaggerSpecGenerator.java | 188 ++++++++++++++++---
.../swagger/internal/ValuePropertyFactory.java | 174 +++++++++++++++++
.../java/domainapp/dom/simple/SimpleObject.java | 9 +
.../webapp/src/main/webapp/about/index.html | 19 +-
5 files changed, 382 insertions(+), 35 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/isis/blob/4502dc10/adocs/documentation/src/main/asciidoc/_migration-notes_1.10.0-to-1.11.0.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/_migration-notes_1.10.0-to-1.11.0.adoc b/adocs/documentation/src/main/asciidoc/_migration-notes_1.10.0-to-1.11.0.adoc
index 65128a4..6dbd3b3 100644
--- a/adocs/documentation/src/main/asciidoc/_migration-notes_1.10.0-to-1.11.0.adoc
+++ b/adocs/documentation/src/main/asciidoc/_migration-notes_1.10.0-to-1.11.0.adoc
@@ -29,3 +29,30 @@ If your application is bootstrapped using an `AppManifest` (recommended; ee
xref:rgcms.adoc#_rgcms_classes_AppManifest-bootstrapping[here]) then the `JaxbService` will automatically be discovered and
registered. However, if you are still using the older `isis.properties` configuration file to explicitly register
services then you will need to add in this service.
+
+
+== Swagger
+
+Update the `web.xml`:
+
+[source,xml]
+----
+<servlet>
+ <servlet-name>WebjarsServlet</servlet-name>
+ <servlet-class>org.webjars.servlet.WebjarsServlet</servlet-class>
+ <init-param>
+ <param-name>disableCache</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ <load-on-startup>2</load-on-startup>
+</servlet>
+<servlet-mapping>
+ <servlet-name>WebjarsServlet</servlet-name>
+ <url-pattern>/webjars/*</url-pattern>
+</servlet-mapping>
+----
+
+
+The text of the simple archetype's `about/index.html` has also changed; the `<li`> for the `/restful` URL has been
+replaced with a `/swagger-ui` URL.
+
http://git-wip-us.apache.org/repos/asf/isis/blob/4502dc10/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 f1ca3e5..c58ee23 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
@@ -29,6 +29,7 @@ import org.apache.isis.applib.annotation.ActionSemantics;
import org.apache.isis.applib.annotation.NatureOfService;
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;
@@ -61,6 +62,7 @@ import io.swagger.util.Yaml;
public class SwaggerSpecGenerator {
private final SpecificationLoader specificationLoader;
+ private final ValuePropertyFactory valuePropertyFactory = new ValuePropertyFactory();
public SwaggerSpecGenerator(final SpecificationLoader specificationLoader) {
this.specificationLoader = specificationLoader;
@@ -122,7 +124,7 @@ public class SwaggerSpecGenerator {
appendServicePath(swagger, serviceSpec);
for (final ObjectAction serviceAction : serviceActions) {
- appendServiceActionInvokePath(swagger, serviceAction);
+ appendServiceActionInvokePath(swagger, serviceSpec, serviceAction);
}
}
}
@@ -157,14 +159,14 @@ public class SwaggerSpecGenerator {
continue;
}
final ModelImpl isisModel = appendObjectPathAndModelDefinitions(swagger, objectSpec);
- appendObjectModel(isisModel, objectProperties, objectCollections);
+ updateObjectModel(isisModel, objectSpec, objectProperties, objectCollections);
for (final OneToManyAssociation objectCollection : objectCollections) {
- appendCollectionTo(swagger, objectCollection);
+ appendCollectionTo(swagger, objectSpec, objectCollection);
}
for (final ObjectAction objectAction : objectActions) {
- appendObjectActionInvokePath(swagger, objectAction);
+ appendObjectActionInvokePath(swagger, objectSpec, objectAction);
}
}
}
@@ -258,17 +260,26 @@ public class SwaggerSpecGenerator {
swagger.addDefinition("LinkModel",
new ModelImpl()
.type("object")
- .property("rel", stringProperty())
- .property("href", stringProperty())
- .property("title", stringProperty())
- .property("method", stringPropertyEnum("GET", "POST", "PUT", "DELETE"))
- .property("type", stringProperty())
- .property("arguments", new ObjectProperty())
+ .property("rel", stringProperty().description("the relationship of the resource to this referencing resource"))
+ .property("href", stringProperty().description("the hyperlink reference (URL) of the resource"))
+ .property("title", stringProperty().description("title to render"))
+ .property("method", stringPropertyEnum("GET", "POST", "PUT", "DELETE").description("HTTP verb to access"))
+ .property("type", stringProperty().description("Content-Type recognized by the resource (for HTTP Accept header)"))
+ .property("arguments", new ObjectProperty().description("Any arguments, to send as query strings or in body"))
+ .property("value", stringProperty().description("the representation of the link if followed"))
.required("rel")
.required("href")
.required("method")
);
+ swagger.addDefinition("HrefModel",
+ new ModelImpl()
+ .type("object")
+ .description("Abbreviated version of the Link resource, used primarily to reference non-value objects")
+ .property("href", stringProperty().description("the hyperlink reference (URL) of the resource"))
+ .required("href")
+ );
+
}
void appendServicePath(final Swagger swagger, final ObjectSpecification objectSpec) {
@@ -307,8 +318,6 @@ public class SwaggerSpecGenerator {
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(
@@ -328,6 +337,7 @@ public class SwaggerSpecGenerator {
// 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)
+ final String restfulObjectsModelDefinition = objectType + "RestfulObjectsModel";
if (false) {
operation.response(200,
newResponse(Caching.TRANSACTIONAL)
@@ -343,13 +353,12 @@ public class SwaggerSpecGenerator {
swagger.addDefinition(restfulObjectsModelDefinition, roSpecModel);
}
+ final String isisModelDefinition = objectType + "Model";
operation
.response(200,
newResponse(Caching.TRANSACTIONAL)
- .description("if Accept: application/json;profile=urn:org.apache.isis/v1")
- .schema(new RefProperty("#/definitions/"
- + isisModelDefinition)));
-
+ .description(objectType + " , if Accept: application/json;profile=urn:org.apache.isis/v1")
+ .schema(new RefProperty("#/definitions/" + isisModelDefinition)));
final ModelImpl isisModel = new ModelImpl();
swagger.addDefinition(isisModelDefinition, isisModel);
@@ -380,9 +389,9 @@ public class SwaggerSpecGenerator {
void appendServiceActionInvokePath(
final Swagger swagger,
+ final ObjectSpecification serviceSpec,
final ObjectAction serviceAction) {
- final ObjectSpecification serviceSpec = serviceAction.getOnType();
final String serviceId = serviceIdFor(serviceSpec);
final String actionId = serviceAction.getId();
@@ -457,16 +466,55 @@ public class SwaggerSpecGenerator {
invokeOperation
.response(
200, new Response()
- .description(roSpecForResponseOf(serviceAction) + ": (invoke) representation of " + serviceId + "#" + actionId)
- .schema(new ObjectProperty())
+ .description(serviceId + "#" + actionId + " , if Accept: application/json;profile=urn:org.apache.isis/v1")
+ .schema(actionReturnTypeFor(serviceAction))
);
}
+ void appendCollectionTo(
+ final Swagger swagger,
+ final ObjectSpecification objectSpec,
+ final OneToManyAssociation collection) {
+
+ final String objectType = objectTypeFor(objectSpec);
+ final String collectionId = collection.getId();
+
+ final Path path = new Path();
+ swagger.path(String.format("/objects/%s/{objectId}/collections/%s", objectType, collectionId), path);
+
+ final Operation collectionOperation =
+ new Operation()
+ .tag(objectType)
+ .description(Util.roSpec("17.1") + ": resource of " + objectType + "#" + collectionId)
+ .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-collection");
+
+ path.get(collectionOperation);
+ collectionOperation
+ .response(
+ 200, new Response()
+ .description(objectType + "#" + collectionId + " , if Accept: application/json;profile=urn:org.apache.isis/v1")
+ .schema(modelFor(collection))
+ );
+ }
+
+ private Property modelFor(final OneToManyAssociation collection) {
+ ObjectSpecification collectionSpecification = collection.getSpecification();
+ return new ArrayProperty()
+ .description("List of " + objectTypeFor(collectionSpecification))
+ .items(modelFor(collectionSpecification));
+ }
+
void appendObjectActionInvokePath(
final Swagger swagger,
+ final ObjectSpecification objectSpec,
final ObjectAction objectAction) {
- final ObjectSpecification objectSpec = objectAction.getOnType();
final String objectType = objectTypeFor(objectSpec);
final String actionId = objectAction.getId();
@@ -544,19 +592,97 @@ public class SwaggerSpecGenerator {
invokeOperation
.response(
200, new Response()
- .description(roSpecForResponseOf(objectAction) + ": (invoke) representation of " + objectType + "#" + actionId)
- .schema(new ObjectProperty())
+ .description(objectType + "#" + actionId)
+ .schema(actionReturnTypeFor(objectAction))
);
}
- void appendCollectionTo(final Swagger members, final OneToManyAssociation serviceAction) {
+ Property actionReturnTypeFor(final ObjectAction objectAction) {
+
+ final ObjectSpecification specification = objectAction.getReturnType();
+ TypeOfFacet typeOfFacet = objectAction.getFacet(TypeOfFacet.class);
+ if(typeOfFacet != null) {
+ ObjectSpecification elementSpec = typeOfFacet.valueSpec();
+ if(elementSpec != null) {
+ return new ArrayProperty()
+ .items(modelFor(elementSpec));
+ }
+ }
+ return modelFor(specification);
+ }
+
+ private Property modelFor(final ObjectSpecification specification) {
+ if(specification == null) {
+ return new ObjectProperty();
+ }
+
+ // no "simple" representation for void or values
+ final Class<?> correspondingClass = specification.getCorrespondingClass();
+ if(correspondingClass == void.class || correspondingClass == Void.class) {
+ return new ObjectProperty();
+ }
+ // no "simple" representation for values
+ final Property property = valuePropertyFactory.newProperty(correspondingClass);
+ if(property != null) {
+ // was recognized as a value
+ return new ObjectProperty();
+ }
+
+ if(specification.isParentedOrFreeCollection()) {
+ TypeOfFacet typeOfFacet = specification.getFacet(TypeOfFacet.class);
+ if(typeOfFacet != null) {
+ ObjectSpecification elementSpec = typeOfFacet.valueSpec();
+ if(elementSpec != null) {
+ return new ArrayProperty()
+ .items(modelFor(elementSpec));
+ }
+ }
+ }
+ return new RefProperty("#/definitions/" + objectTypeFor(specification) + "Model");
}
- void appendObjectModel(
- final ModelImpl swagger,
- final List<OneToOneAssociation> objectProperties, final List<OneToManyAssociation> objectCollections) {
+ void updateObjectModel(
+ final ModelImpl model,
+ final ObjectSpecification objectSpecification,
+ final List<OneToOneAssociation> objectProperties,
+ final List<OneToManyAssociation> objectCollections) {
+ final String objectType = objectTypeFor(objectSpecification);
+ final String className = objectSpecification.getFullIdentifier();
+
+ model
+ .type("object")
+ .description(String.format("%s (%s)", objectType, className));
+
+ for (OneToOneAssociation objectProperty : objectProperties) {
+ model.property(
+ objectProperty.getId(),
+ propertyFor(objectProperty.getSpecification()));
+ }
+
+ for (OneToManyAssociation objectCollection : objectCollections) {
+ final ObjectSpecification elementSpec = objectCollection.getSpecification();
+ final String elementModelDefinition = objectTypeFor(elementSpec) + "Model";
+
+ model.property(
+ objectCollection.getId(),
+ new ArrayProperty()
+ .items(new RefProperty("#/definitions/" + elementModelDefinition))
+ );
+ }
+ }
+
+ Property propertyFor(final ObjectSpecification objectSpecification) {
+ final Property property =
+ valuePropertyFactory.newProperty(objectSpecification.getCorrespondingClass());
+ if (property != null) {
+ return property;
+ }
+ else {
+ // assume this is a reference to an entity/view model, meaning we use an href
+ return refToHrefModel();
+ }
}
static String roSpecForResponseOf(final ObjectAction action) {
@@ -608,7 +734,15 @@ public class SwaggerSpecGenerator {
static ArrayProperty arrayOfLinks() {
return new ArrayProperty()
- .items(new RefProperty("#/definitions/LinkModel"));
+ .items(refToLinkModel());
+ }
+
+ static RefProperty refToLinkModel() {
+ return new RefProperty("#/definitions/LinkModel");
+ }
+
+ static RefProperty refToHrefModel() {
+ return new RefProperty("#/definitions/HrefModel");
}
static ArrayProperty arrayOfStrings() {
http://git-wip-us.apache.org/repos/asf/isis/blob/4502dc10/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/internal/ValuePropertyFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/internal/ValuePropertyFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/internal/ValuePropertyFactory.java
new file mode 100644
index 0000000..c00990e
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/internal/ValuePropertyFactory.java
@@ -0,0 +1,174 @@
+/*
+ * 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.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Map;
+import java.util.UUID;
+
+import com.google.common.collect.Maps;
+
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+import org.joda.time.LocalDateTime;
+
+import io.swagger.models.properties.BooleanProperty;
+import io.swagger.models.properties.ByteArrayProperty;
+import io.swagger.models.properties.DateProperty;
+import io.swagger.models.properties.DateTimeProperty;
+import io.swagger.models.properties.DecimalProperty;
+import io.swagger.models.properties.DoubleProperty;
+import io.swagger.models.properties.FloatProperty;
+import io.swagger.models.properties.IntegerProperty;
+import io.swagger.models.properties.LongProperty;
+import io.swagger.models.properties.Property;
+import io.swagger.models.properties.StringProperty;
+import io.swagger.models.properties.UUIDProperty;
+
+public class ValuePropertyFactory {
+
+ private final Map<Class, Factory> propertyFactoryByClass = Maps.newHashMap();
+
+ static interface Factory {
+ Property newProperty();
+ }
+ public ValuePropertyFactory() {
+
+ final Factory booleanFactory = new Factory() {
+ @Override
+ public Property newProperty() {
+ return new BooleanProperty();
+ }
+ };
+ propertyFactoryByClass.put(boolean.class, booleanFactory);
+ propertyFactoryByClass.put(Boolean.class, booleanFactory);
+
+ final Factory integerFactory = new Factory() {
+ @Override
+ public Property newProperty() {
+ return new IntegerProperty();
+ }
+ };
+ propertyFactoryByClass.put(byte.class, integerFactory);
+ propertyFactoryByClass.put(Byte.class, integerFactory);
+ propertyFactoryByClass.put(short.class, integerFactory);
+ propertyFactoryByClass.put(Short.class, integerFactory);
+ propertyFactoryByClass.put(int.class, integerFactory);
+ propertyFactoryByClass.put(Integer.class, integerFactory);
+ propertyFactoryByClass.put(BigInteger.class, integerFactory);
+
+ final Factory longFactory = new Factory() {
+ @Override
+ public Property newProperty() {
+ return new LongProperty();
+ }
+ };
+ propertyFactoryByClass.put(long.class, longFactory);
+ propertyFactoryByClass.put(Long.class, longFactory);
+ propertyFactoryByClass.put(java.sql.Timestamp.class, longFactory);
+
+ final Factory decimalFactory = new Factory() {
+ @Override
+ public Property newProperty() {
+ return new DecimalProperty();
+ }
+ };
+ propertyFactoryByClass.put(BigDecimal.class, decimalFactory);
+
+ final Factory floatFactory = new Factory() {
+ @Override
+ public Property newProperty() {
+ return new FloatProperty();
+ }
+ };
+ propertyFactoryByClass.put(float.class, floatFactory);
+ propertyFactoryByClass.put(Float.class, floatFactory);
+
+ final Factory doubleFactory = new Factory() {
+ @Override
+ public Property newProperty() {
+ return new DoubleProperty();
+ }
+ };
+ propertyFactoryByClass.put(double.class, doubleFactory);
+ propertyFactoryByClass.put(Double.class, doubleFactory);
+
+ final Factory stringFactory = new Factory() {
+ @Override
+ public Property newProperty() {
+ return new StringProperty();
+ }
+ };
+ propertyFactoryByClass.put(char[].class, stringFactory);
+ propertyFactoryByClass.put(String.class, stringFactory);
+
+ final Factory uuidFactory = new Factory() {
+ @Override
+ public Property newProperty() {
+ return new UUIDProperty();
+ }
+ };
+ propertyFactoryByClass.put(UUID.class, uuidFactory);
+
+ final Factory dateTimeFactory = new Factory() {
+ @Override
+ public Property newProperty() {
+ return new DateTimeProperty();
+ }
+ };
+ propertyFactoryByClass.put(java.util.Date.class, dateTimeFactory);
+ propertyFactoryByClass.put(DateTime.class, dateTimeFactory);
+ propertyFactoryByClass.put(LocalDateTime.class, dateTimeFactory);
+ propertyFactoryByClass.put(org.apache.isis.applib.value.DateTime.class, dateTimeFactory);
+
+ final Factory dateFactory = new Factory() {
+ @Override
+ public Property newProperty() {
+ return new DateProperty();
+ }
+ };
+ propertyFactoryByClass.put(java.sql.Date.class, dateFactory);
+ propertyFactoryByClass.put(LocalDate.class, dateFactory);
+ propertyFactoryByClass.put(org.apache.isis.applib.value.Date.class, dateFactory);
+
+ final Factory byteArrayFactory = new Factory() {
+ @Override
+ public Property newProperty() {
+ return new ByteArrayProperty();
+ }
+ };
+ propertyFactoryByClass.put(byte[].class, byteArrayFactory);
+ propertyFactoryByClass.put(org.apache.isis.applib.value.Blob.class, byteArrayFactory);
+ }
+
+ public Property newProperty(Class<?> cls) {
+ if(cls == null) {
+ return null;
+ }
+
+ final Factory factory = propertyFactoryByClass.get(cls);
+ if(factory != null) {
+ return factory.newProperty();
+ }
+
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/4502dc10/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.java
----------------------------------------------------------------------
diff --git a/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.java b/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.java
index 98a485d..bee0af9 100644
--- a/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.java
+++ b/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.java
@@ -18,10 +18,14 @@
*/
package domainapp.dom.simple;
+import java.util.List;
+
import javax.jdo.JDOHelper;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.VersionStrategy;
+import com.google.common.collect.Lists;
+
import org.apache.isis.applib.DomainObjectContainer;
import org.apache.isis.applib.annotation.Action;
import org.apache.isis.applib.annotation.BookmarkPolicy;
@@ -112,6 +116,11 @@ public class SimpleObject implements Comparable<SimpleObject> {
}
+ public List<SimpleObject> getOthers() {
+ return Lists.newArrayList();
+ }
+
+
/**
* version (derived property)
*/
http://git-wip-us.apache.org/repos/asf/isis/blob/4502dc10/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 b14a4b3..d243565 100644
--- a/example/application/simpleapp/webapp/src/main/webapp/about/index.html
+++ b/example/application/simpleapp/webapp/src/main/webapp/about/index.html
@@ -73,7 +73,7 @@ th, td {
<b><a href="wicket/">wicket/</a></b>
</p>
<p>
- provides accesses to a generic UI for end-users,
+ provides access to a generic UI for end-users,
Isis' <a href="http://isis.apache.org/components/viewers/wicket/about.html" target="_blank">Wicket Viewer</a>.
As its name suggests, this viewer is built on top of <a href="http://wicket.apache.org" target="_blank">Apache Wicket</a>™.
</p>
@@ -85,14 +85,17 @@ th, td {
</b>
</p>
<p>
- 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.
+ provides access to a Swagger UI which uses a subset of the framework's automatically
+ generated <a href="restful/">RESTful API</a>. There are three versions of the Swagger
+ spec files (that drive the UI): <a href="restful/swagger/public">public</a> (for use by
+ "third-party" apps), <a href="restful/swagger/private">private</a> (for use by internal apps),
+ and <a href="restful/swagger/prototyping">prototyping</a> (an extended version of the private
+ API). The Swagger spec files are themselves dynamically generated and can be used to generate
+ client-side stubs.
</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>The RESTful API can return both simple representations and also richer hypermedia representations
+ that are conformant with the <a href="http://restfulobjects.org">Restful Objects</a> spec.
+ The HTTP <code>Accept</code> header is used to select which representation should be generated.
</p>
</li>
</ul>