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 19:29:52 UTC

[29/32] git commit: ISIS-323: RO publishing done, but no xactn stuff yet

ISIS-323: RO publishing done, but no xactn stuff yet

* PublishingService
* EventSerializer
* PayloadFactory
* fix RO rendering so honours @NotPersistable
* extended RO rendering to suppress unimportant details when serializing event payload objects


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/7b745ecd
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/7b745ecd
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/7b745ecd

Branch: refs/heads/master
Commit: 7b745ecd56b7238efb20c06076596c7aa9a74ebe
Parents: 6002a90
Author: Dan Haywood <da...@apache.org>
Authored: Fri Feb 8 13:14:32 2013 +0000
Committer: Dan Haywood <da...@apache.org>
Committed: Fri Feb 8 18:00:46 2013 +0000

----------------------------------------------------------------------
 .../applib/ClientRequestConfigurer.java            |  172 --------
 .../restfulobjects/applib/JsonRepresentation.java  |    1 -
 .../restfulobjects/applib/LinkRepresentation.java  |  164 ++++++++
 .../viewer/restfulobjects/applib/MediaTypes.java   |   39 --
 .../isis/viewer/restfulobjects/applib/Rel.java     |   78 ++++
 .../applib/RepresentationWalker.java               |  179 ---------
 .../restfulobjects/applib/RestfulClient.java       |  139 -------
 .../applib/RestfulClientException.java             |   40 --
 .../restfulobjects/applib/RestfulHttpMethod.java   |   93 +++++
 .../restfulobjects/applib/RestfulRequest.java      |  200 ----------
 .../restfulobjects/applib/RestfulResponse.java     |  305 --------------
 .../viewer/restfulobjects/applib/RoHttpMethod.java |   92 -----
 .../applib/client/ClientRequestConfigurer.java     |  174 ++++++++
 .../applib/client/RepresentationWalker.java        |  180 +++++++++
 .../applib/client/RestfulClient.java               |  141 +++++++
 .../applib/client/RestfulClientException.java      |   40 ++
 .../applib/client/RestfulRequest.java              |  201 ++++++++++
 .../applib/client/RestfulResponse.java             |  307 +++++++++++++++
 .../AbstractObjectMemberRepresentation.java        |    2 +-
 .../applib/domainobjects/DomainRepresentation.java |    4 +-
 .../domainobjects/ObjectActionRepresentation.java  |    2 +-
 .../TransientDomainObjectRepresentation.java       |    2 +-
 .../applib/homepage/HomePageRepresentation.java    |    2 +-
 .../applib/links/LinkRepresentation.java           |  166 --------
 .../viewer/restfulobjects/applib/links/Rel.java    |   78 ----
 .../applib/DomainObjectRepresentationTest.java     |   51 ---
 .../viewer/restfulobjects/applib/JsonFixture.java  |    2 +-
 .../JsonRepresentationTest_getLink_isLink.java     |    3 +-
 .../applib/JsonRepresentationTest_urlEncoding.java |    3 +-
 .../applib/LinkRepresentationTest_equals.java      |   54 +++
 .../applib/RestfulClientTest_follow.java           |  128 ------
 .../applib/RestfulHttpMethodTest_setUp.java        |   94 +++++
 .../RestfulRequestDomainModelTest_parser.java      |   39 --
 ...RestfulRequestRequestParameterTest_valueOf.java |   90 -----
 .../applib/RestfulResponse_HttpStatusCodeTest.java |   43 --
 .../applib/RoHttpMethodTest_setUp.java             |   93 -----
 .../applib/client/RestfulClientTest_follow.java    |  132 ++++++
 .../RestfulRequestDomainModelTest_parser.java      |   40 ++
 ...RestfulRequestRequestParameterTest_valueOf.java |   92 +++++
 .../client/RestfulResponse_HttpStatusCodeTest.java |   43 ++
 .../DomainObjectRepresentationTest.java            |   52 +++
 .../links/LinkRepresentationTest_equals.java       |   53 ---
 .../restfulobjects/rendering/LinkBuilder.java      |    8 +-
 .../rendering/NOTUSED_WellKnownType.java           |   80 ----
 .../rendering/ReprRendererAbstract.java            |    2 +-
 .../AbstractObjectMemberReprRenderer.java          |    2 +-
 .../domainobjects/ActionResultReprRenderer.java    |    2 +-
 .../domainobjects/DomainObjectLinkTo.java          |    2 +-
 .../domainobjects/DomainObjectReprRenderer.java    |   63 ++-
 .../domainobjects/DomainServiceLinkTo.java         |    2 +-
 .../rendering/domainobjects/ListReprRenderer.java  |    2 +-
 .../rendering/domainobjects/MemberType.java        |   16 +-
 .../rendering/domainobjects/MutatorSpec.java       |   12 +-
 .../domainobjects/ObjectActionReprRenderer.java    |   14 +-
 .../domainobjects/ObjectAdapterLinkTo.java         |    2 +-
 .../ObjectCollectionReprRenderer.java              |    2 +-
 .../domainobjects/ObjectPropertyReprRenderer.java  |   17 +-
 .../domainobjects/ScalarValueReprRenderer.java     |    2 +-
 .../AbstractTypeMemberReprRenderer.java            |    2 +-
 .../domaintypes/ActionDescriptionReprRenderer.java |    2 +-
 .../ActionParameterDescriptionReprRenderer.java    |    2 +-
 .../CollectionDescriptionReprRenderer.java         |    2 +-
 .../domaintypes/DomainTypeReprRenderer.java        |    2 +-
 .../PropertyDescriptionReprRenderer.java           |    2 +-
 .../domaintypes/TypeActionResultReprRenderer.java  |    2 +-
 .../domaintypes/TypeListReprRenderer.java          |    2 +-
 .../EventSerializerRendererContext.java            |   51 +++
 .../RestfulObjectsSpecEventSerializer.java         |   70 ++++
 .../rendering/util/InputStreamUtil.java            |   64 ---
 .../rendering/util/NOTUSED_ActionUtils.java        |   53 ---
 .../restfulobjects/rendering/util/OidUtils.java    |    7 -
 .../restfulobjects/rendering/util/StringUtil.java  |   38 --
 .../rendering/util/UrlDecoderUtils.java            |   41 --
 .../rendering/util/UrlParserUtils.java             |   52 ---
 .../rendering/util/UrlParserUtilsTest.java         |   60 ---
 .../restfulobjects/server/HasHttpStatusCode.java   |    2 +-
 .../restfulobjects/server/ResourceContext.java     |    4 +-
 .../server/RestfulObjectsApplicationException.java |    2 +-
 .../RestfulObjectsApplicationExceptionMapper.java  |    2 +-
 .../server/RuntimeExceptionMapper.java             |    2 +-
 .../resources/DomainObjectResourceServerside.java  |    6 +-
 .../server/resources/DomainResourceHelper.java     |    8 +-
 .../resources/DomainTypeResourceServerside.java    |    6 +-
 .../server/resources/HomePageReprRenderer.java     |    2 +-
 .../resources/HomePageResourceServerside.java      |    2 +-
 .../server/resources/ResourceAbstract.java         |    6 +-
 .../resources/VersionResourceServerside.java       |    2 +-
 .../server/util/NOTUSED_ActionUtils.java           |   53 +++
 .../server/util/NOTUSED_InputStreamUtil.java       |   65 +++
 .../server/util/NOTUSED_StringUtil.java            |   39 ++
 .../server/util/NOTUSED_WellKnownType.java         |   80 ++++
 .../restfulobjects/server/util/OidUtils.java       |   47 +++
 .../server/util/UrlDecoderUtils.java               |   41 ++
 .../restfulobjects/server/util/UrlParserUtils.java |   52 +++
 .../server/ResourceContextTest_getArg.java         |    2 +-
 ...stfulObjectsApplicationExceptionMapperTest.java |    2 +-
 .../server/util/UrlParserUtilsTest.java            |   60 +++
 .../restfulobjects/tck/RepresentationMatchers.java |   18 +-
 ...eTest_clientAcceptHeader_exceptionHandling.java |   16 +-
 ...Test_serverSideException_exceptionHandling.java |   14 +-
 .../home/HomePageResourceTest_accept.java          |   16 +-
 ...ePageResourceTest_representationAndHeaders.java |   18 +-
 .../home/HomePageResourceTest_xrofollowlinks.java  |   14 +-
 .../resources/object/DomainObjectResourceTest.java |   46 ++--
 .../DomainServiceResourceTest_invokeAction.java    |   16 +-
 ...DomainServiceResourceTest_serviceId_accept.java |   16 +-
 ...mainServiceResourceTest_serviceId_notFound.java |    6 +-
 ...rceTest_serviceId_representationAndHeaders.java |   10 +-
 ...rviceResourceTest_serviceId_xrofollowlinks.java |   14 +-
 .../DomainServiceResourceTest_services_accept.java |   16 +-
 ...urceTest_services_representationAndHeaders.java |   12 +-
 ...erviceResourceTest_services_xrofollowlinks.java |   14 +-
 .../resources/user/UserResourceTest_accept.java    |   16 +-
 .../UserResourceTest_representationAndHeaders.java |   12 +-
 .../version/VersionResourceTest_accept.java        |   16 +-
 ...rsionResourceTest_representationAndHeaders.java |   12 +-
 .../restfulobjects/tck/stories/UserStoryTest.java  |    4 +-
 .../isis/applib/annotation/PublishedAction.java    |   10 +-
 .../isis/applib/annotation/PublishedObject.java    |   12 +-
 .../applib/services/publish/CanonicalEvent.java    |   29 --
 .../applib/services/publish/EventMetadata.java     |   44 ++
 .../isis/applib/services/publish/EventPayload.java |   28 ++
 .../publish/EventPayloadForActionInvocation.java   |  143 +++++++
 .../publish/EventPayloadForChangedObject.java      |   37 ++
 .../applib/services/publish/EventSerializer.java   |   32 ++
 .../applib/services/publish/ObjectStringifier.java |   16 +
 .../applib/services/publish/PublishingService.java |   17 +-
 .../actions/publish/PublishedActionFacet.java      |    2 +-
 .../publish/PublishedActionFacetAbstract.java      |    4 +-
 .../object/publish/PublishedObjectFacet.java       |    2 +-
 .../publish/PublishedObjectFacetAbstract.java      |    4 +-
 .../PublishedActionAnnotationFacetFactory.java     |    6 +-
 .../publish/PublishedActionFacetAnnotation.java    |    2 +-
 .../PublishedObjectAnnotationFacetFactory.java     |    6 +-
 .../publish/PublishedObjectFacetAnnotation.java    |    2 +-
 .../PersistenceMechanismInstallerAbstract.java     |    6 +-
 .../PublishingServiceWithCanonicalizers.java       |   56 ---
 ...blishingServiceWithDefaultPayloadFactories.java |   59 +++
 .../system/transaction/IsisTransaction.java        |   21 +-
 .../system/transaction/IsisTransactionManager.java |  107 ++++--
 .../PersistenceSessionObjectStoreTest.java         |    4 +-
 .../system/transaction/IsisTransactionTest.java    |    4 +-
 .../dom/src/main/java/dom/todo/ToDoItem.java       |    3 +-
 .../dom/todo/ToDoItemChangedPayloadFactory.java    |   24 ++
 .../src/main/webapp/WEB-INF/isis.properties        |    3 +-
 .../viewer-webapp/src/main/webapp/WEB-INF/web.xml  |    4 +-
 146 files changed, 3241 insertions(+), 2730 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/7b745ecd/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/ClientRequestConfigurer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/ClientRequestConfigurer.java b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/ClientRequestConfigurer.java
deleted file mode 100644
index 179ea48..0000000
--- a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/ClientRequestConfigurer.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- *  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.applib;
-
-import java.util.Map;
-
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.UriBuilder;
-
-import org.apache.isis.viewer.restfulobjects.applib.RestfulRequest.RequestParameter;
-import org.apache.isis.viewer.restfulobjects.applib.links.LinkRepresentation;
-import org.apache.isis.viewer.restfulobjects.applib.util.UrlEncodingUtils;
-import org.jboss.resteasy.client.ClientExecutor;
-import org.jboss.resteasy.client.ClientRequest;
-import org.jboss.resteasy.specimpl.UriBuilderImpl;
-
-/**
- * Configures the body, query string etc of a {@link ClientRequest}.
- * 
- * <p>
- * Needed because, unfortunately, {@link ClientRequest} does not seem to allow
- * the query string to be set directly (only
- * {@link ClientRequest#getQueryParameters() query parameters}). Instead, it is
- * necessary to {@link UriBuilderImpl#replaceQuery(String) use} its underlying
- * {@link UriBuilderImpl}.
- */
-public class ClientRequestConfigurer {
-
-    public static ClientRequestConfigurer create(final ClientExecutor executor, final String uriTemplate) {
-        final UriBuilder uriBuilder = new UriBuilderImpl().uriTemplate(uriTemplate);
-        final ClientRequest clientRequest = executor.createRequest(uriBuilder);
-        return new ClientRequestConfigurer(clientRequest, uriBuilder);
-    }
-
-    private final ClientRequest clientRequest;
-    private final UriBuilder uriBuilder;
-
-    ClientRequestConfigurer(final ClientRequest clientRequest, final UriBuilder uriBuilder) {
-        this.clientRequest = clientRequest;
-        this.uriBuilder = uriBuilder;
-    }
-
-    public ClientRequestConfigurer accept(final MediaType mediaType) {
-        clientRequest.accept(mediaType);
-        return this;
-    }
-
-    public ClientRequestConfigurer header(final String name, final String value) {
-        clientRequest.header(name, value);
-        return this;
-    }
-
-    /**
-     * Prerequisite to {@link #configureArgs(JsonRepresentation)} or
-     * {@link #configureArgs(Map)}.
-     */
-    public ClientRequestConfigurer setHttpMethod(final RoHttpMethod httpMethod) {
-        clientRequest.setHttpMethod(httpMethod.getJavaxRsMethod());
-        return this;
-    }
-
-    /**
-     * Used when creating a request with arguments to execute.
-     * 
-     * <p>
-     * Typical flow is:
-     * <ul>
-     * <li> {@link RestfulClient#createRequest(RoHttpMethod, String)}
-     * <li> {@link RestfulRequest#withArg(RequestParameter, Object)} for each arg
-     * <li> {@link RestfulRequest#execute()} - which calls this method.
-     * </ul>
-     */
-    public ClientRequestConfigurer configureArgs(final Map<RequestParameter<?>, Object> args) {
-        if (clientRequest.getHttpMethod() == null) {
-            throw new IllegalStateException("Must set up http method first");
-        }
-
-        final JsonRepresentation argsAsMap = JsonRepresentation.newMap();
-        for (final RequestParameter<?> requestParam : args.keySet()) {
-            put(args, requestParam, argsAsMap);
-        }
-        getHttpMethod().setUpArgs(this, argsAsMap);
-        return this;
-    }
-
-    private <P> void put(final Map<RequestParameter<?>, Object> args, final RequestParameter<P> requestParam, final JsonRepresentation argsAsMap) {
-        @SuppressWarnings("unchecked")
-        final P value = (P) args.get(requestParam);
-        final String valueStr = requestParam.getParser().asString(value);
-        argsAsMap.mapPut(requestParam.getName(), valueStr);
-    }
-
-    /**
-     * Used when following links (
-     * {@link RestfulClient#follow(LinkRepresentation)}).
-     */
-    public ClientRequestConfigurer configureArgs(final JsonRepresentation requestArgs) {
-        if (clientRequest.getHttpMethod() == null) {
-            throw new IllegalStateException("Must set up http method first");
-        }
-
-        getHttpMethod().setUpArgs(this, requestArgs);
-        return this;
-    }
-
-    /**
-     * Called back from
-     * {@link RoHttpMethod#setUpArgs(ClientRequestConfigurer, JsonRepresentation)}
-     */
-    ClientRequestConfigurer body(final JsonRepresentation requestArgs) {
-        clientRequest.body(MediaType.APPLICATION_JSON_TYPE, requestArgs.toString());
-        return this;
-    }
-
-    /**
-     * Called back from
-     * {@link RoHttpMethod#setUpArgs(ClientRequestConfigurer, JsonRepresentation)}
-     */
-    ClientRequestConfigurer queryString(final JsonRepresentation requestArgs) {
-        if (requestArgs.size() == 0) {
-            return this;
-        }
-        final String queryString = UrlEncodingUtils.urlEncode(requestArgs.toString());
-        uriBuilder.replaceQuery(queryString);
-        return this;
-    }
-
-    /**
-     * Called back from
-     * {@link RoHttpMethod#setUpArgs(ClientRequestConfigurer, JsonRepresentation)}
-     */
-    ClientRequestConfigurer queryArgs(final JsonRepresentation requestArgs) {
-        final MultivaluedMap<String, String> queryParameters = clientRequest.getQueryParameters();
-        for (final Map.Entry<String, JsonRepresentation> entry : requestArgs.mapIterable()) {
-            final String param = entry.getKey();
-            final JsonRepresentation argRepr = entry.getValue();
-            final String arg = UrlEncodingUtils.urlEncode(argRepr.asArg());
-            queryParameters.add(param, arg);
-        }
-        return this;
-    }
-
-    /**
-     * For testing.
-     */
-    ClientRequest getClientRequest() {
-        return clientRequest;
-    }
-
-    RoHttpMethod getHttpMethod() {
-        final String httpMethod = clientRequest.getHttpMethod();
-        return RoHttpMethod.valueOf(httpMethod);
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/7b745ecd/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentation.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentation.java b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentation.java
index d09b45f..71de8f9 100644
--- a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentation.java
+++ b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentation.java
@@ -29,7 +29,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
-import org.apache.isis.viewer.restfulobjects.applib.links.LinkRepresentation;
 import org.apache.isis.viewer.restfulobjects.applib.util.JsonNodeUtils;
 import org.apache.isis.viewer.restfulobjects.applib.util.PathNode;
 import org.apache.isis.viewer.restfulobjects.applib.util.UrlEncodingUtils;

http://git-wip-us.apache.org/repos/asf/isis/blob/7b745ecd/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/LinkRepresentation.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/LinkRepresentation.java b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/LinkRepresentation.java
new file mode 100644
index 0000000..bafbdba
--- /dev/null
+++ b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/LinkRepresentation.java
@@ -0,0 +1,164 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.restfulobjects.applib;
+
+import javax.ws.rs.core.MediaType;
+
+import org.apache.isis.viewer.restfulobjects.applib.client.ClientRequestConfigurer;
+import org.apache.isis.viewer.restfulobjects.applib.client.RestfulRequest;
+import org.apache.isis.viewer.restfulobjects.applib.client.RestfulResponse;
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.node.JsonNodeFactory;
+import org.codehaus.jackson.node.ObjectNode;
+import org.jboss.resteasy.client.ClientExecutor;
+
+public final class LinkRepresentation extends JsonRepresentation {
+
+    public LinkRepresentation() {
+        this(new ObjectNode(JsonNodeFactory.instance));
+        withMethod(RestfulHttpMethod.GET);
+    }
+
+    public LinkRepresentation(final JsonNode jsonNode) {
+        super(jsonNode);
+    }
+
+    public String getRel() {
+        return asObjectNode().path("rel").getTextValue();
+    }
+
+    public LinkRepresentation withRel(final String rel) {
+        asObjectNode().put("rel", rel);
+        return this;
+    }
+
+    public String getHref() {
+        return asObjectNode().path("href").getTextValue();
+    }
+
+    public LinkRepresentation withHref(final String href) {
+        asObjectNode().put("href", href);
+        return this;
+    }
+
+    public JsonRepresentation getValue() {
+        return getRepresentation("value");
+    }
+
+    public String getTitle() {
+        return getString("title");
+    }
+
+    public LinkRepresentation withTitle(final String title) {
+        asObjectNode().put("title", title);
+        return this;
+    }
+
+    public RestfulHttpMethod getHttpMethod() {
+        final String methodStr = asObjectNode().path("method").getTextValue();
+        return RestfulHttpMethod.valueOf(methodStr);
+    }
+
+    public MediaType getType() {
+        final String typeStr = asObjectNode().path("type").getTextValue();
+        if (typeStr == null) {
+            return MediaType.APPLICATION_JSON_TYPE;
+        }
+        return MediaType.valueOf(typeStr);
+    }
+
+    public LinkRepresentation withMethod(final RestfulHttpMethod httpMethod) {
+        asObjectNode().put("method", httpMethod.name());
+        return this;
+    }
+
+    /**
+     * Returns the &quot;arguments&quot; json-property of the link (a map).
+     * 
+     * <p>
+     * If there is no &quot;arguments&quot; node, then as a convenience will
+     * return an empty map.
+     * 
+     * @return
+     */
+    public JsonRepresentation getArguments() {
+        final JsonNode arguments = asObjectNode().get("arguments");
+        if (arguments.isNull()) {
+            return JsonRepresentation.newMap();
+        }
+        return new JsonRepresentation(arguments);
+    }
+
+    public <T> RestfulResponse<JsonRepresentation> follow(final ClientExecutor executor) throws Exception {
+        return follow(executor, null);
+    }
+
+    public <T extends JsonRepresentation> RestfulResponse<T> follow(final ClientExecutor executor, final JsonRepresentation requestArgs) throws Exception {
+
+        final ClientRequestConfigurer clientRequestConfigurer = ClientRequestConfigurer.create(executor, getHref());
+
+        clientRequestConfigurer.accept(MediaType.APPLICATION_JSON_TYPE);
+        clientRequestConfigurer.setHttpMethod(getHttpMethod());
+
+        clientRequestConfigurer.configureArgs(requestArgs);
+
+        final RestfulRequest restfulRequest = new RestfulRequest(clientRequestConfigurer);
+        return restfulRequest.executeT();
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getHref() == null) ? 0 : getHref().hashCode());
+        result = prime * result + ((getHttpMethod() == null) ? 0 : getHttpMethod().hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final LinkRepresentation other = (LinkRepresentation) obj;
+        if (getHref() == null) {
+            if (other.getHref() != null) {
+                return false;
+            }
+        } else if (!getHref().equals(other.getHref())) {
+            return false;
+        }
+        if (getHttpMethod() != other.getHttpMethod()) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "Link [rel=" + getRel() + ", href=" + getHref() + ", method=" + getHttpMethod() + ", type=" + getType() + "]";
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/7b745ecd/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/MediaTypes.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/MediaTypes.java b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/MediaTypes.java
deleted file mode 100644
index d34fb45..0000000
--- a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/MediaTypes.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.apache.isis.viewer.restfulobjects.applib;
-
-import javax.ws.rs.core.MediaType;
-
-import com.google.common.base.Function;
-
-/**
- * Convert between {@link com.google.common.net.MediaType guava MediaType} and {@link javax.ws.rs.core.MediaType jax-rs MediaType}.
- */
-final class MediaTypes {
-    
-    private MediaTypes(){}
-
-    private static final Function<javax.ws.rs.core.MediaType, ? extends com.google.common.net.MediaType> JAXRS_TO_GUAVA = new Function<javax.ws.rs.core.MediaType, com.google.common.net.MediaType>() {
-
-        @Override
-        public com.google.common.net.MediaType apply(javax.ws.rs.core.MediaType input) {
-            return MediaTypes.jaxRsToGuava(input);
-        }
-    };
-
-    private static final Function<com.google.common.net.MediaType, MediaType> GUAVA_TO_JAXRS = new Function<com.google.common.net.MediaType, MediaType>() {
-
-        @Override
-        public MediaType apply(com.google.common.net.MediaType input) {
-            return MediaTypes.guavaToJaxRs(input);
-        }
-    };
-
-
-    private static com.google.common.net.MediaType jaxRsToGuava(javax.ws.rs.core.MediaType jaxRsMediaType) {
-        return com.google.common.net.MediaType.parse(jaxRsMediaType.toString());
-    }
-    
-    private static javax.ws.rs.core.MediaType guavaToJaxRs(com.google.common.net.MediaType guavaMediaType) {
-        return javax.ws.rs.core.MediaType.valueOf(guavaMediaType.toString());
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/7b745ecd/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/Rel.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/Rel.java b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/Rel.java
new file mode 100644
index 0000000..1d20988
--- /dev/null
+++ b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/Rel.java
@@ -0,0 +1,78 @@
+/*
+ *  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.applib;
+
+public enum Rel {
+    
+    // IANA registered
+    SELF("self"), 
+    DESCRIBEDBY("describedby"), 
+    UP("up"), 
+    HELP("help"), 
+    ICON("icon"),
+
+    // Restful Objects namespace
+    ICON16(Spec.REL_PREFIX + "icon16"), 
+    ICON32(Spec.REL_PREFIX + "icon32"), 
+    OBJECT(Spec.REL_PREFIX + "object"), 
+    SERVICE(Spec.REL_PREFIX + "service"), 
+    CHOICE(Spec.REL_PREFIX + "choice"), 
+    DEFAULT(Spec.REL_PREFIX + "default"), 
+    DETAILS(Spec.REL_PREFIX + "details"), 
+    MODIFY(Spec.REL_PREFIX + "modify"), 
+    CLEAR(Spec.REL_PREFIX + "clear"), 
+    ADD_TO(Spec.REL_PREFIX + "addto"), 
+    REMOVE_FROM(Spec.REL_PREFIX + "removefrom"), 
+    INVOKE(Spec.REL_PREFIX + "invoke"), 
+    PERSIST(Spec.REL_PREFIX + "persist"), 
+    PROPERTY(Spec.REL_PREFIX + "property"), 
+    COLLECTION(Spec.REL_PREFIX + "collection"), 
+    ACTION(Spec.REL_PREFIX + "action"), 
+    TYPE_ACTION(Spec.REL_PREFIX + "typeaction"), 
+    ACTION_PARAM(Spec.REL_PREFIX + "actionparam"), 
+    RETURN_TYPE(Spec.REL_PREFIX + "returntype"), 
+    ELEMENT_TYPE(Spec.REL_PREFIX + "elementtype"), 
+    VERSION(Spec.REL_PREFIX + "version"), 
+    USER(Spec.REL_PREFIX + "user"), 
+    SERVICES(Spec.REL_PREFIX + "services"), 
+    TYPES(Spec.REL_PREFIX + "types"), 
+    DOMAIN_TYPE(Spec.REL_PREFIX + "domaintype"),
+
+    // implementation specific
+    CONTRIBUTED_BY(Impl.REL_PREFIX + "contributedby");
+
+    private final String name;
+
+    private Rel(final String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    private static class Spec {
+        final static String REL_PREFIX = "urn:org.restfulobjects:rels/";
+    }
+
+    private static class Impl {
+        final static String REL_PREFIX = "urn:org.apache.isis.restfulobjects:rels/";
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/7b745ecd/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/RepresentationWalker.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/RepresentationWalker.java b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/RepresentationWalker.java
deleted file mode 100644
index 6ccfbb6..0000000
--- a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/RepresentationWalker.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- *  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.applib;
-
-import java.io.IOException;
-import java.util.List;
-
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status.Family;
-
-import org.apache.isis.viewer.restfulobjects.applib.links.LinkRepresentation;
-import org.codehaus.jackson.JsonParseException;
-import org.codehaus.jackson.map.JsonMappingException;
-
-import com.google.common.collect.Lists;
-
-public class RepresentationWalker {
-
-    static class Step {
-        private final String key;
-        private final LinkRepresentation link;
-        private final JsonRepresentation body;
-        private final RestfulResponse<? extends JsonRepresentation> response;
-        private String error;
-        private final Exception exception;
-
-        public Step(final String key, final LinkRepresentation link, final JsonRepresentation body, final RestfulResponse<? extends JsonRepresentation> response, final String error, final Exception exception) {
-            this.key = key;
-            this.link = link;
-            this.body = body;
-            this.response = response;
-            this.error = error;
-            this.exception = exception;
-        }
-
-        @Override
-        public String toString() {
-            return "Step [key=" + key + ", link=" + (link != null ? link.getHref() : "(null)") + ", error=" + error + "]";
-        }
-
-    }
-
-    private final RestfulClient restfulClient;
-    private final List<Step> steps = Lists.newLinkedList();
-
-    public RepresentationWalker(final RestfulClient restfulClient, final Response response) {
-        this.restfulClient = restfulClient;
-        final RestfulResponse<JsonRepresentation> jsonResp = RestfulResponse.of(response);
-
-        addStep(null, null, null, jsonResp, null, null);
-    }
-
-    private Step addStep(final String key, final LinkRepresentation link, final JsonRepresentation body, final RestfulResponse<JsonRepresentation> jsonResp, final String error, final Exception ex) {
-        final Step step = new Step(key, link, body, jsonResp, error, ex);
-        steps.add(0, step);
-        if (error != null) {
-            if (jsonResp.getStatus().getFamily() != Family.SUCCESSFUL) {
-                step.error = "response status code: " + jsonResp.getStatus();
-            }
-        }
-        return step;
-    }
-
-    public void walk(final String path) {
-        walk(path, null);
-    }
-
-    public void walk(final String path, final JsonRepresentation invokeBody) {
-        final Step previousStep = currentStep();
-        if (previousStep.error != null) {
-            return;
-        }
-
-        final RestfulResponse<? extends JsonRepresentation> jsonResponse = previousStep.response;
-        JsonRepresentation entity;
-        try {
-            entity = jsonResponse.getEntity();
-        } catch (final Exception e) {
-            addStep(path, null, null, null, "exception: " + e.getMessage(), e);
-            return;
-        }
-
-        LinkRepresentation link;
-        try {
-            link = entity.getLink(path);
-        } catch (final Exception e) {
-            addStep(path, null, null, null, "exception: " + e.getMessage(), e);
-            return;
-        }
-        if (link == null) {
-            addStep(path, null, null, null, "no such link '" + path + "'", null);
-            return;
-        }
-
-        final RestfulResponse<JsonRepresentation> response;
-        try {
-            if (invokeBody != null) {
-                response = restfulClient.follow(link, invokeBody);
-            } else {
-                response = restfulClient.follow(link);
-            }
-        } catch (final Exception e) {
-            addStep(path, link, null, null, "failed to follow link: " + e.getMessage(), e);
-            return;
-        }
-
-        addStep(path, link, null, response, null, null);
-    }
-
-    /**
-     * The entity returned from the previous walk.
-     * 
-     * <p>
-     * Will return null if the previous walk returned an error.
-     */
-    public JsonRepresentation getEntity() throws JsonParseException, JsonMappingException, IOException {
-        final Step currentStep = currentStep();
-        if (currentStep.response == null || currentStep.error != null) {
-            return null;
-        }
-        return currentStep.response.getEntity();
-    }
-
-    /**
-     * The response returned from the previous walk.
-     * 
-     * <p>
-     * Once a walk/performed has been attempted, is guaranteed to return a
-     * non-null value. (Conversely, will return <tt>null</tt> immediately after
-     * instantiation and prior to a walk being attempted/performed).
-     */
-    public RestfulResponse<?> getResponse() {
-        final Step currentStep = currentStep();
-        return currentStep != null ? currentStep.response : null;
-    }
-
-    /**
-     * The error (if any) that occurred from the previous walk.
-     */
-    public String getError() {
-        final Step currentStep = currentStep();
-        return currentStep != null ? currentStep.error : null;
-    }
-
-    /**
-     * The exception (if any) that occurred from the previous walk.
-     * 
-     * <p>
-     * Will only ever be populated if {@link #getError()} is non-null.
-     */
-    public Exception getException() {
-        final Step currentStep = currentStep();
-        return currentStep != null ? currentStep.exception : null;
-    }
-
-    /**
-     * The step that has just been walked.
-     */
-    private Step currentStep() {
-        return steps.get(0);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/7b745ecd/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/RestfulClient.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/RestfulClient.java b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/RestfulClient.java
deleted file mode 100644
index 19589a2..0000000
--- a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/RestfulClient.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- *  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.applib;
-
-import java.net.URI;
-
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import org.apache.commons.httpclient.HttpClient;
-import org.apache.isis.viewer.restfulobjects.applib.domainobjects.DomainObjectResource;
-import org.apache.isis.viewer.restfulobjects.applib.domainobjects.DomainServiceResource;
-import org.apache.isis.viewer.restfulobjects.applib.domaintypes.DomainTypeResource;
-import org.apache.isis.viewer.restfulobjects.applib.homepage.HomePageResource;
-import org.apache.isis.viewer.restfulobjects.applib.links.LinkRepresentation;
-import org.apache.isis.viewer.restfulobjects.applib.user.UserResource;
-import org.apache.isis.viewer.restfulobjects.applib.version.VersionResource;
-import org.jboss.resteasy.client.ClientExecutor;
-import org.jboss.resteasy.client.ClientRequestFactory;
-import org.jboss.resteasy.client.core.executors.ApacheHttpClientExecutor;
-
-public class RestfulClient {
-
-    private final HomePageResource homePageResource;
-    private final UserResource userResource;
-    private final VersionResource versionResource;
-    private final DomainObjectResource domainObjectResource;
-    private final DomainServiceResource domainServiceResource;
-    private final DomainTypeResource domainTypeResource;
-
-    private final ClientExecutor executor;
-    private final ClientRequestFactory clientRequestFactory;
-
-    public RestfulClient(final URI baseUri) {
-        this(baseUri, new ApacheHttpClientExecutor(new HttpClient()));
-    }
-
-    public RestfulClient(final URI baseUri, final ClientExecutor clientExecutor) {
-        this.executor = clientExecutor;
-        this.clientRequestFactory = new ClientRequestFactory(clientExecutor, baseUri);
-
-        this.homePageResource = clientRequestFactory.createProxy(HomePageResource.class);
-        this.userResource = clientRequestFactory.createProxy(UserResource.class);
-        this.domainTypeResource = clientRequestFactory.createProxy(DomainTypeResource.class);
-        this.domainServiceResource = clientRequestFactory.createProxy(DomainServiceResource.class);
-        this.domainObjectResource = clientRequestFactory.createProxy(DomainObjectResource.class);
-        this.versionResource = clientRequestFactory.createProxy(VersionResource.class);
-    }
-
-    // ///////////////////////////////////////////////////////////////
-    // resources
-    // ///////////////////////////////////////////////////////////////
-
-    public HomePageResource getHomePageResource() {
-        return homePageResource;
-    }
-
-    public UserResource getUserResource() {
-        return userResource;
-    }
-
-    public VersionResource getVersionResource() {
-        return versionResource;
-    }
-
-    public DomainTypeResource getDomainTypeResource() {
-        return domainTypeResource;
-    }
-
-    public DomainObjectResource getDomainObjectResource() {
-        return domainObjectResource;
-    }
-
-    public DomainServiceResource getDomainServiceResource() {
-        return domainServiceResource;
-    }
-
-    // ///////////////////////////////////////////////////////////////
-    // resource walking support
-    // ///////////////////////////////////////////////////////////////
-
-    public RepresentationWalker createWalker(final Response response) {
-        return new RepresentationWalker(this, response);
-    }
-
-    public RestfulResponse<JsonRepresentation> follow(final LinkRepresentation link) throws Exception {
-        return followT(link);
-    }
-
-    public <T extends JsonRepresentation> RestfulResponse<T> followT(final LinkRepresentation link) throws Exception {
-        return followT(link, JsonRepresentation.newMap());
-    }
-
-    public RestfulResponse<JsonRepresentation> follow(final LinkRepresentation link, final JsonRepresentation requestArgs) throws Exception {
-        return followT(link, requestArgs);
-    }
-
-    public <T extends JsonRepresentation> RestfulResponse<T> followT(final LinkRepresentation link, final JsonRepresentation requestArgs) throws Exception {
-        return link.<T> follow(executor, requestArgs);
-    }
-
-    public RestfulRequest createRequest(final RoHttpMethod httpMethod, final String uriTemplate) {
-
-        final boolean includesScheme = uriTemplate.startsWith("http:") || uriTemplate.startsWith("https:");
-        final String base = clientRequestFactory.getBase().toString();
-        final String uri = (includesScheme ? "" : base) + uriTemplate;
-
-        final ClientRequestConfigurer clientRequestConfigurer = ClientRequestConfigurer.create(executor, uri);
-
-        clientRequestConfigurer.accept(MediaType.APPLICATION_JSON_TYPE);
-        clientRequestConfigurer.setHttpMethod(httpMethod);
-
-        return new RestfulRequest(clientRequestConfigurer);
-    }
-
-    /**
-     * exposed for testing purposes only.
-     */
-    public ClientRequestFactory getClientRequestFactory() {
-        return clientRequestFactory;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/7b745ecd/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/RestfulClientException.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/RestfulClientException.java b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/RestfulClientException.java
deleted file mode 100644
index c7b36b5..0000000
--- a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/RestfulClientException.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- *  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.applib;
-
-public class RestfulClientException extends RuntimeException {
-
-    private static final long serialVersionUID = 1L;
-
-    public RestfulClientException() {
-    }
-
-    public RestfulClientException(final String message) {
-        super(message);
-    }
-
-    public RestfulClientException(final Throwable cause) {
-        super(cause);
-    }
-
-    public RestfulClientException(final String message, final Throwable cause) {
-        super(message, cause);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/7b745ecd/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/RestfulHttpMethod.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/RestfulHttpMethod.java b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/RestfulHttpMethod.java
new file mode 100644
index 0000000..db3c25f
--- /dev/null
+++ b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/RestfulHttpMethod.java
@@ -0,0 +1,93 @@
+/*
+ *  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.applib;
+
+import org.apache.isis.viewer.restfulobjects.applib.client.ClientRequestConfigurer;
+import org.jboss.resteasy.client.ClientRequest;
+import org.jboss.resteasy.specimpl.UriBuilderImpl;
+
+public enum RestfulHttpMethod {
+    GET(javax.ws.rs.HttpMethod.GET, ArgStrategy.QUERY_STRING), 
+    PUT(javax.ws.rs.HttpMethod.PUT, ArgStrategy.BODY), 
+    DELETE(javax.ws.rs.HttpMethod.DELETE, ArgStrategy.QUERY_STRING), 
+    POST(javax.ws.rs.HttpMethod.POST, ArgStrategy.BODY);
+
+    private enum ArgStrategy {
+        /**
+         * Individually encodes each query arg.
+         */
+        QUERY_ARGS {
+            @Override
+            void setUpArgs(final ClientRequestConfigurer clientRequestConfigurer, final JsonRepresentation requestArgs) {
+                clientRequestConfigurer.queryArgs(requestArgs);
+            }
+        },
+        /**
+         * Sends entire request args as a URL encoded map
+         */
+        QUERY_STRING {
+            @Override
+            void setUpArgs(final ClientRequestConfigurer clientRequestConfigurer, final JsonRepresentation requestArgs) {
+                clientRequestConfigurer.queryString(requestArgs);
+            }
+        },
+        BODY {
+            @Override
+            void setUpArgs(final ClientRequestConfigurer clientRequestConfigurer, final JsonRepresentation requestArgs) {
+                clientRequestConfigurer.body(requestArgs);
+            }
+        };
+        abstract void setUpArgs(ClientRequestConfigurer clientRequestConfigurer, JsonRepresentation requestArgs);
+    }
+
+    private final String javaxRsMethod;
+    private final ArgStrategy argStrategy;
+
+    private RestfulHttpMethod(final String javaxRsMethod, final ArgStrategy argStrategy) {
+        this.javaxRsMethod = javaxRsMethod;
+        this.argStrategy = argStrategy;
+    }
+
+    public String getJavaxRsMethod() {
+        return javaxRsMethod;
+    }
+
+    /**
+     * It's a bit nasty that we need to ask for the {@link UriBuilderImpl} as
+     * well as the {@link ClientRequest}, but that's because the
+     * {@link ClientRequest} does not allow us to setup raw query strings (only
+     * query name/arg pairs)
+     * 
+     * @param restEasyRequest
+     * @param uriBuilder
+     *            - that sits underneath the restEasyRequest
+     * @param requestArgs
+     */
+    public void setUpArgs(final ClientRequestConfigurer clientRequestConfigurer, final JsonRepresentation requestArgs) {
+        clientRequestConfigurer.setHttpMethod(this);
+        if (requestArgs == null) {
+            return;
+        }
+        if (!requestArgs.isMap()) {
+            throw new IllegalArgumentException("requestArgs must be a map; instead got: " + requestArgs);
+        }
+        argStrategy.setUpArgs(clientRequestConfigurer, requestArgs);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/7b745ecd/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/RestfulRequest.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/RestfulRequest.java b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/RestfulRequest.java
deleted file mode 100644
index d67eb50..0000000
--- a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/RestfulRequest.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- *  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.applib;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import org.apache.isis.viewer.restfulobjects.applib.util.Parser;
-import org.jboss.resteasy.client.core.BaseClientResponse;
-
-import com.google.common.collect.Maps;
-
-public final class RestfulRequest {
-
-    public enum DomainModel {
-        NONE, SIMPLE, FORMAL, SELECTABLE;
-
-        public static Parser<DomainModel> parser() {
-            return new Parser<RestfulRequest.DomainModel>() {
-
-                @Override
-                public DomainModel valueOf(final String str) {
-                    return DomainModel.valueOf(str.toUpperCase());
-                }
-
-                @Override
-                public String asString(final DomainModel t) {
-                    return t.name().toLowerCase();
-                }
-            };
-        }
-
-        @Override
-        public String toString() {
-            return name().toLowerCase();
-        }
-    }
-
-    public static class RequestParameter<Q> {
-
-        public static RequestParameter<List<List<String>>> FOLLOW_LINKS = new RequestParameter<List<List<String>>>("x-ro-follow-links", Parser.forListOfListOfStrings(), Collections.<List<String>> emptyList());
-        public static RequestParameter<Integer> PAGE = new RequestParameter<Integer>("x-ro-page", Parser.forInteger(), 1);
-        public static RequestParameter<Integer> PAGE_SIZE = new RequestParameter<Integer>("x-ro-page-size", Parser.forInteger(), 25);
-        public static RequestParameter<List<String>> SORT_BY = new RequestParameter<List<String>>("x-ro-sort-by", Parser.forListOfStrings(), Collections.<String> emptyList());
-        public static RequestParameter<DomainModel> DOMAIN_MODEL = new RequestParameter<DomainModel>("x-ro-domain-model", DomainModel.parser(), DomainModel.SIMPLE);
-        public static RequestParameter<Boolean> VALIDATE_ONLY = new RequestParameter<Boolean>("x-ro-validate-only", Parser.forBoolean(), false);
-
-        private final String name;
-        private final Parser<Q> parser;
-        private final Q defaultValue;
-
-        private RequestParameter(final String name, final Parser<Q> parser, final Q defaultValue) {
-            this.name = name;
-            this.parser = parser;
-            this.defaultValue = defaultValue;
-        }
-
-        public String getName() {
-            return name;
-        }
-
-        public Parser<Q> getParser() {
-            return parser;
-        }
-
-        public Q valueOf(final JsonRepresentation parameterRepresentation) {
-            if (parameterRepresentation == null) {
-                return defaultValue;
-            }
-            if (!parameterRepresentation.isMap()) {
-                return defaultValue;
-            }
-            final Q parsedValue = getParser().valueOf(parameterRepresentation.getRepresentation(getName()));
-            return parsedValue != null ? parsedValue : defaultValue;
-        }
-
-        public Q getDefault() {
-            return defaultValue;
-        }
-
-        @Override
-        public String toString() {
-            return getName();
-        }
-    }
-
-    public static class Header<X> {
-        public static Header<String> IF_MATCH = new Header<String>("If-Match", Parser.forString());
-        public static Header<List<MediaType>> ACCEPT = new Header<List<MediaType>>("Accept", Parser.forListOfJaxRsMediaTypes());
-
-        private final String name;
-        private final Parser<X> parser;
-
-        /**
-         * public visibility for testing purposes only.
-         */
-        public Header(final String name, final Parser<X> parser) {
-            this.name = name;
-            this.parser = parser;
-        }
-
-        public String getName() {
-            return name;
-        }
-
-        public Parser<X> getParser() {
-            return parser;
-        }
-
-        void setHeader(final ClientRequestConfigurer clientRequestConfigurer, final X t) {
-            clientRequestConfigurer.header(getName(), parser.asString(t));
-        }
-
-        @Override
-        public String toString() {
-            return getName();
-        }
-    }
-
-    private final ClientRequestConfigurer clientRequestConfigurer;
-    private final Map<RequestParameter<?>, Object> args = Maps.newLinkedHashMap();
-
-    public RestfulRequest(final ClientRequestConfigurer clientRequestConfigurer) {
-        this.clientRequestConfigurer = clientRequestConfigurer;
-    }
-
-    public <T> RestfulRequest withHeader(final Header<T> header, final T t) {
-        header.setHeader(clientRequestConfigurer, t);
-        return this;
-    }
-
-    public <T> RestfulRequest withHeader(final Header<List<T>> header, final T... ts) {
-        header.setHeader(clientRequestConfigurer, Arrays.asList(ts));
-        return this;
-    }
-
-    public <Q> RestfulRequest withArg(final RestfulRequest.RequestParameter<Q> queryParam, final String argStrFormat, final Object... args) {
-        final String argStr = String.format(argStrFormat, args);
-        final Q arg = queryParam.getParser().valueOf(argStr);
-        return withArg(queryParam, arg);
-    }
-
-    public <Q> RestfulRequest withArg(final RestfulRequest.RequestParameter<Q> queryParam, final Q arg) {
-        args.put(queryParam, arg);
-        return this;
-    }
-
-    public RestfulResponse<JsonRepresentation> execute() {
-        try {
-            if (!args.isEmpty()) {
-                clientRequestConfigurer.configureArgs(args);
-            }
-            final Response response = clientRequestConfigurer.getClientRequest().execute();
-
-            // this is a bit hacky
-            @SuppressWarnings("unchecked")
-            final BaseClientResponse<String> restEasyResponse = (BaseClientResponse<String>) response;
-            restEasyResponse.setReturnType(String.class);
-
-            return RestfulResponse.ofT(response);
-        } catch (final Exception ex) {
-            throw new RuntimeException(ex);
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    public <T extends JsonRepresentation> RestfulResponse<T> executeT() {
-        final RestfulResponse<JsonRepresentation> restfulResponse = execute();
-        return (RestfulResponse<T>) restfulResponse;
-    }
-
-    /**
-     * For testing only.
-     */
-    ClientRequestConfigurer getClientRequestConfigurer() {
-        return clientRequestConfigurer;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/7b745ecd/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/RestfulResponse.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/RestfulResponse.java b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/RestfulResponse.java
deleted file mode 100644
index e543df7..0000000
--- a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/RestfulResponse.java
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- *  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.applib;
-
-import java.io.IOException;
-import java.util.Date;
-import java.util.Map;
-
-import javax.ws.rs.core.CacheControl;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
-import javax.ws.rs.core.Response.Status.Family;
-import javax.ws.rs.core.Response.StatusType;
-
-import org.apache.isis.viewer.restfulobjects.applib.util.JsonMapper;
-import org.apache.isis.viewer.restfulobjects.applib.util.Parser;
-import org.codehaus.jackson.JsonParseException;
-import org.codehaus.jackson.map.JsonMappingException;
-
-import com.google.common.collect.Maps;
-
-public class RestfulResponse<T> {
-
-    public final static class HttpStatusCode {
-
-        private final static Map<Status, HttpStatusCode> statii = Maps.newHashMap();
-        private final static Map<Integer, HttpStatusCode> statusCodes = Maps.newHashMap();
-
-        private static class StatusTypeImpl implements StatusType {
-
-            private final int statusCode;
-            private final Family family;
-            private final String reasonPhrase;
-
-            private StatusTypeImpl(final int statusCode, final Family family, final String reasonPhrase) {
-                this.statusCode = statusCode;
-                this.family = family;
-                this.reasonPhrase = reasonPhrase;
-            }
-
-            @Override
-            public int getStatusCode() {
-                return statusCode;
-            }
-
-            @Override
-            public Family getFamily() {
-                return family;
-            }
-
-            @Override
-            public String getReasonPhrase() {
-                return reasonPhrase;
-            }
-        }
-
-        public static HttpStatusCode lookup(final int status) {
-            return statusCodes.get(status);
-        }
-
-        public static Family lookupFamily(final int statusCode) {
-            switch (statusCode / 100) {
-            case 1:
-                return Family.INFORMATIONAL;
-            case 2:
-                return Family.SUCCESSFUL;
-            case 3:
-                return Family.REDIRECTION;
-            case 4:
-                return Family.CLIENT_ERROR;
-            case 5:
-                return Family.SERVER_ERROR;
-            default:
-                return Family.OTHER;
-            }
-        }
-
-        // public static final int SC_CONTINUE = 100;
-        // public static final int SC_SWITCHING_PROTOCOLS = 101;
-        // public static final int SC_PROCESSING = 102;
-
-        public final static HttpStatusCode OK = new HttpStatusCode(200, Status.OK);
-        public final static HttpStatusCode CREATED = new HttpStatusCode(201, Status.CREATED);
-
-        // public static final int SC_ACCEPTED = 202;
-        // public static final int SC_NON_AUTHORITATIVE_INFORMATION = 203;
-
-        public static final HttpStatusCode NO_CONTENT = new HttpStatusCode(204, Status.NO_CONTENT);
-
-        // public static final int SC_RESET_CONTENT = 205;
-        // public static final int SC_PARTIAL_CONTENT = 206;
-        // public static final int SC_MULTI_STATUS = 207;
-        // public static final int SC_MULTIPLE_CHOICES = 300;
-        // public static final int SC_MOVED_PERMANENTLY = 301;
-        // public static final int SC_MOVED_TEMPORARILY = 302;
-        // public static final int SC_SEE_OTHER = 303;
-        public final static HttpStatusCode NOT_MODIFIED = new HttpStatusCode(304, Status.BAD_REQUEST);
-
-        // public static final int SC_NOT_MODIFIED = 304;
-        // public static final int SC_USE_PROXY = 305;
-        // public static final int SC_TEMPORARY_REDIRECT = 307;
-
-        public final static HttpStatusCode BAD_REQUEST = new HttpStatusCode(400, Status.BAD_REQUEST);
-        public final static HttpStatusCode UNAUTHORIZED = new HttpStatusCode(401, Status.UNAUTHORIZED);
-
-        // public static final int SC_PAYMENT_REQUIRED = 402;
-        // public static final int SC_FORBIDDEN = 403;
-
-        public final static HttpStatusCode NOT_FOUND = new HttpStatusCode(404, Status.NOT_FOUND);
-        public final static HttpStatusCode METHOD_NOT_ALLOWED = new HttpStatusCode(405, new StatusTypeImpl(405, Family.CLIENT_ERROR, "Method not allowed"));
-        public final static HttpStatusCode NOT_ACCEPTABLE = new HttpStatusCode(406, Status.NOT_ACCEPTABLE);
-
-        // public static final int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
-        // public static final int SC_REQUEST_TIMEOUT = 408;
-
-        public final static HttpStatusCode CONFLICT = new HttpStatusCode(409, Status.CONFLICT);
-
-        // public static final int SC_GONE = 410;
-        // public static final int SC_LENGTH_REQUIRED = 411;
-        // public static final int SC_PRECONDITION_FAILED = 412;
-        // public static final int SC_REQUEST_TOO_LONG = 413;
-        // public static final int SC_REQUEST_URI_TOO_LONG = 414;
-        // public static final int SC_UNSUPPORTED_MEDIA_TYPE = 415;
-
-        public final static HttpStatusCode UNSUPPORTED_MEDIA_TYPE = new HttpStatusCode(415, Status.UNSUPPORTED_MEDIA_TYPE);
-
-        // public static final int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
-        // public static final int SC_EXPECTATION_FAILED = 417;
-        // public static final int SC_INSUFFICIENT_SPACE_ON_RESOURCE = 419;
-
-        public final static HttpStatusCode METHOD_FAILURE = new HttpStatusCode(420, new StatusTypeImpl(420, Family.CLIENT_ERROR, "Method failure"));
-
-        // public static final int SC_UNPROCESSABLE_ENTITY = 422;
-        // public static final int SC_LOCKED = 423;
-        // public static final int SC_FAILED_DEPENDENCY = 424;
-
-        public final static HttpStatusCode INTERNAL_SERVER_ERROR = new HttpStatusCode(500, Status.INTERNAL_SERVER_ERROR);
-        public final static HttpStatusCode NOT_IMPLEMENTED = new HttpStatusCode(501, new StatusTypeImpl(501, Family.SERVER_ERROR, "Not implemented"));
-
-        // public static final int SC_BAD_GATEWAY = 502;
-        // public static final int SC_SERVICE_UNAVAILABLE = 503;
-        // public static final int SC_GATEWAY_TIMEOUT = 504;
-        // public static final int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
-        // public static final int SC_INSUFFICIENT_STORAGE = 507;
-
-        public final static HttpStatusCode statusFor(final int statusCode) {
-            final HttpStatusCode httpStatusCode = statusCodes.get(statusCode);
-            if (httpStatusCode != null) {
-                return httpStatusCode;
-            }
-            return syncStatusFor(statusCode);
-        }
-
-        public final static HttpStatusCode statusFor(final Status status) {
-            return statii.get(status);
-        }
-
-        private final static synchronized HttpStatusCode syncStatusFor(final int statusCode) {
-            HttpStatusCode httpStatusCode = statusCodes.get(statusCode);
-            if (httpStatusCode == null) {
-                httpStatusCode = new HttpStatusCode(statusCode, null);
-                statusCodes.put(statusCode, httpStatusCode);
-            }
-            return httpStatusCode;
-        }
-
-        private final int statusCode;
-        private final Family family;
-        private final StatusType jaxrsStatusType;
-
-        private HttpStatusCode(final int statusCode, final StatusType status) {
-            this.statusCode = statusCode;
-            this.jaxrsStatusType = status;
-            family = lookupFamily(statusCode);
-            statusCodes.put(statusCode, this);
-        }
-
-        public int getStatusCode() {
-            return statusCode;
-        }
-
-        public StatusType getJaxrsStatusType() {
-            return jaxrsStatusType;
-        }
-
-        public Family getFamily() {
-            return family;
-        }
-
-        @Override
-        public int hashCode() {
-            return statusCode;
-        }
-
-        @Override
-        public boolean equals(final Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (obj == null) {
-                return false;
-            }
-            if (getClass() != obj.getClass()) {
-                return false;
-            }
-            final HttpStatusCode other = (HttpStatusCode) obj;
-            if (statusCode != other.statusCode) {
-                return false;
-            }
-            return true;
-        }
-
-        @Override
-        public String toString() {
-            return "HttpStatusCode " + statusCode + ", " + family;
-        }
-
-    }
-
-    public static class Header<X> {
-
-        public final static Header<String> WARNING = new Header<String>("Warning", Parser.forString());
-        public final static Header<Date> LAST_MODIFIED = new Header<Date>("Last-Modified", Parser.forDate());
-        public final static Header<CacheControl> CACHE_CONTROL = new Header<CacheControl>("Cache-Control", Parser.forCacheControl());
-        public final static Header<MediaType> CONTENT_TYPE = new Header<MediaType>("Content-Type", Parser.forJaxRsMediaType());
-
-        private final String name;
-        private final Parser<X> parser;
-
-        private Header(final String name, final Parser<X> parser) {
-            this.name = name;
-            this.parser = parser;
-        }
-
-        public String getName() {
-            return name;
-        }
-
-        public X parse(final String value) {
-            return parser.valueOf(value);
-        }
-
-    }
-
-    private final Response response;
-    private final HttpStatusCode httpStatusCode;
-    private final Class<T> returnType;
-
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    public static RestfulResponse<JsonRepresentation> of(final Response response) {
-        final MediaType jaxRsMediaType = getHeader(response, Header.CONTENT_TYPE);
-        final RepresentationType representationType = RepresentationType.lookup(jaxRsMediaType);
-        final Class<? extends JsonRepresentation> returnType = representationType.getRepresentationClass();
-        return new RestfulResponse(response, returnType);
-    }
-
-    @SuppressWarnings("unchecked")
-    public static <T extends JsonRepresentation> RestfulResponse<T> ofT(final Response response) {
-        return (RestfulResponse<T>) of(response);
-    }
-
-    private RestfulResponse(final Response response, final Class<T> returnType) {
-        this.response = response;
-        this.httpStatusCode = HttpStatusCode.statusFor(response.getStatus());
-        this.returnType = returnType;
-    }
-
-    public HttpStatusCode getStatus() {
-        return httpStatusCode;
-    }
-
-    public T getEntity() throws JsonParseException, JsonMappingException, IOException {
-        return JsonMapper.instance().read(response, returnType);
-    }
-
-    public <V> V getHeader(final Header<V> header) {
-        return getHeader(response, header);
-    }
-
-    private static <V> V getHeader(final Response response, final Header<V> header) {
-        final MultivaluedMap<String, Object> metadata = response.getMetadata();
-        // always returns a String
-        final String value = (String) metadata.getFirst(header.getName());
-        return header.parse(value);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/7b745ecd/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/RoHttpMethod.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/RoHttpMethod.java b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/RoHttpMethod.java
deleted file mode 100644
index eb2679d..0000000
--- a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/RoHttpMethod.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- *  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.applib;
-
-import org.jboss.resteasy.client.ClientRequest;
-import org.jboss.resteasy.specimpl.UriBuilderImpl;
-
-public enum RoHttpMethod {
-    GET(javax.ws.rs.HttpMethod.GET, ArgStrategy.QUERY_STRING), 
-    PUT(javax.ws.rs.HttpMethod.PUT, ArgStrategy.BODY), 
-    DELETE(javax.ws.rs.HttpMethod.DELETE, ArgStrategy.QUERY_STRING), 
-    POST(javax.ws.rs.HttpMethod.POST, ArgStrategy.BODY);
-
-    private enum ArgStrategy {
-        /**
-         * Individually encodes each query arg.
-         */
-        QUERY_ARGS {
-            @Override
-            void setUpArgs(final ClientRequestConfigurer clientRequestConfigurer, final JsonRepresentation requestArgs) {
-                clientRequestConfigurer.queryArgs(requestArgs);
-            }
-        },
-        /**
-         * Sends entire request args as a URL encoded map
-         */
-        QUERY_STRING {
-            @Override
-            void setUpArgs(final ClientRequestConfigurer clientRequestConfigurer, final JsonRepresentation requestArgs) {
-                clientRequestConfigurer.queryString(requestArgs);
-            }
-        },
-        BODY {
-            @Override
-            void setUpArgs(final ClientRequestConfigurer clientRequestConfigurer, final JsonRepresentation requestArgs) {
-                clientRequestConfigurer.body(requestArgs);
-            }
-        };
-        abstract void setUpArgs(ClientRequestConfigurer clientRequestConfigurer, JsonRepresentation requestArgs);
-    }
-
-    private final String javaxRsMethod;
-    private final ArgStrategy argStrategy;
-
-    private RoHttpMethod(final String javaxRsMethod, final ArgStrategy argStrategy) {
-        this.javaxRsMethod = javaxRsMethod;
-        this.argStrategy = argStrategy;
-    }
-
-    public String getJavaxRsMethod() {
-        return javaxRsMethod;
-    }
-
-    /**
-     * It's a bit nasty that we need to ask for the {@link UriBuilderImpl} as
-     * well as the {@link ClientRequest}, but that's because the
-     * {@link ClientRequest} does not allow us to setup raw query strings (only
-     * query name/arg pairs)
-     * 
-     * @param restEasyRequest
-     * @param uriBuilder
-     *            - that sits underneath the restEasyRequest
-     * @param requestArgs
-     */
-    public void setUpArgs(final ClientRequestConfigurer clientRequestConfigurer, final JsonRepresentation requestArgs) {
-        clientRequestConfigurer.setHttpMethod(this);
-        if (requestArgs == null) {
-            return;
-        }
-        if (!requestArgs.isMap()) {
-            throw new IllegalArgumentException("requestArgs must be a map; instead got: " + requestArgs);
-        }
-        argStrategy.setUpArgs(clientRequestConfigurer, requestArgs);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/7b745ecd/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/client/ClientRequestConfigurer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/client/ClientRequestConfigurer.java b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/client/ClientRequestConfigurer.java
new file mode 100644
index 0000000..a7a1b05
--- /dev/null
+++ b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/client/ClientRequestConfigurer.java
@@ -0,0 +1,174 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.restfulobjects.applib.client;
+
+import java.util.Map;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.UriBuilder;
+
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.LinkRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.RestfulHttpMethod;
+import org.apache.isis.viewer.restfulobjects.applib.client.RestfulRequest.RequestParameter;
+import org.apache.isis.viewer.restfulobjects.applib.util.UrlEncodingUtils;
+import org.jboss.resteasy.client.ClientExecutor;
+import org.jboss.resteasy.client.ClientRequest;
+import org.jboss.resteasy.specimpl.UriBuilderImpl;
+
+/**
+ * Configures the body, query string etc of a {@link ClientRequest}.
+ * 
+ * <p>
+ * Needed because, unfortunately, {@link ClientRequest} does not seem to allow
+ * the query string to be set directly (only
+ * {@link ClientRequest#getQueryParameters() query parameters}). Instead, it is
+ * necessary to {@link UriBuilderImpl#replaceQuery(String) use} its underlying
+ * {@link UriBuilderImpl}.
+ */
+public class ClientRequestConfigurer {
+
+    public static ClientRequestConfigurer create(final ClientExecutor executor, final String uriTemplate) {
+        final UriBuilder uriBuilder = new UriBuilderImpl().uriTemplate(uriTemplate);
+        final ClientRequest clientRequest = executor.createRequest(uriBuilder);
+        return new ClientRequestConfigurer(clientRequest, uriBuilder);
+    }
+
+    private final ClientRequest clientRequest;
+    private final UriBuilder uriBuilder;
+
+    ClientRequestConfigurer(final ClientRequest clientRequest, final UriBuilder uriBuilder) {
+        this.clientRequest = clientRequest;
+        this.uriBuilder = uriBuilder;
+    }
+
+    public ClientRequestConfigurer accept(final MediaType mediaType) {
+        clientRequest.accept(mediaType);
+        return this;
+    }
+
+    public ClientRequestConfigurer header(final String name, final String value) {
+        clientRequest.header(name, value);
+        return this;
+    }
+
+    /**
+     * Prerequisite to {@link #configureArgs(JsonRepresentation)} or
+     * {@link #configureArgs(Map)}.
+     */
+    public ClientRequestConfigurer setHttpMethod(final RestfulHttpMethod httpMethod) {
+        clientRequest.setHttpMethod(httpMethod.getJavaxRsMethod());
+        return this;
+    }
+
+    /**
+     * Used when creating a request with arguments to execute.
+     * 
+     * <p>
+     * Typical flow is:
+     * <ul>
+     * <li> {@link RestfulClient#createRequest(RestfulHttpMethod, String)}
+     * <li> {@link RestfulRequest#withArg(RequestParameter, Object)} for each arg
+     * <li> {@link RestfulRequest#execute()} - which calls this method.
+     * </ul>
+     */
+    public ClientRequestConfigurer configureArgs(final Map<RequestParameter<?>, Object> args) {
+        if (clientRequest.getHttpMethod() == null) {
+            throw new IllegalStateException("Must set up http method first");
+        }
+
+        final JsonRepresentation argsAsMap = JsonRepresentation.newMap();
+        for (final RequestParameter<?> requestParam : args.keySet()) {
+            put(args, requestParam, argsAsMap);
+        }
+        getHttpMethod().setUpArgs(this, argsAsMap);
+        return this;
+    }
+
+    private <P> void put(final Map<RequestParameter<?>, Object> args, final RequestParameter<P> requestParam, final JsonRepresentation argsAsMap) {
+        @SuppressWarnings("unchecked")
+        final P value = (P) args.get(requestParam);
+        final String valueStr = requestParam.getParser().asString(value);
+        argsAsMap.mapPut(requestParam.getName(), valueStr);
+    }
+
+    /**
+     * Used when following links (
+     * {@link RestfulClient#follow(LinkRepresentation)}).
+     */
+    public ClientRequestConfigurer configureArgs(final JsonRepresentation requestArgs) {
+        if (clientRequest.getHttpMethod() == null) {
+            throw new IllegalStateException("Must set up http method first");
+        }
+
+        getHttpMethod().setUpArgs(this, requestArgs);
+        return this;
+    }
+
+    /**
+     * Called back from
+     * {@link RestfulHttpMethod#setUpArgs(ClientRequestConfigurer, JsonRepresentation)}
+     */
+    public ClientRequestConfigurer body(final JsonRepresentation requestArgs) {
+        clientRequest.body(MediaType.APPLICATION_JSON_TYPE, requestArgs.toString());
+        return this;
+    }
+
+    /**
+     * Called back from
+     * {@link RestfulHttpMethod#setUpArgs(ClientRequestConfigurer, JsonRepresentation)}
+     */
+    public ClientRequestConfigurer queryString(final JsonRepresentation requestArgs) {
+        if (requestArgs.size() == 0) {
+            return this;
+        }
+        final String queryString = UrlEncodingUtils.urlEncode(requestArgs.toString());
+        uriBuilder.replaceQuery(queryString);
+        return this;
+    }
+
+    /**
+     * Called back from
+     * {@link RestfulHttpMethod#setUpArgs(ClientRequestConfigurer, JsonRepresentation)}
+     */
+    public ClientRequestConfigurer queryArgs(final JsonRepresentation requestArgs) {
+        final MultivaluedMap<String, String> queryParameters = clientRequest.getQueryParameters();
+        for (final Map.Entry<String, JsonRepresentation> entry : requestArgs.mapIterable()) {
+            final String param = entry.getKey();
+            final JsonRepresentation argRepr = entry.getValue();
+            final String arg = UrlEncodingUtils.urlEncode(argRepr.asArg());
+            queryParameters.add(param, arg);
+        }
+        return this;
+    }
+
+    /**
+     * For testing.
+     */
+    ClientRequest getClientRequest() {
+        return clientRequest;
+    }
+
+    RestfulHttpMethod getHttpMethod() {
+        final String httpMethod = clientRequest.getHttpMethod();
+        return RestfulHttpMethod.valueOf(httpMethod);
+    }
+
+}
\ No newline at end of file