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 2012/12/06 11:10:34 UTC

[20/51] [partial] ISIS-188: moving modules into core

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/events/InteractionEvent.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/events/InteractionEvent.java b/framework/core/applib/src/main/java/org/apache/isis/applib/events/InteractionEvent.java
new file mode 100644
index 0000000..65e44f6
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/events/InteractionEvent.java
@@ -0,0 +1,177 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.events;
+
+import java.util.EventObject;
+import java.util.List;
+
+import org.apache.isis.applib.Identifier;
+
+/**
+ * Represents an interaction with a domain object or a particular feature
+ * (property, collection, action) of a domain object.
+ * 
+ * <p>
+ * Many of the interactions are checks for {@link VisibilityEvent visibility},
+ * {@link UsabilityEvent usability} and {@link ValidityEvent validity}.
+ */
+public abstract class InteractionEvent extends EventObject {
+
+    private static final long serialVersionUID = 1L;
+
+    private final Identifier identifier;
+    private String reason;
+    private Class<?> advisorClass;
+
+    public InteractionEvent(final Object source, final Identifier identifier) {
+        super(source);
+        this.identifier = identifier;
+    }
+
+    /**
+     * The domain object (pojo) against which the interaction occurred.
+     */
+    @Override
+    public Object getSource() {
+        return super.getSource();
+    }
+
+    /**
+     * The {@link Identifier} of the feature of the object being interacted
+     * with.
+     * 
+     * <p>
+     * Will be consistent with the subclass of {@link InteractionEvent}. So for
+     * example a {@link PropertyModifyEvent} will have an {@link Identifier}
+     * that identifies the property being modified.
+     * 
+     * @return
+     */
+    public Identifier getIdentifier() {
+        return identifier;
+    }
+
+    /**
+     * As per {@link #getClassName()}, but naturalized.
+     * 
+     * @see #getIdentifier
+     */
+    public String getClassName() {
+        return identifier.getClassName();
+    }
+
+    /**
+     * Convenience method that returns the
+     * {@link Identifier#getClassNaturalName() natural class name} of the
+     * {@link #getIdentifier() identifier}.
+     */
+    public String getClassNaturalName() {
+        return identifier.getClassNaturalName();
+    }
+
+    /**
+     * Convenience method that returns the {@link Identifier#getMemberName()
+     * member name} of the {@link #getIdentifier() identifier}.
+     * 
+     * @see #getIdentifier
+     */
+    public String getMemberName() {
+        return identifier.getMemberName();
+    }
+
+    /**
+     * As per {@link #getMemberName()}, but naturalized.
+     */
+    public String getMemberNaturalName() {
+        return identifier.getMemberNaturalName();
+    }
+
+    /**
+     * Convenience method that returns the {@link Identifier#getClassName()
+     * class name} of the {@link #getIdentifier() identifier}.
+     */
+    public List<String> getMemberParameterNames() {
+        return identifier.getMemberParameterNames();
+    }
+
+    /**
+     * As per {@link #getMemberParameterName()}, but naturalized.
+     */
+    public List<String> getMemberParameterNaturalNames() {
+        return identifier.getMemberParameterNaturalNames();
+    }
+
+    /**
+     * The reason, if any, that this interaction may have been vetoed or
+     * otherwise disallowed.
+     * 
+     * <p>
+     * Intended to be {@link #setReason(String) set} as a result of consulting
+     * one of the facets.
+     * 
+     * @return
+     */
+    public String getReason() {
+        return reason;
+    }
+
+    /**
+     * The class of the (first) advisor, if any, that provided the
+     * {@link #getReason() reason} that this interaction is {@link #isVeto()
+     * vetoed}.
+     * 
+     * @return
+     */
+    public Class<?> getAdvisorClass() {
+        return advisorClass;
+    }
+
+    /**
+     * Specify the {@link #getReason() reason} that this interaction has been
+     * vetoed and the {@link #getAdvisorClass() class of the advisor} that did
+     * the veto.
+     */
+    public void advised(final String reason, final Class<?> advisorClass) {
+        this.reason = reason;
+        this.advisorClass = advisorClass;
+    }
+
+    /**
+     * Whether this interaction has been vetoed (meaning that
+     * {@link #getReason()} and {@link #getAdvisorClass()} will both be non-
+     * <tt>null</tt> and the {@link #getReason() reason} non-empty.)
+     * 
+     * <p>
+     * The interpretation of this depends on the subclass:
+     * <ul>
+     * <li>for {@link VisibilityEvent}, a veto means that the feature (property,
+     * collection, action) is hidden</li>
+     * <li>for {@link UsabilityEvent}, a veto means that the feature is disabled
+     * </li>
+     * <li>for {@link ValidityEvent}, a veto means that the proposed
+     * modification (property value, object added/removed, action argument) is
+     * invalid</li>
+     * </ul>
+     */
+    public boolean isVeto() {
+        return getReason() != null && getReason().length() > 0;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/events/ObjectTitleEvent.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/events/ObjectTitleEvent.java b/framework/core/applib/src/main/java/org/apache/isis/applib/events/ObjectTitleEvent.java
new file mode 100644
index 0000000..c4e19c2
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/events/ObjectTitleEvent.java
@@ -0,0 +1,46 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.events;
+
+import org.apache.isis.applib.Identifier;
+
+/**
+ * Represents an access (reading) of an object's title.
+ * 
+ * <p>
+ * The {@link #getReason()} will always be <tt>null</tt>; access is always
+ * allowed.
+ */
+public class ObjectTitleEvent extends AccessEvent {
+
+    private static final long serialVersionUID = 1L;
+
+    private final String title;
+
+    public ObjectTitleEvent(final Object source, final Identifier classIdentifier, final String title) {
+        super(source, classIdentifier);
+        this.title = title;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/events/ObjectValidityEvent.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/events/ObjectValidityEvent.java b/framework/core/applib/src/main/java/org/apache/isis/applib/events/ObjectValidityEvent.java
new file mode 100644
index 0000000..0266196
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/events/ObjectValidityEvent.java
@@ -0,0 +1,46 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.events;
+
+import org.apache.isis.applib.Identifier;
+
+/**
+ * Represents a check as to whether the current values of the
+ * properties/collections of an object are valid (for example, prior to saving
+ * that object).
+ * 
+ * <p>
+ * If {@link #getReason()} is not <tt>null</tt> then provides the reason why the
+ * object is invalid, otherwise ok.
+ */
+public class ObjectValidityEvent extends ValidityEvent {
+
+    private static final long serialVersionUID = 1L;
+
+    public ObjectValidityEvent(final Object source, final Identifier classIdentifier) {
+        super(source, classIdentifier);
+    }
+
+    @Override
+    public Object getProposed() {
+        return getSource();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/events/ParseValueEvent.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/events/ParseValueEvent.java b/framework/core/applib/src/main/java/org/apache/isis/applib/events/ParseValueEvent.java
new file mode 100644
index 0000000..36566b1
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/events/ParseValueEvent.java
@@ -0,0 +1,62 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.events;
+
+import org.apache.isis.applib.Identifier;
+
+/**
+ * Represents a check as to whether the proposed values of the value type is
+ * valid.
+ * 
+ * <p>
+ * If {@link #getReason()} is not <tt>null</tt> then provides the reason why the
+ * proposed value is invalid, otherwise the new value is acceptable.
+ */
+public class ParseValueEvent extends ValidityEvent {
+
+    private static final long serialVersionUID = 1L;
+
+    private static Object coalesce(final Object source, final String proposed) {
+        return source != null ? source : proposed;
+    }
+
+    private final String proposed;
+
+    public ParseValueEvent(final Object source, final Identifier classIdentifier, final String proposed) {
+        super(coalesce(source, proposed), classIdentifier);
+        this.proposed = proposed;
+    }
+
+    /**
+     * Will be the source provided in the
+     * {@link #ParseValueEvent(Object, Identifier, String) constructor} if not
+     * null, otherwise will fallback to the proposed value.
+     */
+    @Override
+    public Object getSource() {
+        return super.getSource();
+    }
+
+    @Override
+    public String getProposed() {
+        return proposed;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/events/PropertyAccessEvent.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/events/PropertyAccessEvent.java b/framework/core/applib/src/main/java/org/apache/isis/applib/events/PropertyAccessEvent.java
new file mode 100644
index 0000000..090f949
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/events/PropertyAccessEvent.java
@@ -0,0 +1,47 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.events;
+
+import org.apache.isis.applib.Identifier;
+
+/**
+ * Represents an access (reading) of a property.
+ * 
+ * <p>
+ * Analogous to {@link PropertyModifyEvent}, however the {@link #getReason()}
+ * will always be <tt>null</tt>. (If access is not allowed then a
+ * {@link PropertyVisibilityEvent} would have been fired).
+ */
+public class PropertyAccessEvent extends AccessEvent {
+
+    private static final long serialVersionUID = 1L;
+
+    public PropertyAccessEvent(final Object source, final Identifier propertyIdentifier, final Object value) {
+        super(source, propertyIdentifier);
+        this.value = value;
+    }
+
+    private final Object value;
+
+    public Object getValue() {
+        return value;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/events/PropertyModifyEvent.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/events/PropertyModifyEvent.java b/framework/core/applib/src/main/java/org/apache/isis/applib/events/PropertyModifyEvent.java
new file mode 100644
index 0000000..33be17e
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/events/PropertyModifyEvent.java
@@ -0,0 +1,53 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.events;
+
+import org.apache.isis.applib.Identifier;
+
+/**
+ * Represents a check as to whether a particular value for a property is valid
+ * or not.
+ * 
+ * <p>
+ * If {@link #getReason()} is not <tt>null</tt> then provides the reason why the
+ * value is invalid; otherwise the value is valid.
+ */
+public class PropertyModifyEvent extends ValidityEvent {
+
+    private static final long serialVersionUID = 1L;
+
+    private final Object proposed;
+
+    public PropertyModifyEvent(final Object source, final Identifier propertyIdentifier, final Object proposed) {
+        super(source, propertyIdentifier);
+        this.proposed = proposed;
+    }
+
+    /**
+     * If <tt>null</tt>, then the property was cleared.
+     * 
+     * @return
+     */
+    @Override
+    public Object getProposed() {
+        return proposed;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/events/PropertyUsabilityEvent.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/events/PropertyUsabilityEvent.java b/framework/core/applib/src/main/java/org/apache/isis/applib/events/PropertyUsabilityEvent.java
new file mode 100644
index 0000000..a4a94d2
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/events/PropertyUsabilityEvent.java
@@ -0,0 +1,39 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.events;
+
+import org.apache.isis.applib.Identifier;
+
+/**
+ * Represents a check as to whether a property is usable or has been disabled.
+ * 
+ * <p>
+ * If {@link #getReason()} is not <tt>null</tt> then provides the reason why the
+ * property is disabled; otherwise property is enabled.
+ */
+public class PropertyUsabilityEvent extends UsabilityEvent {
+
+    private static final long serialVersionUID = 1L;
+
+    public PropertyUsabilityEvent(final Object source, final Identifier propertyIdentifier) {
+        super(source, propertyIdentifier);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/events/PropertyVisibilityEvent.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/events/PropertyVisibilityEvent.java b/framework/core/applib/src/main/java/org/apache/isis/applib/events/PropertyVisibilityEvent.java
new file mode 100644
index 0000000..c8b72e4
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/events/PropertyVisibilityEvent.java
@@ -0,0 +1,39 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.events;
+
+import org.apache.isis.applib.Identifier;
+
+/**
+ * Represents a check as to whether a property is visible or has been hidden.
+ * 
+ * <p>
+ * If {@link #getReason()} is not <tt>null</tt> then provides the reason why the
+ * property is invisible; otherwise property is visible.
+ */
+public class PropertyVisibilityEvent extends VisibilityEvent {
+
+    private static final long serialVersionUID = 1L;
+
+    public PropertyVisibilityEvent(final Object source, final Identifier propertyIdentifier) {
+        super(source, propertyIdentifier);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/events/ProposedHolderEvent.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/events/ProposedHolderEvent.java b/framework/core/applib/src/main/java/org/apache/isis/applib/events/ProposedHolderEvent.java
new file mode 100644
index 0000000..5358bbb
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/events/ProposedHolderEvent.java
@@ -0,0 +1,33 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.events;
+
+/**
+ * Makes it easier to process different events that hold a single proposed
+ * argument (such as {@link CollectionAddToEvent} and
+ * {@link PropertyModifyEvent}).
+ */
+public interface ProposedHolderEvent {
+
+    Object getProposed();
+
+    String getMemberNaturalName();
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/events/UsabilityEvent.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/events/UsabilityEvent.java b/framework/core/applib/src/main/java/org/apache/isis/applib/events/UsabilityEvent.java
new file mode 100644
index 0000000..7792bdd
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/events/UsabilityEvent.java
@@ -0,0 +1,44 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.events;
+
+import org.apache.isis.applib.Identifier;
+
+/**
+ * Represents a check to determine whether a member of an object is usable or
+ * has been disabled.
+ * 
+ * <p>
+ * If {@link #getReason()} is <tt>null</tt>, then is usable; otherwise is
+ * disabled.
+ * 
+ * @see AccessEvent
+ * @see VisibilityEvent
+ * @see ValidityEvent
+ */
+public abstract class UsabilityEvent extends InteractionEvent {
+
+    private static final long serialVersionUID = 1L;
+
+    public UsabilityEvent(final Object source, final Identifier identifier) {
+        super(source, identifier);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/events/ValidityEvent.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/events/ValidityEvent.java b/framework/core/applib/src/main/java/org/apache/isis/applib/events/ValidityEvent.java
new file mode 100644
index 0000000..5680db7
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/events/ValidityEvent.java
@@ -0,0 +1,57 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.events;
+
+import org.apache.isis.applib.Identifier;
+
+/**
+ * Represents a check to determine whether a proposed change is valid.
+ * 
+ * <p>
+ * Multiple subclasses, including:
+ * <ul>
+ * <li>modifying a property</li>
+ * <li>adding to/removing from a collection</li>
+ * <li>checking a single argument for an action invocation</li>
+ * <li>checking all arguments for an action invocation</li>
+ * <li>checking all properties for an object before saving</li>
+ * </ul>
+ * 
+ * <p>
+ * If {@link #getReason()} is <tt>null</tt>, then is usable; otherwise is
+ * disabled.
+ * 
+ * @see AccessEvent
+ * @see VisibilityEvent
+ * @see UsabilityEvent
+ */
+public abstract class ValidityEvent extends InteractionEvent implements ProposedHolderEvent {
+
+    private static final long serialVersionUID = 1L;
+
+    public ValidityEvent(final Object source, final Identifier identifier) {
+        super(source, identifier);
+    }
+
+    @Override
+    public Object getSource() {
+        return super.getSource();
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/events/VisibilityEvent.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/events/VisibilityEvent.java b/framework/core/applib/src/main/java/org/apache/isis/applib/events/VisibilityEvent.java
new file mode 100644
index 0000000..a306b02
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/events/VisibilityEvent.java
@@ -0,0 +1,44 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.events;
+
+import org.apache.isis.applib.Identifier;
+
+/**
+ * Represents a check to determine whether a member of an object is visible or
+ * has been hidden.
+ * 
+ * <p>
+ * If {@link #getReason()} is <tt>null</tt>, then is usable; otherwise is
+ * invisible.
+ * 
+ * @see AccessEvent
+ * @see UsabilityEvent
+ * @see ValidityEvent
+ */
+public abstract class VisibilityEvent extends InteractionEvent {
+
+    private static final long serialVersionUID = 1L;
+
+    public VisibilityEvent(final Object source, final Identifier identifier) {
+        super(source, identifier);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/events/package-info.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/events/package-info.java b/framework/core/applib/src/main/java/org/apache/isis/applib/events/package-info.java
new file mode 100644
index 0000000..9849bab
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/events/package-info.java
@@ -0,0 +1,30 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+/**
+ * Interaction events, corresponding to gestures in the user interface.
+ * 
+ * <p>
+ * The applib does not provide any means of listening to these events directly, and typically
+ * domain objects would not be interested in them either.  However, they can be subscribed to
+ * using the wrapper progmodel (which effectively provides a drop-in replacement for the
+ * {@link org.apache.isis.applib.DomainObjectContainer} that implements the <tt>WrapperFactory</tt>
+ * interface).  
+ */
+package org.apache.isis.applib.events;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/filter/Filter.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/filter/Filter.java b/framework/core/applib/src/main/java/org/apache/isis/applib/filter/Filter.java
new file mode 100644
index 0000000..57095cf
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/filter/Filter.java
@@ -0,0 +1,47 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.filter;
+
+import com.google.common.base.Predicate;
+
+/**
+ * For use by repository implementations to allow a set of objects returned by a
+ * back-end objectstore to be filtered before being returned to the caller.
+ * 
+ * <p>
+ * Note that this is different from the pattern or criteria object accepted by
+ * some repositories' <tt>findXxx</tt> methods. Such criteria objects are
+ * implementation-specific to the configured objectstore and allow it to return
+ * an already-filtered set of rows. (For example, a Hibernate-based ObjectStore
+ * would accept a representation of a HQL query; an XML-based objectstore might
+ * accept an XPath query, etc.)
+ */
+public interface Filter<T> {
+
+    /**
+     * Whether or not the supplied pojo meets this criteria.
+     * 
+     * @param pojo
+     * @return <tt>true</tt> if this pojo is acceptable, <tt>false</tt>
+     *         otherwise.
+     */
+    public boolean accept(T t);
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/filter/Filters.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/filter/Filters.java b/framework/core/applib/src/main/java/org/apache/isis/applib/filter/Filters.java
new file mode 100644
index 0000000..96a08c0
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/filter/Filters.java
@@ -0,0 +1,101 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.filter;
+
+import com.google.common.base.Predicate;
+
+public final class Filters {
+
+    private Filters() {
+    }
+
+    public static <T> Filter<T> and(final Filter<T>... filters) {
+        return new Filter<T>() {
+            @Override
+            public boolean accept(final T f) {
+                for(final Filter<T> filter: filters) {
+                    if(!filter.accept(f)) {     
+                        return false;
+                    }
+                }
+                return true;
+            }
+        };
+    }
+
+    public static <T> Filter<T> or(final Filter<T>... filters) {
+        return new Filter<T>() {
+            @Override
+            public boolean accept(final T f) {
+                for(final Filter<T> filter: filters) {
+                    if(filter.accept(f)) { 
+                        return true;
+                    }
+                }
+                return false;
+            }
+        };
+    }
+
+    public static <T> Filter<T> not(final Filter<T> f1) {
+        return new Filter<T>() {
+            @Override
+            public boolean accept(final T f) {
+                return !f1.accept(f);
+            }
+        };
+    }
+
+    public static <T> Filter<T> any() {
+        return new Filter<T>() {
+            @Override
+            public boolean accept(final T t) {
+                return true;
+            }
+        };
+    }
+
+    public final static <T> Filter<T> anyOfType(final Class<T> clazz) {
+        return any();
+    }
+
+    public static <T> Filter<T> none() {
+        return new Filter<T>() {
+            @Override
+            public boolean accept(final T f) {
+                return false;
+            }
+        };
+    }
+
+    public static <T> Filter<T> noneOfType(final Class<T> clazz) {
+        return none();
+    }
+
+    public static <T> Predicate<T> asPredicate(final Filter<T> filter) {
+        return new Predicate<T>() {
+            @Override
+            public boolean apply(T candidate) {
+                return filter.accept(candidate);
+            }
+        };
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/filter/package-info.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/filter/package-info.java b/framework/core/applib/src/main/java/org/apache/isis/applib/filter/package-info.java
new file mode 100644
index 0000000..7d3131b
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/filter/package-info.java
@@ -0,0 +1,29 @@
+/*
+ *  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.
+ */
+
+/**
+ * This package defines a {@link org.apache.isis.applib.filter.Filter} interface,
+ * useful in particular for writing (naive) repositories but also useful
+ * more generally.
+ * 
+ * <p>
+ * It also defines a supporting {@link org.apache.isis.applib.filter.Filters utility class}
+ * which can be used to combine {@link org.apache.isis.applib.filter.Filter}s.
+ */
+package org.apache.isis.applib.filter;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/AbstractFixture.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/AbstractFixture.java b/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/AbstractFixture.java
new file mode 100644
index 0000000..260e4da
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/AbstractFixture.java
@@ -0,0 +1,165 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.fixtures;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.fixtures.switchuser.SwitchUserService;
+import org.apache.isis.applib.fixtures.switchuser.SwitchUserServiceAware;
+
+/**
+ * Convenience class for creating fixtures.
+ * 
+ * <p>
+ * Most subclasses will simply override {@link #install()} to setup objects. In
+ * addition though fixtures may also:
+ * <ul>
+ * <li>change the date/time within the course of fixture installation, using
+ * {@link #setDate(int, int, int)} and {@link #setTime(int, int)}.
+ * <li>create composite fixtures using {@link #addFixture(Object)}.
+ * <li>search for existing objects using
+ * {@link #firstMatch(Class, org.apache.isis.applib.Filter)} or
+ * {@link #uniqueMatch(Class, org.apache.isis.applib.Filter)} (and various
+ * overloads thereof).
+ * </ul>
+ * 
+ * <p>
+ * This class has been designed so that it can also be used as a regular
+ * domain object.  This may be useful to allow users to setup demo data in a
+ * running application.
+ *  
+ * <p>
+ * To automatically logon for the demo/test, use {@link LogonFixture}.
+ */
+public abstract class AbstractFixture extends BaseFixture implements CompositeFixture {
+
+    private final List<Object> fixtures = new ArrayList<Object>();
+
+    // ///////////////////////////////////////////////////////////////
+    // Constructor
+    // ///////////////////////////////////////////////////////////////
+
+    /**
+     * Assumed to be {@link FixtureType#DOMAIN_OBJECTS data} fixture.
+     */
+    public AbstractFixture() {
+        this(FixtureType.DOMAIN_OBJECTS);
+    }
+
+    public AbstractFixture(final FixtureType fixtureType) {
+        super(fixtureType);
+    }
+
+    // ///////////////////////////////////////////////////////////////
+    // install() hook (for non-composites)
+    // ///////////////////////////////////////////////////////////////
+
+    /**
+     * Most subclasses will override this method, but composite fixtures should
+     * instead call {@link #addFixture(Object)} in their constructor.
+     * 
+     * <p>
+     * The iteration over the child fixtures is then performed by the
+     * <tt>FixturesInstallerDelegate</tt> (or equivalent).
+     * 
+     * <p>
+     * A slightly strange implementation?  Oh well, it works.
+     */
+    @Override
+    public void install() {
+    }
+
+    // ///////////////////////////////////////////////////////////////
+    // CompositeFixture impl
+    // ///////////////////////////////////////////////////////////////
+
+    /**
+     * Allows the fixture to act as a composite (call within constructor).
+     */
+    protected void addFixture(final Object fixture) {
+        fixtures.add(fixture);
+    }
+
+    /**
+     * Returns an array of any fixtures that have been
+     * {@link #addFixture(Object) added}.
+     */
+    @Programmatic // to allow this class to be used as a domain object
+    @Override
+    public List<Object> getFixtures() {
+        return Collections.unmodifiableList(fixtures);
+    }
+
+    // ///////////////////////////////////////////////////////////////
+    // Date and time
+    // ///////////////////////////////////////////////////////////////
+
+    /**
+     * Will print warning message and do nothing if {@link FixtureClock} could
+     * not be {@link FixtureClock#initialize() initialized}.
+     */
+    @Programmatic // to allow this class to be used as a domain object
+    public void earlierDate(final int years, final int months, final int days) {
+        if (shouldIgnoreCallBecauseNoClockSetup("earlierDate()")) {
+            return;
+        }
+        clock.addDate(-years, -months, -days);
+    }
+
+    /**
+     * Will print warning message and do nothing if {@link FixtureClock} could
+     * not be {@link FixtureClock#initialize() initialized}.
+     */
+    @Programmatic // to allow this class to be used as a domain object
+    public void earlierTime(final int hours, final int minutes) {
+        if (shouldIgnoreCallBecauseNoClockSetup("earlierTime()")) {
+            return;
+        }
+        clock.addTime(-hours, -minutes);
+    }
+
+    /**
+     * Will print warning message and do nothing if {@link FixtureClock} could
+     * not be {@link FixtureClock#initialize() initialized}.
+     */
+    @Programmatic // to allow this class to be used as a domain object
+    public void laterDate(final int years, final int months, final int days) {
+        if (shouldIgnoreCallBecauseNoClockSetup("laterDate()")) {
+            return;
+        }
+        clock.addDate(years, months, days);
+    }
+
+    /**
+     * Will print warning message and do nothing if {@link FixtureClock} could
+     * not be {@link FixtureClock#initialize() initialized}.
+     */
+    @Programmatic // to allow this class to be used as a domain object
+    public void laterTime(final int hours, final int minutes) {
+        if (shouldIgnoreCallBecauseNoClockSetup("laterTime()")) {
+            return;
+        }
+        clock.addTime(hours, minutes);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/AbstractFixtureSusa.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/AbstractFixtureSusa.java b/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/AbstractFixtureSusa.java
new file mode 100644
index 0000000..c804f52
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/AbstractFixtureSusa.java
@@ -0,0 +1,65 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.fixtures;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.isis.applib.fixtures.switchuser.SwitchUserService;
+import org.apache.isis.applib.fixtures.switchuser.SwitchUserServiceAware;
+
+/**
+ * Convenience class for creating fixtures, with support to allow
+ * users to be switching using the {@link SwitchUserService}.
+ * 
+ * <p>
+ * Note that unlike {@link AbstractFixture}, fixtures inheriting from
+ * this class <i>cannot</i> be used as domain objects (the {@link SwitchUserService} does
+ * not conform to the domain object programming conventions).
+ */
+public abstract class AbstractFixtureSusa extends AbstractFixture implements SwitchUserServiceAware {
+
+    public AbstractFixtureSusa() {
+        super();
+    }
+
+    public AbstractFixtureSusa(final FixtureType fixtureType) {
+        super(fixtureType);
+    }
+
+
+    // {{ User
+    protected void switchUser(final String username, final String... roles) {
+        switchUserService.switchUser(username, roles);
+    }
+
+    // }}
+
+    // {{ Injected: SwitchUserService
+    private SwitchUserService switchUserService;
+
+    @Override
+    public void setService(final SwitchUserService fixtureService) {
+        this.switchUserService = fixtureService;
+    }
+    // }}
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/BaseFixture.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/BaseFixture.java b/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/BaseFixture.java
new file mode 100644
index 0000000..96c150e
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/BaseFixture.java
@@ -0,0 +1,109 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.applib.fixtures;
+
+import org.apache.isis.applib.AbstractContainedObject;
+import org.apache.isis.applib.clock.Clock;
+
+abstract class BaseFixture extends AbstractContainedObject implements InstallableFixture {
+
+    private final FixtureType fixtureType;
+    FixtureClock clock = null;
+
+    public BaseFixture(final FixtureType fixtureType) {
+        this.fixtureType = fixtureType;
+        try {
+            clock = FixtureClock.initialize();
+        } catch (final IllegalStateException ex) {
+            clock = null;
+            System.err.println(ex.getMessage());
+            System.err.println("calls to change date or time will be ignored");
+        }
+    }
+
+    // /////////////////////////////////////////////////
+    // FixtureType
+    // /////////////////////////////////////////////////
+
+    /**
+     * As specified in constructor.
+     */
+    @Override
+    public final FixtureType getType() {
+        return fixtureType;
+    }
+
+    // /////////////////////////////////////////////////
+    // FixtureClock
+    // /////////////////////////////////////////////////
+
+    /**
+     * Will print warning message and do nothing if {@link FixtureClock} could
+     * not be {@link FixtureClock#initialize() initialized}.
+     */
+    public void setDate(final int year, final int month, final int day) {
+        if (shouldIgnoreCallBecauseNoClockSetup("setDate()")) {
+            return;
+        }
+        clock.setDate(year, month, day);
+    }
+
+    /**
+     * Will print warning message and do nothing if {@link FixtureClock} could
+     * not be {@link FixtureClock#initialize() initialized}.
+     */
+    public void setTime(final int hour, final int minute) {
+        if (shouldIgnoreCallBecauseNoClockSetup("setTime()")) {
+            return;
+        }
+        clock.setTime(hour, minute);
+    }
+
+    /**
+     * The {@link Clock} singleton, downcast to {@link FixtureClock}.
+     * 
+     * <p>
+     * Will return <tt>null</tt> if {@link FixtureClock} could not be
+     * {@link FixtureClock#initialize() initialized}.
+     */
+    public FixtureClock getFixtureClock() {
+        return clock;
+    }
+
+    /**
+     * Will print warning message and do nothing if {@link FixtureClock} could
+     * not be {@link FixtureClock#initialize() initialized}.
+     */
+    public void resetClock() {
+        if (shouldIgnoreCallBecauseNoClockSetup("resetClock()")) {
+            return;
+        }
+        clock.reset();
+    }
+
+    boolean shouldIgnoreCallBecauseNoClockSetup(final String methodName) {
+        if (clock == null) {
+            System.err.println("clock not set, call to " + methodName + " ignored");
+            return true;
+        }
+        return false;
+    }
+    // }}
+
+}
\ No newline at end of file

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

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/DateFixture.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/DateFixture.java b/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/DateFixture.java
new file mode 100644
index 0000000..a039ef9
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/DateFixture.java
@@ -0,0 +1,89 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.fixtures;
+
+/**
+ * Sole purpose is to set the date/time while object fixtures are being
+ * installed.
+ * 
+ * <p>
+ * An alternative is to change the date using
+ * {@link AbstractFixture#setDate(int, int, int)} and
+ * {@link AbstractFixture#setTime(int, int)}.
+ * 
+ * <p>
+ * Note that the last date set <i>will</i> remain in force for the application
+ * itself. To revert to the current time, have a fixture at the end call
+ * {@link #resetClock()}.
+ * 
+ * @see SwitchUserFixture
+ */
+public class DateFixture extends BaseFixture {
+
+    public DateFixture(final int year, final int month, final int day, final int hour, final int minutes) {
+        super(FixtureType.OTHER);
+        this.year = year;
+        this.month = month;
+        this.day = day;
+        this.hour = hour;
+        this.minute = minutes;
+    }
+
+    public DateFixture(final int year, final int month, final int day) {
+        this(year, month, day, 0, 0);
+    }
+
+    private final int year;
+
+    public int getYear() {
+        return year;
+    }
+
+    private final int month;
+
+    public int getMonth() {
+        return month;
+    }
+
+    private final int day;
+
+    public int getDay() {
+        return day;
+    }
+
+    private final int hour;
+
+    public int getHour() {
+        return hour;
+    }
+
+    private final int minute;
+
+    public int getMinute() {
+        return minute;
+    }
+
+    @Override
+    public void install() {
+        setDate(year, month, day);
+        setTime(hour, minute);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/FixtureClock.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/FixtureClock.java b/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/FixtureClock.java
new file mode 100644
index 0000000..b311230
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/FixtureClock.java
@@ -0,0 +1,213 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.fixtures;
+
+import java.util.Calendar;
+import java.util.TimeZone;
+
+import org.apache.isis.applib.clock.Clock;
+
+/**
+ * This clock, for use by fixtures, can be set to specific time.
+ * 
+ * <p>
+ * If not set it will provide the time provided by the system clock.
+ * 
+ * <p>
+ * Note that - by design - it does not provide any mechanism to advance the time
+ * (eg automatic ticking of the clock). That is, the time returned is always
+ * explicitly under the control of the programmer (it can be moved forward or
+ * back as required).
+ */
+public class FixtureClock extends Clock {
+    private static final TimeZone UTC_TIME_ZONE;
+
+    static {
+        TimeZone tempTimeZone = TimeZone.getTimeZone("Etc/UTC");
+        if (tempTimeZone == null) {
+            tempTimeZone = TimeZone.getTimeZone("UTC");
+        }
+        UTC_TIME_ZONE = tempTimeZone;
+    }
+
+    /**
+     * Configures the system to use a FixtureClock rather than the in-built
+     * system clock. Can be called multiple times.
+     * 
+     * <p>
+     * Must call before any other call to {@link Clock#getInstance()}.
+     * 
+     * @throws IllegalStateException
+     *             if Clock singleton already initialized with some other
+     *             implementation.
+     */
+    public synchronized static FixtureClock initialize() {
+        if (!isInitialized() || !(getInstance() instanceof FixtureClock)) {
+            // installs the FixtureClock as the Clock singleton via the Clock's
+            // constructor
+            // if was initialized, then will replace.
+            // (if non-replaceable, then superclass will throw exception for us.
+            new FixtureClock();
+        }
+        return (FixtureClock) getInstance();
+    }
+
+    /**
+     * Makes {@link Clock#remove()} visible.
+     */
+    public static boolean remove() {
+        return Clock.remove();
+    }
+
+    // //////////////////////////////////////////////////
+    // Constructor
+    // //////////////////////////////////////////////////
+
+    // if non-null, then indicates that the time has been explicitly set.
+    // Otherwise returns the system time.
+    private Calendar calendar = null;
+
+    private FixtureClock() {
+    }
+
+    // //////////////////////////////////////////////////
+    // hook
+    // //////////////////////////////////////////////////
+
+    /**
+     * Access via {@link Clock#getTime()}.
+     * 
+     * <p>
+     * Will just return the system time until {@link #setDate(int, int, int)} or
+     * {@link #setTime(int, int)} (or one of the overloads) has been called.
+     */
+    @Override
+    protected long time() {
+        if (calendar == null) {
+            return System.currentTimeMillis();
+        }
+        return calendar.getTime().getTime();
+    }
+
+    // //////////////////////////////////////////////////
+    // setting/adjusting time
+    // //////////////////////////////////////////////////
+
+    /**
+     * Sets the clock to epoch, that is midnight, 1 Jan 1970 UTC.
+     * 
+     * <p>
+     * This is typically called before either {@link #setDate(int, int, int)}
+     * (so that time is set to midnight) and/or {@link #setTime(int, int)} (so
+     * that date is set to a well known value).
+     */
+    public void clear() {
+        setupCalendarIfRequired();
+        calendar.clear();
+    }
+
+    /**
+     * Sets the hours and minutes as specified, and sets the seconds and
+     * milliseconds to zero, but the date portion is left unchanged.
+     * 
+     * @see #setDate(int, int, int)
+     * @see #addTime(int, int)
+     */
+    public void setTime(final int hour, final int min) {
+        setupCalendarIfRequired();
+        calendar.set(Calendar.HOUR_OF_DAY, hour);
+        calendar.set(Calendar.MINUTE, min);
+        calendar.set(Calendar.SECOND, 0);
+        calendar.set(Calendar.MILLISECOND, 0);
+    }
+
+    /**
+     * Sets the date, but the time portion is left unchanged.
+     * 
+     * @see #setTime(int, int)
+     * @see #addDate(int, int, int)
+     */
+    public void setDate(final int year, final int month, final int day) {
+        setupCalendarIfRequired();
+        calendar.set(Calendar.YEAR, year);
+        calendar.set(Calendar.MONTH, month - 1);
+        calendar.set(Calendar.DAY_OF_MONTH, day);
+    }
+
+    /**
+     * Adjusts the time by the specified number of hours and minutes.
+     * 
+     * <p>
+     * Typically called after {@link #setTime(int, int)}, to move the clock
+     * forward or perhaps back.
+     * 
+     * @see #addDate(int, int, int)
+     */
+    public void addTime(final int hours, final int minutes) {
+        setupCalendarIfRequired();
+        calendar.add(Calendar.HOUR_OF_DAY, hours);
+        calendar.add(Calendar.MINUTE, minutes);
+    }
+
+    /**
+     * Adjusts the time by the specified number of years, months or days.
+     * 
+     * <p>
+     * Typically called after {@link #setDate(int, int, int)}, to move the clock
+     * forward or perhaps back.
+     * 
+     * @see #addTime(int, int)
+     */
+    public void addDate(final int years, final int months, final int days) {
+        setupCalendarIfRequired();
+        calendar.add(Calendar.YEAR, years);
+        calendar.add(Calendar.MONTH, months);
+        calendar.add(Calendar.DAY_OF_MONTH, days);
+    }
+
+    private void setupCalendarIfRequired() {
+        if (calendar != null) {
+            return;
+        }
+        calendar = Calendar.getInstance();
+        calendar.setTimeZone(UTC_TIME_ZONE);
+    }
+
+    // //////////////////////////////////////////////////
+    // reset
+    // //////////////////////////////////////////////////
+
+    /**
+     * Go back to just returning the system's time.
+     */
+    public void reset() {
+        calendar = null;
+    }
+
+    // //////////////////////////////////////////////////
+    // toString
+    // //////////////////////////////////////////////////
+
+    @Override
+    public String toString() {
+        return (calendar == null ? "System" : "Explicitly set") + ": " + Clock.getTimeAsDateTime().toString();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/FixtureType.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/FixtureType.java b/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/FixtureType.java
new file mode 100644
index 0000000..143a25b
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/FixtureType.java
@@ -0,0 +1,67 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.fixtures;
+
+import org.apache.isis.applib.fixtures.userprofile.UserProfileService;
+import org.apache.isis.applib.profiles.Perspective;
+import org.apache.isis.applib.profiles.Profile;
+
+/**
+ * Enumerates the different types of {@link InstallableFixture fixture}s
+ * supported.
+ * 
+ * @see InstallableFixture#getType()
+ */
+public enum FixtureType {
+    /**
+     * A fixture that installs data (either reference data or operational data)
+     * into an object store.
+     * 
+     * <p>
+     * Some object stores are in-memory only, in which case these will always
+     * want fixtures of this type to be installed. However, for object stores
+     * that persist the data (such as XML or to an RDBMS), these typically do
+     * <i>not</i> want data fixtures run (except possibly for the very first
+     * time booted to initially seed them).
+     */
+    DOMAIN_OBJECTS,
+    /**
+     * Analogous to {@link FixtureType#DATA}, but for fixtures (in particular,
+     * the {@link PerspectiveFixture}) that are used to setup {@link Profile}s
+     * and their {@link Perspective}s.
+     * 
+     * @see UserProfileService
+     */
+    USER_PROFILES,
+    /**
+     * A fixture that neither installs data into the object store nor
+     * perspectives into the {@link UserProfileService}.
+     * 
+     * <p>
+     * Fixtures of this type are always installed. Typical examples are:
+     * <ul>
+     * <li>composite fixtures that just aggregate other fixtures
+     * <li>fixtures that set up the date/time (see {@link DateFixture})
+     * <li>fixtures that specify the user to logon as (see {@link LogonFixture}
+     * ).
+     * </ul>
+     */
+    OTHER;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/InstallableFixture.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/InstallableFixture.java b/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/InstallableFixture.java
new file mode 100644
index 0000000..f99fa43
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/InstallableFixture.java
@@ -0,0 +1,32 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.fixtures;
+
+public interface InstallableFixture {
+
+    /**
+     * Determines whether the fixture will be {@link #install() install}ed,
+     * dependent on the state of the object (data) store and the user profile
+     * store.
+     */
+    FixtureType getType();
+
+    public void install();
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/LogonFixture.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/LogonFixture.java b/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/LogonFixture.java
new file mode 100644
index 0000000..5862303
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/LogonFixture.java
@@ -0,0 +1,80 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.fixtures;
+
+import java.util.List;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
+/**
+ * Indicates that the demo or test should be run as the specified user, with the
+ * specified roles.
+ * 
+ * <p>
+ * Note: this fixture does not in itself do anything (its {@link #install()} is
+ * a no-op). However, if present in the fixture list then is &quot;noticed&quot;
+ * by the framework, and is used to automatically logon when the framework is
+ * booted (providing running in prototype or exploration, not in production).
+ * 
+ * <p>
+ * To change the user during the installation of fixtures, either use
+ * {@link SwitchUserFixture}.
+ * 
+ * @see SwitchUserFixture
+ */
+public class LogonFixture implements InstallableFixture {
+
+    private final String username;
+    private final List<String> roles;
+
+    public LogonFixture(final String username, final String... roles) {
+        this(username, Lists.newArrayList(roles));
+    }
+
+    public LogonFixture(final String username, final List<String> roles) {
+        this.username = username;
+        this.roles = ImmutableList.copyOf(roles);
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public List<String> getRoles() {
+        return roles;
+    }
+
+    @Override
+    public final void install() {
+        // does nothing; see comments above.
+    }
+
+    @Override
+    public FixtureType getType() {
+        return FixtureType.OTHER;
+    }
+
+    @Override
+    public String toString() {
+        return "LogonFixture [user: " + getUsername() + ", roles: " + getRoles() + "]";
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/SwitchUserFixture.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/SwitchUserFixture.java b/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/SwitchUserFixture.java
new file mode 100644
index 0000000..854eeb6
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/SwitchUserFixture.java
@@ -0,0 +1,80 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.fixtures;
+
+import java.util.List;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
+import org.apache.isis.applib.fixtures.switchuser.SwitchUserService;
+import org.apache.isis.applib.fixtures.switchuser.SwitchUserServiceAware;
+
+/**
+ * Sole purpose is to switch the current user while object fixtures are being
+ * installed.
+ * 
+ * <p>
+ * An alternative is to switch user using the
+ * {@link AbstractFixture#switchUser(String, String...) switchUser} method.
+ * 
+ * <p>
+ * Note that (unlike the otherwise similar {@link DateFixture}) the last user
+ * switched to is <i>not</i> used as the logon fixture. If you want to
+ * automatically logon as some user, use the {@link LogonFixture}.
+ * 
+ * @see DateFixture
+ * @see LogonFixture
+ */
+public class SwitchUserFixture extends BaseFixture implements SwitchUserServiceAware {
+
+    private final String username;
+    private final List<String> roles;
+    private SwitchUserService switchUserService;
+
+    public SwitchUserFixture(final String username, final String... roles) {
+        this(username, Lists.newArrayList(roles));
+    }
+
+    public SwitchUserFixture(final String username, final List<String> roles) {
+        super(FixtureType.OTHER);
+        this.username = username;
+        this.roles = ImmutableList.copyOf(roles);
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public List<String> getRoles() {
+        return roles;
+    }
+
+    @Override
+    public void install() {
+        switchUserService.switchUser(username, roles.toArray(new String[] {}));
+    }
+
+    @Override
+    public void setService(final SwitchUserService switchUserService) {
+        this.switchUserService = switchUserService;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/UserProfileFixture.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/UserProfileFixture.java b/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/UserProfileFixture.java
new file mode 100644
index 0000000..b247c9c
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/UserProfileFixture.java
@@ -0,0 +1,62 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.fixtures;
+
+import org.apache.isis.applib.fixtures.userprofile.UserProfileService;
+import org.apache.isis.applib.fixtures.userprofile.UserProfileServiceAware;
+import org.apache.isis.applib.profiles.Profile;
+
+public abstract class UserProfileFixture extends BaseFixture implements UserProfileServiceAware {
+
+    private UserProfileService profileService;
+
+    public UserProfileFixture() {
+        super(FixtureType.USER_PROFILES);
+    }
+
+    @Override
+    public void setService(final UserProfileService profileService) {
+        this.profileService = profileService;
+    }
+
+    @Override
+    public final void install() {
+        installProfiles();
+    }
+
+    protected abstract void installProfiles();
+
+    protected Profile newUserProfile() {
+        return profileService.newUserProfile();
+    }
+
+    protected Profile newUserProfile(final Profile profile) {
+        return profileService.newUserProfile(profile);
+    }
+
+    protected void saveForUser(final String name, final Profile profile) {
+        profileService.saveForUser(name, profile);
+    }
+
+    protected void saveAsDefault(final Profile profile) {
+        profileService.saveAsDefault(profile);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/package-info.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/package-info.java b/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/package-info.java
new file mode 100644
index 0000000..1f54d2a
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/package-info.java
@@ -0,0 +1,44 @@
+/*
+ *  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.
+ */
+
+/**
+ * Defines the {@link org.apache.isis.applib.fixtures.InstallableFixture}
+ * interface and supporting classes.
+ * 
+ * <p>
+ * Fixtures are used to initialize the system, typically for either testing
+ * or for demo/prototyping purposes.  Initializing the system means:
+ * <ul>
+ * <li><p>setting up objects within the persistent object store (typically only relevant
+ * if using the in-memory object store; other object stores will generally
+ * ignore these fixtures)</p></li>  
+ * <li><p>setting the current {@link org.apache.isis.applib.fixtures.DateFixture date}</p></li>
+ * <li><p>{@link org.apache.isis.applib.fixtures.SwitchUserFixture switching} 
+ * the current user while fixtures are being installed (eg so that a workflow
+ * can be picked up midway through)</p></li>  
+ * <li><p>specifying the {@link org.apache.isis.applib.fixtures.LogonFixture currently logged on} user once the fixtures have been installed</p></li>
+ * <li><p>setting up objects within the persistent {@link org.apache.isis.applib.fixtures.UserProfileFixture user profile}</p></li>
+ * </ul>
+ * 
+ * <p>
+ * Fixtures are typically combined into a {@link org.apache.isis.applib.fixtures.CompositeFixture composite}
+ * pattern; the {@link org.apache.isis.applib.fixtures.AbstractFixture} adapter
+ * class provides built-in support for this if required.
+ */
+package org.apache.isis.applib.fixtures;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/switchuser/SwitchUserService.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/switchuser/SwitchUserService.java b/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/switchuser/SwitchUserService.java
new file mode 100644
index 0000000..e5a7dd6
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/switchuser/SwitchUserService.java
@@ -0,0 +1,50 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.fixtures.switchuser;
+
+import java.util.List;
+
+import org.apache.isis.applib.fixtures.AbstractFixture;
+import org.apache.isis.applib.fixtures.userprofile.UserProfileService;
+
+/**
+ * Not intended to be used directly; decouples the {@link AbstractFixture},
+ * which needs to be able to switch users dynamically, from the rest of the
+ * framework's runtime.
+ * 
+ * <p>
+ * A suitable implementation is injected into {@link AbstractFixture} when
+ * installed.
+ * 
+ * @see UserProfileService
+ */
+public interface SwitchUserService {
+
+    /**
+     * Switches the current user with the list of specified roles.
+     */
+    void switchUser(String username, String... roles);
+
+    /**
+     * Switches the current user with the list of specified roles.
+     */
+    void switchUser(String username, List<String> roles);
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/switchuser/SwitchUserServiceAware.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/switchuser/SwitchUserServiceAware.java b/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/switchuser/SwitchUserServiceAware.java
new file mode 100644
index 0000000..883a1dd
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/switchuser/SwitchUserServiceAware.java
@@ -0,0 +1,34 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.fixtures.switchuser;
+
+import org.apache.isis.applib.fixtures.AbstractFixture;
+
+/**
+ * Implement if require {@link SwitchUserService} to be injected into fixture.
+ * 
+ * <p>
+ * Most fixtures will subclass from {@link AbstractFixture} which does indeed
+ * implement this interface.
+ */
+public interface SwitchUserServiceAware {
+
+    void setService(SwitchUserService switchUserService);
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/switchuser/package-info.java
----------------------------------------------------------------------
diff --git a/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/switchuser/package-info.java b/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/switchuser/package-info.java
new file mode 100644
index 0000000..07d5bb2
--- /dev/null
+++ b/framework/core/applib/src/main/java/org/apache/isis/applib/fixtures/switchuser/package-info.java
@@ -0,0 +1,28 @@
+/*
+ *  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.
+ */
+
+/**
+ * Provides support for switching the current user while fixtures are
+ * being loaded.
+ * 
+ * <p>
+ * Not expected to be used by domain objects, but decouples the fixtures from
+ * the framework (which provides the implementation of {@link org.apache.isis.applib.fixtures.switchuser.SwitchUserService}).
+ */
+package org.apache.isis.applib.fixtures.switchuser;
\ No newline at end of file