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 2014/10/28 17:16:19 UTC

[16/56] [abbrv] ISIS-937: moved TCK out of core.

http://git-wip-us.apache.org/repos/asf/isis/blob/21e2882a/tck/tck-integtests/src/test/java/org/apache/isis/objectstore/jdo/datanucleus/scenarios/scalar/Persistence_namedQuery_firstOnly.java
----------------------------------------------------------------------
diff --git a/tck/tck-integtests/src/test/java/org/apache/isis/objectstore/jdo/datanucleus/scenarios/scalar/Persistence_namedQuery_firstOnly.java b/tck/tck-integtests/src/test/java/org/apache/isis/objectstore/jdo/datanucleus/scenarios/scalar/Persistence_namedQuery_firstOnly.java
new file mode 100644
index 0000000..15fdcd7
--- /dev/null
+++ b/tck/tck-integtests/src/test/java/org/apache/isis/objectstore/jdo/datanucleus/scenarios/scalar/Persistence_namedQuery_firstOnly.java
@@ -0,0 +1,112 @@
+/*
+ *  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.objectstore.jdo.datanucleus.scenarios.scalar;
+
+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 com.google.common.collect.ImmutableMap;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.apache.isis.core.integtestsupport.IsisSystemWithFixtures;
+import org.apache.isis.core.tck.dom.scalars.PrimitiveValuedEntity;
+import org.apache.isis.core.tck.dom.scalars.PrimitiveValuedEntityRepository;
+import org.apache.isis.objectstore.jdo.datanucleus.Utils;
+
+public class Persistence_namedQuery_firstOnly {
+
+    private PrimitiveValuedEntityRepository repo = new PrimitiveValuedEntityRepository();
+    
+    @Rule
+    public IsisSystemWithFixtures iswf = Utils.systemBuilder()
+        .with(Utils.listenerToDeleteFrom("PRIMITIVEVALUEDENTITY"))
+        .withServices(repo)
+        .build();
+
+    @Before
+    public void setUp() throws Exception {
+
+        iswf.beginTran();
+
+        PrimitiveValuedEntity entity = repo.newEntity();
+        entity.setId(1);
+        entity.setIntProperty(111);
+
+        entity = repo.newEntity();
+        entity.setId(2);
+        entity.setIntProperty(222);
+
+        entity = repo.newEntity();
+        entity.setId(3);
+        entity.setIntProperty(333);
+
+        entity = repo.newEntity();
+        entity.setId(4);
+        entity.setIntProperty(111);
+
+        iswf.commitTran();
+
+    }
+    
+    @Test
+    public void whenOne() throws Exception {
+        
+        PrimitiveValuedEntity entity;
+        
+        iswf.beginTran();
+
+        entity = repo.findByNamedQueryFirstOnly("prmv_findByIntProperty", ImmutableMap.of("i", (Object)222));
+        assertThat(entity, is(not(nullValue())));
+        assertThat(entity.getId(), is(2));
+
+        iswf.commitTran();
+    }
+
+    @Test
+    public void whenTwo() throws Exception {
+        
+        PrimitiveValuedEntity entity;
+        
+        iswf.beginTran();
+
+        entity = repo.findByNamedQueryFirstOnly("prmv_findByIntProperty", ImmutableMap.of("i", (Object)111));
+        assertThat(entity, is(not(nullValue())));
+        assertThat(entity.getId(), is(1));
+
+        iswf.commitTran();
+    }
+
+    @Test
+    public void whenNone() throws Exception {
+        
+        PrimitiveValuedEntity entity;
+        
+        iswf.beginTran();
+
+        entity = repo.findByNamedQueryFirstOnly("prmv_findByIntProperty", ImmutableMap.of("i", (Object)999));
+        assertThat(entity, is(nullValue()));
+
+        iswf.commitTran();
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/21e2882a/tck/tck-integtests/src/test/java/org/apache/isis/objectstore/jdo/datanucleus/scenarios/scalar/Persistence_persistAndUpdate_applibValuedEntity.java
----------------------------------------------------------------------
diff --git a/tck/tck-integtests/src/test/java/org/apache/isis/objectstore/jdo/datanucleus/scenarios/scalar/Persistence_persistAndUpdate_applibValuedEntity.java b/tck/tck-integtests/src/test/java/org/apache/isis/objectstore/jdo/datanucleus/scenarios/scalar/Persistence_persistAndUpdate_applibValuedEntity.java
new file mode 100644
index 0000000..4b27d8d
--- /dev/null
+++ b/tck/tck-integtests/src/test/java/org/apache/isis/objectstore/jdo/datanucleus/scenarios/scalar/Persistence_persistAndUpdate_applibValuedEntity.java
@@ -0,0 +1,92 @@
+/*
+ *  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.objectstore.jdo.datanucleus.scenarios.scalar;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.util.List;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.apache.isis.applib.value.Date;
+import org.apache.isis.core.integtestsupport.IsisSystemWithFixtures;
+import org.apache.isis.core.tck.dom.scalars.ApplibValuedEntity;
+import org.apache.isis.core.tck.dom.scalars.ApplibValuedEntityRepository;
+import org.apache.isis.objectstore.jdo.datanucleus.Utils;
+
+public class Persistence_persistAndUpdate_applibValuedEntity {
+
+    private ApplibValuedEntityRepository repo = new ApplibValuedEntityRepository();
+    
+    @Rule
+    public IsisSystemWithFixtures iswf = Utils.systemBuilder()
+        .with(Utils.listenerToDeleteFrom("APPLIBVALUEDENTITY"))
+        .withServices(repo)
+        .build();
+
+    @Test
+    public void persistTwo() throws Exception {
+        iswf.beginTran();
+        repo.newEntity().setStringProperty("1");
+        repo.newEntity().setStringProperty("2");
+        iswf.commitTran();
+
+        iswf.bounceSystem();
+        
+        iswf.beginTran();
+        List<ApplibValuedEntity> list = repo.list();
+        assertThat(list.size(), is(2));
+        iswf.commitTran();
+    }
+
+    @Test
+    public void persist_then_update() throws Exception {
+        iswf.beginTran();
+        
+        ApplibValuedEntity entity = repo.newEntity();
+        entity.setStringProperty("1");
+
+        Date date = new Date();
+        entity.setDateProperty(date);
+        
+        iswf.commitTran();
+
+        iswf.bounceSystem();
+        
+        iswf.beginTran();
+        entity = repo.list().get(0);
+        assertThat(entity.getDateProperty().dateValue(), is(date.dateValue()));
+        
+        date = date.add(-1, -1, -1);
+        entity.setDateProperty(date);
+        
+        iswf.commitTran();
+
+        iswf.bounceSystem();
+        
+        iswf.beginTran();
+        entity = repo.list().get(0);
+        assertThat(entity.getDateProperty().dateValue(), is(date.dateValue()));
+        
+        iswf.commitTran();
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/21e2882a/tck/tck-integtests/src/test/java/org/apache/isis/objectstore/jdo/datanucleus/scenarios/scalar/Persistence_persistAndUpdate_jdkValuedEntity.java
----------------------------------------------------------------------
diff --git a/tck/tck-integtests/src/test/java/org/apache/isis/objectstore/jdo/datanucleus/scenarios/scalar/Persistence_persistAndUpdate_jdkValuedEntity.java b/tck/tck-integtests/src/test/java/org/apache/isis/objectstore/jdo/datanucleus/scenarios/scalar/Persistence_persistAndUpdate_jdkValuedEntity.java
new file mode 100644
index 0000000..b74224e
--- /dev/null
+++ b/tck/tck-integtests/src/test/java/org/apache/isis/objectstore/jdo/datanucleus/scenarios/scalar/Persistence_persistAndUpdate_jdkValuedEntity.java
@@ -0,0 +1,117 @@
+/*
+ *  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.objectstore.jdo.datanucleus.scenarios.scalar;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.sql.Timestamp;
+import java.util.List;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.apache.isis.core.integtestsupport.IsisSystemWithFixtures;
+import org.apache.isis.core.tck.dom.scalars.JdkValuedEntity;
+import org.apache.isis.core.tck.dom.scalars.JdkValuedEntityRepository;
+import org.apache.isis.core.tck.dom.scalars.MyEnum;
+import org.apache.isis.objectstore.jdo.datanucleus.Utils;
+
+public class Persistence_persistAndUpdate_jdkValuedEntity {
+
+    private JdkValuedEntityRepository repo = new JdkValuedEntityRepository();
+    
+    @Rule
+    public IsisSystemWithFixtures iswf = Utils.systemBuilder()
+        .with(Utils.listenerToDeleteFrom("JDKVALUEDENTITY"))
+        .withServices(repo)
+        .build();
+
+    @Test
+    public void persistTwo() throws Exception {
+        iswf.beginTran();
+        repo.newEntity().setStringProperty("1");
+        repo.newEntity().setStringProperty("2");
+        iswf.commitTran();
+
+        iswf.bounceSystem();
+        
+        iswf.beginTran();
+        List<JdkValuedEntity> list = repo.list();
+        assertThat(list.size(), is(2));
+        iswf.commitTran();
+    }
+
+    @Test
+    public void persist_then_update() throws Exception {
+        iswf.beginTran();
+        JdkValuedEntity entity = repo.newEntity();
+        entity.setStringProperty("1");
+        entity.setBigDecimalProperty(BigDecimal.valueOf(543210987654321L, 0)); // mssqlserver can cope with scale>0, but hsqldb cannot
+        entity.setBigIntegerProperty(BigInteger.valueOf(123456789012345L));
+        entity.setJavaSqlDateProperty(new java.sql.Date(Utils.toMillis(2009, 6, 11)));
+        entity.setJavaSqlTimeProperty(new java.sql.Time(Utils.toMillis(1970, 1, 1, 0, 5, 10))); // date portion is unimportant, is preserved on mssqlserver but not on hsqldb
+        entity.setJavaSqlTimestampProperty(new Timestamp(Utils.toMillis(2010, 5, 13, 20, 25, 30)));
+        entity.setJavaUtilDateProperty(new java.util.Date(Utils.toMillis(2010, 5, 13, 22, 17, 12)));
+        entity.setMyEnum(MyEnum.GREEN);
+        
+        iswf.commitTran();
+
+        iswf.bounceSystem();
+        
+        iswf.beginTran();
+        entity = repo.list().get(0);
+
+        assertThat(entity.getStringProperty(), is("1"));
+        assertThat(entity.getBigDecimalProperty(), is(BigDecimal.valueOf(543210987654321L, 0)));
+        assertThat(entity.getBigIntegerProperty(), is(BigInteger.valueOf(123456789012345L)));
+        assertThat(entity.getJavaSqlDateProperty(), is(new java.sql.Date(Utils.toMillis(2009, 6, 11))));
+        assertThat(entity.getJavaSqlTimeProperty(), is(new java.sql.Time(Utils.toMillis(1970, 1, 1, 0, 5, 10))));
+        assertThat(entity.getJavaSqlTimestampProperty(), is(new Timestamp(Utils.toMillis(2010, 5, 13, 20, 25, 30))));
+        assertThat(entity.getJavaUtilDateProperty(), is(new java.util.Date(Utils.toMillis(2010, 5, 13, 22, 17, 12))));
+        assertThat(entity.getMyEnum(), is(MyEnum.GREEN));
+        
+
+        entity.setBigDecimalProperty(BigDecimal.valueOf(123456789012345L, 0));
+        entity.setBigIntegerProperty(BigInteger.valueOf(543210987654321L));
+        entity.setJavaSqlDateProperty(new java.sql.Date(Utils.toMillis(2010, 5, 13)));
+        entity.setJavaSqlTimeProperty(new java.sql.Time(Utils.toMillis(1970, 1, 1, 5, 10, 15))); 
+        entity.setJavaSqlTimestampProperty(new Timestamp(Utils.toMillis(2010, 5, 13, 10, 15, 20)));
+        entity.setJavaUtilDateProperty(new java.util.Date(Utils.toMillis(2010, 5, 13, 20, 15, 10)));
+        entity.setMyEnum(MyEnum.BLUE);
+        
+        iswf.commitTran();
+
+        iswf.bounceSystem();
+        
+        iswf.beginTran();
+        entity = repo.list().get(0);
+        assertThat(entity.getBigDecimalProperty(), is(BigDecimal.valueOf(123456789012345L, 0)));  
+        assertThat(entity.getBigIntegerProperty(), is(BigInteger.valueOf(543210987654321L)));
+        assertThat(entity.getJavaSqlDateProperty(), is(new java.sql.Date(Utils.toMillis(2010, 5, 13))));
+        assertThat(entity.getJavaSqlTimeProperty(), is(new java.sql.Time(Utils.toMillis(1970, 1, 1, 5, 10, 15))));
+        assertThat(entity.getJavaSqlTimestampProperty(), is(new Timestamp(Utils.toMillis(2010, 5, 13, 10, 15, 20))));
+        assertThat(entity.getJavaUtilDateProperty(), is(new java.util.Date(Utils.toMillis(2010, 5, 13, 20, 15, 10))));
+        assertThat(entity.getMyEnum(), is(MyEnum.BLUE));
+        
+        iswf.commitTran();
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/21e2882a/tck/tck-integtests/src/test/java/org/apache/isis/objectstore/jdo/datanucleus/scenarios/scalar/Persistence_persistAndUpdate_objectAdapters.java
----------------------------------------------------------------------
diff --git a/tck/tck-integtests/src/test/java/org/apache/isis/objectstore/jdo/datanucleus/scenarios/scalar/Persistence_persistAndUpdate_objectAdapters.java b/tck/tck-integtests/src/test/java/org/apache/isis/objectstore/jdo/datanucleus/scenarios/scalar/Persistence_persistAndUpdate_objectAdapters.java
new file mode 100644
index 0000000..d1567cb
--- /dev/null
+++ b/tck/tck-integtests/src/test/java/org/apache/isis/objectstore/jdo/datanucleus/scenarios/scalar/Persistence_persistAndUpdate_objectAdapters.java
@@ -0,0 +1,112 @@
+/*
+ *  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.objectstore.jdo.datanucleus.scenarios.scalar;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.util.List;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.apache.isis.core.integtestsupport.IsisSystemWithFixtures;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.ResolveState;
+import org.apache.isis.core.metamodel.adapter.oid.OidMarshaller;
+import org.apache.isis.core.tck.dom.scalars.PrimitiveValuedEntity;
+import org.apache.isis.core.tck.dom.scalars.PrimitiveValuedEntityRepository;
+import org.apache.isis.objectstore.jdo.datanucleus.Utils;
+
+public class Persistence_persistAndUpdate_objectAdapters {
+
+    private PrimitiveValuedEntityRepository repo = new PrimitiveValuedEntityRepository();
+    
+    @Rule
+    public IsisSystemWithFixtures iswf = Utils.systemBuilder()
+        .with(Utils.listenerToDeleteFrom("PRIMITIVEVALUEDENTITY"))
+        .withServices(repo)
+        .build();
+
+    @Test
+    public void transient_then_persistent() throws Exception {
+        
+        iswf.beginTran();
+        PrimitiveValuedEntity entity = repo.newEntity();
+        ObjectAdapter adapter = iswf.adapterFor(entity);
+        
+        assertThat(adapter.isTransient(), is(true));
+        assertThat(adapter.getResolveState(), is(ResolveState.TRANSIENT));
+        assertThat(adapter.getOid().isTransient(), is(true));
+        
+        entity.setId(1);
+        iswf.commitTran();
+        
+        iswf.bounceSystem();
+        
+        iswf.beginTran();
+        final List<PrimitiveValuedEntity> list = repo.list();
+        assertThat(list.size(), is(1));
+        
+        adapter = iswf.adapterFor(list.get(0));
+        assertThat(adapter.getResolveState(), is(ResolveState.RESOLVED));
+        assertThat(adapter.isTransient(), is(false));
+        assertThat(adapter.getOid().enString(new OidMarshaller()), is("PRMV:i~1"));
+
+        iswf.commitTran();
+    }
+
+    @Test
+    public void updated_and_retrieved() throws Exception {
+
+        // given persisted
+        iswf.beginTran();
+        PrimitiveValuedEntity entity = repo.newEntity();
+        ObjectAdapter adapter = iswf.adapterFor(entity);
+        
+        entity.setId(1);
+        entity.setCharProperty('X');
+        
+        iswf.commitTran();
+        
+        // when update
+        iswf.bounceSystem();
+
+        iswf.beginTran();
+        entity = repo.list().get(0);
+        entity.setCharProperty('Y');
+        iswf.commitTran();
+
+        // then adapter's state is resolved
+        iswf.bounceSystem();
+        
+        iswf.beginTran();
+        entity = repo.list().get(0);
+        assertThat(entity.getCharProperty(), is('Y'));
+        
+        adapter = iswf.adapterFor(entity);
+        assertThat(adapter.getResolveState(), is(ResolveState.RESOLVED));
+        
+        iswf.commitTran();
+
+    }
+
+    
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/21e2882a/tck/tck-integtests/src/test/java/org/apache/isis/objectstore/jdo/datanucleus/scenarios/scalar/Persistence_persistAndUpdate_primitiveValuedEntity.java
----------------------------------------------------------------------
diff --git a/tck/tck-integtests/src/test/java/org/apache/isis/objectstore/jdo/datanucleus/scenarios/scalar/Persistence_persistAndUpdate_primitiveValuedEntity.java b/tck/tck-integtests/src/test/java/org/apache/isis/objectstore/jdo/datanucleus/scenarios/scalar/Persistence_persistAndUpdate_primitiveValuedEntity.java
new file mode 100644
index 0000000..3dfb7d4
--- /dev/null
+++ b/tck/tck-integtests/src/test/java/org/apache/isis/objectstore/jdo/datanucleus/scenarios/scalar/Persistence_persistAndUpdate_primitiveValuedEntity.java
@@ -0,0 +1,119 @@
+/*
+ *  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.objectstore.jdo.datanucleus.scenarios.scalar;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.util.List;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.apache.isis.core.integtestsupport.IsisSystemWithFixtures;
+import org.apache.isis.core.tck.dom.scalars.PrimitiveValuedEntity;
+import org.apache.isis.core.tck.dom.scalars.PrimitiveValuedEntityRepository;
+import org.apache.isis.objectstore.jdo.datanucleus.Utils;
+
+public class Persistence_persistAndUpdate_primitiveValuedEntity {
+
+    private PrimitiveValuedEntityRepository repo = new PrimitiveValuedEntityRepository();
+    
+    @Rule
+    public IsisSystemWithFixtures iswf = Utils.systemBuilder()
+        .with(Utils.listenerToDeleteFrom("PRIMITIVEVALUEDENTITY"))
+        .withServices(repo)
+        .build();
+
+    @Test
+    public void persistTwo() throws Exception {
+        iswf.beginTran();
+        repo.newEntity().setId(1);
+        repo.newEntity().setId(2);
+        iswf.commitTran();
+
+        iswf.bounceSystem();
+        
+        iswf.beginTran();
+        List<PrimitiveValuedEntity> list = repo.list();
+        assertThat(list.size(), is(2));
+        iswf.commitTran();
+    }
+
+    @Test
+    public void persist_then_update() throws Exception {
+        
+        iswf.beginTran();
+        PrimitiveValuedEntity entity = repo.newEntity();
+        entity.setId(1);
+        
+        entity.setBooleanProperty(false);
+        entity.setByteProperty((byte)456);
+        entity.setDoubleProperty(123456789876.0);
+        entity.setFloatProperty(654321.0f);
+        entity.setIntProperty(765);
+        entity.setLongProperty(7654321012345L);
+        entity.setShortProperty((short)543);
+        entity.setCharProperty('A');
+        
+        iswf.commitTran();
+
+        iswf.bounceSystem();
+        
+        iswf.beginTran();
+        entity = repo.list().get(0);
+
+        assertThat(entity.getBooleanProperty(), is(false));
+        assertThat(entity.getByteProperty(), is((byte)456));
+        assertThat(entity.getDoubleProperty(), is(123456789876.0));
+        assertThat(entity.getFloatProperty(), is(654321.0f));
+        assertThat(entity.getIntProperty(), is(765));
+        assertThat(entity.getLongProperty(), is(7654321012345L));
+        assertThat(entity.getShortProperty(), is((short)543));
+        assertThat(entity.getCharProperty(), is('A'));
+
+        
+        entity.setBooleanProperty(true);
+        entity.setByteProperty((byte)123);
+        entity.setDoubleProperty(9876543210987.0);
+        entity.setFloatProperty(123456.0f);
+        entity.setIntProperty(456);
+        entity.setLongProperty(12345678901L);
+        entity.setShortProperty((short)4567);
+        entity.setCharProperty('X');
+
+        iswf.commitTran();
+
+        iswf.bounceSystem();
+        
+        iswf.beginTran();
+        entity = repo.list().get(0);
+
+        assertThat(entity.getBooleanProperty(), is(true));
+        assertThat(entity.getByteProperty(), is((byte)123));
+        assertThat(entity.getDoubleProperty(), is(9876543210987.0));
+        assertThat(entity.getFloatProperty(), is(123456.0f));
+        assertThat(entity.getIntProperty(), is(456));
+        assertThat(entity.getLongProperty(), is(12345678901L));
+        assertThat(entity.getShortProperty(), is((short)4567));
+        assertThat(entity.getCharProperty(), is('X'));
+        
+        iswf.commitTran();
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/21e2882a/tck/tck-integtests/src/test/java/org/apache/isis/objectstore/jdo/datanucleus/scenarios/scalar/Persistence_persistAndUpdate_wrapperValuedEntity.java
----------------------------------------------------------------------
diff --git a/tck/tck-integtests/src/test/java/org/apache/isis/objectstore/jdo/datanucleus/scenarios/scalar/Persistence_persistAndUpdate_wrapperValuedEntity.java b/tck/tck-integtests/src/test/java/org/apache/isis/objectstore/jdo/datanucleus/scenarios/scalar/Persistence_persistAndUpdate_wrapperValuedEntity.java
new file mode 100644
index 0000000..94e3c62
--- /dev/null
+++ b/tck/tck-integtests/src/test/java/org/apache/isis/objectstore/jdo/datanucleus/scenarios/scalar/Persistence_persistAndUpdate_wrapperValuedEntity.java
@@ -0,0 +1,118 @@
+/*
+ *  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.objectstore.jdo.datanucleus.scenarios.scalar;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.util.List;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.apache.isis.core.integtestsupport.IsisSystemWithFixtures;
+import org.apache.isis.core.tck.dom.scalars.WrapperValuedEntity;
+import org.apache.isis.core.tck.dom.scalars.WrapperValuedEntityRepository;
+import org.apache.isis.objectstore.jdo.datanucleus.Utils;
+
+public class Persistence_persistAndUpdate_wrapperValuedEntity {
+
+    private WrapperValuedEntityRepository repo = new WrapperValuedEntityRepository();
+    
+    @Rule
+    public IsisSystemWithFixtures iswf = Utils.systemBuilder()
+        .with(Utils.listenerToDeleteFrom("WRAPPERVALUEDENTITY"))
+        .withServices(repo)
+        .build();
+
+    @Test
+    public void persistTwo() throws Exception {
+        iswf.beginTran();
+        repo.newEntity().setStringProperty("1");
+        repo.newEntity().setStringProperty("2");
+        iswf.commitTran();
+
+        iswf.bounceSystem();
+        
+        iswf.beginTran();
+        List<WrapperValuedEntity> list = repo.list();
+        assertThat(list.size(), is(2));
+        iswf.commitTran();
+    }
+
+    
+    @Test
+    public void persist_then_update() throws Exception {
+        iswf.beginTran();
+        WrapperValuedEntity entity = repo.newEntity();
+        entity.setStringProperty("1");
+        entity.setBooleanProperty(false);
+        entity.setByteProperty((byte)321);
+        entity.setDoubleProperty(123456768723429.0);
+        entity.setFloatProperty(654321.0f);
+        entity.setIntegerProperty(543);
+        entity.setLongProperty(90876512345L);
+        entity.setShortProperty((short)7654);
+        entity.setCharacterProperty('A');
+        
+        iswf.commitTran();
+
+        iswf.bounceSystem();
+
+        iswf.beginTran();
+        entity = repo.list().get(0);
+        assertThat(entity.getStringProperty(), is("1"));
+        assertThat(entity.getBooleanProperty(), is(false));
+        assertThat(entity.getByteProperty(), is((byte)321));
+        assertThat(entity.getDoubleProperty(), is(123456768723429.0));
+        assertThat(entity.getFloatProperty(), is(654321.0f));
+        assertThat(entity.getIntegerProperty(), is(543));
+        assertThat(entity.getLongProperty(), is(90876512345L));
+        assertThat(entity.getShortProperty(), is((short)7654));
+        assertThat(entity.getCharacterProperty(), is('A'));
+        
+        
+        entity.setBooleanProperty(true);
+        entity.setByteProperty((byte)123);
+        entity.setDoubleProperty(9876543210987.0);
+        entity.setFloatProperty(123456.0f);
+        entity.setIntegerProperty(456);
+        entity.setLongProperty(12345678901L);
+        entity.setShortProperty((short)4567);
+        entity.setCharacterProperty('X');
+        
+        iswf.commitTran();
+
+        iswf.bounceSystem();
+
+        iswf.beginTran();
+        entity = repo.list().get(0);
+        assertThat(entity.getBooleanProperty(), is(true));
+        assertThat(entity.getByteProperty(), is((byte)123));
+        assertThat(entity.getDoubleProperty(), is(9876543210987.0));
+        assertThat(entity.getFloatProperty(), is(123456.0f));
+        assertThat(entity.getIntegerProperty(), is(456));
+        assertThat(entity.getLongProperty(), is(12345678901L));
+        assertThat(entity.getShortProperty(), is((short)4567));
+        assertThat(entity.getCharacterProperty(), is('X'));
+        
+        iswf.commitTran();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/21e2882a/tck/tck-integtests/src/test/java/org/apache/isis/objectstore/jdo/datanucleus/scenarios/scalar/Persistence_persist_dataStoreAssignedPrimaryKey.java
----------------------------------------------------------------------
diff --git a/tck/tck-integtests/src/test/java/org/apache/isis/objectstore/jdo/datanucleus/scenarios/scalar/Persistence_persist_dataStoreAssignedPrimaryKey.java b/tck/tck-integtests/src/test/java/org/apache/isis/objectstore/jdo/datanucleus/scenarios/scalar/Persistence_persist_dataStoreAssignedPrimaryKey.java
new file mode 100644
index 0000000..25a858f
--- /dev/null
+++ b/tck/tck-integtests/src/test/java/org/apache/isis/objectstore/jdo/datanucleus/scenarios/scalar/Persistence_persist_dataStoreAssignedPrimaryKey.java
@@ -0,0 +1,59 @@
+/*
+ *  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.objectstore.jdo.datanucleus.scenarios.scalar;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.util.List;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.apache.isis.core.integtestsupport.IsisSystemWithFixtures;
+import org.apache.isis.core.tck.dom.scalars.AutoAssignedEntity;
+import org.apache.isis.core.tck.dom.scalars.AutoAssignedEntityRepository;
+import org.apache.isis.objectstore.jdo.datanucleus.Utils;
+
+public class Persistence_persist_dataStoreAssignedPrimaryKey {
+
+    private AutoAssignedEntityRepository repo = new AutoAssignedEntityRepository();
+    
+    @Rule
+    public IsisSystemWithFixtures iswf = Utils.systemBuilder()
+        .with(Utils.listenerToDeleteFrom("AUTOASSIGNEDENTITY"))
+        .withServices(repo)
+        .build();
+
+    @Test
+    public void persistTwo() throws Exception {
+        iswf.beginTran();
+        repo.newEntity();
+        repo.newEntity();
+        iswf.commitTran();
+
+        iswf.bounceSystem();
+        
+        iswf.beginTran();
+        List<AutoAssignedEntity> list = repo.list();
+        assertThat(list.size(), is(2));
+        iswf.commitTran();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/21e2882a/tck/tck-viewer-restfulobjects/README-testcases.md
----------------------------------------------------------------------
diff --git a/tck/tck-viewer-restfulobjects/README-testcases.md b/tck/tck-viewer-restfulobjects/README-testcases.md
new file mode 100644
index 0000000..b05c06a
--- /dev/null
+++ b/tck/tck-viewer-restfulobjects/README-testcases.md
@@ -0,0 +1,80 @@
+<!--
+ *  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.
+-->
+
+<pre>
+
+[incorrect]_thenResponseCode_405_bad
+
+Get_whenQueryArg_xRoFollowLinks_ok
+Get_whenQueryArg_xRoDomainModel_ok
+
+Get_whenRequestHeaders_Accept_isInvalid_bad
+Get_whenRequestHeaders_Accept_ok
+
+
+[modifying]_givenDisabled_thenResponseCode_203_TODO
+
+[modifying]_givenEtag_whenIfMatchHeaderDoesMatch_ok
+[modifying]_givenEtag_whenIfMatchHeaderDoesNotMatch_bad
+
+[modifying]_givenXxx_whenArgsValid_thenXxx_ok_TODO
+
+
+[modifying]_whenArgsMandatoryButMissing_bad_TODO
+rename from
+[modifying]_whenNoArg_bad_TODO
+
+
+[modifying]_then[PostConditionsHappyCase]_TODO
+
+[modifying]_whenArgIsHrefAndLinksToNonExistentEntity_bad_TODO
+[modifying]_whenArgIsHrefAndLinksToEntityOfWrongType_bad_TODO
+
+[modifying]_whenArgValueIsValid_andQueryArg_XRoValidateOnly_2xx_TODO
+[modifying]_whenArgValueIsInvalid_andQueryArg_XRoValidateOnly_4xx_TODO
+[modifying]_whenArgValueIsInvalid_bad_TODO
+
+[modifying]_whenArgIsMalformed_bad_TODO
+
+[anyValid]_whenDoesntExistOid_thenResponseCode_404_TODO
+[anyValid]_whenDoesntExistMember_thenResponseCode_404_TODO
+[anyValid]_givenHidden_thenResponseCode_404_TODO
+
+[anyValid]_thenRepresentation_ok_TODO
+[anyValid]_thenResponseCode_200_ok
+[anyValid]_thenResponseHeaders_ContentType_ok
+[anyValid]_thenResponseHeaders_ContentLength_ok
+[anyValid]_thenResponseHeaders_CacheControl_ok
+[anyValid]_thenResponseHeaders_eTag_ok
+
+
+
+
+
+
+
+Delete_whenLinkToEntityThatExistsButIsNotInCollection_ok_TODO
+Delete_whenHrefArgLinksToEntityInCollection_ok_TODO
+Put_whenArgsValid_thenMultiplePropertyUpdate_TODO
+
+Put_givenEntityAlreadyInCollection_whenArgsValid_thenNoChange_ok_TODO
+Put_givenEntityNotInCollection_whenArgsValid_thenEntityAddedFromCollection_ok_TODO
+
+Get_givenHiddenMembers_thenRepresentation_ok_TODO
+</pre>

http://git-wip-us.apache.org/repos/asf/isis/blob/21e2882a/tck/tck-viewer-restfulobjects/ide/eclipse/launch/viewer-restful-tck.launch
----------------------------------------------------------------------
diff --git a/tck/tck-viewer-restfulobjects/ide/eclipse/launch/viewer-restful-tck.launch b/tck/tck-viewer-restfulobjects/ide/eclipse/launch/viewer-restful-tck.launch
new file mode 100644
index 0000000..53bd401
--- /dev/null
+++ b/tck/tck-viewer-restfulobjects/ide/eclipse/launch/viewer-restful-tck.launch
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
+<listEntry value="/org.apache.isis.runtimes.dflt.webserver/src/main/java/org/apache/isis/WebServer.java"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
+<listEntry value="1"/>
+</listAttribute>
+<mapAttribute key="org.eclipse.debug.core.preferred_launchers">
+<mapEntry key="[debug]" value="org.eclipse.jdt.launching.localJavaApplication"/>
+<mapEntry key="[run]" value="org.eclipse.jdt.launching.localJavaApplication"/>
+</mapAttribute>
+<stringAttribute key="org.eclipse.debug.core.source_locator_id" value="org.eclipse.jdt.launching.sourceLocator.JavaSourceLookupDirector"/>
+<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="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/21e2882a/tck/tck-viewer-restfulobjects/pom.xml
----------------------------------------------------------------------
diff --git a/tck/tck-viewer-restfulobjects/pom.xml b/tck/tck-viewer-restfulobjects/pom.xml
new file mode 100644
index 0000000..4e53e07
--- /dev/null
+++ b/tck/tck-viewer-restfulobjects/pom.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+  
+         http://www.apache.org/licenses/LICENSE-2.0
+         
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.isis.tck</groupId>
+        <artifactId>isis-tck</artifactId>
+        <version>1.8.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>isis-tck-viewer-restfulobjects</artifactId>
+    <name>Isis RestfulObjects Viewer TCK tests</name>
+
+    <packaging>war</packaging>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.mortbay.jetty</groupId>
+                <artifactId>maven-jetty-plugin</artifactId>
+            </plugin>
+
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <includes>
+                        <include>**/*Test_*.java</include>
+                        <include>**/Get_*.java</include>
+                        <include>**/Delete_*.java</include>
+                        <include>**/Put_*.java</include>
+                        <include>**/Post_*.java</include>
+                    </includes>
+                    <!-- TODO: reinstate -->
+                    <skipTests>true</skipTests>
+                </configuration>
+            </plugin>
+
+        </plugins>
+    </build>
+
+    <repositories>
+        <repository>
+            <id>JBoss Public Release</id>
+            <url>https://repository.jboss.org/nexus/content/groups/public-jboss/</url>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+        </repository>
+    </repositories>
+
+    <dependencies>
+
+        <!-- other modules in this project -->
+        <dependency>
+            <groupId>org.apache.isis.tck</groupId>
+            <artifactId>isis-tck-dom</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.isis.tck</groupId>
+            <artifactId>isis-tck-fixture</artifactId>
+        </dependency>
+
+        <!-- isis viewer -->
+        <dependency>
+            <groupId>org.apache.isis.core</groupId>
+            <artifactId>isis-core-viewer-restfulobjects-server</artifactId>
+        </dependency>
+
+
+        <!-- isis runtime -->
+        <dependency>
+            <groupId>org.apache.isis.core</groupId>
+            <artifactId>isis-core-objectstore</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.isis.core</groupId>
+            <artifactId>isis-core-security</artifactId>
+        </dependency>
+
+        <!-- to run using WebServer -->
+        <dependency>
+            <groupId>org.apache.isis.core</groupId>
+            <artifactId>isis-core-webserver</artifactId>
+            <scope>runtime</scope>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>org.reflections</groupId>
+            <artifactId>reflections</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+    </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/isis/blob/21e2882a/tck/tck-viewer-restfulobjects/src/main/java/org/apache/isis/viewer/restfulobjects/tck/Dummy.java
----------------------------------------------------------------------
diff --git a/tck/tck-viewer-restfulobjects/src/main/java/org/apache/isis/viewer/restfulobjects/tck/Dummy.java b/tck/tck-viewer-restfulobjects/src/main/java/org/apache/isis/viewer/restfulobjects/tck/Dummy.java
new file mode 100644
index 0000000..e72a568
--- /dev/null
+++ b/tck/tck-viewer-restfulobjects/src/main/java/org/apache/isis/viewer/restfulobjects/tck/Dummy.java
@@ -0,0 +1,24 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.restfulobjects.tck;
+
+
+public class Dummy {
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/21e2882a/tck/tck-viewer-restfulobjects/src/main/webapp/WEB-INF/isis.properties
----------------------------------------------------------------------
diff --git a/tck/tck-viewer-restfulobjects/src/main/webapp/WEB-INF/isis.properties b/tck/tck-viewer-restfulobjects/src/main/webapp/WEB-INF/isis.properties
new file mode 100644
index 0000000..e6bf541
--- /dev/null
+++ b/tck/tck-viewer-restfulobjects/src/main/webapp/WEB-INF/isis.properties
@@ -0,0 +1,42 @@
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#  
+#         http://www.apache.org/licenses/LICENSE-2.0
+#         
+#  Unless required by applicable law or agreed to in writing,
+#  software distributed under the License is distributed on an
+#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#  KIND, either express or implied.  See the License for the
+#  specific language governing permissions and limitations
+#  under the License.
+
+isis.authentication=bypass
+isis.authorization=bypass
+
+isis.persistor=in-memory
+
+isis.services-installer=configuration-and-annotation
+isis.services.ServicesInstallerFromAnnotation.packagePrefix=org.apache.isis.core.tck.dom
+
+isis.services = org.apache.isis.applib.services.eventbus.EventBusService$Noop
+
+isis.fixtures.prefix= org.apache.isis.core.tck.fixture
+isis.fixtures=\
+    LogonAsSvenFixture,\
+    scalars.ApplibValuedEntityFixture,\
+    scalars.JdkValuedEntityFixture,\
+    scalars.PrimitiveValuedEntityFixture,\
+    scalars.WrapperValuedEntityFixture,\
+    refs.ParentEntitiesFixture,\
+    defaults.WithDefaultsEntityFixture,\
+    busrules.BusRulesEntityFixture,\
+    actions.ActionsEntityFixture,\
+    scalars.JodaValuedEntityFixture
+    
+
+

http://git-wip-us.apache.org/repos/asf/isis/blob/21e2882a/tck/tck-viewer-restfulobjects/src/main/webapp/WEB-INF/logging.properties
----------------------------------------------------------------------
diff --git a/tck/tck-viewer-restfulobjects/src/main/webapp/WEB-INF/logging.properties b/tck/tck-viewer-restfulobjects/src/main/webapp/WEB-INF/logging.properties
new file mode 100644
index 0000000..c7f605a
--- /dev/null
+++ b/tck/tck-viewer-restfulobjects/src/main/webapp/WEB-INF/logging.properties
@@ -0,0 +1,30 @@
+#  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.
+# apache's log4j is used to provide system logging.
+log4j.rootCategory=WARN, Console
+
+# The console appender
+log4j.appender.Console=org.apache.log4j.ConsoleAppender
+log4j.appender.Console.target=System.out
+log4j.appender.Console.layout=org.apache.log4j.PatternLayout
+log4j.appender.Console.layout.ConversionPattern=%d{ABSOLUTE}  [%-20c{1} %-10t %-5p]  %m%n
+
+log4j.appender.File=org.apache.log4j.RollingFileAppender
+log4j.appender.File.file=isis.log
+log4j.appender.File.append=false
+log4j.appender.File.layout=org.apache.log4j.PatternLayout
+log4j.appender.File.layout.ConversionPattern=%d [%-20c{1} %-10t %-5p]  %m%n

http://git-wip-us.apache.org/repos/asf/isis/blob/21e2882a/tck/tck-viewer-restfulobjects/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/tck/tck-viewer-restfulobjects/src/main/webapp/WEB-INF/web.xml b/tck/tck-viewer-restfulobjects/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..366134d
--- /dev/null
+++ b/tck/tck-viewer-restfulobjects/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+  
+         http://www.apache.org/licenses/LICENSE-2.0
+         
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<web-app id="WebApp_ID" version="2.4"
+	xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
+
+	<display-name>RestfulObjects TCK</display-name>
+
+
+	<filter>
+		<filter-name>ResourceCachingFilter</filter-name>
+		<filter-class>org.apache.isis.core.webapp.content.ResourceCachingFilter</filter-class>
+		<init-param>
+			<param-name>CacheTime</param-name>
+			<param-value>86400</param-value>
+		</init-param>
+	</filter>
+
+	<filter-mapping>
+		<filter-name>ResourceCachingFilter</filter-name>
+		<url-pattern>*.js</url-pattern>
+	</filter-mapping>
+	<filter-mapping>
+		<filter-name>ResourceCachingFilter</filter-name>
+		<url-pattern>*.css</url-pattern>
+	</filter-mapping>
+	<filter-mapping>
+		<filter-name>ResourceCachingFilter</filter-name>
+		<url-pattern>*.jpg</url-pattern>
+	</filter-mapping>
+	<filter-mapping>
+		<filter-name>ResourceCachingFilter</filter-name>
+		<url-pattern>*.png</url-pattern>
+	</filter-mapping>
+	<filter-mapping>
+		<filter-name>ResourceCachingFilter</filter-name>
+		<url-pattern>*.gif</url-pattern>
+	</filter-mapping>
+
+	<servlet>
+		<servlet-name>Resource</servlet-name>
+		<servlet-class>org.apache.isis.core.webapp.content.ResourceServlet</servlet-class>
+	</servlet>
+
+	<servlet-mapping>
+		<servlet-name>Resource</servlet-name>
+		<url-pattern>*.js</url-pattern>
+	</servlet-mapping>
+	<servlet-mapping>
+		<servlet-name>Resource</servlet-name>
+		<url-pattern>*.gif</url-pattern>
+	</servlet-mapping>
+	<servlet-mapping>
+		<servlet-name>Resource</servlet-name>
+		<url-pattern>*.png</url-pattern>
+	</servlet-mapping>
+    <servlet-mapping>
+        <servlet-name>Resource</servlet-name>
+        <url-pattern>*.html</url-pattern>
+    </servlet-mapping>
+
+
+
+
+	<listener>
+		<listener-class>org.apache.isis.core.webapp.IsisWebAppBootstrapper</listener-class>
+	</listener>
+
+	<context-param>
+		<param-name>isis.viewers</param-name>
+		<param-value>restfulobjects</param-value>
+	</context-param>
+
+	<filter>
+		<filter-name>IsisSessionFilter</filter-name>
+		<filter-class>org.apache.isis.core.webapp.IsisSessionFilter</filter-class>
+		<init-param>
+			<!-- trusted client, so no authentication required -->
+			<param-name>authenticationSessionStrategy</param-name>
+			<param-value>org.apache.isis.viewer.restfulobjects.server.authentication.AuthenticationSessionStrategyTrusted</param-value>
+		</init-param>
+		<init-param>
+            <!-- what to do if no session was found; we indicate to issue a 401 basic authentication challenge -->
+            <param-name>whenNoSession</param-name>
+            <param-value>continue</param-value>
+        </init-param>
+	</filter>
+
+	<filter-mapping>
+		<filter-name>IsisSessionFilter</filter-name>
+		<url-pattern>*</url-pattern>
+	</filter-mapping>
+
+    <filter>
+        <filter-name>IsisTransactionFilterForRestfulObjects</filter-name>
+        <filter-class>org.apache.isis.viewer.restfulobjects.server.webapp.IsisTransactionFilterForRestfulObjects</filter-class>
+    </filter>
+    <filter-mapping>
+        <filter-name>IsisTransactionFilterForRestfulObjects</filter-name>
+        <url-pattern>*</url-pattern>
+    </filter-mapping>
+
+
+
+	<listener>
+		<listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
+	</listener>
+
+	<context-param>
+		<param-name>javax.ws.rs.Application</param-name>
+		<param-value>org.apache.isis.viewer.restfulobjects.server.RestfulObjectsApplication</param-value>
+	</context-param>
+
+	<servlet>
+		<servlet-name>RestEasy</servlet-name>
+		<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
+	</servlet>
+
+	<servlet-mapping>
+		<servlet-name>RestEasy</servlet-name>
+		<url-pattern>/</url-pattern>
+	</servlet-mapping>
+
+</web-app>

http://git-wip-us.apache.org/repos/asf/isis/blob/21e2882a/tck/tck-viewer-restfulobjects/src/test/java/org/apache/isis/viewer/restfulobjects/tck/IsisWebServerRule.java
----------------------------------------------------------------------
diff --git a/tck/tck-viewer-restfulobjects/src/test/java/org/apache/isis/viewer/restfulobjects/tck/IsisWebServerRule.java b/tck/tck-viewer-restfulobjects/src/test/java/org/apache/isis/viewer/restfulobjects/tck/IsisWebServerRule.java
new file mode 100644
index 0000000..7197ff0
--- /dev/null
+++ b/tck/tck-viewer-restfulobjects/src/test/java/org/apache/isis/viewer/restfulobjects/tck/IsisWebServerRule.java
@@ -0,0 +1,83 @@
+/*
+ *  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.tck;
+
+import org.apache.http.client.HttpClient;
+import org.jboss.resteasy.client.ClientExecutor;
+import org.junit.rules.MethodRule;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.Statement;
+
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.core.webserver.WebServer;
+import org.apache.isis.viewer.restfulobjects.applib.client.RestfulClient;
+
+public class IsisWebServerRule implements MethodRule {
+
+    private static ThreadLocal<WebServer> WEBSERVER = new ThreadLocal<WebServer>();
+
+    private RestfulClient client;
+
+    @Override
+    public Statement apply(final Statement base, final FrameworkMethod method, final Object target) {
+        getWebServer(); // creates and starts running if required
+        return base;
+    }
+
+    public WebServer getWebServer() {
+        WebServer webServer = WEBSERVER.get();
+        if(webServer == null) {
+            webServer = new WebServer();
+            WEBSERVER.set(webServer);
+            webServer.run(39393);
+        }
+        return webServer;
+    }
+    
+    public void discardWebApp() {
+        getWebServer().stop();
+        WEBSERVER.set(null);
+        IsisContext.testReset();
+    }
+
+    public RestfulClient getClient() {
+        if(client == null) {
+            final WebServer webServer = getWebServer();
+            client = new RestfulClient(webServer.getBase());
+        }
+        return client;
+    }
+    
+    public RestfulClient getClient(HttpClient httpClient) {
+        if(client == null) {
+            final WebServer webServer = getWebServer();
+            client = new RestfulClient(webServer.getBase(), httpClient);
+        }
+        return client;
+    }
+    
+    public RestfulClient getClient(ClientExecutor clientExecutor) {
+        if(client == null) {
+            final WebServer webServer = getWebServer();
+            client = new RestfulClient(webServer.getBase(), clientExecutor);
+        }
+        return client;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/21e2882a/tck/tck-viewer-restfulobjects/src/test/java/org/apache/isis/viewer/restfulobjects/tck/RelTest_matches.java
----------------------------------------------------------------------
diff --git a/tck/tck-viewer-restfulobjects/src/test/java/org/apache/isis/viewer/restfulobjects/tck/RelTest_matches.java b/tck/tck-viewer-restfulobjects/src/test/java/org/apache/isis/viewer/restfulobjects/tck/RelTest_matches.java
new file mode 100644
index 0000000..72808e4
--- /dev/null
+++ b/tck/tck-viewer-restfulobjects/src/test/java/org/apache/isis/viewer/restfulobjects/tck/RelTest_matches.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.viewer.restfulobjects.tck;
+
+import org.junit.Test;
+import org.apache.isis.viewer.restfulobjects.applib.Rel;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+public class RelTest_matches {
+
+    @Test
+    public void whenDoes() throws Exception {
+        assertThat(Rel.ACTION.matches(Rel.ACTION), is(true));
+    }
+
+    @Test
+    public void whenDoesNot() throws Exception {
+        assertThat(Rel.ACTION.matches(Rel.ACTION_PARAM), is(false));
+    }
+
+    @Test
+    public void whenMatchesOnStr() throws Exception {
+        assertThat(Rel.ACTION.matches(Rel.ACTION.getName()), is(true));
+    }
+
+    @Test
+    public void whenMatchesOnStrWithParams() throws Exception {
+        assertThat(Rel.ACTION.matches(Rel.ACTION.andParam("foo", "bar")), is(true));
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/21e2882a/tck/tck-viewer-restfulobjects/src/test/java/org/apache/isis/viewer/restfulobjects/tck/RestfulMatchers.java
----------------------------------------------------------------------
diff --git a/tck/tck-viewer-restfulobjects/src/test/java/org/apache/isis/viewer/restfulobjects/tck/RestfulMatchers.java b/tck/tck-viewer-restfulobjects/src/test/java/org/apache/isis/viewer/restfulobjects/tck/RestfulMatchers.java
new file mode 100644
index 0000000..fa71905
--- /dev/null
+++ b/tck/tck-viewer-restfulobjects/src/test/java/org/apache/isis/viewer/restfulobjects/tck/RestfulMatchers.java
@@ -0,0 +1,660 @@
+/*
+ *  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.tck;
+
+import javax.ws.rs.core.CacheControl;
+import javax.ws.rs.core.MediaType;
+import com.google.common.base.Objects;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+import org.junit.Assert;
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation.HasLinkToSelf;
+import org.apache.isis.viewer.restfulobjects.applib.LinkRepresentation;
+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.RestfulResponse;
+import org.apache.isis.viewer.restfulobjects.applib.client.RestfulResponse.Header;
+import org.apache.isis.viewer.restfulobjects.applib.client.RestfulResponse.HttpStatusCode;
+
+public class RestfulMatchers {
+
+    public static <T extends JsonRepresentation> Matcher<T> isMap() {
+        return new TypeSafeMatcher<T>() {
+
+            @Override
+            public void describeTo(final Description description) {
+                description.appendText("map");
+            }
+
+            @Override
+            public boolean matchesSafely(final T item) {
+                return item != null && item.isMap();
+            }
+        };
+    }
+
+    public static <T extends JsonRepresentation> Matcher<T> isArray() {
+        return new TypeSafeMatcher<T>() {
+
+            @Override
+            public void describeTo(final Description description) {
+                description.appendText("array");
+            }
+
+            @Override
+            public boolean matchesSafely(final T item) {
+                return item != null && item.isArray();
+            }
+        };
+    }
+
+    public static <T extends JsonRepresentation> Matcher<T> isString() {
+        return new TypeSafeMatcher<T>() {
+
+            @Override
+            public void describeTo(final Description description) {
+                description.appendText("string");
+            }
+
+            @Override
+            public boolean matchesSafely(final T item) {
+                return item != null && item.isValue() && item.asJsonNode().isTextual();
+            }
+        };
+    }
+
+    public static Matcher<LinkRepresentation> isLink(final RestfulHttpMethod httpMethod) {
+        return new TypeSafeMatcher<LinkRepresentation>() {
+
+            @Override
+            public void describeTo(final Description description) {
+                description.appendText("link with method " + httpMethod.name());
+            }
+
+            @Override
+            public boolean matchesSafely(final LinkRepresentation item) {
+                return item != null && item.getHttpMethod() == httpMethod;
+            }
+        };
+    }
+
+    public static <T extends JsonRepresentation> Matcher<T> isFollowableLinkToSelf(final RestfulClient client) {
+        return new TypeSafeMatcher<T>() {
+
+            @Override
+            public void describeTo(final Description description) {
+                description.appendText("links to self");
+            }
+
+            @Override
+            public boolean matchesSafely(final T item) {
+                final HasLinkToSelf initialRepr = (HasLinkToSelf) item; // no easy
+                                                                    // way to do
+                                                                    // this with
+                                                                    // Hamcrest
+                // when
+                try {
+                    final RestfulResponse<T> followedResp = client.followT(initialRepr.getSelf());
+
+                    // then
+                    final T repr2 = followedResp.getEntity();
+                    final HasLinkToSelf repr2AsLinksToSelf = (HasLinkToSelf) repr2;
+                    return initialRepr.getSelf().equals(repr2AsLinksToSelf.getSelf());
+                } catch (final Exception e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        };
+    }
+
+    public static <T extends JsonRepresentation> void assertThat(final T actual, final AbstractMatcherBuilder<T> matcherBuilder) {
+        Assert.assertThat(actual, matcherBuilder.build());
+    }
+
+    public static LinkMatcherBuilder isLink(final RestfulClient client) {
+        return new LinkMatcherBuilder(client);
+    }
+
+    public static LinkMatcherBuilder isLink() {
+        return new LinkMatcherBuilder(null);
+    }
+
+    public static abstract class AbstractMatcherBuilder<T> {
+        protected RestfulClient client;
+
+        public AbstractMatcherBuilder() {
+            this(null);
+        }
+
+        public AbstractMatcherBuilder(final RestfulClient client) {
+            this.client = client;
+        }
+
+        public abstract Matcher<T> build();
+    }
+
+    public static class LinkMatcherBuilder extends AbstractMatcherBuilder<JsonRepresentation> {
+        private HttpStatusCode statusCode;
+        private RestfulHttpMethod httpMethod;
+        private String rel;
+        private String href;
+        private Matcher<String> relNameMatcher;
+        private Matcher<String> hrefMatcher;
+        private Matcher<JsonRepresentation> valueMatcher;
+        private Boolean novalue;
+        private MediaType mediaType;
+        private String typeParameterName;
+        private String typeParameterValue;
+        private String selfHref;
+        private JsonRepresentation arguments;
+        private String title;
+        private Matcher<String> titleMatcher;
+
+        private LinkMatcherBuilder(final RestfulClient client) {
+            super(client);
+        }
+
+        public LinkMatcherBuilder rel(final String rel) {
+            this.rel = rel;
+            return this;
+        }
+
+        public LinkMatcherBuilder rel(final Rel rel) {
+            this.rel = rel.getName();
+            return this;
+        }
+
+        public LinkMatcherBuilder rel(final Matcher<String> relNameMatcher) {
+            this.relNameMatcher = relNameMatcher;
+            return this;
+        }
+
+        public LinkMatcherBuilder href(final String href) {
+            this.href = href;
+            return this;
+        }
+
+        public LinkMatcherBuilder href(final Matcher<String> hrefMatcher) {
+            this.hrefMatcher = hrefMatcher;
+            return this;
+        }
+
+        public LinkMatcherBuilder httpMethod(final RestfulHttpMethod httpMethod) {
+            this.httpMethod = httpMethod;
+            return this;
+        }
+
+        public LinkMatcherBuilder type(final MediaType mediaType) {
+            this.mediaType = mediaType;
+            return this;
+        }
+
+        public LinkMatcherBuilder title(String title) {
+            this.title = title;
+            return this;
+        }
+
+        public LinkMatcherBuilder title(Matcher<String> titleMatcher) {
+            this.titleMatcher = titleMatcher;
+            return this;
+        }
+        
+        public LinkMatcherBuilder typeParameter(final String typeParameterName, final String typeParameterValue) {
+            this.typeParameterName = typeParameterName;
+            this.typeParameterValue = typeParameterValue;
+            return this;
+        }
+
+        public LinkMatcherBuilder arguments(JsonRepresentation arguments) {
+            this.arguments = arguments;
+            return this;
+        }
+
+        public LinkMatcherBuilder novalue() {
+            if (valueMatcher != null) {
+                throw new IllegalStateException("cannot assert on both there being a value and there not being a value");
+            }
+            this.novalue = true;
+            return this;
+        }
+
+        public LinkMatcherBuilder value(final Matcher<JsonRepresentation> valueMatcher) {
+            if (this.novalue != null) {
+                throw new IllegalStateException("cannot assert on both there being a value and there not being a value");
+            }
+            this.valueMatcher = valueMatcher;
+            return this;
+        }
+
+        public LinkMatcherBuilder returning(final HttpStatusCode statusCode) {
+            this.statusCode = statusCode;
+            return this;
+        }
+
+        public LinkMatcherBuilder responseEntityWithSelfHref(String selfHref) {
+            this.selfHref = selfHref;
+            return this;
+        }
+
+        @Override
+        public Matcher<JsonRepresentation> build() {
+            return new TypeSafeMatcher<JsonRepresentation>() {
+
+                @Override
+                public void describeTo(final Description description) {
+                    description.appendText("a link");
+                    if (rel != null) {
+                        description.appendText(" with rel '").appendText(rel).appendText("'");
+                    }
+                    if (relNameMatcher != null) {
+                        description.appendText(" with rel '");
+                        relNameMatcher.describeTo(description);
+                    }
+                    if (href != null) {
+                        description.appendText(" with href '").appendText(href).appendText("'");
+                    }
+                    if (hrefMatcher != null) {
+                        description.appendText(" with href ");
+                        hrefMatcher.describeTo(description);
+                    }
+                    if (title != null) {
+                        description.appendText(" with title '").appendText(title).appendText("'");
+                    }
+                    if (titleMatcher != null) {
+                        description.appendText(" with title ");
+                        titleMatcher.describeTo(description);
+                    }
+                    if (httpMethod != null) {
+                        description.appendText(" with method '").appendValue(httpMethod).appendText("'");
+                    }
+                    if (mediaType != null) {
+                        description.appendText(" with type '").appendValue(mediaType).appendText("'");
+                    }
+                    if (typeParameterName != null) {
+                        description.appendText(" with media type parameter '").appendText(typeParameterName).appendText("=").appendText(typeParameterValue).appendText("'");
+                    }
+
+                    if (arguments != null) {
+                        description.appendText(" with arguments").appendText(arguments.toString());
+                    }
+
+                    if (novalue != null && novalue) {
+                        description.appendText(" with no value");
+                    }
+                    if (valueMatcher != null) {
+                        description.appendText(" with value ");
+                        valueMatcher.describeTo(description);
+                    }
+
+                    // trigger link being followed
+                    if (statusCode != null || selfHref != null) {
+                        if (client == null) {
+                            throw new IllegalStateException("require client in order to assert on statusCode");
+                        }
+                        description.appendText(" that when followed");
+                        if (statusCode != null) {
+                            description.appendText(" returns status " + statusCode);
+                        }
+                        if (statusCode != null || selfHref != null) {
+                            description.appendText(" and");
+                        }
+                        if (selfHref != null) {
+                            description.appendText(" has a response whose self.href is " + selfHref);
+                        }
+                    }
+                }
+
+                @Override
+                public boolean matchesSafely(final JsonRepresentation linkRepr) {
+                    if (linkRepr == null) {
+                        return false;
+                    }
+                    final LinkRepresentation link = linkRepr.asLink();
+                    if (rel != null && !Rel.parse(rel).matches(link.getRel())) {
+                        return false;
+                    }
+                    if (relNameMatcher != null && !relNameMatcher.matches(link.getRel())) {
+                        return false;
+                    }
+                    if (href != null && !href.equals(link.getHref())) {
+                        return false;
+                    }
+                    if (hrefMatcher != null && !hrefMatcher.matches(link.getHref())) {
+                        return false;
+                    }
+                    if (title != null && !title.equals(link.getTitle())) {
+                        return false;
+                    }
+                    if (titleMatcher != null && !titleMatcher.matches(link.getTitle())) {
+                        return false;
+                    }
+                    if (httpMethod != null && !httpMethod.equals(link.getHttpMethod())) {
+                        return false;
+                    }
+                    if (mediaType != null && !mediaType.isCompatible(mediaType)) {
+                        return false;
+                    }
+                    if (typeParameterName != null) {
+                        final MediaType mediaType = link.getType();
+                        final String parameterValue = mediaType.getParameters().get(typeParameterName);
+                        if (!typeParameterValue.equals(parameterValue)) {
+                            return false;
+                        }
+                    }
+                    if (novalue != null && novalue && link.getValue() != null) {
+                        return false;
+                    }
+                    if (arguments != null && !arguments.equals(link.getArguments())) {
+                        return false;
+                    }
+                    if (valueMatcher != null && !valueMatcher.matches(link.getValue())) {
+                        return false;
+                    }
+
+                    // follow link if criteria require it
+                    RestfulResponse<JsonRepresentation> jsonResp = null;
+                    if (statusCode != null || selfHref != null) {
+                        if (client == null) {
+                            return false;
+                        }
+                        try {
+                            jsonResp = client.followT(link);
+                        } catch (final Exception e) {
+                            throw new RuntimeException(e);
+                        }
+                    }
+
+                    // assertions based on provided criteria
+                    try {
+                        if (statusCode != null) {
+                            if (jsonResp.getStatus() != statusCode) {
+                                return false;
+                            }
+                        }
+                        if (selfHref != null) {
+                            JsonRepresentation entity;
+                            try {
+                                entity = jsonResp.getEntity();
+                            } catch (Exception e) {
+                                return false;
+                            }
+                            if(entity == null) {
+                                return false;
+                            }
+                            LinkRepresentation selfLink = entity.getLink("links[rel=self]");
+                            if(selfLink == null) {
+                                return false;
+                            }
+                            if (!selfLink.getHref().equals(selfHref)) {
+                                return false;
+                            }
+                        }
+                        return true;
+                    } finally {
+                        // flush any pending response
+                        try {
+                            jsonResp.getEntity();
+                        } catch (Exception e) {
+                            // ignore
+                        }
+                    }
+                }
+            };
+        }
+
+
+
+
+    }
+
+    public static EntryMatcherBuilder entry(final String key) {
+        return new EntryMatcherBuilder(key);
+    }
+
+    public static class EntryMatcherBuilder extends AbstractMatcherBuilder<JsonRepresentation> {
+
+        private final String key;
+        private String value;
+
+        private EntryMatcherBuilder(final String key) {
+            this.key = key;
+        }
+
+        public EntryMatcherBuilder value(final String value) {
+            this.value = value;
+            return this;
+        }
+
+        @Override
+        public Matcher<JsonRepresentation> build() {
+            return new TypeSafeMatcher<JsonRepresentation>() {
+
+                @Override
+                public void describeTo(final Description description) {
+                    description.appendText("map with entry with key: " + key);
+                    if (value != null) {
+                        description.appendText(", and value: " + value);
+                    }
+                }
+
+                @Override
+                public boolean matchesSafely(final JsonRepresentation item) {
+                    if (!item.isMap()) {
+                        return false;
+                    }
+                    final String val = item.getString(key);
+                    if (val == null) {
+                        return false;
+                    }
+                    if (value != null && !value.equals(val)) {
+                        return false;
+                    }
+                    return true;
+                }
+            };
+        }
+
+    }
+
+    public static Matcher<MediaType> hasMediaType(final String type) {
+        return new TypeSafeMatcher<MediaType>() {
+
+            @Override
+            public void describeTo(final Description description) {
+                description.appendText("has type " + type);
+            }
+
+            @Override
+            public boolean matchesSafely(final MediaType item) {
+                final String expectedType = item.getType();
+                return expectedType != null && type.contains(expectedType);
+            }
+        };
+    }
+
+    public static Matcher<MediaType> hasSubType(final String subtype) {
+        return new TypeSafeMatcher<MediaType>() {
+
+            @Override
+            public void describeTo(final Description description) {
+                description.appendText("has subtype " + subtype);
+            }
+
+            @Override
+            public boolean matchesSafely(final MediaType item) {
+                return Objects.equal(subtype, item.getSubtype());
+            }
+        };
+    }
+
+    public static Matcher<MediaType> hasParameter(final String parameterName, final String parameterValue) {
+        return new TypeSafeMatcher<MediaType>() {
+
+            @Override
+            public void describeTo(final Description description) {
+                description.appendText(String.format("has parameter '%s' with value '%s'", parameterName, parameterValue));
+            }
+
+            @Override
+            public boolean matchesSafely(final MediaType item) {
+                final String paramValue = item.getParameters().get(parameterName);
+                return Objects.equal(paramValue, parameterValue);
+            }
+        };
+    }
+
+    public static Matcher<CacheControl> hasMaxAge(final int maxAge) {
+        return new TypeSafeMatcher<CacheControl>() {
+
+            @Override
+            public void describeTo(final Description description) {
+                description.appendText("has max age of " + maxAge + " secs");
+            }
+
+            @Override
+            public boolean matchesSafely(final CacheControl item) {
+                return maxAge == item.getMaxAge();
+            }
+        };
+    }
+
+    public static Matcher<? super JsonRepresentation> mapHas(final String key) {
+        return new TypeSafeMatcher<JsonRepresentation>() {
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendText("is a map with key '" + key + "'");
+            }
+
+            @Override
+            protected boolean matchesSafely(JsonRepresentation item) {
+                return item.mapHas(key);
+            }
+        };
+    }
+
+    public static Matcher<? super MediaType> hasMediaTypeProfile(final String expectedMediaTypeAndProfileStr) {
+        final MediaType expectedMediaType = Header.CONTENT_TYPE.parse(expectedMediaTypeAndProfileStr);
+        final String expectedProfileIfAny = expectedMediaType.getParameters().get("profile");
+        return new TypeSafeMatcher<MediaType>() {
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendText("is a media type 'application/json' with a profile parameter of '" +  expectedMediaTypeAndProfileStr + '"');
+            }
+
+            @Override
+            protected boolean matchesSafely(MediaType item) {
+                
+                if (!item.isCompatible(expectedMediaType)) {
+                    return false;
+                }
+                String actualProfileIfAny = item.getParameters().get("profile");
+                return Objects.equal(expectedProfileIfAny, actualProfileIfAny);
+            }
+        };
+    }
+
+    public static Matcher<? super MediaType> hasMediaTypeXRoDomainType(final String expectedXRoDomainType) {
+        return new TypeSafeMatcher<MediaType>() {
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendText("is a media type with an 'x-ro-domain-type' parameter of '" +  expectedXRoDomainType + '"');
+            }
+
+            @Override
+            protected boolean matchesSafely(MediaType item) {
+                String actualXRoDomainTypeIfany = item.getParameters().get("x-ro-domain-type");
+                return actualXRoDomainTypeIfany != null && actualXRoDomainTypeIfany.contains(expectedXRoDomainType);
+            }
+        };
+    }
+
+    public static Matcher<? super MediaType> hasMediaTypeXRoElementType(final String expectedXRoElementTypeIfAny) {
+        return new TypeSafeMatcher<MediaType>() {
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendText("is a media type with an 'x-ro-element-type' parameter of '" +  expectedXRoElementTypeIfAny + '"');
+            }
+
+            @Override
+            protected boolean matchesSafely(MediaType item) {
+                String actualXRoElementTypeIfany = item.getParameters().get("x-ro-element-type");
+                return actualXRoElementTypeIfany != null && actualXRoElementTypeIfany.contains(expectedXRoElementTypeIfAny);
+            }
+        };
+    }
+
+    public static Matcher<? super RestfulResponse<?>> hasStatus(final HttpStatusCode statusCode) {
+        return new TypeSafeMatcher<RestfulResponse<?>>() {
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendText("has status code of " + statusCode);
+            }
+
+            @Override
+            protected boolean matchesSafely(RestfulResponse<?> item) {
+                return item.getStatus() == statusCode;
+            }
+        };
+    }
+
+    
+    public static class CacheControlMatcherBuilder extends AbstractMatcherBuilder<CacheControl> {
+
+        private Boolean noCache;
+
+        @Override
+        public Matcher<CacheControl> build() {
+            return new TypeSafeMatcher<CacheControl>() {
+
+                @Override
+                public void describeTo(Description description) {
+                    description.appendText("is a CacheControl header ");
+                    if(noCache != null) {
+                        description.appendText("with " + (noCache?"no":"") + " cache");
+                    }
+                }
+
+                @Override
+                protected boolean matchesSafely(CacheControl item) {
+                    if(noCache != null) {
+                        if(item.isNoCache() != noCache) {
+                            return false;
+                        }
+                    }
+                    return true;
+                }
+            };
+        }
+
+        public CacheControlMatcherBuilder withNoCache() {
+            noCache = true;
+            return this;
+        }
+        
+    }
+   
+}