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 2015/04/24 16:06:59 UTC

[1/3] isis git commit: ISIS-1139: adding javadoc for ObjectContracts, and adding convenience overloads...

Repository: isis
Updated Branches:
  refs/heads/master b2621d516 -> 5b4d05041


ISIS-1139: adding javadoc for ObjectContracts, and adding convenience overloads...

... because the current API is slightly non-intuitive


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

Branch: refs/heads/master
Commit: 8cec3ca88102025606d63e7dbada39157799e9e9
Parents: b2621d5
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Fri Apr 24 13:16:39 2015 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Fri Apr 24 13:24:22 2015 +0100

----------------------------------------------------------------------
 .../isis/applib/util/ObjectContracts.java       | 188 +++++++++++++++++--
 1 file changed, 171 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/8cec3ca8/core/applib/src/main/java/org/apache/isis/applib/util/ObjectContracts.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/util/ObjectContracts.java b/core/applib/src/main/java/org/apache/isis/applib/util/ObjectContracts.java
index 281fa52..c4160fe 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/util/ObjectContracts.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/util/ObjectContracts.java
@@ -17,10 +17,12 @@
 package org.apache.isis.applib.util;
 
 import java.lang.reflect.Method;
+import java.util.Arrays;
 import java.util.Comparator;
 import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+
 import com.google.common.base.Function;
 import com.google.common.base.Objects;
 import com.google.common.base.Objects.ToStringHelper;
@@ -34,17 +36,53 @@ import com.google.common.collect.Ordering;
 
 public class ObjectContracts {
 
+    //region > compare
+
+    /**
+     * Evaluates which of p and q is first.
+     *
+     * @deprecated - please be aware that this utility heavily uses reflection.  We don't actually intend to deprecate this method (it's useful while prototyping), but we wanted to bring this to your attention!
+     * @param propertyNames - the property name or names, CSV format.  If multiple properties, use the {@link #compare(Object, Object, String...) varargs} overloaded version of this method.
+     */
+    @Deprecated
     @SuppressWarnings("unchecked")
     public static <T> int compare(T p, T q, String propertyNames) {
+        final Iterable<String> propertyNamesIter = csvToIterable(propertyNames);
+        return compare(p, q, propertyNamesIter);
+    }
+
+    /**
+     * Evaluates which of p and q is first.
+     *
+     * @deprecated - please be aware that this utility heavily uses reflection.  We don't actually intend to deprecate this method (it's useful while prototyping), but we wanted to bring this to your attention!
+     */
+    @Deprecated
+    @SuppressWarnings("unchecked")
+    public static <T> int compare(T p, T q, String... propertyNames) {
+        final Iterable<String> propertyNamesIter = varargsToIterable(propertyNames);
+        return compare((T) p, (T) q, propertyNamesIter);
+    }
+
+    private static <T> int compare(final T p, final T q, final Iterable<String> propertyNamesIter) {
+        final Iterable<Clause> clauses = clausesFor(propertyNamesIter);
         ComparisonChain chain = ComparisonChain.start();
-        for (final Clause clause : iterable(propertyNames)) {
-            final Comparable<T> propertyValue = (Comparable<T>) clause.getValueOf(p);
-            final Comparable<T> propertyValue2 = (Comparable<T>) clause.getValueOf(q);
-            chain = chain.compare(propertyValue, propertyValue2, clause.getDirection().getOrdering());
+        for (final Clause clause : clauses) {
+            final Comparable<T> propertyValueOfP = (Comparable<T>) clause.getValueOf(p);
+            final Comparable<T> propertyValueOfQ = (Comparable<T>) clause.getValueOf(q);
+            chain = chain.compare(propertyValueOfP, propertyValueOfQ, clause.getDirection().getOrdering());
         }
         return chain.result();
     }
+    //endregion
 
+    //region > compareBy
+    /**
+     * Returns a {@link Comparator} to evaluate objects by their property name(s).
+     * @deprecated - please be aware that this utility heavily uses reflection.  We don't actually intend to deprecate this method (it's useful while prototyping), but we wanted to bring this to your attention!
+     * @param propertyNames - the property name or names, CSV format.  If multiple properties, use the {@link #compareBy(String...)} varargs} overloaded version of this method.
+     */
+    @Deprecated
+    @SuppressWarnings("unchecked")
     public static <T> Comparator<T> compareBy(final String propertyNames){
         return new Comparator<T>() {
             @Override
@@ -53,15 +91,68 @@ public class ObjectContracts {
             }
         };
     }
+    /**
+     * Returns a {@link Comparator} to evaluate objects by their property name(s).
+     * @deprecated - please be aware that this utility heavily uses reflection.  We don't actually intend to deprecate this method (it's useful while prototyping), but we wanted to bring this to your attention!
+     */
+    @Deprecated
+    @SuppressWarnings("unchecked")
+    public static <T> Comparator<T> compareBy(final String... propertyNames){
+        return new Comparator<T>() {
+            @Override
+            public int compare(T p, T q) {
+                return ObjectContracts.compare(p, q, propertyNames);
+            }
+        };
+    }
+    //endregion
 
+    //region > toString
 
+    /**
+     * Returns a string representation of the object consisting of the specified property name(s).
+     * @deprecated - please be aware that this utility heavily uses reflection.  We don't actually intend to deprecate this method (it's useful while prototyping), but we wanted to bring this to your attention!
+     * @param propertyNames - the property name or names, CSV format.  If multiple properties, use the {@link #toString(Object, String...)} varargs} overloaded version of this method.
+     */
+    @Deprecated
     public static String toString(Object p, String propertyNames) {
         return new ObjectContracts().toStringOf(p, propertyNames);
     }
-    
+    /**
+     * Returns a string representation of the object consisting of the specified property name(s).
+     * @deprecated - please be aware that this utility heavily uses reflection.  We don't actually intend to deprecate this method (it's useful while prototyping), but we wanted to bring this to your attention!
+     */
+    @Deprecated
+    public static String toString(Object p, String... propertyNames) {
+        return new ObjectContracts().toStringOf(p, propertyNames);
+    }
+    //endregion
+
+    //region > hashCode
+    /**
+     * Returns the hashCode for the object using the specified property name(s).
+     * @deprecated - please be aware that this utility heavily uses reflection.  We don't actually intend to deprecate this method (it's useful while prototyping), but we wanted to bring this to your attention!
+     * @param propertyNames - the property name or names, CSV format.  If multiple properties, use the {@link #hashCode(Object, String...)} varargs} overloaded version of this method.
+     */
+    @Deprecated
     public static int hashCode(Object obj, String propertyNames) {
+        final Iterable<String> propertyNamesIter = csvToIterable(propertyNames);
+        return hashCode(obj, propertyNamesIter);
+    }
+
+    /**
+     * Returns the hashCode for the object using the specified property name(s).
+     * @deprecated - please be aware that this utility heavily uses reflection.  We don't actually intend to deprecate this method (it's useful while prototyping), but we wanted to bring this to your attention!
+     */
+    @Deprecated
+    public static int hashCode(Object obj, String... propertyNames) {
+        final Iterable<String> propertyNamesIter = varargsToIterable(propertyNames);
+        return hashCode(obj, propertyNamesIter);
+    }
+
+    private static int hashCode(final Object obj, final Iterable<String> propertyNamesIter) {
         final List<Object> propertyValues = Lists.newArrayList();
-        for (final Clause clause : iterable(propertyNames)) {
+        for (final Clause clause : clausesFor(propertyNamesIter)) {
             final Object propertyValue = clause.getValueOf(obj);
             if(propertyValue != null) {
                 propertyValues.add(propertyValue);
@@ -69,7 +160,16 @@ public class ObjectContracts {
         }
         return Objects.hashCode(propertyValues.toArray());
     }
+    //endregion
+
+    //region > equals
 
+    /**
+     * Returns whether two objects are equal, considering just the specified property name(s).
+     * @deprecated - please be aware that this utility heavily uses reflection.  We don't actually intend to deprecate this method (it's useful while prototyping), but we wanted to bring this to your attention!
+     * @param propertyNames - the property name or names, CSV format.  If multiple properties, use the {@link #equals(Object, Object, String...)} varargs} overloaded version of this method.
+     */
+    @Deprecated
     public static boolean equals(Object p, Object q, String propertyNames) {
         if(p==null && q==null) {
             return true;
@@ -80,19 +180,45 @@ public class ObjectContracts {
         if(p.getClass() != q.getClass()) {
             return false;
         }
-        for (final Clause clause : iterable(propertyNames)) {
+        final Iterable<String> propertyNamesIter = csvToIterable(propertyNames);
+        return equals(p, q, propertyNamesIter);
+    }
+
+    /**
+     * Returns whether two objects are equal, considering just the specified property name(s).
+     * @deprecated - please be aware that this utility heavily uses reflection.  We don't actually intend to deprecate this method (it's useful while prototyping), but we wanted to bring this to your attention!
+     */
+    @Deprecated
+    public static boolean equals(Object p, Object q, String... propertyNames) {
+        if(p==null && q==null) {
+            return true;
+        }
+        if(p==null || q==null) {
+            return false;
+        }
+        if(p.getClass() != q.getClass()) {
+            return false;
+        }
+        final Iterable<String> propertyNamesIter = varargsToIterable(propertyNames);
+        return equals(p, q, propertyNamesIter);
+    }
+
+    private static boolean equals(final Object p, final Object q, final Iterable<String> propertyNamesIter) {
+        final Iterable<Clause> clauses = clausesFor(propertyNamesIter);
+        for (final Clause clause : clauses) {
             final Object pValue = clause.getValueOf(p);
             final Object qValue = clause.getValueOf(q);
-            if(!Objects.equal(pValue,qValue)) {
+            if(!Objects.equal(pValue, qValue)) {
                 return false;
             }
         }
         return true;
     }
-    // //////////////////////////////////////
-    
-    private static Iterable<Clause> iterable(String propertyNames) {
-        return Iterables.transform(Splitter.on(',').split(propertyNames), new Function<String,Clause>() {
+    //endregion
+
+    //region > helpers
+    private static Iterable<Clause> clausesFor(final Iterable<String> iterable) {
+        return Iterables.transform(iterable, new Function<String, Clause>() {
             @Override
             public Clause apply(String input) {
                 return Clause.parse(input);
@@ -100,15 +226,22 @@ public class ObjectContracts {
         });
     }
 
-    // //////////////////////////////////////
+    private static Iterable<String> csvToIterable(final String propertyNames) {
+        return Splitter.on(',').split(propertyNames);
+    }
+
+    private static List<String> varargsToIterable(final String[] iterable) {
+        return Arrays.asList(iterable);
+    }
+    //endregion
+
+    //region > toStringOf
 
     public interface ToStringEvaluator {
         boolean canEvaluate(Object o);
         String evaluate(Object o);
     }
     
-    // //////////////////////////////////////
-
     private final List<ToStringEvaluator> evaluators = Lists.newArrayList();
 
     public ObjectContracts with(ToStringEvaluator evaluator) {
@@ -116,9 +249,30 @@ public class ObjectContracts {
         return this;
     }
 
+    /**
+     * Returns a string representation of two objects, considering just the specified property name(s).
+     * @deprecated - please be aware that this utility heavily uses reflection.  We don't actually intend to deprecate this method (it's useful while prototyping), but we wanted to bring this to your attention!
+     * @param propertyNames - the property name or names, CSV format.  If multiple properties, use the {@link #toString(Object, String...)} varargs} overloaded version of this method.
+     */
+    @Deprecated
     public String toStringOf(Object p, String propertyNames) {
+        final Iterable<String> propertyNamesIter = csvToIterable(propertyNames);
+        return toStringOf(p, propertyNamesIter);
+    }
+
+    /**
+     * Returns a string representation of two objects, considering just the specified property name(s).
+     * @deprecated - please be aware that this utility heavily uses reflection.  We don't actually intend to deprecate this method (it's useful while prototyping), but we wanted to bring this to your attention!
+     */
+    @Deprecated
+    public String toStringOf(Object p, String... propertyNames) {
+        final Iterable<String> propertyNamesIter = varargsToIterable(propertyNames);
+        return toStringOf(p, propertyNamesIter);
+    }
+
+    private String toStringOf(final Object p, final Iterable<String> propertyNamesIter) {
         final ToStringHelper stringHelper = Objects.toStringHelper(p);
-        for (final Clause clause : iterable(propertyNames)) {
+        for (final Clause clause : clausesFor(propertyNamesIter)) {
             stringHelper.add(clause.getPropertyName(), asString(clause, p));
         }
         return stringHelper.toString();
@@ -137,9 +291,9 @@ public class ObjectContracts {
         return value.toString();
     }
 
+    //endregion
 
 
-    
 }
 class Clause {
     private static Pattern pattern = Pattern.compile("\\W*(\\w+)\\W*(asc|asc nullsFirst|asc nullsLast|desc|desc nullsFirst|desc nullsLast)?\\W*");


[3/3] isis git commit: Merge branch 'ISIS-1139'

Posted by da...@apache.org.
Merge branch 'ISIS-1139'


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

Branch: refs/heads/master
Commit: 5b4d050414de4b416cf8f795eafca8ffcc9e1bac
Parents: b2621d5 5e33aa8
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Fri Apr 24 15:05:56 2015 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Fri Apr 24 15:05:56 2015 +0100

----------------------------------------------------------------------
 ...-guide-reference-applib-utility-classes.adoc | 138 ++++++++++++-
 .../user-guide-reference-cmd-line-args.adoc     |  15 ++
 .../user-guide-reference-web-xml.adoc           |   8 +
 .../user-guide/user-guide-reference.adoc        |   6 +-
 ...er-guide-testing-bdd-integ-test-support.adoc |   7 +
 .../user-guide-testing-fake-data.adoc           |  11 +
 .../user-guide-testing-fixture-scripts.adoc     |  65 ++++++
 .../user-guide-testing-integ-test-support.adoc  |  19 ++
 .../user-guide-testing-unit-test-support.adoc   | 200 +++++++++++++++++++
 .../asciidoc/user-guide/user-guide-testing.adoc |  62 +-----
 adocs/template/document.html.erb                |  22 +-
 .../isis/applib/util/ObjectContracts.java       | 188 +++++++++++++++--
 12 files changed, 662 insertions(+), 79 deletions(-)
----------------------------------------------------------------------



[2/3] isis git commit: ISIS-1139: updating asciidocs with info on ObjectContracts.

Posted by da...@apache.org.
ISIS-1139: updating asciidocs with info on ObjectContracts.


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

Branch: refs/heads/master
Commit: 5e33aa8e61519514c9d4ed18d5505a8a231f9898
Parents: 8cec3ca
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Fri Apr 24 15:05:35 2015 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Fri Apr 24 15:05:35 2015 +0100

----------------------------------------------------------------------
 ...-guide-reference-applib-utility-classes.adoc | 138 ++++++++++++-
 .../user-guide-reference-cmd-line-args.adoc     |  15 ++
 .../user-guide-reference-web-xml.adoc           |   8 +
 .../user-guide/user-guide-reference.adoc        |   6 +-
 ...er-guide-testing-bdd-integ-test-support.adoc |   7 +
 .../user-guide-testing-fake-data.adoc           |  11 +
 .../user-guide-testing-fixture-scripts.adoc     |  65 ++++++
 .../user-guide-testing-integ-test-support.adoc  |  19 ++
 .../user-guide-testing-unit-test-support.adoc   | 200 +++++++++++++++++++
 .../asciidoc/user-guide/user-guide-testing.adoc |  62 +-----
 adocs/template/document.html.erb                |  22 +-
 11 files changed, 491 insertions(+), 62 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/5e33aa8e/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference-applib-utility-classes.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference-applib-utility-classes.adoc b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference-applib-utility-classes.adoc
index 175dbfc..f684ebe 100644
--- a/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference-applib-utility-classes.adoc
+++ b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference-applib-utility-classes.adoc
@@ -3,6 +3,142 @@
 :_basedir: ../
 :_imagesdir: images/
 
-IMPORTANT: TODO
+The `org.apache.isis.applib.util` package has a number of simple utility
+classes designed to simplify the coding of some common tasks.
 
+== Title creation
 
+The `TitleBuffer` utility class is intended to make it easy to construct
+title strings (returned from the `title()` method). For example, it has
+overloaded versions of methods called `append()` and `concat()`.
+
+== Reason text creation (for disable and validate methods)
+
+There are two different classes provided to help build reasons returned
+by `disableXxX()` and `validateXxx()` methods:
+
+* the `org.apache.isis.applib.util.ReasonBuffer` helper class
+* the `org.apache.isis.applib.util.Reasons` helper class
+
+For example:
+
+[source,java]
+----
+public class Customer {
+    ...
+    public String validatePlaceOrder(Product p, int quantity) {
+        return Reasons.coalesce(
+            whetherCustomerBlacklisted(this),
+            whetherProductOutOfStock(p)
+        );
+    }
+}
+----
+
+Which you use (if any) is up to you.
+
+== ObjectContracts
+
+The `ObjectContracts` test provides a series of methods to make it easy for your domain objects to:
+
+* implement `Comparable` (eg so can be stored in ``java.util.SortedSet``s)
+* implement `toString()`
+* implement `equals()`
+* implement `hashCode()`
+
+For example:
+
+[source,java]
+----
+public class ToDoItem implements Comparable<ToDoItem> {
+
+    public boolean isComplete() { ... }
+    public LocalDate getDueBy() { ... }
+    public String getDescription() { ... }
+    public String getOwnedBy() { ... }
+
+    public int compareTo(final ToDoItem other) {
+        return ObjectContracts.compare(this, other, "complete","dueBy","description");
+    }
+
+    public String toString() {
+        return ObjectContracts.toString(this, "description","complete","dueBy","ownedBy");
+    }
+}
+----
+
+[WARNING]
+====
+Note that `ObjectContracts` makes heavy use of Java Reflection.  While it's great to get going quickly in prototyping, we recommend you use your IDE to code generate implementations of these methods for production code.
+
+Moreover (and perhaps even more importantly) `ObjectContracts` implementation can cause DataNucleus to recursively rehydrate a larger number of associated entities (More detail below).
+
+We therefore recommend that you disable persistence-by-reachability by adding:
+
+[source,ini]
+.persistor_datanucleus.properties
+----
+#
+# Require explicit persistence (since entities are Comparable and using ObjectContracts#compareTo).
+#
+isis.persistor.datanucleus.impl.datanucleus.persistenceByReachabilityAtCommit=false
+----
+
+====
+
+### Explanation of the issue in more detail
+
+Consider the entities:
+
+    Party <->* AgreementRole <*-> Agreement
+
+In the course of a transaction, the `Agreement` entity is loaded into memory (not necessarily modified), and then new ``AgreementRole``s are associated to it.
+
+All these entities implement `Comparable` using `ObjectContracts`, so that the implementation of ``AgreementRole``'s (simplified) is:
+
+[source,java]
+----
+public class AgreementRole {
+    ...
+    public int compareTo(AgreementRole other) {
+        return ObjectContracts.compareTo(this, other, "agreement","startDate","party");
+    }
+    ...
+}
+----
+
+while ``Agreement``'s is implemented as:
+
+[source,java]
+----
+    public class Agreement {
+        ...
+        public int compareTo(Agreement other) {
+            return ObjectContracts.compareTo(this, other, "reference");
+        }
+        ...
+    }
+----
+
+and ``Party``'s is similarly implemented as:
+
+[source,java]
+----
+public class Party {
+    ...
+    public int compareTo(Party other) {
+        return ObjectContracts.compareTo(this, other, "reference");
+    }
+    ...
+}
+----
+
+DataNucleus's persistence-by-reachability algorithm adds the ``AgreementRole``s into a `SortedSet`, which causes `AgreementRole#compareTo()` to fire:
+
+* the evaluation of the "agreement" property delegates back to the `Agreement`, whose own `Agreement#compareTo()` uses the scalar `reference` property.  As the `Agreement` is already in-memory, this does not trigger any further database queries
+
+* the evaluation of the "startDate" property is just a scalar property of the `AgreementRole`, so will already in-memory
+
+* the evaluation of the "party" property delegates back to the `Party`, whose own `Party#compareTo()` requires the uses the scalar `reference` property.  However, since the `Party` is not yet in-memory, using the `reference` property triggers a database query to "rehydrate" the `Party` instance.
+
+In other words, figuring out whether `AgreementRole` is comparable requires the persistence-by-reachability algorithm to run, causing the adjacent associated entity `Party` to also be retrieved.

http://git-wip-us.apache.org/repos/asf/isis/blob/5e33aa8e/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference-cmd-line-args.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference-cmd-line-args.adoc b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference-cmd-line-args.adoc
new file mode 100644
index 0000000..06e5cc8
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference-cmd-line-args.adoc
@@ -0,0 +1,15 @@
+= Command Line Arguments
+:Notice: 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.
+:_basedir: ../
+:_imagesdir: images/
+
+IMPORTANT: TODO
+
+
+## `org.apache.isis.WebServer`
+
+For example:
+* `--fixture`
+* `--services`
+
+etc...
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/5e33aa8e/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference-web-xml.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference-web-xml.adoc b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference-web-xml.adoc
new file mode 100644
index 0000000..bc6da88
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference-web-xml.adoc
@@ -0,0 +1,8 @@
+= web.xml Configuration
+:Notice: 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.
+:_basedir: ../
+:_imagesdir: images/
+
+IMPORTANT: TODO
+
+

http://git-wip-us.apache.org/repos/asf/isis/blob/5e33aa8e/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference.adoc b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference.adoc
index 07ed17d..caea6de 100644
--- a/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference.adoc
+++ b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference.adoc
@@ -15,9 +15,11 @@ include::user-guide-reference-domain-services.adoc[leveloffset=+1]
 
 include::user-guide-reference-value-types.adoc[leveloffset=+1]
 
-## Applib Utility Classes
-
 include::user-guide-reference-applib-utility-classes.adoc[leveloffset=+1]
 
 include::user-guide-reference-convenience-superclasses.adoc[leveloffset=+1]
 
+include::user-guide-reference-cmd-line-args.adoc[leveloffset=+1]
+
+include::user-guide-reference-web-xml.adoc[leveloffset=+1]
+

http://git-wip-us.apache.org/repos/asf/isis/blob/5e33aa8e/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-bdd-integ-test-support.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-bdd-integ-test-support.adoc b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-bdd-integ-test-support.adoc
new file mode 100644
index 0000000..714abc5
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-bdd-integ-test-support.adoc
@@ -0,0 +1,7 @@
+= BDD/Integ Test Support
+:Notice: 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.
+:_basedir: ../
+:_imagesdir: images/
+
+IMPORTANT: TODO
+

http://git-wip-us.apache.org/repos/asf/isis/blob/5e33aa8e/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-fake-data.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-fake-data.adoc b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-fake-data.adoc
new file mode 100644
index 0000000..a31b65b
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-fake-data.adoc
@@ -0,0 +1,11 @@
+= Fake Data
+:Notice: 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.
+:_basedir: ../
+:_imagesdir: images/
+
+IMPORTANT: TODO
+
+WARN: Isis Addons, not ASF.
+
+link:https://github.com/isisaddons/isis-module-fakedata
+

http://git-wip-us.apache.org/repos/asf/isis/blob/5e33aa8e/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-fixture-scripts.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-fixture-scripts.adoc b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-fixture-scripts.adoc
new file mode 100644
index 0000000..d4d3ffe
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-fixture-scripts.adoc
@@ -0,0 +1,65 @@
+= Fixture Scripts
+:Notice: 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.
+:_basedir: ../
+:_imagesdir: images/
+
+IMPORTANT: TODO
+
+
+## API and Usage
+
+IMPORTANT: TODO
+
+## SudoService (1.9.0-SNAPSHOT)
+
+Sometimes in our fixture scripts we want to perform a business action runnin as a particular user.  This might be for the usual reason - so that our fixtures accurately reflect the reality of the system with all business constraints enforced using the `WrapperFactory` - or more straightforwardly it might be simply that the action depends on the identity of the user invoking the action.
+
+An example of the latter case is in the link:[todoapp]'s `ToDoItem` class:
+
+[source,java]
+.Production code that depends on current user
+----
+public ToDoItem newToDo(
+        @Parameter(regexPattern = "\\w[@&:\\-\\,\\.\\+ \\w]*") @ParameterLayout(named="Description")
+        final String description,
+        @ParameterLayout(named="Category")
+        final Category category,
+        @Parameter(optionality = Optionality.OPTIONAL) @ParameterLayout(named="Subcategory")
+        final Subcategory subcategory,
+        @Parameter(optionality = Optionality.OPTIONAL) @ParameterLayout(named="Due by")
+        final LocalDate dueBy,
+        @Parameter(optionality = Optionality.OPTIONAL) @ParameterLayout(named="Cost")
+        final BigDecimal cost) {
+    return newToDo(description, category, subcategory, currentUserName(), dueBy, cost);
+}
+private String currentUserName() {
+    return container.getUser().getName(); // <1>
+}
+----
+<1> is the current user.
+
+The fixture for this can use the `SudoService` to run a block of code as a specified user:
+
+[source,java]
+.Fixture Script
+----
+final String description = ...
+final Category category = ...
+final Subcategory subcategory = ...
+final LocalDate dueBy = ...
+final BigDecimal cost = ...
+final Location location = ...
+
+toDoItem = sudoService.sudo(username,
+        new Callable<ToDoItem>() {
+            @Override
+            public ToDoItem call() {
+                final ToDoItem toDoItem = wrap(toDoItems).newToDo(
+                        description, category, subcategory, dueBy, cost);
+                wrap(toDoItem).setLocation(location);
+                return toDoItem;
+            }
+        });
+----
+
+Behind the scenes the `SudoService` simply talks to the `DomainObjectContainer` to override the user returned by the `getUser()` API.  It is possible to override both users and roles.

http://git-wip-us.apache.org/repos/asf/isis/blob/5e33aa8e/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-integ-test-support.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-integ-test-support.adoc b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-integ-test-support.adoc
new file mode 100644
index 0000000..399c2e7
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-integ-test-support.adoc
@@ -0,0 +1,19 @@
+= Integration Test Support
+:Notice: 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.
+:_basedir: ../
+:_imagesdir: images/
+
+IMPORTANT: TODO
+
+
+## Introduction
+
+IMPORTANT: TODO
+
+## Using the WrapperFactory
+
+IMPORTANT: TODO
+
+## IsisConfigurationForJdoIntegTests
+
+IMPORTANT: TODO

http://git-wip-us.apache.org/repos/asf/isis/blob/5e33aa8e/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-unit-test-support.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-unit-test-support.adoc b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-unit-test-support.adoc
new file mode 100644
index 0000000..fefae90
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-unit-test-support.adoc
@@ -0,0 +1,200 @@
+= Unit Test Support
+:Notice: 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.
+:_basedir: ../
+:_imagesdir: images/
+
+Isis Core provides a number of unit test helpers for you to use (if you wish) to test your domain objects.  To use, update the `pom.xml`:
+
+[source,xml]
+----
+<dependency>
+    <groupId>org.apache.isis.core</groupId>
+    <artifactId>isis-core-unittestsupport</artifactId>
+    <scope>test</scope> // <1>
+</dependency>
+----
+<1> Normally `test`; usual Maven scoping rules apply.
+
+
+
+== ``SortedSet``s Contract Test
+
+This contract test automatically checks that all fields of type `java.util.Collection` are declared as `java.util.SortedSet`. In other words, it precludes either `java.util.List` or `java.util.Set` from being used as a collection.
+
+For example, the following passes the contract test:
+
+[source,java]
+----
+public class Department {
+    private SortedSet<Employee> employees = new TreeSet<Employee>();
+    ...
+}
+----
+
+whereas this would not:
+
+[source,java]
+----
+public class SomeDomainObject {
+    private List<Employee> employees = new ArrayList<Employee>();
+    ...
+}
+----
+
+If using the JDO/DataNucleus Objectstore then we strongly recommend that you implement this test, for several reasons:
+
+* First, ``Set``s align more closely to the relational model than do `List`s. A `List` must have an additional index to specify order.
+
+* Second, `SortedSet` is preferable to `Set` because then the order is well-defined and predictable (to an end user, to the programmer).
+
+The <<ObjectContracts>> utility class substantially simplifies the task of implementing `Comparable` in your domain classes.
+
+* Third, if the relationship is bidirectional then JDO/Objectstore will automatically maintain the relationship. See link:../components/objectstores/jdo/managed-1-to-m-relationships.html[here] for further discussion.
+
+To use the contract test, subclass `SortedSetsContractTestAbstract`, specifying the root package to search for domain classes.
+
+For example:
+
+[source,java]
+----
+public class SortedSetsContractTestAll extends SortedSetsContractTestAbstract {
+
+    public SortedSetsContractTestAll() {
+        super("org.estatio.dom");
+        withLoggingTo(System.out);
+    }
+}
+----
+
+
+
+
+== Injected Services Method Contract Test
+
+It is quite common for some basic services to be injected in a project-specific domain object superclass; for example a `ClockService` might generally be injected everywhere:
+
+[source,java]
+----
+public abstract class EstatioDomainObject {
+    protected ClockService clockService;
+    public void injectClockService(ClockService clockService) {
+        this.clockService = clockService;
+    }
+}
+----
+
+If a subclass inadvertantly overrides this method and provides its own `ClockService` field, then the field in the superclass will never initialized. As you might imagine, ``NullPointerException``s could then arise.
+
+This contract test automatically checks that the `injectXxx(...)` method, to allow for injected services, is not overridable, ie `final`.
+
+To use the contract test, , subclass `SortedSetsContractTestAbstract`, specifying the root package to search for domain classes.
+
+For example:
+
+[source,java]
+----
+public class InjectServiceMethodMustBeFinalContractTestAll extends InjectServiceMethodMustBeFinalContractTestAbstract {
+
+    public InjectServiceMethodMustBeFinalContractTestAll() {
+        super("org.estatio.dom");
+        withLoggingTo(System.out);
+    }
+}
+----
+
+
+
+
+== Bidirectional Contract Test
+
+This contract test automatically checks that bidirectional 1:m or 1:1 associations are being maintained correctly (assuming that they follow the link:../more-advanced-topics/how-to-04-060-How-to-set-up-and-maintain-bidirectional-relationships.html[mutual registration pattern]
+
+TIP: If using the link:../components/objectstores/jdo/about.html[JDO Object Store], then there is generally no need to programmatically maintain 1:m relationships (indeed it may introduce subtle errors). For more details, see link:../components/objectstores/jdo/managed-1-to-m-relationships.html[here]. Check out the link:../intro/resources/editor-templates.html[Eclipse templates] for further guidance.
+
+For example, suppose that `ParentDomainObject` and `ChildDomainObject` have a 1:m relationship (`ParentDomainObject#children` / `ChildDomainObject#parent`), and also `PeerDomainObject` has a 1:1 relationship with itself (`PeerDomainObject#next` / `PeerDomainObject#previous`).
+
+The following will exercise these relationships:
+
+[source,java]
+----
+public class BidirectionalRelationshipContractTestAll
+        extends BidirectionalRelationshipContractTestAbstract {
+
+    public BidirectionalRelationshipContractTestAll() {
+        super("org.apache.isis.core.unittestsupport.bidir",
+                ImmutableMap.<Class<?>,Instantiator>of(
+                    ChildDomainObject.class, new InstantiatorForChildDomainObject(),
+                    PeerDomainObject.class, new InstantiatorSimple(PeerDomainObjectForTesting.class)
+                ));
+        withLoggingTo(System.out);
+    }
+}
+----
+
+The first argument to the constructor scopes the search for domain objects; usually this would be something like `&quot;com.mycompany.dom&quot;`.
+
+The second argument provides a map of `Instantiator` for certain of the domain object types. This has two main purposes. First, for abstract classes, it nominates an alternative concrete class to be instantiated. Second, for classes (such as `ChildDomainObject`) that are `Comparable` and are held in a `SortedSet`), it provides the ability to ensure that different instances are unique when compared against each other. If no `Instantiator` is provided, then the contract test simply attempts to instantiates the class.
+
+If any of the supporting methods (`addToXxx()`, `removeFromXxx()`, `modifyXxx()` or `clearXxx()`) are missing, the relationship is skipped.
+
+To see what's going on (and to identify any skipped relationships), use the `withLoggingTo()` method call. If any assertion fails then the error should be descriptive enough to figure out the problem (without enabling logging).
+
+The example tests can be found https://github.com/apache/isis/tree/master/core/unittestsupport/src/test/java/org/apache/isis/core/unittestsupport/bidir[here].
+
+
+
+
+== JMock Extensions
+
+`JUnitRuleMockery2` is an extension to the JMock's `JunitRuleMockery`, providing a simpler API and also providing support for autowiring.
+
+For example, here we see that the class under test, an instance of `CollaboratingUsingSetterInjection`, is automatically wired up with its `Collaborator`:
+
+[source,java]
+----
+public class JUnitRuleMockery2Test_autoWiring_setterInjection_happyCase {
+
+    @Rule
+    public JUnitRuleMockery2 context = JUnitRuleMockery2.createFor(Mode.INTERFACES_AND_CLASSES);
+
+    @Mock
+    private Collaborator collaborator;
+
+    @ClassUnderTest
+    private CollaboratingUsingSetterInjection collaborating;
+
+    @Test
+    public void wiring() {
+        assertThat(collaborating.collaborator, is(not(nullValue())));
+    }
+}
+----
+
+The example tests can be found https://github.com/apache/isis/tree/master/core/unittestsupport/src/test/java/org/apache/isis/core/unittestsupport/jmocking[here]
+
+
+
+
+== Value Objects Contract Test
+
+The `ValueTypeContractTestAbstract` automatically tests that a custom value type implements `equals()` and `hashCode()` correctly.
+
+For example, testing JDK's own `java.math.BigInteger` can be done as follows:
+
+[source,java]
+----
+public class ValueTypeContractTestAbstract_BigIntegerTest extends ValueTypeContractTestAbstract<BigInteger> {
+
+    @Override
+    protected List<BigInteger> getObjectsWithSameValue() {
+        return Arrays.asList(new BigInteger("1"), new BigInteger("1"));
+    }
+
+    @Override
+    protected List<BigInteger> getObjectsWithDifferentValue() {
+        return Arrays.asList(new BigInteger("2"));
+    }
+}
+----
+
+The example unit tests can be found https://github.com/apache/isis/tree/master/core/unittestsupport/src/test/java/org/apache/isis/core/unittestsupport/value[here].
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/5e33aa8e/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing.adoc b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing.adoc
index d7be033..bc2c280 100644
--- a/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing.adoc
+++ b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing.adoc
@@ -5,70 +5,18 @@
 
 IMPORTANT: TODO
 
-## Unit Test Support
+include::user-guide-testing-unit-test-support.adoc[leveloffset=+1]
 
-## Integration Test Support
+include::user-guide-testing-integ-test-support.adoc[leveloffset=+1]
 
-## BDD/Integ Test Support
+include::user-guide-testing-bdd-integ-test-support.adoc[leveloffset=+1]
 
-## Fixture Scripts
+include::user-guide-testing-fixture-scripts.adoc[leveloffset=+1]
 
-## SudoService (1.9.0-SNAPSHOT)
+include::user-guide-testing-fake-data.adoc[leveloffset=+1]
 
-Sometimes in our fixture scripts we want to perform a business action runnin as a particular user.  This might be for the usual reason - so that our fixtures accurately reflect the reality of the system with all business constraints enforced using the `WrapperFactory` - or more straightforwardly it might be simply that the action depends on the identity of the user invoking the action.
 
-An example of the latter case is in the link:[todoapp]'s `ToDoItem` class:
 
-[source,java]
-.Production code that depends on current user
-----
-public ToDoItem newToDo(
-        @Parameter(regexPattern = "\\w[@&:\\-\\,\\.\\+ \\w]*") @ParameterLayout(named="Description")
-        final String description,
-        @ParameterLayout(named="Category")
-        final Category category,
-        @Parameter(optionality = Optionality.OPTIONAL) @ParameterLayout(named="Subcategory")
-        final Subcategory subcategory,
-        @Parameter(optionality = Optionality.OPTIONAL) @ParameterLayout(named="Due by")
-        final LocalDate dueBy,
-        @Parameter(optionality = Optionality.OPTIONAL) @ParameterLayout(named="Cost")
-        final BigDecimal cost) {
-    return newToDo(description, category, subcategory, currentUserName(), dueBy, cost);
-}
-private String currentUserName() {
-    return container.getUser().getName(); // <1>
-}
-----
-<1> is the current user.
 
-The fixture for this can use the `SudoService` to run a block of code as a specified user:
-
-[source,java]
-.Fixture Script
-----
-final String description = ...
-final Category category = ...
-final Subcategory subcategory = ...
-final LocalDate dueBy = ...
-final BigDecimal cost = ...
-final Location location = ...
-
-toDoItem = sudoService.sudo(username,
-        new Callable<ToDoItem>() {
-            @Override
-            public ToDoItem call() {
-                final ToDoItem toDoItem = wrap(toDoItems).newToDo(
-                        description, category, subcategory, dueBy, cost);
-                wrap(toDoItem).setLocation(location);
-                return toDoItem;
-            }
-        });
-----
-
-Behind the scenes the `SudoService` simply talks to the `DomainObjectContainer` to override the user returned by the `getUser()` API.  It is possible to override both users and roles.
-
-## IsisConfigurationForJdoIntegTests
-
-## Isis CmdLine Arguments (for prototyping)
 
 

http://git-wip-us.apache.org/repos/asf/isis/blob/5e33aa8e/adocs/template/document.html.erb
----------------------------------------------------------------------
diff --git a/adocs/template/document.html.erb b/adocs/template/document.html.erb
index 2986460..6106875 100644
--- a/adocs/template/document.html.erb
+++ b/adocs/template/document.html.erb
@@ -108,6 +108,19 @@
         }
     </style>
 
+    <style>
+        /* overriding colony.css stylesheet */
+        .literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] {
+           /*padding: 1.25em 1.5625em 1.125em 1.5625em;*/
+           padding: 0.3em 0.6em 0.25em 0.6em;
+        }
+        @media only screen and (min-width: 1280px)
+        #toc.toc2 {
+          /*width: 20em;*/
+          width: 25em;
+        }
+    </style>
+
 </head>
 <body>
 
@@ -214,7 +227,7 @@
 </div>
 
 <div class="row">
-    <div class="large-9 medium-9 columns">
+    <div class="large-12 medium-12 columns">
 
         <div id="doc-content">
           <%= document.content %>
@@ -231,11 +244,16 @@
 
     </div>
 
-    <div class="large-3 medium-3 columns">
+    <!--
+    as a column to the right
+    (previous was using foundation in a 9:3 ratio with the content, above... decided was too crammed.
+    -->
+    <div class="xlarge-3 xmedium-3 xcolumns">
         <div id="toc" class="<%= attr 'toc-class', 'toc2' %>">
           <%= converter.convert_with_options @document, 'outline', :toclevels => 6  %>
         </div>
     </div>
+
 </div>