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 2017/09/14 17:46:28 UTC

[06/13] isis git commit: Fix ISIS-1715 menuOrder not honored

Fix ISIS-1715 menuOrder not honored

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

Branch: refs/heads/master
Commit: 312ac31b770308a4dd14b115f30fcfc1cf2d45b4
Parents: 2f7a414
Author: hobrom <ho...@gmx.at>
Authored: Tue Sep 12 16:31:47 2017 +0200
Committer: hobrom <ho...@gmx.at>
Committed: Tue Sep 12 16:31:47 2017 +0200

----------------------------------------------------------------------
 .../core/commons/compare/SequenceCompare.java   | 92 ++++++++++++++++++++
 .../domainservice/DomainServiceMenuOrder.java   | 61 +++++++++++++
 .../MemberOrderFacetComparator.java             | 60 +------------
 .../ServicesInstallerFromAnnotation.java        | 26 +-----
 .../serviceactions/ServiceActionUtil.java       | 35 ++++----
 .../serviceactions/ServiceAndAction.java        |  7 +-
 .../serviceactions/ServiceAndActionOrder.java   | 49 +++++++++++
 7 files changed, 231 insertions(+), 99 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/312ac31b/core/metamodel/src/main/java/org/apache/isis/core/commons/compare/SequenceCompare.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/commons/compare/SequenceCompare.java b/core/metamodel/src/main/java/org/apache/isis/core/commons/compare/SequenceCompare.java
new file mode 100644
index 0000000..39b5355
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/commons/compare/SequenceCompare.java
@@ -0,0 +1,92 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.core.commons.compare;
+
+import java.util.StringTokenizer;
+
+public class SequenceCompare {
+
+    public static int compareNullLast(String sequence1, String sequence2) {
+        if (sequence1 == null && sequence2 == null) {
+            return 0;
+        }
+
+        if (sequence1 == null && sequence2 != null) {
+            return +1; // non-null before null
+        }
+        if (sequence1 != null && sequence2 == null) {
+            return -1; // non-null before null
+        }
+
+        final String[] components1 = componentsFor(sequence1);
+        final String[] components2 = componentsFor(sequence2);
+
+        final int length1 = components1.length;
+        final int length2 = components2.length;
+
+        // shouldn't happen but just in case.
+        if (length1 == 0 && length2 == 0) {
+            return 0;
+        }
+
+        // continue to loop until we run out of components.
+        int n = 0;
+        while (true) {
+            final int length = n + 1;
+            // check if run out of components in either side
+            if (length1 < length && length2 >= length) {
+                return -1; // o1 before o2
+            }
+            if (length2 < length && length1 >= length) {
+                return +1; // o2 before o1
+            }
+            if (length1 < length && length2 < length) {
+                // run out of components
+                return 0;
+            }
+            // we have this component on each side
+
+            int componentCompare = 0;
+            try {
+                final Integer c1 = Integer.valueOf(components1[n]);
+                final Integer c2 = Integer.valueOf(components2[n]);
+                componentCompare = c1.compareTo(c2);
+            } catch (final NumberFormatException nfe) {
+                // not integers compare as strings
+                componentCompare = components1[n].compareTo(components2[n]);
+            }
+
+            if (componentCompare != 0) {
+                return componentCompare;
+            }
+            // this component is the same; lets look at the next
+            n++;
+        }
+    }
+
+    private static String[] componentsFor(final String sequence) {
+        final StringTokenizer tokens = new StringTokenizer(sequence, ".", false);
+        final String[] components = new String[tokens.countTokens()];
+        for (int i = 0; tokens.hasMoreTokens(); i++) {
+            components[i] = tokens.nextToken();
+        }
+        return components;
+    }
+	
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/312ac31b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/DomainServiceMenuOrder.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/DomainServiceMenuOrder.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/DomainServiceMenuOrder.java
new file mode 100644
index 0000000..f681449
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/DomainServiceMenuOrder.java
@@ -0,0 +1,61 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.metamodel.facets.object.domainservice;
+
+import org.apache.isis.applib.annotation.DomainService;
+import org.apache.isis.applib.annotation.DomainServiceLayout;
+import org.apache.isis.core.commons.compare.SequenceCompare;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+
+public class DomainServiceMenuOrder {
+
+	public static int compare(ObjectAdapter serviceAdapter1, ObjectAdapter serviceAdapter2) {
+		
+		return SequenceCompare.compareNullLast(
+				orderOf(serviceAdapter1.getSpecification().getCorrespondingClass()),
+				orderOf(serviceAdapter2.getSpecification().getCorrespondingClass()) );
+	}
+	
+	// -- HELPER
+    
+    public static String orderOf(final Class<?> cls) {
+        final DomainServiceLayout domainServiceLayout = cls.getAnnotation(DomainServiceLayout.class);
+        String dslayoutOrder = domainServiceLayout != null ? domainServiceLayout.menuOrder(): null;
+        final DomainService domainService = cls.getAnnotation(DomainService.class);
+        String dsOrder = domainService != null ? domainService.menuOrder() : "" + Integer.MAX_VALUE;
+
+        return minimumOf(dslayoutOrder, dsOrder);
+    }
+
+    private static String minimumOf(final String dslayoutOrder, final String dsOrder) {
+        if(isUndefined(dslayoutOrder)) {
+            return dsOrder;
+        }
+        if(isUndefined(dsOrder)) {
+            return dslayoutOrder;
+        }
+        return dslayoutOrder.compareTo(dsOrder) < 0 ? dslayoutOrder : dsOrder;
+    }
+
+    private static boolean isUndefined(final String str) {
+        return str == null || str.equals("" + Integer.MAX_VALUE);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/312ac31b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layout/memberorderfacet/MemberOrderFacetComparator.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layout/memberorderfacet/MemberOrderFacetComparator.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layout/memberorderfacet/MemberOrderFacetComparator.java
index 2314454..05474af 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layout/memberorderfacet/MemberOrderFacetComparator.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layout/memberorderfacet/MemberOrderFacetComparator.java
@@ -20,8 +20,8 @@
 package org.apache.isis.core.metamodel.layout.memberorderfacet;
 
 import java.util.Comparator;
-import java.util.StringTokenizer;
 
+import org.apache.isis.core.commons.compare.SequenceCompare;
 import org.apache.isis.core.metamodel.facets.members.order.MemberOrderFacet;
 
 public class MemberOrderFacetComparator implements Comparator<MemberOrderFacet> {
@@ -47,63 +47,9 @@ public class MemberOrderFacetComparator implements Comparator<MemberOrderFacet>
         if (ensureInSameGroup && !m1.name().equals(m2.name())) {
             throw new IllegalArgumentException("Not in same group");
         }
+        
+        return SequenceCompare.compareNullLast(m1.sequence(), m2.sequence());
 
-        final String sequence1 = m1.sequence();
-        final String sequence2 = m2.sequence();
-
-        final String[] components1 = componentsFor(sequence1);
-        final String[] components2 = componentsFor(sequence2);
-
-        final int length1 = components1.length;
-        final int length2 = components2.length;
-
-        // shouldn't happen but just in case.
-        if (length1 == 0 && length2 == 0) {
-            return 0;
-        }
-
-        // continue to loop until we run out of components.
-        int n = 0;
-        while (true) {
-            final int length = n + 1;
-            // check if run out of components in either side
-            if (length1 < length && length2 >= length) {
-                return -1; // o1 before o2
-            }
-            if (length2 < length && length1 >= length) {
-                return +1; // o2 before o1
-            }
-            if (length1 < length && length2 < length) {
-                // run out of components
-                return 0;
-            }
-            // we have this component on each side
-
-            int componentCompare = 0;
-            try {
-                final Integer c1 = Integer.valueOf(components1[n]);
-                final Integer c2 = Integer.valueOf(components2[n]);
-                componentCompare = c1.compareTo(c2);
-            } catch (final NumberFormatException nfe) {
-                // not integers compare as strings
-                componentCompare = components1[n].compareTo(components2[n]);
-            }
-
-            if (componentCompare != 0) {
-                return componentCompare;
-            }
-            // this component is the same; lets look at the next
-            n++;
-        }
-    }
-
-    private static String[] componentsFor(final String sequence) {
-        final StringTokenizer tokens = new StringTokenizer(sequence, ".", false);
-        final String[] components = new String[tokens.countTokens()];
-        for (int i = 0; tokens.hasMoreTokens(); i++) {
-            components[i] = tokens.nextToken();
-        }
-        return components;
     }
 
 

http://git-wip-us.apache.org/repos/asf/isis/blob/312ac31b/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 9f2da65..e9031bb 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
@@ -46,6 +46,7 @@ import org.apache.isis.applib.annotation.DomainService;
 import org.apache.isis.applib.annotation.DomainServiceLayout;
 import org.apache.isis.applib.services.classdiscovery.ClassDiscoveryServiceUsingReflections;
 import org.apache.isis.core.commons.config.IsisConfigurationDefault;
+import org.apache.isis.core.metamodel.facets.object.domainservice.DomainServiceMenuOrder;
 import org.apache.isis.core.metamodel.util.DeweyOrderComparator;
 
 import static com.google.common.base.Predicates.and;
@@ -220,7 +221,7 @@ public class ServicesInstallerFromAnnotation extends ServicesInstallerAbstract {
         final List<Class<?>> domainServiceClasses = Lists.newArrayList(Iterables.filter(domainServiceTypes, instantiatable()));
         for (final Class<?> cls : domainServiceClasses) {
 
-            final String order = orderOf(cls);
+            final String order = DomainServiceMenuOrder.orderOf(cls);
             // we want the class name in order to instantiate it
             // (and *not* the value of the @DomainServiceLayout(named=...) annotation attribute)
             final String fullyQualifiedClassName = cls.getName();
@@ -234,29 +235,6 @@ public class ServicesInstallerFromAnnotation extends ServicesInstallerAbstract {
 
     //region > helpers: orderOf, nameOf, asList
 
-    private static String orderOf(final Class<?> cls) {
-        final DomainServiceLayout domainServiceLayout = cls.getAnnotation(DomainServiceLayout.class);
-        String dslayoutOrder = domainServiceLayout != null ? domainServiceLayout.menuOrder(): null;
-        final DomainService domainService = cls.getAnnotation(DomainService.class);
-        String dsOrder = domainService != null ? domainService.menuOrder() : "" + Integer.MAX_VALUE;
-
-        return minimumOf(dslayoutOrder, dsOrder);
-    }
-
-    private static String minimumOf(final String dslayoutOrder, final String dsOrder) {
-        if(isUndefined(dslayoutOrder)) {
-            return dsOrder;
-        }
-        if(isUndefined(dsOrder)) {
-            return dslayoutOrder;
-        }
-        return dslayoutOrder.compareTo(dsOrder) < 0 ? dslayoutOrder : dsOrder;
-    }
-
-    private static boolean isUndefined(final String str) {
-        return str == null || str.equals("" + Integer.MAX_VALUE);
-    }
-
     private static String nameOf(final Class<?> cls) {
         final DomainServiceLayout domainServiceLayout = cls.getAnnotation(DomainServiceLayout.class);
         String name = domainServiceLayout != null ? domainServiceLayout.named(): null;

http://git-wip-us.apache.org/repos/asf/isis/blob/312ac31b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java
index 9d7569c..efc2ea4 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java
@@ -19,27 +19,12 @@
 
 package org.apache.isis.viewer.wicket.ui.components.actionmenu.serviceactions;
 
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import com.google.common.base.Strings;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-
-import org.apache.wicket.AttributeModifier;
-import org.apache.wicket.Component;
-import org.apache.wicket.MarkupContainer;
-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.wicket.markup.html.panel.Fragment;
-import org.apache.wicket.model.Model;
-import org.apache.isis.applib.annotation.ActionSemantics;
 import org.apache.isis.applib.annotation.NatureOfService;
-import org.apache.isis.applib.annotation.SemanticsOf;
 import org.apache.isis.applib.filter.Filters;
 import org.apache.isis.applib.services.i18n.TranslationService;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
@@ -58,8 +43,21 @@ import org.apache.isis.core.runtime.system.session.IsisSessionFactoryBuilder;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
 import org.apache.isis.viewer.wicket.model.models.ServiceActionsModel;
 import org.apache.isis.viewer.wicket.ui.components.actionmenu.CssClassFaBehavior;
-import org.apache.isis.viewer.wicket.ui.panels.PanelUtil;
 import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
+import org.apache.wicket.AttributeModifier;
+import org.apache.wicket.Component;
+import org.apache.wicket.MarkupContainer;
+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.wicket.markup.html.panel.Fragment;
+import org.apache.wicket.model.Model;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
 
 import de.agilecoders.wicket.core.markup.html.bootstrap.components.TooltipBehavior;
 import de.agilecoders.wicket.core.markup.html.bootstrap.components.TooltipConfig;
@@ -206,6 +204,9 @@ public final class ServiceActionUtil {
             collateServiceActions(serviceAdapter, ActionType.PROTOTYPE, serviceActions);
         }
 
+        //XXX ISIS-1715 honor member order
+        Collections.sort(serviceActions);
+        
         final Set<String> serviceNamesInOrder = serviceNamesInOrder(serviceAdapters, serviceActions);
         final Map<String, List<ServiceAndAction>> serviceActionsByName = groupByServiceName(serviceActions);
 

http://git-wip-us.apache.org/repos/asf/isis/blob/312ac31b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceAndAction.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceAndAction.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceAndAction.java
index 8aecb15..65ec519 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceAndAction.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceAndAction.java
@@ -19,7 +19,7 @@ package org.apache.isis.viewer.wicket.ui.components.actionmenu.serviceactions;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
 
-class ServiceAndAction {
+class ServiceAndAction implements Comparable<ServiceAndAction> {
     final String serviceName;
     final EntityModel serviceEntityModel;
     final ObjectAction objectAction;
@@ -41,4 +41,9 @@ class ServiceAndAction {
     public String toString() {
         return serviceName + " ~ " + objectAction.getIdentifier().toFullIdentityString();
     }
+
+	@Override
+	public int compareTo(ServiceAndAction other) {
+		return ServiceAndActionOrder.compare(this, other);
+	}
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/312ac31b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceAndActionOrder.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceAndActionOrder.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceAndActionOrder.java
new file mode 100644
index 0000000..19be3e1
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceAndActionOrder.java
@@ -0,0 +1,49 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.viewer.wicket.ui.components.actionmenu.serviceactions;
+
+import org.apache.isis.core.metamodel.facets.members.order.MemberOrderFacet;
+import org.apache.isis.core.metamodel.facets.object.domainservice.DomainServiceMenuOrder;
+import org.apache.isis.core.metamodel.layout.memberorderfacet.MemberOrderFacetComparator;
+
+class ServiceAndActionOrder {
+
+	private final static MemberOrderFacetComparator memberOrder = 
+			new MemberOrderFacetComparator(false);
+	
+	public static int compare(ServiceAndAction a, ServiceAndAction b) {
+		
+		int c  = a.serviceName.compareTo(b.serviceName);
+		if(c!=0)
+			return c;
+		
+		c = DomainServiceMenuOrder.compare(
+				a.serviceEntityModel.getObject(),
+				b.serviceEntityModel.getObject() );
+		if(c!=0)
+			return c;
+		
+		return memberOrder.compare(
+				a.objectAction.getFacet(MemberOrderFacet.class), 
+				b.objectAction.getFacet(MemberOrderFacet.class) );
+		
+	}
+
+}