This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git

commit e92b4db2846cce03959b7bf7e7f5c31c705e1476
Author: Andi Huber <ahu...@apache.org>
AuthorDate: Fri Oct 27 15:34:55 2017 +0200

    ISIS-1740 initial commit of prototype
---
 .../org/apache/isis/applib/annotation/Parent.java  |  34 ++++++
 .../metamodel/util/pchain/CachingParentChain.java  |  66 +++++++++++
 .../core/metamodel/util/pchain/ParentChain.java    |  99 ++++++++++++++++
 .../metamodel/util/pchain/SimpleParentChain.java   |  75 +++++++++++++
 .../isis/core/metamodel/util/pchain/SoftCache.java | 124 +++++++++++++++++++++
 .../model/models/whereami/WhereAmIModel.java       |  38 +++++++
 .../models/whereami/WhereAmIModelDefault.java      |  68 +++++++++++
 .../viewer/wicket/ui/pages/entity/EntityPage.css   |  29 +++++
 .../viewer/wicket/ui/pages/entity/EntityPage.html  |   7 +-
 .../viewer/wicket/ui/pages/entity/EntityPage.java  |  53 ++++++++-
 10 files changed, 587 insertions(+), 6 deletions(-)

diff --git 
a/core/applib/src/main/java/org/apache/isis/applib/annotation/Parent.java 
b/core/applib/src/main/java/org/apache/isis/applib/annotation/Parent.java
new file mode 100644
index 0000000..6e4a7d8
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/Parent.java
@@ -0,0 +1,34 @@
+/* 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.isis.applib.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Tells the framework which method or field to use in order to construct a 
navigable chain of
+ * parent domain object instances. This annotation can only be used once per 
class declaration. 
+ * 
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD, ElementType.METHOD})
+public @interface Parent {
+}
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/pchain/CachingParentChain.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/pchain/CachingParentChain.java
new file mode 100644
index 0000000..630e928
--- /dev/null
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/pchain/CachingParentChain.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.core.metamodel.util.pchain;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Method;
+
+class CachingParentChain extends SimpleParentChain {
+
+       private final SoftCache<Class<?>, MethodHandle> cache = new 
SoftCache<>();
+
+       @Override
+       public Object parentOf(Object node) {
+               if(node==null)
+                       return null;
+               
+               final MethodHandle mh = cache.computeIfAbsent(node.getClass(), 
+                               key->{
+                                       try {
+                                               return methodHandleOf(node);
+                                       } catch (IllegalAccessException e) {
+                                               e.printStackTrace();
+                                               return null;
+                                       }
+                               });
+               
+               if(mh==null)
+                       return null;
+               
+               try {
+                       return mh.invoke(node);
+               } catch (Throwable e) {
+                       e.printStackTrace();
+                       return null;
+               }
+               
+       }
+       
+       protected static MethodHandle methodHandleOf(Object node) throws 
IllegalAccessException{
+               final Method getter = parentGetterOf(node);
+               return getter!=null ? handleOf(getter) : null;
+       }
+
+       public static MethodHandle handleOf(Method m) throws 
IllegalAccessException {
+               return MethodHandles.publicLookup().unreflect(m);
+       }
+       
+}
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/pchain/ParentChain.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/pchain/ParentChain.java
new file mode 100644
index 0000000..31ae507
--- /dev/null
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/pchain/ParentChain.java
@@ -0,0 +1,99 @@
+/*
+ * 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.core.metamodel.util.pchain;
+
+import java.lang.reflect.Method;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.Set;
+import java.util.stream.Stream;
+
+import org.apache.isis.applib.annotation.Parent;
+import org.apache.isis.core.commons.reflection.Reflect;
+
+/**
+ * Represents a unidirectional linked ordered set of Pojos (chain), where the 
chain 
+ * starts at startNode. Each subsequent node is linked via de-referencing a 
+ * singular field (or no-arg method) that is annotated with {@code @Parent}.
+ * <br/>
+ * 
+ * startNode --@Parent--&gt; node2 --@Parent--&gt; node3 ...
+ * 
+ * @author ahu...@apache.org
+ *
+ */
+public interface ParentChain {
+       
+       static ParentChain simple() {
+               return new SimpleParentChain();
+       }
+       
+       static ParentChain caching() {
+               return new CachingParentChain();
+       }
+       
+       public Object parentOf(Object node);
+       
+       static boolean providesParent(Method m) {
+               if(!Reflect.isNoArg(m))
+                       return false;
+               if(!Reflect.isPublic(m))
+                       return false;
+               if(Reflect.isVoid(m)) 
+                       return false;
+               if(Reflect.isPrimitive(m.getReturnType())) 
+                       return false;
+               
+               if(m.getName().equals("parent"))
+                       return true;
+               
+               if(m.isAnnotationPresent(Parent.class))
+                       return true;
+               
+               return false;
+       }
+
+       default Stream<Object> streamParentChainOf(Object startNode){
+               final Set<Object> chain = new LinkedHashSet<>();
+               
+               chain.add(startNode);
+               
+               Object next = startNode;
+               
+               while((next = parentOf(next))!=null) {
+                       final boolean doContinue = chain.add(next);
+                       if(!doContinue)
+                               break;
+               }
+               
+               return chain.stream().skip(1);
+       }
+       
+       default Stream<Object> streamReversedParentChainOf(Object startNode){
+               final LinkedList<Object> reverseChain = new 
LinkedList<Object>();
+               
+               streamParentChainOf(startNode)
+               .forEach(reverseChain::addFirst);
+               
+               return reverseChain.stream();
+       }
+       
+       
+}
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/pchain/SimpleParentChain.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/pchain/SimpleParentChain.java
new file mode 100644
index 0000000..b30e427
--- /dev/null
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/pchain/SimpleParentChain.java
@@ -0,0 +1,75 @@
+/*
+ * 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.core.metamodel.util.pchain;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import org.apache.isis.applib.annotation.Parent;
+import org.apache.isis.core.commons.lang.NullSafe;
+import org.apache.isis.core.commons.reflection.Reflect;
+
+class SimpleParentChain implements ParentChain {
+
+       @Override
+       public Object parentOf(Object node) {
+               if(node==null)
+                       return null;
+               
+               final Method getter = parentGetterOf(node);
+               if(getter==null)
+                       return null;
+               
+               try {
+                       return getter.invoke(node, Reflect.emptyObjects);
+               } catch (IllegalAccessException | IllegalArgumentException | 
InvocationTargetException e) {
+                       e.printStackTrace();
+               }
+               
+               return null;
+       }
+       
+       protected static Method parentGetterOf(Object node) {
+               return
+               NullSafe.stream(Reflect.getAllDeclaredMethods(node.getClass()))
+               .filter(ParentChain::providesParent)
+               .findFirst()
+               .orElse(findGetterForAnnotatedField(node));
+       }
+       
+       protected static Method findGetterForAnnotatedField(Object node) {
+               return 
+               NullSafe.stream(Reflect.getAllDeclaredFields(node.getClass()))
+               .filter(f->f.isAnnotationPresent(Parent.class))
+               .findFirst()
+               .map(f->getterOf(node, f.getName()))
+               .orElse(null);
+       }
+       
+       private static Method getterOf(Object bean, String propertyName) {
+               try {
+                       return Reflect.getGetter(bean, propertyName);
+               } catch (Exception e) {
+                       e.printStackTrace();
+                       return null;
+               }
+       }
+
+}
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/pchain/SoftCache.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/pchain/SoftCache.java
new file mode 100644
index 0000000..34c1ff6
--- /dev/null
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/pchain/SoftCache.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.isis.core.metamodel.util.pchain;
+
+import java.lang.ref.SoftReference;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+/**
+ * Implements a caching {@code Map} where objects are stored referenced by 
+ * a unique key, while {@codeMap.Entries} might be garbage collected any time. 
+ * 
+ * @author ahu...@apache.org
+ *
+ * @param <K>
+ * @param <T>
+ */
+class SoftCache<K,T> {
+       
+       private Map<K,SoftReference<T>> data;
+       
+       public SoftCache() {
+               data=newMap();
+       }
+       
+       public SoftCache(Supplier<Map<K,SoftReference<T>>> mapFactory) {
+               data=mapFactory.get();
+       }
+       
+       /**
+        * Note: might be overridden to use a different map implementation for 
storage
+        * @return
+        */
+       protected Map<K,SoftReference<T>> newMap(){
+               return new HashMap<>();
+       }
+       
+       /**
+        * Note: call to this method will fool the garbage collector, 
+        * so that last objects in the entry set will be kept longer, 
+        * due to latest access  
+        * @return number of currently usable SoftReferences 
+        */
+       public int computeSize(){
+               Map<K,SoftReference<T>> keep = newMap();
+               for(Map.Entry<K,SoftReference<T>> entry : data.entrySet()){
+                       if(entry.getValue()!=null) 
keep.put(entry.getKey(),entry.getValue()); 
+               }
+               data.clear();
+               data=keep;
+               return data.size();
+       }
+       
+       // keep private! (result is not guaranteed to be accurate, 
+       // since the garbage collector may change the soft references any time)
+       @SuppressWarnings("unused")
+       private boolean contains(K key){
+               return get(key)!=null;
+       }
+       
+       public void put(K key, T x){
+               data.put(key, new SoftReference<T>(x));
+       }
+       
+       public T get(K key){
+               SoftReference<T> ref = data.get(key); 
+               if(ref==null) {
+                       data.remove(key);
+                       return null;
+               }
+               return ref.get();
+       }
+
+       public void clear() {
+               data.clear();           
+       }
+
+       /**
+        * Tries to fetch a value from cache and returns it if it's a hit. 
+        * Otherwise stores and returns the value supplied by the 
mappingFunction.
+        * @param key
+        * @param mappingFunction
+        * @return either the value stored under key or (if there is no such 
key) the result from the factory 
+        */
+       public T computeIfAbsent(K key, Function<? super K,? extends T> 
mappingFunction){
+               return computeIfAbsent(key,()->mappingFunction.apply(key));
+       }
+       
+       /**
+        * Tries to fetch a value from cache and returns it if it's a hit. 
+        * Otherwise stores and returns the value supplied by the factory.
+        * @param key
+        * @param factory
+        * @return either the value stored under key or (if there is no such 
key) the result from the factory 
+        */
+       public T computeIfAbsent(K key, Supplier<T> factory) {
+               T res = get(key);
+               if(res!=null)
+                       return res;
+               res = factory.get();
+               put(key,res); 
+               return res;
+       }
+       
+}
+
diff --git 
a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/whereami/WhereAmIModel.java
 
b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/whereami/WhereAmIModel.java
new file mode 100644
index 0000000..7ecfba0
--- /dev/null
+++ 
b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/whereami/WhereAmIModel.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.isis.viewer.wicket.model.models.whereami;
+
+import java.util.stream.Stream;
+
+import org.apache.isis.viewer.wicket.model.models.EntityModel;
+
+public interface WhereAmIModel {
+
+       public static WhereAmIModel of(EntityModel endOfChain) {
+               return new WhereAmIModelDefault(endOfChain);
+       }
+
+       public boolean isShowWhereAmI();
+       
+       public Stream<EntityModel> streamParentChain();
+       
+       public EntityModel getEndOfChain();
+       
+}
diff --git 
a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/whereami/WhereAmIModelDefault.java
 
b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/whereami/WhereAmIModelDefault.java
new file mode 100644
index 0000000..b3f6679
--- /dev/null
+++ 
b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/whereami/WhereAmIModelDefault.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.model.models.whereami;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+
+import org.apache.isis.core.metamodel.util.pchain.ParentChain;
+import org.apache.isis.viewer.wicket.model.models.EntityModel;
+
+class WhereAmIModelDefault implements WhereAmIModel {
+
+       private final List<Object> chainOfParents = new ArrayList<>();
+       private final EntityModel endOfChain;
+       
+       public WhereAmIModelDefault(EntityModel endOfChain) {
+               this.endOfChain = endOfChain;
+               
+               final Object startPojo = endOfChain.getObject().getObject();
+
+               ParentChain.caching()
+               .streamReversedParentChainOf(startPojo)
+               .forEach(chainOfParents::add);
+       }
+       
+       @Override
+       public EntityModel getEndOfChain() {
+               return endOfChain;
+       }
+       
+       @Override
+       public boolean isShowWhereAmI() {
+               return !chainOfParents.isEmpty();
+       }
+
+       @Override
+       public Stream<EntityModel> streamParentChain() {
+               return chainOfParents.stream()
+               .map(this::toEntityModel);
+       }
+       
+       // -- HELPER
+
+       private EntityModel toEntityModel(Object domainObject) {
+               return new EntityModel(
+                               endOfChain.getPersistenceSession()
+                               .adapterFor(domainObject)       );
+       }
+       
+}
diff --git 
a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.css
 
b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.css
index eaeea17..b3618df 100644
--- 
a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.css
+++ 
b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.css
@@ -16,3 +16,32 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
+ 
+ /* === whereAmI feature === */
+
+.whereAmI {
+    color: #555;
+}
+.whereAmI img {
+    width: 16px !important;
+    height: 16px !important;
+}
+ul.whereAmI {
+    padding: 8px 12px;
+    list-style: none;
+    background-color: #eee;
+}
+
+/* Display list items side by side */
+ul.whereAmI li {
+    display: inline;
+}
+
+/* Add a slash symbol (/) before/behind each list item */
+ul.whereAmI li+li:before {
+    padding: 4px;
+    color: black;
+    content: "/\00a0";
+}
+
+/* -------------------------- */
\ No newline at end of file
diff --git 
a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.html
 
b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.html
index 1caad01..39aa437 100644
--- 
a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.html
+++ 
b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.html
@@ -26,8 +26,13 @@
         <wicket:extend>
             <div class="entityPage" wicket:id="entityPageContainer">
                 <div wicket:id="bookmarks"></div>
+                 <div wicket:id="whereAmI-container">
+                       <ul class="whereAmI">
+                                       <li wicket:id="whereAmI-items"></li>
+                                       </ul>
+                </div>
                 <div wicket:id="entity"></div>
             </div>
         </wicket:extend>
     </body>
-</html>
+</html>
\ No newline at end of file
diff --git 
a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.java
 
b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.java
index f824e1d..e9e04dc 100644
--- 
a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.java
+++ 
b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/entity/EntityPage.java
@@ -22,12 +22,16 @@ package org.apache.isis.viewer.wicket.ui.pages.entity;
 import org.apache.wicket.Application;
 import org.apache.wicket.RestartResponseException;
 import 
org.apache.wicket.authroles.authorization.strategies.role.annotations.AuthorizeInstantiation;
+import org.apache.wicket.markup.head.CssHeaderItem;
+import org.apache.wicket.markup.head.IHeaderResponse;
 import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.html.link.BookmarkablePageLink;
+import org.apache.wicket.markup.repeater.RepeatingView;
 import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.apache.wicket.request.resource.CssResourceReference;
 import org.apache.wicket.util.string.Strings;
 
-import org.apache.isis.applib.layout.grid.Grid;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.version.ConcurrencyException;
 import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
@@ -39,7 +43,9 @@ import 
org.apache.isis.core.metamodel.spec.feature.ObjectMember;
 import org.apache.isis.viewer.wicket.model.common.PageParametersUtils;
 import org.apache.isis.viewer.wicket.model.hints.UiHintContainer;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
+import org.apache.isis.viewer.wicket.model.models.whereami.WhereAmIModel;
 import org.apache.isis.viewer.wicket.ui.ComponentType;
+import 
org.apache.isis.viewer.wicket.ui.components.entity.icontitle.EntityIconAndTitlePanel;
 import 
org.apache.isis.viewer.wicket.ui.components.widgets.breadcrumbs.BreadcrumbModel;
 import 
org.apache.isis.viewer.wicket.ui.components.widgets.breadcrumbs.BreadcrumbModelProvider;
 import org.apache.isis.viewer.wicket.ui.pages.PageAbstract;
@@ -51,8 +57,10 @@ import 
org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
 @AuthorizeInstantiation("org.apache.isis.viewer.wicket.roles.USER")
 public class EntityPage extends PageAbstract {
 
-    private static final long serialVersionUID = 1L;
-    
+       private static final long serialVersionUID = 144368606134796079L;
+       private static final CssResourceReference WHERE_AM_I_CSS = 
+                       new CssResourceReference(EntityPage.class, 
"EntityPage.css");
+
     private final EntityModel model;
     private final String titleString;
 
@@ -63,6 +71,12 @@ public class EntityPage extends PageAbstract {
     public EntityPage(final PageParameters pageParameters) {
         this(pageParameters, createEntityModel(pageParameters));
     }
+    
+    @Override
+    public void renderHead(IHeaderResponse response) {
+       super.renderHead(response);
+       response.render(CssHeaderItem.forReference(WHERE_AM_I_CSS));
+    }
 
     /**
      * Creates an EntityModel from the given page parameters.
@@ -159,7 +173,7 @@ public class EntityPage extends PageAbstract {
             // the facet should always exist, in fact
             // just enough to ask for the metadata.
             // This will cause the current ObjectSpec to be updated as a side 
effect.
-            final Grid unused = gridFacet.getGrid();
+            gridFacet.getGrid();
         }
 
         if(titleString == null) {
@@ -179,6 +193,8 @@ public class EntityPage extends PageAbstract {
 
         themeDiv.addOrReplace(entityPageContainer);
 
+        addWhereAmIIfShown(entityPageContainer, WhereAmIModel.of(model));
+        
         addChildComponents(entityPageContainer, model);
 
         // bookmarks and breadcrumbs
@@ -186,10 +202,37 @@ public class EntityPage extends PageAbstract {
         addBreadcrumbIfShown(model);
 
         addBookmarkedPages(entityPageContainer);
+        
+        
     }
 
     protected DeploymentCategory getDeploymentCategory() {
         return getIsisSessionFactory().getDeploymentCategory();
     }
-
+    
+    protected void addWhereAmIIfShown(
+               WebMarkupContainer entityPageContainer, 
+               WhereAmIModel whereAmIModel) 
+    {
+       
+       final WebMarkupContainer whereAmIContainer = 
+                       new WebMarkupContainer("whereAmI-container");
+       entityPageContainer.addOrReplace(whereAmIContainer);
+       
+       if(!whereAmIModel.isShowWhereAmI()) {
+               whereAmIContainer.setVisible(false);
+               return;
+       }
+       
+       final RepeatingView listItems = new RepeatingView("whereAmI-items");
+       
+       whereAmIModel.streamParentChain().forEach(entityModel->
+               listItems.add(new 
EntityIconAndTitlePanel(listItems.newChildId(), entityModel)) 
+               );
+       
+       listItems.add(new Label(listItems.newChildId(), 
whereAmIModel.getEndOfChain().getTitle()));
+       
+       whereAmIContainer.addOrReplace(listItems);
+       
+       }
 }

-- 
To stop receiving notification emails like this one, please contact
danhayw...@apache.org.

Reply via email to