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/04/27 20:31:35 UTC

[16/50] [abbrv] git commit: ISIS-233: followlinks for service.serviceId

ISIS-233: followlinks for service.serviceId

* and started on bus rule testing, creating tck classes and fixtures.


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

Branch: refs/heads/master
Commit: cfe2b106c4b3804ec2af13ec4bd142ca09005f78
Parents: 5e01f68
Author: Dan Haywood <da...@apache.org>
Authored: Tue Mar 5 20:23:08 2013 +0000
Committer: Dan Haywood <da...@apache.org>
Committed: Sat Apr 27 18:57:37 2013 +0100

----------------------------------------------------------------------
 .../restfulobjects/applib/util/PathNode.java       |   19 ++-
 .../restfulobjects/rendering/LinkFollowSpecs.java  |    8 +-
 .../AbstractObjectMemberReprRenderer.java          |   26 ++-
 .../domainobjects/DomainObjectReprRenderer.java    |   44 +++-
 .../domainobjects/ObjectActionReprRenderer.java    |    8 +-
 .../ObjectCollectionReprRenderer.java              |    6 +-
 .../domainobjects/ObjectPropertyReprRenderer.java  |    6 +-
 .../rendering/LinkFollowSpecsTest_follow.java      |   19 ++-
 .../server/resources/DomainResourceHelper.java     |    6 +-
 .../resources/DomainServiceResourceServerside.java |    4 +-
 .../tck/ide/eclipse/launch/viewer-json-tck.launch  |    2 +-
 .../tck/src/main/webapp/WEB-INF/isis.properties    |   11 +-
 ...ainServiceTest_req_queryarg_xrofollowlinks.java |  110 ++++++++---
 .../DomainServiceTest_resp_representation.java     |    4 +-
 .../isis/core/tck/dom/busrules/BusRulesEntity.java |  164 +++++++++++++++
 .../core/tck/dom/busrules/BusRulesEntityChild.java |   55 +++++
 .../tck/dom/busrules/BusRulesEntityRepository.java |   72 +++++++
 .../fixture/busrules/BusRulesEntityFixture.java    |   50 +++++
 18 files changed, 539 insertions(+), 75 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/cfe2b106/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/util/PathNode.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/util/PathNode.java b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/util/PathNode.java
index a980dae..4cd303a 100644
--- a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/util/PathNode.java
+++ b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/util/PathNode.java
@@ -34,7 +34,7 @@ import com.google.common.collect.Maps;
 public class PathNode {
     private static final Pattern NODE = Pattern.compile("^([^\\[]*)(\\[(.+)\\])?$");
     private static final Pattern WHITESPACE = Pattern.compile("\\s+");
-    private static final Pattern KEY_VALUE = Pattern.compile("^([^=]+)=(.+)$");
+    private static final Pattern LIST_CRITERIA_SYNTAX = Pattern.compile("^([^=]+)=(.+)$");
 
     public static final PathNode NULL = new PathNode("", Collections.<String, String> emptyMap());
 
@@ -79,9 +79,12 @@ public class PathNode {
         final String criteriaStr = nodeMatcher.group(3);
         if (criteriaStr != null) {
             for (final String criterium : Splitter.on(WHITESPACE).split(criteriaStr)) {
-                final Matcher keyValueMatcher = KEY_VALUE.matcher(criterium);
+                final Matcher keyValueMatcher = LIST_CRITERIA_SYNTAX.matcher(criterium);
                 if (keyValueMatcher.matches()) {
                     criteria.put(keyValueMatcher.group(1), keyValueMatcher.group(2));
+                } else {
+                    // take content as a map criteria
+                    criteria.put(criterium, null);
                 }
             }
         }
@@ -115,9 +118,15 @@ public class PathNode {
         }
         for (final Map.Entry<String, String> criterium : getCriteria().entrySet()) {
             final String requiredValue = criterium.getValue();
-            final String actualValue = repr.getString(criterium.getKey());
-            if (!Objects.equal(requiredValue, actualValue)) {
-                return false;
+            if(requiredValue != null) {
+                // list syntax
+                final String actualValue = repr.getString(criterium.getKey());
+                if (!Objects.equal(requiredValue, actualValue)) {
+                    return false;
+                }
+            } else {
+                // map syntax
+                return repr.getRepresentation(criterium.getKey()) != null;
             }
         }
         return true;

http://git-wip-us.apache.org/repos/asf/isis/blob/cfe2b106/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/LinkFollowSpecs.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/LinkFollowSpecs.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/LinkFollowSpecs.java
index ed033a9..253bb17 100644
--- a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/LinkFollowSpecs.java
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/LinkFollowSpecs.java
@@ -105,7 +105,7 @@ public final class LinkFollowSpecs {
      * Any keys in the criterium are ignored (these were matched on during the
      * {@link #follow(String, Object...)} call).
      */
-    public boolean matches(final JsonRepresentation link) {
+    public boolean matches(final JsonRepresentation jsonRepr) {
         if (!isFollowing()) {
             return false;
         }
@@ -113,12 +113,16 @@ public final class LinkFollowSpecs {
             return true;
         }
         for (PathNode criteriaSpec : criteriaSpecs) {
-            if(criteriaSpec.matches(link)) {
+            if(criteriaSpec.matches(jsonRepr)) {
                 return true;
             }
         }
         return false;
     }
 
+    @Override
+    public String toString() {
+        return mode + " : " + criteriaSpecs + " : " + pathSpecs;
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/cfe2b106/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/AbstractObjectMemberReprRenderer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/AbstractObjectMemberReprRenderer.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/AbstractObjectMemberReprRenderer.java
index 63ea8c7..84c8ef4 100644
--- a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/AbstractObjectMemberReprRenderer.java
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/AbstractObjectMemberReprRenderer.java
@@ -65,12 +65,24 @@ public abstract class AbstractObjectMemberReprRenderer<R extends ReprRendererAbs
     protected T objectMember;
     protected Mode mode = Mode.INLINE; // unless we determine otherwise
 
+    /**
+     * Not for rendering, but is the key that the representation being rendered will be held under.
+     * 
+     * <p>
+     * Used to determine whether to follow links; only populated for {@link Mode#INLINE inline} Mode.
+     */
+    private final String memberId;
     private final Where where;
 
-    public AbstractObjectMemberReprRenderer(final RendererContext resourceContext, final LinkFollowSpecs linkFollower, final RepresentationType representationType, final JsonRepresentation representation, Where where) {
+    public AbstractObjectMemberReprRenderer(final RendererContext resourceContext, final LinkFollowSpecs linkFollower, String memberId, final RepresentationType representationType, final JsonRepresentation representation, Where where) {
         super(resourceContext, linkFollower, representationType, representation);
+        this.memberId = memberId;
         this.where = where;
     }
+    
+    protected String getMemberId() {
+        return memberId;
+    }
 
     @Override
     public R with(final ObjectAndMember<T> objectAndMember) {
@@ -79,10 +91,6 @@ public abstract class AbstractObjectMemberReprRenderer<R extends ReprRendererAbs
         this.memberType = MemberType.determineFrom(objectMember);
         usingLinkTo(new DomainObjectLinkTo());
 
-        // done eagerly so can use as criteria for x-ro-follow-links
-        if(!mode.isInline()) {
-            representation.mapPut("id", objectMember.getId());
-        }
         representation.mapPut("memberType", memberType.getName());
 
         return cast(this);
@@ -214,8 +222,12 @@ public abstract class AbstractObjectMemberReprRenderer<R extends ReprRendererAbs
         getLinks().arrayAdd(link);
 
         final LinkFollowSpecs membersLinkFollower = getLinkFollowSpecs();
-        final LinkFollowSpecs detailsLinkFollower = membersLinkFollower.follow("links[rel=%s]", Rel.DETAILS.getName());
-        if (membersLinkFollower.matches(representation) && detailsLinkFollower.matches(link)) {
+        final LinkFollowSpecs detailsLinkFollower = membersLinkFollower.follow("links");
+        
+        // create a temporary map that looks the same as the member map we'll be following
+        final JsonRepresentation memberMap = JsonRepresentation.newMap();
+        memberMap.mapPut(getMemberId(), this.representation);
+        if (membersLinkFollower.matches(memberMap) && detailsLinkFollower.matches(link)) {
             followDetailsLink(link);
         }
         return;

http://git-wip-us.apache.org/repos/asf/isis/blob/cfe2b106/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/DomainObjectReprRenderer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/DomainObjectReprRenderer.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/DomainObjectReprRenderer.java
index ba00775..da3fa24 100644
--- a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/DomainObjectReprRenderer.java
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/DomainObjectReprRenderer.java
@@ -43,7 +43,6 @@ import org.apache.isis.viewer.restfulobjects.rendering.RendererContext;
 import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererAbstract;
 import org.apache.isis.viewer.restfulobjects.rendering.domaintypes.DomainTypeReprRenderer;
 import org.apache.isis.viewer.restfulobjects.rendering.util.OidUtils;
-import org.hamcrest.core.IsSame;
 
 public class DomainObjectReprRenderer extends ReprRendererAbstract<DomainObjectReprRenderer, ObjectAdapter> {
 
@@ -111,8 +110,7 @@ public class DomainObjectReprRenderer extends ReprRendererAbstract<DomainObjectR
         addMediaTypeParams(X_RO_DOMAIN_TYPE, domainTypeHref);
         return this;
     }
-
-
+    
     @Override
     public JsonRepresentation render() {
 
@@ -120,8 +118,7 @@ public class DomainObjectReprRenderer extends ReprRendererAbstract<DomainObjectR
         if (!mode.representsArguments()) {
             if (objectAdapter.representsPersistent()) {
                 if (includesSelf) {
-                    final JsonRepresentation self = linkToBuilder.with(objectAdapter).builder(Rel.SELF).build();
-                    getLinks().arrayAdd(self);
+                    addLinkToSelf();
                 }
                 getExtensions().mapPut("oid", getOidStr());
             }
@@ -147,7 +144,7 @@ public class DomainObjectReprRenderer extends ReprRendererAbstract<DomainObjectR
 
         // described by
         if (mode.includesDescribedBy()) {
-            getLinks().arrayAdd(DomainTypeReprRenderer.newLinkToBuilder(getRendererContext(), Rel.DESCRIBEDBY, objectAdapter.getSpecification()).build());
+            addLinkToDescribedBy();
         }
 
         if (!mode.representsArguments()) {
@@ -164,6 +161,31 @@ public class DomainObjectReprRenderer extends ReprRendererAbstract<DomainObjectR
         return representation;
     }
 
+    private void addLinkToSelf() {
+        final JsonRepresentation link = linkToBuilder.with(objectAdapter).builder(Rel.SELF).build();
+
+        final LinkFollowSpecs linkFollower = getLinkFollowSpecs().follow("links");
+        if (linkFollower.matches(link)) {
+            final DomainObjectReprRenderer renderer = new DomainObjectReprRenderer(getRendererContext(), linkFollower, JsonRepresentation.newMap());
+            renderer.with(objectAdapter);
+            link.mapPut("value", renderer.render());
+        }
+
+        getLinks().arrayAdd(link);
+    }
+
+    private void addLinkToDescribedBy() {
+        final JsonRepresentation link = DomainTypeReprRenderer.newLinkToBuilder(getRendererContext(), Rel.DESCRIBEDBY, objectAdapter.getSpecification()).build();
+
+        final LinkFollowSpecs linkFollower = getLinkFollowSpecs().follow("links");
+        if (linkFollower.matches(link)) {
+            final DomainTypeReprRenderer renderer = new DomainTypeReprRenderer(getRendererContext(), linkFollower, JsonRepresentation.newMap());
+            renderer.with(objectAdapter.getSpecification());
+            link.mapPut("value", renderer.render());
+        }
+        getLinks().arrayAdd(link);
+    }
+
     private String getDomainType() {
         return org.apache.isis.viewer.restfulobjects.rendering.util.OidUtils.getDomainType(objectAdapter);
     }
@@ -202,7 +224,7 @@ public class DomainObjectReprRenderer extends ReprRendererAbstract<DomainObjectR
             if (assoc instanceof OneToOneAssociation) {
                 final OneToOneAssociation property = (OneToOneAssociation) assoc;
 
-                final ObjectPropertyReprRenderer renderer = new ObjectPropertyReprRenderer(getRendererContext(), linkFollower, JsonRepresentation.newMap());
+                final ObjectPropertyReprRenderer renderer = new ObjectPropertyReprRenderer(getRendererContext(), linkFollower, property.getId(), JsonRepresentation.newMap());
 
                 renderer.with(new ObjectAndProperty(objectAdapter, property)).usingLinkTo(linkToBuilder);
 
@@ -220,7 +242,7 @@ public class DomainObjectReprRenderer extends ReprRendererAbstract<DomainObjectR
             if (assoc instanceof OneToManyAssociation) {
                 final OneToManyAssociation collection = (OneToManyAssociation) assoc;
 
-                final ObjectCollectionReprRenderer renderer = new ObjectCollectionReprRenderer(getRendererContext(), linkFollower, JsonRepresentation.newMap());
+                final ObjectCollectionReprRenderer renderer = new ObjectCollectionReprRenderer(getRendererContext(), linkFollower, collection.getId(), JsonRepresentation.newMap());
 
                 renderer.with(new ObjectAndCollection(objectAdapter, collection)).usingLinkTo(linkToBuilder);
 
@@ -230,7 +252,6 @@ public class DomainObjectReprRenderer extends ReprRendererAbstract<DomainObjectR
     }
 
     private void addActions(final ObjectAdapter objectAdapter, final List<ObjectAction> actions, final JsonRepresentation members) {
-        final LinkFollowSpecs linkFollower = getLinkFollowSpecs().follow("members");
         for (final ObjectAction action : actions) {
             final Consent visibility = action.isVisible(getRendererContext().getAuthenticationSession(), objectAdapter, rendererContext.getWhere());
             if (!visibility.isAllowed()) {
@@ -242,8 +263,9 @@ public class DomainObjectReprRenderer extends ReprRendererAbstract<DomainObjectR
                 addActions(objectAdapter, subactions, members);
 
             } else {
-
-                final ObjectActionReprRenderer renderer = new ObjectActionReprRenderer(getRendererContext(), linkFollower, JsonRepresentation.newMap());
+                final LinkFollowSpecs linkFollowSpecs = getLinkFollowSpecs().follow("members["+action.getId()+"]");
+                
+                final ObjectActionReprRenderer renderer = new ObjectActionReprRenderer(getRendererContext(), linkFollowSpecs, action.getId(), JsonRepresentation.newMap());
 
                 renderer.with(new ObjectAndAction(objectAdapter, action)).usingLinkTo(linkToBuilder);
 

http://git-wip-us.apache.org/repos/asf/isis/blob/cfe2b106/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectActionReprRenderer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectActionReprRenderer.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectActionReprRenderer.java
index 7852044..3c147de 100644
--- a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectActionReprRenderer.java
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectActionReprRenderer.java
@@ -37,13 +37,13 @@ import com.google.common.collect.Lists;
 
 public class ObjectActionReprRenderer extends AbstractObjectMemberReprRenderer<ObjectActionReprRenderer, ObjectAction> {
 
-    public ObjectActionReprRenderer(final RendererContext resourceContext, final LinkFollowSpecs linkFollower, final JsonRepresentation representation) {
-        super(resourceContext, linkFollower, RepresentationType.OBJECT_ACTION, representation, Where.OBJECT_FORMS);
+    public ObjectActionReprRenderer(final RendererContext resourceContext, final LinkFollowSpecs linkFollowSpecs, String actionId, final JsonRepresentation representation) {
+        super(resourceContext, linkFollowSpecs, actionId, RepresentationType.OBJECT_ACTION, representation, Where.OBJECT_FORMS);
     }
 
     @Override
     public JsonRepresentation render() {
-        // id and memberType are rendered eagerly
+        // memberType is rendered eagerly
 
         renderMemberContent();
         putDisabledReasonIfDisabled();
@@ -64,7 +64,7 @@ public class ObjectActionReprRenderer extends AbstractObjectMemberReprRenderer<O
      */
     @Override
     protected void followDetailsLink(final JsonRepresentation detailsLink) {
-        final ObjectActionReprRenderer renderer = new ObjectActionReprRenderer(getRendererContext(), getLinkFollowSpecs(), JsonRepresentation.newMap());
+        final ObjectActionReprRenderer renderer = new ObjectActionReprRenderer(getRendererContext(), getLinkFollowSpecs(), null, JsonRepresentation.newMap());
         renderer.with(new ObjectAndAction(objectAdapter, objectMember)).usingLinkTo(linkTo).asFollowed();
         detailsLink.mapPut("value", renderer.render());
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/cfe2b106/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectCollectionReprRenderer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectCollectionReprRenderer.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectCollectionReprRenderer.java
index e3db7c0..4d777b5 100644
--- a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectCollectionReprRenderer.java
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectCollectionReprRenderer.java
@@ -36,8 +36,8 @@ import com.google.common.collect.Lists;
 
 public class ObjectCollectionReprRenderer extends AbstractObjectMemberReprRenderer<ObjectCollectionReprRenderer, OneToManyAssociation> {
 
-    public ObjectCollectionReprRenderer(final RendererContext resourceContext, final LinkFollowSpecs linkFollower, final JsonRepresentation representation) {
-        super(resourceContext, linkFollower, RepresentationType.OBJECT_COLLECTION, representation, Where.PARENTED_TABLES);
+    public ObjectCollectionReprRenderer(final RendererContext resourceContext, final LinkFollowSpecs linkFollower, final String collectionId, final JsonRepresentation representation) {
+        super(resourceContext, linkFollower, collectionId, RepresentationType.OBJECT_COLLECTION, representation, Where.PARENTED_TABLES);
     }
 
     @Override
@@ -88,7 +88,7 @@ public class ObjectCollectionReprRenderer extends AbstractObjectMemberReprRender
      */
     @Override
     protected void followDetailsLink(final JsonRepresentation detailsLink) {
-        final ObjectCollectionReprRenderer renderer = new ObjectCollectionReprRenderer(getRendererContext(), getLinkFollowSpecs(), JsonRepresentation.newMap());
+        final ObjectCollectionReprRenderer renderer = new ObjectCollectionReprRenderer(getRendererContext(), getLinkFollowSpecs(), null, JsonRepresentation.newMap());
         renderer.with(new ObjectAndCollection(objectAdapter, objectMember)).asFollowed();
         detailsLink.mapPut("value", renderer.render());
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/cfe2b106/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectPropertyReprRenderer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectPropertyReprRenderer.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectPropertyReprRenderer.java
index c972610..f04d0ab 100644
--- a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectPropertyReprRenderer.java
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectPropertyReprRenderer.java
@@ -35,8 +35,8 @@ import com.google.common.collect.Lists;
 
 public class ObjectPropertyReprRenderer extends AbstractObjectMemberReprRenderer<ObjectPropertyReprRenderer, OneToOneAssociation> {
 
-    public ObjectPropertyReprRenderer(final RendererContext resourceContext, final LinkFollowSpecs linkFollower, final JsonRepresentation representation) {
-        super(resourceContext, linkFollower, RepresentationType.OBJECT_PROPERTY, representation, Where.OBJECT_FORMS);
+    public ObjectPropertyReprRenderer(final RendererContext resourceContext, final LinkFollowSpecs linkFollower, final String propertyId, final JsonRepresentation representation) {
+        super(resourceContext, linkFollower, propertyId, RepresentationType.OBJECT_PROPERTY, representation, Where.OBJECT_FORMS);
     }
 
     @Override
@@ -84,7 +84,7 @@ public class ObjectPropertyReprRenderer extends AbstractObjectMemberReprRenderer
      */
     @Override
     protected void followDetailsLink(final JsonRepresentation detailsLink) {
-        final ObjectPropertyReprRenderer renderer = new ObjectPropertyReprRenderer(getRendererContext(), getLinkFollowSpecs(), JsonRepresentation.newMap());
+        final ObjectPropertyReprRenderer renderer = new ObjectPropertyReprRenderer(getRendererContext(), getLinkFollowSpecs(), null, JsonRepresentation.newMap());
         renderer.with(new ObjectAndProperty(objectAdapter, objectMember)).asFollowed();
         detailsLink.mapPut("value", renderer.render());
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/cfe2b106/component/viewer/restfulobjects/rendering/src/test/java/org/apache/isis/viewer/restfulobjects/rendering/LinkFollowSpecsTest_follow.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/test/java/org/apache/isis/viewer/restfulobjects/rendering/LinkFollowSpecsTest_follow.java b/component/viewer/restfulobjects/rendering/src/test/java/org/apache/isis/viewer/restfulobjects/rendering/LinkFollowSpecsTest_follow.java
index 3ad5e90..e6f3429 100644
--- a/component/viewer/restfulobjects/rendering/src/test/java/org/apache/isis/viewer/restfulobjects/rendering/LinkFollowSpecsTest_follow.java
+++ b/component/viewer/restfulobjects/rendering/src/test/java/org/apache/isis/viewer/restfulobjects/rendering/LinkFollowSpecsTest_follow.java
@@ -68,7 +68,7 @@ public class LinkFollowSpecsTest_follow {
     }
 
     @Test
-    public void follow_withSingleCriteria() throws Exception {
+    public void follow_withSingleListCriteria() throws Exception {
         final List<List<String>> links = asListOfLists("a[x=y].b.c");
 
         final LinkFollowSpecs linkFollower = LinkFollowSpecs.create(links);
@@ -84,6 +84,23 @@ public class LinkFollowSpecsTest_follow {
     }
 
     @Test
+    public void follow_withSingleMapCriteria() throws Exception {
+        final List<List<String>> links = asListOfLists("a[x].b.c");
+
+        final LinkFollowSpecs linkFollower = LinkFollowSpecs.create(links);
+
+        assertThat(linkFollower.follow("x").isFollowing(), is(false));
+
+        final LinkFollowSpecs followA = linkFollower.follow("a");
+
+        assertThat(followA.isFollowing(), is(true));
+        assertThat(followA.matches(JsonRepresentation.newMap("x", "y")), is(true));
+        assertThat(followA.matches(JsonRepresentation.newMap("x", "z")), is(true));
+        assertThat(followA.matches(JsonRepresentation.newMap()), is(false));
+        assertThat(followA.matches(JsonRepresentation.newMap("p", "z")), is(false));
+    }
+
+    @Test
     public void follow_withMultipleCriteria() throws Exception {
         final List<List<String>> links = asListOfLists("a[x=y z=w].b.c");
 

http://git-wip-us.apache.org/repos/asf/isis/blob/cfe2b106/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainResourceHelper.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainResourceHelper.java b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainResourceHelper.java
index ff95fcf..9fcbb3a 100644
--- a/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainResourceHelper.java
+++ b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainResourceHelper.java
@@ -185,7 +185,7 @@ public final class DomainResourceHelper {
 
         final OneToOneAssociation property = getPropertyThatIsVisibleAndUsable(propertyId, Intent.ACCESS, where);
 
-        final ObjectPropertyReprRenderer renderer = new ObjectPropertyReprRenderer(resourceContext, null, JsonRepresentation.newMap());
+        final ObjectPropertyReprRenderer renderer = new ObjectPropertyReprRenderer(resourceContext, null, null, JsonRepresentation.newMap());
 
         renderer.with(new ObjectAndProperty(objectAdapter, property)).usingLinkTo(adapterLinkTo);
 
@@ -202,7 +202,7 @@ public final class DomainResourceHelper {
 
         final OneToManyAssociation collection = getCollectionThatIsVisibleAndUsable(collectionId, Intent.ACCESS, where);
 
-        final ObjectCollectionReprRenderer renderer = new ObjectCollectionReprRenderer(resourceContext, null, JsonRepresentation.newMap());
+        final ObjectCollectionReprRenderer renderer = new ObjectCollectionReprRenderer(resourceContext, null, null, JsonRepresentation.newMap());
 
         renderer.with(new ObjectAndCollection(objectAdapter, collection)).usingLinkTo(adapterLinkTo);
 
@@ -218,7 +218,7 @@ public final class DomainResourceHelper {
     Response actionPrompt(final String actionId, Where where) {
         final ObjectAction action = getObjectActionThatIsVisibleAndUsable(actionId, Intent.ACCESS, where);
 
-        final ObjectActionReprRenderer renderer = new ObjectActionReprRenderer(resourceContext, null, JsonRepresentation.newMap());
+        final ObjectActionReprRenderer renderer = new ObjectActionReprRenderer(resourceContext, null, null, JsonRepresentation.newMap());
 
         renderer.with(new ObjectAndAction(objectAdapter, action)).usingLinkTo(adapterLinkTo).asStandalone();
 

http://git-wip-us.apache.org/repos/asf/isis/blob/cfe2b106/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainServiceResourceServerside.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainServiceResourceServerside.java b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainServiceResourceServerside.java
index f9e4e47..86156ef 100644
--- a/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainServiceResourceServerside.java
+++ b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainServiceResourceServerside.java
@@ -76,7 +76,9 @@ public class DomainServiceResourceServerside extends ResourceAbstract implements
         final ObjectAdapter serviceAdapter = getServiceAdapter(serviceId);
 
         final DomainObjectReprRenderer renderer = new DomainObjectReprRenderer(getResourceContext(), null, JsonRepresentation.newMap());
-        renderer.usingLinkToBuilder(new DomainServiceLinkTo()).with(serviceAdapter).includesSelf();
+        renderer.usingLinkToBuilder(new DomainServiceLinkTo())
+            .with(serviceAdapter)
+            .includesSelf();
 
         return responseOfOk(renderer, Caching.ONE_DAY).build();
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/cfe2b106/component/viewer/restfulobjects/tck/ide/eclipse/launch/viewer-json-tck.launch
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/tck/ide/eclipse/launch/viewer-json-tck.launch b/component/viewer/restfulobjects/tck/ide/eclipse/launch/viewer-json-tck.launch
index eacbe85..53bd401 100644
--- a/component/viewer/restfulobjects/tck/ide/eclipse/launch/viewer-json-tck.launch
+++ b/component/viewer/restfulobjects/tck/ide/eclipse/launch/viewer-json-tck.launch
@@ -14,6 +14,6 @@
 <booleanAttribute key="org.eclipse.jdt.debug.ui.INCLUDE_EXTERNAL_JARS" value="true"/>
 <stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.m2e.launchconfig.classpathProvider"/>
 <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.apache.isis.WebServer"/>
-<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.apache.isis.viewer.json-tck"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="isis-viewer-restfulobjects-tck"/>
 <stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.m2e.launchconfig.sourcepathProvider"/>
 </launchConfiguration>

http://git-wip-us.apache.org/repos/asf/isis/blob/cfe2b106/component/viewer/restfulobjects/tck/src/main/webapp/WEB-INF/isis.properties
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/tck/src/main/webapp/WEB-INF/isis.properties b/component/viewer/restfulobjects/tck/src/main/webapp/WEB-INF/isis.properties
index 4bd7fbb..03b05ca 100644
--- a/component/viewer/restfulobjects/tck/src/main/webapp/WEB-INF/isis.properties
+++ b/component/viewer/restfulobjects/tck/src/main/webapp/WEB-INF/isis.properties
@@ -15,13 +15,11 @@
 #  specific language governing permissions and limitations
 #  under the License.
 
-isis.persistor=in-memory
-
 isis.authentication=bypass
 isis.authorization=bypass
 
 isis.user-profile-store=in-memory
-
+isis.persistor=in-memory
 
 isis.services.prefix = org.apache.isis.core.tck.dom
 isis.services =\
@@ -40,7 +38,8 @@ isis.services =\
     refs.UnidirReferencedEntityRepository,\
     refs.UnidirReferencingEntityRepository,\
     defaults.WithDefaultsEntityRepository,\
-    defaults.HiddenRepository
+    defaults.HiddenRepository,\
+    busrules.BusRulesEntityRepository
 
 
 isis.fixtures.prefix= org.apache.isis.core.tck.fixture
@@ -51,7 +50,7 @@ isis.fixtures=\
     scalars.PrimitiveValuedEntityFixture,\
     scalars.WrapperValuedEntityFixture,\
     refs.ParentEntitiesFixture,\
-    defaults.WithDefaultsEntityFixture
-
+    defaults.WithDefaultsEntityFixture,\
+    busrules.BusRulesEntityFixture
 
 

http://git-wip-us.apache.org/repos/asf/isis/blob/cfe2b106/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainservice/serviceId/DomainServiceTest_req_queryarg_xrofollowlinks.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainservice/serviceId/DomainServiceTest_req_queryarg_xrofollowlinks.java b/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainservice/serviceId/DomainServiceTest_req_queryarg_xrofollowlinks.java
index 8aabfcf..7e655d7 100644
--- a/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainservice/serviceId/DomainServiceTest_req_queryarg_xrofollowlinks.java
+++ b/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainservice/serviceId/DomainServiceTest_req_queryarg_xrofollowlinks.java
@@ -18,7 +18,7 @@
  */
 package org.apache.isis.viewer.restfulobjects.tck.domainservice.serviceId;
 
-import static org.apache.isis.viewer.restfulobjects.tck.RepresentationMatchers.isArray;
+import static org.apache.isis.viewer.restfulobjects.tck.RepresentationMatchers.isMap;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.CoreMatchers.nullValue;
@@ -37,6 +37,7 @@ import org.junit.Test;
 
 import org.apache.isis.core.webserver.WebServer;
 import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.Rel;
 import org.apache.isis.viewer.restfulobjects.applib.RestfulHttpMethod;
 import org.apache.isis.viewer.restfulobjects.applib.client.RestfulClient;
 import org.apache.isis.viewer.restfulobjects.applib.client.RestfulRequest;
@@ -47,6 +48,7 @@ import org.apache.isis.viewer.restfulobjects.applib.domainobjects.DomainObjectRe
 import org.apache.isis.viewer.restfulobjects.applib.domainobjects.DomainServiceResource;
 import org.apache.isis.viewer.restfulobjects.applib.domainobjects.ListRepresentation;
 import org.apache.isis.viewer.restfulobjects.tck.IsisWebServerRule;
+import static org.apache.isis.viewer.restfulobjects.tck.RepresentationMatchers.*;
 
 public class DomainServiceTest_req_queryarg_xrofollowlinks {
 
@@ -61,51 +63,107 @@ public class DomainServiceTest_req_queryarg_xrofollowlinks {
         client = new RestfulClient(webServer.getBase());
     }
 
-    @Ignore("todo... the service Id is wrong")
     @Test
-    public void withCriteria() throws Exception {
+    public void self() throws Exception {
+        final String href = givenHrefToService("WrapperValuedEntities");
 
-        final String href = givenHrefToService("simples");
+        final RestfulRequest request = client.createRequest(RestfulHttpMethod.GET, href).withArg(RequestParameter.FOLLOW_LINKS, "links[rel=self]");
+        final RestfulResponse<DomainObjectRepresentation> restfulResponse = request.executeT();
 
-        final RestfulRequest request = client.createRequest(RestfulHttpMethod.GET, href).withArg(RequestParameter.FOLLOW_LINKS, "members[id=%s].links[rel=details]", "list");
+        assertThat(restfulResponse.getStatus(), is(HttpStatusCode.OK));
+        final DomainObjectRepresentation repr = restfulResponse.getEntity();
+        
+        assertThat(repr.getSelf().getValue(), is(not(nullValue())));
+    }
+
+    @Test
+    public void toDescribedBy() throws Exception {
+        final String href = givenHrefToService("WrapperValuedEntities");
+
+        final RestfulRequest request = client.createRequest(RestfulHttpMethod.GET, href).withArg(RequestParameter.FOLLOW_LINKS, "links[rel=describedby]");
+        final RestfulResponse<DomainObjectRepresentation> restfulResponse = request.executeT();
+
+        assertThat(restfulResponse.getStatus(), is(HttpStatusCode.OK));
+        final DomainObjectRepresentation repr = restfulResponse.getEntity();
+        
+        assertThat(repr.getLinkWithRel(Rel.DESCRIBEDBY).getValue(), is(not(nullValue())));
+    }
+
+    @Test
+    public void toMembers() throws Exception {
+        final String href = givenHrefToService("WrapperValuedEntities");
+
+        final RestfulRequest request = client.createRequest(RestfulHttpMethod.GET, href).withArg(RequestParameter.FOLLOW_LINKS, "members.links[rel=%s]", Rel.DETAILS.getName());
         final RestfulResponse<DomainObjectRepresentation> restfulResponse = request.executeT();
 
         assertThat(restfulResponse.getStatus(), is(HttpStatusCode.OK));
         final DomainObjectRepresentation repr = restfulResponse.getEntity();
 
         final JsonRepresentation membersList = repr.getMembers();
-        assertThat(membersList, isArray());
+        assertThat(membersList, isMap());
 
         JsonRepresentation actionRepr;
 
-        actionRepr = membersList.getRepresentation("[id=%s]", "list");
-        assertThat(actionRepr.getRepresentation("links[rel=details]"), is(not(nullValue())));
-        assertThat(actionRepr.getRepresentation("links[rel=details].value"), is(not(nullValue()))); // followed
+        actionRepr = membersList.getRepresentation("list");
+        assertThat(actionRepr.getRepresentation("links[rel="+Rel.DETAILS.getName()+"]"), is(not(nullValue())));
+        assertThat(actionRepr.getRepresentation("links[rel="+Rel.DETAILS.getName()+"].value"), is(not(nullValue()))); // followed
 
-        actionRepr = membersList.getRepresentation("[id=%s]", "newTransientEntity");
-        assertThat(actionRepr.getRepresentation("links[rel=details]"), is(not(nullValue())));
-        assertThat(actionRepr.getRepresentation("links[rel=details].value"), is(nullValue())); // not
-                                                                                               // followed
+        actionRepr = membersList.getRepresentation("newEntity");
+        assertThat(actionRepr.getRepresentation("links[rel="+Rel.DETAILS.getName()+"]"), is(not(nullValue())));
+        assertThat(actionRepr.getRepresentation("links[rel="+Rel.DETAILS.getName()+"].value"), is(not(nullValue()))); // also followed
     }
 
-    @Ignore("todo")
     @Test
-    public void toSelf() throws Exception {
-    
-    }
+    public void singleMember_specified_by_criteria() throws Exception {
 
-    @Ignore("todo")
-    @Test
-    public void toDescribedBy() throws Exception {
-    
+        final String href = givenHrefToService("WrapperValuedEntities");
+
+        final RestfulRequest request = client.createRequest(RestfulHttpMethod.GET, href).withArg(RequestParameter.FOLLOW_LINKS, "members[%s].links[rel=%s]", "list", Rel.DETAILS.getName());
+        final RestfulResponse<DomainObjectRepresentation> restfulResponse = request.executeT();
+
+        assertThat(restfulResponse.getStatus(), is(HttpStatusCode.OK));
+        final DomainObjectRepresentation repr = restfulResponse.getEntity();
+
+        final JsonRepresentation membersList = repr.getMembers();
+        assertThat(membersList, isMap());
+
+        JsonRepresentation actionRepr;
+
+        actionRepr = membersList.getRepresentation("list");
+        assertThat(actionRepr.getRepresentation("links[rel="+Rel.DETAILS.getName()+"]"), is(not(nullValue())));
+        assertThat(actionRepr.getRepresentation("links[rel="+Rel.DETAILS.getName()+"].value"), is(not(nullValue()))); // followed
+
+        actionRepr = membersList.getRepresentation("newEntity");
+        assertThat(actionRepr.getRepresentation("links[rel="+Rel.DETAILS.getName()+"]"), is(not(nullValue())));
+        assertThat(actionRepr.getRepresentation("links[rel="+Rel.DETAILS.getName()+"].value"), is(nullValue())); // not followed
     }
 
-    @Ignore("todo")
     @Test
-    public void toMembers() throws Exception {
-    
-        // no need to do an individual member, that's been tested already elsewhere
+    public void multipleMembers() throws Exception {
+
+        final String href = givenHrefToService("WrapperValuedEntities");
+
+        final RestfulRequest request = client.createRequest(RestfulHttpMethod.GET, href).withArg(RequestParameter.FOLLOW_LINKS, "members[%s].links[rel=%s],members[%s].links[rel=%s]", "list", Rel.DETAILS.getName(), "newEntity", Rel.DETAILS.getName());
+        final RestfulResponse<DomainObjectRepresentation> restfulResponse = request.executeT();
+
+        assertThat(restfulResponse.getStatus(), is(HttpStatusCode.OK));
+        final DomainObjectRepresentation repr = restfulResponse.getEntity();
+
+        final JsonRepresentation membersList = repr.getMembers();
+        assertThat(membersList, isMap());
+
+        JsonRepresentation actionRepr;
+
+        actionRepr = membersList.getRepresentation("list");
+        assertThat(actionRepr.getRepresentation("links[rel="+Rel.DETAILS.getName()+"]"), is(not(nullValue())));
+        assertThat(actionRepr.getRepresentation("links[rel="+Rel.DETAILS.getName()+"].value"), is(not(nullValue()))); // followed
+
+        actionRepr = membersList.getRepresentation("newEntity");
+        assertThat(actionRepr.getRepresentation("links[rel="+Rel.DETAILS.getName()+"]"), is(not(nullValue())));
+        assertThat(actionRepr.getRepresentation("links[rel="+Rel.DETAILS.getName()+"].value"), is(not(nullValue()))); // also followed
     }
+    
+
 
     
     private String givenHrefToService(final String serviceId) throws JsonParseException, JsonMappingException, IOException {
@@ -113,7 +171,7 @@ public class DomainServiceTest_req_queryarg_xrofollowlinks {
         final Response response = resource.services();
         final ListRepresentation services = RestfulResponse.<ListRepresentation> ofT(response).getEntity();
 
-        return services.getRepresentation("values[id=%s]", serviceId).asLink().getHref();
+        return services.getRepresentation("value[rel=urn:org.restfulobjects:rels/service;serviceId=\"%s\"]", serviceId).asLink().getHref();
     }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/cfe2b106/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainservice/serviceId/DomainServiceTest_resp_representation.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainservice/serviceId/DomainServiceTest_resp_representation.java b/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainservice/serviceId/DomainServiceTest_resp_representation.java
index b988766..a58cfe4 100644
--- a/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainservice/serviceId/DomainServiceTest_resp_representation.java
+++ b/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainservice/serviceId/DomainServiceTest_resp_representation.java
@@ -23,13 +23,13 @@ import static org.apache.isis.viewer.restfulobjects.tck.RepresentationMatchers.a
 import static org.apache.isis.viewer.restfulobjects.tck.RepresentationMatchers.isArray;
 import static org.apache.isis.viewer.restfulobjects.tck.RepresentationMatchers.isLink;
 import static org.apache.isis.viewer.restfulobjects.tck.RepresentationMatchers.isMap;
-import static org.hamcrest.CoreMatchers.*;
+import static org.hamcrest.CoreMatchers.endsWith;
 import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
 import static org.junit.Assert.assertThat;
 
 import javax.ws.rs.core.Response;
 
-import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
 import org.apache.isis.viewer.restfulobjects.applib.LinkRepresentation;
 import org.apache.isis.viewer.restfulobjects.applib.Rel;
 import org.apache.isis.viewer.restfulobjects.applib.RestfulHttpMethod;

http://git-wip-us.apache.org/repos/asf/isis/blob/cfe2b106/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/busrules/BusRulesEntity.java
----------------------------------------------------------------------
diff --git a/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/busrules/BusRulesEntity.java b/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/busrules/BusRulesEntity.java
new file mode 100644
index 0000000..447ddfb
--- /dev/null
+++ b/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/busrules/BusRulesEntity.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.core.tck.dom.busrules;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.isis.applib.AbstractDomainObject;
+import org.apache.isis.applib.annotation.ActionSemantics;
+import org.apache.isis.applib.annotation.Disabled;
+import org.apache.isis.applib.annotation.Hidden;
+import org.apache.isis.applib.annotation.MemberOrder;
+import org.apache.isis.applib.annotation.ObjectType;
+import org.apache.isis.applib.annotation.ActionSemantics.Of;
+
+@javax.jdo.annotations.PersistenceCapable
+@javax.jdo.annotations.Discriminator("BSRL")
+@javax.jdo.annotations.Query(
+        name="prmv_findByIntProperty", language="JDOQL",  
+        value="SELECT FROM org.apache.isis.tck.dom.busrules.BusRulesEntity WHERE intProperty == :i")
+@ObjectType("BSRL")
+public class BusRulesEntity extends AbstractDomainObject {
+
+    // {{ Id (Integer)
+    private Integer id;
+
+    @javax.jdo.annotations.PrimaryKey // must be on the getter.
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(final Integer id) {
+        this.id = id;
+    }
+    // }}
+
+    // {{ Title
+    public String title() {
+        return null;
+    }
+    // }}
+
+
+    // {{ visibleAndEditableProperty
+    private int visibleAndEditableProperty;
+
+    @MemberOrder(sequence = "1")
+    public int getVisibleAndEditableProperty() {
+        return visibleAndEditableProperty;
+    }
+
+    public void setVisibleAndEditableProperty(final int intProperty) {
+        this.visibleAndEditableProperty = intProperty;
+    }
+    // }}
+
+
+    // {{ visibleButNotEditableProperty
+    private int visibleButNotEditableProperty;
+
+    @Disabled
+    @MemberOrder(sequence = "2")
+    public int getVisibleButNotEditableProperty() {
+        return visibleButNotEditableProperty;
+    }
+
+    public void setVisibleButNotEditableProperty(final int intProperty) {
+        this.visibleButNotEditableProperty = intProperty;
+    }
+    // }}
+
+    // {{ invisibleProperty
+    private int invisibleProperty;
+
+    @Hidden
+    @MemberOrder(sequence = "3")
+    public int getInvisibleProperty() {
+        return invisibleProperty;
+    }
+
+    public void setInvisibleProperty(final int intProperty) {
+        this.invisibleProperty = intProperty;
+    }
+    // }}
+
+    
+    // {{ VisibleAndEditableCollection (Collection)
+    private List<BusRulesEntityChild> editableCollection = new ArrayList<BusRulesEntityChild>();
+
+    @MemberOrder(sequence = "11")
+    public List<BusRulesEntityChild> getVisibleAndEditableCollection() {
+        return editableCollection;
+    }
+
+    public void setVisibleAndEditableCollection(final List<BusRulesEntityChild> children) {
+        this.editableCollection = children;
+    }
+    // }}
+
+    
+    // {{ VisibleButNotEditableCollection (Collection)
+    private List<BusRulesEntityChild> notEditableCollection = new ArrayList<BusRulesEntityChild>();
+
+    @MemberOrder(sequence = "11")
+    public List<BusRulesEntityChild> getVisibleButNotEditableCollection() {
+        return notEditableCollection;
+    }
+
+    public void setVisibleButNotEditableCollection(final List<BusRulesEntityChild> children) {
+        this.notEditableCollection = children;
+    }
+    // }}
+
+    // {{ InvisibleCollection (Collection)
+    private List<BusRulesEntityChild> invisibleCollection = new ArrayList<BusRulesEntityChild>();
+
+    @MemberOrder(sequence = "11")
+    public List<BusRulesEntityChild> getInvisibleCollection() {
+        return invisibleCollection;
+    }
+
+    public void setInvisibleCollection(final List<BusRulesEntityChild> children) {
+        this.invisibleCollection = children;
+    }
+    // }}
+
+    @ActionSemantics(Of.SAFE)
+    @MemberOrder(sequence = "1")
+    public BusRulesEntity visibleAndInvokableAction() {
+        return this;
+    }
+
+    @Disabled
+    @ActionSemantics(Of.SAFE)
+    @MemberOrder(sequence = "1")
+    public BusRulesEntity visibleButUninvokableAction() {
+        return this;
+    }
+
+    @Hidden
+    @ActionSemantics(Of.SAFE)
+    @MemberOrder(sequence = "1")
+    public BusRulesEntity invisibleAction() {
+        return this;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cfe2b106/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/busrules/BusRulesEntityChild.java
----------------------------------------------------------------------
diff --git a/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/busrules/BusRulesEntityChild.java b/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/busrules/BusRulesEntityChild.java
new file mode 100644
index 0000000..5011c23
--- /dev/null
+++ b/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/busrules/BusRulesEntityChild.java
@@ -0,0 +1,55 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.tck.dom.busrules;
+
+import org.apache.isis.applib.AbstractDomainObject;
+import org.apache.isis.applib.annotation.ObjectType;
+
+@javax.jdo.annotations.PersistenceCapable
+@javax.jdo.annotations.Discriminator("BSRC")
+@javax.jdo.annotations.Query(
+        name="prmv_findByIntProperty", language="JDOQL",  
+        value="SELECT FROM org.apache.isis.tck.dom.busrules.BusRulesEntityChild WHERE intProperty == :i")
+@ObjectType("BSRC")
+public class BusRulesEntityChild extends AbstractDomainObject {
+
+
+    // {{ Id (Integer)
+    private Integer id;
+
+    @javax.jdo.annotations.PrimaryKey // must be on the getter.
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(final Integer id) {
+        this.id = id;
+    }
+    // }}
+
+    // {{ Title
+    public String title() {
+        return null;
+    }
+    // }}
+
+
+    
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cfe2b106/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/busrules/BusRulesEntityRepository.java
----------------------------------------------------------------------
diff --git a/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/busrules/BusRulesEntityRepository.java b/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/busrules/BusRulesEntityRepository.java
new file mode 100644
index 0000000..cc1a814
--- /dev/null
+++ b/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/busrules/BusRulesEntityRepository.java
@@ -0,0 +1,72 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.tck.dom.busrules;
+
+import org.apache.isis.applib.annotation.ActionSemantics;
+import org.apache.isis.applib.annotation.ActionSemantics.Of;
+import org.apache.isis.applib.annotation.Disabled;
+import org.apache.isis.applib.annotation.Hidden;
+import org.apache.isis.applib.annotation.MemberOrder;
+import org.apache.isis.applib.annotation.Named;
+import org.apache.isis.applib.annotation.ObjectType;
+import org.apache.isis.applib.query.Query;
+import org.apache.isis.applib.query.QueryDefault;
+import org.apache.isis.core.tck.dom.AbstractEntityRepository;
+
+@Named("BusinessRulesEntities")
+@ObjectType("BusinessRulesEntities")
+public class BusRulesEntityRepository extends AbstractEntityRepository<BusRulesEntity> {
+
+    public BusRulesEntityRepository() {
+        super(BusRulesEntity.class, "BusinessRulesEntities");
+    }
+
+    @ActionSemantics(Of.SAFE)
+    @MemberOrder(sequence = "1")
+    public BusRulesEntity findById(int id) {
+        final Query<BusRulesEntity> query = 
+                new QueryDefault<BusRulesEntity>(BusRulesEntity.class, BusRulesEntity.class.getName() + "#pk", "id", id);
+        return this.firstMatch(query);
+    }
+
+
+    @ActionSemantics(Of.SAFE)
+    @MemberOrder(sequence = "1")
+    public BusRulesEntity visibleAndInvokableAction(int id) {
+        return this.findById(id);
+    }
+
+    @Disabled
+    @ActionSemantics(Of.SAFE)
+    @MemberOrder(sequence = "1")
+    public BusRulesEntity visibleButUninvokableAction(int id) {
+        return this.findById(id);
+    }
+
+    @Hidden
+    @ActionSemantics(Of.SAFE)
+    @MemberOrder(sequence = "1")
+    public BusRulesEntity invisibleAction(int id) {
+        return this.findById(id);
+    }
+
+    
+    
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cfe2b106/core/tck/tck-fixture/src/main/java/org/apache/isis/core/tck/fixture/busrules/BusRulesEntityFixture.java
----------------------------------------------------------------------
diff --git a/core/tck/tck-fixture/src/main/java/org/apache/isis/core/tck/fixture/busrules/BusRulesEntityFixture.java b/core/tck/tck-fixture/src/main/java/org/apache/isis/core/tck/fixture/busrules/BusRulesEntityFixture.java
new file mode 100644
index 0000000..e31578e
--- /dev/null
+++ b/core/tck/tck-fixture/src/main/java/org/apache/isis/core/tck/fixture/busrules/BusRulesEntityFixture.java
@@ -0,0 +1,50 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.core.tck.fixture.busrules;
+
+import org.apache.isis.applib.fixtures.AbstractFixture;
+import org.apache.isis.core.tck.dom.busrules.BusRulesEntity;
+import org.apache.isis.core.tck.dom.busrules.BusRulesEntityRepository;
+
+public class BusRulesEntityFixture extends AbstractFixture {
+
+    @Override
+    public void install() {
+        createEntity(1);
+        createEntity(2);
+        createEntity(3);
+        createEntity(4);
+        createEntity(5);
+    }
+
+    private BusRulesEntity createEntity(Integer id) {
+        final BusRulesEntity entity = repository.newEntity();
+        entity.setId(id);
+        return entity;
+    }
+
+    // {{ injected: WithDefaultsEntityRepository
+    private BusRulesEntityRepository repository;
+
+    public void setBusRulesEntityRepository(final BusRulesEntityRepository repository) {
+        this.repository = repository;
+    }
+    // }}
+
+}