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

[30/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/Scenario.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/Scenario.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/Scenario.java
new file mode 100644
index 0000000..9a2d7c0
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/Scenario.java
@@ -0,0 +1,314 @@
+/*
+ *  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;
+
+import static org.apache.isis.core.commons.ensure.Ensure.ensureThatArg;
+import static org.hamcrest.CoreMatchers.anyOf;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+import org.apache.log4j.FileAppender;
+
+import org.apache.isis.applib.fixtures.LogonFixture;
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.core.commons.config.IsisConfigurationBuilder;
+import org.apache.isis.core.commons.config.IsisConfigurationBuilderFileSystem;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.adapter.oid.AggregatedOid;
+import org.apache.isis.core.progmodel.facets.value.ValueSemanticsProviderAbstractTemporal;
+import org.apache.isis.runtimes.dflt.profilestores.dflt.InMemoryUserProfileStoreInstaller;
+import org.apache.isis.runtimes.dflt.runtime.fixtures.FixturesInstallerNoop;
+import org.apache.isis.runtimes.dflt.runtime.installerregistry.InstallerLookup;
+import org.apache.isis.runtimes.dflt.runtime.installers.InstallerLookupDefault;
+import org.apache.isis.runtimes.dflt.runtime.runner.IsisModule;
+import org.apache.isis.runtimes.dflt.runtime.system.DeploymentType;
+import org.apache.isis.runtimes.dflt.runtime.system.IsisSystem;
+import org.apache.isis.runtimes.dflt.runtime.system.SystemConstants;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.isis.runtimes.dflt.runtime.system.internal.InitialisationSession;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.AdapterManagerSpi;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.PersistenceSession;
+import org.apache.isis.runtimes.dflt.runtime.system.transaction.IsisTransactionManager;
+import org.apache.isis.viewer.bdd.common.components.BddAuthenticationManagerInstaller;
+import org.apache.isis.viewer.bdd.common.components.BddInMemoryPersistenceMechanismInstaller;
+import org.apache.isis.viewer.bdd.common.parsers.DateParser;
+import org.apache.isis.viewer.bdd.common.story.bootstrapping.OpenSession;
+import org.apache.isis.viewer.bdd.common.story.bootstrapping.RunViewer;
+import org.apache.isis.viewer.bdd.common.story.bootstrapping.SetClock;
+import org.apache.isis.viewer.bdd.common.story.bootstrapping.ShutdownIsis;
+import org.apache.isis.viewer.bdd.common.story.registries.AliasRegistryDefault;
+import org.apache.isis.viewer.bdd.common.story.registries.AliasRegistryHolder;
+
+/**
+ * Holds the bootstrapped {@link IsisSystem} and provides access to the
+ * {@link AliasRegistry aliases}.
+ * 
+ * <p>
+ * Typically held in a thread-local by the test framework, acting as a context
+ * to the story.
+ * 
+ * <p>
+ * Implementation note: this class directly implements {@link AliasRegistrySpi},
+ * though delegates to an underlying {@link AliasRegistryDefault}. This is
+ * needed because the underlying {@link AliasRegistry} can change on
+ * {@link #switchUserWithRoles(String, String)} (see
+ * {@link #reAdapt(AliasRegistrySpi)} method).
+ */
+public class Scenario implements AliasRegistryHolder {
+
+    private AliasRegistry aliasRegistry = new AliasRegistryDefault();
+
+    private DeploymentType deploymentType;
+    private String configDirectory;
+
+    private IsisSystem isisSystem;
+
+    private InstallerLookupDefault installerLookup;
+
+    private final DateParser dateParser = new DateParser();
+
+    // /////////////////////////////////////////////////////////////
+    // bootstrap / shutdown
+    // /////////////////////////////////////////////////////////////
+
+    public String getConfigDirectory() {
+        return configDirectory;
+    }
+
+    public DeploymentType getDeploymentType() {
+        return deploymentType;
+    }
+
+    public IsisSystem getSystem() {
+        return isisSystem;
+    }
+
+    public InstallerLookup getInstallerLookup() {
+        return installerLookup;
+    }
+
+    @SuppressWarnings("unchecked")
+    public void bootstrapIsis(final String configDirectory, final DeploymentType deploymentType) {
+        this.configDirectory = configDirectory;
+        this.deploymentType = ensureThatArg(deploymentType, is(anyOf(equalTo(DeploymentType.EXPLORATION), equalTo(DeploymentType.PROTOTYPE))));
+
+        final IsisConfigurationBuilderFileSystem configurationBuilder = new IsisConfigurationBuilderFileSystem(getConfigDirectory());
+
+        configurationBuilder.add(SystemConstants.DEPLOYMENT_TYPE_KEY, deploymentType.name());
+        defaultStoryComponentsInto(configurationBuilder);
+
+        getAliasRegistry().clear();
+
+        try {
+            // create system...
+            isisSystem = createSystem(deploymentType, configurationBuilder);
+
+            // ... and provide a session in order to install fixtures
+            IsisContext.openSession(new InitialisationSession());
+
+        } catch (final RuntimeException e) {
+            if (isisSystem != null) {
+                isisSystem.shutdown();
+            }
+            throw e;
+        }
+    }
+
+    private IsisSystem createSystem(final DeploymentType deploymentType, final IsisConfigurationBuilder isisConfigurationBuilder) {
+        this.installerLookup = new InstallerLookupDefault();
+        isisConfigurationBuilder.injectInto(installerLookup);
+
+        final Injector injector = createGuiceInjector(deploymentType, isisConfigurationBuilder, installerLookup);
+        final IsisSystem system = injector.getInstance(IsisSystem.class);
+        return system;
+    }
+
+    private void defaultStoryComponentsInto(final IsisConfigurationBuilder isisConfigurationBuilder) {
+        isisConfigurationBuilder.add(SystemConstants.AUTHENTICATION_INSTALLER_KEY, BddAuthenticationManagerInstaller.class.getName());
+        isisConfigurationBuilder.add(SystemConstants.OBJECT_PERSISTOR_INSTALLER_KEY, BddInMemoryPersistenceMechanismInstaller.class.getName());
+        isisConfigurationBuilder.add(SystemConstants.PROFILE_PERSISTOR_INSTALLER_KEY, InMemoryUserProfileStoreInstaller.class.getName());
+        isisConfigurationBuilder.add(SystemConstants.FIXTURES_INSTALLER_KEY, FixturesInstallerNoop.class.getName());
+        isisConfigurationBuilder.add(SystemConstants.NOSPLASH_KEY, "" + true);
+    }
+
+    private Injector createGuiceInjector(final DeploymentType deploymentType, final IsisConfigurationBuilder isisConfigurationBuilder, final InstallerLookup installerLookup) {
+        final IsisModule isisModule = new IsisModule(deploymentType, isisConfigurationBuilder, installerLookup);
+        return Guice.createInjector(isisModule);
+    }
+
+    public void shutdownIsis() {
+        new ShutdownIsis(this).shutdown();
+    }
+
+    // /////////////////////////////////////////////////////////////
+    // date+time / logon+switch user
+    // /////////////////////////////////////////////////////////////
+
+    public boolean dateAndTimeIs(final String dateAndTimeStr) {
+        final Date date = dateParser.parse(dateAndTimeStr);
+        if (date != null) {
+            new SetClock(this).setClock(date);
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Logon, specifying no roles.
+     * <p>
+     * Unlike the {@link LogonFixture} on regular fixtures, the logonAs is not
+     * automatically remembered until the end of the setup. It should therefore
+     * be invoked at the end of setup explicitly.
+     */
+    public void logonAsOrSwitchUserTo(final String userName) {
+        final List<String> noRoles = Collections.emptyList();
+        logonAsOrSwitchUserTo(userName, noRoles);
+    }
+
+    /**
+     * Logon, specifying roles.
+     * <p>
+     * Unlike the {@link LogonFixture} on regular Isis fixtures, the logonAs is
+     * not automatically remembered until the end of the setup. It should
+     * therefore be invoked at the end of setup explicitly.
+     */
+    public void logonAsOrSwitchUserTo(final String userName, final List<String> roleList) {
+        new OpenSession(this).openSession(userName, roleList);
+        aliasRegistry = reAdapt(aliasRegistry);
+    }
+
+    /**
+     * Need to recreate aliases whenever logout/login.
+     */
+    private AliasRegistry reAdapt(final AliasRegistry aliasesRegistry) {
+        final AliasRegistry newAliasesRegistry = new AliasRegistryDefault();
+
+        // first pass: root adapters
+        for (final Map.Entry<String, ObjectAdapter> aliasAdapter : aliasesRegistry) {
+            final String alias = aliasAdapter.getKey();
+            final ObjectAdapter oldAdapter = aliasAdapter.getValue();
+
+            if (oldAdapter.getOid() instanceof AggregatedOid) {
+                continue;
+            }
+            newAliasesRegistry.aliasAs(alias, getAdapterManager().adapterFor(oldAdapter.getObject()));
+        }
+
+        // for now, not supporting aggregated adapters (difficulty in looking up
+        // the parent adapter because the Oid changes)
+
+        // // second pass: aggregated adapters
+        // for (Map.Entry<String,NakedObject> aliasAdapter : oldAliasesRegistry)
+        // {
+        // final String alias = aliasAdapter.getKey();
+        // final ObjectAdapter oldAdapter = aliasAdapter.getValue();
+        //
+        // if(!(oldAdapter.getOid() instanceof AggregatedOid)) {
+        // continue;
+        // }
+        // AggregatedOid aggregatedOid = (AggregatedOid) oldAdapter.getOid();
+        // final Object parentOid = aggregatedOid.getParentOid();
+        // final ObjectAdapter parentAdapter =
+        // getAdapterManager().getAdapterFor(parentOid);
+        // final String fieldName = aggregatedOid.getFieldName();
+        // final NakedObjectAssociation association =
+        // parentAdapter.getSpecification().getAssociation(fieldName);
+        // final ObjectAdapter newAdapter =
+        // getAdapterManager().adapterFor(oldAdapter.getObject(), parentAdapter,
+        // association);
+        //
+        // newAliasesRegistry.put(alias, newAdapter);
+        // }
+        return newAliasesRegistry;
+    }
+
+    // /////////////////////////////////////////////////////////
+    // date parser
+    // /////////////////////////////////////////////////////////
+
+    public void usingDateFormat(final String dateFormatStr) {
+        dateParser.setDateFormat(dateFormatStr);
+        setTemporalFormat("date", dateFormatStr);
+        setTemporalFormat("datetime", dateParser.getCombinedMask());
+        setTemporalFormat("timestamp", dateParser.getCombinedMask());
+    }
+
+    public void usingTimeFormat(final String timeFormatStr) {
+        dateParser.setTimeFormat(timeFormatStr);
+        setTemporalFormat("time", timeFormatStr);
+        setTemporalFormat("datetime", dateParser.getCombinedMask());
+        setTemporalFormat("timestamp", dateParser.getCombinedMask());
+    }
+
+    private void setTemporalFormat(final String propertyType, final String formatStr) {
+        ValueSemanticsProviderAbstractTemporal.setFormat(propertyType, formatStr);
+    }
+
+    public DateParser getDateParser() {
+        return dateParser;
+    }
+
+    // /////////////////////////////////////////////////////////
+    // run viewer
+    // /////////////////////////////////////////////////////////
+
+    public void runViewer() {
+        new RunViewer(this).run();
+    }
+
+    // //////////////////////////////////////////////////////////////////
+    // AliasRegistry impl
+    // //////////////////////////////////////////////////////////////////
+
+    @Override
+    public AliasRegistry getAliasRegistry() {
+        return aliasRegistry;
+    }
+
+    // /////////////////////////////////////////////////////////
+    // Dependencies (from context)
+    // /////////////////////////////////////////////////////////
+
+    protected PersistenceSession getPersistenceSession() {
+        return IsisContext.getPersistenceSession();
+    }
+
+    private AdapterManager getAdapterManager() {
+        return getPersistenceSession().getAdapterManager();
+    }
+
+    public IsisTransactionManager getTransactionManager() {
+        return IsisContext.getTransactionManager();
+    }
+
+    protected IsisConfiguration getConfiguration() {
+        return IsisContext.getConfiguration();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/ScenarioBoundValueException.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/ScenarioBoundValueException.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/ScenarioBoundValueException.java
new file mode 100644
index 0000000..969c320
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/ScenarioBoundValueException.java
@@ -0,0 +1,59 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.bdd.common;
+
+import java.io.CharArrayWriter;
+import java.io.PrintWriter;
+
+public class ScenarioBoundValueException extends Exception {
+
+    private static final long serialVersionUID = 1L;
+
+    private final CellBinding cellBinding;
+    private final ScenarioCell storyCell;
+
+    public static ScenarioBoundValueException current(final CellBinding cellBinding, final String message) {
+        return new ScenarioBoundValueException(cellBinding, cellBinding.getCurrentCell(), message);
+    }
+
+    public static ScenarioBoundValueException arg(final CellBinding cellBinding, final ScenarioCell storyCell, final String message) {
+        return new ScenarioBoundValueException(cellBinding, storyCell, message);
+    }
+
+    private ScenarioBoundValueException(final CellBinding cellBinding, final ScenarioCell storyCell, final String message) {
+        super(message);
+        this.cellBinding = cellBinding;
+        this.storyCell = storyCell;
+    }
+
+    public CellBinding getCellBinding() {
+        return cellBinding;
+    }
+
+    public ScenarioCell getStoryCell() {
+        return storyCell;
+    }
+
+    public String asString() {
+        final CharArrayWriter caw = new CharArrayWriter();
+        this.printStackTrace(new PrintWriter(caw));
+        return caw.toString();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/ScenarioCell.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/ScenarioCell.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/ScenarioCell.java
new file mode 100644
index 0000000..40ca0b9
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/ScenarioCell.java
@@ -0,0 +1,38 @@
+/*
+ *  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;
+
+public interface ScenarioCell {
+
+    /**
+     * The text represented by the source.
+     */
+    public String getText();
+
+    /**
+     * Sets the text held by the source.
+     */
+    public void setText(String str);
+
+    /**
+     * The implementation-specific representation of this text.
+     */
+    public Object getSource();
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/ScenarioCellDefault.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/ScenarioCellDefault.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/ScenarioCellDefault.java
new file mode 100644
index 0000000..b6b27fb
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/ScenarioCellDefault.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;
+
+/**
+ * Simply holds the text.
+ * 
+ */
+public class ScenarioCellDefault implements ScenarioCell {
+
+    private String source;
+
+    public ScenarioCellDefault(final String source) {
+        this.source = source;
+    }
+
+    @Override
+    public String getText() {
+        return source;
+    }
+
+    @Override
+    public void setText(final String str) {
+        this.source = str;
+    }
+
+    /**
+     * The implementation-specific representation of this text.
+     */
+    @Override
+    public Object getSource() {
+        return source;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/ScenarioValueException.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/ScenarioValueException.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/ScenarioValueException.java
new file mode 100644
index 0000000..c2a92ca
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/ScenarioValueException.java
@@ -0,0 +1,40 @@
+/*
+ *  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;
+
+public class ScenarioValueException extends Exception {
+
+    private static final long serialVersionUID = 1L;
+
+    public ScenarioValueException() {
+    }
+
+    public ScenarioValueException(final String message) {
+        super(message);
+    }
+
+    public ScenarioValueException(final Throwable cause) {
+        super(cause);
+    }
+
+    public ScenarioValueException(final String message, final Throwable cause) {
+        super(message, cause);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/ServiceRegistry.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/ServiceRegistry.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/ServiceRegistry.java
new file mode 100644
index 0000000..65ee3e1
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/ServiceRegistry.java
@@ -0,0 +1,23 @@
+/*
+ *  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;
+
+public interface ServiceRegistry {
+
+}
\ 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/components/BddAuthenticationManagerInstaller.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/components/BddAuthenticationManagerInstaller.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/components/BddAuthenticationManagerInstaller.java
new file mode 100644
index 0000000..86fdb95
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/components/BddAuthenticationManagerInstaller.java
@@ -0,0 +1,40 @@
+/*
+ *  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.components;
+
+import java.util.List;
+
+import com.google.common.collect.Lists;
+
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.core.runtime.authentication.standard.Authenticator;
+import org.apache.isis.runtimes.dflt.runtime.authentication.AuthenticationManagerStandardInstallerAbstractForDfltRuntime;
+import org.apache.isis.security.dflt.authentication.AuthenticatorDefault;
+
+public class BddAuthenticationManagerInstaller extends AuthenticationManagerStandardInstallerAbstractForDfltRuntime {
+
+    public BddAuthenticationManagerInstaller() {
+        super("bdd");
+    }
+
+    @Override
+    protected List<Authenticator> createAuthenticators(final IsisConfiguration configuration) {
+        return Lists.<Authenticator> newArrayList(new AuthenticatorDefault(configuration));
+    }
+}
\ 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/components/BddInMemoryPersistenceMechanismInstaller.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/components/BddInMemoryPersistenceMechanismInstaller.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/components/BddInMemoryPersistenceMechanismInstaller.java
new file mode 100644
index 0000000..24b399d
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/components/BddInMemoryPersistenceMechanismInstaller.java
@@ -0,0 +1,48 @@
+/*
+ *  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.components;
+
+import org.apache.isis.runtimes.dflt.objectstores.dflt.InMemoryPersistenceMechanismInstaller;
+import org.apache.isis.runtimes.dflt.runtime.system.DeploymentType;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.PersistenceSessionFactory;
+
+public class BddInMemoryPersistenceMechanismInstaller extends InMemoryPersistenceMechanismInstaller {
+
+    public BddInMemoryPersistenceMechanismInstaller() {
+    }
+
+    // ///////////////////////////////////////////////////////////////
+    // Name
+    // ///////////////////////////////////////////////////////////////
+
+    @Override
+    public String getName() {
+        return "bdd";
+    }
+
+    // ///////////////////////////////////////////////////////////////
+    // Hook methods
+    // ///////////////////////////////////////////////////////////////
+
+    @Override
+    public PersistenceSessionFactory createPersistenceSessionFactory(final DeploymentType deploymentType) {
+        return new BddInMemoryPersistenceSessionFactory(deploymentType, getConfiguration(), this);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/components/BddInMemoryPersistenceSessionFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/components/BddInMemoryPersistenceSessionFactory.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/components/BddInMemoryPersistenceSessionFactory.java
new file mode 100644
index 0000000..852c19c
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/components/BddInMemoryPersistenceSessionFactory.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.viewer.bdd.common.components;
+
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.core.metamodel.facets.object.cached.CachedFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.runtimes.dflt.objectstores.dflt.InMemoryPersistenceSessionFactory;
+import org.apache.isis.runtimes.dflt.objectstores.dflt.internal.ObjectStorePersistedObjects;
+import org.apache.isis.runtimes.dflt.runtime.persistence.PersistenceSessionFactoryDelegate;
+import org.apache.isis.runtimes.dflt.runtime.system.DeploymentType;
+
+/**
+ * As per {@link InMemoryPersistenceSessionFactory}, but uses the
+ * {@link BddObjectStorePersistedObjects} implementation which stores any
+ * {@link CachedFacet cached} {@link ObjectSpecification class}es
+ * <tt>static</tt>ally (and thus persisted across multiple setups/teardowns of
+ * the {@link NakedObjectsContext}.
+ */
+public class BddInMemoryPersistenceSessionFactory extends InMemoryPersistenceSessionFactory {
+
+    public BddInMemoryPersistenceSessionFactory(final DeploymentType deploymentType, final IsisConfiguration configuration, final PersistenceSessionFactoryDelegate persistenceSessionFactoryDelegate) {
+        super(deploymentType, configuration, persistenceSessionFactoryDelegate);
+    }
+
+    @Override
+    public ObjectStorePersistedObjects createPersistedObjects() {
+        return new BddObjectStorePersistedObjects();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/components/BddObjectStorePersistedObjects.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/components/BddObjectStorePersistedObjects.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/components/BddObjectStorePersistedObjects.java
new file mode 100644
index 0000000..9c6989f
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/components/BddObjectStorePersistedObjects.java
@@ -0,0 +1,124 @@
+/*
+ *  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.components;
+
+import java.util.Map;
+
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Maps;
+
+import org.apache.isis.core.commons.exceptions.IsisException;
+import org.apache.isis.core.metamodel.adapter.oid.Oid;
+import org.apache.isis.core.metamodel.facets.object.cached.CachedFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecId;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.runtimes.dflt.objectstores.dflt.internal.ObjectStoreInstances;
+import org.apache.isis.runtimes.dflt.objectstores.dflt.internal.ObjectStorePersistedObjects;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.IdentifierGeneratorDefault.Memento;
+
+/**
+ * Stores instances in one of two maps, based on whether have their
+ * specification has the {@link CachedFacet} (represents cached or reference
+ * data) or not (represents operational data).
+ * <p>
+ * Those that are cached are stored in a <tt>static</tt> map that is never
+ * {@link #clear()}ed down. Those that are operational go in a regular instance
+ * cache and can be {@link #clear()}ed.
+ */
+public class BddObjectStorePersistedObjects implements ObjectStorePersistedObjects {
+
+    private static final Map<ObjectSpecification, ObjectStoreInstances> cachedInstancesBySpecMap = Maps.newHashMap();
+
+    private final Map<ObjectSpecification, ObjectStoreInstances> operationalInstancesBySpecMap = Maps.newHashMap();
+    private final Map<ObjectSpecId, Oid> serviceOidByIdMap = Maps.newHashMap();
+    
+    private Memento oidGeneratorMemento;
+
+    @Override
+    public Memento getOidGeneratorMemento() {
+        return oidGeneratorMemento;
+    }
+
+    @Override
+    public void saveOidGeneratorMemento(final Memento memento) {
+        this.oidGeneratorMemento = memento;
+    }
+
+    @Override
+    public Oid getService(final ObjectSpecId objectSpecId) {
+        return serviceOidByIdMap.get(objectSpecId);
+    }
+
+    @Override
+    public void registerService(final ObjectSpecId objectSpecId, final Oid oid) {
+        final Oid oidLookedUpByName = serviceOidByIdMap.get(objectSpecId);
+        if (oidLookedUpByName != null) {
+            if (!oidLookedUpByName.equals(oid)) {
+                throw new IsisException("Already another service registered as name: " + objectSpecId + " (existing Oid: " + oidLookedUpByName + ", " + "intended: " + oid + ")");
+            }
+        } else {
+            serviceOidByIdMap.put(objectSpecId, oid);
+        }
+    }
+
+    @Override
+    public Iterable<ObjectSpecification> specifications() {
+        return Iterables.concat(BddObjectStorePersistedObjects.cachedInstancesBySpecMap.keySet(), operationalInstancesBySpecMap.keySet());
+    }
+
+    @Override
+    public Iterable<ObjectStoreInstances> instances() {
+        return Iterables.concat(BddObjectStorePersistedObjects.cachedInstancesBySpecMap.values(), operationalInstancesBySpecMap.values());
+    }
+
+    @Override
+    public ObjectStoreInstances instancesFor(final ObjectSpecification spec) {
+        if (isCached(spec)) {
+            return getFromMap(spec, BddObjectStorePersistedObjects.cachedInstancesBySpecMap);
+        } else {
+            return getFromMap(spec, operationalInstancesBySpecMap);
+        }
+    }
+
+    // //////////////////////////////////////////////////////////////////
+    // Helpers
+    // //////////////////////////////////////////////////////////////////
+
+    private ObjectStoreInstances getFromMap(final ObjectSpecification spec, final Map<ObjectSpecification, ObjectStoreInstances> map) {
+        ObjectStoreInstances ins = map.get(spec);
+        if (ins == null) {
+            ins = new ObjectStoreInstances(spec);
+            map.put(spec, ins);
+        }
+        return ins;
+    }
+
+    private boolean isCached(final ObjectSpecification spec) {
+        return spec.containsFacet(CachedFacet.class);
+    }
+
+    /**
+     * Only clears the operational instances, not the cached instances.
+     */
+    @Override
+    public void clear() {
+        operationalInstancesBySpecMap.clear();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/components/IsisSystemUsingInstallersWithinStory.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/components/IsisSystemUsingInstallersWithinStory.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/components/IsisSystemUsingInstallersWithinStory.java
new file mode 100644
index 0000000..d3966ba
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/components/IsisSystemUsingInstallersWithinStory.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.components;
+
+import org.apache.isis.core.runtime.authentication.AuthenticationManagerInstaller;
+import org.apache.isis.runtimes.dflt.profilestores.dflt.InMemoryUserProfileStoreInstaller;
+import org.apache.isis.runtimes.dflt.runtime.installerregistry.InstallerLookup;
+import org.apache.isis.runtimes.dflt.runtime.installerregistry.installerapi.PersistenceMechanismInstaller;
+import org.apache.isis.runtimes.dflt.runtime.system.DeploymentType;
+import org.apache.isis.runtimes.dflt.runtime.systemusinginstallers.IsisSystemUsingInstallers;
+import org.apache.isis.runtimes.dflt.runtime.userprofile.UserProfileStoreInstaller;
+
+public class IsisSystemUsingInstallersWithinStory extends IsisSystemUsingInstallers {
+
+    public IsisSystemUsingInstallersWithinStory(final DeploymentType deploymentType, final InstallerLookup installerLookup) {
+        super(deploymentType, installerLookup);
+
+        final AuthenticationManagerInstaller authManagerInstaller = new BddAuthenticationManagerInstaller();
+        setAuthenticationInstaller(getInstallerLookup().injectDependenciesInto(authManagerInstaller));
+
+        final PersistenceMechanismInstaller persistorInstaller = new BddInMemoryPersistenceMechanismInstaller();
+        setPersistenceMechanismInstaller(getInstallerLookup().injectDependenciesInto(persistorInstaller));
+
+        final UserProfileStoreInstaller userProfileStoreInstaller = new InMemoryUserProfileStoreInstaller();
+        setUserProfileStoreInstaller(getInstallerLookup().injectDependenciesInto(userProfileStoreInstaller));
+    }
+
+}

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/AbstractFixturePeer.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/AbstractFixturePeer.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/AbstractFixturePeer.java
new file mode 100644
index 0000000..acb61d6
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/AbstractFixturePeer.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.viewer.bdd.common.fixtures;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.AdapterManagerSpi;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.ObjectStore;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.PersistenceSession;
+import org.apache.isis.runtimes.dflt.runtime.system.transaction.IsisTransactionManager;
+import org.apache.isis.viewer.bdd.common.AliasRegistry;
+import org.apache.isis.viewer.bdd.common.CellBinding;
+
+public abstract class AbstractFixturePeer {
+
+    private final AliasRegistry aliasRegistry;
+    private final List<CellBinding> cellBindings;
+
+    public AbstractFixturePeer(final AliasRegistry aliasRegistry, final CellBinding... cellBindings) {
+        this(aliasRegistry, Arrays.asList(cellBindings));
+    }
+
+    public AbstractFixturePeer(final AliasRegistry storyRegistries, final List<CellBinding> cellBindings) {
+        this.aliasRegistry = storyRegistries;
+        this.cellBindings = cellBindings;
+    }
+
+    public AliasRegistry getAliasRegistry() {
+        return aliasRegistry;
+    }
+
+    public List<CellBinding> getCellBindings() {
+        return cellBindings;
+    }
+
+    public List<Object> getServices() {
+        return IsisContext.getServices();
+    }
+
+    public SpecificationLoaderSpi getSpecificationLoader() {
+        return IsisContext.getSpecificationLoader();
+    }
+
+    public AuthenticationSession getAuthenticationSession() {
+        return IsisContext.getAuthenticationSession();
+    }
+
+    public PersistenceSession getPersistenceSession() {
+        return IsisContext.getPersistenceSession();
+    }
+
+    protected AdapterManager getAdapterManager() {
+        return getPersistenceSession().getAdapterManager();
+    }
+
+    protected ObjectStore getObjectStore() {
+        return getPersistenceSession().getObjectStore();
+    }
+
+    protected IsisTransactionManager getTransactionManager() {
+        return IsisContext.getTransactionManager();
+    }
+
+    public boolean isValidAlias(final String alias) {
+        return getAliasRegistry().getAliased(alias) != 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/AbstractListFixturePeer.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/AbstractListFixturePeer.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/AbstractListFixturePeer.java
new file mode 100644
index 0000000..3201927
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/AbstractListFixturePeer.java
@@ -0,0 +1,87 @@
+/*
+ *  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;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.common.collect.Iterables;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
+import org.apache.isis.viewer.bdd.common.AliasRegistry;
+import org.apache.isis.viewer.bdd.common.CellBinding;
+import org.apache.isis.viewer.bdd.common.ScenarioValueException;
+
+public class AbstractListFixturePeer extends AbstractFixturePeer {
+
+    private final String listAlias;
+
+    /**
+     * @see #collectionAdapters()
+     */
+    private List<ObjectAdapter> objects;
+
+    public AbstractListFixturePeer(final AliasRegistry aliasesRegistry, final String listAlias, final CellBinding... cellBindings) {
+        super(aliasesRegistry, cellBindings);
+
+        this.listAlias = listAlias;
+    }
+
+    protected boolean isValidListAlias() {
+        return getListAdapter() != null && isList();
+    }
+
+    protected ObjectAdapter getListAdapter() {
+        return getAliasRegistry().getAliased(listAlias);
+    }
+
+    public void assertIsList() throws ScenarioValueException {
+        if (!(getListAdapter() != null)) {
+            throw new ScenarioValueException("no such alias");
+        }
+        if (!isList()) {
+            throw new ScenarioValueException("not a list");
+        }
+    }
+
+    public boolean isList() {
+        return getCollectionFacet() != null;
+    }
+
+    /**
+     * Lazily populated, and populated only once.
+     */
+    protected List<ObjectAdapter> collectionAdapters() {
+        if (objects == null) {
+            objects = new ArrayList<ObjectAdapter>();
+            Iterables.addAll(objects, collectionContents());
+        }
+        return objects;
+    }
+
+    private Iterable<ObjectAdapter> collectionContents() {
+        return getCollectionFacet().iterable(getListAdapter());
+    }
+
+    private CollectionFacet getCollectionFacet() {
+        return getListAdapter() != null ? getListAdapter().getSpecification().getFacet(CollectionFacet.class) : 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/AbstractSetUpFixturePeer.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/AbstractSetUpFixturePeer.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/AbstractSetUpFixturePeer.java
new file mode 100644
index 0000000..e329f1d
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/AbstractSetUpFixturePeer.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.
+ */
+package org.apache.isis.viewer.bdd.common.fixtures;
+
+import org.apache.isis.viewer.bdd.common.AliasRegistry;
+import org.apache.isis.viewer.bdd.common.CellBinding;
+
+public class AbstractSetUpFixturePeer extends AbstractFixturePeer {
+
+    public AbstractSetUpFixturePeer(final AliasRegistry aliasRegistry, final CellBinding... cellBindings) {
+        super(aliasRegistry, cellBindings);
+    }
+
+}

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/AliasItemsInListPeer.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/AliasItemsInListPeer.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/AliasItemsInListPeer.java
new file mode 100644
index 0000000..a0b8e21
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/AliasItemsInListPeer.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;
+
+import org.apache.isis.core.commons.lang.StringUtils;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.viewer.bdd.common.AliasRegistry;
+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 AliasItemsInListPeer extends AbstractListFixturePeer {
+
+    private final CellBinding titleBinding;
+    private final CellBinding typeBinding;
+    private final CellBinding aliasBinding;
+
+    public AliasItemsInListPeer(final AliasRegistry aliasesRegistry, final String listAlias, final CellBinding titleBinding, final CellBinding typeBinding, final CellBinding aliasBinding) {
+        super(aliasesRegistry, listAlias, titleBinding, typeBinding, aliasBinding);
+
+        this.titleBinding = titleBinding;
+        this.typeBinding = typeBinding;
+        this.aliasBinding = aliasBinding;
+    }
+
+    public CellBinding getTitleBinding() {
+        return titleBinding;
+    }
+
+    public CellBinding getTypeBinding() {
+        return typeBinding;
+    }
+
+    public CellBinding getAliasBinding() {
+        return aliasBinding;
+    }
+
+    public ScenarioCell findAndAlias() throws ScenarioBoundValueException {
+        final ObjectAdapter foundAdapter = findAdapter();
+        if (foundAdapter == null) {
+            throw ScenarioBoundValueException.current(titleBinding, "not found");
+        }
+
+        final ScenarioCell currentCell = aliasBinding.getCurrentCell();
+        final String currentCellText = currentCell.getText();
+        getAliasRegistry().aliasAs(currentCellText, foundAdapter);
+        return currentCell;
+    }
+
+    private ObjectAdapter findAdapter() {
+        for (final ObjectAdapter adapter : collectionAdapters()) {
+
+            if (!titleMatches(adapter)) {
+                continue; // keep looking
+            }
+            if (!typeMatches(adapter)) {
+                continue; // keep looking
+            }
+
+            return adapter;
+        }
+        return null;
+    }
+
+    private boolean titleMatches(final ObjectAdapter adapter) {
+        final String adapterTitle = adapter.titleString();
+        final String requiredTitle = titleBinding.getCurrentCell().getText();
+        return StringUtils.nullSafeEquals(adapterTitle, requiredTitle);
+    }
+
+    private boolean typeMatches(final ObjectAdapter adapter) {
+        if (typeBinding == null || !typeBinding.isFound()) {
+            return true;
+        }
+
+        final ObjectSpecification spec = adapter.getSpecification();
+        final String requiredTypeName = typeBinding.getCurrentCell().getText();
+        final String specFullName = spec.getFullIdentifier();
+        if (specFullName.equals(requiredTypeName)) {
+            return true;
+        }
+
+        final String simpleSpecName = StringUtils.simpleName(specFullName);
+        final String simpleRequiredType = StringUtils.simpleName(requiredTypeName);
+        return simpleSpecName.equalsIgnoreCase(simpleRequiredType);
+    }
+
+}

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/CheckCollectionContentsPeer.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/CheckCollectionContentsPeer.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/CheckCollectionContentsPeer.java
new file mode 100644
index 0000000..7155dd5
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/CheckCollectionContentsPeer.java
@@ -0,0 +1,119 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.bdd.common.fixtures;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.viewer.bdd.common.AliasRegistry;
+
+public class CheckCollectionContentsPeer extends AbstractListFixturePeer {
+
+    public CheckCollectionContentsPeer(final AliasRegistry aliasesRegistry, final String listAlias) {
+        super(aliasesRegistry, listAlias);
+    }
+
+    /**
+     * Returns <tt>true</tt> if collection contains specified alias.
+     * 
+     * <p>
+     * If either the list alias is invalid, or the provided alias is
+     * {@link #isValidAlias(String) invalid}, will return <tt>false</tt>.
+     */
+    public boolean contains(final String alias) {
+        if (!isValidListAlias()) {
+            return false;
+        }
+
+        final ObjectAdapter adapter = getAliasRegistry().getAliased(alias);
+        if (adapter == null) {
+            return false;
+        }
+        return collectionAdapters().contains(adapter);
+    }
+
+    /**
+     * Returns <tt>true</tt> if collection does not contain specified alias.
+     * 
+     * <p>
+     * If either the list alias is invalid, or the provided alias is
+     * {@link #isValidAlias(String) invalid}, will return <tt>false</tt>.
+     */
+    public boolean doesNotContain(final String alias) {
+        if (!isValidListAlias()) {
+            return false;
+        }
+        final ObjectAdapter adapter = getAliasRegistry().getAliased(alias);
+        if (adapter == null) {
+            return false;
+        }
+        return !collectionAdapters().contains(adapter);
+    }
+
+    /**
+     * Returns <tt>true</tt> if is empty.
+     * 
+     * @return <tt>false</tt> if the alias is invalid or does not represent a
+     *         list
+     */
+    public boolean isEmpty() {
+        if (!isValidListAlias()) {
+            return false;
+        }
+        return collectionAdapters().size() == 0;
+    }
+
+    /**
+     * Returns <tt>true</tt> if is not empty.
+     * 
+     * @return <tt>false</tt> if the alias is invalid or does not represent a
+     *         list
+     */
+    public boolean isNotEmpty() {
+        if (!isValidListAlias()) {
+            return false;
+        }
+
+        return collectionAdapters().size() != 0;
+    }
+
+    /**
+     * Returns <tt>true</tt> if collection has specified size.
+     * 
+     * @return <tt>false</tt> if the alias is invalid or does not represent a
+     *         list
+     */
+    public boolean assertSize(final int size) {
+        if (!isValidListAlias()) {
+            return false;
+        }
+        return getSize() == size;
+    }
+
+    /**
+     * Returns the size of the collection.
+     * 
+     * @return <tt>-1</tt> if the alias is invalid or does not represent a list.
+     */
+    public int getSize() {
+        if (!isValidListAlias()) {
+            return -1;
+        }
+        return collectionAdapters().size();
+    }
+
+}

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/CheckListConstants.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/CheckListConstants.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/CheckListConstants.java
new file mode 100644
index 0000000..69c7cf6
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/CheckListConstants.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.
+ */
+package org.apache.isis.viewer.bdd.common.fixtures;
+
+public final class CheckListConstants {
+
+    private CheckListConstants() {
+    }
+
+    public static final String TITLE_HEAD = "title";
+    public static final String[] TITLE_HEAD_SET = { TITLE_HEAD };
+    public static final String TITLE_NAME = TITLE_HEAD;
+
+}

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/CheckListPeer.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/CheckListPeer.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/CheckListPeer.java
new file mode 100644
index 0000000..5244d3d
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/CheckListPeer.java
@@ -0,0 +1,148 @@
+/*
+ *  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;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.isis.core.commons.lang.StringUtils;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.viewer.bdd.common.AliasRegistry;
+import org.apache.isis.viewer.bdd.common.CellBinding;
+
+public class CheckListPeer extends AbstractListFixturePeer {
+
+    public static enum CheckMode {
+        EXACT {
+            @Override
+            public boolean isExact() {
+                return true;
+            }
+        },
+        NOT_EXACT {
+            @Override
+            public boolean isExact() {
+                return false;
+            }
+        };
+        public abstract boolean isExact();
+    }
+
+    private final CheckMode checkMode;
+
+    private final CellBinding titleBinding;
+    /**
+     * Can be set to null, indicating that no type checking is performed.
+     */
+    private final CellBinding typeBinding;
+
+    /**
+     * Objects found while processing table.
+     */
+    private final List<ObjectAdapter> foundAdapters = new ArrayList<ObjectAdapter>();
+
+    public CheckListPeer(final AliasRegistry aliasesRegistry, final String listAlias, final CheckMode checkMode, final CellBinding titleBinding) {
+        this(aliasesRegistry, listAlias, checkMode, titleBinding, null);
+    }
+
+    public CheckListPeer(final AliasRegistry aliasesRegistry, final String listAlias, final CheckMode checkMode, final CellBinding titleBinding, final CellBinding typeBinding) {
+        super(aliasesRegistry, listAlias, titleBinding, typeBinding);
+        this.checkMode = checkMode;
+        this.titleBinding = titleBinding;
+        this.typeBinding = typeBinding;
+    }
+
+    public boolean isCheckModeExact() {
+        return getCheckMode().isExact();
+    }
+
+    public CellBinding getTitleBinding() {
+        return titleBinding;
+    }
+
+    /**
+     * May be <tt>null</tt> (indicating that no type checking to be performed.
+     */
+    public CellBinding getTypeBinding() {
+        return typeBinding;
+    }
+
+    private CheckMode getCheckMode() {
+        return checkMode;
+    }
+
+    public List<ObjectAdapter> getFoundAdapters() {
+        return foundAdapters;
+    }
+
+    public List<ObjectAdapter> getNotFoundAdapters() {
+        final List<ObjectAdapter> allAdapters = new ArrayList<ObjectAdapter>(collectionAdapters());
+        allAdapters.removeAll(foundAdapters);
+        return allAdapters;
+    }
+
+    public boolean findAndAddObject() {
+        final ObjectAdapter foundAdapter = findAdapter();
+        if (foundAdapter == null) {
+            return false;
+        }
+        foundAdapters.add(foundAdapter);
+        return true;
+    }
+
+    private ObjectAdapter findAdapter() {
+        for (final ObjectAdapter adapter : collectionAdapters()) {
+
+            if (!titleMatches(adapter)) {
+                continue; // keep looking
+            }
+            if (!typeMatches(adapter)) {
+                continue; // keep looking
+            }
+
+            return adapter;
+        }
+        return null;
+    }
+
+    private boolean titleMatches(final ObjectAdapter adapter) {
+        final String adapterTitle = adapter.titleString();
+        final String requiredTitle = titleBinding.getCurrentCell().getText();
+        return StringUtils.nullSafeEquals(adapterTitle, requiredTitle);
+    }
+
+    private boolean typeMatches(final ObjectAdapter adapter) {
+        if (typeBinding == null || !typeBinding.isFound()) {
+            return true;
+        }
+
+        final ObjectSpecification spec = adapter.getSpecification();
+        final String requiredTypeName = typeBinding.getCurrentCell().getText();
+        final String specFullName = spec.getFullIdentifier();
+        if (specFullName.equals(requiredTypeName)) {
+            return true;
+        }
+
+        final String simpleSpecName = StringUtils.simpleName(specFullName);
+        final String simpleRequiredType = StringUtils.simpleName(requiredTypeName);
+        return simpleSpecName.equalsIgnoreCase(simpleRequiredType);
+    }
+
+}
\ 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/DebugClockPeer.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/DebugClockPeer.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/DebugClockPeer.java
new file mode 100644
index 0000000..e6a82e6
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/DebugClockPeer.java
@@ -0,0 +1,49 @@
+/*
+ *  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;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+
+import org.apache.isis.applib.clock.Clock;
+import org.apache.isis.viewer.bdd.common.AliasRegistry;
+import org.apache.isis.viewer.bdd.common.CellBinding;
+import org.apache.isis.viewer.bdd.common.ScenarioCell;
+
+public class DebugClockPeer extends AbstractFixturePeer {
+
+    private final CellBinding cellBinding;
+    private final static SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd-MMM-yyyy HH:mm");
+
+    public DebugClockPeer(final AliasRegistry aliasesRegistry, final CellBinding cellBinding) {
+        super(aliasesRegistry, cellBinding);
+        this.cellBinding = cellBinding;
+    }
+
+    public ScenarioCell getCurrentCell() {
+        return cellBinding.getCurrentCell();
+    }
+
+    public String getFormattedClockTime() {
+        final Calendar cal = Clock.getTimeAsCalendar();
+        final String formattedDate = DATE_FORMAT.format(cal.getTime());
+        return formattedDate;
+    }
+
+}

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/DebugObjectStorePeer.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/DebugObjectStorePeer.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/DebugObjectStorePeer.java
new file mode 100644
index 0000000..c068e3b
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/DebugObjectStorePeer.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.viewer.bdd.common.fixtures;
+
+import org.apache.isis.core.commons.debug.DebugString;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.ObjectStore;
+import org.apache.isis.viewer.bdd.common.AliasRegistry;
+import org.apache.isis.viewer.bdd.common.CellBinding;
+
+public class DebugObjectStorePeer extends AbstractFixturePeer {
+
+    public DebugObjectStorePeer(final AliasRegistry aliasesRegistry, final CellBinding... cellBindings) {
+        super(aliasesRegistry, cellBindings);
+    }
+
+    public String debugObjectStore() {
+        final ObjectStore objectStore = getObjectStore();
+        final DebugString debug = new DebugString();
+        objectStore.debugData(debug);
+        return debug.toString().replaceAll("\n", "<br>");
+    }
+
+}

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/DebugServicesPeer.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/DebugServicesPeer.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/DebugServicesPeer.java
new file mode 100644
index 0000000..767a13d
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/DebugServicesPeer.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;
+
+import java.util.List;
+
+import org.apache.isis.core.commons.debug.DebugString;
+import org.apache.isis.viewer.bdd.common.AliasRegistry;
+import org.apache.isis.viewer.bdd.common.CellBinding;
+
+public class DebugServicesPeer extends AbstractFixturePeer {
+
+    public DebugServicesPeer(final AliasRegistry aliasesRegistry, final CellBinding... cellBindings) {
+        super(aliasesRegistry, cellBindings);
+    }
+
+    public String debugServices() {
+        final DebugString debug = new DebugString();
+
+        final List<Object> services = getServices();
+
+        for (final Object service : services) {
+            debug.append(service.getClass().getName());
+            debug.append("\n");
+        }
+        return debug.toString().replaceAll("\n", "<br>");
+    }
+
+}

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/SetUpObjectsPeer.java
----------------------------------------------------------------------
diff --git a/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/SetUpObjectsPeer.java b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/SetUpObjectsPeer.java
new file mode 100644
index 0000000..321127e
--- /dev/null
+++ b/component/viewer/bdd/common/src/main/java/org/apache/isis/viewer/bdd/common/fixtures/SetUpObjectsPeer.java
@@ -0,0 +1,305 @@
+/*
+ *  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;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.isis.core.commons.exceptions.IsisException;
+import org.apache.isis.core.commons.lang.StringUtils;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facets.object.parseable.ParseableFacet;
+import org.apache.isis.core.metamodel.facets.properties.modify.PropertyClearFacet;
+import org.apache.isis.core.metamodel.facets.properties.modify.PropertySetterFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.isis.viewer.bdd.common.AliasRegistry;
+import org.apache.isis.viewer.bdd.common.CellBinding;
+import org.apache.isis.viewer.bdd.common.ScenarioBoundValueException;
+
+public class SetUpObjectsPeer extends AbstractFixturePeer {
+
+    public static enum Mode {
+        PERSIST, DO_NOT_PERSIST;
+
+        public boolean isPersist() {
+            return this == PERSIST;
+        }
+    }
+
+    public static enum PropertyResult {
+        ALIAS, NO_SUCH_PROPERTY, NOT_A_PROPERTY, OK;
+        public boolean isOk() {
+            return this == OK;
+        }
+    }
+
+    public static enum SetUpObjectResult {
+        OK, NO_ASSOCIATION, CLEARED, CANNOT_CLEAR("(cannot clear)"), CANNOT_SET("(cannot set"), CANNOT_PARSE("(cannot parse)"), UNKNOWN_REFERENCE("(unknown reference)");
+        private String errorMessage;
+
+        private SetUpObjectResult() {
+            this(null);
+        }
+
+        private SetUpObjectResult(final String errorMessage) {
+            this.errorMessage = errorMessage;
+        }
+
+        public boolean isHandled() {
+            return !isError();
+        }
+
+        public boolean isError() {
+            return errorMessage != null;
+        }
+
+        public String getErrorMessage() {
+            return errorMessage;
+        }
+    }
+
+    public interface AssociationVisitor {
+        void visit(OneToOneAssociation association, int colNum);
+    }
+
+    private final ObjectSpecification spec;
+
+    private final List<OneToOneAssociation> properties = new ArrayList<OneToOneAssociation>();
+    private final CellBinding aliasBinding;
+    private final SetUpObjectsPeer.Mode mode;
+
+    private final List<String> cellTextList = new ArrayList<String>();
+    private String alias;
+
+    // ///////////////////////////////////////////////////////////////////////
+    // constructor
+    // ///////////////////////////////////////////////////////////////////////
+
+    public SetUpObjectsPeer(final AliasRegistry aliasRegistry, final String className, final SetUpObjectsPeer.Mode mode, final CellBinding aliasBinding) {
+        super(aliasRegistry, aliasBinding);
+
+        this.spec = loadSpecIfValid(className);
+
+        this.mode = mode;
+        this.aliasBinding = aliasBinding;
+    }
+
+    private ObjectSpecification loadSpecIfValid(final String className) {
+        try {
+            return getSpecificationLoader().loadSpecification(className);
+        } catch (final IsisException ex) {
+            return null;
+        }
+    }
+
+    public boolean isSpecOk() {
+        return spec != null;
+    }
+
+    public List<OneToOneAssociation> getProperties() {
+        return properties;
+    }
+
+    public CellBinding getAliasBinding() {
+        return aliasBinding;
+    }
+
+    // ///////////////////////////////////////////////////////////////////////
+    // header
+    // ///////////////////////////////////////////////////////////////////////
+
+    public PropertyResult definePropertyOrAlias(final String heading, final int colNum) {
+
+        OneToOneAssociation otoa = null;
+
+        try {
+            final int aliasColumn = getAliasBinding().getColumn();
+            if (colNum == aliasColumn) {
+                return PropertyResult.ALIAS;
+            }
+
+            ObjectAssociation association = null;
+            try {
+                final String memberName = StringUtils.memberIdFor(heading);
+                association = spec.getAssociation(memberName);
+            } catch (final Exception ex) {
+                return PropertyResult.NO_SUCH_PROPERTY;
+            }
+
+            if (!association.isOneToOneAssociation()) {
+                return PropertyResult.NOT_A_PROPERTY;
+            }
+
+            otoa = (OneToOneAssociation) association;
+
+            return PropertyResult.OK;
+        } finally {
+            // add an association if OK, add null otherwise
+            getProperties().add(otoa);
+        }
+    }
+
+    // ///////////////////////////////////////////////////////////////////////
+    // each row
+    // ///////////////////////////////////////////////////////////////////////
+
+    /**
+     * Used by Concordion only.
+     * 
+     * <p>
+     * FitNesse, on the other hand, uses a more fine-grained approach, calling
+     * the underlying methods.
+     */
+    public void createObject() throws ScenarioBoundValueException {
+        final ObjectAdapter adapter = createInstance();
+
+        for (int colNum = 0; colNum < getProperties().size(); colNum++) {
+            final SetUpObjectResult result = setUpProperty(adapter, colNum);
+
+            if (!result.isHandled()) {
+                final CellBinding cellBinding = getCellBindings().get(colNum);
+                throw ScenarioBoundValueException.current(cellBinding, result.getErrorMessage());
+            }
+        }
+
+        persistIfNecessary(adapter);
+        alias(adapter);
+        resetForNextObject();
+    }
+
+    public void resetForNextObject() {
+        cellTextList.clear();
+        this.alias = null;
+    }
+
+    public ObjectAdapter createInstance() {
+        if (spec == null) {
+            return null;
+        }
+        return getPersistenceSession().createTransientInstance(spec);
+    }
+
+    public SetUpObjectResult setUpProperty(final ObjectAdapter adapter, final int colNum) {
+
+        final OneToOneAssociation association = getProperties().get(colNum);
+        if (association == null) {
+            return SetUpObjectResult.NO_ASSOCIATION;
+        }
+
+        final String cellText = cellTextList.get(colNum);
+
+        // handle empty cell as null
+        if (cellText == null || cellText.length() == 0) {
+
+            // use clear facet if available
+            final PropertyClearFacet clearFacet = association.getFacet(PropertyClearFacet.class);
+
+            if (clearFacet != null) {
+                clearFacet.clearProperty(adapter);
+                return SetUpObjectResult.CLEARED;
+            }
+
+            // use setter facet otherwise
+            final PropertySetterFacet setterFacet = association.getFacet(PropertySetterFacet.class);
+
+            if (setterFacet != null) {
+                setterFacet.setProperty(adapter, null);
+                return SetUpObjectResult.CLEARED;
+            }
+
+            return SetUpObjectResult.CANNOT_CLEAR;
+        }
+
+        // non-empty, will need a setter
+        final PropertySetterFacet setterFacet = association.getFacet(PropertySetterFacet.class);
+        if (setterFacet == null) {
+            return SetUpObjectResult.CANNOT_SET;
+        }
+
+        final ObjectSpecification fieldSpecification = association.getSpecification();
+        final ParseableFacet parseableFacet = fieldSpecification.getFacet(ParseableFacet.class);
+
+        ObjectAdapter referencedAdapter = null;
+        if (parseableFacet != null) {
+            // handle as parseable value
+            try {
+                referencedAdapter = parseableFacet.parseTextEntry(adapter, cellText, null);
+            } catch (final IllegalArgumentException ex) {
+                return SetUpObjectResult.CANNOT_PARSE;
+            }
+
+        } else {
+            // handle as reference to known object
+            referencedAdapter = getAliasRegistry().getAliased(cellText);
+            if (referencedAdapter == null) {
+                return SetUpObjectResult.UNKNOWN_REFERENCE;
+            }
+        }
+
+        setterFacet.setProperty(adapter, referencedAdapter);
+        return SetUpObjectResult.OK;
+    }
+
+    public void persistIfNecessary(final ObjectAdapter adapter) {
+        if (mode.isPersist()) {
+            // xactn mgmt now done by PersistenceSession#makePersistent()
+            // getTransactionManager().startTransaction();
+            getPersistenceSession().makePersistent(adapter);
+            // getTransactionManager().endTransaction();
+        }
+    }
+
+    public void alias(final ObjectAdapter adapter) {
+        final String alias = aliasFor(adapter);
+        getAliasRegistry().aliasAs(alias, adapter);
+    }
+
+    public String aliasFor(final ObjectAdapter adapter) {
+        if (alias != null) {
+            return alias;
+        } else {
+            final String specShortName = StringUtils.lowerLeading(spec.getShortIdentifier());
+            return getAliasRegistry().aliasPrefixedAs(specShortName, adapter);
+        }
+    }
+
+    public void forEachAssociation(final AssociationVisitor visitor) {
+        for (int colNum = 0; colNum < getProperties().size(); colNum++) {
+            final OneToOneAssociation association = getProperties().get(colNum);
+            if (association != null) {
+                visitor.visit(association, colNum);
+            }
+        }
+    }
+
+    public boolean addPropertyValueOrAlias(final String propertyValue) {
+        cellTextList.add(propertyValue);
+
+        // capture alias if just added
+        final int aliasColumn1based = getAliasBinding().getColumn() + 1;
+        if (cellTextList.size() == aliasColumn1based) {
+            alias = propertyValue;
+        }
+
+        return true;
+    }
+
+}