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 18:42:18 UTC

[32/52] [partial] ISIS-188: moving framework/ subdirs up to parent

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/SaveObject.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/SaveObject.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/SaveObject.java
new file mode 100644
index 0000000..b636d94
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/SaveObject.java
@@ -0,0 +1,71 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.bdd.common.fixtures.perform;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.Persistor;
+import org.apache.isis.viewer.bdd.common.CellBinding;
+import org.apache.isis.viewer.bdd.common.ScenarioBoundValueException;
+
+public class SaveObject extends PerformAbstractTypeParams {
+
+    private ObjectAdapter result;
+
+    public SaveObject(final Perform.Mode mode) {
+        super("save", Type.OBJECT, NumParameters.ZERO, mode);
+    }
+
+    @Override
+    public void doHandle(final PerformContext performContext) throws ScenarioBoundValueException {
+
+        final ObjectAdapter onAdapter = performContext.getOnAdapter();
+
+        final Consent valid = onAdapter.getSpecification().isValid(onAdapter);
+
+        final CellBinding performBinding = performContext.getPeer().getPerformBinding();
+        if (valid.isVetoed()) {
+            throw ScenarioBoundValueException.current(performBinding, valid.getReason());
+        }
+
+        if (onAdapter.representsPersistent()) {
+            throw ScenarioBoundValueException.current(performBinding, "(already persistent)");
+        }
+
+        // persist
+
+        // xactn mgmt now performed by PersistenceSession#makePersistent
+        // getOwner().getTransactionManager().startTransaction();
+        getPersistenceSession().makePersistent(onAdapter);
+        // getOwner().getTransactionManager().endTransaction();
+
+        // all OK.
+    }
+
+    protected Persistor getPersistenceSession() {
+        return IsisContext.getPersistenceSession();
+    }
+
+    @Override
+    public ObjectAdapter getResult() {
+        return result;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/SetProperty.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/SetProperty.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/SetProperty.java
new file mode 100644
index 0000000..71d7c85
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/SetProperty.java
@@ -0,0 +1,79 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.bdd.common.fixtures.perform;
+
+import java.util.List;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.metamodel.facets.properties.modify.PropertySetterFacet;
+import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.isis.viewer.bdd.common.CellBinding;
+import org.apache.isis.viewer.bdd.common.ScenarioBoundValueException;
+import org.apache.isis.viewer.bdd.common.ScenarioCell;
+
+public class SetProperty extends PerformAbstractTypeParams {
+
+    private ObjectAdapter result;
+
+    public SetProperty(final Perform.Mode mode) {
+        super("set property", Type.PROPERTY, NumParameters.ONE, mode);
+    }
+
+    @Override
+    public void doHandle(final PerformContext performContext) throws ScenarioBoundValueException {
+
+        final ObjectAdapter onAdapter = performContext.getOnAdapter();
+        final ObjectMember nakedObjectMember = performContext.getObjectMember();
+        final List<ScenarioCell> argumentCells = performContext.getArgumentCells();
+
+        final OneToOneAssociation otoa = (OneToOneAssociation) nakedObjectMember;
+
+        // set
+        final PropertySetterFacet setterFacet = otoa.getFacet(PropertySetterFacet.class);
+        if (setterFacet == null) {
+            final CellBinding onMemberBinding = performContext.getPeer().getOnMemberBinding();
+            throw ScenarioBoundValueException.current(onMemberBinding, "(cannot set)");
+        }
+
+        // safe to obtain since guaranteed by superclass
+        final CellBinding arg0Binding = performContext.getPeer().getArg0Binding();
+        final ScenarioCell arg0Cell = argumentCells.get(0);
+
+        // obtain existing as 'context' (used if this is a parsed @Value)
+        final ObjectAdapter contextAdapter = otoa.get(onAdapter);
+
+        // validate parameter
+        final ObjectAdapter toSetAdapter = performContext.getPeer().getAdapter(contextAdapter, otoa.getSpecification(), arg0Binding, arg0Cell);
+        final Consent validConsent = otoa.isAssociationValid(onAdapter, toSetAdapter);
+        if (validConsent.isVetoed()) {
+            throw ScenarioBoundValueException.current(arg0Binding, validConsent.getReason());
+        }
+
+        setterFacet.setProperty(onAdapter, toSetAdapter);
+
+    }
+
+    @Override
+    public ObjectAdapter getResult() {
+        return result;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/AssertsContainment.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/AssertsContainment.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/AssertsContainment.java
new file mode 100644
index 0000000..b3b246b
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/AssertsContainment.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.viewer.bdd.common.fixtures.perform.checkthat;
+
+/**
+ * Parameterizes {@link ThatSubcommand}s.
+ */
+public enum AssertsContainment {
+
+    CONTAINS("contains", true, "(does not contain)"), DOES_NOT_CONTAIN("does not contain", false, "(contains)");
+
+    private final String key;
+    private final boolean contains;
+    private final String errorMsgIfNotSatisfied;
+
+    private AssertsContainment(final String key, final boolean contains, final String errorMsgIfNotSatisfied) {
+        this.key = key;
+        this.contains = contains;
+        this.errorMsgIfNotSatisfied = errorMsgIfNotSatisfied;
+    }
+
+    public String getKey() {
+        return key;
+    }
+
+    public boolean doesContain() {
+        return contains;
+    }
+
+    public boolean isSatisfiedBy(final boolean contains) {
+        return this.contains == contains;
+    }
+
+    public String getErrorMsgIfNotSatisfied() {
+        return errorMsgIfNotSatisfied;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/AssertsEmpty.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/AssertsEmpty.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/AssertsEmpty.java
new file mode 100644
index 0000000..6b69c09
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/AssertsEmpty.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.viewer.bdd.common.fixtures.perform.checkthat;
+
+/**
+ * Parameterizes {@link ThatSubcommand}s.
+ */
+public enum AssertsEmpty {
+
+    EMPTY("is empty", true, "(not empty)"), NOT_EMPTY("is not empty", false, "(empty)");
+
+    private final String key;
+    private final boolean empty;
+    private final String errorMsgIfNotSatisfied;
+
+    AssertsEmpty(final String key, final boolean empty, final String errorMsgIfNotSatisfied) {
+        this.key = key;
+        this.empty = empty;
+        this.errorMsgIfNotSatisfied = errorMsgIfNotSatisfied;
+    }
+
+    public String getKey() {
+        return key;
+    }
+
+    public boolean isEmpty() {
+        return empty;
+    }
+
+    public boolean isSatisfiedBy(final boolean empty) {
+        return this.empty == empty;
+    }
+
+    public String getErrorMsgIfNotSatisfied() {
+        return errorMsgIfNotSatisfied;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/AssertsValidity.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/AssertsValidity.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/AssertsValidity.java
new file mode 100644
index 0000000..831512c
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/AssertsValidity.java
@@ -0,0 +1,70 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat;
+
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.viewer.bdd.common.CellBinding;
+
+/**
+ * Parameterizes {@link ThatSubcommand}s.
+ * 
+ * @author Dan Haywood
+ */
+public enum AssertsValidity {
+
+    VALID(true, "is valid for", "is valid", "valid"), INVALID(false, "is not valid for", "is not valid", "not valid", "invalid");
+
+    private final String[] keys;
+    private final boolean valid;
+
+    AssertsValidity(final boolean valid, final String... keys) {
+        this.keys = keys;
+        this.valid = valid;
+    }
+
+    public String[] getKeys() {
+        return keys;
+    }
+
+    public boolean isValid() {
+        return valid;
+    }
+
+    public boolean satisfiedBy(final Consent validityConsent) {
+        return validityConsent.isAllowed() && isValid() || validityConsent.isVetoed() && !isValid();
+    }
+
+    /**
+     * The reason to use if the assertion is not valid.
+     */
+    public String getReason(final Consent validityConsent) {
+        return isValid() ? validityConsent.getReason() : "(valid)";
+    }
+
+    /**
+     * The binding whose current cell should be coloured if the assertion fails.
+     */
+    public CellBinding colorBinding(final CellBinding arg0Binding, final CellBinding thatBinding) {
+        if (arg0Binding == null) {
+            return thatBinding;
+        }
+        return isValid() ? arg0Binding : thatBinding;
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/Disabled.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/Disabled.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/Disabled.java
new file mode 100644
index 0000000..5242f81
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/Disabled.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.viewer.bdd.common.fixtures.perform.checkthat;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.viewer.bdd.common.CellBinding;
+import org.apache.isis.viewer.bdd.common.ScenarioBoundValueException;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.PerformContext;
+
+public class Disabled extends ThatSubcommandAbstract {
+
+    public Disabled() {
+        super("is disabled", "is not usable", "is not enabled");
+    }
+
+    @Override
+    public ObjectAdapter that(final PerformContext performContext) throws ScenarioBoundValueException {
+
+        if (performContext.usableMemberConsent().isAllowed()) {
+            final CellBinding onMemberBinding = performContext.getPeer().getOnMemberBinding();
+            throw ScenarioBoundValueException.current(onMemberBinding, "(usable)");
+        }
+
+        return null;
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/Hidden.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/Hidden.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/Hidden.java
new file mode 100644
index 0000000..a39148c
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/Hidden.java
@@ -0,0 +1,43 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.viewer.bdd.common.CellBinding;
+import org.apache.isis.viewer.bdd.common.ScenarioBoundValueException;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.PerformContext;
+
+public class Hidden extends ThatSubcommandAbstract {
+
+    public Hidden() {
+        super("is hidden", "is not visible");
+    }
+
+    @Override
+    public ObjectAdapter that(final PerformContext performContext) throws ScenarioBoundValueException {
+
+        if (performContext.visibleMemberConsent().isAllowed()) {
+            final CellBinding onMemberBinding = performContext.getPeer().getOnMemberBinding();
+            throw ScenarioBoundValueException.current(onMemberBinding, "(visible)");
+        }
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/PerformCheckThatAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/PerformCheckThatAbstract.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/PerformCheckThatAbstract.java
new file mode 100644
index 0000000..46fbf3a
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/PerformCheckThatAbstract.java
@@ -0,0 +1,78 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.viewer.bdd.common.CellBinding;
+import org.apache.isis.viewer.bdd.common.IsisViewerConstants;
+import org.apache.isis.viewer.bdd.common.ScenarioBoundValueException;
+import org.apache.isis.viewer.bdd.common.ScenarioCell;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.Perform;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.PerformAbstract;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.PerformContext;
+
+public abstract class PerformCheckThatAbstract extends PerformAbstract {
+
+    protected static enum OnMemberColumn {
+        REQUIRED, NOT_REQUIRED
+    }
+
+    private final Map<String, ThatSubcommand> subcommandByKey = new HashMap<String, ThatSubcommand>();
+    private ObjectAdapter result;
+    private final boolean requiresMember;
+
+    public PerformCheckThatAbstract(final String key, final OnMemberColumn onMemberColumn, final Perform.Mode mode, final ThatSubcommand... thatSubcommands) {
+        super(key, mode);
+        requiresMember = onMemberColumn == OnMemberColumn.REQUIRED;
+        for (final ThatSubcommand thatSubcommand : thatSubcommands) {
+            for (final String subKey : thatSubcommand.getSubkeys()) {
+                subcommandByKey.put(subKey, thatSubcommand);
+            }
+        }
+    }
+
+    @Override
+    public void perform(final PerformContext performContext) throws ScenarioBoundValueException {
+        final CellBinding thatItBinding = performContext.getPeer().getThatItBinding();
+        if (!thatItBinding.isFound()) {
+            final CellBinding performBinding = performContext.getPeer().getPerformBinding();
+            throw ScenarioBoundValueException.current(performBinding, "(require " + IsisViewerConstants.THAT_IT_NAME + "' column)");
+        }
+        final ScenarioCell thatItCell = thatItBinding.getCurrentCell();
+        final String thatIt = thatItCell.getText();
+        final ThatSubcommand thatSubcommand = subcommandByKey.get(thatIt);
+        if (thatSubcommand == null) {
+            throw ScenarioBoundValueException.current(thatItBinding, "(unknown '" + IsisViewerConstants.THAT_IT_NAME + "' verb)");
+        }
+        result = thatSubcommand.that(performContext);
+    }
+
+    @Override
+    public ObjectAdapter getResult() {
+        return result;
+    }
+
+    @Override
+    public boolean requiresMember() {
+        return requiresMember;
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/ProposedArgumentValidityAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/ProposedArgumentValidityAbstract.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/ProposedArgumentValidityAbstract.java
new file mode 100644
index 0000000..91fd422
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/ProposedArgumentValidityAbstract.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.viewer.bdd.common.fixtures.perform.checkthat;
+
+import org.apache.isis.core.commons.lang.StringUtils;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
+import org.apache.isis.viewer.bdd.common.CellBinding;
+import org.apache.isis.viewer.bdd.common.ScenarioBoundValueException;
+import org.apache.isis.viewer.bdd.common.ScenarioCell;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.PerformContext;
+
+public abstract class ProposedArgumentValidityAbstract extends ThatValidityAbstract {
+
+    public ProposedArgumentValidityAbstract(final AssertsValidity assertion) {
+        super(assertion);
+    }
+
+    @Override
+    public ObjectAdapter that(final PerformContext performContext) throws ScenarioBoundValueException {
+
+        final ObjectMember nakedObjectMember = performContext.getObjectMember();
+        final CellBinding thatBinding = performContext.getPeer().getThatItBinding();
+        final CellBinding arg0Binding = performContext.getPeer().getArg0Binding();
+
+        // check we have an argument to validate (if one is required)
+        if (!arg0Binding.isFound()) {
+            throw ScenarioBoundValueException.current(thatBinding, "(requires argument)");
+        }
+
+        final ScenarioCell arg0Cell = arg0Binding.getCurrentCell();
+        final String toValidate = arg0Cell.getText();
+        if (StringUtils.isNullOrEmpty(toValidate)) {
+            throw ScenarioBoundValueException.current(arg0Binding, "(required)");
+        }
+
+        final ObjectAdapter toValidateAdapter = performContext.getPeer().getAdapter(null, nakedObjectMember.getSpecification(), arg0Binding, arg0Cell);
+        final Consent validityConsent = determineConsent(performContext, toValidateAdapter);
+        if (!getAssertion().satisfiedBy(validityConsent)) {
+            throw ScenarioBoundValueException.current(getAssertion().colorBinding(arg0Binding, thatBinding), getAssertion().getReason(validityConsent));
+        }
+
+        return toValidateAdapter;
+    }
+
+    protected abstract Consent determineConsent(final PerformContext performContext, ObjectAdapter toValidateAdapter);
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/ThatSubcommand.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/ThatSubcommand.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/ThatSubcommand.java
new file mode 100644
index 0000000..9209512
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/ThatSubcommand.java
@@ -0,0 +1,36 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat;
+
+import java.util.List;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.viewer.bdd.common.ScenarioBoundValueException;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.PerformContext;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.PerformOwner;
+
+public interface ThatSubcommand {
+
+    ObjectAdapter that(PerformContext performContext) throws ScenarioBoundValueException;
+
+    List<String> getSubkeys();
+
+    void setOwner(PerformOwner owner);
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/ThatSubcommandAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/ThatSubcommandAbstract.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/ThatSubcommandAbstract.java
new file mode 100644
index 0000000..fcc8206
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/ThatSubcommandAbstract.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.viewer.bdd.common.fixtures.perform.checkthat;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.isis.viewer.bdd.common.fixtures.perform.PerformOwner;
+
+public abstract class ThatSubcommandAbstract implements ThatSubcommand {
+
+    private final List<String> subkeys;
+    private PerformOwner owner;
+
+    public ThatSubcommandAbstract(final String... subkeys) {
+        this.subkeys = Collections.unmodifiableList(Arrays.asList(subkeys));
+    }
+
+    @Override
+    public List<String> getSubkeys() {
+        return subkeys;
+    }
+
+    protected PerformOwner getOwner() {
+        return owner;
+    }
+
+    /**
+     * Injected.
+     */
+    @Override
+    public void setOwner(final PerformOwner owner) {
+        this.owner = owner;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/ThatValidityAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/ThatValidityAbstract.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/ThatValidityAbstract.java
new file mode 100644
index 0000000..9c41083
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/ThatValidityAbstract.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.viewer.bdd.common.fixtures.perform.checkthat;
+
+public abstract class ThatValidityAbstract extends ThatSubcommandAbstract {
+
+    private final AssertsValidity assertion;
+
+    public ThatValidityAbstract(final AssertsValidity assertion) {
+        super(assertion.getKeys());
+        this.assertion = assertion;
+    }
+
+    public AssertsValidity getAssertion() {
+        return assertion;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/Usable.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/Usable.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/Usable.java
new file mode 100644
index 0000000..b254b94
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/Usable.java
@@ -0,0 +1,43 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.viewer.bdd.common.CellBinding;
+import org.apache.isis.viewer.bdd.common.ScenarioBoundValueException;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.PerformContext;
+
+public class Usable extends ThatSubcommandAbstract {
+
+    public Usable() {
+        super("is usable", "is enabled", "is not disabled");
+    }
+
+    @Override
+    public ObjectAdapter that(final PerformContext performContext) throws ScenarioBoundValueException {
+
+        if (!performContext.usableMemberConsent().isAllowed()) {
+            final CellBinding onMemberBinding = performContext.getPeer().getOnMemberBinding();
+            throw ScenarioBoundValueException.current(onMemberBinding, "(disabled)");
+        }
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/Visible.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/Visible.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/Visible.java
new file mode 100644
index 0000000..02c7c7d
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/Visible.java
@@ -0,0 +1,43 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.viewer.bdd.common.CellBinding;
+import org.apache.isis.viewer.bdd.common.ScenarioBoundValueException;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.PerformContext;
+
+public class Visible extends ThatSubcommandAbstract {
+
+    public Visible() {
+        super("is visible", "is not hidden");
+    }
+
+    @Override
+    public ObjectAdapter that(final PerformContext performContext) throws ScenarioBoundValueException {
+
+        if (performContext.visibleMemberConsent().isVetoed()) {
+            final CellBinding onMemberBinding = performContext.getPeer().getOnMemberBinding();
+            throw ScenarioBoundValueException.current(onMemberBinding, "(hidden)");
+        }
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/action/ArgumentSetNotValid.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/action/ArgumentSetNotValid.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/action/ArgumentSetNotValid.java
new file mode 100644
index 0000000..906305a
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/action/ArgumentSetNotValid.java
@@ -0,0 +1,70 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat.action;
+
+import java.util.List;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
+import org.apache.isis.viewer.bdd.common.CellBinding;
+import org.apache.isis.viewer.bdd.common.ScenarioBoundValueException;
+import org.apache.isis.viewer.bdd.common.ScenarioCell;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.PerformContext;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat.ThatSubcommandAbstract;
+
+public class ArgumentSetNotValid extends ThatSubcommandAbstract {
+
+    public ArgumentSetNotValid() {
+        super("is not valid for", "is invalid", "invalid");
+    }
+
+    // TODO: a lot of duplication with InvokeAction; simplify somehow?
+    @Override
+    public ObjectAdapter that(final PerformContext performContext) throws ScenarioBoundValueException {
+
+        final ObjectAdapter onAdapter = performContext.getOnAdapter();
+        final ObjectMember nakedObjectMember = performContext.getObjectMember();
+        final CellBinding onMemberBinding = performContext.getPeer().getOnMemberBinding();
+        final List<ScenarioCell> argumentCells = performContext.getArgumentCells();
+
+        final ObjectAction nakedObjectAction = (ObjectAction) nakedObjectMember;
+        final int parameterCount = nakedObjectAction.getParameterCount();
+        final boolean isContributedOneArgAction = nakedObjectAction.isContributed() && parameterCount == 1;
+
+        if (isContributedOneArgAction) {
+            return null;
+        }
+
+        // lookup arguments
+        final ObjectAdapter[] proposedArguments = performContext.getPeer().getAdapters(onAdapter, nakedObjectAction, onMemberBinding, argumentCells);
+
+        // validate arguments
+        final Consent argSetValid = nakedObjectAction.isProposedArgumentSetValid(onAdapter, proposedArguments);
+        if (argSetValid.isAllowed()) {
+            final CellBinding thatItBinding = performContext.getPeer().getThatItBinding();
+            throw ScenarioBoundValueException.current(thatItBinding, "(valid)");
+        }
+
+        // execute
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/action/ArgumentSetValid.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/action/ArgumentSetValid.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/action/ArgumentSetValid.java
new file mode 100644
index 0000000..666b2e3
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/action/ArgumentSetValid.java
@@ -0,0 +1,69 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat.action;
+
+import java.util.List;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
+import org.apache.isis.viewer.bdd.common.CellBinding;
+import org.apache.isis.viewer.bdd.common.ScenarioBoundValueException;
+import org.apache.isis.viewer.bdd.common.ScenarioCell;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.PerformContext;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat.ThatSubcommandAbstract;
+
+public class ArgumentSetValid extends ThatSubcommandAbstract {
+
+    public ArgumentSetValid() {
+        super("is valid for", "is valid", "valid");
+    }
+
+    // TODO: a lot of duplication with InvokeAction; simplify somehow?
+    @Override
+    public ObjectAdapter that(final PerformContext performContext) throws ScenarioBoundValueException {
+
+        final ObjectAdapter onAdapter = performContext.getOnAdapter();
+        final ObjectMember nakedObjectMember = performContext.getObjectMember();
+        final CellBinding onMemberBinding = performContext.getPeer().getOnMemberBinding();
+        final List<ScenarioCell> argumentCells = performContext.getArgumentCells();
+
+        final ObjectAction nakedObjectAction = (ObjectAction) nakedObjectMember;
+        final int parameterCount = nakedObjectAction.getParameterCount();
+        final boolean isContributedOneArgAction = nakedObjectAction.isContributed() && parameterCount == 1;
+
+        if (isContributedOneArgAction) {
+            return null;
+        }
+
+        // lookup arguments
+        final ObjectAdapter[] proposedArguments = performContext.getPeer().getAdapters(onAdapter, nakedObjectAction, onMemberBinding, argumentCells);
+
+        // validate arguments
+        final Consent argSetValid = nakedObjectAction.isProposedArgumentSetValid(onAdapter, proposedArguments);
+        if (argSetValid.isVetoed()) {
+            throw ScenarioBoundValueException.current(onMemberBinding, argSetValid.getReason());
+        }
+
+        // execute
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/collections/Containment.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/collections/Containment.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/collections/Containment.java
new file mode 100644
index 0000000..ba485fb
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/collections/Containment.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.viewer.bdd.common.fixtures.perform.checkthat.collections;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
+import org.apache.isis.viewer.bdd.common.CellBinding;
+import org.apache.isis.viewer.bdd.common.ScenarioBoundValueException;
+import org.apache.isis.viewer.bdd.common.ScenarioCell;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.PerformContext;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat.AssertsContainment;
+
+public class Containment extends ThatAbstract {
+
+    private final AssertsContainment assertion;
+
+    public Containment(final AssertsContainment assertion) {
+        super(assertion.getKey());
+        this.assertion = assertion;
+    }
+
+    @Override
+    protected void doThat(final PerformContext performContext, final Iterable<ObjectAdapter> collection) throws ScenarioBoundValueException {
+
+        final ObjectMember nakedObjectMember = performContext.getObjectMember();
+        final CellBinding thatBinding = performContext.getPeer().getThatItBinding();
+        final CellBinding arg0Binding = performContext.getPeer().getArg0Binding();
+
+        if (!arg0Binding.isFound()) {
+            throw ScenarioBoundValueException.current(thatBinding, "(requires argument)");
+        }
+
+        final ScenarioCell arg0Cell = arg0Binding.getCurrentCell();
+
+        final ObjectAdapter containedAdapter = performContext.getPeer().getAdapter(null, nakedObjectMember.getSpecification(), arg0Binding, arg0Cell);
+
+        boolean contains = false;
+        for (final ObjectAdapter eachAdapter : collection) {
+            if (containedAdapter == eachAdapter) {
+                contains = true;
+                break;
+            }
+        }
+
+        if (!assertion.isSatisfiedBy(contains)) {
+            throw ScenarioBoundValueException.current(arg0Binding, assertion.getErrorMsgIfNotSatisfied());
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/collections/Emptiness.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/collections/Emptiness.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/collections/Emptiness.java
new file mode 100644
index 0000000..e07ad75
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/collections/Emptiness.java
@@ -0,0 +1,51 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat.collections;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.viewer.bdd.common.CellBinding;
+import org.apache.isis.viewer.bdd.common.ScenarioBoundValueException;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.PerformContext;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat.AssertsEmpty;
+
+public class Emptiness extends ThatAbstract {
+
+    private final AssertsEmpty assertion;
+
+    public Emptiness(final AssertsEmpty assertion) {
+        super(assertion.getKey());
+        this.assertion = assertion;
+    }
+
+    @Override
+    protected void doThat(final PerformContext performContext, final Iterable<ObjectAdapter> collection) throws ScenarioBoundValueException {
+
+        boolean empty = true;
+        for (@SuppressWarnings("unused")
+        final ObjectAdapter eachObject : collection) {
+            empty = false;
+        }
+
+        if (!assertion.isSatisfiedBy(empty)) {
+            final CellBinding thatItBinding = performContext.getPeer().getThatItBinding();
+            throw ScenarioBoundValueException.current(thatItBinding, assertion.getErrorMsgIfNotSatisfied());
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/collections/ProposedAddTo.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/collections/ProposedAddTo.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/collections/ProposedAddTo.java
new file mode 100644
index 0000000..95cfd4c
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/collections/ProposedAddTo.java
@@ -0,0 +1,43 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat.collections;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.PerformContext;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat.AssertsValidity;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat.ProposedArgumentValidityAbstract;
+
+public class ProposedAddTo extends ProposedArgumentValidityAbstract {
+
+    public ProposedAddTo(final AssertsValidity assertion) {
+        super(assertion);
+    }
+
+    @Override
+    protected Consent determineConsent(final PerformContext performContext, final ObjectAdapter toValidateAdapter) {
+
+        final ObjectAdapter onAdapter = performContext.getOnAdapter();
+        final OneToManyAssociation otma = (OneToManyAssociation) performContext.getObjectMember();
+
+        return otma.isValidToAdd(onAdapter, toValidateAdapter);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/collections/ProposedRemoveFrom.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/collections/ProposedRemoveFrom.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/collections/ProposedRemoveFrom.java
new file mode 100644
index 0000000..dc03f81
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/collections/ProposedRemoveFrom.java
@@ -0,0 +1,43 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat.collections;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.PerformContext;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat.AssertsValidity;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat.ProposedArgumentValidityAbstract;
+
+public class ProposedRemoveFrom extends ProposedArgumentValidityAbstract {
+
+    public ProposedRemoveFrom(final AssertsValidity assertion) {
+        super(assertion);
+    }
+
+    @Override
+    protected Consent determineConsent(final PerformContext performContext, final ObjectAdapter toValidateAdapter) {
+
+        final ObjectAdapter onAdapter = performContext.getOnAdapter();
+        final OneToManyAssociation otma = (OneToManyAssociation) performContext.getObjectMember();
+
+        return otma.isValidToRemove(onAdapter, toValidateAdapter);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/collections/Size.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/collections/Size.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/collections/Size.java
new file mode 100644
index 0000000..49ce0b0
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/collections/Size.java
@@ -0,0 +1,69 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat.collections;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.viewer.bdd.common.CellBinding;
+import org.apache.isis.viewer.bdd.common.ScenarioBoundValueException;
+import org.apache.isis.viewer.bdd.common.ScenarioCell;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.PerformContext;
+
+public class Size extends ThatAbstract {
+
+    public Size() {
+        super("size");
+    }
+
+    @Override
+    protected void doThat(final PerformContext performContext, final Iterable<ObjectAdapter> collection) throws ScenarioBoundValueException {
+
+        final CellBinding thatBinding = performContext.getPeer().getThatItBinding();
+        final CellBinding arg0Binding = performContext.getPeer().getArg0Binding();
+
+        if (!arg0Binding.isFound()) {
+            throw ScenarioBoundValueException.current(thatBinding, "(requires argument)");
+        }
+
+        final ScenarioCell arg0Cell = arg0Binding.getCurrentCell();
+
+        final String expectedSizeStr = arg0Cell.getText();
+        final int expectedSize;
+        try {
+            expectedSize = Integer.parseInt(expectedSizeStr);
+        } catch (final NumberFormatException ex) {
+            throw ScenarioBoundValueException.current(arg0Binding, "(not an integer)");
+        }
+
+        if (expectedSize <= 0) {
+            throw ScenarioBoundValueException.current(arg0Binding, "(not a positive integer)");
+        }
+
+        int actualSize = 0;
+        for (@SuppressWarnings("unused")
+        final ObjectAdapter eachObject : collection) {
+            actualSize++;
+        }
+
+        if (expectedSize != actualSize) {
+            throw ScenarioBoundValueException.current(arg0Binding, "" + actualSize);
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/collections/ThatAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/collections/ThatAbstract.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/collections/ThatAbstract.java
new file mode 100644
index 0000000..e5a39f5
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/collections/ThatAbstract.java
@@ -0,0 +1,50 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat.collections;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
+import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.viewer.bdd.common.ScenarioBoundValueException;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.PerformContext;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat.ThatSubcommandAbstract;
+
+public abstract class ThatAbstract extends ThatSubcommandAbstract {
+
+    public ThatAbstract(final String key) {
+        super(key);
+    }
+
+    @Override
+    public ObjectAdapter that(final PerformContext performContext) throws ScenarioBoundValueException {
+
+        final ObjectAdapter onAdapter = performContext.getOnAdapter();
+        final OneToManyAssociation otma = (OneToManyAssociation) performContext.getObjectMember();
+
+        final ObjectAdapter nakedObjectRepresentingCollection = otma.get(onAdapter);
+        final CollectionFacet collectionFacet = nakedObjectRepresentingCollection.getSpecification().getFacet(CollectionFacet.class);
+
+        doThat(performContext, collectionFacet.iterable(nakedObjectRepresentingCollection));
+
+        return nakedObjectRepresentingCollection; // can alias if wish
+    }
+
+    protected abstract void doThat(PerformContext performContext, Iterable<ObjectAdapter> collection) throws ScenarioBoundValueException;
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/object/NotSaved.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/object/NotSaved.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/object/NotSaved.java
new file mode 100644
index 0000000..544fe98
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/object/NotSaved.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.viewer.bdd.common.fixtures.perform.checkthat.object;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.viewer.bdd.common.CellBinding;
+import org.apache.isis.viewer.bdd.common.ScenarioBoundValueException;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.PerformContext;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat.ThatSubcommandAbstract;
+
+public class NotSaved extends ThatSubcommandAbstract {
+
+    public NotSaved() {
+        super("is not saved", "is not persistent", "is not persisted", "not saved", "not persistent", "not persisted");
+    }
+
+    @Override
+    public ObjectAdapter that(final PerformContext performContext) throws ScenarioBoundValueException {
+
+        final ObjectAdapter onAdapter = performContext.getOnAdapter();
+        final CellBinding thatItBinding = performContext.getPeer().getThatItBinding();
+
+        if (onAdapter.representsPersistent()) {
+            throw ScenarioBoundValueException.current(thatItBinding, "(saved)");
+        }
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/object/NotValid.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/object/NotValid.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/object/NotValid.java
new file mode 100644
index 0000000..f85f85c
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/object/NotValid.java
@@ -0,0 +1,45 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat.object;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.viewer.bdd.common.CellBinding;
+import org.apache.isis.viewer.bdd.common.ScenarioBoundValueException;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.PerformContext;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat.ThatSubcommandAbstract;
+
+public class NotValid extends ThatSubcommandAbstract {
+
+    public NotValid() {
+        super("is not valid", "is invalid", "not valid", "invalid");
+    }
+
+    @Override
+    public ObjectAdapter that(final PerformContext performContext) throws ScenarioBoundValueException {
+
+        final CellBinding thatItBinding = performContext.getPeer().getThatItBinding();
+
+        if (performContext.validObjectConsent().isAllowed()) {
+            throw ScenarioBoundValueException.current(thatItBinding, "(valid)");
+        }
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/object/Saved.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/object/Saved.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/object/Saved.java
new file mode 100644
index 0000000..fdad338
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/object/Saved.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.viewer.bdd.common.fixtures.perform.checkthat.object;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.viewer.bdd.common.CellBinding;
+import org.apache.isis.viewer.bdd.common.ScenarioBoundValueException;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.PerformContext;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat.ThatSubcommandAbstract;
+
+public class Saved extends ThatSubcommandAbstract {
+
+    public Saved() {
+        super("is saved", "is persistent", "is persisted", "saved", "persistent", "persisted");
+    }
+
+    @Override
+    public ObjectAdapter that(final PerformContext performContext) throws ScenarioBoundValueException {
+
+        final ObjectAdapter onAdapter = performContext.getOnAdapter();
+        final CellBinding thatItBinding = performContext.getPeer().getThatItBinding();
+
+        if (!onAdapter.representsPersistent()) {
+            throw ScenarioBoundValueException.current(thatItBinding, "(not saved)");
+        }
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/object/Valid.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/object/Valid.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/object/Valid.java
new file mode 100644
index 0000000..774ed63
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/object/Valid.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.viewer.bdd.common.fixtures.perform.checkthat.object;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.viewer.bdd.common.CellBinding;
+import org.apache.isis.viewer.bdd.common.ScenarioBoundValueException;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.PerformContext;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat.ThatSubcommandAbstract;
+
+public class Valid extends ThatSubcommandAbstract {
+
+    public Valid() {
+        super("is valid", "valid");
+    }
+
+    @Override
+    public ObjectAdapter that(final PerformContext performContext) throws ScenarioBoundValueException {
+
+        if (!performContext.validObjectConsent().isAllowed()) {
+            final CellBinding thatItBinding = performContext.getPeer().getThatItBinding();
+            throw ScenarioBoundValueException.current(thatItBinding, "(not valid)");
+        }
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/property/Contains.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/property/Contains.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/property/Contains.java
new file mode 100644
index 0000000..4334c82
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/property/Contains.java
@@ -0,0 +1,105 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat.property;
+
+import java.util.Date;
+
+import org.apache.isis.core.commons.lang.StringUtils;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.isis.core.progmodel.facets.value.date.DateValueFacet;
+import org.apache.isis.viewer.bdd.common.CellBinding;
+import org.apache.isis.viewer.bdd.common.ScenarioBoundValueException;
+import org.apache.isis.viewer.bdd.common.ScenarioCell;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.PerformContext;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat.ThatSubcommandAbstract;
+import org.apache.isis.viewer.bdd.common.parsers.DateParser;
+
+public class Contains extends ThatSubcommandAbstract {
+
+    public Contains() {
+        super("contains", "is", "does contain");
+    }
+
+    @Override
+    public ObjectAdapter that(final PerformContext performContext) throws ScenarioBoundValueException {
+
+        final OneToOneAssociation otoa = (OneToOneAssociation) performContext.getObjectMember();
+
+        // if we have an expected result
+        final CellBinding arg0Binding = performContext.getPeer().getArg0Binding();
+        final ScenarioCell arg0Cell = arg0Binding.getCurrentCell();
+        final String expected = arg0Cell.getText();
+
+        // get
+        final ObjectAdapter resultAdapter = otoa.get(performContext.getOnAdapter());
+
+        // see if matches null
+        if (resultAdapter == null) {
+            if (StringUtils.isNullOrEmpty(expected)) {
+                return resultAdapter;
+            }
+            throw ScenarioBoundValueException.current(arg0Binding, "(is null)");
+        }
+
+        final String resultTitle = resultAdapter.titleString();
+
+        if (!StringUtils.isNullOrEmpty(expected)) {
+
+            // see if expected matches an alias
+            final ObjectAdapter expectedAdapter = performContext.getPeer().getAliasRegistry().getAliased(expected);
+            if (expectedAdapter != null) {
+                // known
+                if (resultAdapter == expectedAdapter) {
+                    return resultAdapter;
+                }
+                throw ScenarioBoundValueException.current(arg0Binding, resultTitle);
+            }
+
+            // otherwise, see if date and if so compare as such
+            final DateValueFacet dateValueFacet = resultAdapter.getSpecification().getFacet(DateValueFacet.class);
+            if (dateValueFacet != null) {
+                final Date resultDate = dateValueFacet.dateValue(resultAdapter);
+
+                final DateParser dateParser = performContext.getDateParser();
+                final Date expectedDate = dateParser.parse(expected);
+                if (expectedDate != null) {
+                    if (expectedDate.compareTo(resultDate) == 0) {
+                        return resultAdapter; // ok
+                    }
+                }
+                final String format = dateParser.format(resultDate);
+                throw ScenarioBoundValueException.current(arg0Binding, format);
+            }
+
+            // otherwise, compare title
+            if (!StringUtils.nullSafeEquals(resultTitle, expected)) {
+                throw ScenarioBoundValueException.current(arg0Binding, resultTitle);
+            }
+        } else {
+            // try to provide a default
+            final String resultAlias = performContext.getPeer().getAliasRegistry().getAlias(resultAdapter);
+            final String resultStr = resultAlias != null ? resultAlias : resultTitle;
+            performContext.getPeer().provideDefault(arg0Cell, resultStr);
+        }
+
+        return resultAdapter;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/property/DoesNotContain.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/property/DoesNotContain.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/property/DoesNotContain.java
new file mode 100644
index 0000000..9291a7d
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/property/DoesNotContain.java
@@ -0,0 +1,78 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat.property;
+
+import org.apache.isis.core.commons.lang.StringUtils;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.isis.viewer.bdd.common.CellBinding;
+import org.apache.isis.viewer.bdd.common.ScenarioBoundValueException;
+import org.apache.isis.viewer.bdd.common.ScenarioCell;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.PerformContext;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat.ThatSubcommandAbstract;
+
+public class DoesNotContain extends ThatSubcommandAbstract {
+
+    public DoesNotContain() {
+        super("does not contain", "is not");
+    }
+
+    @Override
+    public ObjectAdapter that(final PerformContext performContext) throws ScenarioBoundValueException {
+
+        final OneToOneAssociation otoa = (OneToOneAssociation) performContext.getObjectMember();
+
+        // if we have an expected result
+        final CellBinding arg0Binding = performContext.getPeer().getArg0Binding();
+        final ScenarioCell arg0Cell = arg0Binding.getCurrentCell();
+        final String expected = arg0Cell.getText();
+
+        // get
+        final ObjectAdapter resultAdapter = otoa.get(performContext.getOnAdapter());
+
+        // see if matches null
+        if (resultAdapter == null) {
+            // ok
+            return null;
+        }
+
+        final String resultTitle = resultAdapter.titleString();
+
+        if (!StringUtils.isNullOrEmpty(expected)) {
+
+            // see if expected matches an alias
+            final ObjectAdapter expectedAdapter = performContext.getPeer().getAliasRegistry().getAliased(expected);
+            if (expectedAdapter != null) {
+                // known
+                if (resultAdapter != expectedAdapter) {
+                    return resultAdapter;
+                }
+                throw ScenarioBoundValueException.current(arg0Binding, "(does contain)");
+            }
+
+            // otherwise, compare title
+            if (StringUtils.nullSafeEquals(resultTitle, expected)) {
+                throw ScenarioBoundValueException.current(arg0Binding, "(does contain)");
+            }
+        }
+
+        return resultAdapter;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/property/Empty.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/property/Empty.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/property/Empty.java
new file mode 100644
index 0000000..b4fdd2b
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/perform/checkthat/property/Empty.java
@@ -0,0 +1,54 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat.property;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.isis.viewer.bdd.common.CellBinding;
+import org.apache.isis.viewer.bdd.common.ScenarioBoundValueException;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.PerformContext;
+import org.apache.isis.viewer.bdd.common.fixtures.perform.checkthat.ThatSubcommandAbstract;
+
+public class Empty extends ThatSubcommandAbstract {
+
+    public Empty() {
+        super("is empty");
+    }
+
+    @Override
+    public ObjectAdapter that(final PerformContext performContext) throws ScenarioBoundValueException {
+
+        final OneToOneAssociation otoa = (OneToOneAssociation) performContext.getObjectMember();
+
+        // get
+        final ObjectAdapter resultAdapter = otoa.get(performContext.getOnAdapter());
+
+        if (resultAdapter != null) {
+            String actualStr = performContext.getPeer().getAliasRegistry().getAlias(resultAdapter);
+            if (actualStr == null) {
+                actualStr = resultAdapter.titleString();
+            }
+            final CellBinding thatItBinding = performContext.getPeer().getThatItBinding();
+            throw ScenarioBoundValueException.current(thatItBinding, actualStr);
+        }
+
+        return null;
+    }
+
+}