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/ActionResultResponseType.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/actionresponse/ActionResultResponseType.java
 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/actionresponse/ActionResultResponseType.java
new file mode 100644
index 0000000..62291f8
--- /dev/null
+++ 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/actionresponse/ActionResultResponseType.java
@@ -0,0 +1,202 @@
+/**
+ *  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 java.util.Collection;
+import java.util.List;
+import com.google.common.collect.Lists;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.request.IRequestHandler;
+import org.apache.isis.applib.value.Blob;
+import org.apache.isis.applib.value.Clob;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.version.ConcurrencyException;
+import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.wicket.model.models.ActionModel;
+import org.apache.isis.viewer.wicket.model.models.EntityCollectionModel;
+import org.apache.isis.viewer.wicket.model.models.ValueModel;
+import org.apache.isis.viewer.wicket.model.models.VoidModel;
+import org.apache.isis.viewer.wicket.ui.pages.entity.EntityPage;
+import 
org.apache.isis.viewer.wicket.ui.pages.standalonecollection.StandaloneCollectionPage;
+import org.apache.isis.viewer.wicket.ui.pages.value.ValuePage;
+import org.apache.isis.viewer.wicket.ui.pages.voidreturn.VoidReturnPage;
+
+public enum ActionResultResponseType {
+    OBJECT {
+        @Override
+        public ActionResultResponse interpretResult(final ActionModel model, 
final AjaxRequestTarget target, final ObjectAdapter resultAdapter) {
+            final ObjectAdapter actualAdapter = 
determineActualAdapter(resultAdapter);
+            return toEntityPage(model, actualAdapter, null);
+        }
+
+        @Override
+        public ActionResultResponse interpretResult(final ActionModel model, 
ObjectAdapter targetAdapter, ConcurrencyException ex) {
+            return toEntityPage(model, targetAdapter, ex);
+        }
+    },
+    COLLECTION {
+        @Override
+        public ActionResultResponse interpretResult(final ActionModel 
actionModel, final AjaxRequestTarget target, final ObjectAdapter resultAdapter) 
{
+            final EntityCollectionModel collectionModel = 
EntityCollectionModel.createStandalone(resultAdapter);
+            // take a copy of the actionModel, because the original can get 
mutated (specifically: its arguments cleared)
+            final ActionModel actionModelCopy = actionModel.copy();
+            collectionModel.setActionHint(actionModelCopy);
+            return ActionResultResponse.toPage(new 
StandaloneCollectionPage(collectionModel));
+        }
+    },
+    VALUE {
+        @Override
+        public ActionResultResponse interpretResult(final ActionModel model, 
final AjaxRequestTarget target, final ObjectAdapter resultAdapter) {
+            ValueModel valueModel = new ValueModel(resultAdapter);
+            valueModel.setActionHint(model);
+            final ValuePage valuePage = new ValuePage(valueModel);
+            return ActionResultResponse.toPage(valuePage);
+        }
+    },
+    VALUE_CLOB {
+        @Override
+        public ActionResultResponse interpretResult(final ActionModel model, 
final AjaxRequestTarget target, final ObjectAdapter resultAdapter) {
+            final Object value = resultAdapter.getObject();
+            IRequestHandler handler = ActionModel.downloadHandler(value);
+            return ActionResultResponse.withHandler(handler);
+        }
+    },
+    VALUE_BLOB {
+        @Override
+        public ActionResultResponse interpretResult(final ActionModel model, 
final AjaxRequestTarget target, final ObjectAdapter resultAdapter) {
+            final Object value = resultAdapter.getObject();
+            IRequestHandler handler = ActionModel.downloadHandler(value);
+            return ActionResultResponse.withHandler(handler);
+        }
+    },
+    VALUE_URL_AJAX {
+        @Override
+        public ActionResultResponse interpretResult(final ActionModel model, 
final AjaxRequestTarget target, final ObjectAdapter resultAdapter) {
+            final URL url = (URL)resultAdapter.getObject();
+            return ActionResultResponse.openUrlInBrowser(target, url);
+        }
+
+    },
+    VALUE_URL_NOAJAX {
+        @Override
+        public ActionResultResponse interpretResult(final ActionModel model, 
final AjaxRequestTarget target, final ObjectAdapter resultAdapter) {
+            // open URL server-side redirect
+            final Object value = resultAdapter.getObject();
+            IRequestHandler handler = ActionModel.redirectHandler(value);
+            return ActionResultResponse.withHandler(handler);
+        }
+        
+    },
+    VOID {
+        @Override
+        public ActionResultResponse interpretResult(final ActionModel model, 
final AjaxRequestTarget target, final ObjectAdapter resultAdapter) {
+            final VoidModel voidModel = new VoidModel();
+            voidModel.setActionHint(model);
+            return ActionResultResponse.toPage(new VoidReturnPage(voidModel));
+        }
+    };
+
+    public abstract ActionResultResponse interpretResult(ActionModel model, 
final AjaxRequestTarget target, ObjectAdapter resultAdapter);
+
+    /**
+     * Only overridden for {@link ActionResultResponseType#OBJECT object}
+     */
+    public ActionResultResponse interpretResult(ActionModel model, 
ObjectAdapter targetAdapter, ConcurrencyException ex) {
+        throw new UnsupportedOperationException("Cannot render concurrency 
exception for any result type other than OBJECT");
+    }
+
+    private static ObjectAdapter determineActualAdapter(final ObjectAdapter 
resultAdapter) {
+        if (resultAdapter.getSpecification().isNotCollection()) {
+            return resultAdapter;
+        } else {
+            // will only be a single element
+            final List<Object> pojoList = asList(resultAdapter);
+            final Object pojo = pojoList.get(0);
+            return adapterFor(pojo);
+        }
+    }
+    private static ObjectAdapter adapterFor(final Object pojo) {
+        return 
IsisContext.getPersistenceSession().getAdapterManager().adapterFor(pojo);
+    }
+
+    private static ActionResultResponse toEntityPage(final ActionModel model, 
final ObjectAdapter actualAdapter, ConcurrencyException exIfAny) {
+        // this will not preserve the URL (because pageParameters are not 
copied over)
+        // but trying to preserve them seems to cause the 302 redirect to be 
swallowed somehow
+        final EntityPage entityPage = new EntityPage(actualAdapter, exIfAny);
+        return ActionResultResponse.toPage(entityPage);
+    }
+
+
+    // //////////////////////////////////////
+
+    public static ActionResultResponse determineAndInterpretResult(
+            final ActionModel model, 
+            final AjaxRequestTarget target, 
+            final ObjectAdapter resultAdapter) {
+        ActionResultResponseType arrt = determineFor(resultAdapter, target);
+        return arrt.interpretResult(model, target, resultAdapter);
+    }
+
+    private static ActionResultResponseType determineFor(
+            final ObjectAdapter resultAdapter, 
+            final AjaxRequestTarget target) {
+        if(resultAdapter == null) {
+            return ActionResultResponseType.VOID;
+        }
+        final ObjectSpecification resultSpec = 
resultAdapter.getSpecification();
+        if (resultSpec.isNotCollection()) {
+            if (resultSpec.getFacet(ValueFacet.class) != null) {
+                
+                final Object value = resultAdapter.getObject();
+                if(value instanceof Clob) {
+                    return ActionResultResponseType.VALUE_CLOB;
+                } 
+                if(value instanceof Blob) {
+                    return ActionResultResponseType.VALUE_BLOB;
+                } 
+                if(value instanceof java.net.URL) {
+                    return target != null? 
ActionResultResponseType.VALUE_URL_AJAX: 
ActionResultResponseType.VALUE_URL_NOAJAX;
+                } 
+                // else
+                return ActionResultResponseType.VALUE;
+            } else {
+                return ActionResultResponseType.OBJECT;
+            }
+        } else {
+            final List<Object> pojoList = asList(resultAdapter);
+            switch (pojoList.size()) {
+            case 1:
+                return ActionResultResponseType.OBJECT;
+            default:
+                return ActionResultResponseType.COLLECTION;
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private static List<Object> asList(final ObjectAdapter resultAdapter) {
+        final Collection<Object> coll = (Collection<Object>) 
resultAdapter.getObject();
+        return coll instanceof List
+                ? (List<Object>)coll
+                : Lists.<Object>newArrayList(coll);
+    }
+
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/app/registry/ComponentFactoryRegistrar.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/app/registry/ComponentFactoryRegistrar.java
 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/app/registry/ComponentFactoryRegistrar.java
new file mode 100644
index 0000000..5952f0c
--- /dev/null
+++ 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/app/registry/ComponentFactoryRegistrar.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.wicket.ui.app.registry;
+
+import java.util.Iterator;
+import java.util.List;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Lists;
+
+import org.apache.isis.viewer.wicket.ui.ComponentFactory;
+import org.apache.isis.viewer.wicket.ui.ComponentType;
+
+/**
+ * Defines an API for registering {@link ComponentFactory}s.
+ * 
+ * <p>
+ * As used by {@link ComponentFactoryListDefault}.
+ */
+public interface ComponentFactoryRegistrar {
+    
+    public static class ComponentFactoryList implements 
Iterable<ComponentFactory> {
+        private final List<ComponentFactory> componentFactories = 
Lists.newArrayList();
+
+        public void add(ComponentFactory componentFactory) {
+            componentFactories.add(componentFactory);
+        }
+
+        public void replace(final ComponentFactory 
replacementComponentFactory) {
+            
removeExisting(matching(replacementComponentFactory.getComponentType()));
+            add(replacementComponentFactory);
+        }
+
+        public void replace(final Class<? extends ComponentFactory> toReplace, 
final ComponentFactory replacementComponentFactory) {
+            int indexOfOldFactory = removeExisting(matching(toReplace));
+            insert(indexOfOldFactory, replacementComponentFactory);
+        }
+
+        private void insert(final int indexToInsertInto, final 
ComponentFactory replacementComponentFactory) {
+            if (indexToInsertInto > -1 && indexToInsertInto < 
componentFactories.size()) {
+                componentFactories.add(indexToInsertInto, 
replacementComponentFactory);
+            } else {
+                componentFactories.add(replacementComponentFactory);
+            }
+        }
+
+        private int removeExisting(final Predicate<ComponentFactory> 
predicate) {
+            int indexOfFirst = -1;
+            for (int i = 0; i < componentFactories.size(); i++) {
+                ComponentFactory factory = componentFactories.get(i);
+                if (predicate.apply(factory)) {
+                    componentFactories.remove(i);
+                    if (indexOfFirst == -1) {
+                        indexOfFirst = i;
+                    }
+                    i--;
+                }
+            }
+
+            return indexOfFirst;
+        }
+
+        private static Predicate<ComponentFactory> matching(final 
ComponentType componentType) {
+            return new Predicate<ComponentFactory>() {
+                @Override
+                public boolean apply(ComponentFactory input) {
+                    return input.getComponentType() == componentType;
+                }
+            };
+        }
+
+        private static Predicate<ComponentFactory> matching(final Class<? 
extends ComponentFactory> toReplace) {
+            return new Predicate<ComponentFactory>() {
+                @Override
+                public boolean apply(ComponentFactory input) {
+                    return toReplace.isAssignableFrom(input.getClass());
+                }
+            };
+        }
+
+        @Override
+        public Iterator<ComponentFactory> iterator() {
+            return componentFactories.iterator();
+        }
+    }
+
+    void addComponentFactories(ComponentFactoryList componentFactoryList);
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/app/registry/ComponentFactoryRegistry.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/app/registry/ComponentFactoryRegistry.java
 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/app/registry/ComponentFactoryRegistry.java
new file mode 100644
index 0000000..f037378
--- /dev/null
+++ 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/app/registry/ComponentFactoryRegistry.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.wicket.ui.app.registry;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.MarkupContainer;
+import org.apache.wicket.model.IModel;
+
+import org.apache.isis.viewer.wicket.ui.ComponentFactory;
+import org.apache.isis.viewer.wicket.ui.ComponentType;
+
+/**
+ * API for finding registered {@link ComponentFactory}s.
+ * 
+ * <p>
+ * Ultimately all requests to locate {@link ComponentFactory}s are routed
+ * through to an object implementing this interface.
+ */
+public interface ComponentFactoryRegistry {
+
+    List<ComponentFactory> findComponentFactories(ComponentType componentType, 
IModel<?> model);
+
+    /**
+     * Finds the "best" {@link ComponentFactory} for the viewId.
+     */
+    ComponentFactory findComponentFactory(ComponentType componentType, 
IModel<?> model);
+
+    /**
+     * As per
+     * {@link #addOrReplaceComponent(MarkupContainer, ComponentType, IModel)},
+     * but with the wicket id derived from the {@link ComponentType}.
+     */
+    Component addOrReplaceComponent(MarkupContainer markupContainer, 
ComponentType componentType, IModel<?> model);
+
+    /**
+     * {@link #createComponent(ComponentType, String, IModel) Creates} the
+     * relevant {@link Component} for the provided arguments, and adds to the
+     * provided {@link MarkupContainer}; the wicket id is as specified.
+     * 
+     * <p>
+     * If none can be found, will fail fast.
+     */
+    Component addOrReplaceComponent(MarkupContainer markupContainer, String 
id, ComponentType componentType, IModel<?> model);
+
+    /**
+     * As per {@link #createComponent(ComponentType, String, IModel)}, but with
+     * the wicket id derived from the {@link ComponentType}.
+     * 
+     * @see #createComponent(ComponentType, String, IModel)
+     */
+    Component createComponent(ComponentType componentType, IModel<?> model);
+
+    /**
+     * Create the {@link Component} matching the specified {@link 
ComponentType}
+     * and {@link IModel} to the provided {@link MarkupContainer}; the id is
+     * specified explicitly.
+     * 
+     * <p>
+     * If none can be found, will fail fast.
+     */
+    Component createComponent(ComponentType componentType, String id, 
IModel<?> model);
+
+    ComponentFactory findComponentFactoryElseFailFast(ComponentType 
componentType, IModel<?> model);
+
+    Collection<ComponentFactory> listComponentFactories();
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/app/registry/ComponentFactoryRegistryAccessor.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/app/registry/ComponentFactoryRegistryAccessor.java
 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/app/registry/ComponentFactoryRegistryAccessor.java
new file mode 100644
index 0000000..b433bf4
--- /dev/null
+++ 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/app/registry/ComponentFactoryRegistryAccessor.java
@@ -0,0 +1,31 @@
+/*
+ *  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.app.registry;
+
+import java.io.Serializable;
+
+/**
+ * For obtaining the {@link ComponentFactoryRegistry}.
+ */
+public interface ComponentFactoryRegistryAccessor extends Serializable {
+
+    ComponentFactoryRegistry getComponentFactoryRegistry();
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/AboutPanel.html
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/AboutPanel.html
 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/AboutPanel.html
new file mode 100644
index 0000000..c85780d
--- /dev/null
+++ 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/AboutPanel.html
@@ -0,0 +1,26 @@
+<?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.
+-->
+<html xmlns:wicket="http://wicket.apache.org";>
+<wicket:panel>
+    <div class="aboutPanel aboutComponentType">
+        <div wicket:id="manifestAttributes"></div>
+    </div>
+</wicket:panel>
+</html>

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/AboutPanel.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/AboutPanel.java
 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/AboutPanel.java
new file mode 100644
index 0000000..68f16fa
--- /dev/null
+++ 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/AboutPanel.java
@@ -0,0 +1,69 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.viewer.wicket.ui.components.about;
+
+import java.io.InputStream;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+
+import org.apache.isis.viewer.wicket.model.models.AboutModel;
+import org.apache.isis.viewer.wicket.ui.pages.home.HomePage;
+import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
+
+/**
+ * {@link PanelAbstract Panel} displaying welcome message (as used on
+ * {@link HomePage}).
+ */
+public class AboutPanel extends PanelAbstract<AboutModel> {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final String ID_MANIFEST_ATTRIBUTES = "manifestAttributes";
+
+    @Inject
+    @Named("aboutMessage")
+    private String aboutMessage;
+    
+    /**
+     * We take care to read this only once.
+     *
+     * <p>
+     *     Is <code>transient</code> because
+     * </p>
+     */
+    @Inject
+    @Named("metaInfManifest")
+    private transient InputStream metaInfManifestIs;
+    
+    private JarManifestModel jarManifestModel;
+    
+    public AboutPanel(final String id) {
+        super(id);
+        
+        if(jarManifestModel == null) {
+            jarManifestModel = new JarManifestModel(aboutMessage, 
metaInfManifestIs);
+        }
+        
+        add(new JarManifestPanel(ID_MANIFEST_ATTRIBUTES, jarManifestModel));
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/AboutPanelFactory.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/AboutPanelFactory.java
 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/AboutPanelFactory.java
new file mode 100644
index 0000000..3439855
--- /dev/null
+++ 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/AboutPanelFactory.java
@@ -0,0 +1,50 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.viewer.wicket.ui.components.about;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.model.IModel;
+import org.apache.isis.viewer.wicket.ui.ComponentFactory;
+import org.apache.isis.viewer.wicket.ui.ComponentFactoryAbstract;
+import org.apache.isis.viewer.wicket.ui.ComponentType;
+
+/**
+ * {@link ComponentFactory} for {@link AboutPanel}.
+ */
+public class AboutPanelFactory extends ComponentFactoryAbstract {
+
+    private static final long serialVersionUID = 1L;
+
+    public AboutPanelFactory() {
+        super(ComponentType.ABOUT, AboutPanel.class);
+    }
+
+    @Override
+    public ApplicationAdvice appliesTo(final IModel<?> model) {
+        return ApplicationAdvice.APPLIES;
+    }
+
+    @Override
+    public Component createComponent(final String id, final IModel<?> model) {
+        return new AboutPanel(id);
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/JarManifestAttributes.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/JarManifestAttributes.java
 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/JarManifestAttributes.java
new file mode 100644
index 0000000..fac290c
--- /dev/null
+++ 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/JarManifestAttributes.java
@@ -0,0 +1,68 @@
+/*
+ *  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.components.about;
+
+import java.io.Serializable;
+import java.net.URL;
+import java.util.Map.Entry;
+
+public class JarManifestAttributes implements Serializable {
+    
+    private static final long serialVersionUID = 1L;
+
+    public static JarManifestAttributes jarName(String jarName) {
+        return new JarManifestAttributes(JarManifestAttributes.Type.JAR_NAME, 
jarName);
+    }
+
+    public static JarManifestAttributes jarUrl(URL jarUrl) {
+        return new JarManifestAttributes(JarManifestAttributes.Type.JAR_URL, 
jarUrl != null? jarUrl.toExternalForm(): "");
+    }
+
+    public static JarManifestAttributes attribute(Entry<Object,Object> entry) {
+        StringBuilder buf = new StringBuilder();
+        buf .append("    ")
+            .append(entry.getKey())
+            .append(": ")
+            .append(entry.getValue())
+            .append("\n")
+            ;
+        return new 
JarManifestAttributes(JarManifestAttributes.Type.MANIFEST_ATTRIBUTE, 
buf.toString());
+    }
+
+    enum Type {
+        JAR_NAME,
+        JAR_URL,
+        MANIFEST_ATTRIBUTE
+    }
+    
+    private final Type type;
+    private final String line;
+    
+    public JarManifestAttributes(Type type, String line) {
+        this.type = type;
+        this.line = line;
+    }
+    public JarManifestAttributes.Type getType() {
+        return type;
+    }
+    public String getLine() {
+        return line;
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/JarManifestListView.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/JarManifestListView.java
 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/JarManifestListView.java
new file mode 100644
index 0000000..1565ac9
--- /dev/null
+++ 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/JarManifestListView.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.wicket.ui.components.about;
+
+import java.util.List;
+
+import org.apache.wicket.behavior.AttributeAppender;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+
+public final class JarManifestListView extends ListView<JarManifestAttributes> 
{
+    
+    private static final long serialVersionUID = 1L;
+    private final String idLine;
+
+    public JarManifestListView(String id, String idLine, List<? extends 
JarManifestAttributes> list) {
+        super(id, list);
+        this.idLine = idLine;
+    }
+
+    @Override
+    protected void populateItem(ListItem<JarManifestAttributes> item) {
+        final JarManifestAttributes detail = item.getModelObject();
+        Label label = new Label(idLine, detail.getLine());
+        item.add(new AttributeAppender("class", 
detail.getType().name().toLowerCase()));
+        item.add(label);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/JarManifestModel.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/JarManifestModel.java
 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/JarManifestModel.java
new file mode 100644
index 0000000..d78a290
--- /dev/null
+++ 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/JarManifestModel.java
@@ -0,0 +1,233 @@
+/*
+ *  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.components.about;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+import com.google.common.base.CharMatcher;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Lists;
+
+import org.apache.isis.core.commons.lang.CloseableExtensions;
+import org.apache.isis.viewer.wicket.model.models.ModelAbstract;
+
+public class JarManifestModel extends ModelAbstract<JarManifestModel> {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final List<String> VERSION_KEY_CANDIDATES = 
Arrays.asList("Implementation-Version", "Build-Time");
+    
+    private String aboutMessage;
+
+    private final List<JarManifestAttributes> manifests = Lists.newArrayList();
+
+    /**
+     * @param aboutMessage
+     * @param metaInfManifestIs provide using 
<tt>getServletContext().getResourceAsStream("/META-INF/MANIFEST.MF")</tt>
+     */
+    public JarManifestModel(String aboutMessage, InputStream 
metaInfManifestIs) {
+
+        this.aboutMessage = aboutMessage;
+        
+        Manifest manifest;
+        try {
+            manifest = new Manifest(metaInfManifestIs);
+            manifests.add(JarManifestAttributes.jarName("Web archive (war 
file)"));
+            manifests.add(JarManifestAttributes.jarUrl(null));
+            addAttributes(manifest, manifests);
+            
+            // append the version if able to guess
+            String versionIfAny = guessVersion(manifest); 
+            this.aboutMessage = this.aboutMessage + (versionIfAny != null? 
"\n\n" + versionIfAny: "");
+            
+        } catch (Exception ex) {
+            // ignore
+        } finally {
+            CloseableExtensions.closeSafely(metaInfManifestIs);
+        }
+        
+        Enumeration<?> resEnum;
+        try {
+            resEnum = 
Thread.currentThread().getContextClassLoader().getResources(JarFile.MANIFEST_NAME);
+        } catch (IOException e) {
+            return;
+        }
+        final List<JarManifest> jarManifests = Lists.newArrayList(); 
+        while (resEnum.hasMoreElements()) {
+            URL url = (URL)resEnum.nextElement();
+            JarManifest jarManifest = new JarManifest(url);
+            jarManifests.add(jarManifest);
+
+            InputStream is = null;
+            try {
+                is = url.openStream();
+                if (is != null) {
+                    manifest = new Manifest(is);
+                    jarManifest.addAttributesFrom(manifest);
+                }
+            } catch(Exception e3) {
+                // ignore
+            } finally {
+                CloseableExtensions.closeSafely(is);
+            }
+        }
+        
+        Collections.sort(jarManifests);
+        
+        for (JarManifest jarManifest : jarManifests) {
+            jarManifest.addAttributesTo(manifests);
+        }
+    }
+
+    private static class JarManifest implements Comparable<JarManifest> {
+        private final List<JarManifestAttributes> attributes = 
Lists.newArrayList();
+
+        private final URL url;
+
+        private JarName jarName;
+        
+        public JarManifest(URL url) {
+            this.url = url;
+            jarName = asJarName(url);
+        }
+
+        void addAttributesFrom(Manifest manifest) {
+            addAttributes(manifest, attributes);
+        }
+
+        void addAttributesTo(List<JarManifestAttributes> manifests) {
+            manifests.add(JarManifestAttributes.jarName(jarName.name));
+            manifests.add(JarManifestAttributes.jarUrl(url));
+            manifests.addAll(attributes);
+        }
+
+        @Override
+        public int compareTo(JarManifest o) {
+            return jarName.compareTo(o.jarName);
+        }
+    }
+    
+    static class JarName implements Comparable<JarName>{
+        enum Type {
+            CLASSES, JAR, OTHER
+        }
+        Type type;
+        String name;
+        JarName(Type type, String name) {
+            this.type = type;
+            this.name = name;
+        }
+        @Override
+        public int compareTo(JarName o) {
+            int x = type.compareTo(o.type);
+            if(x != 0) return x;
+            return name.compareTo(o.name);
+        }
+    }
+    
+    private static JarName asJarName(URL url) {
+        final String path = url.getPath();
+        // strip off the meta-inf
+        String strippedPath = stripSuffix(path, "/META-INF/MANIFEST.MF");
+        strippedPath = stripSuffix(strippedPath, "!");
+        
+        // split the path into parts, and reverse
+        List<String> parts = 
Lists.newArrayList(Splitter.on(CharMatcher.anyOf("/\\")).split(strippedPath));
+        Collections.reverse(parts);
+        
+        // searching from the end, return the jar name if possible
+        for (String part : parts) {
+            if(part.endsWith(".jar")) {
+                return new JarName(JarName.Type.JAR, part);
+            }
+        }
+        
+        // see if running in an IDE, under target*/classes; return the part 
prior to that. 
+        if(parts.size()>=3) {
+            if(parts.get(0).equals("classes") && 
parts.get(1).startsWith("target")) {
+                return new JarName(JarName.Type.CLASSES, parts.get(2));
+            }
+        }
+        
+        // otherwise, return the stripped path 
+        return new JarName(JarName.Type.OTHER, strippedPath);
+    }
+
+    public static String stripSuffix(String path, String suffix) {
+        int indexOf = path.indexOf(suffix);
+        if(indexOf != -1) {
+            path = path.substring(0, indexOf);
+        }
+        return path;
+    }
+
+    static void addAttributes(Manifest manifest, List<JarManifestAttributes> 
attributes) {
+        final Attributes mainAttribs = manifest.getMainAttributes();
+        Set<Entry<Object, Object>> entrySet = mainAttribs.entrySet();
+        for (Entry<Object, Object> entry : entrySet) {
+            JarManifestAttributes attribute = 
JarManifestAttributes.attribute(entry);
+            attributes.add(attribute);
+        }
+    }
+
+
+    private static String guessVersion(Manifest manifest) {
+        final Attributes mainAttribs = manifest.getMainAttributes();
+        Set<Entry<Object, Object>> entrySet = mainAttribs.entrySet();
+        for (String candidate : VERSION_KEY_CANDIDATES) {
+            for (Entry<Object, Object> entry : entrySet) {
+                if(candidate.equals(entry.getKey().toString())) {
+                    return entry.getValue().toString();
+                }
+            }
+        }
+        return null;
+    }
+
+
+    @Override
+    protected JarManifestModel load() {
+        return this;
+    }
+
+    @Override
+    public void setObject(JarManifestModel ex) {
+        // no-op
+    }
+
+    public String getAboutMessage() {
+        return aboutMessage;
+    }
+
+    public List<JarManifestAttributes> getDetail() {
+        return manifests;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/JarManifestPanel.css
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/JarManifestPanel.css
 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/JarManifestPanel.css
new file mode 100644
index 0000000..2f05abd
--- /dev/null
+++ 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/JarManifestPanel.css
@@ -0,0 +1,91 @@
+/*
+ *  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.
+ */
+
+ .jarManifestPanel .aboutInfo {
+    margin-left: 50px;
+    margin-right: 50px;
+    padding-top: 50px;
+}
+
+
+.jarManifestPanel .aboutMessage {
+    background:#FFFFFF;
+    border-radius:4px;
+    -moz-border-radius:4px;
+    -webkit-border-radius:4px;
+    padding: 15px;
+    display: block;
+    text-align:center;
+    font-size:1.2em;
+}
+
+ .jarManifestPanel .manifestAttributes {
+    margin-top: 30px; 
+}
+
+.jarManifestPanel .heading {
+    display:block;
+    font-style:normal !important;
+
+    padding:1px 6px 1px 6px;
+}
+
+.jarManifestPanel .heading span {
+    display:block;
+    font-style:normal !important;
+    padding:3px 3px 3px 3px;
+    font-size: 0.8em;
+    font-weight:bold;
+}
+
+.jarManifestPanel .heading:hover {
+    background-color:#FFFFFF;
+    cursor: pointer;
+}
+
+.jarManifestPanel h3 {
+    font-size: larger;
+}
+
+.jarManifestPanel .manifestAttributesList .caused_by_label {
+    margin-top: 30px;
+    font-style:normal !important;
+    font-size: 0.8em;
+    font-weight:bold;
+    color: #46423C;
+}
+
+.jarManifestPanel .manifestAttributesList .jar_name {
+    margin-top: 15px;
+    font-size: 1.2em;
+    font-weight:bold;
+    color: #46423C;
+}
+
+.jarManifestPanel .manifestAttributesList .jar_url {
+    margin-top: 10px;
+    margin-bottom: 10px;
+    font-style: italic;
+    font-size: 1.0em;
+    color: #00477F;
+}
+
+.jarManifestPanel .manifestAttributesList .manifest_attribute{
+    margin-left: 30px;
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/JarManifestPanel.html
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/JarManifestPanel.html
 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/JarManifestPanel.html
new file mode 100644
index 0000000..340922a
--- /dev/null
+++ 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/JarManifestPanel.html
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html>
+<!--
+  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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml";  
+      
xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd";  
+      xml:lang="en"  
+      lang="en">
+    <body>
+        <wicket:panel>
+            <div class="jarManifestPanel">
+                <div class="aboutInfo clear">
+                    <h2 wicket:id="aboutMessage" class="aboutMessage">[about 
message text]</h2>
+                    <div class="manifestAttributes" 
wicket:id="manifestAttributes">
+                        <h4 class="heading well">Jar manifest attributes</h4>
+                        <div class="content">
+                            <div class="manifestAttributesList">
+                                <ul>
+                                    <li wicket:id="manifestAttribute">
+                                        <span 
wicket:id="manifestAttributeLine">[manifest attribute line]</span>
+                                    </li>
+                                </ul>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </wicket:panel>
+    </body>
+</html>

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/JarManifestPanel.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/JarManifestPanel.java
 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/JarManifestPanel.java
new file mode 100644
index 0000000..8a76487
--- /dev/null
+++ 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/JarManifestPanel.java
@@ -0,0 +1,68 @@
+/*
+ *  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.components.about;
+
+import org.apache.wicket.MarkupContainer;
+import org.apache.wicket.markup.head.IHeaderResponse;
+import org.apache.wicket.markup.head.JavaScriptReferenceHeaderItem;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.request.resource.JavaScriptResourceReference;
+import org.apache.isis.viewer.wicket.ui.panels.PanelUtil;
+
+public class JarManifestPanel extends Panel {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final String ID_ABOUT_MESSAGE = "aboutMessage";
+
+    private static final String ID_MANIFEST_ATTRIBUTES = "manifestAttributes";
+
+    private static final String ID_MANIFEST_ATTRIBUTE = "manifestAttribute";
+    private static final String ID_LINE = "manifestAttributeLine";
+
+    private static final JavaScriptResourceReference DIV_TOGGLE_JS = new 
JavaScriptResourceReference(JarManifestPanel.class, "div-toggle.js");
+
+    public JarManifestPanel(String id, JarManifestModel manifestModel) {
+        super(id, manifestModel);
+
+        final String aboutMessage = manifestModel.getAboutMessage();
+        final Label label = new Label(ID_ABOUT_MESSAGE, aboutMessage);
+        // safe to not escape, about message is read from file (part of 
deployed WAR)
+        label.setEscapeModelStrings(false);
+        add(label);
+
+        MarkupContainer container = new 
WebMarkupContainer(ID_MANIFEST_ATTRIBUTES) {
+            private static final long serialVersionUID = 1L;
+            @Override
+            public void renderHead(IHeaderResponse response) {
+                
response.render(JavaScriptReferenceHeaderItem.forReference(DIV_TOGGLE_JS));
+            }
+        };
+        container.add(new JarManifestListView(ID_MANIFEST_ATTRIBUTE, 
JarManifestPanel.ID_LINE, manifestModel.getDetail()));
+        add(container);
+    }
+
+    public void renderHead(final IHeaderResponse response) {
+        PanelUtil.renderHead(response, this.getClass());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/div-toggle.js
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/div-toggle.js
 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/div-toggle.js
new file mode 100644
index 0000000..d51175a
--- /dev/null
+++ 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/about/div-toggle.js
@@ -0,0 +1,25 @@
+/*
+ *  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.
+ */
+jQuery(document).ready(function() {
+  jQuery(".jarManifestPanel .content").hide();
+  jQuery(".jarManifestPanel .heading").click(function()
+  {
+    jQuery(this).next(".jarManifestPanel .content").slideToggle(500);
+  });
+});

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionlink/ActionLinkPanel.html
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionlink/ActionLinkPanel.html
 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionlink/ActionLinkPanel.html
new file mode 100644
index 0000000..e239527
--- /dev/null
+++ 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionlink/ActionLinkPanel.html
@@ -0,0 +1,31 @@
+<?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.
+-->
+<html xmlns:wicket="http://wicket.apache.org";>
+       <body>
+               <wicket:panel>
+                    <span wicket:id="actionLinkWrapper" class="actionLinkPanel 
actionLinkComponentType">
+                               <a href="#" wicket:id="actionLink">
+                                       <span wicket:id="actionTitle" 
class="actionTitle">[action title]</span>
+                               </a>
+                       </span>
+               </wicket:panel>
+       </body>
+</html>
+

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionlink/ActionLinkPanel.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionlink/ActionLinkPanel.java
 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionlink/ActionLinkPanel.java
new file mode 100644
index 0000000..0b81418
--- /dev/null
+++ 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionlink/ActionLinkPanel.java
@@ -0,0 +1,101 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.viewer.wicket.ui.components.actionlink;
+
+import org.apache.wicket.Page;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.link.AbstractLink;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+
+import org.apache.isis.viewer.wicket.model.models.ActionModel;
+import org.apache.isis.viewer.wicket.model.models.EntityModel;
+import org.apache.isis.viewer.wicket.model.models.PageType;
+import org.apache.isis.viewer.wicket.ui.pages.PageClassRegistry;
+import org.apache.isis.viewer.wicket.ui.pages.PageClassRegistryAccessor;
+import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
+import org.apache.isis.viewer.wicket.ui.util.Links;
+
+/**
+ * {@link PanelAbstract Panel} representing the icon and title of an entity,
+ * as per the provided {@link EntityModel}.
+ */
+public class ActionLinkPanel extends PanelAbstract<ActionModel> {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final String ID_ACTION_LINK_WRAPPER = "actionLinkWrapper";
+    private static final String ID_ACTION_LINK = "actionLink";
+    private static final String ID_ACTION_TITLE = "actionTitle";
+
+    private Label label;
+
+    public ActionLinkPanel(final String id, final ActionModel actionModel) {
+        super(id, actionModel);
+    }
+
+    @Override
+    protected void onBeforeRender() {
+        buildGui();
+        super.onBeforeRender();
+    }
+
+    private void buildGui() {
+        addOrReplaceLinkWrapper();
+    }
+
+    private void addOrReplaceLinkWrapper() {
+        final WebMarkupContainer entityLinkWrapper = 
addOrReplaceLinkWrapper(getModel());
+        addOrReplace(entityLinkWrapper);
+    }
+
+    private WebMarkupContainer addOrReplaceLinkWrapper(final ActionModel 
actionModel) {
+
+        final PageParameters pageParameters = actionModel.getPageParameters();
+        final Class<? extends Page> pageClass = 
getPageClassRegistry().getPageClass(PageType.ACTION_PROMPT);
+        final AbstractLink link = newLink(ID_ACTION_LINK, pageClass, 
pageParameters);
+        
+        label = new Label(ID_ACTION_TITLE, determineTitle());
+        link.add(label);
+
+        final WebMarkupContainer actionLinkWrapper = new 
WebMarkupContainer(ID_ACTION_LINK_WRAPPER);
+        actionLinkWrapper.addOrReplace(link);
+        return actionLinkWrapper;
+    }
+
+    private String determineTitle() {
+        return getModel().getActionMemento().getAction().getId();
+    }
+
+    private AbstractLink newLink(final String linkId, final Class<? extends 
Page> pageClass, final PageParameters pageParameters) {
+        return Links.newBookmarkablePageLink(linkId, pageParameters, 
pageClass);
+    }
+
+    
+    // ///////////////////////////////////////////////////////////////////
+    // Convenience
+    // ///////////////////////////////////////////////////////////////////
+
+    protected PageClassRegistry getPageClassRegistry() {
+        final PageClassRegistryAccessor pcra = (PageClassRegistryAccessor) 
getApplication();
+        return pcra.getPageClassRegistry();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionlink/ActionLinkPanelFactory.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionlink/ActionLinkPanelFactory.java
 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionlink/ActionLinkPanelFactory.java
new file mode 100644
index 0000000..29229e8
--- /dev/null
+++ 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionlink/ActionLinkPanelFactory.java
@@ -0,0 +1,60 @@
+/*
+ *  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.components.actionlink;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.request.resource.CssResourceReference;
+
+import org.apache.isis.applib.annotation.ActionSemantics;
+import org.apache.isis.viewer.wicket.model.models.ActionModel;
+import org.apache.isis.viewer.wicket.ui.ComponentFactory;
+import org.apache.isis.viewer.wicket.ui.ComponentFactoryAbstract;
+import org.apache.isis.viewer.wicket.ui.ComponentType;
+
+/**
+ * {@link ComponentFactory} for {@link ActionLinkPanel}.
+ */
+public class ActionLinkPanelFactory extends ComponentFactoryAbstract {
+
+    private static final long serialVersionUID = 1L;
+
+    public ActionLinkPanelFactory() {
+        super(ComponentType.ACTION_LINK, ActionLinkPanel.class);
+    }
+
+    @Override
+    protected ApplicationAdvice appliesTo(IModel<?> model) {
+        if(!(model instanceof ActionModel)) {
+            return ApplicationAdvice.DOES_NOT_APPLY;
+        }
+        final ActionModel actionModel = (ActionModel) model;
+        final ActionSemantics.Of semantics = 
actionModel.getActionMemento().getAction().getSemantics();
+        return ApplicationAdvice.appliesIf(semantics == 
ActionSemantics.Of.SAFE);
+    }
+
+    @Override
+    public Component createComponent(final String id, final IModel<?> model) {
+        final ActionModel actionModel = (ActionModel) model;
+        return new ActionLinkPanel(id, actionModel);
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/CssClassFaBehavior.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/CssClassFaBehavior.java
 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/CssClassFaBehavior.java
new file mode 100644
index 0000000..b1c2a77
--- /dev/null
+++ 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/CssClassFaBehavior.java
@@ -0,0 +1,36 @@
+package org.apache.isis.viewer.wicket.ui.components.actionmenu;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.behavior.Behavior;
+import org.apache.isis.applib.annotation.ActionLayout;
+
+/**
+ * A behavior that prepends or appends the markup needed to show a Font 
Awesome icon
+ * for a LinkAndLabel
+ */
+public class CssClassFaBehavior extends Behavior {
+
+    private final String cssClassFa;
+    private final ActionLayout.CssClassFaPosition position;
+
+    public CssClassFaBehavior(final String cssClassFa, final 
ActionLayout.CssClassFaPosition position) {
+        this.cssClassFa = cssClassFa;
+        this.position = position;
+    }
+
+    @Override
+    public void beforeRender(final Component component) {
+        super.beforeRender(component);
+        if (position == null || ActionLayout.CssClassFaPosition.LEFT == 
position) {
+            component.getResponse().write("<span class=\""+cssClassFa+" 
fontAwesomeIcon\"></span>");
+        }
+    }
+
+    @Override
+    public void afterRender(final Component component) {
+        if (ActionLayout.CssClassFaPosition.RIGHT == position) {
+            component.getResponse().write("<span class=\""+cssClassFa+" 
fontAwesomeIcon\"></span>");
+        }
+        super.afterRender(component);
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsDropDownPanel.html
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsDropDownPanel.html
 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsDropDownPanel.html
new file mode 100644
index 0000000..a240cce
--- /dev/null
+++ 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsDropDownPanel.html
@@ -0,0 +1,43 @@
+<?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.
+-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd";>
+<html xmlns="http://www.w3.org/1999/xhtml";  
+      
xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd";  
+      xml:lang="en"  
+      lang="en">
+    <body>
+        <wicket:panel>
+            <div wicket:id="additionalLinkList" class="additionalLinkList 
additionalLinkListDropDown">
+                <div class="btn-group">
+                    <button type="button" class="btn btn-default btn-sm 
dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
+                        <span class="fa fa-ellipsis-v"></span>
+                    </button>
+                    <ul class="dropdown-menu dropdown-menu-right" role="menu">
+                        <li wicket:id="additionalLinkItem" 
class="additionalLinkItem">
+                            <a href="#" wicket:id="additionalLink">
+                                <span wicket:id="additionalLinkTitle" 
class="additionalLinkItem">[link title]</span>
+                            </a>
+                        </li>
+                    </ul>
+                </div>
+            </div>
+        </wicket:panel>
+    </body>
+</html>

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsDropDownPanel.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsDropDownPanel.java
 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsDropDownPanel.java
new file mode 100644
index 0000000..9b5d793
--- /dev/null
+++ 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsDropDownPanel.java
@@ -0,0 +1,32 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.viewer.wicket.ui.components.actionmenu.entityactions;
+
+import java.util.List;
+import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
+
+public class AdditionalLinksAsDropDownPanel extends AdditionalLinksPanel {
+
+    private static final long serialVersionUID = 1L;
+
+    public AdditionalLinksAsDropDownPanel(String id, List<LinkAndLabel> links) 
{
+        super(id, links);
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsListInlinePanel.html
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsListInlinePanel.html
 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsListInlinePanel.html
new file mode 100644
index 0000000..7cc41f1
--- /dev/null
+++ 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsListInlinePanel.html
@@ -0,0 +1,36 @@
+<?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.
+-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd";>
+<html xmlns="http://www.w3.org/1999/xhtml";  
+      
xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd";  
+      xml:lang="en"  
+      lang="en">
+    <body>
+        <wicket:panel>
+            <ul wicket:id="additionalLinkList" class="additionalLinkList 
additionalLinkListInline list-unstyled list-inline">
+                <li wicket:id="additionalLinkItem" class="additionalLinkItem">
+                    <a href="#" wicket:id="additionalLink" class="btn btn-sm 
btn-default">
+                        <span wicket:id="additionalLinkTitle" 
class="additionalLinkItem">[link title]</span>
+                    </a>
+                </li>
+            </ul>
+        </wicket:panel>
+    </body>
+</html>

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsListInlinePanel.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsListInlinePanel.java
 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsListInlinePanel.java
new file mode 100644
index 0000000..049c1a6
--- /dev/null
+++ 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsListInlinePanel.java
@@ -0,0 +1,32 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.viewer.wicket.ui.components.actionmenu.entityactions;
+
+import java.util.List;
+import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
+
+public class AdditionalLinksAsListInlinePanel extends AdditionalLinksPanel {
+
+    private static final long serialVersionUID = 1L;
+
+    public AdditionalLinksAsListInlinePanel(String id, List<LinkAndLabel> 
links) {
+        super(id, links);
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/d84c6609/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksPanel.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksPanel.java
 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksPanel.java
new file mode 100644
index 0000000..3fd13d6
--- /dev/null
+++ 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksPanel.java
@@ -0,0 +1,146 @@
+/*
+ *  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.components.actionmenu.entityactions;
+
+import java.util.List;
+import com.google.common.base.Strings;
+import org.apache.wicket.MarkupContainer;
+import org.apache.wicket.behavior.AttributeAppender;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.link.AbstractLink;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.isis.applib.annotation.ActionLayout;
+import org.apache.isis.core.commons.lang.StringExtensions;
+import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
+import org.apache.isis.viewer.wicket.model.links.ListOfLinksModel;
+import 
org.apache.isis.viewer.wicket.ui.components.actionmenu.CssClassFaBehavior;
+import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
+import org.apache.isis.viewer.wicket.ui.util.Components;
+import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
+
+public class AdditionalLinksPanel extends PanelAbstract<ListOfLinksModel> {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final String ID_ADDITIONAL_LINK_LIST = "additionalLinkList";
+    private static final String ID_ADDITIONAL_LINK_ITEM = "additionalLinkItem";
+    private static final String ID_ADDITIONAL_LINK_TITLE = 
"additionalLinkTitle";
+
+    public static final String ID_ADDITIONAL_LINK = "additionalLink";
+
+    public enum Style {
+        INLINE_LIST {
+            @Override
+            AdditionalLinksPanel newPanel(String id, List<LinkAndLabel> links) 
{
+                return new AdditionalLinksAsListInlinePanel(id, links);
+            }
+        },
+        DROPDOWN {
+            @Override
+            AdditionalLinksPanel newPanel(String id, List<LinkAndLabel> links) 
{
+                return new AdditionalLinksAsDropDownPanel(id, links);
+            }
+        };
+        abstract AdditionalLinksPanel newPanel(String id, List<LinkAndLabel> 
links);
+    }
+
+    public static AdditionalLinksPanel addAdditionalLinks(
+            final MarkupContainer markupContainer,
+            final String id,
+            final List<LinkAndLabel> links,
+            final Style style) {
+        if(links.isEmpty()) {
+            Components.permanentlyHide(markupContainer, id);
+            return null;
+        }
+
+        final AdditionalLinksPanel additionalLinksPanel =  style.newPanel(id, 
links);
+        markupContainer.addOrReplace(additionalLinksPanel);
+        return additionalLinksPanel;
+    }
+
+
+    private List<LinkAndLabel> linkAndLabels;
+    
+    protected AdditionalLinksPanel(final String id, final List<LinkAndLabel> 
links) {
+        super(id, new ListOfLinksModel(links));
+
+        this.linkAndLabels = getModel().getObject();
+        
+        final WebMarkupContainer container = new 
WebMarkupContainer(ID_ADDITIONAL_LINK_LIST);
+        addOrReplace(container);
+        
+        container.setOutputMarkupId(true);
+        
+        setOutputMarkupId(true);
+        
+        final ListView<LinkAndLabel> listView = new 
ListView<LinkAndLabel>(ID_ADDITIONAL_LINK_ITEM, this.linkAndLabels) {
+
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            protected void populateItem(ListItem<LinkAndLabel> item) {
+                final LinkAndLabel linkAndLabel = item.getModelObject();
+                
+                final AbstractLink link = linkAndLabel.getLink();
+
+                final String itemTitle = 
first(linkAndLabel.getDisabledReasonIfAny(), 
linkAndLabel.getDescriptionIfAny());
+                if(itemTitle != null) {
+                    item.add(new AttributeAppender("title", itemTitle));
+                }
+
+                final Label viewTitleLabel = new 
Label(ID_ADDITIONAL_LINK_TITLE, linkAndLabel.getLabel());
+                if(linkAndLabel.isBlobOrClob()) {
+                    link.add(new CssClassAppender("noVeil"));
+                }
+                if(linkAndLabel.isPrototype()) {
+                    link.add(new CssClassAppender("prototype"));
+                }
+                link.add(new 
CssClassAppender(linkAndLabel.getActionIdentifier()));
+
+                final String cssClass = linkAndLabel.getCssClass();
+                CssClassAppender.appendCssClassTo(link, cssClass);
+
+                viewTitleLabel.add(new 
CssClassAppender(StringExtensions.asLowerDashed(linkAndLabel.getLabel())));
+
+                link.addOrReplace(viewTitleLabel);
+
+                final String cssClassFa = linkAndLabel.getCssClassFa();
+                if(!Strings.isNullOrEmpty(cssClassFa)) {
+                    final ActionLayout.CssClassFaPosition position = 
linkAndLabel.getCssClassFaPosition();
+                    viewTitleLabel.add(new CssClassFaBehavior(cssClassFa, 
position));
+                }
+
+                item.addOrReplace(link);
+            }
+        };
+        container.addOrReplace(listView);
+    }
+
+    private static String first(String... str) {
+        for (String s : str) {
+            if(s != null) return s;
+        }
+        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/components/actionmenu/entityactions/EntityActionLinkFactory.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/EntityActionLinkFactory.java
 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/EntityActionLinkFactory.java
new file mode 100644
index 0000000..67ebf38
--- /dev/null
+++ 
b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/EntityActionLinkFactory.java
@@ -0,0 +1,95 @@
+/*
+ *  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.components.actionmenu.entityactions;
+
+import org.apache.wicket.markup.html.link.AbstractLink;
+
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import 
org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
+import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
+import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
+import org.apache.isis.viewer.wicket.model.models.*;
+import 
org.apache.isis.viewer.wicket.ui.components.widgets.linkandlabel.ActionLinkFactoryAbstract;
+
+public final class EntityActionLinkFactory extends ActionLinkFactoryAbstract {
+
+    private static final long serialVersionUID = 1L;
+
+    @SuppressWarnings("unused")
+    private final EntityModel entityModel;
+
+    public EntityActionLinkFactory(final EntityModel entityModel) {
+        this.entityModel = entityModel;
+    }
+
+    @Override
+    public LinkAndLabel newLink(
+            final ObjectAdapterMemento adapterMemento,
+            final ObjectAction action,
+            final String linkId) {
+
+        final ObjectAdapter objectAdapter = 
adapterMemento.getObjectAdapter(ConcurrencyChecking.NO_CHECK);
+        
+        final Boolean persistent = objectAdapter.representsPersistent();
+        if (!persistent) {
+            throw new IllegalArgumentException("Object '" + 
objectAdapter.titleString(null) + "' is not persistent.");
+        }
+
+        // check visibility and whether enabled
+        final AuthenticationSession session = getAuthenticationSession();
+        
+        final Consent visibility = action.isVisible(session, objectAdapter, 
Where.OBJECT_FORMS);
+        if (visibility.isVetoed()) {
+            return null;
+        }
+
+        
+        final AbstractLink link = newLink(linkId, objectAdapter, action);
+        
+        final Consent usability = action.isUsable(session, objectAdapter, 
Where.OBJECT_FORMS);
+        final String disabledReasonIfAny = usability.getReason();
+        if(disabledReasonIfAny != null) {
+            link.setEnabled(false);
+        }
+
+        return newLinkAndLabel(objectAdapter, action, link, 
disabledReasonIfAny);
+    }
+
+    
+
+    // ///////////////////////////////////////////////////////////////////
+    // Dependencies (from IsisContext)
+    // ///////////////////////////////////////////////////////////////////
+
+    protected PersistenceSession getPersistenceSession() {
+        return IsisContext.getPersistenceSession();
+    }
+
+    protected AuthenticationSession getAuthenticationSession() {
+        return IsisContext.getAuthenticationSession();
+    }
+
+}
\ No newline at end of file

Reply via email to