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 2013/07/24 07:43:26 UTC

[2/4] git commit: ISIS-475: dynamic layouts from JSON

ISIS-475: dynamic layouts from JSON

- new LayoutMetadataReader interface
- new impls for properties and for json
- new classes representing LayoutMetadata (serializable to JSON)
- FacetedMethodsBuilder now uses the new LayoutMetadataReader interface
  - searches for json impl, then properties impl
- utility classes/methods (ObjectAssociations, ObjectSpecifications, EntityActionUtil.memberOrderOf) moved from viewer-wicket to core-metamodel
- example layout for ToDoItem converted to *.isis.json
- DeveloperUtilitiesService allows ability to download layout
- factored out MemberOrderFacetComparator from MemberOrderComparator, so can reuse.


also:
- ArrayUtils and ArrayUtil classes removed
- combined Resources utility class with ResourceUtil utility class, unused methods removed
- unused methods in PropertyUtil removed

also:
- little bit of CSS cosmetic change in table td left borders


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

Branch: refs/heads/master
Commit: a5ad5dcf4502e94cdb0e6931d04cd3c01ade19c3
Parents: 5fa6691
Author: Dan Haywood <da...@apache.org>
Authored: Mon Jul 22 12:30:01 2013 +0100
Committer: Dan Haywood <da...@apache.org>
Committed: Mon Jul 22 12:30:01 2013 +0100

----------------------------------------------------------------------
 .../viewer/wicket/model/models/EntityModel.java |   2 +-
 .../wicket/model/util/ObjectAssociations.java   |  96 ------
 .../wicket/model/util/ObjectSpecifications.java |  87 ------
 .../model/util/ObjectSpecificationsTest.java    |  82 ------
 .../additionallinks/EntityActionUtil.java       |  37 +--
 .../entity/combined/EntityCombinedPanel.java    |   2 +-
 .../entity/header/EntityHeaderPanel.java        |   2 +-
 .../entity/properties/EntityPropertiesForm.java |  12 +-
 .../viewer/wicket/ui/pages/PageAbstract.css     |   3 +
 .../devutils/DeveloperUtilitiesService.java     |  23 +-
 .../ObjectResolveAndObjectChangedEnhancer.java  |   4 +-
 .../ObjectResolveAndObjectChangedEnhancer.java  |   4 +-
 core/metamodel/pom.xml                          |   5 +
 .../isis/core/commons/lang/ArrayUtil.java       |  33 ++-
 .../isis/core/commons/lang/ArrayUtils.java      | 133 ---------
 .../isis/core/commons/lang/PropertyUtil.java    |  20 --
 .../isis/core/commons/lang/ResourceUtil.java    | 111 +++++++
 .../isis/core/commons/lang/Resources.java       | 122 --------
 .../memberorderfacet/MemberOrderComparator.java |  90 +-----
 .../MemberOrderFacetComparator.java             | 113 ++++++++
 .../metamodel/layoutmetadata/ActionRepr.java    |  20 ++
 .../metamodel/layoutmetadata/ColumnRepr.java    |  25 ++
 .../layoutmetadata/LayoutMetadata.java          |  40 +++
 .../layoutmetadata/LayoutMetadataReader.java    |  47 +++
 .../layoutmetadata/MemberGroupRepr.java         |  23 ++
 .../metamodel/layoutmetadata/MemberRepr.java    |  23 ++
 .../json/LayoutMetadataReaderFromJson.java      | 290 +++++++++++++++++++
 .../LayoutMetadataReaderFromPropertyFile.java   |  36 +++
 .../DeveloperUtilitiesServiceDefault.java       | 114 +++++++-
 .../metamodel/spec/ObjectSpecifications.java    |  86 ++++++
 .../metamodel/spec/feature/ObjectActions.java   |  23 ++
 .../spec/feature/ObjectAssociations.java        |  94 ++++++
 .../specimpl/FacetedMethodsBuilder.java         |  43 ++-
 .../imageloader/awt/TemplateImageLoaderAwt.java |   4 +-
 .../core/webapp/content/ResourceServlet.java    |   4 +-
 .../json/ExampleDomainObject.java               |  21 ++
 .../LayoutMetadataReaderFromJsonTest_read.java  |  57 ++++
 ...MetadataReaderFromJsonTest_readMetadata.java |  71 +++++
 .../spec/ObjectSpecificationsTest.java          |  84 ++++++
 .../json/ExampleDomainObject.isis.json          |  79 +++++
 .../json/ExampleDomainObject.isis.properties    |  80 +++++
 core/pom.xml                                    |   5 +
 .../apache/isis/core/webserver/WebServer.java   |   4 +-
 .../webserver/internal/OptionHandlerPort.java   |   4 +-
 .../internal/OptionHandlerStartupMode.java      |   4 +-
 .../src/main/java/dom/todo/ToDoItem.isis.json   |  79 +++++
 .../main/java/dom/todo/ToDoItem.isis.properties |  76 +++++
 .../dom/src/main/java/dom/todo/ToDoItem.layout  |  58 ----
 .../java/app/services/DeveloperUtilities.java   |  14 +-
 49 files changed, 1741 insertions(+), 748 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/a5ad5dcf/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityModel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityModel.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityModel.java
index 23358e3..fb13569 100644
--- a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityModel.java
+++ b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityModel.java
@@ -39,12 +39,12 @@ import org.apache.isis.core.metamodel.facets.object.bookmarkable.BookmarkPolicyF
 import org.apache.isis.core.metamodel.spec.ObjectSpecId;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
+import org.apache.isis.core.metamodel.spec.ObjectSpecifications.MemberGroupLayoutHint;
 import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
 import org.apache.isis.core.runtime.system.context.IsisContext;
 import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
 import org.apache.isis.viewer.wicket.model.mementos.PageParameterNames;
 import org.apache.isis.viewer.wicket.model.mementos.PropertyMemento;
-import org.apache.isis.viewer.wicket.model.util.ObjectSpecifications.MemberGroupLayoutHint;
 
 /**
  * Backing model to represent a {@link ObjectAdapter}.

http://git-wip-us.apache.org/repos/asf/isis/blob/a5ad5dcf/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/ObjectAssociations.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/ObjectAssociations.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/ObjectAssociations.java
deleted file mode 100644
index 1e419e0..0000000
--- a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/ObjectAssociations.java
+++ /dev/null
@@ -1,96 +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.viewer.wicket.model.util;
-
-import java.util.List;
-import java.util.Map;
-
-import com.google.common.base.Function;
-import com.google.common.base.Strings;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
-import org.apache.isis.core.metamodel.facets.members.order.MemberOrderFacet;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
-import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
-
-public final class ObjectAssociations {
-
-    private ObjectAssociations() {
-    }
-
-    public static Function<String, OneToOneAssociation> fromId(final ObjectSpecification noSpec) {
-        return new Function<String, OneToOneAssociation>() {
-            @Override
-            public OneToOneAssociation apply(final String from) {
-                return (OneToOneAssociation) noSpec.getAssociation(from);
-            }
-        };
-    }
-
-    public static Map<String, List<ObjectAssociation>> groupByMemberOrderName(List<ObjectAssociation> associations) {
-        Map<String, List<ObjectAssociation>> associationsByGroup = Maps.newHashMap();
-        for(ObjectAssociation association: associations) {
-            addAssociationIntoGroup(associationsByGroup, association);
-        }
-        return associationsByGroup;
-    }
-
-    private static void addAssociationIntoGroup(Map<String, List<ObjectAssociation>> associationsByGroup, ObjectAssociation association) {
-        final MemberOrderFacet memberOrderFacet = association.getFacet(MemberOrderFacet.class);
-        if(memberOrderFacet != null) {
-            final String name = memberOrderFacet.name();
-            if(!Strings.isNullOrEmpty(name)) {
-                getFrom(associationsByGroup, name).add(association);
-                return;
-            }
-        }
-        getFrom(associationsByGroup, "General").add(association);
-    }
-
-    private static List<ObjectAssociation> getFrom(Map<String, List<ObjectAssociation>> associationsByGroup, final String groupName) {
-        List<ObjectAssociation> list = associationsByGroup.get(groupName);
-        if(list == null) {
-            list = Lists.newArrayList();
-            associationsByGroup.put(groupName, list);
-        }
-        return list;
-    }
-
-    public static Function<ObjectAssociation, String> toName() {
-        return new Function<ObjectAssociation, String>() {
-            @Override
-            public String apply(final ObjectAssociation oa) {
-                return oa.getName();
-            }
-        };
-    }
-
-    public static Function<ObjectAssociation, String> toId() {
-        return new Function<ObjectAssociation, String>() {
-            @Override
-            public String apply(final ObjectAssociation oa) {
-                return oa.getId();
-            }
-        };
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/a5ad5dcf/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/ObjectSpecifications.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/ObjectSpecifications.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/ObjectSpecifications.java
deleted file mode 100644
index 439cf12..0000000
--- a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/ObjectSpecifications.java
+++ /dev/null
@@ -1,87 +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.viewer.wicket.model.util;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-
-import com.google.common.collect.Lists;
-
-import org.apache.isis.core.metamodel.facets.object.membergroups.MemberGroupLayoutFacet;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-
-
-public final class ObjectSpecifications {
-
-    private ObjectSpecifications() {
-    }
-
-    public enum MemberGroupLayoutHint {
-        LEFT,
-        MIDDLE,
-        RIGHT;
-    }
-
-    public static List<String> orderByMemberGroups(ObjectSpecification objSpec, Set<String> groupNamesToOrder, MemberGroupLayoutHint memberGroupLayoutHint) {
-        final MemberGroupLayoutFacet facet = objSpec.getFacet(MemberGroupLayoutFacet.class);
-        final List<String> leftColumnGroupNames = Lists.newArrayList(groupNamesToOrder);
-        
-        // not expected to happen
-        if(facet == null) {
-            return leftColumnGroupNames;
-        }
-        
-        if(memberGroupLayoutHint == MemberGroupLayoutHint.MIDDLE) {
-            return facet.getColumnSpans().getMiddle()>0? facet.getMiddle(): Collections.<String>emptyList();
-        }
-        if(memberGroupLayoutHint == MemberGroupLayoutHint.RIGHT) {
-            return facet.getColumnSpans().getRight()>0? facet.getRight(): Collections.<String>emptyList();
-        }
-        
-        // else left; per the requested order, including any groups not mentioned in either list, 
-        // but excluding any groups in the middle or right columns
-        final List<String> groupNamedInRequiredOrder = facet.getLeft();
-        final List<String> order = order(leftColumnGroupNames, groupNamedInRequiredOrder);
-        
-        if(facet.getColumnSpans().getMiddle() > 0) {
-            order.removeAll(facet.getMiddle());
-        }
-        if(facet.getColumnSpans().getRight() > 0) {
-            order.removeAll(facet.getRight());
-        }
-        return order;
-    }
-
-    static List<String> order(final List<String> valuesToOrder, final List<String> valuesInRequiredOrder) {
-        int i=0;
-        for(String memberGroup: valuesInRequiredOrder) {
-            if(valuesToOrder.contains(memberGroup)) {
-                // move to next position
-                valuesToOrder.remove(memberGroup);
-                valuesToOrder.add(i++, memberGroup);
-            }
-        }
-        
-        return valuesToOrder;
-    }
-
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/a5ad5dcf/component/viewer/wicket/model/src/test/java/org/apache/isis/viewer/wicket/model/util/ObjectSpecificationsTest.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/test/java/org/apache/isis/viewer/wicket/model/util/ObjectSpecificationsTest.java b/component/viewer/wicket/model/src/test/java/org/apache/isis/viewer/wicket/model/util/ObjectSpecificationsTest.java
deleted file mode 100644
index 4894e63..0000000
--- a/component/viewer/wicket/model/src/test/java/org/apache/isis/viewer/wicket/model/util/ObjectSpecificationsTest.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.viewer.wicket.model.util;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-
-import com.google.common.collect.Lists;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class ObjectSpecificationsTest {
-    
-    @Parameters
-    public static Collection<Object[][]> data() {
-        return Arrays.asList(new Object[][][]{
-                {
-                    {"X","Y","Z"}, {"X","Y","Z"}, {"X","Y","Z"},
-                },
-                {
-                    {"X","Y","Z"}, {"A","B","C"}, {"X","Y","Z"}
-                },
-                {
-                    {"X","Y","Z"}, {"Z","B","C"}, {"Z","X","Y"}
-                },
-                {
-                    {"X","Y","Z"}, {"Z","Y","X"}, {"Z","Y","X"}
-                },
-                {
-                    {"Dates","General"}, {"General"}, {"General","Dates"}
-                },
-        });
-    }
-
-    private static List<String> asListOfStrings(Object[] values) {
-        final List<String> list = Lists.newArrayList();
-        for(Object value: values) {
-            list.add((String) value);
-        }
-        return list;
-    }
-
-    private final List<String> valuesToOrder;
-    private final List<String> valuesInRequiredOrder;
-    private final List<String> expected;
-     
-    public ObjectSpecificationsTest(Object[] valuesToOrder, Object[] valuesInRequiredOrder, Object[] expected) {
-        this.valuesToOrder = asListOfStrings(valuesToOrder);
-        this.valuesInRequiredOrder = asListOfStrings(valuesInRequiredOrder);
-        this.expected = asListOfStrings(expected);
-    }
-    
-    @Test
-    public void test() throws Exception {
-        assertThat(ObjectSpecifications.order(valuesToOrder, valuesInRequiredOrder), is(expected));
-    }
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/a5ad5dcf/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/EntityActionUtil.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/EntityActionUtil.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/EntityActionUtil.java
index ce01bbd..da47558 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/EntityActionUtil.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/additionallinks/EntityActionUtil.java
@@ -18,10 +18,11 @@
  */
 package org.apache.isis.viewer.wicket.ui.components.additionallinks;
 
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.List;
 
 import com.google.common.base.Function;
-import com.google.common.base.Strings;
 import com.google.common.collect.Lists;
 
 import org.apache.wicket.Session;
@@ -34,11 +35,13 @@ import org.apache.isis.core.commons.authentication.AuthenticationSessionProvider
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
 import org.apache.isis.core.metamodel.facets.members.order.MemberOrderFacet;
+import org.apache.isis.core.metamodel.layout.memberorderfacet.MemberOrderFacetComparator;
 import org.apache.isis.core.metamodel.spec.ActionType;
 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.ObjectActionContainer.Contributed;
 import org.apache.isis.core.metamodel.spec.feature.ObjectActionFilters;
+import org.apache.isis.core.metamodel.spec.feature.ObjectActions;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
 import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
 import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
@@ -51,6 +54,8 @@ public final class EntityActionUtil {
     
     private EntityActionUtil(){}
 
+    private final static MemberOrderFacetComparator memberOrderFacetComparator = new MemberOrderFacetComparator(false);
+    
     public static List<LinkAndLabel> entityActions(EntityModel entityModel, ObjectAssociation association) {
         final ObjectSpecification adapterSpec = entityModel.getTypeOfSpecification();
         final ObjectAdapter adapter = entityModel.load(ConcurrencyChecking.NO_CHECK);
@@ -58,7 +63,15 @@ public final class EntityActionUtil {
         
         @SuppressWarnings("unchecked")
         final List<ObjectAction> userActions = adapterSpec.getObjectActions(ActionType.USER, Contributed.INCLUDED,
-                Filters.and(EntityActionUtil.memberOrderOf(association), EntityActionUtil.dynamicallyVisibleFor(adapter)));
+                Filters.and(ObjectActions.memberOrderOf(association), EntityActionUtil.dynamicallyVisibleFor(adapter)));
+        Collections.sort(userActions, new Comparator<ObjectAction>() {
+
+            @Override
+            public int compare(ObjectAction o1, ObjectAction o2) {
+                final MemberOrderFacet m1 = o1.getFacet(MemberOrderFacet.class);
+                final MemberOrderFacet m2 = o2.getFacet(MemberOrderFacet.class);
+                return memberOrderFacetComparator.compare(m1, m2);
+            }});
         
         final CssMenuLinkFactory linkFactory = new EntityActionLinkFactory(entityModel);
     
@@ -76,24 +89,4 @@ public final class EntityActionUtil {
         return ObjectActionFilters.dynamicallyVisible(authSession, adapter, Where.ANYWHERE);
     }
 
-    private static Filter<ObjectAction> memberOrderOf(ObjectAssociation association) {
-        final String collectionName = association.getName();
-        final String collectionId = association.getId();
-        return new Filter<ObjectAction>() {
-    
-            @Override
-            public boolean accept(ObjectAction t) {
-                final MemberOrderFacet memberOrderFacet = t.getFacet(MemberOrderFacet.class);
-                if(memberOrderFacet == null) {
-                    return false; 
-                }
-                final String memberOrderName = memberOrderFacet.name();
-                if(Strings.isNullOrEmpty(memberOrderName)) {
-                    return false;
-                }
-                return memberOrderName.equalsIgnoreCase(collectionName) || memberOrderName.equalsIgnoreCase(collectionId);
-            }
-        };
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/a5ad5dcf/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/combined/EntityCombinedPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/combined/EntityCombinedPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/combined/EntityCombinedPanel.java
index 2840ce2..46bbfeb 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/combined/EntityCombinedPanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/combined/EntityCombinedPanel.java
@@ -24,8 +24,8 @@ import org.apache.wicket.Component;
 import org.apache.isis.applib.annotation.MemberGroupLayout.ColumnSpans;
 import org.apache.isis.core.metamodel.facets.members.cssclass.CssClassFacet;
 import org.apache.isis.core.metamodel.facets.object.membergroups.MemberGroupLayoutFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecifications.MemberGroupLayoutHint;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
-import org.apache.isis.viewer.wicket.model.util.ObjectSpecifications.MemberGroupLayoutHint;
 import org.apache.isis.viewer.wicket.ui.ComponentType;
 import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
 import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;

http://git-wip-us.apache.org/repos/asf/isis/blob/a5ad5dcf/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/header/EntityHeaderPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/header/EntityHeaderPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/header/EntityHeaderPanel.java
index 326a24b..e0ff3d3 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/header/EntityHeaderPanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/header/EntityHeaderPanel.java
@@ -39,13 +39,13 @@ import org.apache.isis.core.metamodel.spec.feature.ObjectActionContainer.Contrib
 import org.apache.isis.core.metamodel.spec.feature.ObjectActionFilters;
 import org.apache.isis.core.metamodel.spec.feature.ObjectActions;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociations;
 import org.apache.isis.core.runtime.system.DeploymentType;
 import org.apache.isis.core.runtime.system.context.IsisContext;
 import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
 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.ImageResourceCache;
-import org.apache.isis.viewer.wicket.model.util.ObjectAssociations;
 import org.apache.isis.viewer.wicket.ui.ComponentFactory;
 import org.apache.isis.viewer.wicket.ui.ComponentType;
 import org.apache.isis.viewer.wicket.ui.components.actions.ActionInvokeHandler;

http://git-wip-us.apache.org/repos/asf/isis/blob/a5ad5dcf/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesForm.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesForm.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesForm.java
index 6861344..bdd4b6d 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesForm.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesForm.java
@@ -48,8 +48,10 @@ import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChec
 import org.apache.isis.core.metamodel.adapter.version.ConcurrencyException;
 import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.ObjectSpecifications;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAssociationFilters;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociations;
 import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
 import org.apache.isis.core.runtime.memento.Memento;
 import org.apache.isis.core.runtime.system.context.IsisContext;
@@ -57,8 +59,6 @@ import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
 import org.apache.isis.viewer.wicket.model.mementos.PropertyMemento;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
 import org.apache.isis.viewer.wicket.model.models.ScalarModel;
-import org.apache.isis.viewer.wicket.model.util.ObjectAssociations;
-import org.apache.isis.viewer.wicket.model.util.ObjectSpecifications;
 import org.apache.isis.viewer.wicket.ui.ComponentType;
 import org.apache.isis.viewer.wicket.ui.components.widgets.formcomponent.CancelHintRequired;
 import org.apache.isis.viewer.wicket.ui.errors.JGrowlBehaviour;
@@ -116,7 +116,7 @@ class EntityPropertiesForm extends FormAbstract<ObjectAdapter> {
         final ObjectAdapter adapter = entityModel.getObject();
         final ObjectSpecification objSpec = adapter.getSpecification();
 
-        final List<ObjectAssociation> associations = visibleAssociations(adapter, objSpec, Where.OBJECT_FORMS);
+        final List<ObjectAssociation> associations = visibleProperties(adapter, objSpec, Where.OBJECT_FORMS);
 
         final RepeatingView memberGroupRv = new RepeatingView(ID_MEMBER_GROUP);
         add(memberGroupRv);
@@ -160,12 +160,12 @@ class EntityPropertiesForm extends FormAbstract<ObjectAdapter> {
 		getComponentFactoryRegistry().addOrReplaceComponent(container, ID_PROPERTY, ComponentType.SCALAR_NAME_AND_VALUE, scalarModel);
 	}
 
-    private List<ObjectAssociation> visibleAssociations(final ObjectAdapter adapter, final ObjectSpecification objSpec, Where where) {
-        return objSpec.getAssociations(visibleAssociationFilter(adapter, where));
+    private List<ObjectAssociation> visibleProperties(final ObjectAdapter adapter, final ObjectSpecification objSpec, Where where) {
+        return objSpec.getAssociations(visiblePropertyFilter(adapter, where));
     }
 
     @SuppressWarnings("unchecked")
-    private Filter<ObjectAssociation> visibleAssociationFilter(final ObjectAdapter adapter, Where where) {
+    private Filter<ObjectAssociation> visiblePropertyFilter(final ObjectAdapter adapter, Where where) {
         return Filters.and(ObjectAssociationFilters.PROPERTIES, ObjectAssociationFilters.dynamicallyVisible(getAuthenticationSession(), adapter, where));
     }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/a5ad5dcf/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.css
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.css b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.css
index b2881d4..3c3e50a 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.css
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.css
@@ -521,6 +521,9 @@ tr.section td {
 	padding-top: 0.75em;
 }
 
+table.contents td {
+	border-left: 1px solid #DDD;
+}
 
 /*************** Styling Entity Forms and Parameters ********************/
 

http://git-wip-us.apache.org/repos/asf/isis/blob/a5ad5dcf/core/applib/src/main/java/org/apache/isis/applib/services/devutils/DeveloperUtilitiesService.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/devutils/DeveloperUtilitiesService.java b/core/applib/src/main/java/org/apache/isis/applib/services/devutils/DeveloperUtilitiesService.java
index fad0a5d..3b7c9ea 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/devutils/DeveloperUtilitiesService.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/devutils/DeveloperUtilitiesService.java
@@ -22,19 +22,38 @@ import org.apache.isis.applib.annotation.MemberOrder;
 import org.apache.isis.applib.annotation.Named;
 import org.apache.isis.applib.annotation.NotInServiceMenu;
 import org.apache.isis.applib.annotation.Prototype;
+import org.apache.isis.applib.value.Blob;
 import org.apache.isis.applib.value.Clob;
 
 @Named("Developer Utilities")
 public interface DeveloperUtilitiesService {
 
-    @Prototype
+    @MemberOrder(sequence="1")
     @ActionSemantics(Of.SAFE)
+    @Prototype
     public Clob downloadMetaModel();
+
+    /**
+     * Downloads a zip of the layout of all domain classes.
+     */
+    @ActionSemantics(Of.SAFE)
+    @MemberOrder(sequence="3")
+    @Prototype
+    public Blob downloadLayouts();
+
+    /**
+     * Download the JSON layout of the domain object's type.
+     */
+    @NotInServiceMenu
+    @ActionSemantics(Of.SAFE)
+    @MemberOrder(sequence="2")
+    @Prototype
+    public Clob downloadLayout(Object domainObject);
     
     @NotInServiceMenu
     @ActionSemantics(Of.SAFE)
     @MemberOrder(sequence="99")
     @Prototype
-    public Object refresh(Object domainObject);
+    public Object refreshLayout(Object domainObject);
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/a5ad5dcf/core/bytecode-cglib/src/main/java/org/apache/isis/core/bytecode/cglib/ObjectResolveAndObjectChangedEnhancer.java
----------------------------------------------------------------------
diff --git a/core/bytecode-cglib/src/main/java/org/apache/isis/core/bytecode/cglib/ObjectResolveAndObjectChangedEnhancer.java b/core/bytecode-cglib/src/main/java/org/apache/isis/core/bytecode/cglib/ObjectResolveAndObjectChangedEnhancer.java
index 1ad150f..672d322 100644
--- a/core/bytecode-cglib/src/main/java/org/apache/isis/core/bytecode/cglib/ObjectResolveAndObjectChangedEnhancer.java
+++ b/core/bytecode-cglib/src/main/java/org/apache/isis/core/bytecode/cglib/ObjectResolveAndObjectChangedEnhancer.java
@@ -28,7 +28,7 @@ import net.sf.cglib.proxy.Enhancer;
 import net.sf.cglib.proxy.MethodInterceptor;
 import net.sf.cglib.proxy.MethodProxy;
 
-import org.apache.isis.core.commons.lang.ArrayUtils;
+import org.apache.isis.core.commons.lang.ArrayUtil;
 import org.apache.isis.core.metamodel.facets.ImperativeFacetUtils;
 import org.apache.isis.core.metamodel.facets.ImperativeFacetUtils.ImperativeFacetFlags;
 import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
@@ -98,7 +98,7 @@ public class ObjectResolveAndObjectChangedEnhancer extends ObjectResolveAndObjec
         if (enhancer == null) {
             enhancer = new Enhancer();
             enhancer.setSuperclass(cls);
-            enhancer.setInterfaces(ArrayUtils.combine(cls.getInterfaces(), new Class<?>[] { CglibEnhanced.class }));
+            enhancer.setInterfaces(ArrayUtil.combine(cls.getInterfaces(), new Class<?>[] { CglibEnhanced.class }));
             enhancer.setCallback(callback);
             enhancerByClass.put(cls, enhancer);
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/a5ad5dcf/core/bytecode-javassist/src/main/java/org/apache/isis/core/bytecode/javassist/ObjectResolveAndObjectChangedEnhancer.java
----------------------------------------------------------------------
diff --git a/core/bytecode-javassist/src/main/java/org/apache/isis/core/bytecode/javassist/ObjectResolveAndObjectChangedEnhancer.java b/core/bytecode-javassist/src/main/java/org/apache/isis/core/bytecode/javassist/ObjectResolveAndObjectChangedEnhancer.java
index 0c1d6fb..2b11eae 100644
--- a/core/bytecode-javassist/src/main/java/org/apache/isis/core/bytecode/javassist/ObjectResolveAndObjectChangedEnhancer.java
+++ b/core/bytecode-javassist/src/main/java/org/apache/isis/core/bytecode/javassist/ObjectResolveAndObjectChangedEnhancer.java
@@ -27,7 +27,7 @@ import javassist.util.proxy.ProxyFactory;
 import javassist.util.proxy.ProxyObject;
 
 import org.apache.isis.core.commons.exceptions.IsisException;
-import org.apache.isis.core.commons.lang.ArrayUtils;
+import org.apache.isis.core.commons.lang.ArrayUtil;
 import org.apache.isis.core.metamodel.facets.ImperativeFacetUtils;
 import org.apache.isis.core.metamodel.facets.ImperativeFacetUtils.ImperativeFacetFlags;
 import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
@@ -86,7 +86,7 @@ public class ObjectResolveAndObjectChangedEnhancer extends ObjectResolveAndObjec
 
         final ProxyFactory proxyFactory = new ProxyFactory();
         proxyFactory.setSuperclass(cls);
-        proxyFactory.setInterfaces(ArrayUtils.combine(cls.getInterfaces(), new Class<?>[] { JavassistEnhanced.class }));
+        proxyFactory.setInterfaces(ArrayUtil.combine(cls.getInterfaces(), new Class<?>[] { JavassistEnhanced.class }));
 
         proxyFactory.setFilter(new MethodFilter() {
             @Override

http://git-wip-us.apache.org/repos/asf/isis/blob/a5ad5dcf/core/metamodel/pom.xml
----------------------------------------------------------------------
diff --git a/core/metamodel/pom.xml b/core/metamodel/pom.xml
index 85d97a1..95321bd 100644
--- a/core/metamodel/pom.xml
+++ b/core/metamodel/pom.xml
@@ -92,6 +92,11 @@
             <artifactId>guice</artifactId>
         </dependency>
 
+          <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+          </dependency>
+
         <dependency>
             <groupId>org.apache.geronimo.specs</groupId>
             <artifactId>geronimo-servlet_2.5_spec</artifactId>

http://git-wip-us.apache.org/repos/asf/isis/blob/a5ad5dcf/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ArrayUtil.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ArrayUtil.java b/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ArrayUtil.java
index 643419d..3ff1662 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ArrayUtil.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ArrayUtil.java
@@ -22,6 +22,9 @@ package org.apache.isis.core.commons.lang;
 import java.lang.reflect.Array;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 
 import org.apache.isis.core.commons.exceptions.IsisException;
 
@@ -36,7 +39,7 @@ public final class ArrayUtil {
             return (Object[]) option;
         }
         if (arrayType == char.class) {
-            return ArrayUtils.convertCharToCharacterArray(option);
+            return ArrayUtil.convertCharToCharacterArray(option);
         } else {
             return convertPrimitiveToObjectArray(arrayType, option);
         }
@@ -68,4 +71,32 @@ public final class ArrayUtil {
         return convertedArray;
     }
 
+    public static Object[] convertCharToCharacterArray(final Object originalArray) {
+        final char[] original = (char[]) originalArray;
+        final int len = original.length;
+        final Character[] converted = new Character[len];
+        for (int i = 0; i < converted.length; i++) {
+            converted[i] = Character.valueOf(original[i]);
+        }
+        return converted;
+    }
+
+    public static <T> T[] combine(final T[]... arrays) {
+        final List<T> combinedList = new ArrayList<T>();
+        for (final T[] array : arrays) {
+            for (final T t : array) {
+                combinedList.add(t);
+            }
+        }
+        return combinedList.toArray(arrays[0]); // using 1st element of arrays
+                                                // to specify the type
+    }
+
+    public static String[] append(final String[] args, final String... moreArgs) {
+        final ArrayList<String> argList = new ArrayList<String>();
+        argList.addAll(Arrays.asList(args));
+        argList.addAll(Arrays.asList(moreArgs));
+        return argList.toArray(new String[] {});
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/a5ad5dcf/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ArrayUtils.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ArrayUtils.java b/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ArrayUtils.java
deleted file mode 100644
index 3d6cf76..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ArrayUtils.java
+++ /dev/null
@@ -1,133 +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.commons.lang;
-
-import java.lang.reflect.Array;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
-
-public final class ArrayUtils {
-
-    private ArrayUtils() {
-    }
-
-    public static Object[] convertCharToCharacterArray(final Object originalArray) {
-        final char[] original = (char[]) originalArray;
-        final int len = original.length;
-        final Character[] converted = new Character[len];
-        for (int i = 0; i < converted.length; i++) {
-            converted[i] = Character.valueOf(original[i]);
-        }
-        return converted;
-    }
-
-    public static <T> T[] combine(final T[]... arrays) {
-        final List<T> combinedList = new ArrayList<T>();
-        for (final T[] array : arrays) {
-            for (final T t : array) {
-                combinedList.add(t);
-            }
-        }
-        return combinedList.toArray(arrays[0]); // using 1st element of arrays
-                                                // to specify the type
-    }
-
-    /**
-     * Creates a mutable copy of the provided array.
-     */
-    public static <T> List<T> asList(final T[] items) {
-        final List<T> list = new ArrayList<T>();
-        for (final T item : items) {
-            list.add(item);
-        }
-        return list;
-    }
-
-    /**
-     * Creates a mutable copy of the provided array, eliminating duplicates.
-     * 
-     * <p>
-     * The order of the items will be preserved.
-     */
-    public static <T> Set<T> asOrderedSet(final T[] items) {
-        final LinkedHashSet<T> list = new LinkedHashSet<T>();
-        if (items != null) {
-            for (final T item : items) {
-                list.add(item);
-            }
-        }
-        return list;
-    }
-
-    /**
-     * Creates a mutable list of the provided array, also appending the
-     * additional element(s).
-     */
-    public static <T> List<T> concat(final T[] elements, final T... elementsToAppend) {
-        final List<T> result = new ArrayList<T>();
-        for (final T element : elements) {
-            result.add(element);
-        }
-        for (final T element : elementsToAppend) {
-            if (element != null) {
-                result.add(element);
-            }
-        }
-        return result;
-    }
-
-    public static String[] append(final String[] args, final String... moreArgs) {
-        final ArrayList<String> argList = new ArrayList<String>();
-        argList.addAll(Arrays.asList(args));
-        argList.addAll(Arrays.asList(moreArgs));
-        return argList.toArray(new String[] {});
-    }
-
-    /**
-     * Creates a mutable list of the provided array, also appending the
-     * additional element(s).
-     */
-    public static <T> List<T> concat(final T[] elements, final List<T> elementsToAppend) {
-        final List<T> result = new ArrayList<T>();
-        for (final T element : elements) {
-            result.add(element);
-        }
-        for (final T element : elementsToAppend) {
-            if (element != null) {
-                result.add(element);
-            }
-        }
-        return result;
-    }
-
-    @SuppressWarnings("unchecked")
-    public static <D, S> D[] copy(final S[] source, final Class<D> cls) {
-        if (source == null) {
-            throw new IllegalArgumentException("Source array cannot be null");
-        }
-        final D[] destination = (D[]) Array.newInstance(cls, source.length);
-        System.arraycopy(source, 0, destination, 0, source.length);
-        return destination;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/a5ad5dcf/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/PropertyUtil.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/PropertyUtil.java b/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/PropertyUtil.java
index 56f35c1..540c5d9 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/PropertyUtil.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/PropertyUtil.java
@@ -16,34 +16,14 @@
  */
 package org.apache.isis.core.commons.lang;
 
-import java.io.InputStream;
-import java.net.URL;
-import java.util.Arrays;
-import java.util.List;
 import java.util.Properties;
 
-import com.google.common.base.Function;
 import com.google.common.base.Joiner;
-import com.google.common.collect.Iterables;
-import com.google.common.io.InputSupplier;
-import com.google.common.io.Resources;
 
 public class PropertyUtil {
     
     private PropertyUtil(){}
 
-    public static Properties propertiesFor(final Class<?> cls, final String suffix) {
-        try {
-            final URL url = Resources.getResource(cls, cls.getSimpleName()+suffix);
-            final InputSupplier<InputStream> inputSupplier = Resources.newInputStreamSupplier(url);
-            final Properties properties = new Properties();
-            properties.load(inputSupplier.getInput());
-            return properties;
-        } catch (Exception e) {
-            return null;
-        }
-    }
-
     public static Properties subset(Properties properties, String... prefix) {
         final String prefices = Joiner.on(".").join(prefix);
         return subsetOf(properties, prefices+".");

http://git-wip-us.apache.org/repos/asf/isis/blob/a5ad5dcf/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ResourceUtil.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ResourceUtil.java b/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ResourceUtil.java
new file mode 100644
index 0000000..b0e53d0
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ResourceUtil.java
@@ -0,0 +1,111 @@
+/*
+ *  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.lang;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.nio.charset.Charset;
+import java.util.Properties;
+
+import com.google.common.io.InputSupplier;
+import com.google.common.io.Resources;
+
+/**
+ * Adapted from Ibatis Common, now with some additional guava stuff.
+ */
+public class ResourceUtil {
+
+    /**
+     * Returns the URL, or null if not available.
+     */
+    public static URL getResourceURL(final String resource) {
+
+        // try thread's classloader
+        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+        URL url = classLoader.getResource(resource);
+        if (url != null) {
+            return url;
+        }
+
+        // try this class' classloader
+        classLoader = ResourceUtil.class.getClassLoader();
+        url = classLoader.getResource(resource);
+        if (url != null) {
+            return url;
+        }
+
+        // try system class loader (could return null)
+        // wrapping in a try...catch because when running tests by Maven for a
+        // non-existing
+        // resource, seems to bomb out. Is okay when run from Eclipse. A bit of
+        // a puzzle.
+        try {
+            return ClassLoader.getSystemResource(resource);
+        } catch (final NullPointerException ignore) {
+            return null;
+        }
+    }
+
+    public static InputStream getResourceAsStream(final String resource) {
+
+        // try thread's classloader
+        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+        InputStream is = classLoader.getResourceAsStream(resource);
+        if (is != null) {
+            return is;
+        }
+
+        // try this class' classloader
+        classLoader = ResourceUtil.class.getClassLoader();
+        is = classLoader.getResourceAsStream(resource);
+        if (is != null) {
+            return is;
+        }
+
+        // try system class loader (could return null)
+        // have wrapped in a try...catch because for same reason as
+        // getResourceURL
+        try {
+            return ClassLoader.getSystemResourceAsStream(resource);
+        } catch (final NullPointerException ignore) {
+            return null;
+        }
+    }
+
+
+    public static Properties propertiesFor(final Class<?> cls, final String suffix) {
+        try {
+            final URL url = Resources.getResource(cls, cls.getSimpleName()+suffix);
+            final InputSupplier<InputStream> inputSupplier = com.google.common.io.Resources.newInputStreamSupplier(url);
+            final Properties properties = new Properties();
+            properties.load(inputSupplier.getInput());
+            return properties;
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+    public static String contentOf(final Class<?> cls, final String suffix) throws IOException {
+        final URL url = Resources.getResource(cls, cls.getSimpleName()+suffix);
+        return Resources.toString(url, Charset.defaultCharset());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/a5ad5dcf/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/Resources.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/Resources.java b/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/Resources.java
deleted file mode 100644
index d4eb4e1..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/Resources.java
+++ /dev/null
@@ -1,122 +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.commons.lang;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.Properties;
-
-/**
- * Adapted from Ibatis Common.
- */
-public class Resources {
-
-    /**
-     * Returns the URL, or null if not available.
-     */
-    public static URL getResourceURL(final String resource) {
-
-        // try thread's classloader
-        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
-        URL url = classLoader.getResource(resource);
-        if (url != null) {
-            return url;
-        }
-
-        // try this class' classloader
-        classLoader = Resources.class.getClassLoader();
-        url = classLoader.getResource(resource);
-        if (url != null) {
-            return url;
-        }
-
-        // try system class loader (could return null)
-        // wrapping in a try...catch because when running tests by Maven for a
-        // non-existing
-        // resource, seems to bomb out. Is okay when run from Eclipse. A bit of
-        // a puzzle.
-        try {
-            return ClassLoader.getSystemResource(resource);
-        } catch (final NullPointerException ignore) {
-            return null;
-        }
-    }
-
-    public static InputStream getResourceAsStream(final String resource) {
-
-        // try thread's classloader
-        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
-        InputStream is = classLoader.getResourceAsStream(resource);
-        if (is != null) {
-            return is;
-        }
-
-        // try this class' classloader
-        classLoader = Resources.class.getClassLoader();
-        is = classLoader.getResourceAsStream(resource);
-        if (is != null) {
-            return is;
-        }
-
-        // try system class loader (could return null)
-        // have wrapped in a try...catch because for same reason as
-        // getResourceURL
-        try {
-            return ClassLoader.getSystemResourceAsStream(resource);
-        } catch (final NullPointerException ignore) {
-            return null;
-        }
-    }
-
-    public static File getResourceAsFile(final String resource) {
-        final URL url = getResourceURL(resource);
-        if (url == null) {
-            return null;
-        }
-
-        return new File(url.getFile());
-    }
-
-    public static Properties getResourceAsProperties(final String resource) {
-
-        final InputStream is = getResourceAsStream(resource);
-        if (is == null) {
-            return null;
-        }
-
-        final Properties props = new Properties();
-        try {
-            props.load(is);
-        } catch (final IOException ex) {
-            throw new RuntimeException(ex);
-        } finally {
-            try {
-                is.close();
-            } catch (final IOException ignore) {
-                // ignore
-            }
-        }
-
-        return props;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/a5ad5dcf/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layout/memberorderfacet/MemberOrderComparator.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layout/memberorderfacet/MemberOrderComparator.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layout/memberorderfacet/MemberOrderComparator.java
index cccb8cb..3f157f8 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layout/memberorderfacet/MemberOrderComparator.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layout/memberorderfacet/MemberOrderComparator.java
@@ -20,7 +20,6 @@
 package org.apache.isis.core.metamodel.layout.memberorderfacet;
 
 import java.util.Comparator;
-import java.util.StringTokenizer;
 
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.FacetedMethod;
@@ -45,18 +44,14 @@ import org.apache.isis.core.metamodel.layout.OrderSet;
  */
 public class MemberOrderComparator implements Comparator<Object> {
 
-    private final boolean ensureInSameGroup;
-
-    /**
-     * 
-     * @param ensureGroupIsSame
-     */
+    private final MemberOrderFacetComparator memberOrderFacetComparator;
+    private final MemberIdentifierComparator memberIdentifierComparator = new MemberIdentifierComparator();
+    private final OrderSetGroupNameComparator orderSetComparator = new OrderSetGroupNameComparator(true);
+    
     public MemberOrderComparator(final boolean ensureGroupIsSame) {
-        this.ensureInSameGroup = ensureGroupIsSame;
+        memberOrderFacetComparator = new MemberOrderFacetComparator(ensureGroupIsSame);
     }
 
-    private final MemberIdentifierComparator fallbackComparator = new MemberIdentifierComparator();
-    private final OrderSetGroupNameComparator orderSetComparator = new OrderSetGroupNameComparator(true);
 
     @Override
     public int compare(final Object o1, final Object o2) {
@@ -79,78 +74,13 @@ public class MemberOrderComparator implements Comparator<Object> {
         final MemberOrderFacet m1 = getMemberOrder(o1);
         final MemberOrderFacet m2 = getMemberOrder(o2);
 
-        if (m1 == null && m2 == null) {
-            return fallbackComparator.compare(o1, o2);
-        }
-
-        if (m1 == null && m2 != null) {
-            return +1; // annotated before non-annotated
-        }
-        if (m1 != null && m2 == null) {
-            return -1; // annotated before non-annotated
-        }
-
-        if (ensureInSameGroup && !m1.name().equals(m2.name())) {
-            throw new IllegalArgumentException("Not in same group");
-        }
-
-        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 fallbackComparator.compare(o1, o2);
-        }
-
-        // 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 fallbackComparator.compare(o1, o2);
-            }
-            // 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++;
-        }
+        final int memberOrderComparison = memberOrderFacetComparator.compare(m1, m2);
+        if(memberOrderComparison != 0) {
+            return memberOrderComparison;
+        } 
+        return memberIdentifierComparator.compare(o1, o2);
     }
 
-    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;
-    }
 
     private MemberOrderFacet getMemberOrder(final FacetHolder facetHolder) {
         return facetHolder.getFacet(MemberOrderFacet.class);

http://git-wip-us.apache.org/repos/asf/isis/blob/a5ad5dcf/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
new file mode 100644
index 0000000..1148af1
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layout/memberorderfacet/MemberOrderFacetComparator.java
@@ -0,0 +1,113 @@
+/*
+ *  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.layout.memberorderfacet;
+
+import java.io.Serializable;
+import java.util.Comparator;
+import java.util.StringTokenizer;
+
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.core.metamodel.facets.FacetedMethod;
+import org.apache.isis.core.metamodel.facets.members.order.MemberOrderFacet;
+
+public class MemberOrderFacetComparator implements Comparator<MemberOrderFacet> {
+
+    private boolean ensureInSameGroup;
+    public MemberOrderFacetComparator(boolean ensureInSameGroup) {
+        this.ensureInSameGroup = ensureInSameGroup;
+    }
+    
+    @Override
+    public int compare(final MemberOrderFacet m1, final MemberOrderFacet m2) {
+        if (m1 == null && m2 == null) {
+            return 0;
+        }
+
+        if (m1 == null && m2 != null) {
+            return +1; // annotated before non-annotated
+        }
+        if (m1 != null && m2 == null) {
+            return -1; // annotated before non-annotated
+        }
+
+        if (ensureInSameGroup && !m1.name().equals(m2.name())) {
+            throw new IllegalArgumentException("Not in same group");
+        }
+
+        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/a5ad5dcf/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/ActionRepr.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/ActionRepr.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/ActionRepr.java
new file mode 100644
index 0000000..ba8db76
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/ActionRepr.java
@@ -0,0 +1,20 @@
+/**
+ *  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.layoutmetadata;
+
+public class ActionRepr {
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/a5ad5dcf/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/ColumnRepr.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/ColumnRepr.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/ColumnRepr.java
new file mode 100644
index 0000000..eb2a5c7
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/ColumnRepr.java
@@ -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.
+ */
+package org.apache.isis.core.metamodel.layoutmetadata;
+
+import java.util.Map;
+
+public class ColumnRepr {
+    public int span;
+    public Map<String,MemberGroupRepr> memberGroups;
+    public Map<String,MemberRepr> collections;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/a5ad5dcf/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/LayoutMetadata.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/LayoutMetadata.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/LayoutMetadata.java
new file mode 100644
index 0000000..bf64450
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/LayoutMetadata.java
@@ -0,0 +1,40 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.isis.core.metamodel.layoutmetadata;
+
+import java.util.List;
+import java.util.Map;
+
+public class LayoutMetadata {
+    private List<ColumnRepr> columns;
+    
+    private Map<String,ActionRepr> actions;
+    
+    public List<ColumnRepr> getColumns() {
+        return columns;
+    }
+    public void setColumns(List<ColumnRepr> columns) {
+        this.columns = columns;
+        
+    }
+    public Map<String,ActionRepr> getActions() {
+        return actions;
+    }
+    public void setActions(Map<String,ActionRepr> actions) {
+        this.actions = actions;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/a5ad5dcf/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/LayoutMetadataReader.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/LayoutMetadataReader.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/LayoutMetadataReader.java
new file mode 100644
index 0000000..587cb88
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/LayoutMetadataReader.java
@@ -0,0 +1,47 @@
+/**
+ *  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.layoutmetadata;
+
+import java.util.Properties;
+
+import org.apache.isis.core.commons.exceptions.IsisException;
+
+public interface LayoutMetadataReader {
+
+    public static class ReaderException extends IsisException {
+
+        private static final long serialVersionUID = 1L;
+
+        public ReaderException() {
+            super();
+        }
+
+        public ReaderException(String message, Throwable cause) {
+            super(message, cause);
+        }
+
+        public ReaderException(String message) {
+            super(message);
+        }
+
+        public ReaderException(Throwable cause) {
+            super(cause);
+        }
+    }
+
+    public Properties asProperties(Class<?> domainClass) throws ReaderException;
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/a5ad5dcf/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/MemberGroupRepr.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/MemberGroupRepr.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/MemberGroupRepr.java
new file mode 100644
index 0000000..494da4d
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/MemberGroupRepr.java
@@ -0,0 +1,23 @@
+/**
+ *  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.layoutmetadata;
+
+import java.util.Map;
+
+public class MemberGroupRepr {
+    public Map<String,MemberRepr> members;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/a5ad5dcf/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/MemberRepr.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/MemberRepr.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/MemberRepr.java
new file mode 100644
index 0000000..f7cc8c9
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/MemberRepr.java
@@ -0,0 +1,23 @@
+/**
+ *  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.layoutmetadata;
+
+import java.util.Map;
+
+public class MemberRepr {
+    public Map<String,ActionRepr> actions;
+}
\ No newline at end of file