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

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

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/RepresentationWalker.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/client/RepresentationWalker.java b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/client/RepresentationWalker.java
new file mode 100644
index 0000000..5c2fd87
--- /dev/null
+++ b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/client/RepresentationWalker.java
@@ -0,0 +1,180 @@
+/*
+ *  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.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.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.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/client/RestfulClient.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/client/RestfulClient.java b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/client/RestfulClient.java
new file mode 100644
index 0000000..7aa16f5
--- /dev/null
+++ b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/client/RestfulClient.java
@@ -0,0 +1,141 @@
+/*
+ *  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.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.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.LinkRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.RestfulHttpMethod;
+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.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 RestfulHttpMethod 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/client/RestfulClientException.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/client/RestfulClientException.java b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/client/RestfulClientException.java
new file mode 100644
index 0000000..5023827
--- /dev/null
+++ b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/client/RestfulClientException.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.applib.client;
+
+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/client/RestfulRequest.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/client/RestfulRequest.java b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/client/RestfulRequest.java
new file mode 100644
index 0000000..fa3f0e1
--- /dev/null
+++ b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/client/RestfulRequest.java
@@ -0,0 +1,201 @@
+/*
+ *  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.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.JsonRepresentation;
+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/client/RestfulResponse.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/client/RestfulResponse.java b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/client/RestfulResponse.java
new file mode 100644
index 0000000..17b8818
--- /dev/null
+++ b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/client/RestfulResponse.java
@@ -0,0 +1,307 @@
+/*
+ *  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.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.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+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/domainobjects/AbstractObjectMemberRepresentation.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/domainobjects/AbstractObjectMemberRepresentation.java b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/domainobjects/AbstractObjectMemberRepresentation.java
index a41ade1..d2de410 100644
--- a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/domainobjects/AbstractObjectMemberRepresentation.java
+++ b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/domainobjects/AbstractObjectMemberRepresentation.java
@@ -18,7 +18,7 @@
  */
 package org.apache.isis.viewer.restfulobjects.applib.domainobjects;
 
-import org.apache.isis.viewer.restfulobjects.applib.links.LinkRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.LinkRepresentation;
 import org.codehaus.jackson.JsonNode;
 
 public abstract class AbstractObjectMemberRepresentation extends DomainRepresentation {

http://git-wip-us.apache.org/repos/asf/isis/blob/7b745ecd/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/domainobjects/DomainRepresentation.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/domainobjects/DomainRepresentation.java b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/domainobjects/DomainRepresentation.java
index 55fdc97..784ffde 100644
--- a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/domainobjects/DomainRepresentation.java
+++ b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/domainobjects/DomainRepresentation.java
@@ -19,11 +19,11 @@
 package org.apache.isis.viewer.restfulobjects.applib.domainobjects;
 
 import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.LinkRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.Rel;
 import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation.HasExtensions;
 import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation.HasLinks;
 import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation.LinksToSelf;
-import org.apache.isis.viewer.restfulobjects.applib.links.LinkRepresentation;
-import org.apache.isis.viewer.restfulobjects.applib.links.Rel;
 import org.codehaus.jackson.JsonNode;
 
 public abstract class DomainRepresentation extends JsonRepresentation implements LinksToSelf, HasLinks, HasExtensions {

http://git-wip-us.apache.org/repos/asf/isis/blob/7b745ecd/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/domainobjects/ObjectActionRepresentation.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/domainobjects/ObjectActionRepresentation.java b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/domainobjects/ObjectActionRepresentation.java
index a76f0b5..019adb0 100644
--- a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/domainobjects/ObjectActionRepresentation.java
+++ b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/domainobjects/ObjectActionRepresentation.java
@@ -18,7 +18,7 @@
  */
 package org.apache.isis.viewer.restfulobjects.applib.domainobjects;
 
-import org.apache.isis.viewer.restfulobjects.applib.links.LinkRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.LinkRepresentation;
 import org.codehaus.jackson.JsonNode;
 
 public class ObjectActionRepresentation extends AbstractObjectMemberRepresentation {

http://git-wip-us.apache.org/repos/asf/isis/blob/7b745ecd/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/domainobjects/TransientDomainObjectRepresentation.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/domainobjects/TransientDomainObjectRepresentation.java b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/domainobjects/TransientDomainObjectRepresentation.java
index 4c60ba0..b23f119 100644
--- a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/domainobjects/TransientDomainObjectRepresentation.java
+++ b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/domainobjects/TransientDomainObjectRepresentation.java
@@ -18,7 +18,7 @@
  */
 package org.apache.isis.viewer.restfulobjects.applib.domainobjects;
 
-import org.apache.isis.viewer.restfulobjects.applib.links.LinkRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.LinkRepresentation;
 import org.codehaus.jackson.JsonNode;
 
 public class TransientDomainObjectRepresentation extends AbstractDomainObjectRepresentation {

http://git-wip-us.apache.org/repos/asf/isis/blob/7b745ecd/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/homepage/HomePageRepresentation.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/homepage/HomePageRepresentation.java b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/homepage/HomePageRepresentation.java
index 77e5110..a1e3e74 100644
--- a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/homepage/HomePageRepresentation.java
+++ b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/homepage/HomePageRepresentation.java
@@ -18,8 +18,8 @@
  */
 package org.apache.isis.viewer.restfulobjects.applib.homepage;
 
+import org.apache.isis.viewer.restfulobjects.applib.LinkRepresentation;
 import org.apache.isis.viewer.restfulobjects.applib.domainobjects.DomainRepresentation;
-import org.apache.isis.viewer.restfulobjects.applib.links.LinkRepresentation;
 import org.codehaus.jackson.JsonNode;
 
 public class HomePageRepresentation extends DomainRepresentation {

http://git-wip-us.apache.org/repos/asf/isis/blob/7b745ecd/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/links/LinkRepresentation.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/links/LinkRepresentation.java b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/links/LinkRepresentation.java
deleted file mode 100644
index ae75279..0000000
--- a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/links/LinkRepresentation.java
+++ /dev/null
@@ -1,166 +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.links;
-
-import javax.ws.rs.core.MediaType;
-
-import org.apache.isis.viewer.restfulobjects.applib.ClientRequestConfigurer;
-import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
-import org.apache.isis.viewer.restfulobjects.applib.RestfulRequest;
-import org.apache.isis.viewer.restfulobjects.applib.RestfulResponse;
-import org.apache.isis.viewer.restfulobjects.applib.RoHttpMethod;
-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(RoHttpMethod.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 RoHttpMethod getHttpMethod() {
-        final String methodStr = asObjectNode().path("method").getTextValue();
-        return RoHttpMethod.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 RoHttpMethod 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/links/Rel.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/links/Rel.java b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/links/Rel.java
deleted file mode 100644
index 9d70f03..0000000
--- a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/links/Rel.java
+++ /dev/null
@@ -1,78 +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.links;
-
-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/test/java/org/apache/isis/viewer/restfulobjects/applib/DomainObjectRepresentationTest.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/DomainObjectRepresentationTest.java b/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/DomainObjectRepresentationTest.java
deleted file mode 100644
index 6ef37fa..0000000
--- a/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/DomainObjectRepresentationTest.java
+++ /dev/null
@@ -1,51 +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 static org.apache.isis.viewer.restfulobjects.applib.JsonFixture.readJson;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.not;
-import static org.hamcrest.CoreMatchers.nullValue;
-import static org.junit.Assert.assertThat;
-
-import java.io.IOException;
-
-import org.apache.isis.viewer.restfulobjects.applib.domainobjects.DomainObjectRepresentation;
-import org.codehaus.jackson.JsonParseException;
-import org.codehaus.jackson.map.JsonMappingException;
-import org.junit.Before;
-import org.junit.Test;
-
-public class DomainObjectRepresentationTest {
-
-    private DomainObjectRepresentation representation;
-
-    @Before
-    public void setUp() throws Exception {
-        representation = new DomainObjectRepresentation(readJson("domainObjectRepresentation.json"));
-    }
-
-    @Test
-    public void xx() throws JsonParseException, JsonMappingException, IOException {
-        final JsonRepresentation flag = representation.getProperty("flag");
-        assertThat(flag, is(not(nullValue())));
-        assertThat(flag.getBoolean("value"), is(true));
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/7b745ecd/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonFixture.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonFixture.java b/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonFixture.java
index a2b6cca..6644f92 100644
--- a/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonFixture.java
+++ b/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonFixture.java
@@ -28,7 +28,7 @@ import org.codehaus.jackson.map.JsonMappingException;
 import com.google.common.base.Charsets;
 import com.google.common.io.Resources;
 
-class JsonFixture {
+public class JsonFixture {
 
     private JsonFixture() {
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/7b745ecd/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentationTest_getLink_isLink.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentationTest_getLink_isLink.java b/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentationTest_getLink_isLink.java
index b7c7058..7bc45b9 100644
--- a/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentationTest_getLink_isLink.java
+++ b/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentationTest_getLink_isLink.java
@@ -26,7 +26,6 @@ import static org.junit.Assert.fail;
 
 import java.io.IOException;
 
-import org.apache.isis.viewer.restfulobjects.applib.links.LinkRepresentation;
 import org.codehaus.jackson.JsonParseException;
 import org.codehaus.jackson.map.JsonMappingException;
 import org.junit.Before;
@@ -39,7 +38,7 @@ public class JsonRepresentationTest_getLink_isLink {
 
     @Before
     public void setUp() throws Exception {
-        link = new LinkRepresentation().withHref("http://foo/bar").withMethod(RoHttpMethod.GET);
+        link = new LinkRepresentation().withHref("http://foo/bar").withMethod(RestfulHttpMethod.GET);
         jsonRepresentation = new JsonRepresentation(readJson("map.json"));
     }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/7b745ecd/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentationTest_urlEncoding.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentationTest_urlEncoding.java b/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentationTest_urlEncoding.java
index e1ad36e..c8e8726 100644
--- a/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentationTest_urlEncoding.java
+++ b/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentationTest_urlEncoding.java
@@ -24,7 +24,6 @@ import static org.junit.Assert.assertThat;
 import java.io.UnsupportedEncodingException;
 import java.net.URLDecoder;
 
-import org.apache.isis.viewer.restfulobjects.applib.links.LinkRepresentation;
 import org.junit.Test;
 
 import com.google.common.base.Charsets;
@@ -33,7 +32,7 @@ public class JsonRepresentationTest_urlEncoding {
 
     @Test
     public void test() throws UnsupportedEncodingException {
-        final LinkRepresentation l = new LinkRepresentation().withRel("object").withHref("http://localhost:8080/objects/ABC:123").withMethod(RoHttpMethod.GET);
+        final LinkRepresentation l = new LinkRepresentation().withRel("object").withHref("http://localhost:8080/objects/ABC:123").withMethod(RestfulHttpMethod.GET);
 
         final String expectedValue = "%7B%22method%22%3A%22GET%22%2C%22rel%22%3A%22object%22%2C%22href%22%3A%22http%3A%2F%2Flocalhost%3A8080%2Fobjects%2FABC%3A123%22%7D";
         @SuppressWarnings("unused")

http://git-wip-us.apache.org/repos/asf/isis/blob/7b745ecd/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/LinkRepresentationTest_equals.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/LinkRepresentationTest_equals.java b/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/LinkRepresentationTest_equals.java
new file mode 100644
index 0000000..910c9af
--- /dev/null
+++ b/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/LinkRepresentationTest_equals.java
@@ -0,0 +1,54 @@
+/*
+ *  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 static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.assertThat;
+
+import java.io.UnsupportedEncodingException;
+
+import org.apache.isis.viewer.restfulobjects.applib.LinkRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.RestfulHttpMethod;
+import org.junit.Test;
+
+public class LinkRepresentationTest_equals {
+
+    @Test
+    public void equalDependsOnMethodAndHref() throws UnsupportedEncodingException {
+        final LinkRepresentation link = new LinkRepresentation().withHref("http://localhost:8080/objects/ABC:123").withMethod(RestfulHttpMethod.GET);
+        final LinkRepresentation link2 = new LinkRepresentation().withHref("http://localhost:8080/objects/ABC:123").withMethod(RestfulHttpMethod.GET);
+        final LinkRepresentation link3 = new LinkRepresentation().withHref("http://localhost:8080/objects/ABC:123").withMethod(RestfulHttpMethod.PUT);
+        final LinkRepresentation link4 = new LinkRepresentation().withHref("http://localhost:8080/objects/ABC:456").withMethod(RestfulHttpMethod.GET);
+
+        assertThat(link, is(equalTo(link2)));
+        assertThat(link, is(not(equalTo(link3))));
+        assertThat(link, is(not(equalTo(link4))));
+    }
+
+    @Test
+    public void equalDoesNotDependsOnMethodAndHref() throws UnsupportedEncodingException {
+        final LinkRepresentation link = new LinkRepresentation().withHref("http://localhost:8080/objects/ABC:123").withMethod(RestfulHttpMethod.GET).withRel("something");
+        final LinkRepresentation link2 = new LinkRepresentation().withHref("http://localhost:8080/objects/ABC:123").withMethod(RestfulHttpMethod.GET).withRel("else");
+
+        assertThat(link, is(equalTo(link2)));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/7b745ecd/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/RestfulClientTest_follow.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/RestfulClientTest_follow.java b/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/RestfulClientTest_follow.java
deleted file mode 100644
index f5e2e10..0000000
--- a/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/RestfulClientTest_follow.java
+++ /dev/null
@@ -1,128 +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 org.apache.commons.collections.map.MultiValueMap;
-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.links.LinkRepresentation;
-import org.hamcrest.Description;
-import org.hamcrest.Matcher;
-import org.hamcrest.TypeSafeMatcher;
-import org.jboss.resteasy.client.ClientExecutor;
-import org.jboss.resteasy.client.ClientRequest;
-import org.jboss.resteasy.client.core.BaseClientResponse;
-import org.jboss.resteasy.specimpl.UriBuilderImpl;
-import org.jmock.Expectations;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Rule;
-import org.junit.Test;
-
-public class RestfulClientTest_follow {
-
-    @Rule
-    public JUnitRuleMockery2 context = JUnitRuleMockery2.createFor(Mode.INTERFACES_AND_CLASSES);
-
-    private final URI uri = URI.create("http://yadayada:8080");
-
-    @Mock
-    private ClientExecutor mockExecutor;
-
-    @Mock
-    private ClientRequest mockClientRequest;
-
-    @Mock
-    private BaseClientResponse<String> mockClientResponse;
-
-    private JsonRepresentation jsonRepresentation;
-
-    private RestfulClient client;
-
-    @Before
-    public void setUp() throws Exception {
-        jsonRepresentation = new JsonRepresentation(JsonFixture.readJson("map.json"));
-        client = new RestfulClient(uri, mockExecutor);
-    }
-
-    @Ignore("TODO")
-    @Test
-    public void follow_get() throws Exception {
-        final LinkRepresentation link = jsonRepresentation.getLink("aLink");
-
-        final String href = link.getHref();
-
-        // when
-        context.checking(new Expectations() {
-            {
-                one(mockExecutor).createRequest(with(any(UriBuilderImpl.class)));
-                will(returnValue(mockClientRequest));
-
-                one(mockExecutor).execute(mockClientRequest);
-                will(returnValue(mockClientResponse));
-
-                one(mockClientRequest).accept(MediaType.APPLICATION_JSON_TYPE);
-                atLeast(1).of(mockClientRequest).setHttpMethod("GET");
-
-                allowing(mockClientRequest).getHttpMethod();
-                will(returnValue("GET"));
-
-                one(mockClientRequest).execute();
-                will(returnValue(mockClientResponse));
-
-                one(mockClientResponse).setReturnType(String.class);
-                allowing(mockClientResponse);
-
-                final MultiValueMap result = new MultiValueMap();
-                result.put("Content-Type", "application/json");
-                allowing(mockClientResponse).getMetadata();
-                will(returnValue(result));
-            }
-
-        });
-        final RestfulResponse<JsonRepresentation> response = client.follow(link);
-
-        // then
-    }
-
-    private static Matcher<ClientRequest> requestToHref(final String href) {
-        return new TypeSafeMatcher<ClientRequest>() {
-
-            @Override
-            public void describeTo(final Description description) {
-                description.appendText("request to href: " + href);
-            }
-
-            @Override
-            public boolean matchesSafely(final ClientRequest clientRequest) {
-                try {
-                    return clientRequest.getUri().equals(href);
-                } catch (final Exception e) {
-                    return false;
-                }
-            }
-        };
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/7b745ecd/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/RestfulHttpMethodTest_setUp.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/RestfulHttpMethodTest_setUp.java b/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/RestfulHttpMethodTest_setUp.java
new file mode 100644
index 0000000..07c3d1c
--- /dev/null
+++ b/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/RestfulHttpMethodTest_setUp.java
@@ -0,0 +1,94 @@
+/*
+ *  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.UnsupportedEncodingException;
+
+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.client.ClientRequestConfigurer;
+import org.jmock.Expectations;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class RestfulHttpMethodTest_setUp {
+
+    @Rule
+    public JUnitRuleMockery2 context = JUnitRuleMockery2.createFor(Mode.INTERFACES_AND_CLASSES);
+
+    @Mock
+    private ClientRequestConfigurer requestConfigurer;
+
+    private JsonRepresentation repr;
+
+    @Before
+    public void setUp() throws Exception {
+        repr = JsonRepresentation.newMap();
+        repr.mapPut("aString", "bar");
+        repr.mapPut("anInt", 3);
+        repr.mapPut("aLong", 31231231L);
+        repr.mapPut("aBoolean", true);
+        repr.mapPut("aStringRequiringEncoding", "http://localhost:8080/somewhere");
+    }
+
+    @Test
+    public void get() throws Exception {
+        setsUpQueryString(RestfulHttpMethod.GET);
+    }
+
+    @Test
+    public void delete() throws Exception {
+        setsUpQueryString(RestfulHttpMethod.DELETE);
+    }
+
+    @Test
+    public void post() throws Exception {
+        setsUpBody(RestfulHttpMethod.POST);
+    }
+
+    @Test
+    public void put() throws Exception {
+        setsUpBody(RestfulHttpMethod.PUT);
+    }
+
+    private void setsUpQueryString(final RestfulHttpMethod httpMethod) throws UnsupportedEncodingException {
+        context.checking(new Expectations() {
+            {
+                one(requestConfigurer).setHttpMethod(httpMethod);
+                one(requestConfigurer).queryString(repr);
+            }
+        });
+
+        httpMethod.setUpArgs(requestConfigurer, repr);
+    }
+
+    private void setsUpBody(final RestfulHttpMethod httpMethod) throws UnsupportedEncodingException {
+        context.checking(new Expectations() {
+            {
+                one(requestConfigurer).setHttpMethod(httpMethod);
+                one(requestConfigurer).body(repr);
+            }
+        });
+
+        httpMethod.setUpArgs(requestConfigurer, repr);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/7b745ecd/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/RestfulRequestDomainModelTest_parser.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/RestfulRequestDomainModelTest_parser.java b/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/RestfulRequestDomainModelTest_parser.java
deleted file mode 100644
index 9a93224..0000000
--- a/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/RestfulRequestDomainModelTest_parser.java
+++ /dev/null
@@ -1,39 +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 static org.junit.Assert.assertSame;
-
-import org.apache.isis.viewer.restfulobjects.applib.RestfulRequest.DomainModel;
-import org.apache.isis.viewer.restfulobjects.applib.util.Parser;
-import org.junit.Test;
-
-public class RestfulRequestDomainModelTest_parser {
-
-    @Test
-    public void parser_roundtrips() {
-        final Parser<DomainModel> parser = RestfulRequest.DomainModel.parser();
-        for (final DomainModel domainModel : DomainModel.values()) {
-            final String asString = parser.asString(domainModel);
-            final DomainModel roundtripped = parser.valueOf(asString);
-            assertSame(roundtripped, domainModel);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/7b745ecd/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/RestfulRequestRequestParameterTest_valueOf.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/RestfulRequestRequestParameterTest_valueOf.java b/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/RestfulRequestRequestParameterTest_valueOf.java
deleted file mode 100644
index da72aaa..0000000
--- a/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/RestfulRequestRequestParameterTest_valueOf.java
+++ /dev/null
@@ -1,90 +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 static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-
-import java.util.List;
-
-import org.apache.isis.viewer.restfulobjects.applib.RestfulRequest.RequestParameter;
-import org.junit.Before;
-import org.junit.Test;
-
-public class RestfulRequestRequestParameterTest_valueOf {
-
-    private final RequestParameter<List<List<String>>> requestParameter = RestfulRequest.RequestParameter.FOLLOW_LINKS;
-
-    private JsonRepresentation repr;
-
-    @Before
-    public void setUp() throws Exception {
-        repr = JsonRepresentation.newMap();
-    }
-
-    @Test
-    public void mapContainsList() {
-        repr.mapPut("x-ro-follow-links", "a,b.c");
-        final List<List<String>> valueOf = requestParameter.valueOf(repr);
-
-        assertThat(valueOf.size(), is(2));
-        assertThat(valueOf.get(0).size(), is(1));
-        assertThat(valueOf.get(0).get(0), is("a"));
-        assertThat(valueOf.get(1).size(), is(2));
-        assertThat(valueOf.get(1).get(0), is("b"));
-        assertThat(valueOf.get(1).get(1), is("c"));
-    }
-
-    @Test
-    public void mapHasNoKey() {
-        repr.mapPut("something-else", "a,b.c");
-        final List<List<String>> valueOf = requestParameter.valueOf(repr);
-
-        assertThat(valueOf.size(), is(0));
-    }
-
-    @Test
-    public void mapIsEmpty() {
-        final List<List<String>> valueOf = requestParameter.valueOf(repr);
-
-        assertThat(valueOf.size(), is(0));
-    }
-
-    @Test
-    public void mapIsNull() {
-        final List<List<String>> valueOf = requestParameter.valueOf(null);
-
-        assertThat(valueOf.size(), is(0));
-    }
-
-    @Test
-    public void mapContainsCommaSeparatedList() {
-
-        repr.mapPut("x-ro-follow-links", "a,b.c");
-        final List<List<String>> valueOf = requestParameter.valueOf(repr);
-
-        assertThat(valueOf.size(), is(2));
-        assertThat(valueOf.get(0).size(), is(1));
-        assertThat(valueOf.get(0).get(0), is("a"));
-        assertThat(valueOf.get(1).size(), is(2));
-        assertThat(valueOf.get(1).get(0), is("b"));
-        assertThat(valueOf.get(1).get(1), is("c"));
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/7b745ecd/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/RestfulResponse_HttpStatusCodeTest.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/RestfulResponse_HttpStatusCodeTest.java b/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/RestfulResponse_HttpStatusCodeTest.java
deleted file mode 100644
index d3604e2..0000000
--- a/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/RestfulResponse_HttpStatusCodeTest.java
+++ /dev/null
@@ -1,43 +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 static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-
-import javax.ws.rs.core.Response.Status.Family;
-
-import org.apache.isis.viewer.restfulobjects.applib.RestfulResponse.HttpStatusCode;
-import org.junit.Test;
-
-public class RestfulResponse_HttpStatusCodeTest {
-
-    @Test
-    public void knownStatusCode() {
-        assertThat(HttpStatusCode.statusFor(200), is(HttpStatusCode.OK));
-    }
-
-    @Test
-    public void unknownStatusCode() {
-        final HttpStatusCode statusFor = HttpStatusCode.statusFor(600);
-        assertThat(statusFor.getStatusCode(), is(600));
-        assertThat(statusFor.getFamily(), is(Family.OTHER));
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/7b745ecd/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/RoHttpMethodTest_setUp.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/RoHttpMethodTest_setUp.java b/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/RoHttpMethodTest_setUp.java
deleted file mode 100644
index 903b6ee..0000000
--- a/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/RoHttpMethodTest_setUp.java
+++ /dev/null
@@ -1,93 +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.UnsupportedEncodingException;
-
-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.jmock.Expectations;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-
-public class RoHttpMethodTest_setUp {
-
-    @Rule
-    public JUnitRuleMockery2 context = JUnitRuleMockery2.createFor(Mode.INTERFACES_AND_CLASSES);
-
-    @Mock
-    private ClientRequestConfigurer requestConfigurer;
-
-    private JsonRepresentation repr;
-
-    @Before
-    public void setUp() throws Exception {
-        repr = JsonRepresentation.newMap();
-        repr.mapPut("aString", "bar");
-        repr.mapPut("anInt", 3);
-        repr.mapPut("aLong", 31231231L);
-        repr.mapPut("aBoolean", true);
-        repr.mapPut("aStringRequiringEncoding", "http://localhost:8080/somewhere");
-    }
-
-    @Test
-    public void get() throws Exception {
-        setsUpQueryString(RoHttpMethod.GET);
-    }
-
-    @Test
-    public void delete() throws Exception {
-        setsUpQueryString(RoHttpMethod.DELETE);
-    }
-
-    @Test
-    public void post() throws Exception {
-        setsUpBody(RoHttpMethod.POST);
-    }
-
-    @Test
-    public void put() throws Exception {
-        setsUpBody(RoHttpMethod.PUT);
-    }
-
-    private void setsUpQueryString(final RoHttpMethod httpMethod) throws UnsupportedEncodingException {
-        context.checking(new Expectations() {
-            {
-                one(requestConfigurer).setHttpMethod(httpMethod);
-                one(requestConfigurer).queryString(repr);
-            }
-        });
-
-        httpMethod.setUpArgs(requestConfigurer, repr);
-    }
-
-    private void setsUpBody(final RoHttpMethod httpMethod) throws UnsupportedEncodingException {
-        context.checking(new Expectations() {
-            {
-                one(requestConfigurer).setHttpMethod(httpMethod);
-                one(requestConfigurer).body(repr);
-            }
-        });
-
-        httpMethod.setUpArgs(requestConfigurer, repr);
-    }
-
-}