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/02 01:36:06 UTC

[09/15] isis git commit: ISIS-993: starting on the visitor/normalization stuff for BS3 grid.

ISIS-993: starting on the visitor/normalization stuff for BS3 grid.


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

Branch: refs/heads/ISIS-993
Commit: 25a267a61cf6d4c9ef297f19f134e25dd17e7a91
Parents: c57d8cd
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Mon Feb 1 22:48:27 2016 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Mon Feb 1 22:48:27 2016 +0100

----------------------------------------------------------------------
 .../isis/applib/layout/bootstrap3/BS3Col.java   |  26 +-
 .../isis/applib/layout/bootstrap3/BS3Page.java  | 244 ++++++++++++++++++-
 .../isis/applib/layout/bootstrap3/BS3Row.java   |  41 +++-
 .../applib/layout/bootstrap3/BS3RowContent.java |  20 ++
 .../layout/bootstrap3/BS3RowContentOwner.java   |  25 ++
 .../applib/layout/bootstrap3/BS3RowOwner.java   |  28 +++
 .../isis/applib/layout/bootstrap3/BS3Tab.java   |  23 +-
 .../applib/layout/bootstrap3/BS3TabGroup.java   |  24 +-
 .../layout/bootstrap3/BS3TabGroupOwner.java     |  28 +++
 .../applib/layout/bootstrap3/BS3TabOwner.java   |  28 +++
 .../isis/applib/layout/bootstrap3/HasCssId.java |  28 +++
 .../applib/layout/common/ActionLayoutData.java  |   8 +-
 .../layout/common/ActionLayoutDataOwner.java    |  25 ++
 .../isis/applib/layout/common/ActionOwner.java  |  25 --
 .../layout/common/CollectionLayoutData.java     |   2 +-
 .../layout/common/DomainObjectLayoutData.java   |  20 ++
 .../common/DomainObjectLayoutDataOwner.java     |  23 ++
 .../isis/applib/layout/common/FieldSet.java     |   2 +-
 .../apache/isis/applib/layout/common/Page.java  |  21 +-
 .../layout/common/PropertyLayoutData.java       |   2 +-
 .../isis/applib/layout/fixedcols/FCPage.java    |  95 ++++----
 .../layout/provider/PageNormalizerFC.java       |  28 +--
 .../viewer/wicket/ui/util/CssIdAppender.java    |  70 ++++++
 .../dom/simple/SimpleObject.layout-FC.xml       |  13 +-
 .../dom/simple/SimpleObject.layout.xml          |   6 +-
 25 files changed, 743 insertions(+), 112 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/25a267a6/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 1395c99..90ae5db 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
@@ -29,9 +29,11 @@ import javax.xml.bind.annotation.XmlType;
 import com.google.common.collect.Lists;
 
 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.DomainObjectLayoutData;
 import org.apache.isis.applib.layout.common.FieldSet;
+import org.apache.isis.applib.layout.common.MemberRegionOwner;
 
 /**
  * A column within a row which, depending on its {@link #getSpan()}, could be as narrow as 1/12th of the page's width, all the way up to spanning the entire page.
@@ -60,11 +62,27 @@ import org.apache.isis.applib.layout.common.FieldSet;
             "collections",
         }
 )
-public class BS3Col extends BS3RowContent {
+public class BS3Col extends BS3RowContent implements ActionLayoutDataOwner, BS3TabGroupOwner, BS3RowOwner, MemberRegionOwner, HasCssId {
 
     private static final long serialVersionUID = 1L;
 
 
+
+    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 int span;
 
     @XmlAttribute(required = true)
@@ -87,7 +105,7 @@ public class BS3Col extends BS3RowContent {
      * </p>
      */
     @XmlAttribute(required = false)
-    public boolean getUnreferencedActions() {
+    public boolean isUnreferencedActions() {
         return unreferencedActions;
     }
 
@@ -105,7 +123,7 @@ public class BS3Col extends BS3RowContent {
      * </p>
      */
     @XmlAttribute(required = false)
-    public boolean getUnreferencedProperties() {
+    public boolean isUnreferencedProperties() {
         return unreferencedProperties;
     }
 
@@ -123,7 +141,7 @@ public class BS3Col extends BS3RowContent {
      * </p>
      */
     @XmlAttribute(required = false)
-    public boolean getUnreferencedCollections() {
+    public boolean isUnreferencedCollections() {
         return unreferencedCollections;
     }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/25a267a6/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Page.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Page.java b/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Page.java
index 7796500..6dd559b 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Page.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Page.java
@@ -19,6 +19,7 @@
 package org.apache.isis.applib.layout.bootstrap3;
 
 import java.util.ArrayList;
+import java.util.LinkedHashMap;
 import java.util.List;
 
 import javax.xml.bind.annotation.XmlElement;
@@ -27,9 +28,16 @@ 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;
+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.DomainObjectLayoutData;
+import org.apache.isis.applib.layout.common.FieldSet;
 import org.apache.isis.applib.layout.common.Page;
+import org.apache.isis.applib.layout.common.PropertyLayoutData;
 import org.apache.isis.applib.services.dto.Dto;
 
 /**
@@ -50,7 +58,7 @@ import org.apache.isis.applib.services.dto.Dto;
             , "metadataErrors"
         }
 )
-public class BS3Page extends BS3ElementAbstract implements Page, Dto {
+public class BS3Page extends BS3ElementAbstract implements Page, Dto, BS3RowOwner {
 
     private static final long serialVersionUID = 1L;
 
@@ -83,9 +91,6 @@ public class BS3Page extends BS3ElementAbstract implements Page, Dto {
         this.normalized = normalized;
     }
 
-
-
-
     private List<String> metadataErrors = Lists.newArrayList();
 
     /**
@@ -106,4 +111,235 @@ public class BS3Page extends BS3ElementAbstract implements Page, Dto {
     public void setMetadataErrors(final List<String> metadataErrors) {
         this.metadataErrors = metadataErrors;
     }
+
+    interface Visitor {
+        void visit(final BS3Page bs3Page);
+        void visit(final BS3Row bs3Row);
+        void visit(final BS3Col bs3Col);
+        void visit(final BS3ClearFix bs3ClearFix);
+        void visit(final BS3TabGroup bs3TabGroup);
+        void visit(final BS3Tab bs3Tab);
+        void visit(final FieldSet fieldSet);
+        void visit(final DomainObjectLayoutData domainObjectLayout);
+        void visit(final PropertyLayoutData propertyLayoutData);
+        void visit(final CollectionLayoutData collectionLayoutData);
+        void visit(final ActionLayoutData actionLayoutData);
+    }
+
+    public static class VisitorAdapter implements Visitor {
+        @Override
+        public void visit(final BS3Page bs3Page) { }
+        @Override
+        public void visit(final BS3Row bs3Row) { }
+        @Override
+        public void visit(final BS3Col bs3Col) { }
+        @Override
+        public void visit(final BS3ClearFix bs3ClearFix) { }
+        @Override
+        public void visit(final BS3TabGroup bs3TabGroup) { }
+        @Override
+        public void visit(final BS3Tab bs3Tab) { }
+        @Override
+        public void visit(final DomainObjectLayoutData domainObjectLayout) { }
+        @Override
+        public void visit(final FieldSet fieldSet) {}
+        @Override
+        public void visit(final PropertyLayoutData propertyLayoutData) {}
+        @Override
+        public void visit(final CollectionLayoutData collectionLayoutData) {}
+        @Override
+        public void visit(final ActionLayoutData actionLayoutData) { }
+    }
+
+    public void visit(final BS3Page.Visitor visitor) {
+        visitor.visit(this);
+        traverseRows(this, visitor);
+    }
+
+    protected void traverseRows(final BS3RowOwner rowOwner, final Visitor visitor) {
+        for (BS3Row bs3Row : rowOwner.getRows()) {
+            bs3Row.setOwner(this);
+            visitor.visit(bs3Row);
+            final List<BS3RowContent> cols = bs3Row.getCols();
+            for (BS3RowContent rowContent : cols) {
+                rowContent.setOwner(bs3Row);
+                if(rowContent instanceof BS3Col) {
+                    final BS3Col bs3Col = (BS3Col) rowContent;
+                    visitor.visit(bs3Col);
+                    traverseDomainObject(bs3Col, visitor);
+                    traverseTabGroups(bs3Col, visitor);
+                    traverseActions(bs3Col, visitor);
+                    traverseFieldSets(bs3Col, visitor);
+                    traverseCollections(bs3Col, visitor);
+                    traverseRows(bs3Col, visitor);
+                } else if (rowContent instanceof BS3ClearFix) {
+                    final BS3ClearFix bs3ClearFix = (BS3ClearFix) rowContent;
+                    visitor.visit(bs3ClearFix);
+                } else {
+                    throw new IllegalStateException(
+                            "Unrecognized implementation of BS3RowContent, " + rowContent);
+                }
+            }
+        }
+    }
+
+    private void traverseDomainObject(final BS3Col bs3Col, final Visitor visitor) {
+        final DomainObjectLayoutData domainObject = bs3Col.getDomainObject();
+        if(domainObject == null) {
+            return;
+        }
+        domainObject.setOwner(bs3Col);
+        visitor.visit(domainObject);
+    }
+
+    private void traverseTabGroups(
+            final BS3TabGroupOwner bs3TabGroupOwner,
+            final Visitor visitor) {
+        final List<BS3TabGroup> tabGroups = bs3TabGroupOwner.getTabGroups();
+        for (BS3TabGroup bs3TabGroup : tabGroups) {
+            bs3TabGroup.setOwner(bs3TabGroupOwner);
+            visitor.visit(bs3TabGroup);
+            traverseTabs(bs3TabGroup, visitor);
+        }
+    }
+
+    private void traverseTabs(
+            final BS3TabOwner bs3TabOwner,
+            final Visitor visitor) {
+        final List<BS3Tab> tabs = bs3TabOwner.getTabs();
+        for (BS3Tab tab : tabs) {
+            tab.setOwner(bs3TabOwner);
+            visitor.visit(tab);
+            traverseRows(tab, visitor);
+        }
+    }
+
+    private void traverseActions(
+            final ActionLayoutDataOwner actionLayoutDataOwner,
+            final Visitor visitor) {
+        final List<ActionLayoutData> actionLayoutDatas = actionLayoutDataOwner.getActions();
+        if(actionLayoutDatas == null) {
+            return;
+        }
+        for (final ActionLayoutData actionLayoutData : actionLayoutDatas) {
+            actionLayoutData.setOwner(actionLayoutDataOwner);
+            visitor.visit(actionLayoutData);
+        }
+    }
+
+    private void traverseFieldSets(final BS3Col bs3Col, final Visitor visitor) {
+        final List<FieldSet> fieldSets = bs3Col.getFieldSets();
+        for (FieldSet fieldSet : fieldSets) {
+            fieldSet.setOwner(bs3Col);
+            visitor.visit(fieldSet);
+            traverseActions(fieldSet, visitor);
+            final List<PropertyLayoutData> properties = fieldSet.getProperties();
+            for (final PropertyLayoutData property : properties) {
+                property.setOwner(fieldSet);
+                visitor.visit(property);
+                traverseActions(property, visitor);
+            }
+        }
+    }
+
+    private void traverseCollections(final BS3Col bs3Col, final Visitor visitor) {
+        final List<CollectionLayoutData> collections = bs3Col.getCollections();
+        for (CollectionLayoutData collection : collections) {
+            collection.setOwner(bs3Col);
+            visitor.visit(collection);
+            traverseActions(collection, visitor);
+        }
+    }
+
+
+
+    @Programmatic
+    @XmlTransient
+    public LinkedHashMap<String, PropertyLayoutData> getAllPropertiesById() {
+        final LinkedHashMap<String, PropertyLayoutData> propertiesById = Maps.newLinkedHashMap();
+        visit(new BS3Page.VisitorAdapter() {
+            public void visit(final PropertyLayoutData propertyLayoutData) {
+                propertiesById.put(propertyLayoutData.getId(), propertyLayoutData);
+            }
+        });
+        return propertiesById;
+    }
+
+
+    @Programmatic
+    @XmlTransient
+    public LinkedHashMap<String, CollectionLayoutData> getAllCollectionsById() {
+        final LinkedHashMap<String, CollectionLayoutData> collectionsById = Maps.newLinkedHashMap();
+
+        visit(new BS3Page.VisitorAdapter() {
+            @Override
+            public void visit(final CollectionLayoutData collectionLayoutData) {
+                collectionsById.put(collectionLayoutData.getId(), collectionLayoutData);
+            }
+        });
+        return collectionsById;
+    }
+
+
+    @Programmatic
+    @XmlTransient
+    public LinkedHashMap<String, ActionLayoutData> getAllActionsById() {
+        final LinkedHashMap<String, ActionLayoutData> actionsById = Maps.newLinkedHashMap();
+
+        visit(new BS3Page.VisitorAdapter() {
+            @Override
+            public void visit(final ActionLayoutData actionLayoutData) {
+                actionsById.put(actionLayoutData.getId(), actionLayoutData);
+            }
+        });
+        return actionsById;
+    }
+
+
+    @Programmatic
+    @XmlTransient
+    public LinkedHashMap<String, FieldSet> getAllFieldSetsByName() {
+        final LinkedHashMap<String, FieldSet> fieldSetsByName = Maps.newLinkedHashMap();
+
+        visit(new BS3Page.VisitorAdapter() {
+            @Override
+            public void visit(final FieldSet fieldSet) {
+                fieldSetsByName.put(fieldSet.getName(), fieldSet);
+            }
+        });
+        return fieldSetsByName;
+    }
+
+
+    @Programmatic
+    @XmlTransient
+    public LinkedHashMap<String, BS3Tab> getAllTabsByName() {
+        final LinkedHashMap<String, BS3Tab> tabsByName = Maps.newLinkedHashMap();
+
+        visit(new BS3Page.VisitorAdapter() {
+            @Override
+            public void visit(final BS3Tab bS3Tab) {
+                tabsByName.put(bS3Tab.getName(), bS3Tab);
+            }
+        });
+        return tabsByName;
+    }
+
+
+    // TODO: need to figure out where the checking that can't have multiple divs with the same CSS id should go...
+    @Programmatic
+    @XmlTransient
+    public LinkedHashMap<String, HasCssId> getAllCssId() {
+        final LinkedHashMap<String, HasCssId> divsByCssId = Maps.newLinkedHashMap();
+
+        visit(new BS3Page.VisitorAdapter() {
+            @Override
+            public void visit(final BS3Row bs3Row) {
+                final String id = bs3Row.getId();
+                divsByCssId.put(id, bs3Row);
+            }
+        });
+        return divsByCssId;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/25a267a6/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 821db69..dee70d4 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
@@ -21,8 +21,10 @@ 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.XmlElementRef;
 import javax.xml.bind.annotation.XmlElementRefs;
+import javax.xml.bind.annotation.XmlTransient;
 import javax.xml.bind.annotation.XmlType;
 
 /**
@@ -39,10 +41,27 @@ import javax.xml.bind.annotation.XmlType;
             "cols"
         }
 )
-public class BS3Row extends BS3ElementAbstract {
+public class BS3Row extends BS3ElementAbstract implements HasCssId, BS3RowContentOwner {
 
     private static final long serialVersionUID = 1L;
 
+
+    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 List<BS3RowContent> cols = new ArrayList<BS3RowContent>(){{
         add(new BS3Col());
     }};
@@ -61,4 +80,24 @@ public class BS3Row extends BS3ElementAbstract {
         this.cols = cols;
     }
 
+
+
+    private BS3RowOwner owner;
+
+    /**
+     * Owner.
+     *
+     * <p>
+     *     Set programmatically by framework after reading in from XML.
+     * </p>
+     */
+    @XmlTransient
+    public BS3RowOwner getOwner() {
+        return owner;
+    }
+
+    public void setOwner(final BS3RowOwner owner) {
+        this.owner = owner;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/25a267a6/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3RowContent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3RowContent.java b/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3RowContent.java
index 88e9a69..b537ed9 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3RowContent.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3RowContent.java
@@ -19,6 +19,7 @@
 package org.apache.isis.applib.layout.bootstrap3;
 
 import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlTransient;
 
 /**
  * Common superclass for any content of a row.
@@ -62,4 +63,23 @@ public abstract class BS3RowContent extends BS3ElementAbstract {
         this.size = size;
     }
 
+
+    private BS3RowContentOwner owner;
+
+    /**
+     * Owner.
+     *
+     * <p>
+     *     Set programmatically by framework after reading in from XML.
+     * </p>
+     */
+    @XmlTransient
+    public BS3RowContentOwner getOwner() {
+        return owner;
+    }
+
+    public void setOwner(final BS3RowContentOwner owner) {
+        this.owner = owner;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/25a267a6/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3RowContentOwner.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3RowContentOwner.java b/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3RowContentOwner.java
new file mode 100644
index 0000000..70c1bf2
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3RowContentOwner.java
@@ -0,0 +1,25 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.applib.layout.bootstrap3;
+
+import org.apache.isis.applib.layout.common.Owner;
+
+public interface BS3RowContentOwner extends Owner {
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/25a267a6/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3RowOwner.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3RowOwner.java b/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3RowOwner.java
new file mode 100644
index 0000000..222f4f6
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3RowOwner.java
@@ -0,0 +1,28 @@
+/*
+ *  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.applib.layout.bootstrap3;
+
+import java.util.List;
+
+import org.apache.isis.applib.layout.common.Owner;
+
+public interface BS3RowOwner extends Owner {
+
+    List<BS3Row> getRows();
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/25a267a6/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 4489531..57e7ca5 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
@@ -23,6 +23,7 @@ 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.base.Predicate;
@@ -41,7 +42,7 @@ import com.google.common.base.Predicate;
             "rows"
         }
 )
-public class BS3Tab extends BS3ElementAbstract {
+public class BS3Tab extends BS3ElementAbstract implements BS3RowOwner {
 
     private static final long serialVersionUID = 1L;
 
@@ -72,6 +73,26 @@ public class BS3Tab extends BS3ElementAbstract {
     }
 
 
+
+    private BS3TabOwner owner;
+
+    /**
+     * Owner.
+     *
+     * <p>
+     *     Set programmatically by framework after reading in from XML.
+     * </p>
+     */
+    @XmlTransient
+    public BS3TabOwner getOwner() {
+        return owner;
+    }
+
+    public void setOwner(final BS3TabOwner owner) {
+        this.owner = owner;
+    }
+
+
     public static class Predicates {
         public static Predicate<BS3Tab> notEmpty() {
             return new Predicate<BS3Tab>() {

http://git-wip-us.apache.org/repos/asf/isis/blob/25a267a6/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 7fae67b..c96634a 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
@@ -22,6 +22,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlTransient;
 import javax.xml.bind.annotation.XmlType;
 
 /**
@@ -33,7 +34,7 @@ import javax.xml.bind.annotation.XmlType;
             "tabs"
         }
 )
-public class BS3TabGroup extends BS3ElementAbstract{
+public class BS3TabGroup extends BS3ElementAbstract implements BS3TabOwner {
 
     private static final long serialVersionUID = 1L;
 
@@ -51,4 +52,25 @@ public class BS3TabGroup extends BS3ElementAbstract{
     public void setTabs(final List<BS3Tab> tabs) {
         this.tabs = tabs;
     }
+
+
+    private BS3TabGroupOwner owner;
+
+    /**
+     * Owner.
+     *
+     * <p>
+     *     Set programmatically by framework after reading in from XML.
+     * </p>
+     */
+    @XmlTransient
+    public BS3TabGroupOwner getOwner() {
+        return owner;
+    }
+
+    public void setOwner(final BS3TabGroupOwner owner) {
+        this.owner = owner;
+    }
+
 }
+

http://git-wip-us.apache.org/repos/asf/isis/blob/25a267a6/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3TabGroupOwner.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3TabGroupOwner.java b/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3TabGroupOwner.java
new file mode 100644
index 0000000..1e4ba07
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3TabGroupOwner.java
@@ -0,0 +1,28 @@
+/*
+ *  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.applib.layout.bootstrap3;
+
+import java.util.List;
+
+import org.apache.isis.applib.layout.common.Owner;
+
+public interface BS3TabGroupOwner extends Owner {
+
+    List<BS3TabGroup> getTabGroups();
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/25a267a6/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3TabOwner.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3TabOwner.java b/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3TabOwner.java
new file mode 100644
index 0000000..c6de978
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3TabOwner.java
@@ -0,0 +1,28 @@
+/*
+ *  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.applib.layout.bootstrap3;
+
+import java.util.List;
+
+import org.apache.isis.applib.layout.common.Owner;
+
+public interface BS3TabOwner extends Owner {
+
+    List<BS3Tab> getTabs();
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/25a267a6/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/HasCssId.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/HasCssId.java b/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/HasCssId.java
new file mode 100644
index 0000000..e671d5b
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/HasCssId.java
@@ -0,0 +1,28 @@
+/*
+ *  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.applib.layout.bootstrap3;
+
+public interface HasCssId {
+
+    /**
+     * As per &lt;div id=&quot;...&quot;&gt;...&lt;/div&gt; : must be unique across entire page.
+     */
+    String getId();
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/25a267a6/core/applib/src/main/java/org/apache/isis/applib/layout/common/ActionLayoutData.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/common/ActionLayoutData.java b/core/applib/src/main/java/org/apache/isis/applib/layout/common/ActionLayoutData.java
index f8088fc..8b6cdac 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/common/ActionLayoutData.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/common/ActionLayoutData.java
@@ -48,7 +48,7 @@ import org.apache.isis.applib.annotation.Where;
         , "metadataError"
     }
 )
-public class ActionLayoutData implements Serializable, Owned<ActionOwner> {
+public class ActionLayoutData implements Serializable, Owned<ActionLayoutDataOwner> {
 
     private static final long serialVersionUID = 1L;
 
@@ -192,7 +192,7 @@ public class ActionLayoutData implements Serializable, Owned<ActionOwner> {
 
 
 
-    private ActionOwner owner;
+    private ActionLayoutDataOwner owner;
     /**
      * Owner.
      *
@@ -201,11 +201,11 @@ public class ActionLayoutData implements Serializable, Owned<ActionOwner> {
      * </p>
      */
     @XmlTransient
-    public ActionOwner getOwner() {
+    public ActionLayoutDataOwner getOwner() {
         return owner;
     }
 
-    public void setOwner(final ActionOwner owner) {
+    public void setOwner(final ActionLayoutDataOwner owner) {
         this.owner = owner;
     }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/25a267a6/core/applib/src/main/java/org/apache/isis/applib/layout/common/ActionLayoutDataOwner.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/common/ActionLayoutDataOwner.java b/core/applib/src/main/java/org/apache/isis/applib/layout/common/ActionLayoutDataOwner.java
new file mode 100644
index 0000000..bf2c9ca
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/common/ActionLayoutDataOwner.java
@@ -0,0 +1,25 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.applib.layout.common;
+
+import java.util.List;
+
+public interface ActionLayoutDataOwner extends Owner {
+    List<ActionLayoutData> getActions();
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/25a267a6/core/applib/src/main/java/org/apache/isis/applib/layout/common/ActionOwner.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/common/ActionOwner.java b/core/applib/src/main/java/org/apache/isis/applib/layout/common/ActionOwner.java
deleted file mode 100644
index 71ce307..0000000
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/common/ActionOwner.java
+++ /dev/null
@@ -1,25 +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.applib.layout.common;
-
-import java.util.List;
-
-public interface ActionOwner extends Owner {
-    List<ActionLayoutData> getActions();
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/25a267a6/core/applib/src/main/java/org/apache/isis/applib/layout/common/CollectionLayoutData.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/common/CollectionLayoutData.java b/core/applib/src/main/java/org/apache/isis/applib/layout/common/CollectionLayoutData.java
index e3b53cb..7ba3d5d 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/common/CollectionLayoutData.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/common/CollectionLayoutData.java
@@ -53,7 +53,7 @@ import org.apache.isis.applib.annotation.Where;
                 , "metadataError"
         }
 )
-public class CollectionLayoutData implements MemberRegion, ActionOwner, Serializable {
+public class CollectionLayoutData implements MemberRegion, ActionLayoutDataOwner, Serializable {
 
     private static final long serialVersionUID = 1L;
 

http://git-wip-us.apache.org/repos/asf/isis/blob/25a267a6/core/applib/src/main/java/org/apache/isis/applib/layout/common/DomainObjectLayoutData.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/common/DomainObjectLayoutData.java b/core/applib/src/main/java/org/apache/isis/applib/layout/common/DomainObjectLayoutData.java
index 764d7d6..0db726a 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/common/DomainObjectLayoutData.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/common/DomainObjectLayoutData.java
@@ -23,6 +23,7 @@ import java.io.Serializable;
 import javax.xml.bind.annotation.XmlAttribute;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
 import javax.xml.bind.annotation.XmlType;
 
 import org.apache.isis.applib.annotation.BookmarkPolicy;
@@ -158,5 +159,24 @@ public class DomainObjectLayoutData implements Serializable {
 
 
 
+    private MemberRegionOwner owner;
+    /**
+     * Owner.
+     *
+     * <p>
+     *     Set programmatically by framework after reading in from XML.
+     * </p>
+     */
+    @XmlTransient
+    public MemberRegionOwner getOwner() {
+        return owner;
+    }
+
+    public void setOwner(final MemberRegionOwner owner) {
+        this.owner = owner;
+    }
+
+
+
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/25a267a6/core/applib/src/main/java/org/apache/isis/applib/layout/common/DomainObjectLayoutDataOwner.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/common/DomainObjectLayoutDataOwner.java b/core/applib/src/main/java/org/apache/isis/applib/layout/common/DomainObjectLayoutDataOwner.java
new file mode 100644
index 0000000..2b719e9
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/common/DomainObjectLayoutDataOwner.java
@@ -0,0 +1,23 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.applib.layout.common;
+
+public interface DomainObjectLayoutDataOwner extends Owner {
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/25a267a6/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 d6e56ba..fe0a3fb 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
@@ -51,7 +51,7 @@ import org.apache.isis.applib.annotation.Programmatic;
                 , "properties"
         }
 )
-public class FieldSet implements MemberRegion, ActionOwner, Serializable {
+public class FieldSet implements MemberRegion, ActionLayoutDataOwner, Serializable {
 
     private static final long serialVersionUID = 1L;
 

http://git-wip-us.apache.org/repos/asf/isis/blob/25a267a6/core/applib/src/main/java/org/apache/isis/applib/layout/common/Page.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/common/Page.java b/core/applib/src/main/java/org/apache/isis/applib/layout/common/Page.java
index 7034321..8ed1d88 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/common/Page.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/common/Page.java
@@ -18,6 +18,15 @@
  */
 package org.apache.isis.applib.layout.common;
 
+import java.util.LinkedHashMap;
+
+import javax.xml.bind.annotation.XmlTransient;
+
+import com.google.common.collect.Maps;
+
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.layout.fixedcols.FCPage;
+import org.apache.isis.applib.layout.fixedcols.FCTab;
 import org.apache.isis.applib.services.layout.PageService;
 
 /**
@@ -29,10 +38,20 @@ import org.apache.isis.applib.services.layout.PageService;
  */
 public interface Page {
 
-
     boolean isNormalized();
 
     void setNormalized(final boolean normalized);
 
+    @Programmatic
+    LinkedHashMap<String, PropertyLayoutData> getAllPropertiesById();
+
+    @Programmatic
+    LinkedHashMap<String, CollectionLayoutData> getAllCollectionsById();
+
+    @Programmatic
+    LinkedHashMap<String, ActionLayoutData> getAllActionsById();
+
+    @Programmatic
+    LinkedHashMap<String, FieldSet> getAllFieldSetsByName();
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/25a267a6/core/applib/src/main/java/org/apache/isis/applib/layout/common/PropertyLayoutData.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/common/PropertyLayoutData.java b/core/applib/src/main/java/org/apache/isis/applib/layout/common/PropertyLayoutData.java
index fdc57e0..c9274b6 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/common/PropertyLayoutData.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/common/PropertyLayoutData.java
@@ -46,7 +46,7 @@ import org.apache.isis.applib.annotation.Where;
                 , "metadataError"
         }
 )
-public class PropertyLayoutData implements ActionOwner, Serializable, Owned<FieldSet> {
+public class PropertyLayoutData implements ActionLayoutDataOwner, Serializable, Owned<FieldSet> {
 
     private static final long serialVersionUID = 1L;
 

http://git-wip-us.apache.org/repos/asf/isis/blob/25a267a6/core/applib/src/main/java/org/apache/isis/applib/layout/fixedcols/FCPage.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/fixedcols/FCPage.java b/core/applib/src/main/java/org/apache/isis/applib/layout/fixedcols/FCPage.java
index a86ea88..5c3ecd0 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/fixedcols/FCPage.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/fixedcols/FCPage.java
@@ -32,7 +32,7 @@ import com.google.common.collect.Maps;
 
 import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.layout.common.ActionLayoutData;
-import org.apache.isis.applib.layout.common.ActionOwner;
+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.Page;
@@ -55,7 +55,7 @@ import org.apache.isis.applib.services.dto.Dto;
                 , "right"
         }
 )
-public class FCPage implements Page, Dto, ActionOwner, Serializable, FCColumnOwner, FCTabGroupOwner {
+public class FCPage implements Page, Dto, ActionLayoutDataOwner, Serializable, FCColumnOwner, FCTabGroupOwner {
 
     private static final long serialVersionUID = 1L;
 
@@ -115,10 +115,10 @@ public class FCPage implements Page, Dto, ActionOwner, Serializable, FCColumnOwn
 
 
     interface Visitor {
-        void visit(final FCPage FCPage);
-        void visit(final FCTabGroup tabGroup);
-        void visit(final FCTab FCTab);
-        void visit(final FCColumn FCColumn);
+        void visit(final FCPage fcPage);
+        void visit(final FCTabGroup fcTabGroup);
+        void visit(final FCTab fcTab);
+        void visit(final FCColumn fcColumn);
         void visit(final FieldSet fieldSet);
         void visit(final PropertyLayoutData propertyLayoutData);
         void visit(final CollectionLayoutData collectionLayoutData);
@@ -127,13 +127,13 @@ public class FCPage implements Page, Dto, ActionOwner, Serializable, FCColumnOwn
 
     public static class VisitorAdapter implements Visitor {
         @Override
-        public void visit(final FCPage FCPage) { }
+        public void visit(final FCPage fcPage) { }
         @Override
-        public void visit(final FCTabGroup tabGroup) { }
+        public void visit(final FCTabGroup fcTabGroup) { }
         @Override
-        public void visit(final FCTab FCTab) { }
+        public void visit(final FCTab fcTab) { }
         @Override
-        public void visit(final FCColumn FCColumn) { }
+        public void visit(final FCColumn fcColumn) { }
         @Override
         public void visit(final FieldSet fieldSet) {}
         @Override
@@ -149,39 +149,40 @@ public class FCPage implements Page, Dto, ActionOwner, Serializable, FCColumnOwn
      * Visits all elements of the graph.  The {@link Visitor} implementation
      * can assume that all "owner" references are populated.
      */
-    public void visit(final Visitor visitor) {
+    public void visit(final FCPage.Visitor visitor) {
         visitor.visit(this);
         traverseActions(this, visitor);
         traverseColumn(getLeft(), this, visitor);
         final List<FCTabGroup> tabGroups = getTabGroups();
-        for (final FCTabGroup tabGroup : tabGroups) {
-            tabGroup.setOwner(this);
-            visitor.visit(tabGroup);
-            final List<FCTab> tabs = tabGroup.getTabs();
-            for (final FCTab FCTab : tabs) {
-                FCTab.setOwner(tabGroup);
-                visitor.visit(FCTab);
-                traverseColumn(FCTab.getLeft(), FCTab, visitor);
-                traverseColumn(FCTab.getMiddle(), FCTab, visitor);
-                traverseColumn(FCTab.getRight(), FCTab, visitor);
+        for (final FCTabGroup fcTabGroup : tabGroups) {
+            fcTabGroup.setOwner(this);
+            visitor.visit(fcTabGroup);
+            final List<FCTab> tabs = fcTabGroup.getTabs();
+            for (final FCTab fcTab : tabs) {
+                fcTab.setOwner(fcTabGroup);
+                visitor.visit(fcTab);
+                traverseColumn(fcTab.getLeft(), fcTab, visitor);
+                traverseColumn(fcTab.getMiddle(), fcTab, visitor);
+                traverseColumn(fcTab.getRight(), fcTab, visitor);
             }
         }
         traverseColumn(getRight(), this, visitor);
     }
 
-    private void traverseColumn(final FCColumn FCColumn, final FCColumnOwner FCColumnOwner, final Visitor visitor) {
-        if(FCColumn == null) {
+    private void traverseColumn(
+            final FCColumn fcColumn, final FCColumnOwner fcColumnOwner, final Visitor visitor) {
+        if(fcColumn == null) {
             return;
         }
-        FCColumn.setOwner(FCColumnOwner);
-        visitor.visit(FCColumn);
-        traversePropertyGroups(FCColumn, visitor);
-        traverseCollections(FCColumn, visitor);
+        fcColumn.setOwner(fcColumnOwner);
+        visitor.visit(fcColumn);
+        traverseFieldSets(fcColumn, visitor);
+        traverseCollections(fcColumn, visitor);
     }
 
-    private void traversePropertyGroups(final FCColumn FCColumn, final Visitor visitor) {
-        for (final FieldSet fieldSet : FCColumn.getFieldSets()) {
-            fieldSet.setOwner(FCColumn);
+    private void traverseFieldSets(final FCColumn fcColumn, final Visitor visitor) {
+        for (final FieldSet fieldSet : fcColumn.getFieldSets()) {
+            fieldSet.setOwner(fcColumn);
             visitor.visit(fieldSet);
             traverseActions(fieldSet, visitor);
             final List<PropertyLayoutData> properties = fieldSet.getProperties();
@@ -193,21 +194,21 @@ public class FCPage implements Page, Dto, ActionOwner, Serializable, FCColumnOwn
         }
     }
 
-    private void traverseCollections(final FCColumn FCColumn, final Visitor visitor) {
-        for (final CollectionLayoutData collectionLayoutData : FCColumn.getCollections()) {
-            collectionLayoutData.setOwner(FCColumn);
+    private void traverseCollections(final FCColumn fcColumn, final Visitor visitor) {
+        for (final CollectionLayoutData collectionLayoutData : fcColumn.getCollections()) {
+            collectionLayoutData.setOwner(fcColumn);
             visitor.visit(collectionLayoutData);
             traverseActions(collectionLayoutData, visitor);
         }
     }
 
-    private void traverseActions(final ActionOwner actionOwner, final Visitor visitor) {
-        final List<ActionLayoutData> actionLayoutDatas = actionOwner.getActions();
+    private void traverseActions(final ActionLayoutDataOwner actionLayoutDataOwner, final Visitor visitor) {
+        final List<ActionLayoutData> actionLayoutDatas = actionLayoutDataOwner.getActions();
         if(actionLayoutDatas == null) {
             return;
         }
         for (final ActionLayoutData actionLayoutData : actionLayoutDatas) {
-            actionLayoutData.setOwner(actionOwner);
+            actionLayoutData.setOwner(actionLayoutDataOwner);
             visitor.visit(actionLayoutData);
         }
     }
@@ -258,36 +259,35 @@ public class FCPage implements Page, Dto, ActionOwner, Serializable, FCColumnOwn
 
     @Programmatic
     @XmlTransient
-    public LinkedHashMap<String, FCTab> getAllTabsByName() {
-        final LinkedHashMap<String, FCTab> tabsByName = Maps.newLinkedHashMap();
+    public LinkedHashMap<String, FieldSet> getAllFieldSetsByName() {
+        final LinkedHashMap<String, FieldSet> fieldSetsByName = Maps.newLinkedHashMap();
 
         visit(new FCPage.VisitorAdapter() {
             @Override
-            public void visit(final FCTab FCTab) {
-                tabsByName.put(FCTab.getName(), FCTab);
+            public void visit(final FieldSet fieldSet) {
+                fieldSetsByName.put(fieldSet.getName(), fieldSet);
             }
         });
-        return tabsByName;
+        return fieldSetsByName;
     }
 
 
     @Programmatic
     @XmlTransient
-    public LinkedHashMap<String, FieldSet> getAllPropertyGroupsByName() {
-        final LinkedHashMap<String, FieldSet> propertyGroupsByName = Maps.newLinkedHashMap();
+    public LinkedHashMap<String, FCTab> getAllTabsByName() {
+        final LinkedHashMap<String, FCTab> tabsByName = Maps.newLinkedHashMap();
 
         visit(new FCPage.VisitorAdapter() {
             @Override
-            public void visit(final FieldSet fieldSet) {
-                propertyGroupsByName.put(fieldSet.getName(), fieldSet);
+            public void visit(final FCTab fcTab) {
+                tabsByName.put(fcTab.getName(), fcTab);
             }
         });
-        return propertyGroupsByName;
+        return tabsByName;
     }
 
 
 
-
     private boolean normalized;
 
     @Programmatic
@@ -301,4 +301,5 @@ public class FCPage implements Page, Dto, ActionOwner, Serializable, FCColumnOwn
         this.normalized = normalized;
     }
 
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/25a267a6/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/layout/provider/PageNormalizerFC.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/layout/provider/PageNormalizerFC.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/layout/provider/PageNormalizerFC.java
index 813fb37..c86b2d9 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/layout/provider/PageNormalizerFC.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/layout/provider/PageNormalizerFC.java
@@ -33,7 +33,7 @@ import org.apache.isis.applib.layout.fixedcols.FCTab;
 import org.apache.isis.applib.layout.fixedcols.FCTabGroup;
 import org.apache.isis.applib.layout.common.MemberRegionOwner;
 import org.apache.isis.applib.layout.common.ActionLayoutData;
-import org.apache.isis.applib.layout.common.ActionOwner;
+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.PropertyLayoutData;
@@ -125,8 +125,8 @@ public class PageNormalizerFC extends PageNormalizerAbstract<FCPage> {
         // capture the first property group (if any) with the default name ('General')
         metadata.visit(new FCPage.VisitorAdapter() {
             @Override
-            public void visit(final FCColumn FCColumn) {
-                firstColumnRef.compareAndSet(null, FCColumn);
+            public void visit(final FCColumn fcColumn) {
+                firstColumnRef.compareAndSet(null, fcColumn);
             }
             @Override
             public void visit(final FieldSet fieldSet) {
@@ -135,8 +135,8 @@ public class PageNormalizerFC extends PageNormalizerAbstract<FCPage> {
                 }
             }
             @Override
-            public void visit(final FCTabGroup tabGroup) {
-                lastTabGroupRef.set(tabGroup);
+            public void visit(final FCTabGroup fcTabGroup) {
+                lastTabGroupRef.set(fcTabGroup);
             }
         });
 
@@ -252,7 +252,7 @@ public class PageNormalizerFC extends PageNormalizerAbstract<FCPage> {
 
             @Override
             public void visit(final ActionLayoutData actionLayoutData) {
-                final ActionOwner actionOwner = actionLayoutData.getOwner();
+                final ActionLayoutDataOwner actionLayoutDataOwner = actionLayoutData.getOwner();
                 final ObjectAction objectAction = objectActionById.get(actionLayoutData.getId());
                 if(objectAction == null) {
                     return;
@@ -260,18 +260,18 @@ public class PageNormalizerFC extends PageNormalizerAbstract<FCPage> {
 
                 final String memberOrderName;
                 final int memberOrderSequence;
-                if(actionOwner instanceof FieldSet) {
-                    final FieldSet fieldSet = (FieldSet) actionOwner;
+                if(actionLayoutDataOwner instanceof FieldSet) {
+                    final FieldSet fieldSet = (FieldSet) actionLayoutDataOwner;
                     final List<PropertyLayoutData> properties = fieldSet.getProperties();
                     final PropertyLayoutData propertyLayoutData = properties.get(0); // any will do
                     memberOrderName = propertyLayoutData.getId();
                     memberOrderSequence = actionPropertyGroupSequence++;
-                } else if(actionOwner instanceof PropertyLayoutData) {
-                    final PropertyLayoutData propertyLayoutData = (PropertyLayoutData) actionOwner;
+                } else if(actionLayoutDataOwner instanceof PropertyLayoutData) {
+                    final PropertyLayoutData propertyLayoutData = (PropertyLayoutData) actionLayoutDataOwner;
                     memberOrderName = propertyLayoutData.getId();
                     memberOrderSequence = actionPropertySequence++;
-                } else if(actionOwner instanceof CollectionLayoutData) {
-                    final CollectionLayoutData collectionLayoutData = (CollectionLayoutData) actionOwner;
+                } else if(actionLayoutDataOwner instanceof CollectionLayoutData) {
+                    final CollectionLayoutData collectionLayoutData = (CollectionLayoutData) actionLayoutDataOwner;
                     memberOrderName = collectionLayoutData.getId();
                     memberOrderSequence = actionCollectionSequence++;
                 } else {
@@ -283,13 +283,13 @@ public class PageNormalizerFC extends PageNormalizerAbstract<FCPage> {
                         new MemberOrderFacetXml(memberOrderName, ""+memberOrderSequence, translationService, objectAction));
 
 
-                if(actionOwner instanceof FieldSet) {
+                if(actionLayoutDataOwner instanceof FieldSet) {
                     if(actionLayoutData.getPosition() == null ||
                             actionLayoutData.getPosition() == org.apache.isis.applib.annotation.ActionLayout.Position.BELOW ||
                             actionLayoutData.getPosition() == org.apache.isis.applib.annotation.ActionLayout.Position.RIGHT) {
                         actionLayoutData.setPosition(org.apache.isis.applib.annotation.ActionLayout.Position.PANEL);
                     }
-                } else if(actionOwner instanceof PropertyLayoutData) {
+                } else if(actionLayoutDataOwner instanceof PropertyLayoutData) {
                     if(actionLayoutData.getPosition() == null ||
                             actionLayoutData.getPosition() == org.apache.isis.applib.annotation.ActionLayout.Position.PANEL_DROPDOWN ||
                             actionLayoutData.getPosition() == org.apache.isis.applib.annotation.ActionLayout.Position.PANEL) {

http://git-wip-us.apache.org/repos/asf/isis/blob/25a267a6/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/util/CssIdAppender.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/util/CssIdAppender.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/util/CssIdAppender.java
new file mode 100644
index 0000000..1d78137
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/util/CssIdAppender.java
@@ -0,0 +1,70 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.viewer.wicket.ui.util;
+
+import com.google.common.base.Strings;
+
+import org.apache.wicket.MarkupContainer;
+import org.apache.wicket.behavior.AttributeAppender;
+import org.apache.wicket.markup.ComponentTag;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+
+/**
+ * Implementation of {@link AttributeAppender} that appends the provided CSS
+ * <tt>id</tt> attribute.
+ */
+public class CssIdAppender extends AttributeAppender {
+
+    private static final long serialVersionUID = 1L;
+
+    public CssIdAppender(final IModel<String> appendModel) {
+        super("id", appendModel, " ");
+    }
+
+    public CssIdAppender(final String append) {
+        this(Model.of(append));
+    }
+
+    /**
+     * Adds CSS id to tag (providing that the id is non-null and non-empty).
+     */
+    public static void appendCssIdTo(
+            final ComponentTag tag,
+            final String cssId) {
+        if(Strings.isNullOrEmpty(cssId)) {
+            return;
+        }
+        tag.append("id", cssId, " ");
+    }
+
+    /**
+     * Adds CSS class to container (providing that the class is non-null and non-empty).
+     */
+    public static void appendCssIdTo(
+            final MarkupContainer markupContainer,
+            final String cssClass) {
+        if(Strings.isNullOrEmpty(cssClass)) {
+            return;
+        }
+        markupContainer.add(new CssIdAppender(cssClass));
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/25a267a6/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.layout-FC.xml
----------------------------------------------------------------------
diff --git a/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.layout-FC.xml b/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.layout-FC.xml
index da9fc4c..91a1fd1 100644
--- a/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.layout-FC.xml
+++ b/example/application/simpleapp/dom/src/main/java/domainapp/dom/simple/SimpleObject.layout-FC.xml
@@ -6,9 +6,9 @@
     </left>
     <tabGroup>
         <tab name="Properties">
-            <left span="8">
+            <left span="12">
                 <c:fieldSet name="General">
-                    <c:action id="delete"/>
+                    <c:action id="delete" position="PANEL_DROPDOWN"/>
                     <c:property id="name" labelPosition="TOP">
                         <c:action id="updateName">
                             <c:describedAs>This allows the name to be updated</c:describedAs>
@@ -16,18 +16,21 @@
                     </c:property>
                 </c:fieldSet>
             </left>
-            <middle span="4">
+        </tab>
+        <tab name="Metadata">
+            <left span="12">
                 <c:fieldSet name="Foo">
                     <c:action id="downloadJdoMetadata" position="PANEL"/>
                     <c:action id="downloadLayoutXml" position="PANEL"/>
                     <c:property id="versionSequence"/>
                 </c:fieldSet>
-            </middle>
+
+            </left>
         </tab>
     </tabGroup>
     <tabGroup>
         <tab name="Collections">
-            <left span="6">
+            <left span="12">
                 <c:collection id="similarTo" defaultView="table"/>
             </left>
             <right span="6">

http://git-wip-us.apache.org/repos/asf/isis/blob/25a267a6/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 482f6fa..c241c08 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
@@ -5,7 +5,8 @@
         <bs3:col span="8">
             <c:domainObject/>
         </bs3:col>
-        <bs3:col span="4" cssClass="foobar">
+        <bs3:col span="4" cssClass="foobar" unreferencedActions="true">
+            <c:action id="delete" cssClassFa="fa-trash"/>
         </bs3:col>
     </bs3:row>
 
@@ -16,7 +17,8 @@
                     <bs3:row>
                         <bs3:col span="12">
                             <c:fieldSet name="Metadata">
-                                <c:action id="downloadJdoMetadata" position="PANEL"/>
+                                <c:action id="downloadJdMetadata">
+                                </c:action>
                                 <c:action id="downloadLayoutXml" position="PANEL_DROPDOWN"/>
                                 <c:property id="versionSequence">
                                 </c:property>