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 2013/02/08 14:16:19 UTC
[4/24] ISIS-323: lots more refactoring of RO
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainTypeResourceServerside.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainTypeResourceServerside.java b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainTypeResourceServerside.java
new file mode 100644
index 0000000..16e02c5
--- /dev/null
+++ b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainTypeResourceServerside.java
@@ -0,0 +1,339 @@
+/*
+ * 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.viewer.restfulobjects.server.resources;
+
+import java.util.Collection;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+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.ObjectMember;
+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.RepresentationType;
+import org.apache.isis.viewer.restfulobjects.applib.RestfulMediaType;
+import org.apache.isis.viewer.restfulobjects.applib.RestfulResponse.HttpStatusCode;
+import org.apache.isis.viewer.restfulobjects.applib.domaintypes.DomainTypeResource;
+import org.apache.isis.viewer.restfulobjects.applib.links.Rel;
+import org.apache.isis.viewer.restfulobjects.rendering.LinkBuilder;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererFactory;
+import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.DomainObjectReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.domaintypes.ActionDescriptionReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.domaintypes.ActionParameterDescriptionReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.domaintypes.CollectionDescriptionReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.domaintypes.DomainTypeReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.domaintypes.ParentSpecAndAction;
+import org.apache.isis.viewer.restfulobjects.rendering.domaintypes.ParentSpecAndActionParam;
+import org.apache.isis.viewer.restfulobjects.rendering.domaintypes.ParentSpecAndCollection;
+import org.apache.isis.viewer.restfulobjects.rendering.domaintypes.ParentSpecAndProperty;
+import org.apache.isis.viewer.restfulobjects.rendering.domaintypes.PropertyDescriptionReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.domaintypes.TypeActionResultReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.domaintypes.TypeListReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.util.UrlParserUtils;
+import org.apache.isis.viewer.restfulobjects.server.RestfulObjectsApplicationException;
+import org.jboss.resteasy.annotations.ClientResponseType;
+
+import com.google.common.base.Strings;
+
+/**
+ * Implementation note: it seems to be necessary to annotate the implementation
+ * with {@link Path} rather than the interface (at least under RestEasy 1.0.2
+ * and 1.1-RC2).
+ */
+@Path("/domainTypes")
+public class DomainTypeResourceServerside extends ResourceAbstract implements DomainTypeResource {
+
+ @Override
+ @GET
+ @Path("/")
+ @Produces({ MediaType.APPLICATION_JSON, RestfulMediaType.APPLICATION_JSON_TYPE_LIST })
+ public Response domainTypes() {
+ final RepresentationType representationType = RepresentationType.TYPE_LIST;
+ init(representationType, Where.ANYWHERE);
+
+ final Collection<ObjectSpecification> allSpecifications = getSpecificationLoader().allSpecifications();
+
+ final RendererFactory rendererFactory = rendererFactoryRegistry.find(representationType);
+
+ final TypeListReprRenderer renderer = (TypeListReprRenderer) rendererFactory.newRenderer(getResourceContext(), null, JsonRepresentation.newMap());
+ renderer.with(allSpecifications).includesSelf();
+
+ return responseOfOk(renderer, Caching.ONE_DAY).build();
+ }
+
+ @Override
+ @GET
+ @Path("/{domainType}")
+ @Produces({ MediaType.APPLICATION_JSON, RestfulMediaType.APPLICATION_JSON_DOMAIN_TYPE })
+ public Response domainType(@PathParam("domainType") final String domainType) {
+
+ final RepresentationType representationType = RepresentationType.DOMAIN_TYPE;
+ init(representationType, Where.ANYWHERE);
+
+ final ObjectSpecification objectSpec = getSpecificationLoader().loadSpecification(domainType);
+
+ final RendererFactory rendererFactory = rendererFactoryRegistry.find(representationType);
+
+ final DomainTypeReprRenderer renderer = (DomainTypeReprRenderer) rendererFactory.newRenderer(getResourceContext(), null, JsonRepresentation.newMap());
+ renderer.with(objectSpec).includesSelf();
+
+ return responseOfOk(renderer, Caching.ONE_DAY).build();
+ }
+
+ @Override
+ @GET
+ @Path("/{domainType}/properties/{propertyId}")
+ @Produces({ MediaType.APPLICATION_JSON, RestfulMediaType.APPLICATION_JSON_PROPERTY_DESCRIPTION })
+ public Response typeProperty(@PathParam("domainType") final String domainType, @PathParam("propertyId") final String propertyId) {
+ final RepresentationType representationType = RepresentationType.PROPERTY_DESCRIPTION;
+ init(representationType, Where.ANYWHERE);
+
+ final ObjectSpecification parentSpec = getSpecificationLoader().loadSpecification(domainType);
+ if (parentSpec == null) {
+ throw RestfulObjectsApplicationException.create(HttpStatusCode.NOT_FOUND);
+ }
+
+ final ObjectMember objectMember = parentSpec.getAssociation(propertyId);
+ if (objectMember == null || objectMember.isOneToManyAssociation()) {
+ throw RestfulObjectsApplicationException.create(HttpStatusCode.NOT_FOUND);
+ }
+ final OneToOneAssociation property = (OneToOneAssociation) objectMember;
+
+ final RendererFactory rendererFactory = rendererFactoryRegistry.find(representationType);
+
+ final PropertyDescriptionReprRenderer renderer = (PropertyDescriptionReprRenderer) rendererFactory.newRenderer(getResourceContext(), null, JsonRepresentation.newMap());
+ renderer.with(new ParentSpecAndProperty(parentSpec, property)).includesSelf();
+
+ return responseOfOk(renderer, Caching.ONE_DAY).build();
+ }
+
+ @Override
+ @GET
+ @Path("/{domainType}/collections/{collectionId}")
+ @Produces({ MediaType.APPLICATION_JSON, RestfulMediaType.APPLICATION_JSON_COLLECTION_DESCRIPTION })
+ public Response typeCollection(@PathParam("domainType") final String domainType, @PathParam("collectionId") final String collectionId) {
+ final RepresentationType representationType = RepresentationType.COLLECTION_DESCRIPTION;
+ init(representationType, Where.ANYWHERE);
+
+ final ObjectSpecification parentSpec = getSpecificationLoader().loadSpecification(domainType);
+ if (parentSpec == null) {
+ throw RestfulObjectsApplicationException.create(HttpStatusCode.NOT_FOUND);
+ }
+
+ final ObjectMember objectMember = parentSpec.getAssociation(collectionId);
+ if (objectMember == null || objectMember.isOneToOneAssociation()) {
+ throw RestfulObjectsApplicationException.create(HttpStatusCode.NOT_FOUND);
+ }
+ final OneToManyAssociation collection = (OneToManyAssociation) objectMember;
+
+ final RendererFactory rendererFactory = rendererFactoryRegistry.find(representationType);
+
+ final CollectionDescriptionReprRenderer renderer = (CollectionDescriptionReprRenderer) rendererFactory.newRenderer(getResourceContext(), null, JsonRepresentation.newMap());
+ renderer.with(new ParentSpecAndCollection(parentSpec, collection)).includesSelf();
+
+ return responseOfOk(renderer, Caching.ONE_DAY).build();
+ }
+
+ @Override
+ @GET
+ @Path("/{domainType}/actions/{actionId}")
+ @Produces({ MediaType.APPLICATION_JSON, RestfulMediaType.APPLICATION_JSON_ACTION_DESCRIPTION })
+ public Response typeAction(@PathParam("domainType") final String domainType, @PathParam("actionId") final String actionId) {
+ final RepresentationType representationType = RepresentationType.ACTION_DESCRIPTION;
+ init(representationType, Where.ANYWHERE);
+
+ final ObjectSpecification parentSpec = getSpecificationLoader().loadSpecification(domainType);
+ if (parentSpec == null) {
+ throw RestfulObjectsApplicationException.create(HttpStatusCode.NOT_FOUND);
+ }
+
+ final ObjectMember objectMember = parentSpec.getObjectAction(actionId);
+ if (objectMember == null) {
+ throw RestfulObjectsApplicationException.create(HttpStatusCode.NOT_FOUND);
+ }
+ final ObjectAction action = (ObjectAction) objectMember;
+
+ final RendererFactory rendererFactory = rendererFactoryRegistry.find(representationType);
+
+ final ActionDescriptionReprRenderer renderer = (ActionDescriptionReprRenderer) rendererFactory.newRenderer(getResourceContext(), null, JsonRepresentation.newMap());
+ renderer.with(new ParentSpecAndAction(parentSpec, action)).includesSelf();
+
+ return responseOfOk(renderer, Caching.ONE_DAY).build();
+ }
+
+ @Override
+ @GET
+ @Path("/{domainType}/actions/{actionId}/params/{paramName}")
+ @Produces({ MediaType.APPLICATION_JSON, RestfulMediaType.APPLICATION_JSON_ACTION_PARAMETER_DESCRIPTION })
+ public Response typeActionParam(@PathParam("domainType") final String domainType, @PathParam("actionId") final String actionId, @PathParam("paramName") final String paramName) {
+ final RepresentationType representationType = RepresentationType.ACTION_PARAMETER_DESCRIPTION;
+ init(representationType, Where.ANYWHERE);
+
+ final ObjectSpecification parentSpec = getSpecificationLoader().loadSpecification(domainType);
+ if (parentSpec == null) {
+ throw RestfulObjectsApplicationException.create(HttpStatusCode.NOT_FOUND);
+ }
+
+ final ObjectMember objectMember = parentSpec.getObjectAction(actionId);
+ if (objectMember == null) {
+ throw RestfulObjectsApplicationException.create(HttpStatusCode.NOT_FOUND);
+ }
+ final ObjectAction parentAction = (ObjectAction) objectMember;
+
+ final ObjectActionParameter actionParam = parentAction.getParameterByName(paramName);
+
+ final RendererFactory rendererFactory = rendererFactoryRegistry.find(representationType);
+
+ final ActionParameterDescriptionReprRenderer renderer = (ActionParameterDescriptionReprRenderer) rendererFactory.newRenderer(getResourceContext(), null, JsonRepresentation.newMap());
+ renderer.with(new ParentSpecAndActionParam(parentSpec, actionParam)).includesSelf();
+
+ return responseOfOk(renderer, Caching.ONE_DAY).build();
+ }
+
+ // //////////////////////////////////////////////////////////
+ // domain type actions
+ // //////////////////////////////////////////////////////////
+
+ @Override
+ @GET
+ @Path("/{domainType}/typeactions/isSubtypeOf/invoke")
+ @Produces({ MediaType.APPLICATION_JSON, RestfulMediaType.APPLICATION_JSON_TYPE_ACTION_RESULT, RestfulMediaType.APPLICATION_JSON_ERROR })
+ public Response domainTypeIsSubtypeOf(@PathParam("domainType") final String domainType, @QueryParam("supertype") final String superTypeStr, // simple
+ // style
+ @QueryParam("args") final String args // formal style
+ ) {
+
+ final RepresentationType representationType = RepresentationType.TYPE_ACTION_RESULT;
+ init(Where.ANYWHERE);
+
+ final String supertype = domainTypeFor(superTypeStr, args, "supertype");
+
+ final ObjectSpecification domainTypeSpec = getSpecificationLoader().loadSpecification(domainType);
+ final ObjectSpecification supertypeSpec = getSpecificationLoader().loadSpecification(supertype);
+
+ final RendererFactory rendererFactory = rendererFactoryRegistry.find(representationType);
+ final TypeActionResultReprRenderer renderer = (TypeActionResultReprRenderer) rendererFactory.newRenderer(getResourceContext(), null, JsonRepresentation.newMap());
+
+ final String url = "domainTypes/" + domainTypeSpec.getFullIdentifier() + "/typeactions/isSubtypeOf/invoke";
+ final LinkBuilder linkBuilder = LinkBuilder.newBuilder(getResourceContext(), Rel.SELF, RepresentationType.TYPE_ACTION_RESULT, url);
+ final JsonRepresentation arguments = DomainTypeReprRenderer.argumentsTo(getResourceContext(), "supertype", supertypeSpec);
+ final JsonRepresentation selfLink = linkBuilder.withArguments(arguments).build();
+
+ final boolean value = domainTypeSpec.isOfType(supertypeSpec);
+ renderer.with(domainTypeSpec).withSelf(selfLink).withValue(value);
+
+ return responseOfOk(renderer, Caching.ONE_DAY).build();
+ }
+
+ @Override
+ @GET
+ @Path("/{domainType}/typeactions/isSupertypeOf/invoke")
+ @Produces({ MediaType.APPLICATION_JSON, RestfulMediaType.APPLICATION_JSON_TYPE_ACTION_RESULT, RestfulMediaType.APPLICATION_JSON_ERROR })
+ public Response domainTypeIsSupertypeOf(
+ @PathParam("domainType") final String domainType,
+ @QueryParam("subtype") final String subTypeStr, // simple style
+ @QueryParam("args") final String args // formal style
+ ) {
+
+ final RepresentationType representationType = RepresentationType.TYPE_ACTION_RESULT;
+ init(Where.ANYWHERE);
+
+ final String subtype = domainTypeFor(subTypeStr, args, "subtype");
+
+ final ObjectSpecification domainTypeSpec = getSpecificationLoader().loadSpecification(domainType);
+ final ObjectSpecification subtypeSpec = getSpecificationLoader().loadSpecification(subtype);
+
+ final RendererFactory rendererFactory = rendererFactoryRegistry.find(representationType);
+ final TypeActionResultReprRenderer renderer = (TypeActionResultReprRenderer) rendererFactory.newRenderer(getResourceContext(), null, JsonRepresentation.newMap());
+
+ final String url = "domainTypes/" + domainTypeSpec.getFullIdentifier() + "/typeactions/isSupertypeOf/invoke";
+ final LinkBuilder linkBuilder = LinkBuilder.newBuilder(getResourceContext(), Rel.SELF, RepresentationType.TYPE_ACTION_RESULT, url);
+ final JsonRepresentation arguments = DomainTypeReprRenderer.argumentsTo(getResourceContext(), "subtype", subtypeSpec);
+ final JsonRepresentation selfLink = linkBuilder.withArguments(arguments).build();
+
+ final boolean value = subtypeSpec.isOfType(domainTypeSpec);
+ renderer.with(domainTypeSpec).withSelf(selfLink).withValue(value);
+
+ return responseOfOk(renderer, Caching.ONE_DAY).build();
+ }
+
+ @Override
+ @GET
+ @Path("/{domainType}/typeactions/newTransientInstance/invoke")
+ @Produces({ MediaType.APPLICATION_JSON, RestfulMediaType.APPLICATION_JSON_TYPE_ACTION_RESULT, RestfulMediaType.APPLICATION_JSON_ERROR })
+ @ClientResponseType(entityType = String.class)
+ public Response newTransientInstance(@PathParam("domainType") final String domainTypeStr, @QueryParam("args") final String args) {
+
+ final RepresentationType representationType = RepresentationType.TYPE_ACTION_RESULT;
+ init(representationType, Where.ANYWHERE);
+
+ final String domainType = domainTypeFor(domainTypeStr, args, "domainType");
+
+ final ObjectSpecification domainTypeSpec = getSpecificationLoader().loadSpecification(domainType);
+
+ final RendererFactory rendererFactory = rendererFactoryRegistry.find(representationType);
+ final TypeActionResultReprRenderer renderer = (TypeActionResultReprRenderer) rendererFactory.newRenderer(getResourceContext(), null, JsonRepresentation.newMap());
+
+ final String url = "domainTypes/" + domainTypeSpec.getFullIdentifier() + "/typeactions/newTransientInstance/invoke";
+ final LinkBuilder linkBuilder = LinkBuilder.newBuilder(getResourceContext(), Rel.SELF, RepresentationType.TYPE_ACTION_RESULT, url);
+ final JsonRepresentation selfLink = linkBuilder.build();
+
+ final RendererFactory domainObjectRendererFactory = rendererFactoryRegistry.find(RepresentationType.DOMAIN_OBJECT);
+ final DomainObjectReprRenderer domainObjectRenderer = (DomainObjectReprRenderer) domainObjectRendererFactory.newRenderer(getResourceContext(), null, JsonRepresentation.newMap());
+ final ObjectAdapter transientInstance = getResourceContext().getPersistenceSession().createTransientInstance(domainTypeSpec);
+ domainObjectRenderer.with(transientInstance).includesSelf();
+
+ renderer.with(domainTypeSpec).withSelf(selfLink).withValue(domainObjectRenderer.render());
+
+ return responseOfOk(renderer, Caching.ONE_DAY).build();
+ }
+
+ private static String domainTypeFor(final String domainTypeStr, final String argumentsQueryString, final String argsParamName) {
+ // simple style; simple return
+ if (!Strings.isNullOrEmpty(domainTypeStr)) {
+ return domainTypeStr;
+ }
+
+ // formal style; must parse from args that has a link with an href to
+ // the domain type
+ final String href = linkFromFormalArgs(argumentsQueryString, argsParamName);
+ return UrlParserUtils.domainTypeFrom(href);
+ }
+
+ private static String linkFromFormalArgs(final String argumentsQueryString, final String paramName) {
+ final JsonRepresentation arguments = DomainResourceHelper.readQueryStringAsMap(argumentsQueryString);
+ if (!arguments.isLink(paramName)) {
+ throw RestfulObjectsApplicationException.create(HttpStatusCode.BAD_REQUEST, "Args should contain a link '%s'", paramName);
+ }
+
+ return arguments.getLink(paramName).getHref();
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/HomePageReprRenderer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/HomePageReprRenderer.java b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/HomePageReprRenderer.java
new file mode 100644
index 0000000..49c881b
--- /dev/null
+++ b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/HomePageReprRenderer.java
@@ -0,0 +1,165 @@
+/*
+ * 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.viewer.restfulobjects.server.resources;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+import org.apache.isis.viewer.restfulobjects.applib.links.Rel;
+import org.apache.isis.viewer.restfulobjects.rendering.LinkBuilder;
+import org.apache.isis.viewer.restfulobjects.rendering.LinkFollower;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererContext;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererFactory;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererFactoryRegistry;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererAbstract;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererFactoryAbstract;
+import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.DomainServiceLinkTo;
+import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.ListReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.domaintypes.TypeListReprRenderer;
+import org.apache.isis.viewer.restfulobjects.server.ResourceContext;
+
+public class HomePageReprRenderer extends ReprRendererAbstract<HomePageReprRenderer, Void> {
+
+ public static class Factory extends ReprRendererFactoryAbstract {
+ public Factory() {
+ super(RepresentationType.HOME_PAGE);
+ }
+
+ @Override
+ public ReprRenderer<?, ?> newRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final JsonRepresentation representation) {
+ return new HomePageReprRenderer(resourceContext, linkFollower, getRepresentationType(), representation);
+ }
+ }
+
+ private HomePageReprRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final RepresentationType representationType, final JsonRepresentation representation) {
+ super(resourceContext, linkFollower, representationType, representation);
+ }
+
+ @Override
+ public HomePageReprRenderer with(final Void t) {
+ return this;
+ }
+
+ @Override
+ public JsonRepresentation render() {
+
+ // self
+ if (includesSelf) {
+ addLinkToSelf(representation);
+ }
+
+ addLinkToUser(getResourceContext().getAuthenticationSession());
+ addLinkToServices(((ResourceContext)getResourceContext()).getPersistenceSession().getServices());
+ addLinkToVersion();
+ addLinkToDomainTypes(((ResourceContext)getResourceContext()).getSpecificationLookup().allSpecifications());
+
+ // inks and extensions
+ representation.mapPut("extensions", JsonRepresentation.newMap());
+
+ return representation;
+ }
+
+ private void addLinkToSelf(final JsonRepresentation representation) {
+ final JsonRepresentation link = LinkBuilder.newBuilder(resourceContext, Rel.SELF, getRepresentationType(), "").build();
+
+ final LinkFollower linkFollower = getLinkFollower().follow("links[rel=self]");
+ if (linkFollower.matches(link)) {
+
+ final RendererFactory factory = RendererFactoryRegistry.instance.find(RepresentationType.HOME_PAGE);
+ final HomePageReprRenderer renderer = (HomePageReprRenderer) factory.newRenderer(getResourceContext(), linkFollower, JsonRepresentation.newMap());
+
+ link.mapPut("value", renderer.render());
+ }
+ getLinks().arrayAdd(link);
+ }
+
+ private void addLinkToVersion() {
+ final JsonRepresentation link = LinkBuilder.newBuilder(getResourceContext(), Rel.VERSION, RepresentationType.VERSION, "version").build();
+
+ final LinkFollower linkFollower = getLinkFollower().follow("links[rel=version]");
+ if (linkFollower.matches(link)) {
+
+ final RendererFactory factory = RendererFactoryRegistry.instance.find(RepresentationType.VERSION);
+ final VersionReprRenderer renderer = (VersionReprRenderer) factory.newRenderer(getResourceContext(), linkFollower, JsonRepresentation.newMap());
+
+ link.mapPut("value", renderer.render());
+ }
+
+ getLinks().arrayAdd(link);
+ }
+
+ private void addLinkToServices(List<ObjectAdapter> serviceAdapters) {
+
+ final JsonRepresentation link = LinkBuilder.newBuilder(getResourceContext(), Rel.SERVICES, RepresentationType.LIST, "services").build();
+
+ final LinkFollower linkFollower = getLinkFollower().follow("links[rel=services]");
+ if (linkFollower.matches(link)) {
+
+ final RendererFactory factory = RendererFactoryRegistry.instance.find(RepresentationType.LIST);
+
+ final ListReprRenderer renderer = (ListReprRenderer) factory.newRenderer(getResourceContext(), linkFollower, JsonRepresentation.newMap());
+ renderer.usingLinkToBuilder(new DomainServiceLinkTo()).withSelf("services").with(serviceAdapters);
+
+ link.mapPut("value", renderer.render());
+ }
+
+ getLinks().arrayAdd(link);
+ }
+
+ private void addLinkToUser(AuthenticationSession authenticationSession) {
+ final JsonRepresentation link = LinkBuilder.newBuilder(getResourceContext(), Rel.USER, RepresentationType.USER, "user").build();
+
+ final LinkFollower linkFollower = getLinkFollower().follow("links[rel=user]");
+ if (linkFollower.matches(link)) {
+ final RendererFactory factory = RendererFactoryRegistry.instance.find(RepresentationType.USER);
+ final UserReprRenderer renderer = (UserReprRenderer) factory.newRenderer(getResourceContext(), linkFollower, JsonRepresentation.newMap());
+ renderer.with(authenticationSession);
+
+ link.mapPut("value", renderer.render());
+ }
+
+ getLinks().arrayAdd(link);
+ }
+
+ private void addLinkToDomainTypes(final Collection<ObjectSpecification> specifications) {
+
+ final JsonRepresentation link = LinkBuilder.newBuilder(getResourceContext(), Rel.TYPES, RepresentationType.TYPE_LIST, "domainTypes").build();
+
+ final LinkFollower linkFollower = getLinkFollower().follow("links[rel=types]");
+ if (linkFollower.matches(link)) {
+
+ final RendererFactory factory = RendererFactoryRegistry.instance.find(RepresentationType.TYPE_LIST);
+
+ final TypeListReprRenderer renderer = (TypeListReprRenderer) factory.newRenderer(getResourceContext(), linkFollower, JsonRepresentation.newMap());
+
+ renderer.withSelf("domainTypes").with(specifications);
+
+ link.mapPut("value", renderer.render());
+ }
+
+ getLinks().arrayAdd(link);
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/HomePageResourceServerside.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/HomePageResourceServerside.java b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/HomePageResourceServerside.java
new file mode 100644
index 0000000..b3d7b66
--- /dev/null
+++ b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/HomePageResourceServerside.java
@@ -0,0 +1,65 @@
+/*
+ * 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.viewer.restfulobjects.server.resources;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+import org.apache.isis.viewer.restfulobjects.applib.RestfulMediaType;
+import org.apache.isis.viewer.restfulobjects.applib.RestfulResponse.HttpStatusCode;
+import org.apache.isis.viewer.restfulobjects.applib.homepage.HomePageResource;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererFactory;
+import org.apache.isis.viewer.restfulobjects.server.RestfulObjectsApplicationException;
+
+/**
+ * Implementation note: it seems to be necessary to annotate the implementation
+ * with {@link Path} rather than the interface (at least under RestEasy 1.0.2
+ * and 1.1-RC2).
+ */
+public class HomePageResourceServerside extends ResourceAbstract implements HomePageResource {
+
+ @Override
+ @Produces({ RestfulMediaType.APPLICATION_JSON_HOME_PAGE })
+ public Response homePage() {
+ final RepresentationType representationType = RepresentationType.HOME_PAGE;
+ init(representationType, Where.NOWHERE);
+
+ final RendererFactory factory = rendererFactoryRegistry.find(representationType);
+ final HomePageReprRenderer renderer = (HomePageReprRenderer) factory.newRenderer(getResourceContext(), null, JsonRepresentation.newMap());
+ renderer.includesSelf();
+
+ return responseOfOk(renderer, Caching.ONE_DAY).build();
+ }
+
+ @Override
+ @GET
+ @Path("/notAuthenticated")
+ @Produces({ MediaType.APPLICATION_JSON })
+ public Response notAuthenticated() {
+
+ throw RestfulObjectsApplicationException.create(HttpStatusCode.UNAUTHORIZED);
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/ResourceAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/ResourceAbstract.java b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/ResourceAbstract.java
new file mode 100644
index 0000000..aa4397e
--- /dev/null
+++ b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/ResourceAbstract.java
@@ -0,0 +1,254 @@
+/*
+ * 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.viewer.restfulobjects.server.resources;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.CacheControl;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.applib.profiles.Localization;
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.adapter.version.Version;
+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.SpecificationLoaderSpi;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.core.runtime.system.persistence.OidGenerator;
+import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
+import org.apache.isis.viewer.restfulobjects.applib.MediaTypes;
+import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+import org.apache.isis.viewer.restfulobjects.applib.RestfulResponse.HttpStatusCode;
+import org.apache.isis.viewer.restfulobjects.applib.util.JsonMapper;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererFactoryRegistry;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.util.OidUtils;
+import org.apache.isis.viewer.restfulobjects.rendering.util.UrlDecoderUtils;
+import org.apache.isis.viewer.restfulobjects.server.ResourceContext;
+import org.apache.isis.viewer.restfulobjects.server.RestfulObjectsApplicationException;
+import org.codehaus.jackson.JsonGenerationException;
+import org.codehaus.jackson.map.JsonMappingException;
+
+public abstract class ResourceAbstract {
+
+ protected final static JsonMapper jsonMapper = JsonMapper.instance();
+
+ public enum Caching {
+ ONE_DAY(24 * 60 * 60), ONE_HOUR(60 * 60), NONE(0);
+
+ private final CacheControl cacheControl;
+
+ private Caching(final int maxAge) {
+ this.cacheControl = new CacheControl();
+ if (maxAge > 0) {
+ cacheControl.setMaxAge(maxAge);
+ } else {
+ cacheControl.setNoCache(true);
+ }
+ }
+
+ public CacheControl getCacheControl() {
+ return cacheControl;
+ }
+ }
+
+ // nb: SET is excluded; we simply flatten contributed actions.
+ public final static ActionType[] ACTION_TYPES = { ActionType.USER, ActionType.DEBUG, ActionType.EXPLORATION };
+
+ // TODO: should inject this instead...
+ protected final static RendererFactoryRegistry rendererFactoryRegistry = RendererFactoryRegistry.instance;
+
+ @Context
+ HttpHeaders httpHeaders;
+
+ @Context
+ UriInfo uriInfo;
+
+ @Context
+ Request request;
+
+ @Context
+ HttpServletRequest httpServletRequest;
+
+ @Context
+ HttpServletResponse httpServletResponse;
+
+ @Context
+ SecurityContext securityContext;
+
+ private ResourceContext resourceContext;
+
+ protected void init(Where where) {
+ init(RepresentationType.GENERIC, where);
+ }
+
+ protected void init(final RepresentationType representationType, Where where) {
+ if (!IsisContext.inSession()) {
+ throw RestfulObjectsApplicationException.create(HttpStatusCode.UNAUTHORIZED);
+ }
+ if (getAuthenticationSession() == null) {
+ throw RestfulObjectsApplicationException.create(HttpStatusCode.UNAUTHORIZED);
+ }
+
+ this.resourceContext = new ResourceContext(representationType, httpHeaders, uriInfo, request, httpServletRequest, httpServletResponse, securityContext, getLocalization(), getAuthenticationSession(), getPersistenceSession(), getAdapterManager(), getSpecificationLoader(), getConfiguration(), where);
+ }
+
+ protected ResourceContext getResourceContext() {
+ return resourceContext;
+ }
+
+ // //////////////////////////////////////////////////////////////
+ // Rendering
+ // //////////////////////////////////////////////////////////////
+
+ protected static String jsonFor(final Object object) {
+ try {
+ return jsonMapper.write(object);
+ } catch (final JsonGenerationException e) {
+ throw new RuntimeException(e);
+ } catch (final JsonMappingException e) {
+ throw new RuntimeException(e);
+ } catch (final IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ // //////////////////////////////////////////////////////////////
+ // Isis integration
+ // //////////////////////////////////////////////////////////////
+
+ protected ObjectSpecification getSpecification(final String specFullName) {
+ return getSpecificationLoader().loadSpecification(specFullName);
+ }
+
+ protected ObjectAdapter getObjectAdapter(final String oidEncodedStr) {
+
+ final ObjectAdapter objectAdapter = OidUtils.getObjectAdapter(resourceContext, oidEncodedStr);
+
+ if (objectAdapter == null) {
+ final String oidStr = UrlDecoderUtils.urlDecode(oidEncodedStr);
+ throw RestfulObjectsApplicationException.create(HttpStatusCode.NOT_FOUND, "could not determine adapter for OID: '%s'", oidStr);
+ }
+ return objectAdapter;
+ }
+
+ protected ObjectAdapter getServiceAdapter(final String serviceId) {
+ final List<ObjectAdapter> serviceAdapters = getPersistenceSession().getServices();
+ for (final ObjectAdapter serviceAdapter : serviceAdapters) {
+ final Object servicePojo = serviceAdapter.getObject();
+ final String id = ServiceUtil.id(servicePojo);
+ if (serviceId.equals(id)) {
+ return serviceAdapter;
+ }
+ }
+ throw RestfulObjectsApplicationException.create(HttpStatusCode.NOT_FOUND, "Could not locate service '%s'", serviceId);
+ }
+
+ protected String getOidStr(final ObjectAdapter objectAdapter) {
+ return OidUtils.getOidStr(resourceContext, objectAdapter);
+ }
+
+ // //////////////////////////////////////////////////////////////
+ // Responses
+ // //////////////////////////////////////////////////////////////
+
+ public static ResponseBuilder responseOfNoContent() {
+ return responseOf(HttpStatusCode.NO_CONTENT);
+ }
+
+ public static ResponseBuilder responseOfOk(final ReprRenderer<?, ?> renderer, final Caching caching) {
+ return responseOfOk(renderer, caching, null);
+ }
+
+ public static ResponseBuilder responseOfOk(final ReprRenderer<?, ?> renderer, final Caching caching, final Version version) {
+ final RepresentationType representationType = renderer.getRepresentationType();
+ final ResponseBuilder response = responseOf(HttpStatusCode.OK).type(MediaTypes.guavaToJaxRs(representationType.getMediaType())).cacheControl(caching.getCacheControl()).entity(jsonFor(renderer.render()));
+ return addLastModifiedAndETagIfAvailable(response, version);
+ }
+
+ private static ResponseBuilder responseOf(final HttpStatusCode httpStatusCode) {
+ return Response.status(httpStatusCode.getJaxrsStatusType()).type(MediaType.APPLICATION_JSON_TYPE);
+ }
+
+ public static ResponseBuilder addLastModifiedAndETagIfAvailable(final ResponseBuilder responseBuilder, final Version version) {
+ if (version != null && version.getTime() != null) {
+ final Date time = version.getTime();
+ responseBuilder.lastModified(time);
+ responseBuilder.tag("" + time);
+ }
+ return responseBuilder;
+ }
+
+ // //////////////////////////////////////////////////////////////
+ // Dependencies (from singletons)
+ // //////////////////////////////////////////////////////////////
+
+ protected IsisConfiguration getConfiguration () {
+ return IsisContext.getConfiguration();
+ }
+
+ protected AuthenticationSession getAuthenticationSession() {
+ return IsisContext.getAuthenticationSession();
+ }
+
+ protected SpecificationLoaderSpi getSpecificationLoader() {
+ return IsisContext.getSpecificationLoader();
+ }
+
+ protected AdapterManager getAdapterManager() {
+ return getPersistenceSession().getAdapterManager();
+ }
+
+ protected PersistenceSession getPersistenceSession() {
+ return IsisContext.getPersistenceSession();
+ }
+
+ private OidGenerator getOidGenerator() {
+ return getPersistenceSession().getOidGenerator();
+ }
+
+ protected Localization getLocalization() {
+ return IsisContext.getLocalization();
+ }
+
+ // //////////////////////////////////////////////////////////////
+ // Dependencies (injected via @Context)
+ // //////////////////////////////////////////////////////////////
+
+ protected HttpServletRequest getServletRequest() {
+ return getResourceContext().getHttpServletRequest();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/UserReprRenderer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/UserReprRenderer.java b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/UserReprRenderer.java
new file mode 100644
index 0000000..ed6bf6f
--- /dev/null
+++ b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/UserReprRenderer.java
@@ -0,0 +1,66 @@
+/**
+ * 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.viewer.restfulobjects.server.resources;
+
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+import org.apache.isis.viewer.restfulobjects.rendering.LinkFollower;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererContext;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererAbstract;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererFactoryAbstract;
+
+public class UserReprRenderer extends ReprRendererAbstract<UserReprRenderer, AuthenticationSession> {
+
+ public static class Factory extends ReprRendererFactoryAbstract {
+
+ public Factory() {
+ super(RepresentationType.USER);
+ }
+
+ @Override
+ public ReprRenderer<?, ?> newRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final JsonRepresentation representation) {
+ return new UserReprRenderer(resourceContext, linkFollower, getRepresentationType(), representation);
+ }
+ }
+
+ private UserReprRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final RepresentationType representationType, final JsonRepresentation representation) {
+ super(resourceContext, linkFollower, representationType, representation);
+ }
+
+ @Override
+ public UserReprRenderer with(final AuthenticationSession authenticationSession) {
+ representation.mapPut("userName", authenticationSession.getUserName());
+ final JsonRepresentation roles = JsonRepresentation.newArray();
+ for (final String role : authenticationSession.getRoles()) {
+ roles.arrayAdd(role);
+ }
+ representation.mapPut("roles", roles);
+ return this;
+ }
+
+ @Override
+ public JsonRepresentation render() {
+ if (includesSelf) {
+ withSelf("user");
+ }
+ getExtensions();
+ return representation;
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/UserResourceServerside.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/UserResourceServerside.java b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/UserResourceServerside.java
new file mode 100644
index 0000000..eefd602
--- /dev/null
+++ b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/UserResourceServerside.java
@@ -0,0 +1,47 @@
+/*
+ * 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.viewer.restfulobjects.server.resources;
+
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+import org.apache.isis.viewer.restfulobjects.applib.RestfulMediaType;
+import org.apache.isis.viewer.restfulobjects.applib.user.UserResource;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererFactory;
+
+public class UserResourceServerside extends ResourceAbstract implements UserResource {
+
+ @Override
+ @Produces({ MediaType.APPLICATION_JSON, RestfulMediaType.APPLICATION_JSON_USER })
+ public Response user() {
+ final RepresentationType user = RepresentationType.USER;
+ init(user, Where.NOWHERE);
+
+ final RendererFactory factory = rendererFactoryRegistry.find(user);
+ final UserReprRenderer renderer = (UserReprRenderer) factory.newRenderer(getResourceContext(), null, JsonRepresentation.newMap());
+ renderer.includesSelf().with(getAuthenticationSession());
+
+ return responseOfOk(renderer, Caching.ONE_HOUR).build();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/VersionReprRenderer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/VersionReprRenderer.java b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/VersionReprRenderer.java
new file mode 100644
index 0000000..3453c93
--- /dev/null
+++ b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/VersionReprRenderer.java
@@ -0,0 +1,103 @@
+/*
+ * 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.viewer.restfulobjects.server.resources;
+
+import java.nio.charset.Charset;
+
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+import org.apache.isis.viewer.restfulobjects.rendering.LinkFollower;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererContext;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRenderer;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererAbstract;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererFactoryAbstract;
+import org.apache.isis.viewer.restfulobjects.server.RestfulObjectsApplication;
+
+import com.google.common.io.Resources;
+
+public class VersionReprRenderer extends ReprRendererAbstract<VersionReprRenderer, Void> {
+
+ private static final String META_INF_POM_PROPERTIES = "/META-INF/maven/org.apache.isis.viewer/restfulobjects-viewer/pom.properties";
+
+ public static class Factory extends ReprRendererFactoryAbstract {
+ public Factory() {
+ super(RepresentationType.VERSION);
+ }
+
+ @Override
+ public ReprRenderer<?, ?> newRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final JsonRepresentation representation) {
+ return new VersionReprRenderer(resourceContext, linkFollower, getRepresentationType(), representation);
+ }
+ }
+
+ private VersionReprRenderer(final RendererContext resourceContext, final LinkFollower linkFollower, final RepresentationType representationType, final JsonRepresentation representation) {
+ super(resourceContext, linkFollower, representationType, representation);
+ }
+
+ @Override
+ public VersionReprRenderer with(final Void t) {
+ return this;
+ }
+
+ @Override
+ public JsonRepresentation render() {
+
+ if (includesSelf) {
+ withSelf("version/");
+ }
+
+ representation.mapPut("specVersion", RestfulObjectsApplication.SPEC_VERSION);
+ representation.mapPut("implVersion", versionFromManifest());
+
+ putOptionalCapabilities();
+ putExtensions();
+
+ return representation;
+ }
+
+ private static String versionFromManifest() {
+ try {
+ return Resources.toString(Resources.getResource(META_INF_POM_PROPERTIES), Charset.defaultCharset());
+ } catch (final Exception ex) {
+ return "UNKNOWN";
+ }
+ }
+
+ private void putOptionalCapabilities() {
+ final JsonRepresentation optionalCapabilities = JsonRepresentation.newMap();
+
+ optionalCapabilities.mapPut("concurrencyChecking", "no");
+ optionalCapabilities.mapPut("transientObjects", "yes");
+ optionalCapabilities.mapPut("deleteObjects", "no");
+ optionalCapabilities.mapPut("simpleArguments", "no");
+ optionalCapabilities.mapPut("partialArguments", "no");
+ optionalCapabilities.mapPut("followLinks", "yes");
+ optionalCapabilities.mapPut("validateOnly", "no");
+ optionalCapabilities.mapPut("pagination", "no");
+ optionalCapabilities.mapPut("sorting", "no");
+ optionalCapabilities.mapPut("domainModel", "rich");
+
+ representation.mapPut("optionalCapabilities", optionalCapabilities);
+ }
+
+ private void putExtensions() {
+ representation.mapPut("extensions", JsonRepresentation.newMap());
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/VersionResourceServerside.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/VersionResourceServerside.java b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/VersionResourceServerside.java
new file mode 100644
index 0000000..6f6859c
--- /dev/null
+++ b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/VersionResourceServerside.java
@@ -0,0 +1,68 @@
+/*
+ * 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.viewer.restfulobjects.server.resources;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+import org.apache.isis.viewer.restfulobjects.applib.RestfulMediaType;
+import org.apache.isis.viewer.restfulobjects.applib.RestfulResponse.HttpStatusCode;
+import org.apache.isis.viewer.restfulobjects.applib.version.VersionResource;
+import org.apache.isis.viewer.restfulobjects.rendering.RendererFactory;
+import org.apache.isis.viewer.restfulobjects.server.RestfulObjectsApplicationException;
+
+/**
+ * Implementation note: it seems to be necessary to annotate the implementation
+ * with {@link Path} rather than the interface (at least under RestEasy 1.0.2
+ * and 1.1-RC2).
+ */
+@Path("/version")
+public class VersionResourceServerside extends ResourceAbstract implements VersionResource {
+
+ @Override
+ @GET
+ @Produces({ MediaType.APPLICATION_JSON, RestfulMediaType.APPLICATION_JSON_VERSION })
+ public Response version() {
+ final RepresentationType representationType = RepresentationType.VERSION;
+
+ init(representationType, Where.NOWHERE);
+ fakeRuntimeExceptionIfXFail();
+
+ final RendererFactory factory = rendererFactoryRegistry.find(representationType);
+ final VersionReprRenderer renderer = (VersionReprRenderer) factory.newRenderer(getResourceContext(), null, JsonRepresentation.newMap());
+ renderer.includesSelf();
+
+ return responseOfOk(renderer, Caching.ONE_DAY).build();
+ }
+
+ private void fakeRuntimeExceptionIfXFail() {
+ final HttpHeaders httpHeaders = getResourceContext().getHttpHeaders();
+ if (httpHeaders.getRequestHeader("X-Fail") != null) {
+ throw RestfulObjectsApplicationException.create(HttpStatusCode.METHOD_FAILURE);
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/util/PathUtils.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/util/PathUtils.java b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/util/PathUtils.java
new file mode 100644
index 0000000..2410679
--- /dev/null
+++ b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/util/PathUtils.java
@@ -0,0 +1,40 @@
+/*
+ * 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.viewer.restfulobjects.server.util;
+
+import javax.servlet.http.HttpServletRequest;
+
+
+public final class PathUtils {
+
+ private PathUtils() {
+ }
+
+ public static String combine(final HttpServletRequest request, final String... pathElements) {
+ final StringBuilder buf = new StringBuilder(request.getContextPath());
+ for (final String pathElement : pathElements) {
+ if (!pathElement.startsWith("/")) {
+ buf.append("/");
+ }
+ buf.append(pathElement);
+ }
+ return buf.toString();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/webapp/PreProcessInterceptorForIsisSession.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/webapp/PreProcessInterceptorForIsisSession.java b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/webapp/PreProcessInterceptorForIsisSession.java
new file mode 100644
index 0000000..1320c29
--- /dev/null
+++ b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/webapp/PreProcessInterceptorForIsisSession.java
@@ -0,0 +1,42 @@
+/*
+ * 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.viewer.restfulobjects.server.webapp;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.ext.Provider;
+
+import org.jboss.resteasy.annotations.interception.ServerInterceptor;
+import org.jboss.resteasy.core.ResourceMethod;
+import org.jboss.resteasy.core.ServerResponse;
+import org.jboss.resteasy.spi.Failure;
+import org.jboss.resteasy.spi.HttpRequest;
+import org.jboss.resteasy.spi.interception.PreProcessInterceptor;
+
+@Provider
+@ServerInterceptor
+public class PreProcessInterceptorForIsisSession implements PreProcessInterceptor {
+
+ @Override
+ public ServerResponse preProcess(final HttpRequest request, final ResourceMethod method) throws Failure, WebApplicationException {
+
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/server/src/site/apt/index.apt
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/server/src/site/apt/index.apt b/component/viewer/restfulobjects/server/src/site/apt/index.apt
new file mode 100644
index 0000000..02e46ea
--- /dev/null
+++ b/component/viewer/restfulobjects/server/src/site/apt/index.apt
@@ -0,0 +1,27 @@
+~~ 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.
+
+RestfulObjects for Isis Viewer
+
+ The <viewer> module provides a set of JAX-RS resource implementations
+ that serve up the domain objects as JSON representations.
+
+
+Further Info
+
+ See this module's {{{./apidocs/index.html}Javadoc}} and the {{{../docbkx/html/guide/isis-restfulobjects-viewer.html}user guide}} for more information.
+
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/server/src/site/apt/jottings.apt
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/server/src/site/apt/jottings.apt b/component/viewer/restfulobjects/server/src/site/apt/jottings.apt
new file mode 100644
index 0000000..c5d1200
--- /dev/null
+++ b/component/viewer/restfulobjects/server/src/site/apt/jottings.apt
@@ -0,0 +1,24 @@
+~~ 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.
+
+
+
+Jottings
+
+ This page is to capture any random jottings relating to this module prior
+ to being moved into formal documentation.
+
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/server/src/site/site.xml
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/server/src/site/site.xml b/component/viewer/restfulobjects/server/src/site/site.xml
new file mode 100644
index 0000000..63e2551
--- /dev/null
+++ b/component/viewer/restfulobjects/server/src/site/site.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<project name="${project.name}">
+ <version position="right"/>
+ <body>
+ <breadcrumbs>
+ <item name="Viewer" href="index.html"/>
+ </breadcrumbs>
+
+ <menu name="RestfulObjects for Isis">
+ <item name="About" href="index.html" />
+ <item name="Jottings" href="jottings.html" />
+ </menu>
+
+ <menu name="RestfulObjects Modules">
+ <item name="Applib" href="../restfulobjects-applib/index.html" />
+ <item name="Viewer" href="../restfulobjects-viewer/index.html" />
+ </menu>
+
+ <menu name="Maven Reports" ref="reports" />
+ </body>
+</project>
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/server/src/test/java/org/apache/isis/viewer/restfulobjects/server/ResourceContextTest_ensureCompatibleAcceptHeader.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/server/src/test/java/org/apache/isis/viewer/restfulobjects/server/ResourceContextTest_ensureCompatibleAcceptHeader.java b/component/viewer/restfulobjects/server/src/test/java/org/apache/isis/viewer/restfulobjects/server/ResourceContextTest_ensureCompatibleAcceptHeader.java
new file mode 100644
index 0000000..4ae4ab5
--- /dev/null
+++ b/component/viewer/restfulobjects/server/src/test/java/org/apache/isis/viewer/restfulobjects/server/ResourceContextTest_ensureCompatibleAcceptHeader.java
@@ -0,0 +1,133 @@
+/*
+ * 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.viewer.restfulobjects.server;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+
+import org.apache.isis.viewer.restfulobjects.applib.MediaTypes;
+import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererException;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.integration.junit4.JUnit4Mockery;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ResourceContextTest_ensureCompatibleAcceptHeader {
+
+ private HttpHeaders httpHeaders;
+ private HttpServletRequest httpServletRequest;
+
+ private final Mockery context = new JUnit4Mockery();
+
+ @Before
+ public void setUp() throws Exception {
+ httpHeaders = context.mock(HttpHeaders.class);
+ httpServletRequest = context.mock(HttpServletRequest.class);
+ context.checking(new Expectations() {
+ {
+ allowing(httpServletRequest).getQueryString();
+ will(returnValue(""));
+ }
+ });
+ }
+
+ @Test
+ public void noop() throws Exception {
+ final RepresentationType representationType = RepresentationType.HOME_PAGE;
+ givenHttpHeadersGetAcceptableMediaTypesReturns(Arrays.<MediaType> asList(MediaTypes.guavaToJaxRs(representationType.getMediaType())));
+
+ instantiateResourceContext(representationType);
+ }
+
+ @Test
+ public void happyCase() throws Exception {
+ final RepresentationType representationType = RepresentationType.HOME_PAGE;
+ givenHttpHeadersGetAcceptableMediaTypesReturns(Arrays.<MediaType> asList(MediaTypes.guavaToJaxRs(representationType.getMediaType())));
+
+ instantiateResourceContext(representationType);
+ }
+
+ @Test
+ public void acceptGenericAndProduceGeneric() throws Exception {
+ final RepresentationType representationType = RepresentationType.GENERIC;
+ givenHttpHeadersGetAcceptableMediaTypesReturns(Arrays.<MediaType> asList(MediaType.APPLICATION_JSON_TYPE));
+
+ instantiateResourceContext(representationType);
+ }
+
+ @Test
+ public void acceptGenericAndProduceSpecific() throws Exception {
+ final RepresentationType representationType = RepresentationType.HOME_PAGE;
+ givenHttpHeadersGetAcceptableMediaTypesReturns(Arrays.<MediaType> asList(MediaType.APPLICATION_JSON_TYPE));
+
+ instantiateResourceContext(representationType);
+ }
+
+ @Test(expected = ReprRendererException.class)
+ public void nonMatching() throws Exception {
+ final RepresentationType representationType = RepresentationType.HOME_PAGE;
+ givenHttpHeadersGetAcceptableMediaTypesReturns(Arrays.<MediaType> asList(MediaType.APPLICATION_ATOM_XML_TYPE));
+
+ instantiateResourceContext(representationType);
+ }
+
+ @Test(expected = ReprRendererException.class)
+ public void nonMatchingProfile() throws Exception {
+ final RepresentationType representationType = RepresentationType.HOME_PAGE;
+ givenHttpHeadersGetAcceptableMediaTypesReturns(Arrays.<MediaType> asList(MediaTypes.guavaToJaxRs(RepresentationType.USER.getMediaType())));
+
+ instantiateResourceContext(representationType);
+ }
+
+ @Test(expected = ReprRendererException.class)
+ public void nonMatchingProfile_ignoreGeneric() throws Exception {
+ final RepresentationType representationType = RepresentationType.HOME_PAGE;
+ givenHttpHeadersGetAcceptableMediaTypesReturns(Arrays.<MediaType> asList(MediaTypes.guavaToJaxRs(RepresentationType.USER.getMediaType()), MediaType.APPLICATION_JSON_TYPE));
+
+ instantiateResourceContext(representationType);
+ }
+
+ @Test(expected = ReprRendererException.class)
+ public void emptyList() throws Exception {
+ final RepresentationType representationType = RepresentationType.HOME_PAGE;
+ givenHttpHeadersGetAcceptableMediaTypesReturns(Arrays.<MediaType> asList());
+
+ instantiateResourceContext(representationType);
+ }
+
+ private void givenHttpHeadersGetAcceptableMediaTypesReturns(final List<MediaType> mediaTypes) {
+ context.checking(new Expectations() {
+ {
+ one(httpHeaders).getAcceptableMediaTypes();
+ will(returnValue(mediaTypes));
+ }
+ });
+ }
+
+ private ResourceContext instantiateResourceContext(final RepresentationType representationType) {
+ return new ResourceContext(representationType, httpHeaders, null, null, httpServletRequest, null, null, null, null, null, null, null, null, null);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/server/src/test/java/org/apache/isis/viewer/restfulobjects/server/ResourceContextTest_getArg.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/server/src/test/java/org/apache/isis/viewer/restfulobjects/server/ResourceContextTest_getArg.java b/component/viewer/restfulobjects/server/src/test/java/org/apache/isis/viewer/restfulobjects/server/ResourceContextTest_getArg.java
new file mode 100644
index 0000000..daaaf0c
--- /dev/null
+++ b/component/viewer/restfulobjects/server/src/test/java/org/apache/isis/viewer/restfulobjects/server/ResourceContextTest_getArg.java
@@ -0,0 +1,90 @@
+/*
+ * 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.viewer.restfulobjects.server;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.jmock.Expectations;
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.apache.isis.core.unittestsupport.jmock.auto.Mock;
+import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2;
+import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2.Mode;
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+import org.apache.isis.viewer.restfulobjects.applib.RestfulRequest.RequestParameter;
+import org.apache.isis.viewer.restfulobjects.applib.util.UrlEncodingUtils;
+
+public class ResourceContextTest_getArg {
+
+ @Rule
+ public JUnitRuleMockery2 context = JUnitRuleMockery2.createFor(Mode.INTERFACES_AND_CLASSES);
+
+ @Mock
+ private HttpServletRequest httpServletRequest;
+ @Mock
+ private ResourceContext resourceContext;
+
+ private String queryString;
+
+ @Test
+ public void whenArgExists() throws Exception {
+ queryString = UrlEncodingUtils.urlEncode(JsonRepresentation.newMap("x-ro-page", "123").asJsonNode());
+
+ context.checking(new Expectations() {
+ {
+ one(httpServletRequest).getQueryString();
+ will(returnValue(queryString));
+ }
+ });
+ resourceContext = new ResourceContext(null, null, null, null, httpServletRequest, null, null, null, null, null, null, null, null, null) {
+ @Override
+ void init(final RepresentationType representationType) {
+ //
+ }
+ };
+ final Integer arg = resourceContext.getArg(RequestParameter.PAGE);
+ assertThat(arg, equalTo(123));
+ }
+
+ @Test
+ public void whenArgDoesNotExist() throws Exception {
+ queryString = UrlEncodingUtils.urlEncode(JsonRepresentation.newMap("xxx", "123").asJsonNode());
+
+ context.checking(new Expectations() {
+ {
+ one(httpServletRequest).getQueryString();
+ will(returnValue(queryString));
+ }
+ });
+ resourceContext = new ResourceContext(null, null, null, null, httpServletRequest, null, null, null, null, null, null, null, null, null) {
+ @Override
+ void init(final RepresentationType representationType) {
+ //
+ }
+ };
+ final Integer arg = resourceContext.getArg(RequestParameter.PAGE);
+ assertThat(arg, equalTo(RequestParameter.PAGE.getDefault()));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/server/src/test/java/org/apache/isis/viewer/restfulobjects/server/RestfulObjectsApplicationExceptionMapperTest.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/server/src/test/java/org/apache/isis/viewer/restfulobjects/server/RestfulObjectsApplicationExceptionMapperTest.java b/component/viewer/restfulobjects/server/src/test/java/org/apache/isis/viewer/restfulobjects/server/RestfulObjectsApplicationExceptionMapperTest.java
new file mode 100644
index 0000000..550bf3a
--- /dev/null
+++ b/component/viewer/restfulobjects/server/src/test/java/org/apache/isis/viewer/restfulobjects/server/RestfulObjectsApplicationExceptionMapperTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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.viewer.restfulobjects.server;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.junit.Assert.assertThat;
+
+import javax.ws.rs.core.Response;
+
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.RestfulResponse.HttpStatusCode;
+import org.apache.isis.viewer.restfulobjects.applib.util.JsonMapper;
+import org.junit.Before;
+import org.junit.Test;
+
+public class RestfulObjectsApplicationExceptionMapperTest {
+
+ private RestfulObjectsApplicationExceptionMapper exceptionMapper;
+
+ @Before
+ public void setUp() throws Exception {
+ exceptionMapper = new RestfulObjectsApplicationExceptionMapper();
+ }
+
+ @Test
+ public void simpleNoMessage() throws Exception {
+
+ // given
+ final HttpStatusCode status = HttpStatusCode.BAD_REQUEST;
+ final RestfulObjectsApplicationException ex = RestfulObjectsApplicationException.create(status);
+
+ // when
+ final Response response = exceptionMapper.toResponse(ex);
+
+ // then
+ assertThat(HttpStatusCode.lookup(response.getStatus()), is(status));
+ assertThat(response.getMetadata().get("Warning"), is(nullValue()));
+
+ // and then
+ final String entity = (String) response.getEntity();
+ assertThat(entity, is(not(nullValue())));
+ final JsonRepresentation jsonRepr = JsonMapper.instance().read(entity, JsonRepresentation.class);
+
+ // then
+ assertThat(jsonRepr.getString("message"), is(nullValue()));
+ assertThat(jsonRepr.getArray("stackTrace"), is(not(nullValue())));
+ assertThat(jsonRepr.getArray("stackTrace").size(), is(greaterThan(0)));
+ assertThat(jsonRepr.getRepresentation("causedBy"), is(nullValue()));
+ }
+
+ @Test
+ public void entity_withMessage() throws Exception {
+
+ // givens
+ final RestfulObjectsApplicationException ex = RestfulObjectsApplicationException.create(HttpStatusCode.BAD_REQUEST, "foobar");
+
+ // when
+ final Response response = exceptionMapper.toResponse(ex);
+
+ // then
+ assertThat((String) response.getMetadata().get("Warning").get(0), is(ex.getMessage()));
+
+ // and then
+ final String entity = (String) response.getEntity();
+ assertThat(entity, is(not(nullValue())));
+ final JsonRepresentation jsonRepr = JsonMapper.instance().read(entity, JsonRepresentation.class);
+
+ // then
+ assertThat(jsonRepr.getString("message"), is(ex.getMessage()));
+ }
+
+ @Test
+ public void entity_withCause() throws Exception {
+ // given
+ final Exception cause = new Exception("barfoo");
+ final RestfulObjectsApplicationException ex = RestfulObjectsApplicationException.create(HttpStatusCode.BAD_REQUEST, cause, "foobar");
+
+ // when
+ final Response response = exceptionMapper.toResponse(ex);
+ final String entity = (String) response.getEntity();
+ assertThat(entity, is(not(nullValue())));
+ final JsonRepresentation jsonRepr = JsonMapper.instance().read(entity, JsonRepresentation.class);
+
+ // then
+ assertThat(jsonRepr.getString("message"), is(ex.getMessage()));
+ final JsonRepresentation causedByRepr = jsonRepr.getRepresentation("causedBy");
+ assertThat(causedByRepr, is(not(nullValue())));
+ assertThat(causedByRepr.getString("message"), is(cause.getMessage()));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/server/src/test/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainResourceHelperTest_readBodyAsMap.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/server/src/test/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainResourceHelperTest_readBodyAsMap.java b/component/viewer/restfulobjects/server/src/test/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainResourceHelperTest_readBodyAsMap.java
new file mode 100644
index 0000000..49d798d
--- /dev/null
+++ b/component/viewer/restfulobjects/server/src/test/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainResourceHelperTest_readBodyAsMap.java
@@ -0,0 +1,77 @@
+/*
+ * 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.viewer.restfulobjects.server.resources;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererException;
+import org.junit.Test;
+
+public class DomainResourceHelperTest_readBodyAsMap {
+
+ private JsonRepresentation representation;
+
+ @Test
+ public void whenNull() throws Exception {
+ representation = DomainResourceHelper.readAsMap(null);
+
+ assertThat(representation.isMap(), is(true));
+ assertThat(representation.size(), is(0));
+ }
+
+ @Test
+ public void whenEmptyString() throws Exception {
+ representation = DomainResourceHelper.readAsMap("");
+
+ assertThat(representation.isMap(), is(true));
+ assertThat(representation.size(), is(0));
+ }
+
+ @Test
+ public void whenWhitespaceOnlyString() throws Exception {
+ representation = DomainResourceHelper.readAsMap(" \t ");
+
+ assertThat(representation.isMap(), is(true));
+ assertThat(representation.size(), is(0));
+ }
+
+ @Test
+ public void emptyMap() throws Exception {
+ representation = DomainResourceHelper.readAsMap("{}");
+
+ assertThat(representation.isMap(), is(true));
+ assertThat(representation.size(), is(0));
+ }
+
+ @Test
+ public void map() throws Exception {
+ representation = DomainResourceHelper.readAsMap("{\"foo\":\"bar\"}");
+
+ assertThat(representation.isMap(), is(true));
+ assertThat(representation.size(), is(1));
+ }
+
+ @Test(expected = ReprRendererException.class)
+ public void whenArray() throws Exception {
+ DomainResourceHelper.readAsMap("[]");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/75f41b75/component/viewer/restfulobjects/tck/pom.xml
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/tck/pom.xml b/component/viewer/restfulobjects/tck/pom.xml
index 13c5245..2a8f76a 100644
--- a/component/viewer/restfulobjects/tck/pom.xml
+++ b/component/viewer/restfulobjects/tck/pom.xml
@@ -28,7 +28,7 @@
<groupId>org.apache.isis.viewer</groupId>
<artifactId>isis-viewer-restfulobjects-tck</artifactId>
- <version>1.0.1-SNAPSHOT</version>
+ <version>2.0.0-SNAPSHOT</version>
<name>Isis RestfulObjects Viewer TCK tests</name>
@@ -37,7 +37,7 @@
<properties>
<maven.test.skip>true</maven.test.skip>
- <isis-viewer-restfulobjects.version>1.0.1-SNAPSHOT</isis-viewer-restfulobjects.version>
+ <isis-viewer-restfulobjects.version>2.0.0-SNAPSHOT</isis-viewer-restfulobjects.version>
<siteBaseDir>..</siteBaseDir>
<relativeUrl>restfulobjects-tck/</relativeUrl>
@@ -81,7 +81,7 @@
<!-- isis viewer -->
<dependency>
<groupId>org.apache.isis.viewer</groupId>
- <artifactId>isis-viewer-restfulobjects-impl</artifactId>
+ <artifactId>isis-viewer-restfulobjects-server</artifactId>
<version>${isis-viewer-restfulobjects.version}</version>
</dependency>