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/01 08:26:26 UTC
[3/5] isis git commit: ISIS-1274: new simplified Accept header and
corresponding returned content type now more-or-less implemented.
ISIS-1274: new simplified Accept header and corresponding returned content type now more-or-less implemented.
For domain objects, domain object (parented) collections, and actions, can specify an Accept header of 'application/json;profile="urn:org.apache.isis/v1"
This will generate a simplified representation, with the original RO v1.0 representation still available under a '$$ro' property
For collections and actions returning lists, a list is returned rather than a map. The RO v1.0 representation is available as an object in this list, with a single '$$ro' property.
The caller can distinguish whether a domain object or collection or list has been returned by checking the Content-Type header. This uses a 'repr-type' parameter to distinguish, so will take the values of either:
- domain object:
application/json;profile="urn:org.apache.isis/v1";repr-type="object"
- parented collection:
application/json;profile="urn:org.apache.isis/v1";repr-type="object-collection"
- standalone list (from action):
application/json;profile="urn:org.apache.isis/v1";repr-type="list"
In addition, the '$$ro' representation can be suppressed completely by using the 'suppress' parameter for the Accept header, eg application/json;profile="urn:org.apache.isis/v1";suppress="true"
Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/5f46ef13
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/5f46ef13
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/5f46ef13
Branch: refs/heads/master
Commit: 5f46ef13fa3b427a34e4ab48e4098fe6a1f26f98
Parents: a4f04eb
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Tue Dec 1 06:53:56 2015 +0000
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Tue Dec 1 06:53:56 2015 +0000
----------------------------------------------------------------------
.../ActionResultRepresentation.java | 3 +-
.../restfulobjects/rendering/Responses.java | 25 +-
.../domainobjects/ActionResultReprRenderer.java | 108 +++---
.../domainobjects/DomainObjectReprRenderer.java | 16 +-
.../domainobjects/ListReprRenderer.java | 5 +
.../ObjectAndActionInvocation.java | 31 ++
.../ObjectCollectionReprRenderer.java | 9 +-
.../domainobjects/ScalarValueReprRenderer.java | 5 +-
.../ContentNegotiationServiceAbstract.java | 8 +-
...NegotiationServiceForRestfulObjectsV1_0.java | 87 +++--
.../ContentNegotiationServiceSimplified.java | 358 +++++++++++++++----
11 files changed, 493 insertions(+), 162 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/isis/blob/5f46ef13/core/viewer-restfulobjects-applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/domainobjects/ActionResultRepresentation.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/domainobjects/ActionResultRepresentation.java b/core/viewer-restfulobjects-applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/domainobjects/ActionResultRepresentation.java
index d03a5d6..252ae20 100644
--- a/core/viewer-restfulobjects-applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/domainobjects/ActionResultRepresentation.java
+++ b/core/viewer-restfulobjects-applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/domainobjects/ActionResultRepresentation.java
@@ -19,6 +19,7 @@
package org.apache.isis.viewer.restfulobjects.applib.domainobjects;
import com.fasterxml.jackson.databind.JsonNode;
+
import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
public class ActionResultRepresentation extends AbstractObjectMemberRepresentation {
@@ -28,7 +29,7 @@ public class ActionResultRepresentation extends AbstractObjectMemberRepresentati
private final String value;
- private ResultType(final String value) {
+ ResultType(final String value) {
this.value = value;
}
http://git-wip-us.apache.org/repos/asf/isis/blob/5f46ef13/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/Responses.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/Responses.java b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/Responses.java
index 0d4ddac..e68e250 100644
--- a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/Responses.java
+++ b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/Responses.java
@@ -41,11 +41,14 @@ public final class Responses {
return ofOk(renderer, caching, null, null);
}
+ /**
+ * @param rootRepresentationIfAny - if specified, is used for entity; otherwise the renderer is used. The idea is that the renderer will be set up to render to some sub-node of root representation
+ */
public static Response.ResponseBuilder ofOk(
final ReprRenderer<?, ?> renderer,
final Caching caching,
- final JsonRepresentation rootRepresentation) {
- return ofOk(renderer, caching, null, rootRepresentation);
+ final JsonRepresentation rootRepresentationIfAny) {
+ return ofOk(renderer, caching, null, rootRepresentationIfAny);
}
public static Response.ResponseBuilder ofOk(
@@ -55,17 +58,20 @@ public final class Responses {
return ofOk(renderer, caching, version, null);
}
+ /**
+ * @param rootRepresentationIfAny - if specified, is used for entity; otherwise the renderer is used. The idea is that the renderer will be set up to render to some sub-node of root representation
+ */
public static Response.ResponseBuilder ofOk(
final ReprRenderer<?, ?> renderer,
final Caching caching,
final Version version,
- final JsonRepresentation rootRepresentation) {
+ final JsonRepresentation rootRepresentationIfAny) {
final JsonRepresentation representation = renderer.render();
// if a rootRepresentation is provided, then the assumption is that the rendered
// will be rendering to some submap of the rootRepresentation
final JsonRepresentation entityRepresentation =
- rootRepresentation != null? rootRepresentation : representation;
+ rootRepresentationIfAny != null? rootRepresentationIfAny : representation;
final MediaType mediaType = renderer.getMediaType();
final Response.ResponseBuilder response =
@@ -80,7 +86,16 @@ public final class Responses {
return Response.status(httpStatusCode.getJaxrsStatusType()).type(MediaType.APPLICATION_JSON_TYPE);
}
- public static Response.ResponseBuilder addLastModifiedAndETagIfAvailable(final Response.ResponseBuilder responseBuilder, final Version version) {
+ public static Response.ResponseBuilder mediaType(
+ final Response.ResponseBuilder responseBuilder,
+ final MediaType mediaType) {
+ responseBuilder.type(mediaType);
+ return responseBuilder;
+ }
+
+ public static Response.ResponseBuilder addLastModifiedAndETagIfAvailable(
+ final Response.ResponseBuilder responseBuilder,
+ final Version version) {
if (version != null && version.getTime() != null) {
final Date time = version.getTime();
responseBuilder.lastModified(time);
http://git-wip-us.apache.org/repos/asf/isis/blob/5f46ef13/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ActionResultReprRenderer.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ActionResultReprRenderer.java b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ActionResultReprRenderer.java
index 7917a1e..7ebaaec 100644
--- a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ActionResultReprRenderer.java
+++ b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ActionResultReprRenderer.java
@@ -20,9 +20,9 @@ import java.util.Collection;
import java.util.Map;
import com.fasterxml.jackson.databind.node.NullNode;
+
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
-import org.apache.isis.core.metamodel.facets.object.encodeable.EncodableFacet;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
@@ -43,17 +43,17 @@ public class ActionResultReprRenderer extends ReprRendererAbstract<ActionResultR
private JsonRepresentation arguments;
private ObjectAdapter returnedAdapter;
private final SelfLink selfLink;
-
+ private ObjectAndActionInvocation objectAndActionInvocation;
public enum SelfLink {
INCLUDED, EXCLUDED
}
- public ActionResultReprRenderer(final RendererContext rendererContext, final SelfLink selfLink) {
- this(rendererContext, null, selfLink, JsonRepresentation.newMap());
- }
-
- public ActionResultReprRenderer(final RendererContext rendererContext, final LinkFollowSpecs linkFollower, final SelfLink selfLink, final JsonRepresentation representation) {
+ public ActionResultReprRenderer(
+ final RendererContext rendererContext,
+ final LinkFollowSpecs linkFollower,
+ final SelfLink selfLink,
+ final JsonRepresentation representation) {
super(rendererContext, linkFollower, RepresentationType.ACTION_RESULT, representation);
this.selfLink = selfLink;
}
@@ -61,6 +61,8 @@ public class ActionResultReprRenderer extends ReprRendererAbstract<ActionResultR
@Override
public ActionResultReprRenderer with(final ObjectAndActionInvocation objectAndActionInvocation) {
+ this.objectAndActionInvocation = objectAndActionInvocation;
+
objectAdapter = objectAndActionInvocation.getObjectAdapter();
action = objectAndActionInvocation.getAction();
arguments = objectAndActionInvocation.getArguments();
@@ -78,6 +80,10 @@ public class ActionResultReprRenderer extends ReprRendererAbstract<ActionResultR
@Override
public JsonRepresentation render() {
+ if(representation == null) {
+ return null;
+ }
+
representationWithSelfFor(action, arguments);
addResult(representation);
@@ -88,8 +94,10 @@ public class ActionResultReprRenderer extends ReprRendererAbstract<ActionResultR
}
private void addResult(final JsonRepresentation representation) {
+
+ final ResultType resultType = objectAndActionInvocation.determineResultType();
final JsonRepresentation result = JsonRepresentation.newMap();
- final ResultType resultType = addResultTo(result);
+ addResultTo(resultType, result);
if (!resultType.isVoid()) {
putResultType(representation, resultType);
@@ -101,55 +109,61 @@ public class ActionResultReprRenderer extends ReprRendererAbstract<ActionResultR
}
}
- private ResultType addResultTo(final JsonRepresentation result) {
+ private void addResultTo(
+ final ResultType resultType, final JsonRepresentation representation) {
- final ObjectSpecification returnType = this.action.getReturnType();
+ if(returnedAdapter == null) {
+ return;
+ }
- if (returnType.getCorrespondingClass() == void.class) {
- // void
- return ResultType.VOID;
+ final ReprRendererAbstract<?, ?> renderer = buildResultRenderer(resultType, representation);
+ if(renderer != null) {
+ renderer.render();
}
+ }
- final CollectionFacet collectionFacet = returnType.getFacet(CollectionFacet.class);
- if (collectionFacet != null) {
- // collection
+ private ReprRendererAbstract<?, ?> buildResultRenderer(
+ final ResultType resultType,
+ final JsonRepresentation representation) {
- if(returnedAdapter != null) {
+ final ObjectSpecification returnType = this.action.getReturnType();
+
+ switch (resultType) {
+ case VOID:
+ return null;
+
+ case LIST:
+
+ final CollectionFacet collectionFacet = returnType.getFacet(CollectionFacet.class);
final Collection<ObjectAdapter> collectionAdapters = collectionFacet.collection(returnedAdapter);
-
- final ListReprRenderer renderer = new ListReprRenderer(rendererContext, null, result).withElementRel(Rel.ELEMENT);
- renderer.with(collectionAdapters).withReturnType(action.getReturnType()).withElementType(returnedAdapter.getElementSpecification());
-
- renderer.render();
- }
- return ResultType.LIST;
- }
- final EncodableFacet encodableFacet = returnType.getFacet(EncodableFacet.class);
- if (encodableFacet != null) {
- // scalar
+ final ListReprRenderer listReprRenderer =
+ new ListReprRenderer(rendererContext, null, representation).withElementRel(Rel.ELEMENT);
+ listReprRenderer.with(collectionAdapters)
+ .withReturnType(action.getReturnType())
+ .withElementType(returnedAdapter.getElementSpecification());
- if(returnedAdapter != null) {
- final ScalarValueReprRenderer renderer = new ScalarValueReprRenderer(rendererContext, null, result);
- renderer.with(returnedAdapter).withReturnType(action.getReturnType());
-
- renderer.render();
- }
- return ResultType.SCALAR_VALUE;
+ return listReprRenderer;
- }
+ case SCALAR_VALUE:
- {
- // object
- if(returnedAdapter != null) {
- final DomainObjectReprRenderer renderer = new DomainObjectReprRenderer(rendererContext, null, result
- );
-
- renderer.with(returnedAdapter).includesSelf();
-
- renderer.render();
- }
- return ResultType.DOMAIN_OBJECT;
+ final ScalarValueReprRenderer scalarValueReprRenderer =
+ new ScalarValueReprRenderer(rendererContext, null, representation);
+ scalarValueReprRenderer.with(returnedAdapter)
+ .withReturnType(action.getReturnType());
+
+ return scalarValueReprRenderer;
+
+ case DOMAIN_OBJECT:
+
+ final DomainObjectReprRenderer objectReprRenderer =
+ new DomainObjectReprRenderer(rendererContext, null, representation);
+
+ objectReprRenderer.with(returnedAdapter).includesSelf();
+
+ return objectReprRenderer;
+ default:
+ throw new IllegalStateException("All possible states of ResultType enumerated; resultType = " + resultType);
}
}
http://git-wip-us.apache.org/repos/asf/isis/blob/5f46ef13/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/DomainObjectReprRenderer.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/DomainObjectReprRenderer.java b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/DomainObjectReprRenderer.java
index 95fdd5d..5dc34b8 100644
--- a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/DomainObjectReprRenderer.java
+++ b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/DomainObjectReprRenderer.java
@@ -124,6 +124,10 @@ public class DomainObjectReprRenderer extends ReprRendererAbstract<DomainObjectR
@Override
public JsonRepresentation render() {
+ if(representation == null) {
+ return null;
+ }
+
final boolean isService = objectAdapter.getSpecification().isService();
if (!(mode.isArgs())) {
@@ -185,8 +189,8 @@ public class DomainObjectReprRenderer extends ReprRendererAbstract<DomainObjectR
final LinkFollowSpecs linkFollower = getLinkFollowSpecs().follow("links");
if (linkFollower.matches(link)) {
- final DomainObjectReprRenderer renderer = new DomainObjectReprRenderer(getRendererContext(), linkFollower, JsonRepresentation.newMap()
- );
+ final DomainObjectReprRenderer renderer =
+ new DomainObjectReprRenderer(getRendererContext(), linkFollower, JsonRepresentation.newMap());
renderer.with(objectAdapter);
link.mapPut("value", renderer.render());
}
@@ -335,8 +339,8 @@ public class DomainObjectReprRenderer extends ReprRendererAbstract<DomainObjectR
if(objectAdapter.getSpecification().containsDoOpFacet(NotPersistableFacet.class)) {
return;
}
- final DomainObjectReprRenderer renderer = new DomainObjectReprRenderer(getRendererContext(), null, JsonRepresentation.newMap()
- );
+ final DomainObjectReprRenderer renderer =
+ new DomainObjectReprRenderer(getRendererContext(), null, JsonRepresentation.newMap());
final JsonRepresentation domainObjectRepr = renderer.with(objectAdapter).asPersistLinkArguments().render();
final String domainType = objectAdapter.getSpecification().getSpecId().asString();
@@ -373,8 +377,8 @@ public class DomainObjectReprRenderer extends ReprRendererAbstract<DomainObjectR
return;
}
- final DomainObjectReprRenderer renderer = new DomainObjectReprRenderer(getRendererContext(), null, JsonRepresentation.newMap()
- );
+ final DomainObjectReprRenderer renderer =
+ new DomainObjectReprRenderer(getRendererContext(), null, JsonRepresentation.newMap());
final JsonRepresentation domainObjectRepr = renderer.with(objectAdapter).asUpdatePropertiesLinkArguments().render();
if(!getRendererContext().suppressUpdateLink()) {
http://git-wip-us.apache.org/repos/asf/isis/blob/5f46ef13/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ListReprRenderer.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ListReprRenderer.java b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ListReprRenderer.java
index 0135345..2e837a9 100644
--- a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ListReprRenderer.java
+++ b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ListReprRenderer.java
@@ -68,6 +68,11 @@ public class ListReprRenderer extends ReprRendererAbstract<ListReprRenderer, Col
@Override
public JsonRepresentation render() {
+
+ if(representation == null) {
+ return null;
+ }
+
addValue();
addLinkToReturnType();
http://git-wip-us.apache.org/repos/asf/isis/blob/5f46ef13/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectAndActionInvocation.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectAndActionInvocation.java b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectAndActionInvocation.java
index a8c16fb..f009d3f 100644
--- a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectAndActionInvocation.java
+++ b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectAndActionInvocation.java
@@ -19,8 +19,12 @@
package org.apache.isis.viewer.restfulobjects.rendering.domainobjects;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
+import org.apache.isis.core.metamodel.facets.object.encodeable.EncodableFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.domainobjects.ActionResultRepresentation;
public class ObjectAndActionInvocation {
@@ -62,4 +66,31 @@ public class ObjectAndActionInvocation {
public ActionResultReprRenderer.SelfLink getSelfLink() {
return selfLink;
}
+
+
+ /**
+ * not API
+ */
+ public ActionResultRepresentation.ResultType determineResultType() {
+
+ final ObjectSpecification returnType = this.action.getReturnType();
+
+ if (returnType.getCorrespondingClass() == void.class) {
+ return ActionResultRepresentation.ResultType.VOID;
+ }
+
+ final CollectionFacet collectionFacet = returnType.getFacet(CollectionFacet.class);
+ if (collectionFacet != null) {
+ return ActionResultRepresentation.ResultType.LIST;
+ }
+
+ final EncodableFacet encodableFacet = returnType.getFacet(EncodableFacet.class);
+ if (encodableFacet != null) {
+ return ActionResultRepresentation.ResultType.SCALAR_VALUE;
+ }
+
+ // else
+ return ActionResultRepresentation.ResultType.DOMAIN_OBJECT;
+ }
+
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/5f46ef13/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectCollectionReprRenderer.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectCollectionReprRenderer.java b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectCollectionReprRenderer.java
index c91751f..aac5e03 100644
--- a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectCollectionReprRenderer.java
+++ b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectCollectionReprRenderer.java
@@ -37,11 +37,6 @@ import org.apache.isis.viewer.restfulobjects.rendering.domaintypes.CollectionDes
public class ObjectCollectionReprRenderer extends AbstractObjectMemberReprRenderer<ObjectCollectionReprRenderer, OneToManyAssociation> {
public ObjectCollectionReprRenderer(
- final RendererContext rendererContext) {
- this(rendererContext, null, null, JsonRepresentation.newMap());
- }
-
- public ObjectCollectionReprRenderer(
final RendererContext rendererContext,
final LinkFollowSpecs linkFollowSpecs,
final String collectionId,
@@ -53,6 +48,10 @@ public class ObjectCollectionReprRenderer extends AbstractObjectMemberReprRender
@Override
public JsonRepresentation render() {
+ if(representation == null) {
+ return null;
+ }
+
renderMemberContent();
final LinkFollowSpecs followValue = getLinkFollowSpecs().follow("value");
http://git-wip-us.apache.org/repos/asf/isis/blob/5f46ef13/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ScalarValueReprRenderer.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ScalarValueReprRenderer.java b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ScalarValueReprRenderer.java
index 5aee110..0d319fc 100644
--- a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ScalarValueReprRenderer.java
+++ b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ScalarValueReprRenderer.java
@@ -31,7 +31,10 @@ public class ScalarValueReprRenderer extends ReprRendererAbstract<ScalarValueRep
private ObjectSpecification returnType;
- ScalarValueReprRenderer(final RendererContext resourceContext, final LinkFollowSpecs linkFollower, final JsonRepresentation representation) {
+ public ScalarValueReprRenderer(
+ final RendererContext resourceContext,
+ final LinkFollowSpecs linkFollower,
+ final JsonRepresentation representation) {
super(resourceContext, linkFollower, null, representation); // null for representationType (there is none)
}
http://git-wip-us.apache.org/repos/asf/isis/blob/5f46ef13/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceAbstract.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceAbstract.java b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceAbstract.java
index ca7e651..18dc7c1 100644
--- a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceAbstract.java
+++ b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceAbstract.java
@@ -129,12 +129,12 @@ public abstract class ContentNegotiationServiceAbstract implements ContentNegoti
}
}
- protected boolean canAccept(
+ protected boolean mediaTypeParameterMatches(
final List<MediaType> acceptableMediaTypes,
- final String profileValue) {
+ final String parameter, final String parameterValue) {
for (MediaType mediaType : acceptableMediaTypes) {
- final String paramValue = mediaType.getParameters().get("profile");
- if (Objects.equals(paramValue, profileValue)) {
+ final String paramValue = mediaType.getParameters().get(parameter);
+ if (Objects.equals(paramValue, parameterValue)) {
return true;
}
}
http://git-wip-us.apache.org/repos/asf/isis/blob/5f46ef13/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceForRestfulObjectsV1_0.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceForRestfulObjectsV1_0.java b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceForRestfulObjectsV1_0.java
index 04fe098..e24b6f9 100644
--- a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceForRestfulObjectsV1_0.java
+++ b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceForRestfulObjectsV1_0.java
@@ -73,14 +73,14 @@ public class ContentNegotiationServiceForRestfulObjectsV1_0 implements ContentNe
@Override
public ResponseBuilder buildResponse(
- final RepresentationService.Context2 renderContext2,
+ final RepresentationService.Context2 rendererContext,
final ObjectAdapter objectAdapter) {
- final List<MediaType> list = renderContext2.getAcceptableMediaTypes();
+ final List<MediaType> list = rendererContext.getAcceptableMediaTypes();
ensureCompatibleAcceptHeader(RepresentationType.DOMAIN_OBJECT, list);
final ResponseBuilder responseBuilder = buildResponseTo(
- renderContext2, objectAdapter, JsonRepresentation.newMap(), null);
+ rendererContext, objectAdapter, JsonRepresentation.newMap(), null);
return responseBuilder(responseBuilder);
}
@@ -89,19 +89,19 @@ public class ContentNegotiationServiceForRestfulObjectsV1_0 implements ContentNe
* Not API
*/
ResponseBuilder buildResponseTo(
- final RepresentationService.Context2 renderContext2,
+ final RepresentationService.Context2 rendererContext,
final ObjectAdapter objectAdapter,
- final JsonRepresentation representation,
+ final JsonRepresentation representationIfAnyRequired,
final JsonRepresentation rootRepresentation) {
final DomainObjectReprRenderer renderer =
- new DomainObjectReprRenderer(renderContext2, null, representation);
+ new DomainObjectReprRenderer(rendererContext, null, representationIfAnyRequired);
renderer.with(objectAdapter).includesSelf();
final ResponseBuilder responseBuilder = Responses.ofOk(renderer, Caching.NONE, rootRepresentation);
- if(renderContext2 instanceof RepresentationService.Context6) {
- final RepresentationService.Context6 context6 = (RepresentationService.Context6) renderContext2;
+ if(rendererContext instanceof RepresentationService.Context6) {
+ final RepresentationService.Context6 context6 = (RepresentationService.Context6) rendererContext;
final RepresentationService.Intent intent = context6.getIntent();
if(intent == RepresentationService.Intent.JUST_CREATED) {
responseBuilder.status(Response.Status.CREATED);
@@ -117,15 +117,15 @@ public class ContentNegotiationServiceForRestfulObjectsV1_0 implements ContentNe
@Override
public ResponseBuilder buildResponse(
- final RepresentationService.Context2 renderContext2,
+ final RepresentationService.Context2 rendererContext,
final ObjectAndProperty objectAndProperty) {
- final List<MediaType> list = renderContext2.getAcceptableMediaTypes();
+ final List<MediaType> list = rendererContext.getAcceptableMediaTypes();
ensureCompatibleAcceptHeader(RepresentationType.OBJECT_PROPERTY, list);
- final ObjectPropertyReprRenderer renderer = new ObjectPropertyReprRenderer(renderContext2);
+ final ObjectPropertyReprRenderer renderer = new ObjectPropertyReprRenderer(rendererContext);
renderer.with(objectAndProperty)
- .usingLinkTo(renderContext2.getAdapterLinkTo());
+ .usingLinkTo(rendererContext.getAdapterLinkTo());
if(objectAndProperty instanceof ObjectAndProperty2) {
final ObjectAndProperty2 objectAndProperty2 = (ObjectAndProperty2) objectAndProperty;
@@ -140,15 +140,30 @@ public class ContentNegotiationServiceForRestfulObjectsV1_0 implements ContentNe
@Override
public ResponseBuilder buildResponse(
- final RepresentationService.Context2 renderContext2,
+ final RepresentationService.Context2 rendererContext,
final ObjectAndCollection objectAndCollection) {
- final List<MediaType> list = renderContext2.getAcceptableMediaTypes();
+ final List<MediaType> list = rendererContext.getAcceptableMediaTypes();
ensureCompatibleAcceptHeader(RepresentationType.OBJECT_COLLECTION, list);
- final ObjectCollectionReprRenderer renderer = new ObjectCollectionReprRenderer(renderContext2);
+ final ResponseBuilder responseBuilder =
+ buildResponseTo(rendererContext, objectAndCollection, JsonRepresentation.newMap(), null);
+
+ return responseBuilder(responseBuilder);
+ }
+
+ /**
+ * Not API
+ */
+ ResponseBuilder buildResponseTo(
+ final RepresentationService.Context2 rendererContext,
+ final ObjectAndCollection objectAndCollection,
+ final JsonRepresentation representation,
+ final JsonRepresentation rootRepresentation) {
+ final ObjectCollectionReprRenderer renderer =
+ new ObjectCollectionReprRenderer(rendererContext, null, null, representation);
renderer.with(objectAndCollection)
- .usingLinkTo(renderContext2.getAdapterLinkTo());
+ .usingLinkTo(rendererContext.getAdapterLinkTo());
if(objectAndCollection instanceof ObjectAndCollection2) {
final ObjectAndCollection2 objectAndCollection2 = (ObjectAndCollection2) objectAndCollection;
@@ -156,22 +171,20 @@ public class ContentNegotiationServiceForRestfulObjectsV1_0 implements ContentNe
renderer.withMemberMode(objectAndCollection2.getMemberReprMode());
}
- final ResponseBuilder responseBuilder = Responses.ofOk(renderer, Caching.NONE);
-
- return responseBuilder(responseBuilder);
+ return Responses.ofOk(renderer, Caching.NONE, rootRepresentation);
}
@Override
public ResponseBuilder buildResponse(
- final RepresentationService.Context2 renderContext2,
+ final RepresentationService.Context2 rendererContext,
final ObjectAndAction objectAndAction) {
- final List<MediaType> list = renderContext2.getAcceptableMediaTypes();
+ final List<MediaType> list = rendererContext.getAcceptableMediaTypes();
ensureCompatibleAcceptHeader(RepresentationType.OBJECT_ACTION, list);
- final ObjectActionReprRenderer renderer = new ObjectActionReprRenderer(renderContext2);
+ final ObjectActionReprRenderer renderer = new ObjectActionReprRenderer(rendererContext);
renderer.with(objectAndAction)
- .usingLinkTo(renderContext2.getAdapterLinkTo())
+ .usingLinkTo(rendererContext.getAdapterLinkTo())
.asStandalone();
final ResponseBuilder responseBuilder = Responses.ofOk(renderer, Caching.NONE);
@@ -181,20 +194,34 @@ public class ContentNegotiationServiceForRestfulObjectsV1_0 implements ContentNe
@Override
public ResponseBuilder buildResponse(
- final RepresentationService.Context2 renderContext2,
+ final RepresentationService.Context2 rendererContext,
final ObjectAndActionInvocation objectAndActionInvocation) {
- final List<MediaType> list = renderContext2.getAcceptableMediaTypes();
+ final List<MediaType> list = rendererContext.getAcceptableMediaTypes();
ensureCompatibleAcceptHeader(RepresentationType.ACTION_RESULT, list);
- final ActionResultReprRenderer renderer = new ActionResultReprRenderer(renderContext2, objectAndActionInvocation.getSelfLink());
+ final ResponseBuilder responseBuilder =
+ buildResponseTo(rendererContext, objectAndActionInvocation, JsonRepresentation.newMap(), null);
+
+ return responseBuilder(responseBuilder);
+ }
+
+ /**
+ * Not API
+ */
+ ResponseBuilder buildResponseTo(
+ final RepresentationService.Context2 rendererContext,
+ final ObjectAndActionInvocation objectAndActionInvocation,
+ final JsonRepresentation representation,
+ final JsonRepresentation rootRepresentation) {
+ final ActionResultReprRenderer renderer =
+ new ActionResultReprRenderer(rendererContext, null, objectAndActionInvocation.getSelfLink(), representation);
renderer.with(objectAndActionInvocation)
- .using(renderContext2.getAdapterLinkTo());
+ .using(rendererContext.getAdapterLinkTo());
- final ResponseBuilder responseBuilder = Responses.ofOk(renderer, Caching.NONE);
+ final ResponseBuilder responseBuilder = Responses.ofOk(renderer, Caching.NONE, rootRepresentation);
Responses.addLastModifiedAndETagIfAvailable(responseBuilder, objectAndActionInvocation.getObjectAdapter().getVersion());
-
- return responseBuilder(responseBuilder);
+ return responseBuilder;
}
/**
http://git-wip-us.apache.org/repos/asf/isis/blob/5f46ef13/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceSimplified.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceSimplified.java b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceSimplified.java
index 7ebddef..2d774aa 100644
--- a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceSimplified.java
+++ b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceSimplified.java
@@ -18,6 +18,7 @@
*/
package org.apache.isis.viewer.restfulobjects.rendering.service.conneg;
+import java.util.Collection;
import java.util.List;
import javax.inject.Inject;
@@ -33,16 +34,19 @@ import org.apache.isis.applib.annotation.Where;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
import org.apache.isis.core.metamodel.consent.Consent;
import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacetUtils;
+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.OneToManyAssociation;
import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.domainobjects.ActionResultRepresentation;
import org.apache.isis.viewer.restfulobjects.rendering.RendererContext;
import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.ObjectAndAction;
import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.ObjectAndActionInvocation;
import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.ObjectAndCollection;
import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.ObjectAndProperty;
-import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.ObjectCollectionReprRenderer;
import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.ObjectPropertyReprRenderer;
import org.apache.isis.viewer.restfulobjects.rendering.service.RepresentationService;
@@ -54,108 +58,227 @@ import org.apache.isis.viewer.restfulobjects.rendering.service.RepresentationSer
)
public class ContentNegotiationServiceSimplified extends ContentNegotiationServiceAbstract {
- private static final String ACCEPT_OBJECT = "urn:org.apache.isis:repr-types/object/v1";
+ /**
+ * Unlike RO v1.0, use a single content-type of <code>application/json;profile="urn:org.apache.isis/v1"</code>.
+ *
+ * <p>
+ * The response content types ({@link #CONTENT_TYPE_OAI_V1_OBJECT}, {@link #CONTENT_TYPE_OAI_V1_OBJECT_COLLECTION},
+ * {@link #CONTENT_TYPE_OAI_V1_LIST}) append the 'repr-type' parameter.
+ * </p>
+ */
+ public static final String ACCEPT_PROFILE = "urn:org.apache.isis/v1";
+
+ /**
+ * Whether to suppress the RO v1.0 '$$ro' node; suppress='false' or suppress='true'
+ */
+ public static final String ACCEPT_RO = "suppress";
+
+ /**
+ * The media type (as a string) used as the content-Type header when a domain object is rendered.
+ *
+ * @see #ACCEPT_PROFILE for discussion.
+ */
+ public static final String CONTENT_TYPE_OAI_V1_OBJECT = "application/json;"
+ + "profile=\"" + ACCEPT_PROFILE + "\""
+ + ";repr-type=\"object\""
+ ;
+ /**
+ * The media type (as a string) used as the content-Type header when a parented collection is rendered.
+ *
+ * @see #ACCEPT_PROFILE for discussion.
+ */
+ public static final String CONTENT_TYPE_OAI_V1_OBJECT_COLLECTION = "application/json;"
+ + "profile=\"" + ACCEPT_PROFILE + "\""
+ + ";repr-type=\"object-collection\""
+ ;
+ /**
+ * The media type (as a string) used as the content-Type header when a standalone collection is rendered.
+ *
+ * @see #ACCEPT_PROFILE for discussion.
+ */
+ public static final String CONTENT_TYPE_OAI_V1_LIST = "application/json;"
+ + "profile=\"" + ACCEPT_PROFILE + "\""
+ + ";repr-type=\"list\""
+ ;
private ContentNegotiationServiceForRestfulObjectsV1_0 restfulObjectsV1_0 = new ContentNegotiationServiceForRestfulObjectsV1_0();
+ /**
+ * Domain object is returned as a map with the RO 1.0 representation as a special '$$ro' property
+ * within that map.
+ */
public Response.ResponseBuilder buildResponse(
- final RepresentationService.Context2 renderContext2,
+ final RepresentationService.Context2 rendererContext,
final ObjectAdapter objectAdapter) {
- final List<MediaType> acceptableMediaTypes = renderContext2.getAcceptableMediaTypes();
-
- boolean canAccept = canAccept(acceptableMediaTypes, ACCEPT_OBJECT);
+ boolean canAccept = canAccept(rendererContext);
if(!canAccept) {
return null;
}
-
- final InteractionInitiatedBy interactionInitiatedBy =
- determineInteractionInitiatedByFrom(renderContext2);
- final Where where = renderContext2.getWhere();
+ boolean suppressRO = suppress(rendererContext);
final JsonRepresentation rootRepresentation = JsonRepresentation.newMap();
- List<OneToOneAssociation> properties = objectAdapter.getSpecification().getProperties(Contributed.INCLUDED);
- for (final OneToOneAssociation property : properties) {
-
- final Consent visibility = property.isVisible(objectAdapter, interactionInitiatedBy, where);
- if (!visibility.isAllowed()) {
- continue;
- }
-
- final JsonRepresentation propertyRepresentation = JsonRepresentation.newMap();
- final ObjectPropertyReprRenderer renderer =
- new ObjectPropertyReprRenderer(renderContext2, null, property.getId(), propertyRepresentation);
- renderer.with(new ObjectAndProperty(objectAdapter, property));
-
- final JsonRepresentation propertyValueRepresentation = renderer.render();
- rootRepresentation.mapPut(property.getId(), propertyValueRepresentation.getRepresentation("value"));
- }
-
- List<OneToManyAssociation> collections = objectAdapter.getSpecification().getCollections(Contributed.INCLUDED);
- for (final OneToManyAssociation collection : collections) {
+ appendObjectTo(rendererContext, objectAdapter, rootRepresentation);
- final Consent visibility = collection.isVisible(objectAdapter, interactionInitiatedBy, where);
- if (!visibility.isAllowed()) {
- continue;
- }
-
- final JsonRepresentation propertyRepresentation = JsonRepresentation.newMap();
- final ObjectCollectionReprRenderer renderer =
- new ObjectCollectionReprRenderer(renderContext2, null, collection.getId(), propertyRepresentation);
- renderer.with(new ObjectAndCollection(objectAdapter, collection));
-
- final JsonRepresentation collectionValueRepresentation = renderer.render();
- rootRepresentation.mapPut(collection.getId(), collectionValueRepresentation);
+ final JsonRepresentation $$roRepresentation;
+ if(!suppressRO) {
+ $$roRepresentation = JsonRepresentation.newMap();
+ rootRepresentation.mapPut("$$ro", $$roRepresentation);
+ } else {
+ $$roRepresentation = null;
}
-
-
- final JsonRepresentation $$roRepresentation = JsonRepresentation.newMap();
- rootRepresentation.mapPut("$$ro", $$roRepresentation);
-
final Response.ResponseBuilder responseBuilder =
restfulObjectsV1_0.buildResponseTo(
- renderContext2, objectAdapter, $$roRepresentation, rootRepresentation);
+ rendererContext, objectAdapter, $$roRepresentation, rootRepresentation);
- return responseBuilder(responseBuilder);
- }
+ responseBuilder.type(CONTENT_TYPE_OAI_V1_OBJECT);
- private static InteractionInitiatedBy determineInteractionInitiatedByFrom(
- final RendererContext rendererContext) {
- if (rendererContext instanceof RepresentationService.Context4) {
- return ((RepresentationService.Context4) rendererContext).getInteractionInitiatedBy();
- } else {
- // fallback
- return InteractionInitiatedBy.USER;
- }
+ return responseBuilder(responseBuilder);
}
+ /**
+ * Individual property of an object is not supported.
+ */
@Programmatic
public Response.ResponseBuilder buildResponse(
- final RepresentationService.Context2 renderContext2,
+ final RepresentationService.Context2 rendererContext,
final ObjectAndProperty objectAndProperty) {
+
return null;
}
+ /**
+ * Individual (parented) collection of an object is returned as a list with the RO representation
+ * as an object in the list with a single property named '$$ro'
+ */
@Programmatic
public Response.ResponseBuilder buildResponse(
- final RepresentationService.Context2 renderContext2,
+ final RepresentationService.Context2 rendererContext,
final ObjectAndCollection objectAndCollection) {
- return null;
+
+ if(!canAccept(rendererContext)) {
+ return null;
+ }
+ boolean suppressRO = suppress(rendererContext);
+
+ final JsonRepresentation rootRepresentation = JsonRepresentation.newArray();
+
+ ObjectAdapter objectAdapter = objectAndCollection.getObjectAdapter();
+ OneToManyAssociation collection = objectAndCollection.getMember();
+
+ appendCollectionTo(rendererContext, objectAdapter, collection, rootRepresentation);
+
+ final JsonRepresentation $$roRepresentation;
+ if(!suppressRO) {
+ // $$ro representation will be an object in the list with a single property named "$$ro"
+ final JsonRepresentation $$roContainerRepresentation = JsonRepresentation.newMap();
+ rootRepresentation.arrayAdd($$roContainerRepresentation);
+
+ $$roRepresentation = JsonRepresentation.newMap();
+ $$roContainerRepresentation.mapPut("$$ro", $$roRepresentation);
+ } else {
+ $$roRepresentation = null;
+ }
+
+ final Response.ResponseBuilder responseBuilder =
+ restfulObjectsV1_0.buildResponseTo(
+ rendererContext, objectAndCollection, $$roRepresentation, rootRepresentation);
+
+ responseBuilder.type(CONTENT_TYPE_OAI_V1_OBJECT_COLLECTION);
+
+ return responseBuilder(responseBuilder);
}
+ /**
+ * Action prompt is not supported.
+ */
@Programmatic
public Response.ResponseBuilder buildResponse(
- final RepresentationService.Context2 renderContext2,
+ final RepresentationService.Context2 rendererContext,
final ObjectAndAction objectAndAction) {
return null;
}
+ /**
+ * Action invocation is supported provided it returns a single domain object or a list of domain objects
+ * (ie invocations returning void or scalar value are not supported).
+ *
+ * Action invocations returning a domain object will be rendered as a map with the RO v1.0 representation as a
+ * '$$ro' property within (same as {@link #buildResponse(RepresentationService.Context2, ObjectAdapter)}), while
+ * action invocations returning a list will be rendered as a list with the RO v1.0 representation as a map object
+ * with a single '$$ro' property (similar to {@link #buildResponse(RepresentationService.Context2, ObjectAndCollection)})
+ */
@Programmatic
public Response.ResponseBuilder buildResponse(
- final RepresentationService.Context2 renderContext2,
+ final RepresentationService.Context2 rendererContext,
final ObjectAndActionInvocation objectAndActionInvocation) {
- return null;
+
+ if(!canAccept(rendererContext)) {
+ return null;
+ }
+ boolean suppressRO = suppress(rendererContext);
+
+ JsonRepresentation rootRepresentation = null;
+ final JsonRepresentation $$roRepresentation;
+ if(!suppressRO) {
+ $$roRepresentation = JsonRepresentation.newMap();
+ } else {
+ $$roRepresentation = null;
+ }
+
+ final ObjectAdapter returnedAdapter = objectAndActionInvocation.getReturnedAdapter();
+ final ObjectSpecification returnType = objectAndActionInvocation.getAction().getReturnType();
+
+ if (returnedAdapter == null) {
+ return null;
+ }
+
+ final ActionResultRepresentation.ResultType resultType = objectAndActionInvocation.determineResultType();
+ switch (resultType) {
+ case DOMAIN_OBJECT:
+
+ rootRepresentation = JsonRepresentation.newMap();
+ appendObjectTo(rendererContext, returnedAdapter, rootRepresentation);
+
+ break;
+
+ case LIST:
+
+ rootRepresentation = JsonRepresentation.newArray();
+
+ final CollectionFacet collectionFacet = returnType.getFacet(CollectionFacet.class);
+ final Collection<ObjectAdapter> collectionAdapters = collectionFacet.collection(returnedAdapter);
+ appendIterableTo(rendererContext, collectionAdapters, rootRepresentation);
+
+ // $$ro representation will be an object in the list with a single property named "$$ro"
+ if(!suppressRO) {
+ JsonRepresentation $$roContainerRepresentation = JsonRepresentation.newMap();
+ rootRepresentation.arrayAdd($$roContainerRepresentation);
+ $$roContainerRepresentation.mapPut("$$ro", $$roRepresentation);
+ }
+
+ break;
+
+ case SCALAR_VALUE:
+ case VOID:
+
+ // not supported
+ return null;
+ }
+
+ final Response.ResponseBuilder responseBuilder =
+ restfulObjectsV1_0.buildResponseTo(
+ rendererContext, objectAndActionInvocation, $$roRepresentation, rootRepresentation);
+
+ // set appropriate Content-Type
+ responseBuilder.type(
+ resultType == ActionResultRepresentation.ResultType.DOMAIN_OBJECT
+ ? CONTENT_TYPE_OAI_V1_OBJECT
+ : CONTENT_TYPE_OAI_V1_LIST
+ );
+
+ return responseBuilder(responseBuilder);
}
/**
@@ -165,6 +288,115 @@ public class ContentNegotiationServiceSimplified extends ContentNegotiationServi
return responseBuilder;
}
+ boolean canAccept(final RepresentationService.Context2 rendererContext) {
+ final List<MediaType> acceptableMediaTypes = rendererContext.getAcceptableMediaTypes();
+ return mediaTypeParameterMatches(acceptableMediaTypes, "profile", ACCEPT_PROFILE);
+ }
+
+ protected boolean suppress(
+ final RepresentationService.Context2 rendererContext) {
+ final List<MediaType> acceptableMediaTypes = rendererContext.getAcceptableMediaTypes();
+ return mediaTypeParameterMatches(acceptableMediaTypes, "suppress", "true");
+ }
+
+ private void appendObjectTo(
+ final RepresentationService.Context2 rendererContext,
+ final ObjectAdapter objectAdapter,
+ final JsonRepresentation rootRepresentation) {
+
+ appendPropertiesTo(rendererContext, objectAdapter, rootRepresentation);
+
+ final List<OneToManyAssociation> collections = objectAdapter.getSpecification().getCollections(Contributed.INCLUDED);
+ final Where where = rendererContext.getWhere();
+ for (final OneToManyAssociation collection : collections) {
+
+ final JsonRepresentation collectionRepresentation = JsonRepresentation.newArray();
+
+ rootRepresentation.mapPut(collection.getId(), collectionRepresentation);
+
+ final InteractionInitiatedBy interactionInitiatedBy = determineInteractionInitiatedByFrom(rendererContext);
+ final Consent visibility = collection.isVisible(objectAdapter, interactionInitiatedBy, where);
+ if (!visibility.isAllowed()) {
+ continue;
+ }
+
+ appendCollectionTo(rendererContext, objectAdapter, collection, collectionRepresentation);
+ }
+ }
+
+ private void appendPropertiesTo(
+ final RepresentationService.Context2 rendererContext,
+ final ObjectAdapter objectAdapter,
+ final JsonRepresentation rootRepresentation) {
+ final InteractionInitiatedBy interactionInitiatedBy = determineInteractionInitiatedByFrom(rendererContext);
+ final Where where = rendererContext.getWhere();
+ List<OneToOneAssociation> properties = objectAdapter.getSpecification().getProperties(Contributed.INCLUDED);
+ for (final OneToOneAssociation property : properties) {
+
+ final Consent visibility = property.isVisible(objectAdapter, interactionInitiatedBy, where);
+ if (!visibility.isAllowed()) {
+ continue;
+ }
+
+ final JsonRepresentation propertyRepresentation = JsonRepresentation.newMap();
+ final ObjectPropertyReprRenderer renderer =
+ new ObjectPropertyReprRenderer(rendererContext, null, property.getId(), propertyRepresentation)
+ .asStandalone();
+ renderer.with(new ObjectAndProperty(objectAdapter, property));
+
+ final JsonRepresentation propertyValueRepresentation = renderer.render();
+
+ final String upHref = propertyValueRepresentation.getString("links[rel=up].href");
+ rootRepresentation.mapPut("$$href", upHref);
+ final String upTitle = propertyValueRepresentation.getString("links[rel=up].title");
+ rootRepresentation.mapPut("$$title", upTitle);
+
+ final JsonRepresentation value = propertyValueRepresentation.getRepresentation("value");
+ rootRepresentation.mapPut(property.getId(), value);
+ }
+ }
+
+ private void appendCollectionTo(
+ final RepresentationService.Context2 rendererContext,
+ final ObjectAdapter objectAdapter,
+ final OneToManyAssociation collection,
+ final JsonRepresentation representation) {
+
+ final InteractionInitiatedBy interactionInitiatedBy = determineInteractionInitiatedByFrom(rendererContext);
+ final ObjectAdapter valueAdapter = collection.get(objectAdapter, interactionInitiatedBy);
+ if (valueAdapter == null) {
+ return;
+ }
+
+ final CollectionFacet facet = CollectionFacetUtils.getCollectionFacetFromSpec(valueAdapter);
+ final Iterable<ObjectAdapter> iterable = facet.iterable(valueAdapter);
+ appendIterableTo(rendererContext, iterable, representation);
+ }
+
+ private void appendIterableTo(
+ final RepresentationService.Context2 rendererContext,
+ final Iterable<ObjectAdapter> iterable,
+ final JsonRepresentation collectionRepresentation) {
+ for (final ObjectAdapter elementAdapter : iterable) {
+
+ JsonRepresentation elementRepresentation = JsonRepresentation.newMap();
+ appendPropertiesTo(rendererContext, elementAdapter, elementRepresentation);
+
+ collectionRepresentation.arrayAdd(elementRepresentation);
+ }
+ }
+
+ private static InteractionInitiatedBy determineInteractionInitiatedByFrom(
+ final RendererContext rendererContext) {
+ if (rendererContext instanceof RepresentationService.Context4) {
+ return ((RepresentationService.Context4) rendererContext).getInteractionInitiatedBy();
+ } else {
+ // fallback
+ return InteractionInitiatedBy.USER;
+ }
+ }
+
+
@Inject
protected DomainObjectContainer container;
}