You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2016/02/12 11:05:28 UTC

[1/2] isis git commit: ISIS-993: guard against invisible actions corresponding to null links.

Repository: isis
Updated Branches:
  refs/heads/ISIS-993 959d42477 -> d2340ebd5


ISIS-993: guard against invisible actions corresponding to null links.


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/bbd593bc
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/bbd593bc
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/bbd593bc

Branch: refs/heads/ISIS-993
Commit: bbd593bc10ab486aad16cc7eff6dd3b2e06a0222
Parents: 959d424
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Thu Feb 11 10:08:59 2016 +0000
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Thu Feb 11 10:08:59 2016 +0000

----------------------------------------------------------------------
 .../entityactions/EntityActionUtil.java         | 24 ++++++++++++++------
 1 file changed, 17 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/bbd593bc/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/EntityActionUtil.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/EntityActionUtil.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/EntityActionUtil.java
index de6e2ca..efa53f6 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/EntityActionUtil.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/EntityActionUtil.java
@@ -22,6 +22,8 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 import com.google.common.base.Function;
+import com.google.common.base.Predicates;
+import com.google.common.collect.FluentIterable;
 import com.google.common.collect.Lists;
 import org.apache.wicket.Session;
 import org.apache.isis.applib.annotation.Where;
@@ -107,6 +109,11 @@ public final class EntityActionUtil {
      * Converts an {@link org.apache.isis.viewer.wicket.model.models.EntityModel} and a (subset of its) {@link org.apache.isis.core.metamodel.spec.feature.ObjectAction}s into a
      * list of {@link org.apache.isis.viewer.wicket.model.links.LinkAndLabel}s intended to be apassed
      * to the {@link AdditionalLinksPanel}.
+     *
+     * <p>
+     *     The length of the list returned may smaller than the inbound actions; any null links
+     *     (for invisible actions) will be discarded.
+     * </p>
      */
     public static List<LinkAndLabel> asLinkAndLabelsForAdditionalLinksPanel(
             final EntityModel entityModel,
@@ -116,13 +123,16 @@ public final class EntityActionUtil {
         final ActionLinkFactory linkFactory = new EntityActionLinkFactory(entityModel);
 
         final ObjectAdapterMemento adapterMemento = entityModel.getObjectAdapterMemento();
-        return Lists.transform(actions, new Function<ObjectAction, LinkAndLabel>() {
-
-            @Override
-            public LinkAndLabel apply(ObjectAction objectAction) {
-                return linkFactory.newLink(linkId, adapterMemento, objectAction);
-            }
-        });
+        return FluentIterable.from(actions)
+                .transform(new Function<ObjectAction, LinkAndLabel>() {
+
+                    @Override
+                    public LinkAndLabel apply(ObjectAction objectAction) {
+                        return linkFactory.newLink(linkId, adapterMemento, objectAction);
+                    }
+                })
+                .filter(Predicates.<LinkAndLabel>notNull())
+                .toList();
     }
 
     private static List<ObjectAction> addActions(


[2/2] isis git commit: ISIS-993: associate properties into their correct fieldsets, honouring ordering. Also order collections.

Posted by da...@apache.org.
ISIS-993: associate properties into their correct fieldsets, honouring ordering.  Also order collections.

in addition:
- bug fix to suppress not contributed collections (from superclasses) being rendered also as actions
- tweak to CSS for BS3 layout
- move DeweyComparator to metamodel module (from runtime module).


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/d2340ebd
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/d2340ebd
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/d2340ebd

Branch: refs/heads/ISIS-993
Commit: d2340ebd5839d94b0976f00a530e4daba6c41b45
Parents: bbd593b
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Fri Feb 12 10:05:01 2016 +0000
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Fri Feb 12 10:05:01 2016 +0000

----------------------------------------------------------------------
 .../layout/ActionLayoutFacetFactory.java        |   6 +-
 .../facets/object/grid/GridFacetDefault.java    |   6 +-
 .../bootstrap3/GridNormalizerServiceBS3.java    | 126 +++++++++++++++----
 .../metamodel/util/DeweyOrderComparator.java    |  82 ++++++++++++
 .../runtime/services/DeweyOrderComparator.java  |  82 ------------
 .../ServicesInstallerFromAnnotation.java        |   7 +-
 .../ServicesInstallerFromConfiguration.java     |   1 +
 ...InstallerFromConfigurationAndAnnotation.java |   1 +
 .../services/DeweyOrderComparatorTest.java      |   2 +
 .../ui/components/layout/bs3/col/Col.html       |   2 +-
 .../collections/EntityCollectionsPanel.java     |   2 +-
 .../wicket/ui/pages/bootstrap-overrides.css     |   2 +
 12 files changed, 200 insertions(+), 119 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/d2340ebd/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/ActionLayoutFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/ActionLayoutFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/ActionLayoutFacetFactory.java
index 6219faa..5803825 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/ActionLayoutFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/ActionLayoutFacetFactory.java
@@ -18,7 +18,6 @@
  */
 package org.apache.isis.core.metamodel.facets.actions.layout;
 
-import java.lang.reflect.Method;
 import java.util.Properties;
 
 import org.apache.isis.applib.annotation.ActionLayout;
@@ -133,9 +132,8 @@ public class ActionLayoutFacetFactory extends FacetFactoryAbstract implements Co
     }
 
     protected boolean isContributingServiceOrMixinObject(final ProcessMethodContext processMethodContext) {
-        final Method method = processMethodContext.getMethod();
-        final Class<?> declaringClass = method.getDeclaringClass();
-        final ObjectSpecification spec = getSpecificationLoader().loadSpecification(declaringClass);
+        final Class<?> cls =  processMethodContext.getCls();
+        final ObjectSpecification spec = getSpecificationLoader().loadSpecification(cls);
 
         return isContributingService(spec) || isMixinObject(spec);
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/d2340ebd/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/grid/GridFacetDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/grid/GridFacetDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/grid/GridFacetDefault.java
index b4329db..9cdabb5 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/grid/GridFacetDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/grid/GridFacetDefault.java
@@ -149,7 +149,9 @@ public class GridFacetDefault
             propsRow.getCols().add(col);
             final List<String> leftMemberGroups = memberGroupNames;
             for (String memberGroup : leftMemberGroups) {
-                final FieldSet fieldSet = new FieldSet(memberGroup);
+                final FieldSet fieldSet = new FieldSet();
+                fieldSet.setId(memberGroup); // to bind to later via @MemberOrder#name()
+                fieldSet.setName(memberGroup);
                 if(unreferencedProperties && col.getFieldSets().isEmpty()) {
                     fieldSet.setUnreferencedProperties(true);
                 }
@@ -164,7 +166,7 @@ public class GridFacetDefault
         if(grid == null) {
             return null;
         }
-        final Class<?> domainClass = getSpecification().getCorrespondingClass();
+        // unused... final Class<?> domainClass = getSpecification().getCorrespondingClass();
 
         return gridService.normalize(grid);
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/d2340ebd/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridNormalizerServiceBS3.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridNormalizerServiceBS3.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridNormalizerServiceBS3.java
index 7523e10..1cb65c9 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridNormalizerServiceBS3.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridNormalizerServiceBS3.java
@@ -16,6 +16,7 @@
  */
 package org.apache.isis.core.metamodel.services.grid.bootstrap3;
 
+import java.util.Comparator;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -23,30 +24,34 @@ import java.util.concurrent.atomic.AtomicReference;
 
 import javax.annotation.Nullable;
 
+import com.google.common.base.Function;
 import com.google.common.base.Predicate;
 import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 
 import org.apache.isis.applib.annotation.DomainService;
 import org.apache.isis.applib.annotation.NatureOfService;
+import org.apache.isis.applib.layout.component.ActionLayoutData;
+import org.apache.isis.applib.layout.component.CollectionLayoutData;
+import org.apache.isis.applib.layout.component.FieldSet;
+import org.apache.isis.applib.layout.component.Grid;
+import org.apache.isis.applib.layout.component.PropertyLayoutData;
 import org.apache.isis.applib.layout.grid.bootstrap3.BS3Col;
 import org.apache.isis.applib.layout.grid.bootstrap3.BS3Grid;
 import org.apache.isis.applib.layout.grid.bootstrap3.BS3Row;
 import org.apache.isis.applib.layout.grid.bootstrap3.BS3RowContent;
 import org.apache.isis.applib.layout.grid.bootstrap3.BS3Tab;
 import org.apache.isis.applib.layout.grid.bootstrap3.BS3TabGroup;
-import org.apache.isis.applib.layout.component.ActionLayoutData;
-import org.apache.isis.applib.layout.component.CollectionLayoutData;
-import org.apache.isis.applib.layout.component.FieldSet;
-import org.apache.isis.applib.layout.component.Grid;
-import org.apache.isis.applib.layout.component.PropertyLayoutData;
 import org.apache.isis.core.metamodel.facets.members.order.MemberOrderFacet;
 import org.apache.isis.core.metamodel.services.grid.GridNormalizerServiceAbstract;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
 import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
 import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.isis.core.metamodel.util.DeweyOrderComparator;
 
 @DomainService(
         nature = NatureOfService.DOMAIN
@@ -80,6 +85,7 @@ public class GridNormalizerServiceBS3 extends GridNormalizerServiceAbstract<BS3G
 
         final LinkedHashMap<String, BS3Row> rowIds = Maps.newLinkedHashMap();
         final LinkedHashMap<String, BS3Col> colIds = Maps.newLinkedHashMap();
+        final LinkedHashMap<String, FieldSet> fieldSetIds = Maps.newLinkedHashMap();
 
         final AtomicReference<Boolean> duplicateIdDetected = new AtomicReference<>(false);
 
@@ -111,6 +117,20 @@ public class GridNormalizerServiceBS3 extends GridNormalizerServiceAbstract<BS3G
                 }
                 colIds.put(id, bs3Col);
             }
+
+            @Override
+            public void visit(final FieldSet fieldSet) {
+                final String id = fieldSet.getId();
+                if(id == null) {
+                    return;
+                }
+                if(rowIds.containsKey(id) || fieldSetIds.containsKey(id)) {
+                    fieldSet.setMetadataError("There is another fieldset with this id");
+                    duplicateIdDetected.set(true);
+                    return;
+                }
+                fieldSetIds.put(id, fieldSet);
+            }
         });
 
         if(duplicateIdDetected.get()) {
@@ -212,9 +232,43 @@ public class GridNormalizerServiceBS3 extends GridNormalizerServiceAbstract<BS3G
         }
 
         if(!missingPropertyIds.isEmpty()) {
-            final FieldSet fieldSet = fieldSetForUnreferencedPropertiesRef.get();
-            if(fieldSet != null) {
-                addMissingPropertiesTo(fieldSet, missingPropertyIds);
+            final Map<String, List<OneToOneAssociation>> boundAssociationsByFieldSetId = Maps.newHashMap();
+            final List<String> unboundPropertyIds = Lists.newArrayList(missingPropertyIds);
+            for (String missingPropertyId : missingPropertyIds) {
+                final OneToOneAssociation otoa = oneToOneAssociationById.get(missingPropertyId);
+                final MemberOrderFacet memberOrderFacet = otoa.getFacet(MemberOrderFacet.class);
+                if(memberOrderFacet != null) {
+                    final String name = memberOrderFacet.name();
+                    if(fieldSetIds.containsKey(name)) {
+                        List<OneToOneAssociation> boundAssociations =
+                                boundAssociationsByFieldSetId.get(name);
+                        if(boundAssociations == null) {
+                            boundAssociations = Lists.newArrayList();
+                            boundAssociationsByFieldSetId.put(name, boundAssociations);
+                        }
+                        boundAssociations.add(otoa);
+                        unboundPropertyIds.remove(missingPropertyId);
+                    }
+                }
+            }
+
+            for (String fieldSetId : boundAssociationsByFieldSetId.keySet()) {
+                final FieldSet fieldSet = fieldSetIds.get(fieldSetId);
+                final List<OneToOneAssociation> associations =
+                        boundAssociationsByFieldSetId.get(fieldSetId);
+
+                associations.sort(byMemberOrderSequence());
+                addPropertiesTo(fieldSet,
+                        FluentIterable.from(associations)
+                                      .transform(ObjectAssociation.Functions.toId())
+                                      .toList());
+            }
+
+            if(!unboundPropertyIds.isEmpty()) {
+                final FieldSet fieldSet = fieldSetForUnreferencedPropertiesRef.get();
+                if(fieldSet != null) {
+                    addPropertiesTo(fieldSet, unboundPropertyIds);
+                }
             }
         }
 
@@ -229,13 +283,25 @@ public class GridNormalizerServiceBS3 extends GridNormalizerServiceAbstract<BS3G
         }
 
         if(!missingCollectionIds.isEmpty()) {
+            List<OneToManyAssociation> sortedCollections = Lists.newArrayList(
+                    FluentIterable.from(missingCollectionIds)
+                    .transform(new Function<String, OneToManyAssociation>() {
+                        @Nullable @Override public OneToManyAssociation apply(@Nullable final String collectionId) {
+                            return oneToManyAssociationById.get(collectionId);
+                        }
+                    })
+                    .toSortedList(byMemberOrderSequence())
+
+            );
+            final ImmutableList<String> sortedMissingCollectionIds = FluentIterable.from(sortedCollections)
+                    .transform(ObjectAssociation.Functions.toId()).toList();
             final BS3TabGroup bs3TabGroup = tabGroupForUnreferencedCollectionsRef.get();
             if(bs3TabGroup != null) {
-                addMissingCollectionsTo(bs3TabGroup, missingCollectionIds, objectSpec);
+                addCollectionsTo(bs3TabGroup, sortedMissingCollectionIds, objectSpec);
             } else {
                 final BS3Col bs3Col = colForUnreferencedCollectionsRef.get();
                 if(bs3Col != null) {
-                    addMissingCollectionsTo(bs3Col, missingCollectionIds);
+                    addCollectionsTo(bs3Col, sortedMissingCollectionIds);
                 }
             }
         }
@@ -273,11 +339,11 @@ public class GridNormalizerServiceBS3 extends GridNormalizerServiceAbstract<BS3G
         if(!missingActionIds.isEmpty()) {
             final BS3Col bs3Col = colForUnreferencedActionsRef.get();
             if(bs3Col != null) {
-                addMissingActionsTo(bs3Col, missingActionIds);
+                addActionsTo(bs3Col, missingActionIds);
             } else {
                 final FieldSet fieldSet = fieldSetForUnreferencedActionsRef.get();
                 if(fieldSet != null) {
-                    addMissingActionsTo(fieldSet, missingActionIds);
+                    addActionsTo(fieldSet, missingActionIds);
                 }
             }
         }
@@ -285,15 +351,29 @@ public class GridNormalizerServiceBS3 extends GridNormalizerServiceAbstract<BS3G
         return true;
     }
 
-    protected void addMissingPropertiesTo(
+    private static Comparator<ObjectAssociation> byMemberOrderSequence() {
+        return new Comparator<ObjectAssociation>() {
+            private final DeweyOrderComparator deweyOrderComparator = new DeweyOrderComparator();
+            @Override
+            public int compare(final ObjectAssociation o1, final ObjectAssociation o2) {
+                final MemberOrderFacet o1Facet = o1.getFacet(MemberOrderFacet.class);
+                final MemberOrderFacet o2Facet = o2.getFacet(MemberOrderFacet.class);
+                return o1Facet == null? +1:
+                        o2Facet == null? -1:
+                                deweyOrderComparator.compare(o1Facet.sequence(), o2Facet.sequence());
+            }
+        };
+    }
+
+    protected void addPropertiesTo(
             final FieldSet fieldSet,
-            final List<String> missingPropertyIds) {
-        for (final String propertyId : missingPropertyIds) {
+            final List<String> propertyIds) {
+        for (final String propertyId : propertyIds) {
             fieldSet.getProperties().add(new PropertyLayoutData(propertyId));
         }
     }
 
-    protected void addMissingActionsTo(final BS3Col bs3Col, final List<String> missingActionIds) {
+    protected void addActionsTo(final BS3Col bs3Col, final List<String> missingActionIds) {
         for (String actionId : missingActionIds) {
             List<ActionLayoutData> actions = bs3Col.getActions();
             if(actions == null) {
@@ -304,28 +384,28 @@ public class GridNormalizerServiceBS3 extends GridNormalizerServiceAbstract<BS3G
         }
     }
 
-    protected void addMissingActionsTo(final FieldSet fieldSet, final List<String> missingActionIds) {
+    protected void addActionsTo(final FieldSet fieldSet, final List<String> missingActionIds) {
         List<ActionLayoutData> actions = fieldSet.getActions();
         for (String actionId : missingActionIds) {
             actions.add(new ActionLayoutData(actionId));
         }
     }
 
-    protected void addMissingCollectionsTo(
+    protected void addCollectionsTo(
             final BS3Col tabRowCol,
-            final List<String> missingCollectionIds) {
-        for (final String collectionId : missingCollectionIds) {
+            final List<String> collectionIds) {
+        for (final String collectionId : collectionIds) {
             final CollectionLayoutData layoutMetadata = new CollectionLayoutData(collectionId);
             layoutMetadata.setDefaultView("table");
             tabRowCol.getCollections().add(layoutMetadata);
         }
     }
 
-    protected void addMissingCollectionsTo(
+    protected void addCollectionsTo(
             final BS3TabGroup tabGroup,
-            final List<String> missingCollectionIds,
+            final List<String> collectionIds,
             final ObjectSpecification objectSpec) {
-        for (final String collectionId : missingCollectionIds) {
+        for (final String collectionId : collectionIds) {
             final BS3Tab bs3Tab = new BS3Tab();
             bs3Tab.setName(objectSpec.getAssociation(collectionId).getName());
             tabGroup.getTabs().add(bs3Tab);

http://git-wip-us.apache.org/repos/asf/isis/blob/d2340ebd/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/DeweyOrderComparator.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/DeweyOrderComparator.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/DeweyOrderComparator.java
new file mode 100644
index 0000000..0845838
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/DeweyOrderComparator.java
@@ -0,0 +1,82 @@
+/*
+ *  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;
+
+import java.util.Comparator;
+import java.util.List;
+import com.google.common.base.Function;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Iterators;
+import com.google.common.collect.Lists;
+
+public class DeweyOrderComparator implements Comparator<String> {
+
+    public DeweyOrderComparator() {}
+
+    @Override
+    public int compare(String o1, String o2) {
+        final Parsed<String> p1 = new Parsed<String>(o1);
+        final Parsed<String> p2 = new Parsed<String>(o2);
+        return p1.compareTo(p2);
+    }
+
+    private static class Parsed<V> implements Comparable<Parsed<V>> {
+        private static final Function<String, Integer> PARSE = new Function<String, Integer>() {
+            @Override
+            public Integer apply(String input) {
+                try {
+                    return Integer.parseInt(input);
+                } catch (NumberFormatException e) {
+                    return Integer.MAX_VALUE;
+                }
+            }
+        };
+        private final List<Integer> parts;
+        private final String key;
+        Parsed(String key) {
+            this.key = key;
+            final Iterable<String> iter = Splitter.on(".").split(key);
+            parts = Lists.newArrayList(Iterators.transform(iter.iterator(), PARSE));
+        }
+
+        @Override
+        public int compareTo(Parsed<V> other) {
+            for (int i = 0; i < parts.size(); i++) {
+                Integer p = parts.get(i);
+                if (other.parts.size() == i) {
+                    // run out of parts for other, put it before us
+                    return +1;
+                }
+                final Integer q = other.parts.get(i);
+                final int comparison = p.compareTo(q);
+                if(comparison != 0) {
+                    return +comparison;
+                }
+            }
+            if(other.parts.size() > parts.size()) {
+                // run out of parts on our side, still more on others; put us before it
+                return -1;
+            }
+            return 0;
+        }
+    }
+}
+
+

http://git-wip-us.apache.org/repos/asf/isis/blob/d2340ebd/core/runtime/src/main/java/org/apache/isis/core/runtime/services/DeweyOrderComparator.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/DeweyOrderComparator.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/DeweyOrderComparator.java
deleted file mode 100644
index 7c6d373..0000000
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/DeweyOrderComparator.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- *  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.runtime.services;
-
-import java.util.Comparator;
-import java.util.List;
-import com.google.common.base.Function;
-import com.google.common.base.Splitter;
-import com.google.common.collect.Iterators;
-import com.google.common.collect.Lists;
-
-public class DeweyOrderComparator implements Comparator<String> {
-
-    public DeweyOrderComparator() {}
-
-    @Override
-    public int compare(String o1, String o2) {
-        final Parsed<String> p1 = new Parsed<String>(o1);
-        final Parsed<String> p2 = new Parsed<String>(o2);
-        return p1.compareTo(p2);
-    }
-
-    private static class Parsed<V> implements Comparable<Parsed<V>> {
-        private static final Function<String, Integer> PARSE = new Function<String, Integer>() {
-            @Override
-            public Integer apply(String input) {
-                try {
-                    return Integer.parseInt(input);
-                } catch (NumberFormatException e) {
-                    return Integer.MAX_VALUE;
-                }
-            }
-        };
-        private final List<Integer> parts;
-        private final String key;
-        Parsed(String key) {
-            this.key = key;
-            final Iterable<String> iter = Splitter.on(".").split(key);
-            parts = Lists.newArrayList(Iterators.transform(iter.iterator(), PARSE));
-        }
-
-        @Override
-        public int compareTo(Parsed<V> other) {
-            for (int i = 0; i < parts.size(); i++) {
-                Integer p = parts.get(i);
-                if (other.parts.size() == i) {
-                    // run out of parts for other, put it before us
-                    return +1;
-                }
-                final Integer q = other.parts.get(i);
-                final int comparison = p.compareTo(q);
-                if(comparison != 0) {
-                    return +comparison;
-                }
-            }
-            if(other.parts.size() > parts.size()) {
-                // run out of parts on our side, still more on others; put us before it
-                return -1;
-            }
-            return 0;
-        }
-    }
-}
-
-

http://git-wip-us.apache.org/repos/asf/isis/blob/d2340ebd/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ServicesInstallerFromAnnotation.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ServicesInstallerFromAnnotation.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ServicesInstallerFromAnnotation.java
index dfc19e7..5b7ebb2 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ServicesInstallerFromAnnotation.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ServicesInstallerFromAnnotation.java
@@ -26,7 +26,6 @@ import java.util.SortedMap;
 import java.util.SortedSet;
 
 import javax.annotation.PreDestroy;
-import javax.jdo.annotations.PersistenceCapable;
 
 import com.google.common.base.Function;
 import com.google.common.base.Joiner;
@@ -38,10 +37,6 @@ import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 
 import org.reflections.Reflections;
-import org.reflections.scanners.SubTypesScanner;
-import org.reflections.scanners.TypeAnnotationsScanner;
-import org.reflections.util.ClasspathHelper;
-import org.reflections.util.ConfigurationBuilder;
 import org.reflections.vfs.Vfs;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -49,8 +44,8 @@ import org.slf4j.LoggerFactory;
 import org.apache.isis.applib.AppManifest;
 import org.apache.isis.applib.annotation.DomainService;
 import org.apache.isis.applib.annotation.DomainServiceLayout;
-import org.apache.isis.applib.fixturescripts.FixtureScript;
 import org.apache.isis.applib.services.classdiscovery.ClassDiscoveryServiceUsingReflections;
+import org.apache.isis.core.metamodel.util.DeweyOrderComparator;
 
 import static com.google.common.base.Predicates.and;
 import static com.google.common.base.Predicates.not;

http://git-wip-us.apache.org/repos/asf/isis/blob/d2340ebd/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ServicesInstallerFromConfiguration.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ServicesInstallerFromConfiguration.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ServicesInstallerFromConfiguration.java
index e58d90e..0b75593 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ServicesInstallerFromConfiguration.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ServicesInstallerFromConfiguration.java
@@ -34,6 +34,7 @@ import org.slf4j.LoggerFactory;
 
 import org.apache.isis.core.commons.config.ConfigurationConstants;
 import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.core.metamodel.util.DeweyOrderComparator;
 import org.apache.isis.core.runtime.fixturedomainservice.ObjectFixtureService;
 import org.apache.isis.core.runtime.system.DeploymentType;
 import org.apache.isis.core.runtime.system.SystemConstants;

http://git-wip-us.apache.org/repos/asf/isis/blob/d2340ebd/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ServicesInstallerFromConfigurationAndAnnotation.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ServicesInstallerFromConfigurationAndAnnotation.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ServicesInstallerFromConfigurationAndAnnotation.java
index 3ef5ad7..20c5869 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ServicesInstallerFromConfigurationAndAnnotation.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ServicesInstallerFromConfigurationAndAnnotation.java
@@ -30,6 +30,7 @@ import org.slf4j.LoggerFactory;
 
 import org.apache.isis.core.commons.config.IsisConfiguration;
 import org.apache.isis.core.commons.config.IsisConfigurationBuilder;
+import org.apache.isis.core.metamodel.util.DeweyOrderComparator;
 
 public class ServicesInstallerFromConfigurationAndAnnotation extends ServicesInstallerAbstract  {
 

http://git-wip-us.apache.org/repos/asf/isis/blob/d2340ebd/core/runtime/src/test/java/org/apache/isis/core/runtime/services/DeweyOrderComparatorTest.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/test/java/org/apache/isis/core/runtime/services/DeweyOrderComparatorTest.java b/core/runtime/src/test/java/org/apache/isis/core/runtime/services/DeweyOrderComparatorTest.java
index d0f5448..71b6e01 100644
--- a/core/runtime/src/test/java/org/apache/isis/core/runtime/services/DeweyOrderComparatorTest.java
+++ b/core/runtime/src/test/java/org/apache/isis/core/runtime/services/DeweyOrderComparatorTest.java
@@ -26,6 +26,8 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 
+import org.apache.isis.core.metamodel.util.DeweyOrderComparator;
+
 import static org.hamcrest.CoreMatchers.is;
 
 public class DeweyOrderComparatorTest {

http://git-wip-us.apache.org/repos/asf/isis/blob/d2340ebd/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/layout/bs3/col/Col.html
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/layout/bs3/col/Col.html b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/layout/bs3/col/Col.html
index fef305b..6518561 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/layout/bs3/col/Col.html
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/layout/bs3/col/Col.html
@@ -40,7 +40,7 @@
                 <div class="fieldSets" wicket:id="fieldSets">
                     [fieldsets]
                 </div>
-                <div class="collections" wicket:id="collections">
+                <div class="collections entityCollection" wicket:id="collections">
                     [collections]
                 </div>
             </div>

http://git-wip-us.apache.org/repos/asf/isis/blob/d2340ebd/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/layout/fixedcols/collections/EntityCollectionsPanel.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/layout/fixedcols/collections/EntityCollectionsPanel.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/layout/fixedcols/collections/EntityCollectionsPanel.java
index 6f36549..09337dc 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/layout/fixedcols/collections/EntityCollectionsPanel.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/layout/fixedcols/collections/EntityCollectionsPanel.java
@@ -38,7 +38,7 @@ import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
 import org.apache.isis.core.metamodel.facets.members.order.MemberOrderFacet;
 import org.apache.isis.core.metamodel.spec.feature.Contributed;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
-import org.apache.isis.core.runtime.services.DeweyOrderComparator;
+import org.apache.isis.core.metamodel.util.DeweyOrderComparator;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
 import org.apache.isis.viewer.wicket.ui.components.entity.collection.EntityCollectionPanel;
 import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;

http://git-wip-us.apache.org/repos/asf/isis/blob/d2340ebd/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides.css
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides.css b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides.css
index 43c615d..5df7fcb 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides.css
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides.css
@@ -469,6 +469,8 @@ div.additionalLinkList {
     padding-bottom: 10px;
 }
 
+.collections div.additionalLinkList,
+.collections ul.additionalLinkList,
 .standaloneCollectionPanel div.additionalLinkList,
 .standaloneCollectionPanel ul.additionalLinkList,
 .entityCollectionsPanel div.additionalLinkList,