http://git-wip-us.apache.org/repos/asf/isis/blob/a4ec0b72/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItem.java
----------------------------------------------------------------------
diff --git 
a/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItem.java 
b/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItem.java
deleted file mode 100644
index 75f5583..0000000
--- a/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItem.java
+++ /dev/null
@@ -1,979 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package dom.todo;
-
-import java.math.BigDecimal;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import javax.jdo.JDOHelper;
-import javax.jdo.annotations.IdentityType;
-import javax.jdo.annotations.VersionStrategy;
-import com.google.common.base.Objects;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Ordering;
-import org.joda.time.LocalDate;
-import org.apache.isis.applib.DomainObjectContainer;
-import org.apache.isis.applib.Identifier;
-import org.apache.isis.applib.NonRecoverableException;
-import org.apache.isis.applib.RecoverableException;
-import org.apache.isis.applib.annotation.Action;
-import org.apache.isis.applib.annotation.BookmarkPolicy;
-import org.apache.isis.applib.annotation.Collection;
-import org.apache.isis.applib.annotation.CollectionLayout;
-import org.apache.isis.applib.annotation.DomainObject;
-import org.apache.isis.applib.annotation.DomainObjectLayout;
-import org.apache.isis.applib.annotation.Editing;
-import org.apache.isis.applib.annotation.RestrictTo;
-import org.apache.isis.applib.annotation.InvokeOn;
-import org.apache.isis.applib.annotation.InvokedOn;
-import org.apache.isis.applib.annotation.Optionality;
-import org.apache.isis.applib.annotation.Parameter;
-import org.apache.isis.applib.annotation.ParameterLayout;
-import org.apache.isis.applib.annotation.Programmatic;
-import org.apache.isis.applib.annotation.Property;
-import org.apache.isis.applib.annotation.SemanticsOf;
-import org.apache.isis.applib.annotation.Where;
-import org.apache.isis.applib.security.UserMemento;
-import org.apache.isis.applib.services.actinvoc.ActionInvocationContext;
-import org.apache.isis.applib.services.eventbus.ActionDomainEvent;
-import org.apache.isis.applib.services.eventbus.EventBusService;
-import org.apache.isis.applib.services.scratchpad.Scratchpad;
-import org.apache.isis.applib.services.wrapper.HiddenException;
-import org.apache.isis.applib.services.wrapper.WrapperFactory;
-import org.apache.isis.applib.util.ObjectContracts;
-import org.apache.isis.applib.util.TitleBuffer;
-import org.apache.isis.applib.value.Blob;
-import org.apache.isis.applib.value.Clob;
-
[email protected](identityType=IdentityType.DATASTORE)
[email protected](
-        strategy=javax.jdo.annotations.IdGeneratorStrategy.IDENTITY,
-         column="id")
[email protected](
-        strategy=VersionStrategy.VERSION_NUMBER, 
-        column="version")
[email protected]({
-    @javax.jdo.annotations.Unique(
-            name="ToDoItem_description_must_be_unique", 
-            members={"ownedBy","description"})
-})
[email protected]( {
-    @javax.jdo.annotations.Query(
-            name = "findByOwnedBy", language = "JDOQL",
-            value = "SELECT "
-                    + "FROM dom.todo.ToDoItem "
-                    + "WHERE ownedBy == :ownedBy"),
-    @javax.jdo.annotations.Query(
-            name = "findByOwnedByAndCompleteIsFalse", language = "JDOQL",
-            value = "SELECT "
-                    + "FROM dom.todo.ToDoItem "
-                    + "WHERE ownedBy == :ownedBy "
-                    + "   && complete == false"),
-    @javax.jdo.annotations.Query(
-            name = "findByOwnedByAndCompleteIsTrue", language = "JDOQL",
-            value = "SELECT "
-                    + "FROM dom.todo.ToDoItem "
-                    + "WHERE ownedBy == :ownedBy "
-                    + "&& complete == true"),
-    @javax.jdo.annotations.Query(
-            name = "findByOwnedByAndCategory", language = "JDOQL",
-            value = "SELECT "
-                    + "FROM dom.todo.ToDoItem "
-                    + "WHERE ownedBy == :ownedBy "
-                    + "&& category == :category"),
-    @javax.jdo.annotations.Query(
-            name = "findByOwnedByAndDescriptionContains", language = "JDOQL",
-            value = "SELECT "
-                    + "FROM dom.todo.ToDoItem "
-                    + "WHERE ownedBy == :ownedBy && "
-                    + "description.indexOf(:description) >= 0")
-})
-@DomainObject(
-        autoCompleteRepository = ToDoItems.class, // for drop-downs, unless 
autoCompleteNXxx() is present
-        autoCompleteAction = "autoComplete",
-        // bounded = true,  // for drop-downs if only a small number of 
instances only (overrides autoComplete)
-        objectType = "TODO"
-)
-@DomainObjectLayout(
-        bookmarking = BookmarkPolicy.AS_ROOT
-)
-public class ToDoItem implements Categorized, Comparable<ToDoItem> {
-
-    //region > LOG
-    /**
-     * It isn't common for entities to log, but they can if required.  
-     * Isis uses slf4j API internally (with log4j as implementation), and is 
the recommended API to use. 
-     */
-    private final static org.slf4j.Logger LOG = 
org.slf4j.LoggerFactory.getLogger(ToDoItem.class);
-    //endregion
-
-    // region > title, icon
-    public String title() {
-        final TitleBuffer buf = new TitleBuffer();
-        buf.append(getDescription());
-        if (isComplete()) {
-            buf.append("- Completed!");
-        } else {
-            try {
-                final LocalDate dueBy = wrapperFactory.wrap(this).getDueBy();
-                if (dueBy != null) {
-                    buf.append(" due by", dueBy);
-                }
-            } catch(final HiddenException ignored) {
-            }
-        }
-        return buf.toString();
-    }
-    
-    public String iconName() {
-        return !isComplete() ? "todo" : "done";
-    }
-
-    public String cssClass() { return iconName(); }
-
-    //endregion
-
-    //region > description (property)
-    private String description;
-
-    @javax.jdo.annotations.Column(allowsNull="false", length=100)
-    @Property(
-        regexPattern = "\\w[@&:\\-\\,\\.\\+ \\w]*"
-    )
-    public String getDescription() {
-        return description;
-    }
-
-    public void setDescription(final String description) {
-        this.description = description;
-    }
-    public void modifyDescription(final String description) {
-        setDescription(description);
-    }
-    public void clearDescription() {
-        setDescription(null);
-    }
-    //endregion
-
-    //region > dueBy (property)
-    @javax.jdo.annotations.Persistent(defaultFetchGroup="true")
-    private LocalDate dueBy;
-
-    @javax.jdo.annotations.Column(allowsNull="true")
-    public LocalDate getDueBy() {
-        return dueBy;
-    }
-
-    /**
-     * Demonstrates how to perform security checks within the domain code.
-     *
-     * <p>
-     *     Generally speaking this approach is not recommended; such checks 
should
-     *     wherever possible be externalized in the security subsystem.
-     * </p>
-     */
-    public boolean hideDueBy() {
-        final UserMemento user = container.getUser();
-        return user.hasRole("realm1:noDueBy_role");
-    }
-
-    public void setDueBy(final LocalDate dueBy) {
-        this.dueBy = dueBy;
-    }
-    public void clearDueBy() {
-        setDueBy(null);
-    }
-    // proposed new value is validated before setting
-    public String validateDueBy(final LocalDate dueBy) {
-        if (dueBy == null) {
-            return null;
-        }
-        return toDoItems.validateDueBy(dueBy);
-    }
-    //endregion
-
-    //region > category and subcategory (property)
-
-    public static enum Category {
-        Professional {
-            @Override
-            public List<Subcategory> subcategories() {
-                return Arrays.asList(null, Subcategory.OpenSource, 
Subcategory.Consulting, Subcategory.Education, Subcategory.Marketing);
-            }
-        }, Domestic {
-            @Override
-            public List<Subcategory> subcategories() {
-                return Arrays.asList(null, Subcategory.Shopping, 
Subcategory.Housework, Subcategory.Garden, Subcategory.Chores);
-            }
-        }, Other {
-            @Override
-            public List<Subcategory> subcategories() {
-                return Arrays.asList(null, Subcategory.Other);
-            }
-        };
-        
-        public abstract List<Subcategory> subcategories();
-    }
-
-    public static enum Subcategory {
-        // professional
-        OpenSource, Consulting, Education, Marketing,
-        // domestic
-        Shopping, Housework, Garden, Chores,
-        // other
-        Other;
-
-        public static List<Subcategory> listFor(final Category category) {
-            return category != null? category.subcategories(): 
Collections.<Subcategory>emptyList();
-        }
-
-        static String validate(final Category category, final Subcategory 
subcategory) {
-            if(category == null) {
-                return "Enter category first";
-            }
-            return !category.subcategories().contains(subcategory) 
-                    ? "Invalid subcategory for category '" + category + "'" 
-                    : null;
-        }
-        
-        public static Predicate<Subcategory> thoseFor(final Category category) 
{
-            return new Predicate<Subcategory>() {
-
-                @Override
-                public boolean apply(final Subcategory subcategory) {
-                    return category.subcategories().contains(subcategory);
-                }
-            };
-        }
-    }
-
-    // //////////////////////////////////////
-
-    private Category category;
-
-    @javax.jdo.annotations.Column(allowsNull="false")
-    @Property(
-            editing = Editing.DISABLED,
-            editingDisabledReason = "Use action to update both category and 
subcategory"
-    )
-    public Category getCategory() {
-        return category;
-    }
-
-    public void setCategory(final Category category) {
-        this.category = category;
-    }
-
-    // //////////////////////////////////////
-
-    private Subcategory subcategory;
-
-    @javax.jdo.annotations.Column(allowsNull="true")
-    @Property(
-            editing = Editing.DISABLED,
-            editingDisabledReason = "Use action to update both category and 
subcategory"
-    )
-    public Subcategory getSubcategory() {
-        return subcategory;
-    }
-    public void setSubcategory(final Subcategory subcategory) {
-        this.subcategory = subcategory;
-    }
-    //endregion
-
-    //region > ownedBy (property)
-
-    private String ownedBy;
-
-    @javax.jdo.annotations.Column(allowsNull="false")
-    public String getOwnedBy() {
-        return ownedBy;
-    }
-
-    public void setOwnedBy(final String ownedBy) {
-        this.ownedBy = ownedBy;
-    }
-    //endregion
-
-    //region > complete (property), completed (action), notYetCompleted 
(action)
-
-    private boolean complete;
-
-    @Property(
-        editing = Editing.DISABLED
-    )
-    public boolean isComplete() {
-        return complete;
-    }
-
-    public void setComplete(final boolean complete) {
-        this.complete = complete;
-    }
-
-    @Action(
-            domainEvent =CompletedEvent.class,
-            invokeOn = InvokeOn.OBJECT_AND_COLLECTION
-    )
-    public ToDoItem completed() {
-        setComplete(true);
-        
-        //
-        // remainder of method just demonstrates the use of the 
Bulk.InteractionContext service 
-        //
-        @SuppressWarnings("unused")
-        final List<Object> allObjects = 
actionInvocationContext.getDomainObjects();
-        
-        LOG.debug("completed: "
-                + actionInvocationContext.getIndex() +
-                " [" + actionInvocationContext.getSize() + "]"
-                + (actionInvocationContext.isFirst() ? " (first)" : "")
-                + (actionInvocationContext.isLast() ? " (last)" : ""));
-
-        // if invoked as a regular action, return this object;
-        // otherwise (if invoked as bulk), return null (so go back to the list)
-        return actionInvocationContext.getInvokedOn() == InvokedOn.OBJECT? 
this: null;
-    }
-    // disable action dependent on state of object
-    public String disableCompleted() {
-        return isComplete() ? "Already completed" : null;
-    }
-
-    @Action(
-        invokeOn = InvokeOn.OBJECT_AND_COLLECTION
-    )
-    public ToDoItem notYetCompleted() {
-        setComplete(false);
-
-        // if invoked as a regular action, return this object;
-        // otherwise (if invoked as bulk), return null (so go back to the list)
-        return actionInvocationContext.getInvokedOn() == InvokedOn.OBJECT ? 
this: null;
-    }
-    // disable action dependent on state of object
-    public String disableNotYetCompleted() {
-        return !complete ? "Not yet completed" : null;
-    }
-    //endregion
-
-    //region > completeSlowly (property)
-    // 
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-    @Action(
-            hidden = Where.EVERYWHERE
-    )
-    public void completeSlowly(final int millis) {
-        try {
-            Thread.sleep(millis);
-        } catch (final InterruptedException ignored) {
-        }
-        setComplete(true);
-    }
-    //endregion
-
-    //region > cost (property), updateCost (action)
-    private BigDecimal cost;
-
-    @javax.jdo.annotations.Column(allowsNull="true", scale=2)
-    @javax.validation.constraints.Digits(integer=10, fraction=2)
-    @Property(
-            editing = Editing.DISABLED,
-            editingDisabledReason = "Update using action"
-    )
-    public BigDecimal getCost() {
-        return cost;
-    }
-
-    public void setCost(final BigDecimal cost) {
-        this.cost = cost!=null?cost.setScale(2, 
BigDecimal.ROUND_HALF_EVEN):null;
-    }
-
-    @Action(
-            semantics = SemanticsOf.IDEMPOTENT
-    )
-    public ToDoItem updateCost(
-            @Parameter(optionality = Optionality.OPTIONAL)
-            @ParameterLayout(named = "New cost")
-            @javax.validation.constraints.Digits(integer=10, fraction=2)
-            final BigDecimal cost) {
-        LOG.debug("%s: cost updated: %s -> %s", container.titleOf(this), 
getCost(), cost);
-        
-        // just to simulate a long-running action
-        try {
-            Thread.sleep(3000);
-        } catch (final InterruptedException ignored) {
-        }
-        
-        setCost(cost);
-        return this;
-    }
-
-    // provide a default value for argument #0
-    public BigDecimal default0UpdateCost() {
-        return getCost();
-    }
-    
-    // validate action arguments
-    public String validateUpdateCost(final BigDecimal proposedCost) {
-        if(proposedCost == null) { return null; }
-        return proposedCost.compareTo(BigDecimal.ZERO) < 0? "Cost must be 
positive": null;
-    }
-    //endregion
-
-    //region > notes (property)
-    private String notes;
-
-    @javax.jdo.annotations.Column(allowsNull="true", length=400)
-    public String getNotes() {
-        return notes;
-    }
-
-    public void setNotes(final String notes) {
-        this.notes = notes;
-    }
-    //endregion
-
-    //region > attachment (property)
-    private Blob attachment;
-    @javax.jdo.annotations.Persistent(defaultFetchGroup="false", columns = {
-            @javax.jdo.annotations.Column(name = "attachment_name"),
-            @javax.jdo.annotations.Column(name = "attachment_mimetype"),
-            @javax.jdo.annotations.Column(name = "attachment_bytes", jdbcType 
= "BLOB", sqlType = "BLOB")
-    })
-    @Property(
-            optionality = Optionality.OPTIONAL
-    )
-    public Blob getAttachment() {
-        return attachment;
-    }
-
-    public void setAttachment(final Blob attachment) {
-        this.attachment = attachment;
-    }
-    //endregion
-
-    //region > doc (property)
-    private Clob doc;
-    @javax.jdo.annotations.Persistent(defaultFetchGroup="false", columns = {
-            @javax.jdo.annotations.Column(name = "doc_name"),
-            @javax.jdo.annotations.Column(name = "doc_mimetype"),
-            @javax.jdo.annotations.Column(name = "doc_chars", jdbcType = 
"CLOB", sqlType = "CLOB")
-    })
-    @Property(
-            optionality = Optionality.OPTIONAL
-    )
-    public Clob getDoc() {
-        return doc;
-    }
-
-    public void setDoc(final Clob doc) {
-        this.doc = doc;
-    }
-    //endregion
-
-    //region > version (derived property)
-    public Long getVersionSequence() {
-        if(!(this instanceof javax.jdo.spi.PersistenceCapable)) {
-            return null;
-        }
-        return (Long) JDOHelper.getVersion((javax.jdo.spi.PersistenceCapable) 
this);
-    }
-    // hide property (imperatively, based on state of object)
-    public boolean hideVersionSequence() {
-        return !(this instanceof javax.jdo.spi.PersistenceCapable);
-    }
-    //endregion
-
-    //region > dependencies (property), add (action), remove (action)
-
-    // overrides the natural ordering
-    public static class DependenciesComparator implements Comparator<ToDoItem> 
{
-        @Override
-        public int compare(final ToDoItem p, final ToDoItem q) {
-            final Ordering<ToDoItem> byDescription = new Ordering<ToDoItem>() {
-                public int compare(final ToDoItem p, final ToDoItem q) {
-                    return 
Ordering.natural().nullsFirst().compare(p.getDescription(), q.getDescription());
-                }
-            };
-            return byDescription
-                    .compound(Ordering.<ToDoItem>natural())
-                    .compare(p, q);
-        }
-    }
-
-    @javax.jdo.annotations.Persistent(table="ToDoItemDependencies")
-    @javax.jdo.annotations.Join(column="dependingId")
-    @javax.jdo.annotations.Element(column="dependentId")
-
-    private Set<ToDoItem> dependencies = new TreeSet<>();
-    //private SortedSet<ToDoItem> dependencies = new TreeSet<>();  // not 
compatible with neo4j (as of DN v3.2.3)
-
-    @Collection()
-    @CollectionLayout(/*sortedBy = DependenciesComparator.class*/) // not 
compatible with neo4j (as of DN v3.2.3)
-    public Set<ToDoItem> getDependencies() {
-        return dependencies;
-    }
-
-    public void setDependencies(final Set<ToDoItem> dependencies) {
-        this.dependencies = dependencies;
-    }
-
-    public void addToDependencies(final ToDoItem toDoItem) {
-        getDependencies().add(toDoItem);
-    }
-    public void removeFromDependencies(final ToDoItem toDoItem) {
-        getDependencies().remove(toDoItem);
-    }
-
-    public ToDoItem add(
-            @ParameterLayout(typicalLength = 20)
-            final ToDoItem toDoItem) {
-        // By wrapping the call, Isis will detect that the collection is 
modified
-        // and it will automatically send CollectionInteractionEvents to the 
Event Bus.
-        // ToDoItemSubscriptions is a demo subscriber to this event
-        wrapperFactory.wrapSkipRules(this).addToDependencies(toDoItem);
-        return this;
-    }
-    public List<ToDoItem> autoComplete0Add(
-            @Parameter(minLength = 2)
-            final String search) {
-        final List<ToDoItem> list = toDoItems.autoComplete(search);
-        list.removeAll(getDependencies());
-        list.remove(this);
-        return list;
-    }
-
-    public String disableAdd(final ToDoItem toDoItem) {
-        if(isComplete()) {
-            return "Cannot add dependencies for items that are complete";
-        }
-        return null;
-    }
-    // validate the provided argument prior to invoking action
-    public String validateAdd(final ToDoItem toDoItem) {
-        if(getDependencies().contains(toDoItem)) {
-            return "Already a dependency";
-        }
-        if(toDoItem == this) {
-            return "Can't set up a dependency to self";
-        }
-        return null;
-    }
-
-    public ToDoItem remove(
-            @ParameterLayout(typicalLength = 20)
-            final ToDoItem toDoItem) {
-        // By wrapping the call, Isis will detect that the collection is 
modified
-        // and it will automatically send a CollectionInteractionEvent to the 
Event Bus.
-        // ToDoItemSubscriptions is a demo subscriber to this event
-        wrapperFactory.wrapSkipRules(this).removeFromDependencies(toDoItem);
-        return this;
-    }
-    // disable action dependent on state of object
-    public String disableRemove(final ToDoItem toDoItem) {
-        if(isComplete()) {
-            return "Cannot remove dependencies for items that are complete";
-        }
-        return getDependencies().isEmpty()? "No dependencies to remove": null;
-    }
-    // validate the provided argument prior to invoking action
-    public String validateRemove(final ToDoItem toDoItem) {
-        if(!getDependencies().contains(toDoItem)) {
-            return "Not a dependency";
-        }
-        return null;
-    }
-    // provide a drop-down
-    public java.util.Collection<ToDoItem> choices0Remove() {
-        return getDependencies();
-    }
-    //endregion
-
-    //region > clone (action)
-
-    // the name of the action in the UI
-    // nb: method is not called "clone()" is inherited by java.lang.Object and
-    // (a) has different semantics and (b) is in any case automatically ignored
-    // by the framework
-    public ToDoItem duplicate(
-            @Parameter(regexPattern = "\\w[@&:\\-\\,\\.\\+ \\w]*" )
-            @ParameterLayout(named="Description")
-            final String description,
-            @ParameterLayout(named="Category")
-            final Category category,
-            @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 toDoItems.newToDo(description, category, subcategory, dueBy, 
cost);
-    }
-    public String default0Duplicate() {
-        return getDescription() + " - Copy";
-    }
-    public Category default1Duplicate() {
-        return getCategory();
-    }
-    public Subcategory default2Duplicate() {
-        return getSubcategory();
-    }
-    public LocalDate default3Duplicate() {
-        return getDueBy();
-    }
-    public List<Subcategory> choices2Duplicate(
-            final String description, final Category category) {
-        return toDoItems.choices2NewToDo(description, category);
-    }
-    public String validateDuplicate(
-            final String description, 
-            final Category category, final Subcategory subcategory, 
-            final LocalDate dueBy, final BigDecimal cost) {
-        return toDoItems.validateNewToDo(description, category, subcategory, 
dueBy, cost);
-    }
-    //endregion
-
-    //region > delete (action)
-    @Action(
-            domainEvent =DeletedEvent.class,
-            invokeOn = InvokeOn.OBJECT_AND_COLLECTION
-    )
-    public List<ToDoItem> delete() {
-        
-        container.removeIfNotAlready(this);
-
-        container.informUser("Deleted " + container.titleOf(this));
-        
-        // invalid to return 'this' (cannot render a deleted object)
-        return toDoItems.notYetComplete();
-    }
-    //endregion
-
-    //region > totalCost (property)
-    @Action(
-            semantics = SemanticsOf.SAFE,
-            invokeOn = InvokeOn.COLLECTION_ONLY
-    )
-    public BigDecimal totalCost() {
-        BigDecimal total = (BigDecimal) scratchpad.get("runningTotal");
-        if(getCost() != null) {
-            total = total != null ? total.add(getCost()) : getCost();
-            scratchpad.put("runningTotal", total);
-        }
-        return total.setScale(2, BigDecimal.ROUND_HALF_EVEN);
-    }
-    //endregion
-
-    //region > openSourceCodeOnGithub (action)
-    @Action(
-            semantics = SemanticsOf.SAFE,
-            restrictTo = RestrictTo.PROTOTYPING
-    )
-    public URL openSourceCodeOnGithub() throws MalformedURLException {
-        return new 
URL("https://github.com/apache/isis/tree/master/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItem.java";);
-    }
-    //endregion
-
-    //region > demoException (action)
-
-    static enum DemoExceptionType {
-        RecoverableException,
-        RecoverableExceptionAutoEscalated,
-        NonRecoverableException;
-    }
-
-    @Action(
-            semantics = SemanticsOf.SAFE,
-            restrictTo = RestrictTo.PROTOTYPING
-    )
-    public void demoException(
-            @ParameterLayout(named="Type")
-            final DemoExceptionType type) {
-        switch(type) {
-        case NonRecoverableException:
-            throw new NonRecoverableException("Demo throwing " + type.name());
-        case RecoverableException:
-            throw new RecoverableException("Demo throwing " + type.name());
-        case RecoverableExceptionAutoEscalated:
-            try {
-                // this will trigger an exception (because category cannot be 
null), causing the xactn to be aborted
-                setCategory(null);
-                container.flush();
-            } catch(Exception e) {
-                // it's a programming mistake to throw only a recoverable 
exception here, because of the xactn's state.
-                // the framework should instead auto-escalate this to a 
non-recoverable exception
-                throw new RecoverableException("Demo throwing " + type.name(), 
e);
-            }
-        }
-    }
-    //endregion
-
-    //region > lifecycle callbacks
-
-    public void created() {
-        LOG.debug("lifecycle callback: created: " + this.toString());
-    }
-    public void loaded() {
-        LOG.debug("lifecycle callback: loaded: " + this.toString());
-    }
-    public void persisting() {
-        LOG.debug("lifecycle callback: persisting: " + this.toString());
-    }
-    public void persisted() {
-        LOG.debug("lifecycle callback: persisted: " + this.toString());
-    }
-    public void updating() {
-        LOG.debug("lifecycle callback: updating: " + this.toString());
-    }
-    public void updated() {
-        LOG.debug("lifecycle callback: updated: " + this.toString());
-    }
-    public void removing() {
-        LOG.debug("lifecycle callback: removing: " + this.toString());
-    }
-    public void removed() {
-        LOG.debug("lifecycle callback: removed: " + this.toString());
-    }
-    //endregion
-
-    //region > object-level validation
-
-    /**
-     * Prevent user from viewing another user's data.
-     */
-    public boolean hidden() {
-        // uncomment to enable.  As things stand, the disabled() method below 
instead will make object "read-only".
-        //return !Objects.equal(getOwnedBy(), container.getUser().getName());
-        return false;
-    }
-
-    /**
-     * Prevent user from modifying any other user's data.
-     */
-    public String disabled(final Identifier.Type identifierType){
-        final UserMemento currentUser = container.getUser();
-        final String currentUserName = currentUser.getName();
-        if(Objects.equal(getOwnedBy(), currentUserName)) { return null; }
-        return "This object is owned by '" + getOwnedBy() + "' and cannot be 
modified by you";
-    }
-
-    /**
-     * In a real app, if this were actually a rule, then we'd expect that
-     * invoking the {@link #completed() done} action would clear the {@link 
#getDueBy() dueBy}
-     * property (rather than require the user to have to clear manually).
-     */
-    public String validate() {
-        if(isComplete() && getDueBy() != null) {
-            return "Due by date must be set to null if item has been 
completed";
-        }
-        return null;
-    }
-
-
-    //endregion
-
-
-    //region > programmatic helpers
-    @Programmatic // excluded from the framework's metamodel
-    public boolean isDue() {
-        if (getDueBy() == null) {
-            return false;
-        }
-        return !toDoItems.isMoreThanOneWeekInPast(getDueBy());
-    }
-    //endregion
-
-    //region > events
-
-    public static abstract class AbstractActionDomainEvent extends 
ActionDomainEvent<ToDoItem> {
-        private static final long serialVersionUID = 1L;
-        private final String description;
-        public AbstractActionDomainEvent(
-                final String description,
-                final ToDoItem source,
-                final Identifier identifier,
-                final Object... arguments) {
-            super(source, identifier, arguments);
-            this.description = description;
-        }
-        public String getEventDescription() {
-            return description;
-        }
-    }
-
-    public static class CompletedEvent extends AbstractActionDomainEvent {
-        private static final long serialVersionUID = 1L;
-        public CompletedEvent(
-                final ToDoItem source, 
-                final Identifier identifier, 
-                final Object... arguments) {
-            super("completed", source, identifier, arguments);
-        }
-    }
-
-    public static class NoLongerCompletedEvent extends 
AbstractActionDomainEvent {
-        private static final long serialVersionUID = 1L;
-        public NoLongerCompletedEvent(
-                final ToDoItem source, 
-                final Identifier identifier, 
-                final Object... arguments) {
-            super("no longer completed", source, identifier, arguments);
-        }
-    }
-
-    public static class DeletedEvent extends AbstractActionDomainEvent {
-        private static final long serialVersionUID = 1L;
-        public DeletedEvent(
-                final ToDoItem source, 
-                final Identifier identifier, 
-                final Object... arguments) {
-            super("deleted", source, identifier, arguments);
-        }
-    }
-
-    //endregion
-
-    //region > predicates
-
-    public static class Predicates {
-        
-        public static Predicate<ToDoItem> thoseOwnedBy(final String 
currentUser) {
-            return new Predicate<ToDoItem>() {
-                @Override
-                public boolean apply(final ToDoItem toDoItem) {
-                    return Objects.equal(toDoItem.getOwnedBy(), currentUser);
-                }
-            };
-        }
-
-        public static Predicate<ToDoItem> thoseCompleted(
-                final boolean completed) {
-            return new Predicate<ToDoItem>() {
-                @Override
-                public boolean apply(final ToDoItem t) {
-                    return Objects.equal(t.isComplete(), completed);
-                }
-            };
-        }
-
-        public static Predicate<ToDoItem> thoseWithSimilarDescription(final 
String description) {
-            return new Predicate<ToDoItem>() {
-                @Override
-                public boolean apply(final ToDoItem t) {
-                    return t.getDescription().contains(description);
-                }
-            };
-        }
-
-        @SuppressWarnings("unchecked")
-        public static Predicate<ToDoItem> thoseSimilarTo(final ToDoItem 
toDoItem) {
-            return com.google.common.base.Predicates.and(
-                    thoseNot(toDoItem),
-                    thoseOwnedBy(toDoItem.getOwnedBy()),
-                    thoseCategorised(toDoItem.getCategory()));
-        }
-
-        public static Predicate<ToDoItem> thoseNot(final ToDoItem toDoItem) {
-            return new Predicate<ToDoItem>() {
-                @Override
-                public boolean apply(final ToDoItem t) {
-                    return t != toDoItem;
-                }
-            };
-        }
-
-        public static Predicate<ToDoItem> thoseCategorised(final Category 
category) {
-            return new Predicate<ToDoItem>() {
-                @Override
-                public boolean apply(final ToDoItem toDoItem) {
-                    return Objects.equal(toDoItem.getCategory(), category);
-                }
-            };
-        }
-
-        public static Predicate<ToDoItem> thoseSubcategorised(
-                final Subcategory subcategory) {
-            return new Predicate<ToDoItem>() {
-                @Override
-                public boolean apply(final ToDoItem t) {
-                    return Objects.equal(t.getSubcategory(), subcategory);
-                }
-            };
-        }
-
-        public static Predicate<ToDoItem> thoseCategorised(
-                final Category category, final Subcategory subcategory) {
-            return com.google.common.base.Predicates.and(
-                    thoseCategorised(category), 
-                    thoseSubcategorised(subcategory)); 
-        }
-
-    }
-
-    //endregion
-
-    //region > toString, compareTo
-    @Override
-    public String toString() {
-        return ObjectContracts.toString(this, 
"description,complete,dueBy,ownedBy");
-    }
-
-    /**
-     * Required so can store in {@link SortedSet sorted set}s (eg {@link 
#getDependencies()}). 
-     */
-    @Override
-    public int compareTo(final ToDoItem other) {
-        return ObjectContracts.compare(this, other, 
"complete,dueBy,description");
-    }
-    //endregion
-
-    //region > injected services
-    @javax.inject.Inject
-    DomainObjectContainer container;
-
-    @javax.inject.Inject
-    ToDoItems toDoItems;
-
-    @javax.inject.Inject
-    Scratchpad scratchpad;
-
-    /**
-     * public only so can be injected from integ tests
-     */
-    @javax.inject.Inject
-    public ActionInvocationContext actionInvocationContext;
-
-    /**
-     * public only so can be injected from integ tests
-     */
-    @javax.inject.Inject
-    public EventBusService eventBusService;
-
-    @javax.inject.Inject
-    WrapperFactory wrapperFactory;
-
-    //endregion
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/a4ec0b72/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItem.layout.json
----------------------------------------------------------------------
diff --git 
a/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItem.layout.json 
b/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItem.layout.json
deleted file mode 100644
index cda5fdc..0000000
--- 
a/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItem.layout.json
+++ /dev/null
@@ -1,222 +0,0 @@
-/**
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-{
-    "columns": [
-    {
-        "span": 6,
-        "memberGroups": {
-            "General": {
-                "members": {
-                    "description": {
-                        "propertyLayout": {
-                            "cssClass": "x-key",
-                            "labelPosition": "TOP"
-                        }
-                    },
-                    "category": {
-                        "propertyLayout": {
-                            "labelPosition": "TOP"
-                        }
-                    },
-                    "subcategory": {
-                        "propertyLayout": {
-                            "labelPosition": "NONE"
-                        },
-                        "actions": {
-                            "updateCategory": {
-                                "actionLayout": {
-                                    "named": "Update"
-                                }
-                            },
-                            "analyseCategory": {
-                                "actionLayout": {
-                                    "cssClass": "btn-default",
-                                    "cssClassFa": "fa fa-pie-chart"
-                                }
-                            }
-                        }
-                    },
-                    "ownedBy": {
-                        "propertyLayout": {
-                            "hidden": "EVERYWHERE"
-                        }
-                    },
-                    "complete": {
-                        "propertyLayout": {
-                            "named": "Whether this todo item has been 
<i>completed</i> or not.",
-                            "namedEscaped": false,
-                            "describedAs": "Whether this todo item has been 
completed, or not.",
-                            "labelPosition": "LEFT"
-                        },
-                        "actions": {
-                            "completed": {
-                                "actionLayout": {
-                                    "named": "Done",
-                                    "describedAs": "Update this todo item as 
complete",
-                                    "cssClass": "btn-success",
-                                    "cssClassFa": "fa fa-thumbs-up"
-                                }
-                            },
-                            "notYetCompleted": {
-                                "actionLayout": {
-                                    "named": "Not done",
-                                    "describedAs": "Update this todo item as 
not yet complete",
-                                    "cssClass": "btn-info",
-                                    "cssClassFa": "fa fa-thumbs-down"
-                                }
-                            },
-                            "scheduleExplicitly": {
-                            },
-                            "scheduleImplicitly": {
-                            }
-                        }
-                    }
-                }
-            },
-            "Misc": {
-                "members": {
-                    "versionSequence": {
-                        "propertyLayout": {
-                            "named": "Version",
-                            "hidden": "ALL_TABLES"
-                        },
-                        "disabled": {}
-                    }
-                }
-            }
-        }
-    },
-    {
-        "span": 6,
-        "memberGroups": {
-            "Priority": {
-                "members": {
-                     "relativePriority": {
-                        "actions": {
-                            "previous": {
-                                "actionLayout": {
-                                    "cssClassFa": "fa fa-step-backward"
-                                }
-                            },
-                            "next": {
-                                "actionLayout": {
-                                    "cssClassFa": "fa fa-step-forward",
-                                    "cssClassFaPosition": "right"
-                                }
-                            }
-                        }
-                    },
-                    "dueBy": {
-                        "propertyLayout": {
-                            "renderedAsDayBefore": "false"
-                        }
-                    }
-                }
-            },
-            "Other": {
-                "members": {
-                    "cost": {
-                        "actions": {
-                            "updateCost":{
-                                "actionLayout": {
-                                    "named": "Update",
-                                    "cssClassFa": "fa fa-dollar"
-                                }
-                            }
-                        }
-                    },
-                    "notes": {
-                        "propertyLayout": {
-                            "hidden": "ALL_TABLES",
-                            "labelPosition": "TOP",
-                            "multiLine": 5
-                        }
-                    },
-                    "attachment": {
-                        "propertyLayout": {
-                            "hidden": "STANDALONE_TABLES"
-                        }
-                    },
-                    "doc": {
-                        "propertyLayout": {
-                            "hidden": "STANDALONE_TABLES"
-                        }
-                    }
-                }
-            }
-        }
-    },
-    {
-        "span": 0
-    },
-    {
-        "span": 6,
-        "collections": {
-            "dependencies": {
-                "collectionLayout": {
-                    "named": "Todo items that are <i>dependencies</i> of this 
item.",
-                    "namedEscaped": false,
-                    "describedAs": "Todo items that must be completed before 
this one",
-                    "paged": 5,
-                    "render": "EAGERLY"
-                },
-                "disabled": {},
-                "actions": {
-                    "add":{
-                        "actionLayout": {
-                            "cssClass": "btn-default",
-                            "cssClassFa": "fa fa-plus-square"
-                        }
-                    },
-                    "remove": {
-                        "actionLayout": {
-                            "cssClass": "x-caution btn-default",
-                            "cssClassFa": "fa fa-minus-square"
-                        }
-                    }
-                }
-            },
-            "similarTo": {
-                "collectionLayout": {
-                    "named": "Todo items that are <i>similar to</i> this one",
-                    "namedEscaped": false,
-                    "paged": 3,
-                    "render": "LAZILY"
-                },
-                "disabled": {}
-            }
-        }
-    }
-    ],
-    "actions": {
-        "totalCost": {},
-        "delete": {
-            "actionLayout": {
-                "cssClass": "btn btn-danger",
-                "cssClassFa": "fa fa-trash fa-lg"
-            }
-        },
-        "duplicate": {
-            "actionLayout": {
-                "named": "Clone",
-                "describedAs": "Create a new todo item from this one",
-                "cssClass": "btn-warn",
-                "cssClassFa": "fa fa-copy fa-lg"
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/a4ec0b72/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItem.png
----------------------------------------------------------------------
diff --git 
a/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItem.png 
b/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItem.png
deleted file mode 100644
index 99a9fed..0000000
Binary files 
a/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItem.png and 
/dev/null differ

http://git-wip-us.apache.org/repos/asf/isis/blob/a4ec0b72/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemChangedPayloadFactory.java
----------------------------------------------------------------------
diff --git 
a/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemChangedPayloadFactory.java
 
b/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemChangedPayloadFactory.java
deleted file mode 100644
index 32b2aa4..0000000
--- 
a/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemChangedPayloadFactory.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package dom.todo;
-
-import org.apache.isis.applib.annotation.PublishingChangeKind;
-import org.apache.isis.applib.annotation.PublishingPayloadFactoryForObject;
-import org.apache.isis.applib.services.publish.EventPayload;
-import org.apache.isis.applib.services.publish.EventPayloadForObjectChanged;
-
-public class ToDoItemChangedPayloadFactory implements 
PublishingPayloadFactoryForObject {
-
-    public static class ToDoItemPayload extends 
EventPayloadForObjectChanged<ToDoItem> {
-
-        public ToDoItemPayload(ToDoItem changed) {
-            super(changed);
-        }
-        
-        /**
-         * Expose the item's {@link ToDoItem#getDescription() description} 
more explicitly
-         * in the payload.
-         */
-        public String getDescription() {
-            return getChanged().getDescription();
-        }
-    }
-
-    @Override
-    public EventPayload payloadFor(final Object changedObject, final 
PublishingChangeKind publishingChangeKind) {
-        return new ToDoItemPayload((ToDoItem) changedObject);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/a4ec0b72/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemContributions.java
----------------------------------------------------------------------
diff --git 
a/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemContributions.java
 
b/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemContributions.java
deleted file mode 100644
index b35135c..0000000
--- 
a/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemContributions.java
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package dom.todo;
-
-import dom.todo.ToDoItem.Category;
-import dom.todo.ToDoItem.Subcategory;
-
-import java.util.List;
-import java.util.concurrent.Callable;
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Ordering;
-import org.joda.time.LocalDate;
-import org.apache.isis.applib.AbstractFactoryAndRepository;
-import org.apache.isis.applib.annotation.Action;
-import org.apache.isis.applib.annotation.ActionLayout;
-import org.apache.isis.applib.annotation.Contributed;
-import org.apache.isis.applib.annotation.DomainService;
-import org.apache.isis.applib.annotation.Editing;
-import org.apache.isis.applib.annotation.NatureOfService;
-import org.apache.isis.applib.annotation.Optionality;
-import org.apache.isis.applib.annotation.Parameter;
-import org.apache.isis.applib.annotation.ParameterLayout;
-import org.apache.isis.applib.annotation.Property;
-import org.apache.isis.applib.annotation.SemanticsOf;
-import org.apache.isis.applib.annotation.Where;
-import org.apache.isis.applib.query.QueryDefault;
-import org.apache.isis.applib.services.queryresultscache.QueryResultsCache;
-import org.apache.isis.applib.value.Clob;
-
-@DomainService(nature = NatureOfService.VIEW_CONTRIBUTIONS_ONLY)
-public class ToDoItemContributions extends AbstractFactoryAndRepository {
-
-    //region > priority (contributed property)
-    @Action(
-            semantics = SemanticsOf.SAFE,
-            hidden = Where.ALL_TABLES
-    )
-    @ActionLayout(
-            describedAs = "The relative priority of this item compared to 
others not yet complete (using 'due by' date)",
-            contributed = Contributed.AS_ASSOCIATION
-    )
-    @Property(
-            editing = Editing.DISABLED,
-            editingDisabledReason = "Relative priority, derived from due date"
-    )
-    public Integer relativePriority(final ToDoItem toDoItem) {
-        return queryResultsCache.execute(new Callable<Integer>(){
-            @Override
-            public Integer call() throws Exception {
-                if(toDoItem.isComplete()) {
-                    return null;
-                }
-
-                // sort items, then locate this one
-                int i=1;
-                for (final ToDoItem each : sortedNotYetComplete()) {
-                    if(each == toDoItem) {
-                        return i;
-                    }
-                    i++;
-                }
-                return null;
-            }}, ToDoItemContributions.class, "relativePriority", toDoItem);
-    }
-
-    private List<ToDoItem> sortedNotYetComplete() {
-        return ORDERING_DUE_BY
-        .compound(ORDERING_DESCRIPTION)
-        .sortedCopy(toDoItems.notYetComplete());
-    }
-
-    private static final Ordering<ToDoItem> ORDERING_DUE_BY =
-        Ordering.natural().nullsLast().onResultOf(new Function<ToDoItem, 
LocalDate>(){
-            @Override
-            public LocalDate apply(final ToDoItem input) {
-                return input.getDueBy();
-            }
-        });
-    
-    private static final Ordering<ToDoItem> ORDERING_DESCRIPTION =
-        Ordering.natural().nullsLast().onResultOf(new Function<ToDoItem, 
String>(){
-            @Override
-            public String apply(final ToDoItem input) {
-                return input.getDescription();
-            }
-        });
-
-
-    //endregion
-
-    //region >  next, previous (contributed actions)
-    @Action(semantics = SemanticsOf.SAFE)
-    @ActionLayout(
-            describedAs = "The next item not yet completed",
-            contributed = Contributed.AS_ACTION
-    )
-    public ToDoItem next(final ToDoItem item) {
-        final Integer priority = relativePriority(item);
-        if(priority == null) {
-            return item;
-        }
-        int priorityOfNext = priority != null ? priority + 1 : 0;
-        return itemWithPriorityElse(priorityOfNext, item);
-    }
-    public String disableNext(final ToDoItem toDoItem) {
-        if (toDoItem.isComplete()) {
-            return "Completed";
-        }
-        if(next(toDoItem) == null) {
-            return "No next item";
-        }
-        return null;
-    }
-
-    // //////////////////////////////////////
-
-    @ActionLayout(
-            describedAs = "The previous item not yet completed",
-            contributed = Contributed.AS_ACTION
-    )
-    @Action(semantics = SemanticsOf.SAFE)
-    public ToDoItem previous(final ToDoItem item) {
-        final Integer priority = relativePriority(item);
-        if(priority == null) {
-            return item;
-        }
-        int priorityOfPrevious = priority != null? priority - 1 : 0;
-        return itemWithPriorityElse(priorityOfPrevious, item);
-    }
-    public String disablePrevious(final ToDoItem toDoItem) {
-        if (toDoItem.isComplete()) {
-            return "Completed";
-        }
-        if(previous(toDoItem) == null) {
-            return "No previous item";
-        }
-        return null;
-    }
-
-    // //////////////////////////////////////
-
-    /**
-     * @param priority : 1-based priority
-     */
-    private ToDoItem itemWithPriorityElse(int priority, final ToDoItem 
itemElse) {
-        if(priority < 1) {
-            return null;
-        }
-        final List<ToDoItem> items = sortedNotYetComplete();
-        if(priority > items.size()) {
-            return null;
-        }
-        return priority>=0 && items.size()>=priority? items.get(priority-1): 
itemElse;
-    }
-    //endregion
-
-    //region > similarTo (contributed collection)
-    @ActionLayout(
-            contributed = Contributed.AS_ASSOCIATION
-    )
-    @Action(semantics = SemanticsOf.SAFE)
-    public List<ToDoItem> similarTo(final ToDoItem toDoItem) {
-        final List<ToDoItem> similarToDoItems = allMatches(
-                new QueryDefault<ToDoItem>(ToDoItem.class,
-                        "findByOwnedByAndCategory", 
-                        "ownedBy", currentUserName(), 
-                        "category", toDoItem.getCategory()));
-        return Lists.newArrayList(Iterables.filter(similarToDoItems, 
excluding(toDoItem)));
-    }
-
-
-    private static Predicate<ToDoItem> excluding(final ToDoItem toDoItem) {
-        return new Predicate<ToDoItem>() {
-            @Override
-            public boolean apply(ToDoItem input) {
-                return input != toDoItem;
-            }
-        };
-    }
-    //endregion
-
-    //region > updateCategory (contributed action)
-
-    @ActionLayout(
-            describedAs = "Update category and subcategory"
-    )
-    @Action(semantics = SemanticsOf.IDEMPOTENT)
-    public Categorized updateCategory(
-            final Categorized item,
-            final @ParameterLayout(named="Category") Category category,
-            final @Parameter(optionality = Optionality.OPTIONAL) 
@ParameterLayout(named="Subcategory") Subcategory subcategory) {
-        item.setCategory(category);
-        item.setSubcategory(subcategory);
-        return item;
-    }
-    public Category default1UpdateCategory(
-            final Categorized item) {
-        return item != null? item.getCategory(): null;
-    }
-    public Subcategory default2UpdateCategory(
-            final Categorized item) {
-        return item != null? item.getSubcategory(): null;
-    }
-
-    public List<Subcategory> choices2UpdateCategory(
-            final Categorized item, final Category category) {
-        return Subcategory.listFor(category);
-    }
-    
-    public String validateUpdateCategory(
-            final Categorized item, final Category category, final Subcategory 
subcategory) {
-        return Subcategory.validate(category, subcategory);
-    }
-    //endregion
-
-    // region > exportAsJson (action)
-    /**
-     * Demonstrates functionality of streaming back Clob/Blob result within an 
action with a prompt, i.e. Ajax request
-     */
-    @Action(semantics = SemanticsOf.SAFE)
-    public Clob exportAsJson(
-            final ToDoItem toDoItem,
-            @ParameterLayout(named = "File name") String fileName
-    ) {
-        if(!fileName.endsWith(".json")) {
-            fileName += ".json";
-        }
-        return new Clob(
-                fileName,
-                "application/json",
-                "{" +
-                "\"description\": \"" + toDoItem.getDescription()+"\"" +
-                ",\"complete\": " + ""+toDoItem.isComplete() +
-                "}");
-    }
-
-    public String default1ExportAsJson() {
-        return "todo";
-    }
-    //endregion
-
-
-    //region > helpers
-    protected String currentUserName() {
-        return getContainer().getUser().getName();
-    }
-    //endregion
-
-    //region > injected services
-    @javax.inject.Inject
-    private ToDoItems toDoItems;
-
-    @javax.inject.Inject
-    private QueryResultsCache queryResultsCache;
-    //endregion
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/a4ec0b72/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java
----------------------------------------------------------------------
diff --git 
a/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java
 
b/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java
deleted file mode 100644
index 91b0ee8..0000000
--- 
a/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java
+++ /dev/null
@@ -1,399 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package dom.todo;
-
-import java.util.EventObject;
-import java.util.List;
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Lists;
-import com.google.common.eventbus.Subscribe;
-import org.apache.isis.applib.DomainObjectContainer;
-import org.apache.isis.applib.NonRecoverableException;
-import org.apache.isis.applib.RecoverableException;
-import org.apache.isis.applib.annotation.Action;
-import org.apache.isis.applib.annotation.ActionLayout;
-import org.apache.isis.applib.annotation.DomainService;
-import org.apache.isis.applib.annotation.DomainServiceLayout;
-import org.apache.isis.applib.annotation.MemberOrder;
-import org.apache.isis.applib.annotation.NatureOfService;
-import org.apache.isis.applib.annotation.ParameterLayout;
-import org.apache.isis.applib.annotation.Programmatic;
-import org.apache.isis.applib.annotation.RestrictTo;
-import org.apache.isis.applib.annotation.SemanticsOf;
-import org.apache.isis.applib.services.eventbus.ActionDomainEvent;
-import org.apache.isis.applib.services.eventbus.CollectionDomainEvent;
-import org.apache.isis.applib.services.eventbus.EventBusService;
-import org.apache.isis.applib.services.eventbus.PropertyDomainEvent;
-
-import static com.google.common.collect.Iterables.filter;
-import static com.google.common.collect.Iterables.transform;
-import static com.google.common.collect.Lists.newArrayList;
-
-/**
- * Subscribes to changes made to  the {@link dom.todo.ToDoItem} entity.
- *
- * <p>
- *     (For demo purposes) the behaviour can be influenced using {@link 
#subscriberBehaviour(dom.todo.ToDoItemSubscriptions.Behaviour)}.
- *     In particular, the subscriber can be used to hide/disable/validate 
actions, or just to perform pre- or post-execute
- *     tasks.  This also includes being set to throw an exception during the 
execution of the action (also in effect
- *     vetoing the change).
- * </p>
- */
-@DomainService(nature = NatureOfService.VIEW_MENU_ONLY)
-@DomainServiceLayout(menuBar = DomainServiceLayout.MenuBar.SECONDARY, 
menuOrder = "30")
-public class ToDoItemSubscriptions {
-
-    //region > LOG
-    private final static org.slf4j.Logger LOG = 
org.slf4j.LoggerFactory.getLogger(ToDoItemSubscriptions.class);
-    //endregion
-
-    //region > postConstruct, preDestroy
-
-    /**
-     * Registers this service with the {@link 
org.apache.isis.applib.services.eventbus.EventBusService}.
-     *
-     * <p>
-     *     Because this service is a singleton, this is called during initial 
bootstrap.
-     * </p>
-     */
-    @Programmatic
-    @PostConstruct
-    public void postConstruct() {
-        LOG.info("postConstruct: registering to event bus");
-        eventBusService.register(this);
-    }
-
-    /**
-     * Unregisters this service from the {@link 
org.apache.isis.applib.services.eventbus.EventBusService}.
-     *
-     * <p>
-     *     Because this service is a singleton, this is only done when the 
system is shutdown.
-     * </p>
-     */
-    @Programmatic
-    @PreDestroy
-    public void preDestroy() {
-        LOG.info("preDestroy: unregistering from event bus");
-        eventBusService.unregister(this);
-    }
-    //endregion
-
-
-    //region > on(Event)...
-
-    public static enum Behaviour {
-        AnyExecuteAccept,
-        AnyExecuteVetoWithRecoverableException,
-        AnyExecuteVetoWithNonRecoverableException,
-        AnyExecuteVetoWithOtherException,
-        UpdateCostActionHide,
-        UpdateCostActionDisable,
-        UpdateCostActionInvalidate,
-        DescriptionPropertyHide,
-        DescriptionPropertyDisable,
-        DescriptionPropertyInvalidate,
-        DependenciesCollectionHide,
-        // not implemented in Wicket viewer, but supported in wrapped objects
-        DependenciesCollectionDisable,
-        // not implemented in Wicket viewer, but supported in wrapped objects
-        DependenciesCollectionInvalidateAdd,
-        DependenciesCollectionInvalidateRemove,
-        SimilarToCollectionHide
-    }
-
-    /**
-     * The desired behaviour of this service.
-     */
-    private Behaviour behaviour = Behaviour.AnyExecuteAccept;
-
-    /**
-     * To demo/test what occurs if a subscriber that might veto an event.
-     */
-    @MemberOrder(name = "Prototyping", sequence = "80")
-    @ActionLayout(
-        named="Set subscriber behaviour"
-    )
-    @Action(
-            semantics = SemanticsOf.IDEMPOTENT,
-            restrictTo = RestrictTo.PROTOTYPING
-    )
-    public void subscriberBehaviour(
-            @ParameterLayout(
-                    named="Behaviour"
-            )
-            final Behaviour behaviour) {
-        this.behaviour = behaviour;
-        container.informUser("Subscriber behaviour set to: " + behaviour);
-    }
-    public Behaviour default0SubscriberBehaviour() {
-        return this.behaviour;
-    }
-
-    @Programmatic
-    public Behaviour getSubscriberBehaviour() {
-        return behaviour;
-    }
-
-
-    private void onExecutedThrowExceptionIfSet(final ActionDomainEvent<?> ev) {
-        if(ev != null && ev.getSemantics().isSafe()) {
-            return;
-        }
-        onExecutedThrowExceptionIfSet();
-    }
-    private void onExecutedThrowExceptionIfSet(final PropertyDomainEvent<?, ?> 
ev) {
-        onExecutedThrowExceptionIfSet();
-    }
-    private void onExecutedThrowExceptionIfSet(final CollectionDomainEvent<?, 
?> ev) {
-        onExecutedThrowExceptionIfSet();
-    }
-
-
-    private void onExecutedThrowExceptionIfSet() {
-        if(behaviour == Behaviour.AnyExecuteVetoWithRecoverableException) {
-            throw new RecoverableException("Rejecting event (recoverable 
exception thrown)");
-        }
-        if(behaviour == Behaviour.AnyExecuteVetoWithNonRecoverableException) {
-            throw new NonRecoverableException("Rejecting event 
(non-recoverable exception thrown)");
-        }
-        if(behaviour == Behaviour.AnyExecuteVetoWithOtherException) {
-            throw new RuntimeException("Throwing some other exception");
-        }
-    }
-    //endregion
-
-    //region > on(Event) for ToDoItem-specific events
-    @Programmatic
-    @Subscribe
-    public void on(final ToDoItem.CompletedEvent ev) {
-        recordEvent(ev);
-        switch(ev.getEventPhase()) {
-            case HIDE:
-                break;
-            case DISABLE:
-                break;
-            case VALIDATE:
-                break;
-            case EXECUTING:
-                break;
-            case EXECUTED:
-                LOG.info("Received ToDoItem.CompletedEvent for : " + 
ev.getSource().toString());
-                break;
-        }
-    }
-    //endregion
-
-    //region > on(Event) ... general purpose
-
-    @Programmatic
-    @Subscribe
-    public void on(final ActionDomainEvent<?> ev) {
-        recordEvent(ev);
-        switch(ev.getEventPhase()) {
-            case HIDE:
-                if(getSubscriberBehaviour() == Behaviour.UpdateCostActionHide) 
{
-                    
if(ev.getIdentifier().getMemberName().equals("updateCost")) {
-                        ev.hide();
-                    }
-                }
-                break;
-            case DISABLE:
-                if(getSubscriberBehaviour() == 
Behaviour.UpdateCostActionDisable) {
-                    
if(ev.getIdentifier().getMemberName().equals("updateCost")) {
-                        ev.disable("ToDoItemSubscriptions says: updateCost 
action disabled!");
-                    }
-                }
-                break;
-            case VALIDATE:
-                if(getSubscriberBehaviour() == 
Behaviour.UpdateCostActionInvalidate &&
-                        
ev.getIdentifier().getMemberName().equals("updateCost")) {
-                    ev.invalidate("ToDoItemSubscriptions says: can't invoke 
updateCost action with these args!");
-                }
-                break;
-            case EXECUTING:
-                break;
-            case EXECUTED:
-                LOG.info("Received ActionDomainEvent, " + 
ev.getSource().toString() + ", invoked " + ev.getIdentifier().getMemberName());
-                onExecutedThrowExceptionIfSet(ev);
-                break;
-        }
-    }
-
-    @Programmatic
-    @Subscribe
-    public void on(PropertyDomainEvent<?,?> ev) {
-        recordEvent(ev);
-        switch(ev.getEventPhase()) {
-            case HIDE:
-                if(getSubscriberBehaviour() == 
Behaviour.DescriptionPropertyHide &&
-                    ev.getIdentifier().getMemberName().equals("description")) {
-                    ev.veto("");
-                }
-                break;
-            case DISABLE:
-                if(getSubscriberBehaviour() == 
Behaviour.DescriptionPropertyDisable &&
-                    ev.getIdentifier().getMemberName().equals("description")) {
-                    ev.veto("ToDoItemSubscriptions says: description property 
disabled!");
-                }
-                break;
-            case VALIDATE:
-                if(getSubscriberBehaviour() == 
Behaviour.DescriptionPropertyInvalidate &&
-                    ev.getIdentifier().getMemberName().equals("description")) {
-                    ev.veto("ToDoItemSubscriptions says: can't change 
description property to this value!");
-                }
-                break;
-            case EXECUTING:
-                break;
-            case EXECUTED:
-                LOG.info("Received PropertyDomainEvent, " + 
ev.getSource().toString() + ", changed " + ev.getIdentifier().getMemberName() + 
" : " + ev.getOldValue() + " -> " + ev.getNewValue());
-                onExecutedThrowExceptionIfSet(ev);
-
-                if(ev.getIdentifier().getMemberName().contains("description")) 
{
-                    String newValue = (String) ev.getNewValue();
-                    if(newValue.matches(".*demo veto.*")) {
-                        throw new RecoverableException("oh no you don't! " + 
ev.getNewValue());
-                    }
-                }
-                break;
-        }
-    }
-
-    @Programmatic
-    @Subscribe
-    public void on(CollectionDomainEvent<?,?> ev) {
-        recordEvent(ev);
-        switch (ev.getEventPhase()) {
-            case HIDE:
-                if(getSubscriberBehaviour() == 
Behaviour.DependenciesCollectionHide &&
-                    ev.getIdentifier().getMemberName().equals("dependencies")) 
{
-                    ev.veto("");
-                }
-                if (getSubscriberBehaviour() == 
Behaviour.SimilarToCollectionHide &&
-                    ev.getIdentifier().getMemberName().equals("similarTo")) {
-                    ev.veto("");
-                }
-                break;
-            case DISABLE:
-                if (getSubscriberBehaviour() == 
Behaviour.DependenciesCollectionDisable &&
-                    ev.getIdentifier().getMemberName().equals("dependencies")) 
{
-                    ev.veto("ToDoItemSubscriptions says: dependencies 
collection disabled!");
-                }
-                break;
-            case VALIDATE:
-                if(getSubscriberBehaviour() == 
Behaviour.DependenciesCollectionInvalidateAdd &&
-                    ev.getIdentifier().getMemberName().equals("dependencies") 
&&
-                    ev.getOf() == CollectionDomainEvent.Of.ADD_TO ) {
-                    ev.veto("ToDoItemSubscriptions says: can't add this object 
to dependencies collection!");
-                }
-                if(getSubscriberBehaviour() == 
Behaviour.DependenciesCollectionInvalidateRemove &&
-                    ev.getIdentifier().getMemberName().equals("dependencies") 
&&
-                    ev.getOf() == CollectionDomainEvent.Of.REMOVE_FROM ) {
-                    ev.veto("ToDoItemSubscriptions says: can't remove this 
object from dependencies collection!");
-                }
-                break;
-            case EXECUTING:
-                break;
-            case EXECUTED:
-                if(ev.getOf() == CollectionDomainEvent.Of.ADD_TO) {
-                    LOG.info("Received CollectionDomainEvent, " + 
ev.getSource().toString() + ", added to " + ev.getIdentifier().getMemberName() 
+ " : " + ev.getValue());
-                } else {
-                    LOG.info("Received CollectionDomainEvent, " + 
ev.getSource().toString() + ", removed from " + 
ev.getIdentifier().getMemberName() + " : " + ev.getValue());
-                }
-                onExecutedThrowExceptionIfSet(ev);
-                break;
-        }
-
-    }
-
-    //endregion
-
-    //region > receivedEvents
-    private final List<java.util.EventObject> receivedEvents = 
Lists.newLinkedList();
-
-    /**
-     * Used in integration tests.
-     */
-    @Programmatic
-    public List<java.util.EventObject> receivedEvents() {
-        return receivedEvents;
-    }
-
-    /**
-     * Used in integration tests.
-     */
-    @Programmatic
-    public <T extends java.util.EventObject> List<T> receivedEvents(final 
Class<T> expectedType) {
-        return newArrayList(
-                    transform(
-                        filter(receivedEvents, instanceOf(expectedType)),
-                        castTo(expectedType)));
-    }
-
-    private static <T extends EventObject> Function<EventObject, T> 
castTo(Class<T> expectedType) {
-        return new Function<EventObject, T>() {
-                    @Override
-                    public T apply(EventObject input) {
-                        return (T) input;
-                    }
-                };
-    }
-
-    private static <T extends EventObject> Predicate<EventObject> 
instanceOf(final Class<T> expectedType) {
-        return new Predicate<EventObject>() {
-            @Override
-            public boolean apply(EventObject input) {
-                return expectedType.isInstance(input);
-            }
-        };
-    }
-
-    /**
-     * Used in integration tests.
-     */
-    @Programmatic
-    public <T extends java.util.EventObject> T 
mostRecentlyReceivedEvent(Class<T> expectedType) {
-        final List<T> receivedEvents = receivedEvents(expectedType);
-        return !receivedEvents.isEmpty() ? receivedEvents.get(0) : null;
-    }
-    private void recordEvent(final java.util.EventObject ev) {
-        receivedEvents.add(0, ev);
-    }
-    /**
-     * Used in integration tests.
-     */
-    @Programmatic
-    public void reset() {
-        receivedEvents.clear();
-        subscriberBehaviour(ToDoItemSubscriptions.Behaviour.AnyExecuteAccept);
-    }
-    //endregion
-
-    //region > injected services
-    @javax.inject.Inject
-    private DomainObjectContainer container;
-
-    @javax.inject.Inject
-    private EventBusService eventBusService;
-    //endregion
-
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/a4ec0b72/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItems.java
----------------------------------------------------------------------
diff --git 
a/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItems.java 
b/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItems.java
deleted file mode 100644
index da392a5..0000000
--- a/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItems.java
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package dom.todo;
-
-import dom.todo.ToDoItem.Category;
-import dom.todo.ToDoItem.Subcategory;
-
-import java.math.BigDecimal;
-import java.util.List;
-import com.google.common.base.Predicates;
-import org.joda.time.LocalDate;
-import org.apache.isis.applib.DomainObjectContainer;
-import org.apache.isis.applib.annotation.Action;
-import org.apache.isis.applib.annotation.ActionLayout;
-import org.apache.isis.applib.annotation.BookmarkPolicy;
-import org.apache.isis.applib.annotation.DomainService;
-import org.apache.isis.applib.annotation.DomainServiceLayout;
-import org.apache.isis.applib.annotation.RestrictTo;
-import org.apache.isis.applib.annotation.MemberOrder;
-import org.apache.isis.applib.annotation.Optionality;
-import org.apache.isis.applib.annotation.Parameter;
-import org.apache.isis.applib.annotation.ParameterLayout;
-import org.apache.isis.applib.annotation.Programmatic;
-import org.apache.isis.applib.annotation.SemanticsOf;
-import org.apache.isis.applib.query.QueryDefault;
-import org.apache.isis.applib.services.clock.ClockService;
-
-@DomainServiceLayout(named="ToDos", menuOrder = "10")
-@DomainService(repositoryFor = ToDoItem.class)
-public class ToDoItems {
-
-    //region > notYetComplete (action)
-    @Action(semantics = SemanticsOf.SAFE)
-    @ActionLayout(
-        cssClassFa = "fa fa-thumbs-down",
-        bookmarking = BookmarkPolicy.AS_ROOT
-    )
-    @MemberOrder(sequence = "10")
-    public List<ToDoItem> notYetComplete() {
-        final List<ToDoItem> items = notYetCompleteNoUi();
-        if(items.isEmpty()) {
-            container.informUser("All to-do items have been completed :-)");
-        }
-        return items;
-    }
-
-    @Programmatic
-    public List<ToDoItem> notYetCompleteNoUi() {
-        return container.allMatches(
-                new QueryDefault<>(ToDoItem.class,
-                        "findByOwnedByAndCompleteIsFalse", 
-                        "ownedBy", currentUserName()));
-    }
-    //endregion
-
-    //region > complete (action)
-    @ActionLayout(
-        cssClassFa = "fa fa-thumbs-up"
-    )
-    @Action(semantics = SemanticsOf.SAFE)
-    @MemberOrder(sequence = "20")
-    public List<ToDoItem> complete() {
-        final List<ToDoItem> items = completeNoUi();
-        if(items.isEmpty()) {
-            container.informUser("No to-do items have yet been completed :-(");
-        }
-        return items;
-    }
-
-    @Programmatic
-    public List<ToDoItem> completeNoUi() {
-        return container.allMatches(
-            new QueryDefault<>(ToDoItem.class,
-                    "findByOwnedByAndCompleteIsTrue", 
-                    "ownedBy", currentUserName()));
-    }
-    //endregion
-
-    //region > categorized (action)
-    @SuppressWarnings("unchecked")
-    @Action(semantics = SemanticsOf.SAFE)
-    @ActionLayout(
-        cssClassFa = "fa fa-question",
-        bookmarking = BookmarkPolicy.AS_ROOT
-    )
-    @MemberOrder(sequence = "40")
-    public List<ToDoItem> categorized(
-               @ParameterLayout(named="Category") final Category category,
-               @ParameterLayout(named="Subcategory") final Subcategory 
subcategory,
-               @ParameterLayout(named="Completed?") final boolean completed) {
-       // an example "naive" implementation (filtered in Java code, not DBMS)
-        return container.allMatches(ToDoItem.class, 
-                Predicates.and(
-                    ToDoItem.Predicates.thoseOwnedBy(currentUserName()), 
-                    ToDoItem.Predicates.thoseCompleted(completed),
-                    ToDoItem.Predicates.thoseCategorised(category, 
subcategory)));
-    }
-    public Category default0Categorized() {
-        return Category.Professional;
-    }
-    public Subcategory default1Categorized() {
-        return default0Categorized().subcategories().get(0);
-    }
-    public boolean default2Categorized() {
-        return false;
-    }
-    public List<Subcategory> choices1Categorized(
-            final Category category) {
-        return Subcategory.listFor(category);
-    }
-    public String validateCategorized(
-            final Category category, 
-            final Subcategory subcategory, 
-            final boolean completed) {
-        return Subcategory.validate(category, subcategory);
-    }
-    //endregion
-
-    //region > newToDo (action)
-    @ActionLayout(cssClassFa = "fa fa-plus")
-    @MemberOrder(sequence = "5")
-    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);
-    }
-    public Category default1NewToDo() {
-        return Category.Professional;
-    }
-    public Subcategory default2NewToDo() {
-        return Category.Professional.subcategories().get(0);
-    }
-    public LocalDate default3NewToDo() {
-        return clockService.now().plusDays(14);
-    }
-    public List<Subcategory> choices2NewToDo(
-            final String description, final Category category) {
-        return Subcategory.listFor(category);
-    }
-    public String validateNewToDo(
-            final String description, 
-            final Category category, final Subcategory subcategory, 
-            final LocalDate dueBy, final BigDecimal cost) {
-        return Subcategory.validate(category, subcategory);
-    }
-    //endregion
-
-    //region > allToDos (action)
-    @ActionLayout(
-        cssClassFa = "fa fa-globe"
-    )
-    @Action(
-            semantics = SemanticsOf.SAFE,
-            restrictTo = RestrictTo.PROTOTYPING
-    )
-    @MemberOrder(sequence = "50")
-    public List<ToDoItem> allToDos() {
-        final List<ToDoItem> items = container.allMatches(
-                new QueryDefault<>(ToDoItem.class,
-                        "findByOwnedBy", 
-                        "ownedBy", currentUserName()));
-        if(items.isEmpty()) {
-            container.warnUser("No to-do items found.");
-        }
-        return items;
-    }
-    //endregion
-
-    //region > autoComplete (programmatic)
-    @Programmatic // not part of metamodel
-    public List<ToDoItem> autoComplete(final String description) {
-        return container.allMatches(
-                new QueryDefault<>(ToDoItem.class,
-                        "findByOwnedByAndDescriptionContains", 
-                        "ownedBy", currentUserName(), 
-                        "description", description));
-    }
-    //endregion
-
-    //region > helpers
-    @Programmatic // for use by fixtures
-    public ToDoItem newToDo(
-            final String description, 
-            final Category category, 
-            final Subcategory subcategory,
-            final String userName, 
-            final LocalDate dueBy, final BigDecimal cost) {
-        final ToDoItem toDoItem = 
container.newTransientInstance(ToDoItem.class);
-        toDoItem.setDescription(description);
-        toDoItem.setCategory(category);
-        toDoItem.setSubcategory(subcategory);
-        toDoItem.setOwnedBy(userName);
-        toDoItem.setDueBy(dueBy);
-        toDoItem.setCost(cost);
-
-        container.persist(toDoItem);
-        container.flush();
-
-        return toDoItem;
-    }
-    
-    private String currentUserName() {
-        return container.getUser().getName();
-    }
-
-    //endregion
-
-    //region > common validation
-    private static final long ONE_WEEK_IN_MILLIS = 7 * 24 * 60 * 60 * 1000L;
-
-    @Programmatic
-    public String validateDueBy(final LocalDate dueBy) {
-        return isMoreThanOneWeekInPast(dueBy) ? "Due by date cannot be more 
than one week old" : null;
-    }
-    @Programmatic
-    boolean isMoreThanOneWeekInPast(final LocalDate dueBy) {
-        return dueBy.toDateTimeAtStartOfDay().getMillis() < 
clockService.nowAsMillis() - ONE_WEEK_IN_MILLIS;
-    }
-    //endregion
-
-    //region > injected services
-    @javax.inject.Inject
-    private DomainObjectContainer container;
-
-    @javax.inject.Inject
-    private ClockService clockService;
-    //endregion
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/a4ec0b72/example/application/todoapp/dom/src/test/java/dom/todo/ToDoItemTest.java
----------------------------------------------------------------------
diff --git 
a/example/application/todoapp/dom/src/test/java/dom/todo/ToDoItemTest.java 
b/example/application/todoapp/dom/src/test/java/dom/todo/ToDoItemTest.java
deleted file mode 100644
index b1f5168..0000000
--- a/example/application/todoapp/dom/src/test/java/dom/todo/ToDoItemTest.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/**
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package dom.todo;
-
-import org.jmock.Expectations;
-import org.jmock.auto.Mock;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.apache.isis.applib.DomainObjectContainer;
-import org.apache.isis.applib.services.actinvoc.ActionInvocationContext;
-import org.apache.isis.applib.security.RoleMemento;
-import org.apache.isis.applib.security.UserMemento;
-import org.apache.isis.applib.services.eventbus.EventBusService;
-import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2;
-import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2.Mode;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.not;
-import static org.hamcrest.CoreMatchers.nullValue;
-import static org.junit.Assert.assertThat;
-
-public abstract class ToDoItemTest {
-
-    @Rule
-    public JUnitRuleMockery2 context = 
JUnitRuleMockery2.createFor(Mode.INTERFACES_AND_CLASSES);
-
-    @Mock
-    EventBusService eventBusService;
-
-    ToDoItem toDoItem;
-
-    @Before
-    public void setUp() throws Exception {
-        toDoItem = new ToDoItem();
-
-        toDoItem.actionInvocationContext = 
ActionInvocationContext.onObject(toDoItem);
-        toDoItem.eventBusService = eventBusService;
-
-        context.ignoring(eventBusService);
-    }
-
-    public static class Properties extends ToDoItemTest {
-
-        @Mock
-        DomainObjectContainer mockContainer;
-
-        public static class DueBy extends Properties {
-
-            @Test
-            public void hiddenForNoDueByRole() {
-                final UserMemento userWithRole = new UserMemento("user", new 
RoleMemento("realm1:noDueBy_role"));
-                context.checking(new Expectations() {{
-                    allowing(mockContainer).getUser();
-                    will(returnValue(userWithRole));
-                }});
-
-                toDoItem.container = mockContainer;
-
-                assertThat(toDoItem.hideDueBy(), is(true));
-            }
-
-            @Test
-            public void notHiddenWithoutRole() {
-                final UserMemento userWithRole = new UserMemento("user", new 
RoleMemento("realm1:someOtherRole"));
-                context.checking(new Expectations() {{
-                    allowing(mockContainer).getUser();
-                    will(returnValue(userWithRole));
-                }});
-
-                toDoItem.container = mockContainer;
-
-                assertThat(toDoItem.hideDueBy(), is(false));
-            }
-        }
-
-    }
-
-    public static class Actions extends ToDoItemTest {
-
-        public static class Completed extends Actions {
-
-            @Test
-            public void happyCase() throws Exception {
-
-                // given
-                toDoItem.setComplete(false);
-                assertThat(toDoItem.disableCompleted(), is(nullValue()));
-
-                // when
-                toDoItem.completed();
-
-                // then
-                assertThat(toDoItem.isComplete(), is(true));
-                assertThat(toDoItem.disableCompleted(), is(not(nullValue())));
-            }
-        }
-
-        public static class NotYetCompleted extends Actions {
-
-            @Test
-            public void happyCase() throws Exception {
-
-                // given
-                toDoItem.setComplete(true);
-                assertThat(toDoItem.disableNotYetCompleted(), is(nullValue()));
-
-                // when
-                toDoItem.notYetCompleted();
-
-                // then
-                assertThat(toDoItem.isComplete(), is(false));
-                assertThat(toDoItem.disableNotYetCompleted(), 
is(not(nullValue())));
-            }
-        }
-    }
-
-
-}

Reply via email to