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

[3/3] isis git commit: ISIS-993: unreferenced properties/actions/collectoins handling

ISIS-993: unreferenced properties/actions/collectoins handling


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

Branch: refs/heads/ISIS-993
Commit: 8fcac96481cb21a47d8db0a64a76fa4693d5582d
Parents: fe46a78
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Wed Feb 3 21:22:30 2016 +0000
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Wed Feb 3 21:22:30 2016 +0000

----------------------------------------------------------------------
 .../applib/layout/bootstrap3/bootstrap3.xsd     |  29 ++-
 .../schema/applib/layout/common/common.xsd      |   6 +-
 .../isis/applib/layout/bootstrap3/BS3Col.java   |  41 +---
 .../isis/applib/layout/bootstrap3/BS3Grid.java  |  31 ++-
 .../isis/applib/layout/bootstrap3/BS3Row.java   |  15 +-
 .../isis/applib/layout/bootstrap3/BS3Tab.java   |   7 +-
 .../applib/layout/bootstrap3/BS3TabGroup.java   |  54 ++++-
 .../isis/applib/layout/common/FieldSet.java     |  81 +++++++-
 .../isis/applib/layout/common/GridAbstract.java |   2 +-
 .../applib/layout/fixedcols/FCTabGroup.java     |   9 +-
 .../isis/core/metamodel/facetapi/FacetUtil.java |  21 +-
 .../facets/object/grid/GridFacetDefault.java    |   3 +
 .../grid/GridNormalizerServiceAbstract.java     | 110 ++++++----
 .../bootstrap3/GridNormalizerServiceBS3.java    | 201 +++++++++++++------
 .../grid/fixedcols/GridNormalizerServiceFC.java |  39 +---
 .../metamodel/services/grid/BS3GridTest.java    |  24 ++-
 .../java/domainapp/dom/simple/SimpleObject.java |   2 +
 .../dom/simple/SimpleObject.layout.xml          |  70 +++----
 18 files changed, 473 insertions(+), 272 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/8fcac964/adocs/documentation/src/main/asciidoc/schema/applib/layout/bootstrap3/bootstrap3.xsd
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/schema/applib/layout/bootstrap3/bootstrap3.xsd b/adocs/documentation/src/main/asciidoc/schema/applib/layout/bootstrap3/bootstrap3.xsd
index 7259fcc..12c9de7 100644
--- a/adocs/documentation/src/main/asciidoc/schema/applib/layout/bootstrap3/bootstrap3.xsd
+++ b/adocs/documentation/src/main/asciidoc/schema/applib/layout/bootstrap3/bootstrap3.xsd
@@ -12,18 +12,10 @@
     <xs:element name="grid" type="tns:grid"/>
 
     <xs:complexType name="grid">
-        <xs:complexContent>
-            <xs:extension base="tns:bs3ElementAbstract">
-                <xs:sequence>
-                    <xs:element name="row" type="tns:row" maxOccurs="unbounded"/>
-                    <xs:element name="metadataErrors" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
-                </xs:sequence>
-            </xs:extension>
-        </xs:complexContent>
-    </xs:complexType>
-
-    <xs:complexType name="bs3ElementAbstract" abstract="true">
-        <xs:sequence/>
+        <xs:sequence>
+            <xs:element name="row" type="tns:row" maxOccurs="unbounded"/>
+            <xs:element name="metadataError" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
         <xs:attribute name="cssClass" type="xs:string"/>
     </xs:complexType>
 
@@ -36,12 +28,18 @@
                         <xs:element ref="tns:clearFixVisible"/>
                         <xs:element ref="tns:clearFixHidden"/>
                     </xs:choice>
+                    <xs:element name="metadataError" type="xs:string" minOccurs="0"/>
                 </xs:sequence>
                 <xs:attribute name="id" type="xs:string"/>
             </xs:extension>
         </xs:complexContent>
     </xs:complexType>
 
+    <xs:complexType name="bs3ElementAbstract" abstract="true">
+        <xs:sequence/>
+        <xs:attribute name="cssClass" type="xs:string"/>
+    </xs:complexType>
+
     <xs:complexType name="col">
         <xs:complexContent>
             <xs:extension base="tns:bs3RowContent">
@@ -52,12 +50,11 @@
                     <xs:element name="tabGroup" type="tns:tabGroup" minOccurs="0" maxOccurs="unbounded"/>
                     <xs:element ref="ns1:fieldSet" minOccurs="0" maxOccurs="unbounded"/>
                     <xs:element ref="ns1:collection" minOccurs="0" maxOccurs="unbounded"/>
+                    <xs:element name="metadataError" type="xs:string" minOccurs="0"/>
                 </xs:sequence>
                 <xs:attribute name="id" type="xs:string"/>
                 <xs:attribute name="span" type="xs:int" use="required"/>
                 <xs:attribute name="unreferencedActions" type="xs:boolean"/>
-                <xs:attribute name="unreferencedCollections" type="xs:boolean"/>
-                <xs:attribute name="unreferencedProperties" type="xs:boolean"/>
             </xs:extension>
         </xs:complexContent>
     </xs:complexType>
@@ -75,8 +72,10 @@
         <xs:complexContent>
             <xs:extension base="tns:bs3ElementAbstract">
                 <xs:sequence>
-                    <xs:element name="tab" type="tns:tab" maxOccurs="unbounded"/>
+                    <xs:element name="tab" type="tns:tab" minOccurs="0" maxOccurs="unbounded"/>
+                    <xs:element name="metadataError" type="xs:string" minOccurs="0"/>
                 </xs:sequence>
+                <xs:attribute name="unreferencedCollections" type="xs:boolean"/>
             </xs:extension>
         </xs:complexContent>
     </xs:complexType>

http://git-wip-us.apache.org/repos/asf/isis/blob/8fcac964/adocs/documentation/src/main/asciidoc/schema/applib/layout/common/common.xsd
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/schema/applib/layout/common/common.xsd b/adocs/documentation/src/main/asciidoc/schema/applib/layout/common/common.xsd
index 992a378..5b614a9 100644
--- a/adocs/documentation/src/main/asciidoc/schema/applib/layout/common/common.xsd
+++ b/adocs/documentation/src/main/asciidoc/schema/applib/layout/common/common.xsd
@@ -43,9 +43,13 @@
   <xs:complexType name="fieldSet">
     <xs:sequence>
       <xs:element ref="tns:action" minOccurs="0" maxOccurs="unbounded"/>
-      <xs:element ref="tns:property" maxOccurs="unbounded"/>
+      <xs:element ref="tns:property" minOccurs="0" maxOccurs="unbounded"/>
+      <xs:element name="metadataError" type="xs:string" minOccurs="0"/>
     </xs:sequence>
     <xs:attribute name="name" type="xs:string" use="required"/>
+    <xs:attribute name="id" type="xs:string"/>
+    <xs:attribute name="unreferencedActions" type="xs:boolean"/>
+    <xs:attribute name="unreferencedProperties" type="xs:boolean"/>
   </xs:complexType>
 
   <xs:complexType name="property">

http://git-wip-us.apache.org/repos/asf/isis/blob/8fcac964/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Col.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Col.java b/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Col.java
index 752c7e4..f51fcba 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Col.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Col.java
@@ -118,43 +118,6 @@ public class BS3Col extends BS3RowContent
     }
 
 
-    private Boolean unreferencedProperties;
-    /**
-     * Whether the first fieldset in this column should be used to hold any unreferenced properties (contributed or &quot;native&quot;).
-     *
-     * <p>
-     *     Any layout must have precisely one column that has this attribute set, and that column must have at least one {@link FieldSet}.
-     * </p>
-     */
-    @XmlAttribute(required = false)
-    public Boolean isUnreferencedProperties() {
-        return unreferencedProperties;
-    }
-
-    public void setUnreferencedProperties(final Boolean unreferencedProperties) {
-        this.unreferencedProperties = unreferencedProperties;
-    }
-
-
-    private Boolean unreferencedCollections;
-    /**
-     * Whether this column should be used to hold any unreferenced collections (contributed or &quot;native&quot;).
-     *
-     * <p>
-     *     Any layout must have precisely one column that has this attribute set.
-     * </p>
-     */
-    @XmlAttribute(required = false)
-    public Boolean isUnreferencedCollections() {
-        return unreferencedCollections;
-    }
-
-    public void setUnreferencedCollections(final Boolean unreferencedCollections) {
-        this.unreferencedCollections = unreferencedCollections;
-    }
-
-
-
 
     private DomainObjectLayoutData domainObject;
 
@@ -241,6 +204,10 @@ public class BS3Col extends BS3RowContent
     }
 
 
+    @Override
+    public String getPath() {
+        return getId() != null? getId(): super.getPath();
+    }
 
 
 

http://git-wip-us.apache.org/repos/asf/isis/blob/8fcac964/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Grid.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Grid.java b/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Grid.java
index 6360480..f5e9d5d 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Grid.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Grid.java
@@ -18,7 +18,6 @@
  */
 package org.apache.isis.applib.layout.bootstrap3;
 
-import java.util.ArrayList;
 import java.util.LinkedHashMap;
 import java.util.List;
 
@@ -28,6 +27,7 @@ import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlTransient;
 import javax.xml.bind.annotation.XmlType;
 
+import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 
 import org.apache.isis.applib.annotation.Programmatic;
@@ -54,8 +54,8 @@ import org.apache.isis.applib.services.dto.Dto;
 @XmlType(
         name = "grid"
         , propOrder = {
-            "rows"
-            , "metadataErrors"
+            "rows",
+            "metadataErrors"
         }
 )
 public class BS3Grid extends GridAbstract implements BS3Element, Dto, BS3RowOwner {
@@ -91,9 +91,7 @@ public class BS3Grid extends GridAbstract implements BS3Element, Dto, BS3RowOwne
 
 
 
-    private List<BS3Row> rows = new ArrayList<BS3Row>(){{
-        add(new BS3Row());
-    }};
+    private List<BS3Row> rows = Lists.newArrayList();
 
     // no wrapper
     @XmlElement(name = "row", required = true)
@@ -107,6 +105,27 @@ public class BS3Grid extends GridAbstract implements BS3Element, Dto, BS3RowOwne
 
 
 
+    private List<String> metadataErrors = Lists.newArrayList();
+
+    /**
+     * For diagnostics; populated by the framework if and only if a metadata error.
+     */
+    @XmlElement(name = "metadataError", required = false)
+    public List<String> getMetadataErrors() {
+        return metadataErrors;
+    }
+
+    public void setMetadataErrors(final List<String> metadataErrors) {
+        this.metadataErrors = metadataErrors;
+    }
+
+
+
+
+    private BS3RowOwner owner;
+
+
+
     interface Visitor extends Grid.Visitor {
         void visit(final BS3Grid bs3Page);
         void visit(final BS3Row bs3Row);

http://git-wip-us.apache.org/repos/asf/isis/blob/8fcac964/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Row.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Row.java b/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Row.java
index d05dbf8..097c883 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Row.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Row.java
@@ -18,7 +18,6 @@
  */
 package org.apache.isis.applib.layout.bootstrap3;
 
-import java.util.ArrayList;
 import java.util.List;
 
 import javax.xml.bind.annotation.XmlAttribute;
@@ -28,6 +27,8 @@ import javax.xml.bind.annotation.XmlElementRefs;
 import javax.xml.bind.annotation.XmlTransient;
 import javax.xml.bind.annotation.XmlType;
 
+import com.google.common.collect.Lists;
+
 /**
  * Contains a row of content, either on the top-level {@link BS3Grid page} or at any other lower-level element that can
  * contain rows, eg {@link BS3Tab tabs}.
@@ -64,9 +65,7 @@ public class BS3Row extends BS3ElementAbstract implements HasCssId, BS3RowConten
 
 
 
-    private List<BS3RowContent> cols = new ArrayList<BS3RowContent>(){{
-        add(new BS3Col());
-    }};
+    private List<BS3RowContent> cols = Lists.newArrayList();
 
     // no wrapper
     @XmlElementRefs({
@@ -84,6 +83,13 @@ public class BS3Row extends BS3ElementAbstract implements HasCssId, BS3RowConten
 
 
 
+    @Override
+    public String getPath() {
+        return getId() != null? getId(): super.getPath();
+    }
+
+
+
     private String metadataError;
 
     /**
@@ -101,6 +107,7 @@ public class BS3Row extends BS3ElementAbstract implements HasCssId, BS3RowConten
 
     private BS3RowOwner owner;
 
+
     /**
      * Owner.
      *

http://git-wip-us.apache.org/repos/asf/isis/blob/8fcac964/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Tab.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Tab.java b/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Tab.java
index 57e7ca5..f1d4256 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Tab.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Tab.java
@@ -18,7 +18,6 @@
  */
 package org.apache.isis.applib.layout.bootstrap3;
 
-import java.util.ArrayList;
 import java.util.List;
 
 import javax.xml.bind.annotation.XmlAttribute;
@@ -27,6 +26,7 @@ import javax.xml.bind.annotation.XmlTransient;
 import javax.xml.bind.annotation.XmlType;
 
 import com.google.common.base.Predicate;
+import com.google.common.collect.Lists;
 
 /**
  * Represents a tab within a {@link BS3TabGroup tab group}.
@@ -57,10 +57,7 @@ public class BS3Tab extends BS3ElementAbstract implements BS3RowOwner {
     }
 
 
-    // at least one row
-    private List<BS3Row> rows = new ArrayList<BS3Row>(){{
-        add(new BS3Row());
-    }};
+    private List<BS3Row> rows = Lists.newArrayList();
 
     // no wrapper
     @XmlElement(name = "row", required = true)

http://git-wip-us.apache.org/repos/asf/isis/blob/8fcac964/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3TabGroup.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3TabGroup.java b/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3TabGroup.java
index c96634a..6f65bf7 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3TabGroup.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3TabGroup.java
@@ -18,20 +18,23 @@
  */
 package org.apache.isis.applib.layout.bootstrap3;
 
-import java.util.ArrayList;
 import java.util.List;
 
+import javax.xml.bind.annotation.XmlAttribute;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlTransient;
 import javax.xml.bind.annotation.XmlType;
 
+import com.google.common.collect.Lists;
+
 /**
  * Represents a tab group containing one or more {@link BS3Tab tab}s.
  */
 @XmlType(
         name = "tabGroup"
         , propOrder = {
-            "tabs"
+            "tabs",
+            "metadataError"
         }
 )
 public class BS3TabGroup extends BS3ElementAbstract implements BS3TabOwner {
@@ -39,12 +42,31 @@ public class BS3TabGroup extends BS3ElementAbstract implements BS3TabOwner {
     private static final long serialVersionUID = 1L;
 
 
-    private List<BS3Tab> tabs = new ArrayList<BS3Tab>(){{
-        add(new BS3Tab());
-    }};
 
-    // no wrapper
-    @XmlElement(name = "tab", required = true)
+    private Boolean unreferencedCollections;
+    /**
+     * Whether this column should be used to hold any unreferenced collections (contributed or &quot;native&quot;).
+     *
+     * <p>
+     *     Any layout must have precisely one column that has this attribute set.
+     * </p>
+     */
+    @XmlAttribute(required = false)
+    public Boolean isUnreferencedCollections() {
+        return unreferencedCollections;
+    }
+
+    public void setUnreferencedCollections(final Boolean unreferencedCollections) {
+        this.unreferencedCollections = unreferencedCollections;
+    }
+
+
+
+
+    private List<BS3Tab> tabs = Lists.newArrayList();
+
+    // no wrapper; required=false because may be auto-generated
+    @XmlElement(name = "tab", required = false)
     public List<BS3Tab> getTabs() {
         return tabs;
     }
@@ -72,5 +94,23 @@ public class BS3TabGroup extends BS3ElementAbstract implements BS3TabOwner {
         this.owner = owner;
     }
 
+
+
+    private String metadataError;
+
+    /**
+     * For diagnostics; populated by the framework if and only if a metadata error.
+     */
+    @XmlElement(required = false)
+    public String getMetadataError() {
+        return metadataError;
+    }
+
+    public void setMetadataError(final String metadataError) {
+        this.metadataError = metadataError;
+    }
+
+
+
 }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/8fcac964/core/applib/src/main/java/org/apache/isis/applib/layout/common/FieldSet.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/common/FieldSet.java b/core/applib/src/main/java/org/apache/isis/applib/layout/common/FieldSet.java
index fe0a3fb..40769eb 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/common/FieldSet.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/common/FieldSet.java
@@ -19,7 +19,6 @@
 package org.apache.isis.applib.layout.common;
 
 import java.io.Serializable;
-import java.util.ArrayList;
 import java.util.List;
 
 import javax.annotation.Nullable;
@@ -49,6 +48,7 @@ import org.apache.isis.applib.annotation.Programmatic;
                 "name"
                 , "actions"
                 , "properties"
+                , "metadataError"
         }
 )
 public class FieldSet implements MemberRegion, ActionLayoutDataOwner, Serializable {
@@ -62,6 +62,63 @@ public class FieldSet implements MemberRegion, ActionLayoutDataOwner, Serializab
         setName(name);
     }
 
+
+
+    private String id;
+
+    /**
+     * As per &lt;div id=&quot;...&quot;&gt;...&lt;/div&gt; : must be unique across entire page.
+     */
+    @XmlAttribute(required = false)
+    public String getId() {
+        return id;
+    }
+
+    public void setId(final String id) {
+        this.id = id;
+    }
+
+
+
+    private Boolean unreferencedActions;
+
+    /**
+     * Whether this fieldset should be used to hold any unreferenced actions (contributed or &quot;native&quot;).
+     *
+     * <p>
+     *     Any layout must have precisely one fieldset that has this attribute set.
+     * </p>
+     */
+    @XmlAttribute(required = false)
+    public Boolean isUnreferencedActions() {
+        return unreferencedActions;
+    }
+
+    public void setUnreferencedActions(final Boolean unreferencedActions) {
+        this.unreferencedActions = unreferencedActions;
+    }
+
+
+    private Boolean unreferencedProperties;
+    /**
+     * Whether this fieldset should be used to hold any unreferenced properties (contributed or &quot;native&quot;).
+     *
+     * <p>
+     *     Any grid layout must have precisely one fieldset that has this attribute set.
+     * </p>
+     */
+    @XmlAttribute(required = false)
+    public Boolean isUnreferencedProperties() {
+        return unreferencedProperties;
+    }
+
+    public void setUnreferencedProperties(final Boolean unreferencedProperties) {
+        this.unreferencedProperties = unreferencedProperties;
+    }
+
+
+
+
     private String name;
 
     /**
@@ -92,11 +149,10 @@ public class FieldSet implements MemberRegion, ActionLayoutDataOwner, Serializab
 
 
 
-    private List<PropertyLayoutData> properties = new ArrayList<PropertyLayoutData>() {{
-        add(new PropertyLayoutData());
-    }};
+    private List<PropertyLayoutData> properties = Lists.newArrayList();
 
-    @XmlElement(name = "property", required = true)
+    // no wrapper; required=false because may be auto-generated
+    @XmlElement(name = "property", required = false)
     public List<PropertyLayoutData> getProperties() {
         return properties;
     }
@@ -141,6 +197,21 @@ public class FieldSet implements MemberRegion, ActionLayoutDataOwner, Serializab
 
 
 
+    private String metadataError;
+
+    /**
+     * For diagnostics; populated by the framework if and only if a metadata error.
+     */
+    @XmlElement(required = false)
+    public String getMetadataError() {
+        return metadataError;
+    }
+
+    public void setMetadataError(final String metadataError) {
+        this.metadataError = metadataError;
+    }
+
+
 
     public static class Util {
         private Util(){}

http://git-wip-us.apache.org/repos/asf/isis/blob/8fcac964/core/applib/src/main/java/org/apache/isis/applib/layout/common/GridAbstract.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/common/GridAbstract.java b/core/applib/src/main/java/org/apache/isis/applib/layout/common/GridAbstract.java
index 70cee11..2efb85c 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/common/GridAbstract.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/common/GridAbstract.java
@@ -27,7 +27,6 @@ import com.google.common.collect.Maps;
 
 import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.layout.bootstrap3.BS3Grid;
-import org.apache.isis.applib.layout.fixedcols.FCColumn;
 import org.apache.isis.applib.services.layout.GridService;
 
 /**
@@ -37,6 +36,7 @@ import org.apache.isis.applib.services.layout.GridService;
  *     It is used by the {@link GridService} as a common based type for any layouts read in from XML.
  * </p>
  */
+@XmlTransient // ignore this class
 public abstract class GridAbstract implements Grid {
 
     private boolean normalized;

http://git-wip-us.apache.org/repos/asf/isis/blob/8fcac964/core/applib/src/main/java/org/apache/isis/applib/layout/fixedcols/FCTabGroup.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/fixedcols/FCTabGroup.java b/core/applib/src/main/java/org/apache/isis/applib/layout/fixedcols/FCTabGroup.java
index 567f278..d4ad9dc 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/fixedcols/FCTabGroup.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/fixedcols/FCTabGroup.java
@@ -19,7 +19,6 @@
 package org.apache.isis.applib.layout.fixedcols;
 
 import java.io.Serializable;
-import java.util.ArrayList;
 import java.util.List;
 
 import javax.xml.bind.annotation.XmlElement;
@@ -28,6 +27,7 @@ import javax.xml.bind.annotation.XmlType;
 
 import com.google.common.base.Predicate;
 import com.google.common.collect.FluentIterable;
+import com.google.common.collect.Lists;
 
 import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.layout.common.Owned;
@@ -42,13 +42,10 @@ public class FCTabGroup implements FCColumnOwner, Serializable, Owned<FCTabGroup
 
     private static final long serialVersionUID = 1L;
 
-    // must be at least one tab.
-    private List<FCTab> tabs = new ArrayList<FCTab>(){{
-        add(new FCTab());
-    }};
+    private List<FCTab> tabs = Lists.newArrayList();
 
     // no wrapper
-    @XmlElement(name = "tab", required = true)
+    @XmlElement(name = "tab", required = false)
     public List<FCTab> getTabs() {
         return tabs;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/8fcac964/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facetapi/FacetUtil.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facetapi/FacetUtil.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facetapi/FacetUtil.java
index b5e67f7..8d9eb73 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facetapi/FacetUtil.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facetapi/FacetUtil.java
@@ -33,6 +33,26 @@ public final class FacetUtil {
     private FacetUtil() {
     }
 
+    public static void addOrReplaceFacet(final Facet facet) {
+        if (facet == null) {
+            return;
+        }
+        final FacetHolder facetHolder = facet.getFacetHolder();
+        final List<Facet> facets = facetHolder.getFacets(new Filter<Facet>() {
+            @Override
+            public boolean accept(final Facet each) {
+                return facet.facetType() == each.facetType() && facet.getClass() == each.getClass();
+            }
+        });
+        if(facets.size() == 1) {
+            final Facet existingFacet = facets.get(0);
+            final Facet underlyingFacet = existingFacet.getUnderlyingFacet();
+            facetHolder.removeFacet(existingFacet);
+            facet.setUnderlyingFacet(underlyingFacet);
+        }
+        facetHolder.addFacet(facet);
+    }
+
     /**
      * Attaches the {@link Facet} to its {@link Facet#getFacetHolder() facet
      * holder}.
@@ -151,5 +171,4 @@ public final class FacetUtil {
         }
     }
 
-
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/8fcac964/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/grid/GridFacetDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/grid/GridFacetDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/grid/GridFacetDefault.java
index f2de0fc..596829d 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/grid/GridFacetDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/grid/GridFacetDefault.java
@@ -104,6 +104,9 @@ public class GridFacetDefault
         final Class<?> domainClass = getSpecification().getCorrespondingClass();
 
         gridNormalizerService.normalize(grid, domainClass);
+
+        grid.setNormalized(true);
+
         return grid;
     }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/8fcac964/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridNormalizerServiceAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridNormalizerServiceAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridNormalizerServiceAbstract.java
index 1c0ab06..91d8aba 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridNormalizerServiceAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridNormalizerServiceAbstract.java
@@ -26,6 +26,10 @@ import com.google.common.base.Strings;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.isis.applib.DomainObjectContainer;
 import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.layout.common.ActionLayoutData;
 import org.apache.isis.applib.layout.common.ActionLayoutDataOwner;
@@ -39,6 +43,8 @@ import org.apache.isis.applib.layout.fixedcols.FCColumnOwner;
 import org.apache.isis.applib.layout.fixedcols.FCGrid;
 import org.apache.isis.applib.layout.fixedcols.FCTab;
 import org.apache.isis.applib.services.i18n.TranslationService;
+import org.apache.isis.applib.services.jaxb.JaxbService;
+import org.apache.isis.core.metamodel.facetapi.Facet;
 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;
@@ -65,6 +71,7 @@ import org.apache.isis.core.metamodel.facets.properties.propertylayout.RenderedA
 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;
@@ -72,7 +79,10 @@ 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 abstract class GridNormalizerServiceAbstract<G extends Grid> implements GridNormalizerService<G> {
+public abstract class GridNormalizerServiceAbstract<G extends Grid>
+        implements GridNormalizerService<G>, SpecificationLoaderAware {
+
+    private static final Logger LOG = LoggerFactory.getLogger(GridNormalizerServiceAbstract.class);
 
     private final Class<G> gridImplementation;
     private final String tns;
@@ -118,9 +128,17 @@ public abstract class GridNormalizerServiceAbstract<G extends Grid> implements G
         final Map<String, ObjectAction> objectActionById =
                 ObjectMember.Util.mapById(objectSpec.getObjectActions(Contributed.INCLUDED));
 
-        final boolean validation = validateAndDerive(grid, oneToOneAssociationById, oneToManyAssociationById, objectActionById);
-        if(validation) {
+        final boolean valid =
+                validateAndDerive(
+                    grid, oneToOneAssociationById, oneToManyAssociationById, objectActionById, objectSpec);
+        if (valid) {
             overwrite(grid, oneToOneAssociationById, oneToManyAssociationById, objectActionById);
+            if(LOG.isDebugEnabled()) {
+                LOG.debug("Grid:\n\n" + jaxbService.toXml(grid) + "\n\n");
+            }
+        } else {
+            container.warnUser("Grid metadata errors; check the error log");
+            LOG.error("Grid metadata errors:\n\n" + jaxbService.toXml(grid) + "\n\n");
         }
     }
 
@@ -131,11 +149,16 @@ public abstract class GridNormalizerServiceAbstract<G extends Grid> implements G
             final Grid grid,
             final Map<String, OneToOneAssociation> oneToOneAssociationById,
             final Map<String, OneToManyAssociation> oneToManyAssociationById,
-            final Map<String, ObjectAction> objectActionById);
-
-
-
+            final Map<String, ObjectAction> objectActionById,
+            final ObjectSpecification objectSpec);
 
+    /**
+     * Overwrites (replaces) any existing facets in the metamodel with info taken from the grid.
+     *
+     * <p>
+     *     This code uses {@link FacetUtil#addOrReplaceFacet(Facet)} because the layout might be changed multiple times.
+     * </p>
+     */
     protected void overwrite(
             final G fcGrid,
             final Map<String, OneToOneAssociation> oneToOneAssociationById,
@@ -143,9 +166,9 @@ public abstract class GridNormalizerServiceAbstract<G extends Grid> implements G
             final Map<String, ObjectAction> objectActionById) {
 
         final Map<String, int[]> propertySequenceByGroup = Maps.newHashMap();
-
         fcGrid.visit(new FCGrid.VisitorAdapter() {
             private int collectionSequence = 1;
+
             private int actionDomainObjectSequence = 1;
             private int actionPropertyGroupSequence = 1;
             private int actionPropertySequence = 1;
@@ -176,14 +199,17 @@ public abstract class GridNormalizerServiceAbstract<G extends Grid> implements G
                     memberOrderName = collectionLayoutData.getId();
                     memberOrderSequence = actionCollectionSequence++;
                 } else {
-                    // DomainObject
+                    // means' don't add: any existing metadata should be preserved
                     memberOrderName = null;
                     memberOrderSequence = actionDomainObjectSequence++;
                 }
-                FacetUtil.addFacet(
-                        new MemberOrderFacetXml(memberOrderName, ""+memberOrderSequence, translationService, objectAction));
-
+                if(memberOrderName != null) {
+                    FacetUtil.addOrReplaceFacet(
+                            new MemberOrderFacetXml(memberOrderName, "" + memberOrderSequence, translationService,
+                                    objectAction));
+                }
 
+                // fix up the action position if required
                 if(actionLayoutDataOwner instanceof FieldSet) {
                     if(actionLayoutData.getPosition() == null ||
                             actionLayoutData.getPosition() == org.apache.isis.applib.annotation.ActionLayout.Position.BELOW ||
@@ -201,13 +227,13 @@ public abstract class GridNormalizerServiceAbstract<G extends Grid> implements G
                     actionLayoutData.setPosition(null);
                 }
 
-                FacetUtil.addFacet(ActionPositionFacetForActionXml.create(actionLayoutData, objectAction));
-                FacetUtil.addFacet(BookmarkPolicyFacetForActionXml.create(actionLayoutData, objectAction));
-                FacetUtil.addFacet(CssClassFacetForActionXml.create(actionLayoutData, objectAction));
-                FacetUtil.addFacet(CssClassFaFacetForActionXml.create(actionLayoutData, objectAction));
-                FacetUtil.addFacet(DescribedAsFacetForActionXml.create(actionLayoutData, objectAction));
-                FacetUtil.addFacet(HiddenFacetForActionLayoutXml.create(actionLayoutData, objectAction));
-                FacetUtil.addFacet(NamedFacetForActionXml.create(actionLayoutData, objectAction));
+                FacetUtil.addOrReplaceFacet(ActionPositionFacetForActionXml.create(actionLayoutData, objectAction));
+                FacetUtil.addOrReplaceFacet(BookmarkPolicyFacetForActionXml.create(actionLayoutData, objectAction));
+                FacetUtil.addOrReplaceFacet(CssClassFacetForActionXml.create(actionLayoutData, objectAction));
+                FacetUtil.addOrReplaceFacet(CssClassFaFacetForActionXml.create(actionLayoutData, objectAction));
+                FacetUtil.addOrReplaceFacet(DescribedAsFacetForActionXml.create(actionLayoutData, objectAction));
+                FacetUtil.addOrReplaceFacet(HiddenFacetForActionLayoutXml.create(actionLayoutData, objectAction));
+                FacetUtil.addOrReplaceFacet(NamedFacetForActionXml.create(actionLayoutData, objectAction));
             }
 
             @Override
@@ -217,21 +243,21 @@ public abstract class GridNormalizerServiceAbstract<G extends Grid> implements G
                     return;
                 }
 
-                FacetUtil.addFacet(CssClassFacetForPropertyXml.create(propertyLayoutData, oneToOneAssociation));
-                FacetUtil.addFacet(DescribedAsFacetForPropertyXml.create(propertyLayoutData, oneToOneAssociation));
-                FacetUtil.addFacet(HiddenFacetForPropertyXml.create(propertyLayoutData, oneToOneAssociation));
-                FacetUtil.addFacet(LabelAtFacetForPropertyXml.create(propertyLayoutData, oneToOneAssociation));
-                FacetUtil.addFacet(MultiLineFacetForPropertyXml.create(propertyLayoutData, oneToOneAssociation));
-                FacetUtil.addFacet(NamedFacetForPropertyXml.create(propertyLayoutData, oneToOneAssociation));
-                FacetUtil.addFacet(
+                FacetUtil.addOrReplaceFacet(CssClassFacetForPropertyXml.create(propertyLayoutData, oneToOneAssociation));
+                FacetUtil.addOrReplaceFacet(DescribedAsFacetForPropertyXml.create(propertyLayoutData, oneToOneAssociation));
+                FacetUtil.addOrReplaceFacet(HiddenFacetForPropertyXml.create(propertyLayoutData, oneToOneAssociation));
+                FacetUtil.addOrReplaceFacet(LabelAtFacetForPropertyXml.create(propertyLayoutData, oneToOneAssociation));
+                FacetUtil.addOrReplaceFacet(MultiLineFacetForPropertyXml.create(propertyLayoutData, oneToOneAssociation));
+                FacetUtil.addOrReplaceFacet(NamedFacetForPropertyXml.create(propertyLayoutData, oneToOneAssociation));
+                FacetUtil.addOrReplaceFacet(
                         RenderedAdjustedFacetForPropertyXml.create(propertyLayoutData, oneToOneAssociation));
-                FacetUtil.addFacet(TypicalLengthFacetForPropertyXml.create(propertyLayoutData, oneToOneAssociation));
+                FacetUtil.addOrReplaceFacet(TypicalLengthFacetForPropertyXml.create(propertyLayoutData, oneToOneAssociation));
 
                 // @MemberOrder#name based on owning property group, @MemberOrder#sequence monotonically increasing
                 final FieldSet fieldSet = propertyLayoutData.getOwner();
                 final String groupName = fieldSet.getName();
                 final String sequence = nextInSequenceFor(groupName, propertySequenceByGroup);
-                FacetUtil.addFacet(
+                FacetUtil.addOrReplaceFacet(
                         new MemberOrderFacetXml(groupName, sequence, translationService, oneToOneAssociation));
             }
 
@@ -242,20 +268,20 @@ public abstract class GridNormalizerServiceAbstract<G extends Grid> implements G
                     return;
                 }
 
-                FacetUtil.addFacet(CssClassFacetForCollectionXml.create(collectionLayoutData, oneToManyAssociation));
-                FacetUtil.addFacet(
+                FacetUtil.addOrReplaceFacet(CssClassFacetForCollectionXml.create(collectionLayoutData, oneToManyAssociation));
+                FacetUtil.addOrReplaceFacet(
                         DefaultViewFacetForCollectionXml.create(collectionLayoutData, oneToManyAssociation));
-                FacetUtil.addFacet(
+                FacetUtil.addOrReplaceFacet(
                         DescribedAsFacetForCollectionXml.create(collectionLayoutData, oneToManyAssociation));
-                FacetUtil.addFacet(HiddenFacetForCollectionXml.create(collectionLayoutData, oneToManyAssociation));
-                FacetUtil.addFacet(NamedFacetForCollectionXml.create(collectionLayoutData, oneToManyAssociation));
-                FacetUtil.addFacet(PagedFacetForCollectionXml.create(collectionLayoutData, oneToManyAssociation));
-                FacetUtil.addFacet(SortedByFacetForCollectionXml.create(collectionLayoutData, oneToManyAssociation));
+                FacetUtil.addOrReplaceFacet(HiddenFacetForCollectionXml.create(collectionLayoutData, oneToManyAssociation));
+                FacetUtil.addOrReplaceFacet(NamedFacetForCollectionXml.create(collectionLayoutData, oneToManyAssociation));
+                FacetUtil.addOrReplaceFacet(PagedFacetForCollectionXml.create(collectionLayoutData, oneToManyAssociation));
+                FacetUtil.addOrReplaceFacet(SortedByFacetForCollectionXml.create(collectionLayoutData, oneToManyAssociation));
 
                 // @MemberOrder#name based on the collection's id (so that each has a single "member group")
                 final String groupName = collectionLayoutData.getId();
                 final String sequence = "" + collectionSequence++;
-                FacetUtil.addFacet(
+                FacetUtil.addOrReplaceFacet(
                         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'
@@ -326,10 +352,20 @@ public abstract class GridNormalizerServiceAbstract<G extends Grid> implements G
     }
 
 
-    @Inject
     SpecificationLoader specificationLookup;
+
+    public void setSpecificationLoader(final SpecificationLoader specificationLookup) {
+        this.specificationLookup = specificationLookup;
+    }
+
     @Inject
     TranslationService translationService;
 
+    @Inject
+    JaxbService jaxbService;
+
+    @Inject
+    DomainObjectContainer container;
+
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/8fcac964/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridNormalizerServiceBS3.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridNormalizerServiceBS3.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridNormalizerServiceBS3.java
index a4f845a..5761965 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridNormalizerServiceBS3.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridNormalizerServiceBS3.java
@@ -21,6 +21,10 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicReference;
 
+import javax.annotation.Nullable;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 
@@ -29,6 +33,7 @@ import org.apache.isis.applib.annotation.NatureOfService;
 import org.apache.isis.applib.layout.bootstrap3.BS3Col;
 import org.apache.isis.applib.layout.bootstrap3.BS3Grid;
 import org.apache.isis.applib.layout.bootstrap3.BS3Row;
+import org.apache.isis.applib.layout.bootstrap3.BS3RowContent;
 import org.apache.isis.applib.layout.bootstrap3.BS3Tab;
 import org.apache.isis.applib.layout.bootstrap3.BS3TabGroup;
 import org.apache.isis.applib.layout.common.ActionLayoutData;
@@ -36,9 +41,9 @@ import org.apache.isis.applib.layout.common.CollectionLayoutData;
 import org.apache.isis.applib.layout.common.FieldSet;
 import org.apache.isis.applib.layout.common.Grid;
 import org.apache.isis.applib.layout.common.PropertyLayoutData;
-import org.apache.isis.applib.layout.fixedcols.FCColumn;
-import org.apache.isis.core.metamodel.facets.object.membergroups.MemberGroupLayoutFacet;
+import org.apache.isis.core.metamodel.facets.members.order.MemberOrderFacet;
 import org.apache.isis.core.metamodel.services.grid.GridNormalizerServiceAbstract;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
 import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
@@ -61,7 +66,7 @@ public class GridNormalizerServiceBS3 extends GridNormalizerServiceAbstract<BS3G
             final Grid grid,
             final Map<String, OneToOneAssociation> oneToOneAssociationById,
             final Map<String, OneToManyAssociation> oneToManyAssociationById,
-            final Map<String, ObjectAction> objectActionById) {
+            final Map<String, ObjectAction> objectActionById, final ObjectSpecification objectSpec) {
 
         final BS3Grid bs3Grid = (BS3Grid) grid;
 
@@ -117,53 +122,75 @@ public class GridNormalizerServiceBS3 extends GridNormalizerServiceAbstract<BS3G
         // unreferencedActions, unreferencedProperties and unreferencedCollections attribute set.
 
         final AtomicReference<BS3Col> colForUnreferencedActionsRef = new AtomicReference<>();
-        final AtomicReference<BS3Col> colForUnreferencedPropertiesRef = new AtomicReference<>();
-        final AtomicReference<FieldSet> fieldSetForUnreferencedPropsRef = new AtomicReference<>();
-        final AtomicReference<BS3Col> colForUnreferencedCollectionsRef = new AtomicReference<>();
+        final AtomicReference<FieldSet> fieldSetForUnreferencedActionsRef = new AtomicReference<>();
+        final AtomicReference<FieldSet> fieldSetForUnreferencedPropertiesRef = new AtomicReference<>();
+        final AtomicReference<BS3TabGroup> tabGroupForUnreferencedCollectionsRef = new AtomicReference<>();
 
         bs3Grid.visit(new BS3Grid.VisitorAdapter(){
             @Override
             public void visit(final BS3Col bs3Col) {
-                if(bs3Col.isUnreferencedActions()) {
+                if(isSet(bs3Col.isUnreferencedActions())) {
                     if(colForUnreferencedActionsRef.get() != null) {
                         bs3Col.setMetadataError("More than one col with 'unreferencedActions' attribute set");
+                    } else if(fieldSetForUnreferencedActionsRef.get() != null) {
+                        bs3Col.setMetadataError("Already found a fieldset with 'unreferencedActions' attribute set");
                     } else {
                         colForUnreferencedActionsRef.set(bs3Col);
                     }
                 }
-                if(bs3Col.isUnreferencedProperties()) {
-                    if(colForUnreferencedPropertiesRef.get() != null) {
-                        bs3Col.setMetadataError("More than one col with 'unreferencedProperties' attribute set");
+            }
+
+            @Override
+            public void visit(final FieldSet fieldSet) {
+                if(isSet(fieldSet.isUnreferencedActions())) {
+                    if(fieldSetForUnreferencedActionsRef.get() != null) {
+                        fieldSet.setMetadataError("More than one fieldset with 'unreferencedActions' attribute set");
+                    } else if(colForUnreferencedActionsRef.get() != null) {
+                        fieldSet.setMetadataError("Already found a column with 'unreferencedActions' attribute set");
                     } else {
-                        final List<FieldSet> fieldSets = bs3Col.getFieldSets();
-                        for (FieldSet fieldSet : fieldSets) {
-                            if(fieldSet.getName().equals(MemberGroupLayoutFacet.DEFAULT_GROUP)) {
-                                fieldSetForUnreferencedPropsRef.set(fieldSet);
-                            }
-                        }
-                        colForUnreferencedPropertiesRef.set(bs3Col);
+                        fieldSetForUnreferencedActionsRef.set(fieldSet);
                     }
                 }
-                if(bs3Col.isUnreferencedCollections()) {
-                    if(colForUnreferencedCollectionsRef.get() != null) {
-                        bs3Col.setMetadataError("More than one col with 'unreferencedCollections' attribute set");
+                if(isSet(fieldSet.isUnreferencedProperties())) {
+                    if(fieldSetForUnreferencedPropertiesRef.get() != null) {
+                        fieldSet.setMetadataError("More than one col with 'unreferencedProperties' attribute set");
+                    } else {
+                        fieldSetForUnreferencedPropertiesRef.set(fieldSet);
+                    }
+                }
+            }
+
+            @Override
+            public void visit(final BS3TabGroup bs3TabGroup) {
+                if(isSet(bs3TabGroup.isUnreferencedCollections())) {
+                    if(tabGroupForUnreferencedCollectionsRef.get() != null) {
+                        bs3TabGroup.setMetadataError("More than one tabgroup with 'unreferencedCollections' attribute set");
                     } else {
-                        colForUnreferencedCollectionsRef.set(bs3Col);
+                        tabGroupForUnreferencedCollectionsRef.set(bs3TabGroup);
                     }
                 }
             }
         });
 
-        if(     colForUnreferencedActionsRef.get() == null ||
-                colForUnreferencedPropertiesRef.get() == null ||
-                colForUnreferencedCollectionsRef.get() == null) {
-            return false;
+        if(colForUnreferencedActionsRef.get() == null && fieldSetForUnreferencedActionsRef.get() == null) {
+            bs3Grid.getMetadataErrors().add("No column and no fieldset has the 'unreferencedActions' attribute set");
+        }
+        if(fieldSetForUnreferencedPropertiesRef.get() == null) {
+            bs3Grid.getMetadataErrors().add("No fieldset has the 'unreferencedProperties' attribute set");
+        }
+        if(tabGroupForUnreferencedCollectionsRef.get() == null) {
+            bs3Grid.getMetadataErrors().add("No tabgroup has the 'unreferencedCollections' attribute set");
         }
 
+        if(     colForUnreferencedActionsRef.get() == null && fieldSetForUnreferencedActionsRef.get() == null ||
+                fieldSetForUnreferencedPropertiesRef.get() == null ||
+                tabGroupForUnreferencedCollectionsRef.get() == null) {
+            return false;
+        }
 
         // add missing properties will be added to the first fieldset of the specified column
         final Tuple<List<String>> propertyIdTuple =
-                surplusAndMissing(propertyIds.keySet(), oneToOneAssociationById.keySet());
+                surplusAndMissing(propertyIds.keySet(),  oneToOneAssociationById.keySet());
         final List<String> surplusPropertyIds = propertyIdTuple.first;
         final List<String> missingPropertyIds = propertyIdTuple.second;
 
@@ -172,18 +199,9 @@ public class GridNormalizerServiceBS3 extends GridNormalizerServiceAbstract<BS3G
         }
 
         if(!missingPropertyIds.isEmpty()) {
-            final BS3Col bs3Col = colForUnreferencedPropertiesRef.get();
-            if(bs3Col != null) {
-                // ensure that there is a field set to use, else create
-                boolean wasSet = fieldSetForUnreferencedPropsRef.compareAndSet(null, new FieldSet(MemberGroupLayoutFacet.DEFAULT_GROUP));
-                final FieldSet fieldSetForUnref = fieldSetForUnreferencedPropsRef.get();
-                if(wasSet) {
-                    fieldSetForUnref.setOwner(bs3Col);
-                    bs3Col.getFieldSets().add(fieldSetForUnref);
-                }
-                for (final String propertyId : missingPropertyIds) {
-                    bs3Col.getFieldSets().get(0).getProperties().add(new PropertyLayoutData(propertyId));
-                }
+            final FieldSet fieldSet = fieldSetForUnreferencedPropertiesRef.get();
+            if(fieldSet != null) {
+                addMissingPropertiesTo(fieldSet, missingPropertyIds);
             }
         }
 
@@ -198,20 +216,9 @@ public class GridNormalizerServiceBS3 extends GridNormalizerServiceAbstract<BS3G
         }
 
         if(!missingCollectionIds.isEmpty()) {
-            final BS3Col bs3Col = colForUnreferencedCollectionsRef.get();
-            if(bs3Col != null) {
-                final BS3TabGroup tabGroup = new BS3TabGroup();
-                tabGroup.setOwner(bs3Col);
-                bs3Col.getTabGroups().add(tabGroup);
-                for (final String collectionId : missingCollectionIds) {
-                    final BS3Tab bs3Tab = new BS3Tab();
-                    tabGroup.getTabs().add(bs3Tab);
-                    FCColumn left = new FCColumn(12);
-                    bs3Tab.setOwner(tabGroup);
-                    final CollectionLayoutData layoutMetadata = new CollectionLayoutData(collectionId);
-                    layoutMetadata.setDefaultView("table");
-                    left.getCollections().add(layoutMetadata);
-                }
+            final BS3TabGroup bs3TabGroup = tabGroupForUnreferencedCollectionsRef.get();
+            if(bs3TabGroup != null) {
+                addMissingCollectionsTo(bs3TabGroup, missingCollectionIds, objectSpec);
             }
         }
 
@@ -219,7 +226,27 @@ public class GridNormalizerServiceBS3 extends GridNormalizerServiceAbstract<BS3G
         final Tuple<List<String>> actionIdTuple =
                 surplusAndMissing(actionIds.keySet(), objectActionById.keySet());
         final List<String> surplusActionIds = actionIdTuple.first;
-        final List<String> missingActionIds = actionIdTuple.second;
+
+        // ... the missing actions are those in the second tuple, excluding those bound via @MemberOrder#name
+        // to a property or collection.
+        final List<String> missingActionIds =
+                FluentIterable.from(actionIdTuple.second)
+                        .filter(new Predicate<String>() {
+                            @Override public boolean apply(@Nullable final String actionId) {
+                                final ObjectAction oa = objectActionById.get(actionId);
+                                final MemberOrderFacet memberOrderFacet = oa.getFacet(MemberOrderFacet.class);
+                                if(memberOrderFacet == null) {
+                                    return true;
+                                }
+                                final String memberOrderName = memberOrderFacet.name();
+                                if (memberOrderName == null) {
+                                    return true;
+                                }
+                                return  !oneToOneAssociationById.containsKey(memberOrderName) &&
+                                        !oneToManyAssociationById.containsKey(memberOrderName);
+                            }
+                        })
+                        .toList();
 
         for (String surplusActionId : surplusActionIds) {
             actionIds.get(surplusActionId).setMetadataError("No such action");
@@ -228,13 +255,11 @@ public class GridNormalizerServiceBS3 extends GridNormalizerServiceAbstract<BS3G
         if(!missingActionIds.isEmpty()) {
             final BS3Col bs3Col = colForUnreferencedActionsRef.get();
             if(bs3Col != null) {
-                for (String actionId : missingActionIds) {
-                    List<ActionLayoutData> actions = bs3Col.getActions();
-                    if(actions == null) {
-                        actions = Lists.newArrayList();
-                        bs3Col.setActions(actions);
-                    }
-                    actions.add(new ActionLayoutData(actionId));
+                addMissingActionsTo(bs3Col, missingActionIds);
+            } else {
+                final FieldSet fieldSet = fieldSetForUnreferencedActionsRef.get();
+                if(fieldSet != null) {
+                    addMissingActionsTo(fieldSet, missingActionIds);
                 }
             }
         }
@@ -242,4 +267,60 @@ public class GridNormalizerServiceBS3 extends GridNormalizerServiceAbstract<BS3G
         return true;
     }
 
+    protected void addMissingPropertiesTo(
+            final FieldSet fieldSet,
+            final List<String> missingPropertyIds) {
+        for (final String propertyId : missingPropertyIds) {
+            fieldSet.getProperties().add(new PropertyLayoutData(propertyId));
+        }
+    }
+
+    protected void addMissingActionsTo(final BS3Col bs3Col, final List<String> missingActionIds) {
+        for (String actionId : missingActionIds) {
+            List<ActionLayoutData> actions = bs3Col.getActions();
+            if(actions == null) {
+                actions = Lists.newArrayList();
+                bs3Col.setActions(actions);
+            }
+            actions.add(new ActionLayoutData(actionId));
+        }
+    }
+
+    protected void addMissingActionsTo(final FieldSet fieldSet, final List<String> missingActionIds) {
+        List<ActionLayoutData> actions = fieldSet.getActions();
+        for (String actionId : missingActionIds) {
+            actions.add(new ActionLayoutData(actionId));
+        }
+    }
+
+    protected void addMissingCollectionsTo(
+            final BS3TabGroup tabGroup,
+            final List<String> missingCollectionIds,
+            final ObjectSpecification objectSpec) {
+        for (final String collectionId : missingCollectionIds) {
+            final BS3Tab bs3Tab = new BS3Tab();
+            bs3Tab.setName(objectSpec.getAssociation(collectionId).getName());
+            tabGroup.getTabs().add(bs3Tab);
+            bs3Tab.setOwner(tabGroup);
+
+            final BS3Row tabRow = new BS3Row();
+            tabRow.setOwner(bs3Tab);
+            bs3Tab.getRows().add(tabRow);
+
+            final BS3Col tabRowCol = new BS3Col();
+            tabRowCol.setSpan(12);
+            tabRowCol.setSize(BS3RowContent.Size.MD);
+            tabRowCol.setOwner(tabRow);
+            tabRow.getCols().add(tabRowCol);
+
+            final CollectionLayoutData layoutMetadata = new CollectionLayoutData(collectionId);
+            layoutMetadata.setDefaultView("table");
+            tabRowCol.getCollections().add(layoutMetadata);
+        }
+    }
+
+    private static Boolean isSet(final Boolean flag) {
+        return flag != null && flag;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/8fcac964/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/fixedcols/GridNormalizerServiceFC.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/fixedcols/GridNormalizerServiceFC.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/fixedcols/GridNormalizerServiceFC.java
index cf18f80..c617c73 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/fixedcols/GridNormalizerServiceFC.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/fixedcols/GridNormalizerServiceFC.java
@@ -21,57 +21,22 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicReference;
 
-import javax.inject.Inject;
-
-import com.google.common.base.Strings;
 import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
 
 import org.apache.isis.applib.annotation.DomainService;
 import org.apache.isis.applib.annotation.NatureOfService;
 import org.apache.isis.applib.layout.common.ActionLayoutData;
-import org.apache.isis.applib.layout.common.ActionLayoutDataOwner;
 import org.apache.isis.applib.layout.common.CollectionLayoutData;
 import org.apache.isis.applib.layout.common.FieldSet;
 import org.apache.isis.applib.layout.common.Grid;
-import org.apache.isis.applib.layout.common.MemberRegionOwner;
 import org.apache.isis.applib.layout.common.PropertyLayoutData;
 import org.apache.isis.applib.layout.fixedcols.FCColumn;
-import org.apache.isis.applib.layout.fixedcols.FCColumnOwner;
 import org.apache.isis.applib.layout.fixedcols.FCGrid;
 import org.apache.isis.applib.layout.fixedcols.FCTab;
 import org.apache.isis.applib.layout.fixedcols.FCTabGroup;
-import org.apache.isis.applib.services.i18n.TranslationService;
-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.services.grid.GridNormalizerServiceAbstract;
-import org.apache.isis.core.metamodel.spec.SpecificationLoader;
-import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
-import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
-import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 
 @DomainService(
         nature = NatureOfService.DOMAIN
@@ -98,7 +63,7 @@ public class GridNormalizerServiceFC extends GridNormalizerServiceAbstract {
             final Grid grid,
             final Map oneToOneAssociationById,
             final Map oneToManyAssociationById,
-            final Map objectActionById) {
+            final Map objectActionById, final ObjectSpecification objectSpec) {
 
         final FCGrid fcGrid = (FCGrid) grid;
 

http://git-wip-us.apache.org/repos/asf/isis/blob/8fcac964/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/grid/BS3GridTest.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/grid/BS3GridTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/grid/BS3GridTest.java
index 3d9d6b2..706db56 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/grid/BS3GridTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/grid/BS3GridTest.java
@@ -72,8 +72,10 @@ public class BS3GridTest {
         final BS3Grid bs3Grid = new BS3Grid();
 
         // header
-        final BS3Row headerRow = bs3Grid.getRows().get(0);
-        final BS3Col headerCol = (BS3Col) headerRow.getCols().get(0);
+        final BS3Row headerRow = new BS3Row();
+        bs3Grid.getRows().add(headerRow);
+        final BS3Col headerCol = new BS3Col();
+        headerRow.getCols().add(headerCol);
         headerCol.setSpan(12);
 
         final DomainObjectLayoutData objectLayoutData = new DomainObjectLayoutData();
@@ -88,18 +90,22 @@ public class BS3GridTest {
         final BS3Row contentRow = new BS3Row();
         bs3Grid.getRows().add(contentRow);
 
-        final BS3Col contentCol = (BS3Col) contentRow.getCols().get(0);
+        final BS3Col contentCol = new BS3Col();
+        contentRow.getCols().add(contentCol);
         contentCol.setSpan(12);
 
         // a tabgroup containing a 'Common' tab
         final BS3TabGroup tabGroup = new BS3TabGroup();
         contentCol.getTabGroups().add(tabGroup);
-        BS3Tab bs3Tab = tabGroup.getTabs().get(0);
+        BS3Tab bs3Tab = new BS3Tab();
+        tabGroup.getTabs().add(bs3Tab);
         bs3Tab.setName("Common");
 
         // with a left col...
-        final BS3Row tabRow = bs3Tab.getRows().get(0);
-        final BS3Col tabLeftCol = (BS3Col) tabRow.getCols().get(0);
+        final BS3Row tabRow = new BS3Row();
+        bs3Tab.getRows().add(tabRow);
+        final BS3Col tabLeftCol = new BS3Col();
+        tabRow.getCols().add(tabLeftCol);
         tabLeftCol.setSpan(6);
 
         // containing a fieldset
@@ -109,7 +115,8 @@ public class BS3GridTest {
         leftPropGroup.setName("General");
 
         // with a single property
-        final PropertyLayoutData namePropertyLayoutData = leftPropGroup.getProperties().get(0);
+        final PropertyLayoutData namePropertyLayoutData = new PropertyLayoutData();
+        leftPropGroup.getProperties().add(namePropertyLayoutData);
         namePropertyLayoutData.setNamed("name");
 
         // and its associated action
@@ -119,7 +126,8 @@ public class BS3GridTest {
         namePropertyLayoutData.getActions().add(updateNameActionLayoutData);
 
         // and the tab also has a right col...
-        final BS3Col tabRightCol = (BS3Col) tabRow.getCols().get(0);
+        final BS3Col tabRightCol = new BS3Col();
+        tabRow.getCols().add(tabRightCol);
         tabRightCol.setSpan(6);
 
         // containing a collection

http://git-wip-us.apache.org/repos/asf/isis/blob/8fcac964/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.java
----------------------------------------------------------------------
diff --git a/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.java b/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.java
index dad55cf..7f2702e 100644
--- a/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.java
+++ b/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.java
@@ -31,6 +31,7 @@ import org.apache.isis.applib.annotation.BookmarkPolicy;
 import org.apache.isis.applib.annotation.DomainObject;
 import org.apache.isis.applib.annotation.DomainObjectLayout;
 import org.apache.isis.applib.annotation.Editing;
+import org.apache.isis.applib.annotation.MemberOrder;
 import org.apache.isis.applib.annotation.Parameter;
 import org.apache.isis.applib.annotation.ParameterLayout;
 import org.apache.isis.applib.annotation.Property;
@@ -104,6 +105,7 @@ public class SimpleObject implements Comparable<SimpleObject> {
             domainEvent = UpdateNameDomainEvent.class,
             semantics = SemanticsOf.IDEMPOTENT
     )
+    @MemberOrder(name = "name", sequence = "1")
     public SimpleObject updateName(
             @Parameter(maxLength = NAME_LENGTH)
             @ParameterLayout(named = "New name")

http://git-wip-us.apache.org/repos/asf/isis/blob/8fcac964/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.layout.xml
----------------------------------------------------------------------
diff --git a/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.layout.xml b/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.layout.xml
index b1b3ed9..34bbb54 100644
--- a/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.layout.xml
+++ b/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.layout.xml
@@ -1,64 +1,50 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <bs3:grid xsi:schemaLocation="http://isis.apache.org/schema/applib/layout/common http://isis.apache.org/schema/applib/layout/common/common.xsd http://isis.apache.org/schema/applib/layout/bootstrap3 http://isis.apache.org/schema/applib/layout/bootstrap3/bootstrap3.xsd" xmlns:c="http://isis.apache.org/schema/applib/layout/common" xmlns:bs3="http://isis.apache.org/schema/applib/layout/bootstrap3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 
-    <bs3:row cssClass="bishbosh">
-        <bs3:col span="8">
+<!--
+    <bs3:row>
+        <bs3:col span="8" unreferencedActions="false">
             <c:domainObject/>
         </bs3:col>
-        <bs3:col span="4" cssClass="foobar" unreferencedActions="true">
-            <c:action id="delete" cssClassFa="fa-trash"/>
-        </bs3:col>
     </bs3:row>
 
     <bs3:row>
         <bs3:col span="12">
             <bs3:tabGroup>
-                <bs3:tab name="Metadata">
+                <bs3:tab name="Properties">
                     <bs3:row>
-                        <bs3:col span="12">
-                            <c:fieldSet name="Metadata">
-                                <c:action id="downloadJdMetadata"/>
-                                <c:action id="downloadLayoutXml" position="PANEL_DROPDOWN"/>
-                                <c:property id="versionSequence"/>
-                            </c:fieldSet>
-                        </bs3:col>
                         <bs3:col span="6">
-                            <c:fieldSet name="Xxx">
-                                <c:property id="name" labelPosition="TOP">
-                                    <c:action id="updateName">
-                                        <c:describedAs>This allows the name to be updated</c:describedAs>
-                                    </c:action>
-                                </c:property>
-                            </c:fieldSet>
+                            <c:fieldSet name="General" unreferencedProperties="true" unreferencedActions="true"/>
                         </bs3:col>
                         <bs3:col span="6">
-                            <c:fieldSet name="Xxx">
-                                <c:property id="name" labelPosition="TOP">
-                                    <c:action id="updateName">
-                                        <c:describedAs>This allows the name to be updated</c:describedAs>
-                                    </c:action>
-                                </c:property>
+                            <c:fieldSet name="Metadata">
+                                <c:action id="downloadJdoMetadata"/>
+                                <c:action id="downloadLayoutXml" position="PANEL_DROPDOWN"/>
+                                <c:property id="versionSequence"/>
                             </c:fieldSet>
                         </bs3:col>
                     </bs3:row>
                 </bs3:tab>
             </bs3:tabGroup>
-            <bs3:tabGroup>
-                <bs3:tab name="SimilarTo">
-                    <bs3:row>
-                        <bs3:col span="12">
-                            <c:collection id="similarTo" defaultView="table"/>
-                        </bs3:col>
-                    </bs3:row>
-                </bs3:tab>
-                <bs3:tab name="Others">
-                    <bs3:row>
-                        <bs3:col span="12">
-                            <c:collection id="others" defaultView="hide"/>
-                        </bs3:col>
-                    </bs3:row>
-                </bs3:tab>
-            </bs3:tabGroup>
+        </bs3:col>
+    </bs3:row>
+    <bs3:row>
+        <bs3:col span="12">
+            <bs3:tabGroup unreferencedCollections="true"/>
+        </bs3:col>
+    </bs3:row>
+-->
+    <bs3:row>
+        <bs3:col span="12" unreferencedActions="true">
+            <c:domainObject/>
+        </bs3:col>
+    </bs3:row>
+    <bs3:row>
+        <bs3:col span="6">
+            <c:fieldSet name="Properties" unreferencedProperties="true"/>
+        </bs3:col>
+        <bs3:col span="6">
+            <bs3:tabGroup unreferencedCollections="true"/>
         </bs3:col>
     </bs3:row>
 </bs3:grid>