http://git-wip-us.apache.org/repos/asf/isis/blob/fb0f1273/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/HiddenFacetForActionLayoutXml.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/HiddenFacetForActionLayoutXml.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/HiddenFacetForActionLayoutXml.java
index c0b98da1..05ffb10 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/HiddenFacetForActionLayoutXml.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/HiddenFacetForActionLayoutXml.java
@@ -21,7 +21,7 @@ package org.apache.isis.core.metamodel.facets.actions.layout;
 
 import org.apache.isis.applib.annotation.When;
 import org.apache.isis.applib.annotation.Where;
-import org.apache.isis.applib.layout.v1_0.Action;
+import org.apache.isis.applib.layout.v1_0.ActionLayoutMetadata;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.all.hide.HiddenFacet;
@@ -29,7 +29,7 @@ import 
org.apache.isis.core.metamodel.facets.members.hidden.HiddenFacetAbstract;
 
 public class HiddenFacetForActionLayoutXml extends HiddenFacetAbstract {
 
-    public static HiddenFacet create(final Action actionLayout, final 
FacetHolder holder) {
+    public static HiddenFacet create(final ActionLayoutMetadata actionLayout, 
final FacetHolder holder) {
         if (actionLayout == null) {
             return null;
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/fb0f1273/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/NamedFacetForActionXml.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/NamedFacetForActionXml.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/NamedFacetForActionXml.java
index c96fa2a..efa4191 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/NamedFacetForActionXml.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/NamedFacetForActionXml.java
@@ -21,14 +21,14 @@ package 
org.apache.isis.core.metamodel.facets.actions.layout;
 
 import com.google.common.base.Strings;
 
-import org.apache.isis.applib.layout.v1_0.Action;
+import org.apache.isis.applib.layout.v1_0.ActionLayoutMetadata;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.all.named.NamedFacet;
 import org.apache.isis.core.metamodel.facets.all.named.NamedFacetAbstract;
 
 public class NamedFacetForActionXml extends NamedFacetAbstract {
 
-    public static NamedFacet create(final Action actionLayout, final 
FacetHolder holder) {
+    public static NamedFacet create(final ActionLayoutMetadata actionLayout, 
final FacetHolder holder) {
         if(actionLayout == null) {
             return null;
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/fb0f1273/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/CssClassFacetForCollectionXml.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/CssClassFacetForCollectionXml.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/CssClassFacetForCollectionXml.java
index c75d5a7..c2ffd02 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/CssClassFacetForCollectionXml.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/CssClassFacetForCollectionXml.java
@@ -21,14 +21,14 @@ package 
org.apache.isis.core.metamodel.facets.collections.layout;
 
 import com.google.common.base.Strings;
 
-import org.apache.isis.applib.layout.v1_0.Collection;
+import org.apache.isis.applib.layout.v1_0.CollectionLayoutMetadata;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.members.cssclass.CssClassFacet;
 import 
org.apache.isis.core.metamodel.facets.members.cssclass.CssClassFacetAbstract;
 
 public class CssClassFacetForCollectionXml extends CssClassFacetAbstract {
 
-    public static CssClassFacet create(Collection collectionLayout, 
FacetHolder holder) {
+    public static CssClassFacet create(CollectionLayoutMetadata 
collectionLayout, FacetHolder holder) {
         if(collectionLayout == null) {
             return null;
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/fb0f1273/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/DefaultViewFacetForCollectionXml.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/DefaultViewFacetForCollectionXml.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/DefaultViewFacetForCollectionXml.java
index 594bca0..5802d5d 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/DefaultViewFacetForCollectionXml.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/DefaultViewFacetForCollectionXml.java
@@ -21,7 +21,7 @@ package 
org.apache.isis.core.metamodel.facets.collections.layout;
 
 import com.google.common.base.Strings;
 
-import org.apache.isis.applib.layout.v1_0.Collection;
+import org.apache.isis.applib.layout.v1_0.CollectionLayoutMetadata;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import 
org.apache.isis.core.metamodel.facets.collections.collection.defaultview.DefaultViewFacet;
 import 
org.apache.isis.core.metamodel.facets.collections.collection.defaultview.DefaultViewFacetAbstract;
@@ -32,7 +32,7 @@ public class DefaultViewFacetForCollectionXml extends 
DefaultViewFacetAbstract {
         super(value, holder);
     }
 
-    public static DefaultViewFacet create(Collection collectionLayout, 
FacetHolder holder) {
+    public static DefaultViewFacet create(CollectionLayoutMetadata 
collectionLayout, FacetHolder holder) {
         if (collectionLayout == null) {
             return null;
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/fb0f1273/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/DescribedAsFacetForCollectionXml.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/DescribedAsFacetForCollectionXml.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/DescribedAsFacetForCollectionXml.java
index a159fc2..b9561f4 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/DescribedAsFacetForCollectionXml.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/DescribedAsFacetForCollectionXml.java
@@ -21,14 +21,14 @@ package 
org.apache.isis.core.metamodel.facets.collections.layout;
 
 import com.google.common.base.Strings;
 
-import org.apache.isis.applib.layout.v1_0.Collection;
+import org.apache.isis.applib.layout.v1_0.CollectionLayoutMetadata;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.all.describedas.DescribedAsFacet;
 import 
org.apache.isis.core.metamodel.facets.all.describedas.DescribedAsFacetAbstract;
 
 public class DescribedAsFacetForCollectionXml extends DescribedAsFacetAbstract 
{
 
-    public static DescribedAsFacet create(Collection collectionLayout, 
FacetHolder holder) {
+    public static DescribedAsFacet create(CollectionLayoutMetadata 
collectionLayout, FacetHolder holder) {
         if(collectionLayout == null) {
             return null;
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/fb0f1273/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/HiddenFacetForCollectionXml.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/HiddenFacetForCollectionXml.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/HiddenFacetForCollectionXml.java
index 8a52c8e..a76ab13 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/HiddenFacetForCollectionXml.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/HiddenFacetForCollectionXml.java
@@ -21,7 +21,7 @@ package 
org.apache.isis.core.metamodel.facets.collections.layout;
 
 import org.apache.isis.applib.annotation.When;
 import org.apache.isis.applib.annotation.Where;
-import org.apache.isis.applib.layout.v1_0.Collection;
+import org.apache.isis.applib.layout.v1_0.CollectionLayoutMetadata;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.all.hide.HiddenFacet;
@@ -29,7 +29,7 @@ import 
org.apache.isis.core.metamodel.facets.members.hidden.HiddenFacetAbstract;
 
 public class HiddenFacetForCollectionXml extends HiddenFacetAbstract {
 
-    public static HiddenFacet create(final Collection collectionLayout, final 
FacetHolder holder) {
+    public static HiddenFacet create(final CollectionLayoutMetadata 
collectionLayout, final FacetHolder holder) {
         if (collectionLayout == null) {
             return null;
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/fb0f1273/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/NamedFacetForCollectionXml.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/NamedFacetForCollectionXml.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/NamedFacetForCollectionXml.java
index 295cbc9..9509253 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/NamedFacetForCollectionXml.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/NamedFacetForCollectionXml.java
@@ -21,14 +21,14 @@ package 
org.apache.isis.core.metamodel.facets.collections.layout;
 
 import com.google.common.base.Strings;
 
-import org.apache.isis.applib.layout.v1_0.Collection;
+import org.apache.isis.applib.layout.v1_0.CollectionLayoutMetadata;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.all.named.NamedFacet;
 import org.apache.isis.core.metamodel.facets.all.named.NamedFacetAbstract;
 
 public class NamedFacetForCollectionXml extends NamedFacetAbstract {
 
-    public static NamedFacet create(Collection collectionLayout, FacetHolder 
holder) {
+    public static NamedFacet create(CollectionLayoutMetadata collectionLayout, 
FacetHolder holder) {
         if(collectionLayout == null) {
             return null;
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/fb0f1273/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/PagedFacetForCollectionXml.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/PagedFacetForCollectionXml.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/PagedFacetForCollectionXml.java
index eee8838..6b577c0 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/PagedFacetForCollectionXml.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/PagedFacetForCollectionXml.java
@@ -19,14 +19,14 @@
 
 package org.apache.isis.core.metamodel.facets.collections.layout;
 
-import org.apache.isis.applib.layout.v1_0.Collection;
+import org.apache.isis.applib.layout.v1_0.CollectionLayoutMetadata;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.object.paged.PagedFacet;
 import org.apache.isis.core.metamodel.facets.object.paged.PagedFacetAbstract;
 
 public class PagedFacetForCollectionXml extends PagedFacetAbstract {
 
-    public static PagedFacet create(Collection collectionLayout, FacetHolder 
holder) {
+    public static PagedFacet create(CollectionLayoutMetadata collectionLayout, 
FacetHolder holder) {
         if(collectionLayout == null) {
             return null;
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/fb0f1273/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/SortedByFacetForCollectionXml.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/SortedByFacetForCollectionXml.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/SortedByFacetForCollectionXml.java
index dbba9dd..72410ce 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/SortedByFacetForCollectionXml.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/layout/SortedByFacetForCollectionXml.java
@@ -21,7 +21,7 @@ package 
org.apache.isis.core.metamodel.facets.collections.layout;
 
 import java.util.Comparator;
 
-import org.apache.isis.applib.layout.v1_0.Collection;
+import org.apache.isis.applib.layout.v1_0.CollectionLayoutMetadata;
 import org.apache.isis.core.commons.lang.ClassUtil;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import 
org.apache.isis.core.metamodel.facets.collections.sortedby.SortedByFacet;
@@ -29,7 +29,7 @@ import 
org.apache.isis.core.metamodel.facets.collections.sortedby.SortedByFacetA
 
 public class SortedByFacetForCollectionXml extends SortedByFacetAbstract {
 
-    public static SortedByFacet create(Collection collectionLayout, 
FacetHolder holder) {
+    public static SortedByFacet create(CollectionLayoutMetadata 
collectionLayout, FacetHolder holder) {
         if(collectionLayout == null) {
             return null;
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/fb0f1273/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/LayoutXmlFacet.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/LayoutXmlFacet.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/LayoutXmlFacet.java
deleted file mode 100644
index 608abbe..0000000
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/LayoutXmlFacet.java
+++ /dev/null
@@ -1,32 +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.metamodel.facets.object.layoutxml;
-
-
-import org.apache.isis.core.metamodel.facetapi.Facet;
-import org.apache.isis.applib.layout.v1_0.DomainObject;
-
-/**
- * Corresponds to providing a <code>.layout.xml</code> file for the domain 
object's class.
- */
-public interface LayoutXmlFacet extends Facet {
-
-    public DomainObject getLayoutMetadata();
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/fb0f1273/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/LayoutXmlFacetDefault.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/LayoutXmlFacetDefault.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/LayoutXmlFacetDefault.java
deleted file mode 100644
index eedda94..0000000
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/LayoutXmlFacetDefault.java
+++ /dev/null
@@ -1,381 +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.metamodel.facets.object.layoutxml;
-
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicReference;
-
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
-import org.apache.isis.applib.layout.v1_0.Action;
-import org.apache.isis.applib.layout.v1_0.ActionHolder;
-import org.apache.isis.applib.layout.v1_0.Collection;
-import org.apache.isis.applib.layout.v1_0.Column;
-import org.apache.isis.applib.layout.v1_0.DomainObject;
-import org.apache.isis.applib.layout.v1_0.Property;
-import org.apache.isis.applib.layout.v1_0.PropertyGroup;
-import org.apache.isis.applib.layout.v1_0.Tab;
-import org.apache.isis.applib.layout.v1_0.TabGroup;
-import org.apache.isis.applib.services.i18n.TranslationService;
-import org.apache.isis.core.metamodel.facetapi.Facet;
-import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
-import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.facetapi.FacetUtil;
-import 
org.apache.isis.core.metamodel.facets.actions.layout.ActionPositionFacetForActionXml;
-import 
org.apache.isis.core.metamodel.facets.actions.layout.BookmarkPolicyFacetForActionXml;
-import 
org.apache.isis.core.metamodel.facets.actions.layout.CssClassFaFacetForActionXml;
-import 
org.apache.isis.core.metamodel.facets.actions.layout.CssClassFacetForActionXml;
-import 
org.apache.isis.core.metamodel.facets.actions.layout.DescribedAsFacetForActionXml;
-import 
org.apache.isis.core.metamodel.facets.actions.layout.HiddenFacetForActionLayoutXml;
-import 
org.apache.isis.core.metamodel.facets.actions.layout.NamedFacetForActionXml;
-import 
org.apache.isis.core.metamodel.facets.collections.layout.CssClassFacetForCollectionXml;
-import 
org.apache.isis.core.metamodel.facets.collections.layout.DefaultViewFacetForCollectionXml;
-import 
org.apache.isis.core.metamodel.facets.collections.layout.DescribedAsFacetForCollectionXml;
-import 
org.apache.isis.core.metamodel.facets.collections.layout.HiddenFacetForCollectionXml;
-import 
org.apache.isis.core.metamodel.facets.collections.layout.NamedFacetForCollectionXml;
-import 
org.apache.isis.core.metamodel.facets.collections.layout.PagedFacetForCollectionXml;
-import 
org.apache.isis.core.metamodel.facets.collections.layout.SortedByFacetForCollectionXml;
-import 
org.apache.isis.core.metamodel.facets.members.order.annotprop.MemberOrderFacetXml;
-import 
org.apache.isis.core.metamodel.facets.object.membergroups.MemberGroupLayoutFacet;
-import 
org.apache.isis.core.metamodel.facets.properties.propertylayout.CssClassFacetForPropertyXml;
-import 
org.apache.isis.core.metamodel.facets.properties.propertylayout.DescribedAsFacetForPropertyXml;
-import 
org.apache.isis.core.metamodel.facets.properties.propertylayout.HiddenFacetForPropertyXml;
-import 
org.apache.isis.core.metamodel.facets.properties.propertylayout.LabelAtFacetForPropertyXml;
-import 
org.apache.isis.core.metamodel.facets.properties.propertylayout.MultiLineFacetForPropertyXml;
-import 
org.apache.isis.core.metamodel.facets.properties.propertylayout.NamedFacetForPropertyXml;
-import 
org.apache.isis.core.metamodel.facets.properties.propertylayout.RenderedAdjustedFacetForPropertyXml;
-import 
org.apache.isis.core.metamodel.facets.properties.propertylayout.TypicalLengthFacetForPropertyXml;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.metamodel.spec.feature.Contributed;
-import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
-import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
-import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
-import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
-import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
-
-public class LayoutXmlFacetDefault
-            extends FacetAbstract
-            implements LayoutXmlFacet {
-
-    private final DomainObject metadata;
-    private final TranslationService translationService;
-
-    public static Class<? extends Facet> type() {
-        return LayoutXmlFacet.class;
-    }
-
-
-    public static LayoutXmlFacet create(
-            final FacetHolder facetHolder,
-            final DomainObject domainObject,
-            final TranslationService translationService) {
-        if(domainObject == null) {
-            return null;
-        }
-        return new LayoutXmlFacetDefault(facetHolder, domainObject, 
translationService);
-    }
-
-    private LayoutXmlFacetDefault(
-            final FacetHolder facetHolder,
-            final DomainObject metadata,
-            final TranslationService translationService) {
-        super(LayoutXmlFacetDefault.type(), facetHolder, 
Derivation.NOT_DERIVED);
-        this.metadata = metadata;
-        this.translationService = translationService;
-    }
-
-
-    private boolean derived;
-
-    public DomainObject getLayoutMetadata() {
-        //return derived ? metadata : deriveAndOverwrite(metadata);
-        return deriveAndOverwrite(metadata);
-    }
-
-    private  DomainObject deriveAndOverwrite(final DomainObject metadata) {
-        synchronized (metadata) {
-            doDeriveAndOverwrite(metadata);
-            derived = true;
-        }
-        return metadata;
-    }
-
-    private void doDeriveAndOverwrite(final DomainObject metadata) {
-
-        final ObjectSpecification objectSpec = (ObjectSpecification) 
getFacetHolder();
-        final Map<String, OneToOneAssociation> oneToOneAssociationById =
-                ObjectMember.Util.mapById(getOneToOneAssociations(objectSpec));
-        final Map<String, OneToManyAssociation> oneToManyAssociationById =
-                
ObjectMember.Util.mapById(getOneToManyAssociations(objectSpec));
-        final Map<String, ObjectAction> objectActionById =
-                
ObjectMember.Util.mapById(objectSpec.getObjectActions(Contributed.INCLUDED));
-
-        derive(metadata, oneToOneAssociationById, oneToManyAssociationById, 
objectActionById);
-        overwrite(metadata, oneToOneAssociationById, oneToManyAssociationById, 
objectActionById);
-    }
-
-    /**
-     * Ensures that all object members (properties, collections and actions) 
are in the metadata.
-     *
-     * <p>
-     *     If they are missing then they will be added to default tabs 
(created on the fly if need be).
-     * </p>
-     */
-    private static void derive(
-            final DomainObject metadata,
-            final Map<String, OneToOneAssociation> oneToOneAssociationById,
-            final Map<String, OneToManyAssociation> oneToManyAssociationById,
-            final Map<String, ObjectAction> objectActionById) {
-        final List<String> propertyIds = Lists.newArrayList();
-        final List<String> collectionIds = Lists.newArrayList();
-        final List<String> actionIds = Lists.newArrayList();
-        final AtomicReference<PropertyGroup> defaultPropertyGroupRef = new 
AtomicReference<>();
-        final AtomicReference<Column> firstColumnRef = new AtomicReference<>();
-        final AtomicReference<TabGroup> lastTabGroupRef = new 
AtomicReference<>();
-
-        // catalog which property, collection and action Ids appear (anywhere) 
in the metadata
-        metadata.visit(new DomainObject.VisitorAdapter() {
-            @Override
-            public void visit(final Property property) {
-                propertyIds.add(property.getId());
-            }
-            @Override
-            public void visit(final Collection collection) {
-                collectionIds.add(collection.getId());
-            }
-            @Override
-            public void visit(final Action action) {
-                actionIds.add(action.getId());
-            }
-        });
-
-        // capture the first column, and also
-        // capture the first property group (if any) with the default name 
('General')
-        metadata.visit(new DomainObject.VisitorAdapter() {
-            @Override
-            public void visit(final Column column) {
-                firstColumnRef.compareAndSet(null, column);
-            }
-            @Override
-            public void visit(final PropertyGroup propertyGroup) {
-                
if(MemberGroupLayoutFacet.DEFAULT_GROUP.equals(propertyGroup.getName())) {
-                    defaultPropertyGroupRef.compareAndSet(null, propertyGroup);
-                }
-            }
-            @Override
-            public void visit(final TabGroup tabGroup) {
-                lastTabGroupRef.set(tabGroup);
-            }
-        });
-
-        // any missing properties will be added to the (first) 'General' 
property group found
-        // if there is no default ('General') property group
-        // then one will be added to the first Column of the first Tab.
-        final List<String> missingPropertyIds = 
Lists.newArrayList(oneToOneAssociationById.keySet());
-        missingPropertyIds.removeAll(propertyIds);
-
-        if(!missingPropertyIds.isEmpty()) {
-            // ensure that there is a property group to use
-            boolean wasSet = defaultPropertyGroupRef.compareAndSet(null, new 
PropertyGroup(MemberGroupLayoutFacet.DEFAULT_GROUP));
-            final PropertyGroup defaultPropertyGroup = 
defaultPropertyGroupRef.get();
-            if(wasSet) {
-                
firstColumnRef.get().getPropertyGroups().add(defaultPropertyGroup);
-            }
-            Iterables.removeAll(propertyIds, oneToOneAssociationById.keySet());
-            for (final String propertyId : missingPropertyIds) {
-                defaultPropertyGroup.getProperties().add(new 
Property(propertyId));
-            }
-        }
-
-        // any missing collections will be added as tabs to the last TabGroup.
-        // If there is only a single tab group then a new TabGroup will be 
added first
-        final List<String> missingCollectionIds = 
Lists.newArrayList(oneToManyAssociationById.keySet());
-        missingCollectionIds.removeAll(collectionIds);
-
-        if(!missingCollectionIds.isEmpty()) {
-            while(metadata.getTabGroups().size() < 2) {
-                final TabGroup tabGroup = new TabGroup();
-                metadata.getTabGroups().add(tabGroup);
-                lastTabGroupRef.set(tabGroup);
-            }
-            final TabGroup lastTabGroup = lastTabGroupRef.get();
-            for (final String collectionId : missingCollectionIds) {
-                final Tab tab = new Tab();
-                lastTabGroup.getTabs().add(tab);
-                Column left = new Column(12);
-                tab.setLeft(left);
-                left.getCollections().add(new Collection(collectionId));
-            }
-        }
-
-        // any missing actions will be added as domain object actions (in the 
header)
-        final List<String> missingActionIds = 
Lists.newArrayList(objectActionById.keySet());
-        missingActionIds.removeAll(actionIds);
-
-        if(!missingActionIds.isEmpty()) {
-            for (String actionId : missingActionIds) {
-                metadata.getActions().add(new Action(actionId));
-            }
-        }
-    }
-
-    private void overwrite(
-            final DomainObject metadata,
-            final Map<String, OneToOneAssociation> oneToOneAssociationById,
-            final Map<String, OneToManyAssociation> oneToManyAssociationById,
-            final Map<String, ObjectAction> objectActionById) {
-
-        metadata.visit(new DomainObject.VisitorAdapter() {
-            private final Map<String, int[]> propertySequenceByGroup = 
Maps.newHashMap();
-            private int actionDomainObjectSequence = 1;
-            private int actionPropertyGroupSequence = 1;
-            private int actionPropertySequence = 1;
-            private int actionCollectionSequence = 1;
-
-            @Override
-            public void visit(final Action action) {
-                final ActionHolder actionHolder = action.getOwner();
-                final ObjectAction objectAction = 
objectActionById.get(action.getId());
-                final String memberOrderName;
-                final int memberOrderSequence;
-                if(actionHolder instanceof PropertyGroup) {
-                    final PropertyGroup propertyGroup = (PropertyGroup) 
actionHolder;
-                    final List<Property> properties = 
propertyGroup.getProperties();
-                    final Property property = properties.get(0); // any will do
-                    memberOrderName = property.getId();
-                    memberOrderSequence = actionPropertyGroupSequence++;
-                } else if(actionHolder instanceof Property) {
-                    final Property property = (Property) actionHolder;
-                    memberOrderName = property.getId();
-                    memberOrderSequence = actionPropertySequence++;
-                } else if(actionHolder instanceof Collection) {
-                    final Collection collection = (Collection) actionHolder;
-                    memberOrderName = collection.getId();
-                    memberOrderSequence = actionCollectionSequence++;
-                } else {
-                    // DomainObject
-                    memberOrderName = null;
-                    memberOrderSequence = actionDomainObjectSequence++;
-                }
-                FacetUtil.addFacet(
-                    new MemberOrderFacetXml(memberOrderName, 
""+memberOrderSequence, translationService, objectAction));
-
-
-                if(actionHolder instanceof PropertyGroup) {
-                    if(action.getPosition() == null ||
-                       action.getPosition() == 
org.apache.isis.applib.annotation.ActionLayout.Position.BELOW ||
-                       action.getPosition() == 
org.apache.isis.applib.annotation.ActionLayout.Position.RIGHT) {
-                       
action.setPosition(org.apache.isis.applib.annotation.ActionLayout.Position.PANEL);
-                    }
-                } else if(actionHolder instanceof Property) {
-                    if(action.getPosition() == null ||
-                       action.getPosition() == 
org.apache.isis.applib.annotation.ActionLayout.Position.PANEL_DROPDOWN ||
-                       action.getPosition() == 
org.apache.isis.applib.annotation.ActionLayout.Position.PANEL) {
-                       
action.setPosition(org.apache.isis.applib.annotation.ActionLayout.Position.BELOW);
-                    }
-                } else {
-                    // doesn't do anything for DomainObject or Collection
-                    action.setPosition(null);
-                }
-
-                
FacetUtil.addFacet(ActionPositionFacetForActionXml.create(action, 
objectAction));
-                
FacetUtil.addFacet(BookmarkPolicyFacetForActionXml.create(action, 
objectAction));
-                FacetUtil.addFacet(CssClassFacetForActionXml.create(action, 
objectAction));
-                FacetUtil.addFacet(CssClassFaFacetForActionXml.create(action, 
objectAction));
-                FacetUtil.addFacet(DescribedAsFacetForActionXml.create(action, 
objectAction));
-                
FacetUtil.addFacet(HiddenFacetForActionLayoutXml.create(action, objectAction));
-                FacetUtil.addFacet(NamedFacetForActionXml.create(action, 
objectAction));
-            }
-
-            @Override
-            public void visit(final Property property) {
-
-                final OneToOneAssociation oneToOneAssociation = 
oneToOneAssociationById.get(property.getId());
-                
FacetUtil.addFacet(CssClassFacetForPropertyXml.create(property, 
oneToOneAssociation));
-                
FacetUtil.addFacet(DescribedAsFacetForPropertyXml.create(property, 
oneToOneAssociation));
-                FacetUtil.addFacet(HiddenFacetForPropertyXml.create(property, 
oneToOneAssociation));
-                FacetUtil.addFacet(LabelAtFacetForPropertyXml.create(property, 
oneToOneAssociation));
-                
FacetUtil.addFacet(MultiLineFacetForPropertyXml.create(property, 
oneToOneAssociation));
-                FacetUtil.addFacet(NamedFacetForPropertyXml.create(property, 
oneToOneAssociation));
-                
FacetUtil.addFacet(RenderedAdjustedFacetForPropertyXml.create(property, 
oneToOneAssociation));
-                
FacetUtil.addFacet(TypicalLengthFacetForPropertyXml.create(property, 
oneToOneAssociation));
-
-                // @MemberOrder#name based on owning property group, 
@MemberOrder#sequence monotonically increasing
-                final PropertyGroup propertyGroup = property.getOwner();
-                final String groupName = propertyGroup.getName();
-                final String sequence = nextInSequenceFor(groupName);
-                FacetUtil.addFacet(
-                        new MemberOrderFacetXml(groupName, sequence, 
translationService, oneToOneAssociation));
-            }
-
-            @Override
-            public void visit(final Collection collection) {
-                final OneToManyAssociation oneToManyAssociation = 
oneToManyAssociationById.get(collection.getId());
-
-                
FacetUtil.addFacet(CssClassFacetForCollectionXml.create(collection, 
oneToManyAssociation));
-                
FacetUtil.addFacet(DefaultViewFacetForCollectionXml.create(collection, 
oneToManyAssociation));
-                
FacetUtil.addFacet(DescribedAsFacetForCollectionXml.create(collection, 
oneToManyAssociation));
-                
FacetUtil.addFacet(HiddenFacetForCollectionXml.create(collection, 
oneToManyAssociation));
-                
FacetUtil.addFacet(NamedFacetForCollectionXml.create(collection, 
oneToManyAssociation));
-                
FacetUtil.addFacet(PagedFacetForCollectionXml.create(collection, 
oneToManyAssociation));
-                
FacetUtil.addFacet(SortedByFacetForCollectionXml.create(collection, 
oneToManyAssociation));
-
-                // @MemberOrder#name based on the collection's id (so that 
each has a single "member group")
-                final String groupName = collection.getId();
-                final String sequence = nextInSequenceFor(groupName);
-                FacetUtil.addFacet(
-                        new MemberOrderFacetXml(groupName, sequence, 
translationService, oneToManyAssociation));
-
-                // if there is only a single column and no other contents, 
then copy the collection Id onto the tab'
-                final Column column = collection.getOwner();
-                final Tab tab = column.getOwner();
-                if(tab.getContents().size() == 1) {
-                    tab.setName(collection.getId());
-                }
-            }
-
-            private String nextInSequenceFor(final String propertyGroupName) {
-                synchronized (propertySequenceByGroup) {
-                    int[] holder = 
propertySequenceByGroup.get(propertyGroupName);
-                    if(holder == null) {
-                        holder = new int[]{0};
-                        propertySequenceByGroup.put(propertyGroupName, holder);
-                    }
-                    holder[0]++;
-                    return ""+holder[0];
-                }
-            }
-        });
-
-    }
-
-    private static List<OneToOneAssociation> getOneToOneAssociations(final 
ObjectSpecification objectSpec) {
-        List associations = objectSpec
-                .getAssociations(Contributed.INCLUDED, 
ObjectAssociation.Filters.PROPERTIES);
-        return associations;
-    }
-    private static List<OneToManyAssociation> getOneToManyAssociations(final 
ObjectSpecification objectSpec) {
-        List associations = objectSpec
-                .getAssociations(Contributed.INCLUDED, 
ObjectAssociation.Filters.COLLECTIONS);
-        return associations;
-    }
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/fb0f1273/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/LayoutXmlFacetFactory.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/LayoutXmlFacetFactory.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/LayoutXmlFacetFactory.java
index 606f34a..f898f61 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/LayoutXmlFacetFactory.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/LayoutXmlFacetFactory.java
@@ -16,22 +16,15 @@
  * under the License. */
 package org.apache.isis.core.metamodel.facets.object.layoutxml;
 
-import java.io.IOException;
-import java.util.Set;
-
-import com.google.common.collect.Sets;
-
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import org.apache.isis.applib.services.i18n.TranslationService;
-import org.apache.isis.applib.services.jaxb.JaxbService;
-import org.apache.isis.core.commons.lang.ClassExtensions;
+import org.apache.isis.applib.layout.v1_0.ObjectLayoutMetadata;
+import org.apache.isis.applib.services.layout.ObjectLayoutMetadataService;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facetapi.FacetUtil;
 import org.apache.isis.core.metamodel.facetapi.FeatureType;
 import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
-import org.apache.isis.applib.layout.v1_0.DomainObject;
 import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
 import org.apache.isis.core.metamodel.runtimecontext.ServicesInjectorAware;
 
@@ -48,46 +41,14 @@ public class LayoutXmlFacetFactory extends 
FacetFactoryAbstract implements Servi
         final Class<?> cls = processClassContext.getCls();
         final FacetHolder facetHolder = processClassContext.getFacetHolder();
 
-        final TranslationService translationService = 
servicesInjector.lookupService(TranslationService.class);
-        FacetUtil.addFacet(LayoutXmlFacetDefault.create(facetHolder, 
readMetadata(cls), translationService));
+        final ObjectLayoutMetadataService objectLayoutMetadataService = 
servicesInjector.lookupService(ObjectLayoutMetadataService.class);
+        FacetUtil.addFacet(
+                ObjectLayoutMetadataFacetDefault.create(facetHolder, 
readMetadata(cls), objectLayoutMetadataService));
     }
 
-    private final Set<Class<?>> blacklisted = Sets.newConcurrentHashSet();
-
-    private DomainObject readMetadata(final Class<?> domainClass) {
-
-        if(blacklisted.contains(domainClass)) {
-            return null;
-        }
-        final String xml;
-
-        final String resourceName = domainClass.getSimpleName() + 
".layout.xml";
-        try {
-            xml = ClassExtensions.resourceContentOf(domainClass, resourceName);
-        } catch (IOException | IllegalArgumentException ex) {
-
-            blacklisted.add(domainClass);
-            final String message = String .format(
-                    "Failed to locate file %s (relative to %s.class); ex: %s)",
-                    resourceName, domainClass.getName(), ex.getMessage());
-
-            LOG.debug(message);
-            return null;
-        }
-
-        try {
-            final JaxbService jaxbService = 
servicesInjector.lookupService(JaxbService.class);
-            final DomainObject metadata = 
jaxbService.fromXml(DomainObject.class, xml);
-            return metadata;
-        } catch(Exception ex) {
-
-            // note that we don't blacklist if the file exists but couldn't be 
parsed;
-            // the developer might fix so we will want to retry.
-            final String message = "Failed to parse " + resourceName + " file 
(" + ex.getMessage() + ")";
-            LOG.warn(message);
-
-            return null;
-        }
+    private ObjectLayoutMetadata readMetadata(final Class<?> domainClass) {
+        final ObjectLayoutMetadataService objectLayoutMetadataService = 
servicesInjector.lookupService(ObjectLayoutMetadataService.class);
+        return objectLayoutMetadataService.fromXml(domainClass);
     }
 
     private ServicesInjector servicesInjector;

http://git-wip-us.apache.org/repos/asf/isis/blob/fb0f1273/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/ObjectLayoutMetadataFacet.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/ObjectLayoutMetadataFacet.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/ObjectLayoutMetadataFacet.java
new file mode 100644
index 0000000..7285fc0
--- /dev/null
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/ObjectLayoutMetadataFacet.java
@@ -0,0 +1,35 @@
+/*
+ *  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.layoutxml;
+
+
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.applib.layout.v1_0.ObjectLayoutMetadata;
+
+/**
+ * Corresponds to providing a <code>.layout.xml</code> file for the domain 
object's class.
+ */
+public interface ObjectLayoutMetadataFacet extends Facet {
+
+    /**
+     * Will have been {@link 
org.apache.isis.applib.services.layout.ObjectLayoutMetadataService#normalize(ObjectLayoutMetadata,
 Class) normalized}.
+     */
+    ObjectLayoutMetadata getMetadata();
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/fb0f1273/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/ObjectLayoutMetadataFacetDefault.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/ObjectLayoutMetadataFacetDefault.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/ObjectLayoutMetadataFacetDefault.java
new file mode 100644
index 0000000..05d3cc8
--- /dev/null
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/layoutxml/ObjectLayoutMetadataFacetDefault.java
@@ -0,0 +1,65 @@
+/*
+ *  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.layoutxml;
+
+import org.apache.isis.applib.layout.v1_0.ObjectLayoutMetadata;
+import org.apache.isis.applib.services.layout.ObjectLayoutMetadataService;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+
+public class ObjectLayoutMetadataFacetDefault
+            extends FacetAbstract
+            implements ObjectLayoutMetadataFacet {
+
+    private final ObjectLayoutMetadata metadata;
+    private final ObjectLayoutMetadataService objectLayoutMetadataService;
+
+    public static Class<? extends Facet> type() {
+        return ObjectLayoutMetadataFacet.class;
+    }
+
+
+    public static ObjectLayoutMetadataFacet create(
+            final FacetHolder facetHolder,
+            final ObjectLayoutMetadata objectLayoutMetadata,
+            final ObjectLayoutMetadataService objectLayoutMetadataService) {
+        if(objectLayoutMetadata == null) {
+            return null;
+        }
+        return new ObjectLayoutMetadataFacetDefault(facetHolder, 
objectLayoutMetadata, objectLayoutMetadataService);
+    }
+
+    private ObjectLayoutMetadataFacetDefault(
+            final FacetHolder facetHolder,
+            final ObjectLayoutMetadata metadata,
+            final ObjectLayoutMetadataService objectLayoutMetadataService) {
+        super(ObjectLayoutMetadataFacetDefault.type(), facetHolder, 
Derivation.NOT_DERIVED);
+        this.metadata = metadata;
+        this.objectLayoutMetadataService = objectLayoutMetadataService;
+    }
+
+
+    public ObjectLayoutMetadata getMetadata() {
+        final ObjectSpecification objectSpecification = (ObjectSpecification) 
getFacetHolder();
+        return objectLayoutMetadataService.normalize(metadata, 
objectSpecification.getCorrespondingClass());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/fb0f1273/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/CssClassFacetForPropertyXml.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/CssClassFacetForPropertyXml.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/CssClassFacetForPropertyXml.java
index 065e80c..e16cad5 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/CssClassFacetForPropertyXml.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/CssClassFacetForPropertyXml.java
@@ -21,14 +21,14 @@ package 
org.apache.isis.core.metamodel.facets.properties.propertylayout;
 
 import com.google.common.base.Strings;
 
-import org.apache.isis.applib.layout.v1_0.Property;
+import org.apache.isis.applib.layout.v1_0.PropertyLayoutMetadata;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.members.cssclass.CssClassFacet;
 import 
org.apache.isis.core.metamodel.facets.members.cssclass.CssClassFacetAbstract;
 
 public class CssClassFacetForPropertyXml extends CssClassFacetAbstract {
 
-    public static CssClassFacet create(Property propertyLayout, FacetHolder 
holder) {
+    public static CssClassFacet create(PropertyLayoutMetadata propertyLayout, 
FacetHolder holder) {
         if(propertyLayout == null) {
             return null;
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/fb0f1273/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/DescribedAsFacetForPropertyXml.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/DescribedAsFacetForPropertyXml.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/DescribedAsFacetForPropertyXml.java
index 2c9f6f6..e2c6bb6 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/DescribedAsFacetForPropertyXml.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/DescribedAsFacetForPropertyXml.java
@@ -21,14 +21,14 @@ package 
org.apache.isis.core.metamodel.facets.properties.propertylayout;
 
 import com.google.common.base.Strings;
 
-import org.apache.isis.applib.layout.v1_0.Property;
+import org.apache.isis.applib.layout.v1_0.PropertyLayoutMetadata;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.all.describedas.DescribedAsFacet;
 import 
org.apache.isis.core.metamodel.facets.all.describedas.DescribedAsFacetAbstract;
 
 public class DescribedAsFacetForPropertyXml extends DescribedAsFacetAbstract {
 
-    public static DescribedAsFacet create(Property propertyLayout, FacetHolder 
holder) {
+    public static DescribedAsFacet create(PropertyLayoutMetadata 
propertyLayout, FacetHolder holder) {
         if(propertyLayout == null) {
             return null;
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/fb0f1273/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/HiddenFacetForPropertyXml.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/HiddenFacetForPropertyXml.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/HiddenFacetForPropertyXml.java
index 4ee7f1d..83d15ab 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/HiddenFacetForPropertyXml.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/HiddenFacetForPropertyXml.java
@@ -21,7 +21,7 @@ package 
org.apache.isis.core.metamodel.facets.properties.propertylayout;
 
 import org.apache.isis.applib.annotation.When;
 import org.apache.isis.applib.annotation.Where;
-import org.apache.isis.applib.layout.v1_0.Property;
+import org.apache.isis.applib.layout.v1_0.PropertyLayoutMetadata;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.all.hide.HiddenFacet;
@@ -29,7 +29,7 @@ import 
org.apache.isis.core.metamodel.facets.members.hidden.HiddenFacetAbstract;
 
 public class HiddenFacetForPropertyXml extends HiddenFacetAbstract {
 
-    public static HiddenFacet create(final Property propertyLayout, final 
FacetHolder holder) {
+    public static HiddenFacet create(final PropertyLayoutMetadata 
propertyLayout, final FacetHolder holder) {
         if (propertyLayout == null) {
             return null;
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/fb0f1273/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/LabelAtFacetForPropertyXml.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/LabelAtFacetForPropertyXml.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/LabelAtFacetForPropertyXml.java
index ba512a9..fc55c5d 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/LabelAtFacetForPropertyXml.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/LabelAtFacetForPropertyXml.java
@@ -20,14 +20,14 @@
 package org.apache.isis.core.metamodel.facets.properties.propertylayout;
 
 import org.apache.isis.applib.annotation.LabelPosition;
-import org.apache.isis.applib.layout.v1_0.Property;
+import org.apache.isis.applib.layout.v1_0.PropertyLayoutMetadata;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.objectvalue.labelat.LabelAtFacet;
 import 
org.apache.isis.core.metamodel.facets.objectvalue.labelat.LabelAtFacetAbstract;
 
 public class LabelAtFacetForPropertyXml extends LabelAtFacetAbstract {
 
-    public static LabelAtFacet create(final Property propertyLayout, 
FacetHolder holder) {
+    public static LabelAtFacet create(final PropertyLayoutMetadata 
propertyLayout, FacetHolder holder) {
         if (propertyLayout == null) {
             return null;
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/fb0f1273/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/MultiLineFacetForPropertyXml.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/MultiLineFacetForPropertyXml.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/MultiLineFacetForPropertyXml.java
index 9a48271..599ceba 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/MultiLineFacetForPropertyXml.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/MultiLineFacetForPropertyXml.java
@@ -19,14 +19,14 @@
 
 package org.apache.isis.core.metamodel.facets.properties.propertylayout;
 
-import org.apache.isis.applib.layout.v1_0.Property;
+import org.apache.isis.applib.layout.v1_0.PropertyLayoutMetadata;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import 
org.apache.isis.core.metamodel.facets.objectvalue.multiline.MultiLineFacet;
 import 
org.apache.isis.core.metamodel.facets.objectvalue.multiline.MultiLineFacetAbstract;
 
 public class MultiLineFacetForPropertyXml extends MultiLineFacetAbstract {
 
-    public static MultiLineFacet create(Property propertyLayout, FacetHolder 
holder) {
+    public static MultiLineFacet create(PropertyLayoutMetadata propertyLayout, 
FacetHolder holder) {
         if(propertyLayout == null) {
             return null;
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/fb0f1273/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/NamedFacetForPropertyXml.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/NamedFacetForPropertyXml.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/NamedFacetForPropertyXml.java
index 392a152..8f2ea3a 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/NamedFacetForPropertyXml.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/NamedFacetForPropertyXml.java
@@ -21,14 +21,14 @@ package 
org.apache.isis.core.metamodel.facets.properties.propertylayout;
 
 import com.google.common.base.Strings;
 
-import org.apache.isis.applib.layout.v1_0.Property;
+import org.apache.isis.applib.layout.v1_0.PropertyLayoutMetadata;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.all.named.NamedFacet;
 import org.apache.isis.core.metamodel.facets.all.named.NamedFacetAbstract;
 
 public class NamedFacetForPropertyXml extends NamedFacetAbstract {
 
-    public static NamedFacet create(Property propertyLayout, FacetHolder 
holder) {
+    public static NamedFacet create(PropertyLayoutMetadata propertyLayout, 
FacetHolder holder) {
         if(propertyLayout == null) {
             return null;
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/fb0f1273/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/RenderedAdjustedFacetForPropertyXml.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/RenderedAdjustedFacetForPropertyXml.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/RenderedAdjustedFacetForPropertyXml.java
index 63a3e4a..1947070 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/RenderedAdjustedFacetForPropertyXml.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/RenderedAdjustedFacetForPropertyXml.java
@@ -19,14 +19,14 @@
 
 package org.apache.isis.core.metamodel.facets.properties.propertylayout;
 
-import org.apache.isis.applib.layout.v1_0.Property;
+import org.apache.isis.applib.layout.v1_0.PropertyLayoutMetadata;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import 
org.apache.isis.core.metamodel.facets.objectvalue.renderedadjusted.RenderedAdjustedFacet;
 import 
org.apache.isis.core.metamodel.facets.objectvalue.renderedadjusted.RenderedAdjustedFacetAbstract;
 
 public class RenderedAdjustedFacetForPropertyXml extends 
RenderedAdjustedFacetAbstract {
 
-    public static RenderedAdjustedFacet create(final Property propertyLayout, 
FacetHolder holder) {
+    public static RenderedAdjustedFacet create(final PropertyLayoutMetadata 
propertyLayout, FacetHolder holder) {
         if(propertyLayout == null) {
             return null;
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/fb0f1273/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/TypicalLengthFacetForPropertyXml.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/TypicalLengthFacetForPropertyXml.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/TypicalLengthFacetForPropertyXml.java
index 1a193e5..dfbfb79 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/TypicalLengthFacetForPropertyXml.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/propertylayout/TypicalLengthFacetForPropertyXml.java
@@ -19,14 +19,14 @@
 
 package org.apache.isis.core.metamodel.facets.properties.propertylayout;
 
-import org.apache.isis.applib.layout.v1_0.Property;
+import org.apache.isis.applib.layout.v1_0.PropertyLayoutMetadata;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import 
org.apache.isis.core.metamodel.facets.objectvalue.typicallen.TypicalLengthFacet;
 import 
org.apache.isis.core.metamodel.facets.objectvalue.typicallen.TypicalLengthFacetAbstract;
 
 public class TypicalLengthFacetForPropertyXml extends 
TypicalLengthFacetAbstract {
 
-    public static TypicalLengthFacet create(Property propertyLayout, 
FacetHolder holder) {
+    public static TypicalLengthFacet create(PropertyLayoutMetadata 
propertyLayout, FacetHolder holder) {
         if(propertyLayout == null) {
             return null;
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/fb0f1273/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/layout/ObjectLayoutMetadataServiceDefault.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/layout/ObjectLayoutMetadataServiceDefault.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/layout/ObjectLayoutMetadataServiceDefault.java
new file mode 100644
index 0000000..c9daf91
--- /dev/null
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/layout/ObjectLayoutMetadataServiceDefault.java
@@ -0,0 +1,468 @@
+/**
+ *  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.services.layout;
+
+import java.io.IOException;
+import java.net.URL;
+import java.nio.charset.Charset;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.inject.Inject;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.common.io.Resources;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.isis.applib.annotation.DomainService;
+import org.apache.isis.applib.annotation.NatureOfService;
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.layout.v1_0.ActionHolder;
+import org.apache.isis.applib.layout.v1_0.ActionLayoutMetadata;
+import org.apache.isis.applib.layout.v1_0.CollectionLayoutMetadata;
+import org.apache.isis.applib.layout.v1_0.Column;
+import org.apache.isis.applib.layout.v1_0.ObjectLayoutMetadata;
+import org.apache.isis.applib.layout.v1_0.PropertyGroup;
+import org.apache.isis.applib.layout.v1_0.PropertyLayoutMetadata;
+import org.apache.isis.applib.layout.v1_0.Tab;
+import org.apache.isis.applib.layout.v1_0.TabGroup;
+import org.apache.isis.applib.services.i18n.TranslationService;
+import org.apache.isis.applib.services.jaxb.JaxbService;
+import org.apache.isis.applib.services.layout.ObjectLayoutMetadataService;
+import org.apache.isis.core.metamodel.deployment.DeploymentCategory;
+import org.apache.isis.core.metamodel.deployment.DeploymentCategoryAware;
+import org.apache.isis.core.metamodel.facetapi.FacetUtil;
+import 
org.apache.isis.core.metamodel.facets.actions.layout.ActionPositionFacetForActionXml;
+import 
org.apache.isis.core.metamodel.facets.actions.layout.BookmarkPolicyFacetForActionXml;
+import 
org.apache.isis.core.metamodel.facets.actions.layout.CssClassFaFacetForActionXml;
+import 
org.apache.isis.core.metamodel.facets.actions.layout.CssClassFacetForActionXml;
+import 
org.apache.isis.core.metamodel.facets.actions.layout.DescribedAsFacetForActionXml;
+import 
org.apache.isis.core.metamodel.facets.actions.layout.HiddenFacetForActionLayoutXml;
+import 
org.apache.isis.core.metamodel.facets.actions.layout.NamedFacetForActionXml;
+import 
org.apache.isis.core.metamodel.facets.collections.layout.CssClassFacetForCollectionXml;
+import 
org.apache.isis.core.metamodel.facets.collections.layout.DefaultViewFacetForCollectionXml;
+import 
org.apache.isis.core.metamodel.facets.collections.layout.DescribedAsFacetForCollectionXml;
+import 
org.apache.isis.core.metamodel.facets.collections.layout.HiddenFacetForCollectionXml;
+import 
org.apache.isis.core.metamodel.facets.collections.layout.NamedFacetForCollectionXml;
+import 
org.apache.isis.core.metamodel.facets.collections.layout.PagedFacetForCollectionXml;
+import 
org.apache.isis.core.metamodel.facets.collections.layout.SortedByFacetForCollectionXml;
+import 
org.apache.isis.core.metamodel.facets.members.order.annotprop.MemberOrderFacetXml;
+import 
org.apache.isis.core.metamodel.facets.object.membergroups.MemberGroupLayoutFacet;
+import 
org.apache.isis.core.metamodel.facets.properties.propertylayout.CssClassFacetForPropertyXml;
+import 
org.apache.isis.core.metamodel.facets.properties.propertylayout.DescribedAsFacetForPropertyXml;
+import 
org.apache.isis.core.metamodel.facets.properties.propertylayout.HiddenFacetForPropertyXml;
+import 
org.apache.isis.core.metamodel.facets.properties.propertylayout.LabelAtFacetForPropertyXml;
+import 
org.apache.isis.core.metamodel.facets.properties.propertylayout.MultiLineFacetForPropertyXml;
+import 
org.apache.isis.core.metamodel.facets.properties.propertylayout.NamedFacetForPropertyXml;
+import 
org.apache.isis.core.metamodel.facets.properties.propertylayout.RenderedAdjustedFacetForPropertyXml;
+import 
org.apache.isis.core.metamodel.facets.properties.propertylayout.TypicalLengthFacetForPropertyXml;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.SpecificationLoader;
+import org.apache.isis.core.metamodel.spec.SpecificationLoaderAware;
+import org.apache.isis.core.metamodel.spec.feature.Contributed;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
+import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+
+@DomainService(nature = NatureOfService.DOMAIN)
+public class ObjectLayoutMetadataServiceDefault
+        implements ObjectLayoutMetadataService, DeploymentCategoryAware , 
SpecificationLoaderAware {
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(ObjectLayoutMetadataServiceDefault.class);
+
+    private final Set<Class<?>> blacklisted = Sets.newConcurrentHashSet();
+
+    @Programmatic
+    public ObjectLayoutMetadata fromXml(Class<?> domainClass) {
+
+        if(blacklisted.contains(domainClass)) {
+            return null;
+        }
+
+        final String xml;
+        final String resourceName = domainClass.getSimpleName() + 
".layout.xml";
+        try {
+            xml = resourceContentOf(domainClass, resourceName);
+        } catch (IOException | IllegalArgumentException ex) {
+
+            blacklisted.add(domainClass);
+            final String message = String .format(
+                    "Failed to locate file %s (relative to %s.class); ex: %s)",
+                    resourceName, domainClass.getName(), ex.getMessage());
+
+            LOG.debug(message);
+            return null;
+        }
+
+        try {
+            final ObjectLayoutMetadata metadata = 
jaxbService.fromXml(ObjectLayoutMetadata.class, xml);
+            return metadata;
+        } catch(Exception ex) {
+
+            // note that we don't blacklist if the file exists but couldn't be 
parsed;
+            // the developer might fix so we will want to retry.
+            final String message = "Failed to parse " + resourceName + " file 
(" + ex.getMessage() + ")";
+            LOG.warn(message);
+
+            return null;
+        }
+    }
+
+    private static String resourceContentOf(final Class<?> cls, final String 
resourceName) throws IOException {
+        final URL url = Resources.getResource(cls, resourceName);
+        return Resources.toString(url, Charset.defaultCharset());
+    }
+
+
+    @Override
+    public ObjectLayoutMetadata normalize(final ObjectLayoutMetadata 
objectLayoutMetadata, final Class<?> domainClass) {
+        // caching (of whether validated) is enabled only in production.
+        return objectLayoutMetadata.isNormalized() && 
deploymentCategory.isProduction()
+                ? objectLayoutMetadata
+                : deriveAndOverwrite(objectLayoutMetadata, domainClass);
+    }
+
+    private ObjectLayoutMetadata deriveAndOverwrite(final ObjectLayoutMetadata 
objectLayoutMetadata, final Class<?> domainClass) {
+        synchronized (objectLayoutMetadata) {
+            final ObjectSpecification objectSpec = 
specificationLookup.loadSpecification(domainClass);
+            doDeriveAndOverwrite(objectLayoutMetadata, objectSpec);
+            objectLayoutMetadata.setNormalized(true);
+        }
+        return objectLayoutMetadata;
+    }
+
+    private void doDeriveAndOverwrite(final ObjectLayoutMetadata metadata, 
final ObjectSpecification objectSpec) {
+
+        final Map<String, OneToOneAssociation> oneToOneAssociationById =
+                ObjectMember.Util.mapById(getOneToOneAssociations(objectSpec));
+        final Map<String, OneToManyAssociation> oneToManyAssociationById =
+                
ObjectMember.Util.mapById(getOneToManyAssociations(objectSpec));
+        final Map<String, ObjectAction> objectActionById =
+                
ObjectMember.Util.mapById(objectSpec.getObjectActions(Contributed.INCLUDED));
+
+        derive(metadata, oneToOneAssociationById, oneToManyAssociationById, 
objectActionById);
+        overwrite(metadata, oneToOneAssociationById, oneToManyAssociationById, 
objectActionById);
+    }
+
+    /**
+     * Ensures that all object members (properties, collections and actions) 
are in the metadata.
+     *
+     * <p>
+     *     If they are missing then they will be added to default tabs 
(created on the fly if need be).
+     * </p>
+     */
+    private static void derive(
+            final ObjectLayoutMetadata metadata,
+            final Map<String, OneToOneAssociation> oneToOneAssociationById,
+            final Map<String, OneToManyAssociation> oneToManyAssociationById,
+            final Map<String, ObjectAction> objectActionById) {
+
+        final LinkedHashMap<String, PropertyLayoutMetadata> propertyIds = 
metadata.getAllPropertiesById();
+        final LinkedHashMap<String, CollectionLayoutMetadata> collectionIds = 
metadata.getAllCollectionsById();
+        final LinkedHashMap<String, ActionLayoutMetadata> actionIds = 
metadata.getAllActionsById();
+
+        final AtomicReference<PropertyGroup> defaultPropertyGroupRef = new 
AtomicReference<>();
+        final AtomicReference<Column> firstColumnRef = new AtomicReference<>();
+        final AtomicReference<TabGroup> lastTabGroupRef = new 
AtomicReference<>();
+
+        // capture the first column, and also
+        // capture the first property group (if any) with the default name 
('General')
+        metadata.visit(new ObjectLayoutMetadata.VisitorAdapter() {
+            @Override
+            public void visit(final Column column) {
+                firstColumnRef.compareAndSet(null, column);
+            }
+            @Override
+            public void visit(final PropertyGroup propertyGroup) {
+                
if(MemberGroupLayoutFacet.DEFAULT_GROUP.equals(propertyGroup.getName())) {
+                    defaultPropertyGroupRef.compareAndSet(null, propertyGroup);
+                }
+            }
+            @Override
+            public void visit(final TabGroup tabGroup) {
+                lastTabGroupRef.set(tabGroup);
+            }
+        });
+
+        // any missing properties will be added to the (first) 'General' 
property group found
+        // if there is no default ('General') property group
+        // then one will be added to the first Column of the first Tab.
+        final List<String>[] propertyIdTuple = 
surplusAndMissing(propertyIds.keySet(), oneToOneAssociationById.keySet());
+        final List<String> surplusPropertyIds = propertyIdTuple[0];
+        final List<String> missingPropertyIds = propertyIdTuple[1];
+
+        for (String surplusPropertyId : surplusPropertyIds) {
+            propertyIds.get(surplusPropertyId).setMetadataError("No such 
property");
+        }
+
+        if(!missingPropertyIds.isEmpty()) {
+            // ensure that there is a property group to use
+            boolean wasSet = defaultPropertyGroupRef.compareAndSet(null, new 
PropertyGroup(MemberGroupLayoutFacet.DEFAULT_GROUP));
+            final PropertyGroup defaultPropertyGroup = 
defaultPropertyGroupRef.get();
+            if(wasSet) {
+                
firstColumnRef.get().getPropertyGroups().add(defaultPropertyGroup);
+            }
+            for (final String propertyId : missingPropertyIds) {
+                defaultPropertyGroup.getProperties().add(new 
PropertyLayoutMetadata(propertyId));
+            }
+        }
+
+
+        // any missing collections will be added as tabs to the last TabGroup.
+        // If there is only a single tab group then a new TabGroup will be 
added first
+        final List<String>[] collectionIdTuple = 
surplusAndMissing(collectionIds.keySet(), oneToManyAssociationById.keySet());
+        final List<String> surplusCollectionIds = collectionIdTuple[0];
+        final List<String> missingCollectionIds = collectionIdTuple[1];
+
+        for (String surplusCollectionId : surplusCollectionIds) {
+            collectionIds.get(surplusCollectionId).setMetadataError("No such 
collection");
+        }
+
+        if(!missingCollectionIds.isEmpty()) {
+            while(metadata.getTabGroups().size() < 2) {
+                final TabGroup tabGroup = new TabGroup();
+                metadata.getTabGroups().add(tabGroup);
+                lastTabGroupRef.set(tabGroup);
+            }
+            final TabGroup lastTabGroup = lastTabGroupRef.get();
+            for (final String collectionId : missingCollectionIds) {
+                final Tab tab = new Tab();
+                lastTabGroup.getTabs().add(tab);
+                Column left = new Column(12);
+                tab.setLeft(left);
+                left.getCollections().add(new 
CollectionLayoutMetadata(collectionId));
+            }
+        }
+
+        // any missing actions will be added as domain object actions (in the 
header)
+        final List<String>[] actionIdTuple = 
surplusAndMissing(actionIds.keySet(), objectActionById.keySet());
+        final List<String> surplusActionIds = actionIdTuple[0];
+        final List<String> missingActionIds = actionIdTuple[1];
+
+        for (String surplusActionId : surplusActionIds) {
+            actionIds.get(surplusActionId).setMetadataError("No such action");
+        }
+
+        if(!missingActionIds.isEmpty()) {
+            for (String actionId : missingActionIds) {
+                metadata.getActions().add(new ActionLayoutMetadata(actionId));
+            }
+        }
+    }
+
+    /**
+     * Returns a 2-element array (a tuple) of [first-second, second-first]
+     */
+    static <T> List<T>[] surplusAndMissing(final java.util.Collection<T> 
first, final java.util.Collection<T> second){
+        final List<T> firstNotSecond = Lists.newArrayList(first);
+        firstNotSecond.removeAll(second);
+        final List<T> secondNotFirst = Lists.newArrayList(second);
+        secondNotFirst.removeAll(first);
+        return new List[]{ firstNotSecond, secondNotFirst };
+    }
+
+    private void overwrite(
+            final ObjectLayoutMetadata metadata,
+            final Map<String, OneToOneAssociation> oneToOneAssociationById,
+            final Map<String, OneToManyAssociation> oneToManyAssociationById,
+            final Map<String, ObjectAction> objectActionById) {
+
+        metadata.visit(new ObjectLayoutMetadata.VisitorAdapter() {
+            private final Map<String, int[]> propertySequenceByGroup = 
Maps.newHashMap();
+            private int actionDomainObjectSequence = 1;
+            private int actionPropertyGroupSequence = 1;
+            private int actionPropertySequence = 1;
+            private int actionCollectionSequence = 1;
+
+            @Override
+            public void visit(final ActionLayoutMetadata actionLayoutMetadata) 
{
+                final ActionHolder actionHolder = 
actionLayoutMetadata.getOwner();
+                final ObjectAction objectAction = 
objectActionById.get(actionLayoutMetadata.getId());
+                if(objectAction == null) {
+                    return;
+                }
+
+                final String memberOrderName;
+                final int memberOrderSequence;
+                if(actionHolder instanceof PropertyGroup) {
+                    final PropertyGroup propertyGroup = (PropertyGroup) 
actionHolder;
+                    final List<PropertyLayoutMetadata> properties = 
propertyGroup.getProperties();
+                    final PropertyLayoutMetadata propertyLayoutMetadata = 
properties.get(0); // any will do
+                    memberOrderName = propertyLayoutMetadata.getId();
+                    memberOrderSequence = actionPropertyGroupSequence++;
+                } else if(actionHolder instanceof PropertyLayoutMetadata) {
+                    final PropertyLayoutMetadata propertyLayoutMetadata = 
(PropertyLayoutMetadata) actionHolder;
+                    memberOrderName = propertyLayoutMetadata.getId();
+                    memberOrderSequence = actionPropertySequence++;
+                } else if(actionHolder instanceof CollectionLayoutMetadata) {
+                    final CollectionLayoutMetadata collectionLayoutMetadata = 
(CollectionLayoutMetadata) actionHolder;
+                    memberOrderName = collectionLayoutMetadata.getId();
+                    memberOrderSequence = actionCollectionSequence++;
+                } else {
+                    // DomainObject
+                    memberOrderName = null;
+                    memberOrderSequence = actionDomainObjectSequence++;
+                }
+                FacetUtil.addFacet(
+                        new MemberOrderFacetXml(memberOrderName, 
""+memberOrderSequence, translationService, objectAction));
+
+
+                if(actionHolder instanceof PropertyGroup) {
+                    if(actionLayoutMetadata.getPosition() == null ||
+                            actionLayoutMetadata.getPosition() == 
org.apache.isis.applib.annotation.ActionLayout.Position.BELOW ||
+                            actionLayoutMetadata.getPosition() == 
org.apache.isis.applib.annotation.ActionLayout.Position.RIGHT) {
+                        
actionLayoutMetadata.setPosition(org.apache.isis.applib.annotation.ActionLayout.Position.PANEL);
+                    }
+                } else if(actionHolder instanceof PropertyLayoutMetadata) {
+                    if(actionLayoutMetadata.getPosition() == null ||
+                            actionLayoutMetadata.getPosition() == 
org.apache.isis.applib.annotation.ActionLayout.Position.PANEL_DROPDOWN ||
+                            actionLayoutMetadata.getPosition() == 
org.apache.isis.applib.annotation.ActionLayout.Position.PANEL) {
+                        
actionLayoutMetadata.setPosition(org.apache.isis.applib.annotation.ActionLayout.Position.BELOW);
+                    }
+                } else {
+                    // doesn't do anything for DomainObject or Collection
+                    actionLayoutMetadata.setPosition(null);
+                }
+
+                
FacetUtil.addFacet(ActionPositionFacetForActionXml.create(actionLayoutMetadata, 
objectAction));
+                
FacetUtil.addFacet(BookmarkPolicyFacetForActionXml.create(actionLayoutMetadata, 
objectAction));
+                
FacetUtil.addFacet(CssClassFacetForActionXml.create(actionLayoutMetadata, 
objectAction));
+                
FacetUtil.addFacet(CssClassFaFacetForActionXml.create(actionLayoutMetadata, 
objectAction));
+                
FacetUtil.addFacet(DescribedAsFacetForActionXml.create(actionLayoutMetadata, 
objectAction));
+                
FacetUtil.addFacet(HiddenFacetForActionLayoutXml.create(actionLayoutMetadata, 
objectAction));
+                
FacetUtil.addFacet(NamedFacetForActionXml.create(actionLayoutMetadata, 
objectAction));
+            }
+
+            @Override
+            public void visit(final PropertyLayoutMetadata 
propertyLayoutMetadata) {
+                final OneToOneAssociation oneToOneAssociation = 
oneToOneAssociationById.get(propertyLayoutMetadata.getId());
+                if(oneToOneAssociation == null) {
+                    return;
+                }
+
+                
FacetUtil.addFacet(CssClassFacetForPropertyXml.create(propertyLayoutMetadata, 
oneToOneAssociation));
+                
FacetUtil.addFacet(DescribedAsFacetForPropertyXml.create(propertyLayoutMetadata,
 oneToOneAssociation));
+                
FacetUtil.addFacet(HiddenFacetForPropertyXml.create(propertyLayoutMetadata, 
oneToOneAssociation));
+                
FacetUtil.addFacet(LabelAtFacetForPropertyXml.create(propertyLayoutMetadata, 
oneToOneAssociation));
+                
FacetUtil.addFacet(MultiLineFacetForPropertyXml.create(propertyLayoutMetadata, 
oneToOneAssociation));
+                
FacetUtil.addFacet(NamedFacetForPropertyXml.create(propertyLayoutMetadata, 
oneToOneAssociation));
+                
FacetUtil.addFacet(RenderedAdjustedFacetForPropertyXml.create(propertyLayoutMetadata,
 oneToOneAssociation));
+                
FacetUtil.addFacet(TypicalLengthFacetForPropertyXml.create(propertyLayoutMetadata,
 oneToOneAssociation));
+
+                // @MemberOrder#name based on owning property group, 
@MemberOrder#sequence monotonically increasing
+                final PropertyGroup propertyGroup = 
propertyLayoutMetadata.getOwner();
+                final String groupName = propertyGroup.getName();
+                final String sequence = nextInSequenceFor(groupName);
+                FacetUtil.addFacet(
+                        new MemberOrderFacetXml(groupName, sequence, 
translationService, oneToOneAssociation));
+            }
+
+            @Override
+            public void visit(final CollectionLayoutMetadata 
collectionLayoutMetadata) {
+                final OneToManyAssociation oneToManyAssociation = 
oneToManyAssociationById.get(collectionLayoutMetadata.getId());
+                if(oneToManyAssociation == null) {
+                    return;
+                }
+
+                
FacetUtil.addFacet(CssClassFacetForCollectionXml.create(collectionLayoutMetadata,
 oneToManyAssociation));
+                
FacetUtil.addFacet(DefaultViewFacetForCollectionXml.create(collectionLayoutMetadata,
 oneToManyAssociation));
+                
FacetUtil.addFacet(DescribedAsFacetForCollectionXml.create(collectionLayoutMetadata,
 oneToManyAssociation));
+                
FacetUtil.addFacet(HiddenFacetForCollectionXml.create(collectionLayoutMetadata, 
oneToManyAssociation));
+                
FacetUtil.addFacet(NamedFacetForCollectionXml.create(collectionLayoutMetadata, 
oneToManyAssociation));
+                
FacetUtil.addFacet(PagedFacetForCollectionXml.create(collectionLayoutMetadata, 
oneToManyAssociation));
+                
FacetUtil.addFacet(SortedByFacetForCollectionXml.create(collectionLayoutMetadata,
 oneToManyAssociation));
+
+                // @MemberOrder#name based on the collection's id (so that 
each has a single "member group")
+                final String groupName = collectionLayoutMetadata.getId();
+                final String sequence = nextInSequenceFor(groupName);
+                FacetUtil.addFacet(
+                        new MemberOrderFacetXml(groupName, sequence, 
translationService, oneToManyAssociation));
+
+                // if there is only a single column and no other contents, 
then copy the collection Id onto the tab'
+                final Column column = collectionLayoutMetadata.getOwner();
+                final Tab tab = column.getOwner();
+                if(tab.getContents().size() == 1) {
+                    tab.setName(collectionLayoutMetadata.getNamed());
+                }
+            }
+
+            private String nextInSequenceFor(final String propertyGroupName) {
+                synchronized (propertySequenceByGroup) {
+                    int[] holder = 
propertySequenceByGroup.get(propertyGroupName);
+                    if(holder == null) {
+                        holder = new int[]{0};
+                        propertySequenceByGroup.put(propertyGroupName, holder);
+                    }
+                    holder[0]++;
+                    return ""+holder[0];
+                }
+            }
+        });
+    }
+
+    private static List<OneToOneAssociation> getOneToOneAssociations(final 
ObjectSpecification objectSpec) {
+        List associations = objectSpec
+                .getAssociations(Contributed.INCLUDED, 
ObjectAssociation.Filters.PROPERTIES);
+        return associations;
+    }
+    private static List<OneToManyAssociation> getOneToManyAssociations(final 
ObjectSpecification objectSpec) {
+        List associations = objectSpec
+                .getAssociations(Contributed.INCLUDED, 
ObjectAssociation.Filters.COLLECTIONS);
+        return associations;
+    }
+
+
+    @Override
+    public String toXml(final ObjectLayoutMetadata objectLayoutMetadata) {
+        return jaxbService.toXml(objectLayoutMetadata);
+    }
+
+
+    //region > injected dependencies
+    private DeploymentCategory deploymentCategory;
+
+    @Override
+    public void setDeploymentCategory(final DeploymentCategory 
deploymentCategory) {
+        this.deploymentCategory = deploymentCategory;
+    }
+
+    private SpecificationLoader specificationLookup;
+
+    @Override
+    public void setSpecificationLoader(final SpecificationLoader 
specificationLookup) {
+        this.specificationLookup = specificationLookup;
+    }
+
+
+    @Inject
+    JaxbService jaxbService;
+
+    @Inject
+    TranslationService translationService;
+
+    //endregion
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/fb0f1273/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java
index 8b56996..9a23a1d 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java
@@ -48,7 +48,6 @@ public class MetaModelServiceDefault implements 
MetaModelService, SpecificationL
     private final static Logger LOG = 
LoggerFactory.getLogger(MetaModelServiceDefault.class);
 
 
-
     //region > fromObjectType, toObjectType
     @Programmatic
     public Class<?> fromObjectType(final String objectType) {

Reply via email to