http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ServiceActionsModel.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ServiceActionsModel.java
 
b/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ServiceActionsModel.java
new file mode 100644
index 0000000..d0bcc36
--- /dev/null
+++ 
b/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ServiceActionsModel.java
@@ -0,0 +1,74 @@
+/*
+ *  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.wicket.model.models;
+
+import java.util.List;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import org.apache.isis.applib.annotation.DomainServiceLayout;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import 
org.apache.isis.core.metamodel.facets.object.domainservicelayout.DomainServiceLayoutFacet;
+
+/**
+ * Backing model for actions of application services menu bar (typically, as
+ * displayed along the top or side of the page).
+ */
+public class ServiceActionsModel extends ModelAbstract<List<ObjectAdapter>> {
+
+    private static final long serialVersionUID = 1L;
+
+    private final DomainServiceLayout.MenuBar menuBar;
+
+    /**
+     * @param menuBar - may be null in special case of rendering the tertiary 
menu on the error page.
+     */
+    public ServiceActionsModel(final DomainServiceLayout.MenuBar menuBar) {
+        this.menuBar = menuBar;
+    }
+
+    /**
+     * The menu bar being rendered; may be null in special case of rendering 
the tertiary menu on the error page.
+     */
+    public DomainServiceLayout.MenuBar getMenuBar() {
+        return menuBar;
+    }
+
+    protected List<ObjectAdapter> load() {
+        return Lists.newArrayList(Iterables.filter(getServiceAdapters(), 
with(menuBar)));
+    }
+
+    private static Predicate<ObjectAdapter> with(final 
DomainServiceLayout.MenuBar menuBar) {
+        return new Predicate<ObjectAdapter>() {
+            @Override
+            public boolean apply(ObjectAdapter input) {
+                final DomainServiceLayoutFacet facet = 
input.getSpecification().getFacet
+                        (DomainServiceLayoutFacet.class);
+                return facet != null && facet.getMenuBar() == menuBar;
+            }
+        };
+    }
+
+    protected List<ObjectAdapter> getServiceAdapters() {
+        return getPersistenceSession().getServices();
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ValueModel.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ValueModel.java
 
b/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ValueModel.java
new file mode 100644
index 0000000..9ddd054
--- /dev/null
+++ 
b/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ValueModel.java
@@ -0,0 +1,66 @@
+/*
+ *  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.wicket.model.models;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import 
org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
+
+/**
+ * Represents a standalone value.
+ */
+public class ValueModel extends ModelAbstract<ObjectAdapter> {
+
+    private static final long serialVersionUID = 1L;
+
+    private final ObjectAdapterMemento adapterMemento;
+
+    public ValueModel(final ObjectAdapter adapter) {
+        adapterMemento = ObjectAdapterMemento.createOrNull(adapter);
+    }
+
+    @Override
+    protected ObjectAdapter load() {
+        return adapterMemento.getObjectAdapter(ConcurrencyChecking.NO_CHECK);
+    }
+
+    // //////////////////////////////////////
+
+    private ActionModel actionModelHint;
+    /**
+     * The {@link ActionModel model} of the {@link ObjectAction action} 
+     * that generated this {@link ValueModel}.
+     * 
+     * @see #setActionHint(ActionModel)
+     */
+    public ActionModel getActionModelHint() {
+        return actionModelHint;
+    }
+    /**
+     * Called by action.
+     * 
+     * @see #getActionModelHint()
+     */
+    public void setActionHint(ActionModel actionModelHint) {
+        this.actionModelHint = actionModelHint;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/VoidModel.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/VoidModel.java
 
b/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/VoidModel.java
new file mode 100644
index 0000000..c0437d3
--- /dev/null
+++ 
b/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/VoidModel.java
@@ -0,0 +1,61 @@
+/*
+ *  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.wicket.model.models;
+
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+
+
+/**
+ * Represents the result of invoking a <tt>void</tt> action.
+ */
+public class VoidModel extends ModelAbstract<Void> {
+
+    private static final long serialVersionUID = 1L;
+
+    public VoidModel() {
+    }
+
+    @Override
+    protected Void load() {
+        return null;
+    }
+
+
+    // //////////////////////////////////////
+
+    private ActionModel actionModelHint;
+    /**
+     * The {@link ActionModel model} of the {@link ObjectAction action} 
+     * that generated this {@link VoidModel}.
+     * 
+     * @see #setActionHint(ActionModel)
+     */
+    public ActionModel getActionModelHint() {
+        return actionModelHint;
+    }
+    /**
+     * Called by action.
+     * 
+     * @see #getActionModelHint()
+     */
+    public void setActionHint(ActionModel actionModelHint) {
+        this.actionModelHint = actionModelHint;
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/WelcomeModel.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/WelcomeModel.java
 
b/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/WelcomeModel.java
new file mode 100644
index 0000000..8e43887
--- /dev/null
+++ 
b/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/WelcomeModel.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.wicket.model.models;
+
+/**
+ * Model providing welcome text.
+ */
+public class WelcomeModel extends ModelAbstract<String> {
+
+    private static final long serialVersionUID = 1L;
+
+    public WelcomeModel(final String message) {
+        setObject(message);
+    }
+
+    @Override
+    protected String load() {
+        return getObject();
+    }
+
+    @Override
+    public void setObject(final String message) {
+        if(message == null) {
+            return;
+        }
+        super.setObject(message);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/WicketComponentUtils.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/WicketComponentUtils.java
 
b/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/WicketComponentUtils.java
new file mode 100644
index 0000000..1fba4ed
--- /dev/null
+++ 
b/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/WicketComponentUtils.java
@@ -0,0 +1,57 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.isis.viewer.wicket.model.models;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.Page;
+import org.apache.wicket.markup.renderStrategy.DeepChildFirstVisitor;
+import org.apache.wicket.util.visit.IVisit;
+
+public class WicketComponentUtils {
+
+    public WicketComponentUtils(){}
+
+    /**
+     * Locates a component implementing the required class on the same page as 
the supplied component.
+     */
+    public static <T> T getFrom(Component component, final Class<T> cls) {
+        return getFrom(component.getPage(), cls);
+    }
+
+    /**
+     * Locates a component implementing the required class on the supplied 
page.
+     */
+    public static <T> T getFrom(Page page, final Class<T> cls) {
+        final Object[] pComponent = new Object[1];
+        page.visitChildren(new DeepChildFirstVisitor() {
+            @Override
+            public void component(Component component, IVisit<Void> visit) {
+                if(cls.isAssignableFrom(component.getClass())) {
+                    pComponent[0] =  component;
+                    visit.stop();
+                }
+            }
+            @Override
+            public boolean preCheck(Component component) {
+                return false;
+            }
+        });
+
+        return (T) pComponent[0];
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/MementoFunctions.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/MementoFunctions.java
 
b/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/MementoFunctions.java
new file mode 100644
index 0000000..45cfd33
--- /dev/null
+++ 
b/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/MementoFunctions.java
@@ -0,0 +1,104 @@
+/*
+ *  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.wicket.model.util;
+
+import com.google.common.base.Function;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.spec.ObjectSpecId;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
+import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.wicket.model.mementos.ActionMemento;
+import org.apache.isis.viewer.wicket.model.mementos.ActionParameterMemento;
+import org.apache.isis.viewer.wicket.model.mementos.CollectionMemento;
+import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
+import org.apache.isis.viewer.wicket.model.mementos.PropertyMemento;
+
+/**
+ * @deprecated - use {@link ObjectAdapterMemento.Functions}
+ */
+@Deprecated
+public final class MementoFunctions {
+
+    private MementoFunctions() {
+    }
+
+    /**
+     * @deprecated - use {@link ObjectAdapterMemento.Functions}
+     */
+    @Deprecated
+    public static Function<ObjectSpecification, ObjectSpecId> fromSpec() {
+        return ObjectAdapterMemento.Functions.fromSpec();
+    }
+
+    /**
+     * @deprecated - use {@link ObjectAdapterMemento.Functions}
+     */
+    @Deprecated
+    public static Function<OneToOneAssociation, PropertyMemento> 
fromProperty() {
+        return ObjectAdapterMemento.Functions.fromProperty();
+    }
+
+    /**
+     * @deprecated - use {@link ObjectAdapterMemento.Functions}
+     */
+    @Deprecated
+    public static Function<OneToManyAssociation, CollectionMemento> 
fromCollection() {
+        return ObjectAdapterMemento.Functions.fromCollection();
+    }
+
+    /**
+     * @deprecated - use {@link ObjectAdapterMemento.Functions}
+     */
+    @Deprecated
+    public static Function<ObjectAction, ActionMemento> fromAction() {
+        return ObjectAdapterMemento.Functions.fromAction();
+    }
+
+    /**
+     * @deprecated - use {@link ObjectAdapterMemento.Functions}
+     */
+    @Deprecated
+    public static Function<ObjectActionParameter, ActionParameterMemento> 
fromActionParameter() {
+        return ObjectAdapterMemento.Functions.fromActionParameter();
+    }
+
+    /**
+     * @deprecated - use {@link ObjectAdapterMemento.Functions}
+     */
+    @Deprecated
+    public static Function<Object, ObjectAdapterMemento> fromPojo(final 
AdapterManager adapterManager) {
+        return ObjectAdapterMemento.Functions.fromPojo(adapterManager);
+    }
+
+    /**
+     * @deprecated - use {@link ObjectAdapterMemento.Functions}
+     */
+    @Deprecated
+    public static Function<ObjectAdapter, ObjectAdapterMemento> fromAdapter() {
+        return ObjectAdapterMemento.Functions.fromAdapter();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/ObjectAdapterFunctions.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/ObjectAdapterFunctions.java
 
b/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/ObjectAdapterFunctions.java
new file mode 100644
index 0000000..7700e04
--- /dev/null
+++ 
b/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/ObjectAdapterFunctions.java
@@ -0,0 +1,62 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.viewer.wicket.model.util;
+
+import com.google.common.base.Function;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import 
org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
+import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
+
+/**
+ * @deprecated - use {@link ObjectAdapter.Functions} or {@link 
ObjectAdapterMemento.Functions}
+ */
+@Deprecated
+public final class ObjectAdapterFunctions {
+
+    private ObjectAdapterFunctions() {
+    }
+
+    /**
+     * @deprecated - use {@link ObjectAdapter.Functions}
+     */
+    @Deprecated
+    public static Function<Object, ObjectAdapter> fromPojo(final 
AdapterManager adapterManager) {
+        return ObjectAdapter.Functions.adapterForUsing(adapterManager);
+    }
+
+    /**
+     * @deprecated - use {@link ObjectAdapterMemento.Functions}
+     */
+    @Deprecated
+    public static Function<ObjectAdapterMemento, ObjectAdapter> 
fromMemento(final ConcurrencyChecking concurrencyChecking) {
+        return ObjectAdapterMemento.Functions.fromMemento(concurrencyChecking);
+    }
+
+    /**
+     * @deprecated - use {@link ObjectAdapterMemento.Functions}
+     */
+    @Deprecated
+    public static Function<ObjectAdapter, ObjectAdapterMemento> toMemento() {
+        return ObjectAdapterMemento.Functions.toMemento();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/OidMatchers.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/OidMatchers.java
 
b/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/OidMatchers.java
new file mode 100644
index 0000000..7904a35
--- /dev/null
+++ 
b/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/OidMatchers.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.wicket.model.util;
+
+import org.hamcrest.Matcher;
+
+import org.apache.isis.core.metamodel.adapter.oid.Oid;
+
+/**
+ * @deprecated - use {@link Oid.Matchers}
+ */
+@Deprecated
+public final class OidMatchers {
+
+    private OidMatchers() {
+    }
+
+    /**
+     * @deprecated - use {@link Oid.Matchers}
+     */
+    @Deprecated
+    public static Matcher<Oid> isTransient() {
+        return Oid.Matchers.isTransient();
+    }
+
+    /**
+     * @deprecated - use {@link Oid.Matchers}
+     */
+    @Deprecated
+    public static Matcher<Oid> isPersistent() {
+        return Oid.Matchers.isPersistent();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/model/src/test/java/org/apache/isis/viewer/wicket/model/models/ActionModelTest.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/model/src/test/java/org/apache/isis/viewer/wicket/model/models/ActionModelTest.java
 
b/core/viewer-wicket/model/src/test/java/org/apache/isis/viewer/wicket/model/models/ActionModelTest.java
new file mode 100644
index 0000000..f7b5baa
--- /dev/null
+++ 
b/core/viewer-wicket/model/src/test/java/org/apache/isis/viewer/wicket/model/models/ActionModelTest.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.wicket.model.models;
+
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+import java.util.Map;
+
+import org.junit.Test;
+
+public class ActionModelTest {
+
+    @Test
+    public void whenParseThenParses() throws Exception {
+        final Map.Entry<Integer, String> parsed = 
ActionModel.parse("3=OBJECT_OID:123");
+        assertThat(parsed, is(not(nullValue())));
+        assertThat(parsed.getKey(), is(3));
+        assertThat(parsed.getValue(), is("OBJECT_OID:123"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/model/src/test/java/org/apache/isis/viewer/wicket/model/models/LowestCommonSuperclassClosureTest.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/model/src/test/java/org/apache/isis/viewer/wicket/model/models/LowestCommonSuperclassClosureTest.java
 
b/core/viewer-wicket/model/src/test/java/org/apache/isis/viewer/wicket/model/models/LowestCommonSuperclassClosureTest.java
new file mode 100644
index 0000000..08205b2
--- /dev/null
+++ 
b/core/viewer-wicket/model/src/test/java/org/apache/isis/viewer/wicket/model/models/LowestCommonSuperclassClosureTest.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.wicket.model.models;
+
+import static org.junit.Assert.assertThat;
+
+import java.util.List;
+
+import com.google.common.collect.Lists;
+
+import org.junit.Test;
+
+import org.apache.isis.core.commons.lang.IterableExtensions;
+import org.apache.isis.core.commons.matchers.IsisMatchers;
+
+public class LowestCommonSuperclassClosureTest {
+
+    static class Animal {}
+    static class Mineral {}
+    static class Vegetable {}
+    static class Mammal extends Animal {}
+    static class Lion extends Mammal {}
+    
+    @Test
+    public void nothingInCommon() throws Exception {
+        assertLowestCommonOfListIs(listOf(Animal.class, Mineral.class, 
Vegetable.class), Object.class);
+    }
+
+    @Test
+    public void superclassInCommon() throws Exception {
+        assertLowestCommonOfListIs(listOf(Animal.class, Mammal.class), 
Animal.class);
+    }
+    
+    @Test
+    public void subclassInCommon() throws Exception {
+        assertLowestCommonOfListIs(listOf(Lion.class, Lion.class), Lion.class);
+    }
+    
+    private static void assertLowestCommonOfListIs(List<Class<? extends 
Object>> list, Class<?> expected) {
+        EntityCollectionModel.LowestCommonSuperclassClosure closure = new 
EntityCollectionModel.LowestCommonSuperclassClosure();
+        IterableExtensions.fold(list, closure);
+        assertThat(closure.getLowestCommonSuperclass(), 
IsisMatchers.classEqualTo(expected));
+    }
+
+    private static List<Class<? extends Object>> listOf(Class<?>... classes) {
+        return Lists.newArrayList(classes);
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/model/src/test/java/org/apache/isis/viewer/wicket/model/models/ModelAbstractTest.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/model/src/test/java/org/apache/isis/viewer/wicket/model/models/ModelAbstractTest.java
 
b/core/viewer-wicket/model/src/test/java/org/apache/isis/viewer/wicket/model/models/ModelAbstractTest.java
new file mode 100644
index 0000000..4655239
--- /dev/null
+++ 
b/core/viewer-wicket/model/src/test/java/org/apache/isis/viewer/wicket/model/models/ModelAbstractTest.java
@@ -0,0 +1,170 @@
+/**
+ *  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.wicket.model.models;
+
+import java.util.Map;
+import org.apache.wicket.Component;
+import org.apache.wicket.MarkupContainer;
+import org.apache.wicket.model.IModel;
+import org.jmock.Expectations;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2;
+import org.apache.isis.viewer.wicket.model.hints.UiHintPathSignificant;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+public class ModelAbstractTest {
+
+    @Rule
+    public JUnitRuleMockery2 context = 
JUnitRuleMockery2.createFor(JUnitRuleMockery2.Mode.INTERFACES_AND_CLASSES);
+
+    ModelAbstract<String> target;
+
+    static class UiHintPathSignificantComponent extends Component implements 
UiHintPathSignificant {
+        public UiHintPathSignificantComponent(String id) {
+            super(id);
+        }
+
+        public UiHintPathSignificantComponent(String id, IModel<?> model) {
+            super(id, model);
+        }
+
+        @Override
+        protected void onRender() {
+        }
+    }
+
+    static class UiHintPathSignificantMarkupContainer extends MarkupContainer 
implements UiHintPathSignificant {
+        public UiHintPathSignificantMarkupContainer(String id) {
+            super(id);
+        }
+
+        public UiHintPathSignificantMarkupContainer(String id, IModel<?> 
model) {
+            super(id, model);
+        }
+
+        @Override
+        protected void onRender() {
+        }
+    }
+
+    MarkupContainer mockParent;
+    Component mockComponent1;
+    Component mockComponent2;
+
+    @Before
+    public void setUp() throws Exception {
+        target = new ModelAbstract<String>("foo"){
+            @Override
+            protected String load() {
+                return null;
+            }
+        };
+
+        mockParent = context.mock(UiHintPathSignificantMarkupContainer.class, 
"parent");
+        mockComponent1 = context.mock(UiHintPathSignificantComponent.class, 
"component1");
+        mockComponent2 = context.mock(UiHintPathSignificantComponent.class, 
"component2");
+
+        context.checking(new Expectations() {{
+            allowing(mockParent).getId();
+            will(returnValue("parent"));
+
+            allowing(mockComponent1).getId();
+            will(returnValue("id1"));
+
+            allowing(mockComponent2).getId();
+            will(returnValue("id2"));
+
+            ignoring(mockComponent1);
+            ignoring(mockComponent2);
+
+        }});
+
+        mockComponent1.setParent(mockParent);
+        mockComponent2.setParent(mockParent);
+    }
+
+    public static class Hints extends ModelAbstractTest {
+
+        @Test
+        public void empty() throws Exception {
+            assertThat(target.getHint(mockComponent1, "key1"), 
is(nullValue()));
+        }
+
+        @Test
+        public void single() throws Exception {
+            target.setHint(mockComponent1, "key1", "value1");
+            assertThat(target.getHint(mockComponent1, "key1"), is("value1"));
+        }
+
+        @Test
+        public void clear() throws Exception {
+            target.setHint(mockComponent1, "key1", "value1");
+            assertThat(target.getHint(mockComponent1, "key1"), is("value1"));
+            target.clearHint(mockComponent1, "key1");
+            assertThat(target.getHint(mockComponent1, "key1"), 
is(nullValue()));
+        }
+
+        @Test
+        public void setToNull() throws Exception {
+            target.setHint(mockComponent1, "key1", "value1");
+            assertThat(target.getHint(mockComponent1, "key1"), is("value1"));
+            target.setHint(mockComponent1, "key1", null);
+            assertThat(target.getHint(mockComponent1, "key1"), 
is(nullValue()));
+        }
+
+        @Test
+        public void multipleKeys() throws Exception {
+            target.setHint(mockComponent1, "key1", "value1");
+            target.setHint(mockComponent1, "key2", "value2");
+            assertThat(target.getHint(mockComponent1, "key1"), is("value1"));
+            assertThat(target.getHint(mockComponent1, "key2"), is("value2"));
+        }
+
+        @Test
+        public void multipleComponents() throws Exception {
+            target.setHint(mockComponent1, "key", "valueA");
+            target.setHint(mockComponent2, "key", "valueB");
+            assertThat(target.getHint(mockComponent1, "key"), is("valueA"));
+            assertThat(target.getHint(mockComponent2, "key"), is("valueB"));
+        }
+
+        @Test
+        public void smoke() throws Exception {
+            target.setHint(mockComponent1, "X", "1.X");
+            target.setHint(mockComponent1, "A", "1.A");
+            target.setHint(mockComponent1, "B", "1.B");
+            target.setHint(mockComponent1, "C", "1.C");
+            target.setHint(mockComponent2, "X", "2.X");
+            target.setHint(mockComponent2, "P", "2.P");
+            target.setHint(mockComponent2, "Q", "2.Q");
+            target.setHint(mockComponent2, "R", "2.R");
+
+            final Map<String, String> hints = target.getHints();
+            assertThat(hints.size(), is(8));
+            assertThat(hints.get("id1-X"), is("1.X"));
+            assertThat(hints.get("id2-X"), is("2.X"));
+            assertThat(hints.get("id1-B"), is("1.B"));
+            assertThat(hints.get("id2-R"), is("2.R"));
+        }
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/pom.xml
----------------------------------------------------------------------
diff --git a/core/viewer-wicket/pom.xml b/core/viewer-wicket/pom.xml
new file mode 100644
index 0000000..0e61f86
--- /dev/null
+++ b/core/viewer-wicket/pom.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+
+       <modelVersion>4.0.0</modelVersion>
+
+       <parent>
+               <groupId>org.apache.isis.core</groupId>
+               <artifactId>isis</artifactId>
+        <version>1.8.0-SNAPSHOT</version>
+       </parent>
+
+       <groupId>org.apache.isis.viewer</groupId>
+       <artifactId>isis-viewer-wicket</artifactId>
+
+       <name>Isis Wicket Viewer</name>
+
+       <packaging>pom</packaging>
+
+    <properties>
+        <siteBaseDir>..</siteBaseDir>
+        <relativeUrl />
+
+    </properties>
+
+    <!-- used in Site generation for relative references. -->
+    <url>http://isis.apache.org/${relativeUrl}</url>
+
+    <modules>
+        <module>applib</module>
+        <module>model</module>
+        <module>ui</module>
+        <module>impl</module>
+    </modules>
+
+    <build>
+        <pluginManagement>
+            <plugins>
+                               <plugin>
+                                       <groupId>net.alchim31.maven</groupId>
+                                       
<artifactId>yuicompressor-maven-plugin</artifactId>
+                                       <version>1.5.0</version>
+                                       <configuration>
+                                               <statistics>true</statistics>
+                                               <jswarn>false</jswarn>
+                                               <suffix>.min</suffix>
+                                               <excludes>
+                                                       
<exclude>**/moment.js</exclude>
+                                                       
<exclude>**/moment.min.js</exclude>
+                                                       
<exclude>**/bootstrap-datetimepicker.js</exclude>
+                                                       
<exclude>**/bootstrap-datetimepicker.min.js</exclude>
+                                                       
<exclude>**/bootstrap-growl.js</exclude>
+                                                       
<exclude>**/bootstrap-growl.min.js</exclude>
+                                               </excludes>
+                                       </configuration>
+                                       <executions>
+                                               <execution>
+                                                       <goals>
+                                                               
<goal>compress</goal>
+                                                       </goals>
+                                               </execution>
+                                       </executions>
+                               </plugin>
+                       </plugins>
+               </pluginManagement>
+       </build>
+
+</project>

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/src/main/appended-resources/supplemental-models.xml
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/src/main/appended-resources/supplemental-models.xml 
b/core/viewer-wicket/src/main/appended-resources/supplemental-models.xml
new file mode 100644
index 0000000..b839240
--- /dev/null
+++ b/core/viewer-wicket/src/main/appended-resources/supplemental-models.xml
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 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. -->
+<supplementalDataModels 
xmlns="http://maven.apache.org/supplemental-model/1.0.0";
+                        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+                        
xsi:schemaLocation="http://maven.apache.org/supplemental-model/1.0.0 
http://maven.apache.org/xsd/supplemental-model-1.0.0.xsd";>
+
+  <supplement>
+    <project>
+      <groupId>aopalliance</groupId>
+      <artifactId>aopalliance</artifactId>
+      <version>1.0</version>
+      <licenses>
+          <license>
+              <name>Public Domain</name>
+          </license>
+      </licenses>
+    </project>
+  </supplement>
+
+  <supplement>
+    <project>
+      <groupId>dom4j</groupId>
+      <artifactId>dom4j</artifactId>
+      <version>1.6.1</version>
+      <licenses>
+        <license>
+            <name>BSD License</name>
+            <url>http://dom4j.sourceforge.net/dom4j-1.6.1/license.html</url>
+            <distribution>repo</distribution>          
+        </license>
+      </licenses>
+    </project>
+  </supplement>
+
+
+    <supplement>
+        <project>
+            <groupId>org.datanucleus</groupId>
+            <artifactId>datanucleus-jdo-query</artifactId>
+            <version>3.0.2</version>
+            <licenses>
+                <license>
+                    <name>The Apache Software License, Version 2.0</name>
+                    <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+                </license>
+            </licenses>
+        </project>
+    </supplement>
+
+    <supplement>
+        <project>
+            <groupId>javax.transaction</groupId>
+            <artifactId>transaction-api</artifactId>
+            <version>1.1</version>
+            <name>Java Transaction API (JTA)</name>
+            <organization>
+                <name>Oracle Corp</name>
+                <url>http://www.oracle.com/</url>
+            </organization>
+            <licenses>
+                <license>
+                    <name>Common Development and Distribution License (CDDL) 
v1.0</name>
+                    <url>https://glassfish.java.net/public/CDDLv1.0.html</url>
+                </license>
+            </licenses>
+        </project>
+    </supplement>
+
+    <!--
+      <supplement>
+        <project>
+            <groupId>org.datanucleus</groupId>
+            <artifactId>datanucleus-jodatime</artifactId>
+            <version>3.1.1</version>
+              <licenses>
+                <license>
+                    <name>The Apache Software License, Version 2.0</name>
+                    <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+                </license>
+            </licenses>
+        </project>
+      </supplement>
+
+      <supplement>
+        <project>
+          <groupId>org.scannotation</groupId>
+          <artifactId>scannotation</artifactId>
+          <version>1.0.3</version>
+          <licenses>
+            <license>
+                <name>The Apache Software License, Version 2.0</name>
+                <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+                <distribution>repo</distribution>
+            </license>
+          </licenses>
+        </project>
+      </supplement>
+
+      <supplement>
+        <project>
+          <groupId>net.jcip</groupId>
+          <artifactId>jcip-annotations</artifactId>
+          <version>1.0</version>
+          <licenses>
+            <license>
+                <name>Creative Commons Attribution 2.5 License</name>
+                <url>http://creativecommons.org/licenses/by/2.5/</url>
+                <distribution>repo</distribution>
+            </license>
+          </licenses>
+        </project>
+      </supplement>
+
+
+      <supplement>
+        <project>
+          <groupId>xalan</groupId>
+          <artifactId>xalan</artifactId>
+          <version>2.7.0</version>
+          <licenses>
+            <license>
+                <name>The Apache Software License, Version 2.0</name>
+                <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+                <distribution>repo</distribution>
+            </license>
+          </licenses>
+        </project>
+      </supplement>
+     -->
+
+ 
+</supplementalDataModels>

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/ui/pom.xml
----------------------------------------------------------------------
diff --git a/core/viewer-wicket/ui/pom.xml b/core/viewer-wicket/ui/pom.xml
new file mode 100644
index 0000000..bca5b7d
--- /dev/null
+++ b/core/viewer-wicket/ui/pom.xml
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+
+       <modelVersion>4.0.0</modelVersion>
+
+       <parent>
+               <groupId>org.apache.isis.viewer</groupId>
+               <artifactId>isis-viewer-wicket</artifactId>
+        <version>1.8.0-SNAPSHOT</version>
+       </parent>
+
+       <artifactId>isis-viewer-wicket-ui</artifactId>
+       <name>Isis Wicket Viewer UI Components</name>
+
+    <properties>
+               <siteBaseDir>..</siteBaseDir>
+               <relativeUrl>ui/</relativeUrl>
+       </properties>
+
+    <!-- used in Site generation for relative references. -->
+    <url>http://isis.apache.org/${relativeUrl}</url>
+
+       <build>
+               <resources>
+                       <resource>
+                               <filtering>false</filtering>
+                               <directory>src/main/resources</directory>
+                       </resource>
+                       <resource>
+                               <filtering>false</filtering>
+                               <directory>src/main/java</directory>
+                               <includes>
+                                       <include>**</include>
+                               </includes>
+                               <excludes>
+                                       <exclude>**/*.java</exclude>
+                               </excludes>
+                       </resource>
+               </resources>
+               <plugins>
+                       <plugin>
+                               <groupId>net.alchim31.maven</groupId>
+                               
<artifactId>yuicompressor-maven-plugin</artifactId>
+                       </plugin>
+               </plugins>
+       </build>
+
+       <dependencies>
+               <dependency>
+                       <groupId>org.apache.isis.viewer</groupId>
+                       <artifactId>isis-viewer-wicket-model</artifactId>
+               </dependency>
+
+               <dependency>
+                   <groupId>org.apache.isis.core</groupId>
+                   <artifactId>isis-core-metamodel</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.apache.isis.core</groupId>
+                       <artifactId>isis-core-unittestsupport</artifactId>
+                       <scope>test</scope>
+               </dependency>
+
+               <dependency>
+                       <groupId>org.apache.wicket</groupId>
+                       <artifactId>wicket-core</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.apache.wicket</groupId>
+                       <artifactId>wicket-extensions</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.apache.wicket</groupId>
+                       <artifactId>wicket-auth-roles</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.apache.wicket</groupId>
+                       <artifactId>wicket-guice</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>com.vaynberg.wicket.select2</groupId>
+                       <artifactId>wicket-select2</artifactId>
+               </dependency>
+
+        <dependency>
+            <groupId>org.webjars</groupId>
+            <artifactId>select2</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.webjars</groupId>
+            <artifactId>jquery-ui</artifactId>
+        </dependency>
+
+        <!-- WEBJARS -->
+        <dependency>
+            <groupId>de.agilecoders.wicket.webjars</groupId>
+            <artifactId>wicket-webjars</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>de.agilecoders.wicket</groupId>
+            <artifactId>wicket-bootstrap-core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>de.agilecoders.wicket</groupId>
+            <artifactId>wicket-bootstrap-extensions</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>de.agilecoders.wicket</groupId>
+            <artifactId>wicket-bootstrap-themes</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-servlet_2.5_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- LOGGING DEPENDENCIES - LOG4J -->
+
+               <dependency>
+                       <groupId>org.slf4j</groupId>
+                       <artifactId>slf4j-log4j12</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>log4j</groupId>
+                       <artifactId>log4j</artifactId>
+               </dependency>
+
+       </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/ui/src/main/java/images/Images.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket/ui/src/main/java/images/Images.java 
b/core/viewer-wicket/ui/src/main/java/images/Images.java
new file mode 100644
index 0000000..f1e6fb0
--- /dev/null
+++ b/core/viewer-wicket/ui/src/main/java/images/Images.java
@@ -0,0 +1,33 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package images;
+
+import org.apache.wicket.request.resource.PackageResource;
+
+/**
+ * This is a bit of a hack, but the Isis convention is to plonk all the images
+ * in an images package. This empty class allows Wicket to pick them up as
+ * {@link PackageResource}s.
+ */
+public final class Images {
+
+    private Images() {
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/CollectionContentsAsFactory.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/CollectionContentsAsFactory.java
 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/CollectionContentsAsFactory.java
new file mode 100644
index 0000000..440b0ff
--- /dev/null
+++ 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/CollectionContentsAsFactory.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.wicket.ui;
+
+import org.apache.wicket.model.IModel;
+
+/**
+ * <p>
+ * An interface for all {@link 
org.apache.isis.viewer.wicket.ui.ComponentFactory component factories}
+ * (e.g. CollectionContentAsXyzFactory-ies) which want to provide specific 
title and CSS class(es)
+ * for their representation in {@link 
org.apache.isis.viewer.wicket.ui.components.collectioncontents.multiple.CollectionContentsMultipleViewsPanel}.
+ * </p>
+ * <p>
+ * If the {@link org.apache.isis.viewer.wicket.ui.ComponentFactory} doesn't 
implement this interface or the implementation
+ * of any of its methods return {@code null} then {@link 
ComponentFactory#getName()} will be used as title and its
+ * {@link 
org.apache.isis.core.commons.lang.StringExtensions#asLowerDashed(java.lang.String)
 dashed representation}
+ * as CSS class for the optional image.
+ * </p>
+ */
+public interface CollectionContentsAsFactory {
+
+    /**
+     * @return A model that will be used as a label for the "View as" dropdown 
for "collection contents as"
+     * component factories
+     */
+    IModel<String> getTitleLabel();
+
+    /**
+     * @return A model that will be used as a CSS class for the icon/image 
next to "View as" dropdown
+     * for "collection contents as" component factories
+     */
+    IModel<String> getCssClass();
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/ComponentFactory.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/ComponentFactory.java
 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/ComponentFactory.java
new file mode 100644
index 0000000..e52ad7a
--- /dev/null
+++ 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/ComponentFactory.java
@@ -0,0 +1,107 @@
+/*
+ *  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.wicket.ui;
+
+import java.io.Serializable;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.request.resource.CssResourceReference;
+
+import org.apache.isis.viewer.wicket.ui.app.registry.ComponentFactoryRegistry;
+
+/**
+ * Creates {@link Component}s of a specified {@link ComponentType}, optionally
+ * {@link #appliesTo(ComponentType, IModel) dependent on} the provided
+ * {@link IModel model}.
+ * 
+ * <p>
+ * This interface is at the very heart of the Wicket Objects' model, being an
+ * usage of the chain-of-responsibility design pattern. The available
+ * {@link ComponentFactory}s are registered through
+ * {@link ComponentFactoryRegistry} (bootstrapped from the
+ * <tt>IsisWicketApplication</tt>); various adapters make it easy to lookup
+ * {@link Component}s from this registry.
+ */
+public interface ComponentFactory extends Serializable {
+
+    /**
+     * The {@link ComponentType} with which this component factory has been
+     * registered.
+     */
+    ComponentType getComponentType();
+
+    public enum ApplicationAdvice {
+        APPLIES(true, false), 
+        APPLIES_EXCLUSIVELY(true, true), 
+        DOES_NOT_APPLY(false, false);
+        private final boolean applies;
+        private final boolean exclusively;
+
+        private ApplicationAdvice(final boolean applies, final boolean 
exclusively) {
+            this.applies = applies;
+            this.exclusively = exclusively;
+        }
+
+        public boolean applies() {
+            return applies;
+        }
+
+        /**
+         * Whether no other {@link ComponentFactory}s should apply (ie stop
+         * searching for other views).
+         */
+        public boolean exclusively() {
+            return exclusively;
+        }
+        
+        public static final ApplicationAdvice appliesIf(final boolean b) {
+            return b ? ApplicationAdvice.APPLIES : 
ApplicationAdvice.DOES_NOT_APPLY;
+        }
+    }
+
+    /**
+     * Whether the {@link Component} created by this factory applies to the
+     * specified {@link ComponentType} and {@link IModel}.
+     */
+    ApplicationAdvice appliesTo(ComponentType componentType, IModel<?> model);
+
+    /**
+     * Creates component, with id being derived from the
+     * {@link #getComponentType() component type} for this factory.
+     * 
+     * @param model
+     * @return
+     */
+    Component createComponent(IModel<?> model);
+
+    /**
+     * Creates component, with specified id.
+     */
+    Component createComponent(String id, IModel<?> model);
+
+    /**
+     * Used for rendering in drop-downs.
+     */
+    String getName();
+
+    CssResourceReference getCssResourceReference();
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/ComponentFactoryAbstract.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/ComponentFactoryAbstract.java
 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/ComponentFactoryAbstract.java
new file mode 100644
index 0000000..e018a74
--- /dev/null
+++ 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/ComponentFactoryAbstract.java
@@ -0,0 +1,115 @@
+/*
+ *  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.wicket.ui;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.request.resource.CssResourceReference;
+
+import org.apache.isis.viewer.wicket.ui.panels.PanelUtil;
+
+/**
+ * Adapter implementation for {@link ComponentFactory}.
+ */
+public abstract class ComponentFactoryAbstract implements ComponentFactory {
+
+    private static final long serialVersionUID = 1L;
+
+    private final ComponentType componentType;
+    private final String name;
+
+    private final Class<?> componentClass;
+
+    public ComponentFactoryAbstract(final ComponentType componentType) {
+        this(componentType, null, null);
+    }
+
+    public ComponentFactoryAbstract(final ComponentType componentType, final 
String name) {
+        this(componentType, name, null);
+    }
+    
+    public ComponentFactoryAbstract(final ComponentType componentType, 
@SuppressWarnings("rawtypes") Class componentClass) {
+        this(componentType, null, componentClass);
+    }
+
+    public ComponentFactoryAbstract(final ComponentType componentType, final 
String name, @SuppressWarnings("rawtypes") Class componentClass) {
+        this.componentType = componentType;
+        this.name = name != null ? name : getClass().getSimpleName();
+        if(componentClass != null && 
ComponentFactory.class.isAssignableFrom(componentClass)) {
+            throw new IllegalArgumentException("specified a ComponentFactory 
as a componentClass... you probably meant the component instead? componentClass 
= " + componentClass.getName());
+        }
+        this.componentClass = componentClass;
+    }
+
+    @Override
+    public ComponentType getComponentType() {
+        return componentType;
+    }
+
+    /**
+     * Applies if {@link #getComponentType()} matches; disregards the provided
+     * {@link IModel}.
+     * 
+     * @see #appliesTo(IModel)
+     */
+    @Override
+    public final ApplicationAdvice appliesTo(final ComponentType 
componentType, final IModel<?> model) {
+        if (componentType != getComponentType()) {
+            return ApplicationAdvice.DOES_NOT_APPLY;
+        }
+        return appliesTo(model);
+    }
+
+    /**
+     * Hook for subclasses to check the {@link IModel}.
+     */
+    protected abstract ApplicationAdvice appliesTo(IModel<?> model);
+
+    protected final ApplicationAdvice appliesIf(final boolean b) {
+        return ApplicationAdvice.appliesIf(b);
+    }
+
+    /**
+     * Convenience for subclasses to call from {@link #appliesTo(IModel)}
+     */
+    protected final ApplicationAdvice appliesExclusivelyIf(final boolean b) {
+        return b ? ApplicationAdvice.APPLIES_EXCLUSIVELY : 
ApplicationAdvice.DOES_NOT_APPLY;
+    }
+
+    @Override
+    public final Component createComponent(final IModel<?> model) {
+        return createComponent(getComponentType().toString(), model);
+    }
+
+    @Override
+    public abstract Component createComponent(String id, IModel<?> model);
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public CssResourceReference getCssResourceReference() {
+        return PanelUtil.cssResourceReferenceFor(componentClass);
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/ComponentType.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/ComponentType.java
 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/ComponentType.java
new file mode 100644
index 0000000..70281cf
--- /dev/null
+++ 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/ComponentType.java
@@ -0,0 +1,180 @@
+/*
+ *  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.wicket.ui;
+
+import org.apache.wicket.Component;
+
+import org.apache.isis.core.commons.lang.StringExtensions;
+
+/**
+ * Enumerates the different types of {@link Component}s that can be constructed
+ * using {@link ComponentFactory}.
+ * 
+ * <p>
+ * Some are fine-grained (such as {@link ComponentType#SCALAR_NAME_AND_VALUE}, 
a
+ * panel to represent a single scalar property or parameter), but others are
+ * somewhat larger (such as {@link ComponentType#ENTITY}, representing an
+ * entity, with its actions, properties and collections).
+ */
+public enum ComponentType {
+
+    
+    /**
+     * About page text.
+     */
+    ABOUT,
+    /**
+     * Welcome page text.
+     */
+    WELCOME,
+    /**
+     * List of services and their actions.
+     * 
+     * <p>
+     * Could be rendered using a JavaScript or DHTML menu, an accordion, or a
+     * tree view.
+     */
+    SERVICE_ACTIONS,
+    /**
+     * A single domain entity.
+     */
+    ENTITY,
+    /**
+     * Icon and title for a single entity.
+     */
+    ENTITY_ICON_AND_TITLE,
+    /**
+     * Icon, title and a copy link for a single entity.
+     */
+    ENTITY_ICON_TITLE_AND_COPYLINK,
+    /**
+     * Title, icon and action list for a single entity.
+     */
+    ENTITY_SUMMARY,
+    /**
+     * The set of properties for a single entity.
+     */
+    ENTITY_PROPERTIES,
+    /**
+     * The set of collections of a single entity, designed to be standalone 
outside of a form.
+     * 
+     * <p>
+     * compare with {@value #ENTITY_COLLECTIONS}.
+     */
+    ENTITY_COLLECTIONS,
+    /**
+     * A single standalone value, as might be returned from an action.
+     */
+    VALUE,
+    /**
+     * The name and value of a single property or parameter, ie a scalar.
+     */
+    SCALAR_NAME_AND_VALUE,
+    /**
+     * The name and contents of a single collection of an entity;
+     * {@link Component}s are expected to use {@link #COLLECTION_CONTENTS} to
+     * actually render the contents.
+     */
+    COLLECTION_NAME_AND_CONTENTS,
+    /**
+     * The parameter form (dialog box) of an action.
+     */
+    PARAMETERS,
+    /**
+     * Info details for an action, eg to display the target, a resubmit button,
+     * any description or help text, and so on.
+     */
+    ACTION_INFO,
+    /**
+     * Used to display the parameters of an action.
+     */
+    ACTION_PROMPT,
+    /**
+     * Top-level component for rendering a standalone collection (ie as 
returned by
+     * an action).
+     */
+    STANDALONE_COLLECTION,
+    /**
+     * Bookmarked link to invoke an action
+     */
+    ACTION_LINK,
+    /**
+     * A collection of entities (the value of)
+     */
+    COLLECTION_CONTENTS,
+    /**
+     * A link to an entity.
+     */
+    ENTITY_LINK,
+    /**
+     * A collection of entities, from an action, but none returned.
+     */
+    EMPTY_COLLECTION,
+    /**
+     * A void result from an action.
+     */
+    VOID_RETURN,
+    /**
+     * A list of {@link IsisModel}s, rendered as a list of links.
+     */
+    BOOKMARKED_PAGES, 
+    /**
+     * Place holder for a component used to represent an unknown model;
+     * not used for matching, since the {@link ComponentFactory} implementation
+     * acts as a fallback whenever a more suitable factory cannot be located.
+     */
+    UNKNOWN,
+
+    /**
+     * The header (navigation bar) of the page
+     */
+    HEADER,
+
+    /**
+     * The footer of the page
+     */
+    FOOTER;
+
+    /**
+     * Returns the {@link #name()} formatted as
+     * {@link 
org.apache.isis.core.commons.lang.StringExtensions#toCamelCase(String) case}.
+     * 
+     * <p>
+     * For example, <tt>OBJECT_EDIT</tt> becomes <tt>objectEdit</tt>.
+     */
+    @Override
+    public String toString() {
+        return getWicketId();
+    }
+
+    public String getWicketId() {
+        return StringExtensions.toCamelCase(name());
+    }
+
+    public static ComponentType lookup(final String id) {
+        for (final ComponentType componentType : values()) {
+            if (componentType.getWicketId().equals(id)) {
+                return componentType;
+            }
+        }
+        return null;
+    }
+
+}

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

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/actionresponse/ActionResultResponse.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/actionresponse/ActionResultResponse.java
 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/actionresponse/ActionResultResponse.java
new file mode 100644
index 0000000..ad5bbf5
--- /dev/null
+++ 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/actionresponse/ActionResultResponse.java
@@ -0,0 +1,92 @@
+/**
+ *  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.wicket.ui.actionresponse;
+
+import java.net.URL;
+
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.request.IRequestHandler;
+
+import org.apache.isis.viewer.wicket.ui.pages.PageAbstract;
+
+/**
+ * The response to provide as a result of interpreting the response;
+ * either to show a {@link #toPage(PageAbstract) page}, or to {@link 
#withHandler(IRequestHandler) redirect} to a 
+ * handler (eg a download).
+ */
+public class ActionResultResponse {
+    
+    private final ActionResultResponseHandlingStrategy handlingStrategy;
+    private final IRequestHandler handler;
+    private final PageAbstract page;
+    private final AjaxRequestTarget target;
+    private final URL url;
+    
+    public static ActionResultResponse withHandler(IRequestHandler handler) {
+        return new ActionResultResponse(
+                ActionResultResponseHandlingStrategy.SCHEDULE_HANDLER, 
handler, null, null, null);
+    }
+    public static ActionResultResponse toPage(PageAbstract page) {
+        return new ActionResultResponse(
+                ActionResultResponseHandlingStrategy.REDIRECT_TO_PAGE, null, 
page, null, null);
+    }
+    public static ActionResultResponse openUrlInBrowser(final 
AjaxRequestTarget target, final URL url) {
+        return new ActionResultResponse(
+                ActionResultResponseHandlingStrategy.OPEN_URL_IN_BROWSER, 
null, null, target, url);
+    }
+    private ActionResultResponse(
+            final ActionResultResponseHandlingStrategy strategy, 
+            final IRequestHandler handler, 
+            final PageAbstract page, 
+            final AjaxRequestTarget target,
+            final URL url) {
+        handlingStrategy = strategy;
+        this.handler = handler;
+        this.page = page;
+        this.target = target;
+        this.url = url;
+    }
+
+    public ActionResultResponseHandlingStrategy getHandlingStrategy() {
+        return handlingStrategy;
+    }
+
+    /**
+     * Populated only if {@link #getHandlingStrategy() handling strategy} is 
{@link ActionResultResponseHandlingStrategy#SCHEDULE_HANDLER}
+     */
+    public IRequestHandler getHandler() {
+        return handler;
+    }
+    /**
+     * Populated only if {@link #getHandlingStrategy() handling strategy} is 
{@link ActionResultResponseHandlingStrategy#REDIRECT_TO_PAGE}
+     */
+    public PageAbstract getToPage() {
+        return page;
+    }
+    /**
+     * Populated only if {@link #getHandlingStrategy() handling strategy} is 
{@link ActionResultResponseHandlingStrategy#OPEN_URL_IN_BROWSER}
+     */
+    public AjaxRequestTarget getTarget() {
+        return target;
+    }
+    /**
+     * Populated only if {@link #getHandlingStrategy() handling strategy} is 
{@link ActionResultResponseHandlingStrategy#OPEN_URL_IN_BROWSER}
+     */
+    public URL getUrl() {
+        return url;
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/actionresponse/ActionResultResponseHandlingStrategy.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/actionresponse/ActionResultResponseHandlingStrategy.java
 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/actionresponse/ActionResultResponseHandlingStrategy.java
new file mode 100644
index 0000000..3bc6e65
--- /dev/null
+++ 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/actionresponse/ActionResultResponseHandlingStrategy.java
@@ -0,0 +1,139 @@
+/**
+ *  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.wicket.ui.actionresponse;
+
+import java.net.URL;
+
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.wicket.model.models.VoidModel;
+import org.apache.isis.viewer.wicket.ui.pages.voidreturn.VoidReturnPage;
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.behavior.AbstractAjaxBehavior;
+import org.apache.wicket.request.Url;
+import org.apache.wicket.request.cycle.RequestCycle;
+import org.apache.wicket.request.handler.resource.ResourceStreamRequestHandler;
+import org.apache.wicket.request.resource.ContentDisposition;
+import org.apache.wicket.util.resource.IResourceStream;
+import org.apache.wicket.util.time.Duration;
+
+public enum ActionResultResponseHandlingStrategy {
+    REDIRECT_TO_VOID {
+        @Override
+        public void handleResults(Component component, ActionResultResponse 
resultResponse) {
+            component.setResponsePage(new VoidReturnPage(new VoidModel()));
+        }
+    },
+    REDIRECT_TO_PAGE {
+        @Override
+        public void handleResults(final Component component, final 
ActionResultResponse resultResponse) {
+            // force any changes in state etc to happen now prior to the 
redirect;
+            // in the case of an object being returned, this should cause our 
page mementos 
+            // (eg EntityModel) to hold the correct state.  I hope.
+            IsisContext.getTransactionManager().flushTransaction();
+            
+            // "redirect-after-post"
+            component.setResponsePage(resultResponse.getToPage());
+        }
+    },
+    SCHEDULE_HANDLER {
+        @Override
+        public void handleResults(final Component component, final 
ActionResultResponse resultResponse) {
+            RequestCycle requestCycle = component.getRequestCycle();
+            AjaxRequestTarget target = 
requestCycle.find(AjaxRequestTarget.class);
+            if (target == null) {
+                // normal (non-Ajax) request => just stream the Lob to the 
browser
+                
requestCycle.scheduleRequestHandlerAfterCurrent(resultResponse.getHandler());
+            } else {
+                // Ajax request => respond with a redirect to be able to 
stream the Lob to the client
+                ResourceStreamRequestHandler scheduledHandler = 
(ResourceStreamRequestHandler) resultResponse.getHandler();
+                StreamAfterAjaxResponseBehavior streamingBehavior = new 
StreamAfterAjaxResponseBehavior(scheduledHandler);
+                component.getPage().add(streamingBehavior);
+                CharSequence callbackUrl = streamingBehavior.getCallbackUrl();
+                target.appendJavaScript("setTimeout(\"window.location.href='" 
+ callbackUrl + "'\", 10);");
+            }
+        }
+    },
+    OPEN_URL_IN_BROWSER {
+        @Override
+        public void handleResults(final Component component, final 
ActionResultResponse resultResponse) {
+            final AjaxRequestTarget target = resultResponse.getTarget();
+            final URL url = resultResponse.getUrl();
+            
+            RequestCycle requestCycle = component.getRequestCycle();
+
+            final String fullUrl = expanded(requestCycle, url);
+            
target.appendJavaScript("setTimeout(function(){Wicket.Event.publish(Isis.Topic.OPEN_IN_NEW_TAB,
 '" + fullUrl + "');}, 100);");
+        }
+
+    };
+
+    public abstract void handleResults(Component component, 
ActionResultResponse resultResponse);
+
+    /**
+     * @see #expanded(String)
+     */
+    public static String expanded(RequestCycle requestCycle, final URL url) {
+        String urlStr = expanded(url);
+        return requestCycle.getUrlRenderer().renderFullUrl(Url.parse(urlStr));
+    }
+
+    /**
+     * @see #expanded(String)
+     */
+    public static String expanded(final URL url) {
+        return expanded(url.toString());
+    }
+
+    /**
+     * very simple templating support, the idea being that 
"antiCache=${currentTimeMillis}"
+     * will be replaced automatically.
+     */
+    public static String expanded(String urlStr) {
+        if(urlStr.contains("antiCache=${currentTimeMillis}")) {
+            urlStr = urlStr.replace("antiCache=${currentTimeMillis}", 
"antiCache="+System.currentTimeMillis());
+        }
+        return urlStr;
+    }
+
+    /**
+     * A special Ajax behavior that is used to stream the contents of a Lob 
after
+     * an Ajax request.
+     */
+    private static class StreamAfterAjaxResponseBehavior extends 
AbstractAjaxBehavior {
+
+        private final String fileName;
+        private final IResourceStream resourceStream;
+        private final Duration cacheDuration;
+
+        public StreamAfterAjaxResponseBehavior(ResourceStreamRequestHandler 
scheduledHandler) {
+            this.fileName = scheduledHandler.getFileName();
+            this.resourceStream = scheduledHandler.getResourceStream();
+            this.cacheDuration = scheduledHandler.getCacheDuration();
+        }
+
+        @Override
+        public void onRequest() {
+            ResourceStreamRequestHandler handler = new 
ResourceStreamRequestHandler(resourceStream, fileName);
+            handler.setCacheDuration(cacheDuration);
+            handler.setContentDisposition(ContentDisposition.ATTACHMENT);
+            Component page = getComponent();
+            page.getRequestCycle().scheduleRequestHandlerAfterCurrent(handler);
+            page.remove(this);
+        }
+    }
+}

Reply via email to