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/10 17:12:40 UTC

[3/5] isis git commit: ISIS-993: moving around and renaming the applib schema files for layout

http://git-wip-us.apache.org/repos/asf/isis/blob/67b6e05e/core/applib/src/main/java/org/apache/isis/applib/layout/component/ActionLayoutDataOwner.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/component/ActionLayoutDataOwner.java b/core/applib/src/main/java/org/apache/isis/applib/layout/component/ActionLayoutDataOwner.java
new file mode 100644
index 0000000..6372cfb
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/component/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.component;
+
+import java.util.List;
+
+public interface ActionLayoutDataOwner extends Owner {
+    List<ActionLayoutData> getActions();
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/67b6e05e/core/applib/src/main/java/org/apache/isis/applib/layout/component/CollectionLayoutData.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/component/CollectionLayoutData.java b/core/applib/src/main/java/org/apache/isis/applib/layout/component/CollectionLayoutData.java
new file mode 100644
index 0000000..813c8c1
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/component/CollectionLayoutData.java
@@ -0,0 +1,268 @@
+/*
+ *  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.component;
+
+import java.io.Serializable;
+import java.util.List;
+
+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 com.google.common.base.Function;
+
+import org.apache.isis.applib.annotation.Where;
+
+/**
+ * Describes the layout of a single collection, broadly corresponds to the {@link org.apache.isis.applib.annotation.CollectionLayout} annotation.
+ *
+ * <p>
+ *     Note that {@link org.apache.isis.applib.annotation.CollectionLayout#render()} is omitted because
+ *     {@link #defaultView} is its replacement.
+ * </p>
+ */
+@XmlRootElement(
+        name = "collection"
+)
+@XmlType(
+        name = "collection"
+        , propOrder = {
+                "named"
+                ,"describedAs"
+                ,"sortedBy"
+                , "actions"
+                , "metadataError"
+        }
+)
+public class CollectionLayoutData
+        implements MemberRegion<CollectionLayoutDataOwner>,
+                   ActionLayoutDataOwner,
+                   Serializable,
+                   HasCssClass, HasDescribedAs, HasHidden, HasNamed {
+
+    private static final long serialVersionUID = 1L;
+
+    public CollectionLayoutData() {
+    }
+    public CollectionLayoutData(final String id) {
+        setId(id);
+    }
+
+
+    private String id;
+
+    /**
+     * Collection identifier, being the getter method without "get" prefix, first letter lower cased.
+     */
+    @XmlAttribute(required = true)
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+
+
+    private String cssClass;
+
+    @Override
+    @XmlAttribute(required = false)
+    public String getCssClass() {
+        return cssClass;
+    }
+
+    @Override
+    public void setCssClass(String cssClass) {
+        this.cssClass = cssClass;
+    }
+
+
+
+    private String describedAs;
+
+    @Override
+    @XmlElement(required = false)
+    public String getDescribedAs() {
+        return describedAs;
+    }
+
+    @Override
+    public void setDescribedAs(String describedAs) {
+        this.describedAs = describedAs;
+    }
+
+
+
+    private String defaultView;
+
+    /**
+     * Typically <code>table</code> or <code>hidden</code>, but could be any other named view that is configured and
+     * appropriate, eg <code>gmap3</code> or <code>fullcalendar2</code>.
+     */
+    @XmlAttribute(required = false)
+    public String getDefaultView() {
+        return defaultView;
+    }
+
+    public void setDefaultView(String defaultView) {
+        this.defaultView = defaultView;
+    }
+
+
+    private Where hidden;
+
+    @Override
+    @XmlAttribute(required = false)
+    public Where getHidden() {
+        return hidden;
+    }
+
+    @Override
+    public void setHidden(Where hidden) {
+        this.hidden = hidden;
+    }
+
+
+    private String named;
+
+    @Override
+    @XmlElement(required = false)
+    public String getNamed() {
+        return named;
+    }
+
+    @Override
+    public void setNamed(String named) {
+        this.named = named;
+    }
+
+
+    private Boolean namedEscaped;
+
+    @Override
+    @XmlAttribute(required = false)
+    public Boolean getNamedEscaped() {
+        return namedEscaped;
+    }
+
+    @Override
+    public void setNamedEscaped(Boolean namedEscaped) {
+        this.namedEscaped = namedEscaped;
+    }
+
+
+    private Integer paged;
+
+    @XmlAttribute(required = false)
+    public Integer getPaged() {
+        return paged;
+    }
+
+    public void setPaged(Integer paged) {
+        this.paged = paged;
+    }
+
+
+
+    private String sortedBy;
+
+    @XmlElement(required = false)
+    public String getSortedBy() {
+        return sortedBy;
+    }
+
+    public void setSortedBy(String sortedBy) {
+        this.sortedBy = sortedBy;
+    }
+
+
+
+    private List<ActionLayoutData> actions;
+
+    // no wrapper
+    @XmlElement(name = "action", required = false)
+    public List<ActionLayoutData> getActions() {
+        return actions;
+    }
+
+    public void setActions(List<ActionLayoutData> actionLayoutDatas) {
+        this.actions = actionLayoutDatas;
+    }
+
+
+
+    private CollectionLayoutDataOwner owner;
+    /**
+     * Owner.
+     *
+     * <p>
+     *     Set programmatically by framework after reading in from XML.
+     * </p>
+     */
+    @XmlTransient
+    public CollectionLayoutDataOwner getOwner() {
+        return owner;
+    }
+
+    public void setOwner(final CollectionLayoutDataOwner owner) {
+        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;
+    }
+
+
+
+
+
+    public static class Functions {
+        private Functions(){}
+
+        public static Function<CollectionLayoutData, String> id() {
+            return new Function<CollectionLayoutData, String>() {
+                @Override
+                public String apply(final CollectionLayoutData metadata) {
+                    return metadata.getId();
+                }
+            };
+        }
+    }
+
+    @Override public String toString() {
+        return "CollectionLayoutData{" +
+                "id='" + id + '\'' +
+                '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/67b6e05e/core/applib/src/main/java/org/apache/isis/applib/layout/component/CollectionLayoutDataOwner.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/component/CollectionLayoutDataOwner.java b/core/applib/src/main/java/org/apache/isis/applib/layout/component/CollectionLayoutDataOwner.java
new file mode 100644
index 0000000..b4ecb19
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/component/CollectionLayoutDataOwner.java
@@ -0,0 +1,26 @@
+/*
+ *  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.component;
+
+import java.util.List;
+
+public interface CollectionLayoutDataOwner extends MemberRegionOwner {
+
+    List<CollectionLayoutData> getCollections();
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/67b6e05e/core/applib/src/main/java/org/apache/isis/applib/layout/component/DomainObjectLayoutData.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/component/DomainObjectLayoutData.java b/core/applib/src/main/java/org/apache/isis/applib/layout/component/DomainObjectLayoutData.java
new file mode 100644
index 0000000..276b0a3
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/component/DomainObjectLayoutData.java
@@ -0,0 +1,208 @@
+/*
+ *  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.component;
+
+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;
+
+/**
+ * Describes the layout of the title and icon of a domain object, broadly corresponding to {@link org.apache.isis.applib.annotation.DomainObjectLayout}.
+ */
+@XmlRootElement(
+        name = "domainObject"
+)
+@XmlType(
+        name = "domainObject"
+        , propOrder = {
+            "named"
+            , "describedAs"
+            , "plural"
+            , "metadataError"
+        }
+)
+public class DomainObjectLayoutData implements Serializable, Owned<DomainObjectLayoutDataOwner>,
+        HasBookmarking, HasCssClass, HasCssClassFa, HasDescribedAs, HasNamed {
+
+    private static final long serialVersionUID = 1L;
+
+    public DomainObjectLayoutData() {
+    }
+
+
+    private BookmarkPolicy bookmarking;
+
+    @Override
+    @XmlAttribute(required = false)
+    public BookmarkPolicy getBookmarking() {
+        return bookmarking;
+    }
+
+    @Override
+    public void setBookmarking(BookmarkPolicy bookmarking) {
+        this.bookmarking = bookmarking;
+    }
+
+
+
+    private String cssClass;
+
+    @Override
+    @XmlAttribute(required = false)
+    public String getCssClass() {
+        return cssClass;
+    }
+
+    @Override
+    public void setCssClass(String cssClass) {
+        this.cssClass = cssClass;
+    }
+
+
+    private String cssClassFa;
+
+    @Override
+    @XmlAttribute(required = false)
+    public String getCssClassFa() {
+        return cssClassFa;
+    }
+
+    @Override
+    public void setCssClassFa(String cssClassFa) {
+        this.cssClassFa = cssClassFa;
+    }
+
+
+
+    private org.apache.isis.applib.annotation.ActionLayout.CssClassFaPosition cssClassFaPosition;
+
+    @Override
+    @XmlAttribute(required = false)
+    public org.apache.isis.applib.annotation.ActionLayout.CssClassFaPosition getCssClassFaPosition() {
+        return cssClassFaPosition;
+    }
+
+    @Override
+    public void setCssClassFaPosition(org.apache.isis.applib.annotation.ActionLayout.CssClassFaPosition cssClassFaPosition) {
+        this.cssClassFaPosition = cssClassFaPosition;
+    }
+
+
+    private String describedAs;
+
+    @Override
+    @XmlElement(required = false)
+    public String getDescribedAs() {
+        return describedAs;
+    }
+
+    @Override
+    public void setDescribedAs(String describedAs) {
+        this.describedAs = describedAs;
+    }
+
+
+
+    private String named;
+
+    @Override
+    @XmlElement(required = false)
+    public String getNamed() {
+        return named;
+    }
+
+    @Override
+    public void setNamed(String named) {
+        this.named = named;
+    }
+
+
+    private Boolean namedEscaped;
+
+    @Override
+    @XmlAttribute(required = false)
+    public Boolean getNamedEscaped() {
+        return namedEscaped;
+    }
+
+    @Override
+    public void setNamedEscaped(Boolean namedEscaped) {
+        this.namedEscaped = namedEscaped;
+    }
+
+
+
+    private String plural;
+
+    @XmlElement(required = false)
+    public String getPlural() {
+        return plural;
+    }
+
+    public void setPlural(String plural) {
+        this.plural = plural;
+    }
+
+
+
+
+
+    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;
+    }
+
+
+
+    private DomainObjectLayoutDataOwner owner;
+    /**
+     * Owner.
+     *
+     * <p>
+     *     Set programmatically by framework after reading in from XML.
+     * </p>
+     */
+    @XmlTransient
+    public DomainObjectLayoutDataOwner getOwner() {
+        return owner;
+    }
+
+    public void setOwner(final DomainObjectLayoutDataOwner owner) {
+        this.owner = owner;
+    }
+
+
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/67b6e05e/core/applib/src/main/java/org/apache/isis/applib/layout/component/DomainObjectLayoutDataOwner.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/component/DomainObjectLayoutDataOwner.java b/core/applib/src/main/java/org/apache/isis/applib/layout/component/DomainObjectLayoutDataOwner.java
new file mode 100644
index 0000000..74c6a25
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/component/DomainObjectLayoutDataOwner.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.component;
+
+public interface DomainObjectLayoutDataOwner extends Owner {
+
+    DomainObjectLayoutData getDomainObject();
+    void setDomainObject(DomainObjectLayoutData domainObjectLayoutData);
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/67b6e05e/core/applib/src/main/java/org/apache/isis/applib/layout/component/FieldSet.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/component/FieldSet.java b/core/applib/src/main/java/org/apache/isis/applib/layout/component/FieldSet.java
new file mode 100644
index 0000000..e2533da
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/component/FieldSet.java
@@ -0,0 +1,223 @@
+/*
+ *  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.component;
+
+import java.io.Serializable;
+import java.util.List;
+
+import javax.annotation.Nullable;
+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 com.google.common.base.Function;
+import com.google.common.collect.Lists;
+
+import org.apache.isis.applib.annotation.MemberOrder;
+import org.apache.isis.applib.layout.grid.bootstrap3.BS3Col;
+
+/**
+ * A {@link MemberRegion region} of the page containing a set of
+ * related {@link PropertyLayoutData properties} and associated
+ * {@link ActionLayoutData actions}.
+ */
+@XmlRootElement(
+        name = "fieldSet"
+)
+@XmlType(
+        name = "fieldSet"
+        , propOrder = {
+                "name"
+                , "actions"
+                , "properties"
+                , "metadataError"
+        }
+)
+public class FieldSet
+        implements MemberRegion<FieldSetOwner>,
+                   ActionLayoutDataOwner,
+                   Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    public FieldSet() {
+    }
+
+    public FieldSet(final String name) {
+        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 or {@link BS3Col col} 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;
+
+    /**
+     * Corresponds to the {@link MemberOrder#name()} (when applied to properties).
+     */
+    @XmlAttribute(required = true)
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+
+
+    private List<ActionLayoutData> actions = Lists.newArrayList();
+
+    // no wrapper
+    @XmlElement(name = "action", required = false)
+    public List<ActionLayoutData> getActions() {
+        return actions;
+    }
+
+    public void setActions(List<ActionLayoutData> actionLayoutDatas) {
+        this.actions = actionLayoutDatas;
+    }
+
+
+
+    private List<PropertyLayoutData> properties = Lists.newArrayList();
+
+    // no wrapper; required=false because may be auto-generated
+    @XmlElement(name = "property", required = false)
+    public List<PropertyLayoutData> getProperties() {
+        return properties;
+    }
+
+    public void setProperties(List<PropertyLayoutData> properties) {
+        this.properties = properties;
+    }
+
+
+    private FieldSetOwner owner;
+    /**
+     * Owner.
+     *
+     * <p>
+     *     Set programmatically by framework after reading in from XML.
+     * </p>
+     */
+    @XmlTransient
+    public FieldSetOwner getOwner() {
+        return owner;
+    }
+
+    public void setOwner(final FieldSetOwner owner) {
+        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;
+    }
+
+
+
+    public static class Util {
+        private Util(){}
+        public static Function<? super FieldSet, String> nameOf() {
+            return new Function<FieldSet, String>() {
+                @Nullable @Override
+                public String apply(@Nullable final FieldSet fieldSet) {
+                    return fieldSet.getName();
+                }
+            };
+        }
+    }
+
+    @Override public String toString() {
+        return "FieldSet{" +
+                "id='" + id + '\'' +
+                '}';
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/67b6e05e/core/applib/src/main/java/org/apache/isis/applib/layout/component/FieldSetOwner.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/component/FieldSetOwner.java b/core/applib/src/main/java/org/apache/isis/applib/layout/component/FieldSetOwner.java
new file mode 100644
index 0000000..c6a0942
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/component/FieldSetOwner.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.component;
+
+import java.util.List;
+
+public interface FieldSetOwner extends MemberRegionOwner {
+    List<FieldSet> getFieldSets();
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/67b6e05e/core/applib/src/main/java/org/apache/isis/applib/layout/component/Grid.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/component/Grid.java b/core/applib/src/main/java/org/apache/isis/applib/layout/component/Grid.java
new file mode 100644
index 0000000..754a2b1
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/component/Grid.java
@@ -0,0 +1,84 @@
+/*
+ *  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.component;
+
+import java.util.LinkedHashMap;
+
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.services.layout.GridService;
+
+/**
+ * All top-level page layout classes should implement this interface.
+ *
+ * <p>
+ *     It is used by the {@link GridService} as a common based type for any layouts read in from XML.
+ * </p>
+ */
+public interface Grid {
+
+    @Programmatic
+    Class<?> getDomainClass();
+
+    @Programmatic
+    void setDomainClass(final Class<?> domainClass);
+
+    @Programmatic
+    boolean isNormalized();
+
+    @Programmatic
+    void setNormalized(final boolean normalized);
+
+    @Programmatic
+    LinkedHashMap<String, PropertyLayoutData> getAllPropertiesById();
+
+    @Programmatic
+    LinkedHashMap<String, CollectionLayoutData> getAllCollectionsById();
+
+    @Programmatic
+    LinkedHashMap<String, ActionLayoutData> getAllActionsById();
+
+    interface Visitor {
+        void visit(final DomainObjectLayoutData domainObjectLayoutData);
+
+        void visit(final ActionLayoutData actionLayoutData);
+
+        void visit(final PropertyLayoutData propertyLayoutData);
+
+        void visit(final CollectionLayoutData collectionLayoutData);
+
+        void visit(final FieldSet fieldSet);
+    }
+
+    class VisitorAdapter implements Visitor {
+        @Override public void visit(final DomainObjectLayoutData domainObjectLayoutData) {
+        }
+        @Override public void visit(final ActionLayoutData actionLayoutData) {
+        }
+        @Override public void visit(final PropertyLayoutData propertyLayoutData) {
+        }
+        @Override public void visit(final CollectionLayoutData collectionLayoutData) {
+        }
+        @Override public void visit(final FieldSet fieldSet) {
+        }
+    }
+
+    @Programmatic
+    void visit(final Grid.Visitor visitor);
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/67b6e05e/core/applib/src/main/java/org/apache/isis/applib/layout/component/GridAbstract.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/component/GridAbstract.java b/core/applib/src/main/java/org/apache/isis/applib/layout/component/GridAbstract.java
new file mode 100644
index 0000000..e097756
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/component/GridAbstract.java
@@ -0,0 +1,181 @@
+/*
+ *  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.component;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlTransient;
+
+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.grid.bootstrap3.BS3Grid;
+import org.apache.isis.applib.services.layout.GridService;
+
+/**
+ * All top-level page layout classes should implement this interface.
+ *
+ * <p>
+ *     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 Class<?> domainClass;
+
+    @Programmatic
+    @XmlTransient
+    public Class<?> getDomainClass() {
+        return domainClass;
+    }
+
+    @Programmatic
+    public void setDomainClass(final Class<?> domainClass) {
+        this.domainClass = domainClass;
+    }
+
+
+
+    private boolean normalized;
+
+    @Programmatic
+    @XmlTransient
+    public boolean isNormalized() {
+        return normalized;
+    }
+
+    @Programmatic
+    public void setNormalized(final boolean normalized) {
+        this.normalized = normalized;
+    }
+
+
+    /**
+     * Convenience for subclasses.
+     */
+    protected void traverseActions(
+            final ActionLayoutDataOwner actionLayoutDataOwner,
+            final GridAbstract.Visitor visitor) {
+        final List<ActionLayoutData> actionLayoutDatas = actionLayoutDataOwner.getActions();
+        if(actionLayoutDatas == null) {
+            return;
+        }
+        for (final ActionLayoutData actionLayoutData : Lists.newArrayList(actionLayoutDatas)) {
+            actionLayoutData.setOwner(actionLayoutDataOwner);
+            visitor.visit(actionLayoutData);
+        }
+    }
+
+
+    /**
+     * Convenience for subclasses.
+     */
+    protected void traverseFieldSets(final FieldSetOwner fieldSetOwner, final GridAbstract.Visitor visitor) {
+        final List<FieldSet> fieldSets = fieldSetOwner.getFieldSets();
+        for (FieldSet fieldSet : Lists.newArrayList(fieldSets)) {
+            fieldSet.setOwner(fieldSetOwner);
+            visitor.visit(fieldSet);
+            traverseActions(fieldSet, visitor);
+            final List<PropertyLayoutData> properties = fieldSet.getProperties();
+            for (final PropertyLayoutData property : Lists.newArrayList(properties)) {
+                property.setOwner(fieldSet);
+                visitor.visit(property);
+                traverseActions(property, visitor);
+            }
+        }
+    }
+
+
+    /**
+     * Convenience for subclasses.
+     */
+    protected void traverseCollections(
+            final CollectionLayoutDataOwner owner, final GridAbstract.Visitor visitor) {
+        final List<CollectionLayoutData> collections = owner.getCollections();
+        for (CollectionLayoutData collection : Lists.newArrayList(collections)) {
+            collection.setOwner(owner);
+            visitor.visit(collection);
+            traverseActions(collection, visitor);
+        }
+    }
+
+
+    @Programmatic
+    @XmlTransient
+    public LinkedHashMap<String, PropertyLayoutData> getAllPropertiesById() {
+        final LinkedHashMap<String, PropertyLayoutData> propertiesById = Maps.newLinkedHashMap();
+        visit(new BS3Grid.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 BS3Grid.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 BS3Grid.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 BS3Grid.VisitorAdapter() {
+            @Override
+            public void visit(final FieldSet fieldSet) {
+                fieldSetsByName.put(fieldSet.getName(), fieldSet);
+            }
+        });
+        return fieldSetsByName;
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/67b6e05e/core/applib/src/main/java/org/apache/isis/applib/layout/component/HasBookmarking.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/component/HasBookmarking.java b/core/applib/src/main/java/org/apache/isis/applib/layout/component/HasBookmarking.java
new file mode 100644
index 0000000..b4750cf
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/component/HasBookmarking.java
@@ -0,0 +1,14 @@
+package org.apache.isis.applib.layout.component;
+
+import javax.xml.bind.annotation.XmlAttribute;
+
+import org.apache.isis.applib.annotation.BookmarkPolicy;
+
+/**
+ * Created by Dan on 10/02/2016.
+ */
+public interface HasBookmarking {
+    @XmlAttribute(required = false) BookmarkPolicy getBookmarking();
+
+    void setBookmarking(BookmarkPolicy bookmarking);
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/67b6e05e/core/applib/src/main/java/org/apache/isis/applib/layout/component/HasCssClass.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/component/HasCssClass.java b/core/applib/src/main/java/org/apache/isis/applib/layout/component/HasCssClass.java
new file mode 100644
index 0000000..3126d09
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/component/HasCssClass.java
@@ -0,0 +1,12 @@
+package org.apache.isis.applib.layout.component;
+
+import javax.xml.bind.annotation.XmlAttribute;
+
+/**
+ * Created by Dan on 10/02/2016.
+ */
+public interface HasCssClass {
+    @XmlAttribute(required = false) String getCssClass();
+
+    void setCssClass(String cssClass);
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/67b6e05e/core/applib/src/main/java/org/apache/isis/applib/layout/component/HasCssClassFa.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/component/HasCssClassFa.java b/core/applib/src/main/java/org/apache/isis/applib/layout/component/HasCssClassFa.java
new file mode 100644
index 0000000..f6111d8
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/component/HasCssClassFa.java
@@ -0,0 +1,16 @@
+package org.apache.isis.applib.layout.component;
+
+import javax.xml.bind.annotation.XmlAttribute;
+
+/**
+ * Created by Dan on 10/02/2016.
+ */
+public interface HasCssClassFa {
+    @XmlAttribute(required = false) String getCssClassFa();
+
+    void setCssClassFa(String cssClassFa);
+
+    @XmlAttribute(required = false) org.apache.isis.applib.annotation.ActionLayout.CssClassFaPosition getCssClassFaPosition();
+
+    void setCssClassFaPosition(org.apache.isis.applib.annotation.ActionLayout.CssClassFaPosition cssClassFaPosition);
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/67b6e05e/core/applib/src/main/java/org/apache/isis/applib/layout/component/HasDescribedAs.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/component/HasDescribedAs.java b/core/applib/src/main/java/org/apache/isis/applib/layout/component/HasDescribedAs.java
new file mode 100644
index 0000000..44e4b5d
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/component/HasDescribedAs.java
@@ -0,0 +1,12 @@
+package org.apache.isis.applib.layout.component;
+
+import javax.xml.bind.annotation.XmlElement;
+
+/**
+ * Created by Dan on 10/02/2016.
+ */
+public interface HasDescribedAs {
+    @XmlElement(required = false) String getDescribedAs();
+
+    void setDescribedAs(String describedAs);
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/67b6e05e/core/applib/src/main/java/org/apache/isis/applib/layout/component/HasHidden.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/component/HasHidden.java b/core/applib/src/main/java/org/apache/isis/applib/layout/component/HasHidden.java
new file mode 100644
index 0000000..935357a
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/component/HasHidden.java
@@ -0,0 +1,14 @@
+package org.apache.isis.applib.layout.component;
+
+import javax.xml.bind.annotation.XmlAttribute;
+
+import org.apache.isis.applib.annotation.Where;
+
+/**
+ * Created by Dan on 10/02/2016.
+ */
+public interface HasHidden {
+    @XmlAttribute(required = false) Where getHidden();
+
+    void setHidden(Where hidden);
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/67b6e05e/core/applib/src/main/java/org/apache/isis/applib/layout/component/HasNamed.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/component/HasNamed.java b/core/applib/src/main/java/org/apache/isis/applib/layout/component/HasNamed.java
new file mode 100644
index 0000000..3099496
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/component/HasNamed.java
@@ -0,0 +1,17 @@
+package org.apache.isis.applib.layout.component;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+
+/**
+ * Created by Dan on 10/02/2016.
+ */
+public interface HasNamed {
+    @XmlElement(required = false) String getNamed();
+
+    void setNamed(String named);
+
+    @XmlAttribute(required = false) Boolean getNamedEscaped();
+
+    void setNamedEscaped(Boolean namedEscaped);
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/67b6e05e/core/applib/src/main/java/org/apache/isis/applib/layout/component/MemberRegion.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/component/MemberRegion.java b/core/applib/src/main/java/org/apache/isis/applib/layout/component/MemberRegion.java
new file mode 100644
index 0000000..f44efe2
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/component/MemberRegion.java
@@ -0,0 +1,33 @@
+/*
+ *  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.component;
+
+/**
+ * Represents an area on the page containing one or several related members.
+ *
+ * <p>
+ *     Implementations include a <code>FieldSet</code> (containing a number
+ *     of properties and their actions), and a <code>CollectionLayoutData</code>
+ *     (containing a single collection and associated actions)
+ * </p>
+ */
+public interface MemberRegion<T extends MemberRegionOwner> extends Owned<T> {
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/67b6e05e/core/applib/src/main/java/org/apache/isis/applib/layout/component/MemberRegionOwner.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/component/MemberRegionOwner.java b/core/applib/src/main/java/org/apache/isis/applib/layout/component/MemberRegionOwner.java
new file mode 100644
index 0000000..a32526a
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/component/MemberRegionOwner.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.component;
+
+public interface MemberRegionOwner extends Owner {
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/67b6e05e/core/applib/src/main/java/org/apache/isis/applib/layout/component/Owned.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/component/Owned.java b/core/applib/src/main/java/org/apache/isis/applib/layout/component/Owned.java
new file mode 100644
index 0000000..807fe54
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/component/Owned.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.component;
+
+public interface Owned<T extends Owner> {
+    T getOwner();
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/67b6e05e/core/applib/src/main/java/org/apache/isis/applib/layout/component/Owner.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/component/Owner.java b/core/applib/src/main/java/org/apache/isis/applib/layout/component/Owner.java
new file mode 100644
index 0000000..37299cf
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/component/Owner.java
@@ -0,0 +1,24 @@
+/*
+ *  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.component;
+
+public interface Owner {
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/67b6e05e/core/applib/src/main/java/org/apache/isis/applib/layout/component/PropertyLayoutData.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/component/PropertyLayoutData.java b/core/applib/src/main/java/org/apache/isis/applib/layout/component/PropertyLayoutData.java
new file mode 100644
index 0000000..cf09ced
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/component/PropertyLayoutData.java
@@ -0,0 +1,252 @@
+/*
+ *  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.component;
+
+import java.io.Serializable;
+import java.util.List;
+
+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.LabelPosition;
+import org.apache.isis.applib.annotation.Where;
+
+/**
+ * Describes the layout of a single property, broadly corresponds to the {@link org.apache.isis.applib.annotation.PropertyLayout} annotation.
+ */
+@XmlRootElement(
+        name = "property"
+)
+@XmlType(
+        name = "property"
+        , propOrder = {
+                "named"
+                , "describedAs"
+                , "actions"
+                , "metadataError"
+        }
+)
+public class PropertyLayoutData
+        implements ActionLayoutDataOwner,
+                   Serializable,
+                   Owned<FieldSet>,
+                   HasCssClass, HasDescribedAs, HasHidden, HasNamed {
+
+    private static final long serialVersionUID = 1L;
+
+    public PropertyLayoutData() {
+    }
+
+    public PropertyLayoutData(final String id) {
+        this.id = id;
+    }
+
+    private String id;
+
+    /**
+     * Property identifier, being the getter method without "get" or "is" prefix, first letter lower cased.
+     */
+    @XmlAttribute(required = true)
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+
+
+    private String cssClass;
+
+    @Override
+    @XmlAttribute(required = false)
+    public String getCssClass() {
+        return cssClass;
+    }
+
+    @Override
+    public void setCssClass(String cssClass) {
+        this.cssClass = cssClass;
+    }
+
+
+    private String describedAs;
+
+    @Override
+    @XmlElement(required = false)
+    public String getDescribedAs() {
+        return describedAs;
+    }
+
+    @Override
+    public void setDescribedAs(String describedAs) {
+        this.describedAs = describedAs;
+    }
+
+
+    private Where hidden;
+
+    @Override
+    @XmlAttribute(required = false)
+    public Where getHidden() {
+        return hidden;
+    }
+
+    @Override
+    public void setHidden(Where hidden) {
+        this.hidden = hidden;
+    }
+
+
+    private LabelPosition labelPosition;
+
+    @XmlAttribute(required = false)
+    public LabelPosition getLabelPosition() {
+        return labelPosition;
+    }
+
+    public void setLabelPosition(LabelPosition labelPosition) {
+        this.labelPosition = labelPosition;
+    }
+
+
+    private Integer multiLine;
+
+    @XmlAttribute(required = false)
+    public Integer getMultiLine() {
+        return multiLine;
+    }
+
+    public void setMultiLine(Integer multiLine) {
+        this.multiLine = multiLine;
+    }
+
+
+    private String named;
+
+    @Override
+    @XmlElement(required = false)
+    public String getNamed() {
+        return named;
+    }
+
+    @Override
+    public void setNamed(String named) {
+        this.named = named;
+    }
+
+
+    private Boolean namedEscaped;
+
+    @Override
+    @XmlAttribute(required = false)
+    public Boolean getNamedEscaped() {
+        return namedEscaped;
+    }
+
+    @Override
+    public void setNamedEscaped(Boolean namedEscaped) {
+        this.namedEscaped = namedEscaped;
+    }
+
+
+    private Boolean renderedAsDayBefore;
+
+    @XmlAttribute(required = false)
+    public Boolean getRenderedAsDayBefore() {
+        return renderedAsDayBefore;
+    }
+
+    public void setRenderedAsDayBefore(Boolean renderedAsDayBefore) {
+        this.renderedAsDayBefore = renderedAsDayBefore;
+    }
+
+
+    private Integer typicalLength;
+
+    @XmlAttribute(required = false)
+    public Integer getTypicalLength() {
+        return typicalLength;
+    }
+
+    public void setTypicalLength(Integer typicalLength) {
+        this.typicalLength = typicalLength;
+    }
+
+
+
+    private List<ActionLayoutData> actions;
+
+    // no wrapper
+    @XmlElement(name = "action", required = false)
+    public List<ActionLayoutData> getActions() {
+        return actions;
+    }
+
+    public void setActions(List<ActionLayoutData> actionLayoutDatas) {
+        this.actions = actionLayoutDatas;
+    }
+
+
+    private FieldSet owner;
+    /**
+     * Owner.
+     *
+     * <p>
+     *     Set programmatically by framework after reading in from XML.
+     * </p>
+     */
+    @XmlTransient
+    public FieldSet getOwner() {
+        return owner;
+    }
+
+    public void setOwner(final FieldSet owner) {
+        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;
+    }
+
+
+    @Override
+    public String toString() {
+        return "PropertyLayoutData{" +
+                "id='" + id + '\'' +
+                '}';
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/67b6e05e/core/applib/src/main/java/org/apache/isis/applib/layout/component/package-info.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/component/package-info.java b/core/applib/src/main/java/org/apache/isis/applib/layout/component/package-info.java
new file mode 100644
index 0000000..3b17836
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/component/package-info.java
@@ -0,0 +1,36 @@
+/*
+ *  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.
+ */
+
+/**
+ * The classes in this package provide layout metadata for a domain object's properties, collections and actions - the
+ * &quot;building blocks&quot; which then must be arranged into some sort of layout.
+ *
+ * <p>
+ *     The <code>bootstrap3</code> and <code>fixedcols</code> packages both provide different ways of doing the layout,
+ *     and both reference the classes in this package.
+ * </p>
+ *
+ */
+@javax.xml.bind.annotation.XmlSchema(
+        namespace = "http://isis.apache.org/applib/layout/component",
+        elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED
+        // specifying the location seems to cause JaxbService#toXsd() to not generate the schema; not sure why...
+        //, location = ..."http://isis.apache.org/schema/metamodel/layout/common/common.xsd"
+)
+package org.apache.isis.applib.layout.component;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/67b6e05e/core/applib/src/main/java/org/apache/isis/applib/layout/grid/bootstrap3/BS3ClearFix.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/grid/bootstrap3/BS3ClearFix.java b/core/applib/src/main/java/org/apache/isis/applib/layout/grid/bootstrap3/BS3ClearFix.java
new file mode 100644
index 0000000..acf64e9
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/grid/bootstrap3/BS3ClearFix.java
@@ -0,0 +1,24 @@
+/*
+ *  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.grid.bootstrap3;
+
+public abstract class BS3ClearFix extends BS3RowContent {
+
+    public abstract String toCssClass();
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/67b6e05e/core/applib/src/main/java/org/apache/isis/applib/layout/grid/bootstrap3/BS3ClearFixHidden.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/grid/bootstrap3/BS3ClearFixHidden.java b/core/applib/src/main/java/org/apache/isis/applib/layout/grid/bootstrap3/BS3ClearFixHidden.java
new file mode 100644
index 0000000..817b685
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/grid/bootstrap3/BS3ClearFixHidden.java
@@ -0,0 +1,39 @@
+/*
+ *  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.grid.bootstrap3;
+
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlRootElement(
+        name = "clearFixHidden"
+)
+@XmlType(
+        name = "clearFixHidden"
+)
+public class BS3ClearFixHidden extends BS3ClearFix {
+
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    public String toCssClass() {
+        return "clearfix hidden-" + getSize().toCssClassFragment();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/67b6e05e/core/applib/src/main/java/org/apache/isis/applib/layout/grid/bootstrap3/BS3ClearFixVisible.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/grid/bootstrap3/BS3ClearFixVisible.java b/core/applib/src/main/java/org/apache/isis/applib/layout/grid/bootstrap3/BS3ClearFixVisible.java
new file mode 100644
index 0000000..bb83ca5
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/grid/bootstrap3/BS3ClearFixVisible.java
@@ -0,0 +1,59 @@
+/*
+ *  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.grid.bootstrap3;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlRootElement(
+        name = "clearFixVisible"
+)
+@XmlType(
+        name = "clearFixVisible"
+)
+public class BS3ClearFixVisible extends BS3ClearFix {
+
+    private static final long serialVersionUID = 1L;
+
+    public enum CssDisplay {
+        BLOCK,
+        INLINE,
+        INLINE_BLOCK
+    }
+
+    private CssDisplay cssDisplay;
+
+
+    @XmlAttribute(required = true)
+    public CssDisplay getCssDisplay() {
+        return cssDisplay;
+    }
+
+    public void setCssDisplay(final CssDisplay cssDisplay) {
+        this.cssDisplay = cssDisplay;
+    }
+
+
+    @Override
+    public String toCssClass() {
+        return "clearfix visible-" + getSize().toCssClassFragment() + "-" + getCssClass().toLowerCase().replace('_', '-');
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/67b6e05e/core/applib/src/main/java/org/apache/isis/applib/layout/grid/bootstrap3/BS3Col.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/grid/bootstrap3/BS3Col.java b/core/applib/src/main/java/org/apache/isis/applib/layout/grid/bootstrap3/BS3Col.java
new file mode 100644
index 0000000..bc289d8
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/grid/bootstrap3/BS3Col.java
@@ -0,0 +1,257 @@
+/*
+ *  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.grid.bootstrap3;
+
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementRef;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+import com.google.common.collect.Lists;
+
+import org.apache.isis.applib.layout.component.ActionLayoutData;
+import org.apache.isis.applib.layout.component.ActionLayoutDataOwner;
+import org.apache.isis.applib.layout.component.CollectionLayoutData;
+import org.apache.isis.applib.layout.component.CollectionLayoutDataOwner;
+import org.apache.isis.applib.layout.component.DomainObjectLayoutData;
+import org.apache.isis.applib.layout.component.DomainObjectLayoutDataOwner;
+import org.apache.isis.applib.layout.component.FieldSet;
+import org.apache.isis.applib.layout.component.FieldSetOwner;
+
+/**
+ * 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.
+ *
+ * <p>
+ *     Pretty much other content can be contained within a column, though most commonly it will be {@link FieldSet fieldset}s
+ *     (a group of properties) or {@link CollectionLayoutData collection}s.  However, columns can also be used to
+ *     contain further {@link BS3Row row}s (creating a nested grid of rows/cols/rows/cols) and {@link BS3TabGroup tabgroup}s.
+ * </p>
+ *
+ * <p>
+ *     It is rendered as a (eg) &lt;div class=&quot;col-md-4 ...&quot;&gt;
+ * </p>
+ */
+@XmlRootElement(
+        name = "col"
+)
+@XmlType(
+        name = "col"
+        , propOrder = {
+            "domainObject",
+            "actions",
+            "rows",
+            "tabGroups",
+            "fieldSets",
+            "collections",
+            "metadataError"
+        }
+)
+public class BS3Col extends BS3RowContent
+        implements ActionLayoutDataOwner, BS3TabGroupOwner, BS3RowOwner, FieldSetOwner, HasCssId,
+        CollectionLayoutDataOwner, DomainObjectLayoutDataOwner {
+
+    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)
+    public int getSpan() {
+        return span;
+    }
+
+    public void setSpan(final int span) {
+        this.span = span;
+    }
+
+
+    private Boolean unreferencedActions;
+
+    /**
+     * Whether this column should be used to hold any unreferenced actions (contributed or &quot;native&quot;).
+     *
+     * <p>
+     *     Any layout must have precisely one column or {@link 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 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 or {@link BS3TabGroup tabgroup} 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;
+
+    /**
+     * Whether to show the object's icon and title.
+     */
+    @XmlElementRef(type=DomainObjectLayoutData.class, name="domainObject", required = false)
+    public DomainObjectLayoutData getDomainObject() {
+        return domainObject;
+    }
+
+    public void setDomainObject(final DomainObjectLayoutData domainObjectLayoutData) {
+        this.domainObject = domainObjectLayoutData;
+    }
+
+
+
+    private List<ActionLayoutData> actions = Lists.newArrayList();
+
+    // no wrapper
+    @XmlElementRef(type = ActionLayoutData.class, name = "action", required = false)
+    public List<ActionLayoutData> getActions() {
+        return actions;
+    }
+
+    public void setActions(final List<ActionLayoutData> actions) {
+        this.actions = actions;
+    }
+
+
+
+    private List<BS3Row> rows = Lists.newArrayList();
+
+    // no wrapper
+    @XmlElement(name = "row", required = false)
+    public List<BS3Row> getRows() {
+        return rows;
+    }
+
+    public void setRows(final List<BS3Row> rows) {
+        this.rows = rows;
+    }
+
+
+
+    private List<BS3TabGroup> tabGroups = Lists.newArrayList();
+
+    // no wrapper
+    @XmlElement(name = "tabGroup", required = false)
+    public List<BS3TabGroup> getTabGroups() {
+        return tabGroups;
+    }
+
+    public void setTabGroups(final List<BS3TabGroup> tabGroups) {
+        this.tabGroups = tabGroups;
+    }
+
+
+
+    private List<FieldSet> fieldSets = Lists.newArrayList();
+
+    // no wrapper
+    @XmlElementRef(type=FieldSet.class, name = "fieldSet", required = false)
+    public List<FieldSet> getFieldSets() {
+        return fieldSets;
+    }
+
+    public void setFieldSets(final List<FieldSet> fieldSets) {
+        this.fieldSets = fieldSets;
+    }
+
+
+
+    private List<CollectionLayoutData> collections = Lists.newArrayList();
+
+    // no wrapper
+    @XmlElementRef(type=CollectionLayoutData.class, name = "collection", required = false)
+    public List<CollectionLayoutData> getCollections() {
+        return collections;
+    }
+
+    public void setCollections(final List<CollectionLayoutData> collections) {
+        this.collections = collections;
+    }
+
+
+
+    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 String toCssClass() {
+        final Size size = getSize() != null? getSize(): Size.MD;
+        return "col-" + size.toCssClassFragment() + "-" + getSpan();
+    }
+
+
+    @Override public String toString() {
+        return "BS3Col{" +
+                "id='" + id + '\'' +
+                '}';
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/67b6e05e/core/applib/src/main/java/org/apache/isis/applib/layout/grid/bootstrap3/BS3Element.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/grid/bootstrap3/BS3Element.java b/core/applib/src/main/java/org/apache/isis/applib/layout/grid/bootstrap3/BS3Element.java
new file mode 100644
index 0000000..062d557
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/grid/bootstrap3/BS3Element.java
@@ -0,0 +1,35 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.applib.layout.grid.bootstrap3;
+
+import java.io.Serializable;
+
+public interface BS3Element extends WithinGrid, Serializable {
+
+    /**
+     * Any additional CSS classes to render on the page element corresponding to this object,
+     * eg as per the <a href="http://getbootstrap.com/css/#grid-less">Bootstrap mixins</a> or just for
+     * custom styling.
+     */
+    String getCssClass();
+
+    void setCssClass(final String cssClass);
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/67b6e05e/core/applib/src/main/java/org/apache/isis/applib/layout/grid/bootstrap3/BS3ElementAbstract.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/grid/bootstrap3/BS3ElementAbstract.java b/core/applib/src/main/java/org/apache/isis/applib/layout/grid/bootstrap3/BS3ElementAbstract.java
new file mode 100644
index 0000000..ef0e312
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/grid/bootstrap3/BS3ElementAbstract.java
@@ -0,0 +1,46 @@
+/*
+ *  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.grid.bootstrap3;
+
+import javax.xml.bind.annotation.XmlAttribute;
+
+/**
+ * Superclass for all layout classes, factoring out the common {@link #getCssClass()} attribute.
+ */
+public abstract class BS3ElementAbstract implements BS3Element {
+
+    private String cssClass;
+
+    /**
+     * Any additional CSS classes to render on the page element corresponding to this object,
+     * eg as per the <a href="http://getbootstrap.com/css/#grid-less">Bootstrap mixins</a> or just for
+     * custom styling.
+     */
+    @XmlAttribute(required = false)
+    public String getCssClass() {
+        return cssClass;
+    }
+
+    public void setCssClass(final String cssClass) {
+        this.cssClass = cssClass;
+    }
+
+
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/67b6e05e/core/applib/src/main/java/org/apache/isis/applib/layout/grid/bootstrap3/BS3Grid.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/grid/bootstrap3/BS3Grid.java b/core/applib/src/main/java/org/apache/isis/applib/layout/grid/bootstrap3/BS3Grid.java
new file mode 100644
index 0000000..dc836ec
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/grid/bootstrap3/BS3Grid.java
@@ -0,0 +1,304 @@
+/*
+ *  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.grid.bootstrap3;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+
+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 com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.layout.component.ActionLayoutData;
+import org.apache.isis.applib.layout.component.CollectionLayoutData;
+import org.apache.isis.applib.layout.component.DomainObjectLayoutData;
+import org.apache.isis.applib.layout.component.FieldSet;
+import org.apache.isis.applib.layout.component.Grid;
+import org.apache.isis.applib.layout.component.GridAbstract;
+import org.apache.isis.applib.layout.component.PropertyLayoutData;
+import org.apache.isis.applib.services.dto.Dto;
+
+/**
+ * This is the top-level for rendering the domain object's properties, collections and actions.  It simply consists
+ * of a number of rows.
+ *
+ * <p>
+ *     The element is rendered as a &lt;div class=&quot;...&quot;&gt;
+ * </p>
+ */
+@XmlRootElement(
+        name = "grid"
+)
+@XmlType(
+        name = "grid"
+        , propOrder = {
+            "rows",
+            "metadataErrors"
+        }
+)
+public class BS3Grid extends GridAbstract implements BS3Element, Dto, BS3RowOwner {
+
+    private static final long serialVersionUID = 1L;
+
+
+    private String cssClass;
+
+    @XmlAttribute(required = false)
+    public String getCssClass() {
+        return cssClass;
+    }
+
+    public void setCssClass(final String cssClass) {
+        this.cssClass = cssClass;
+    }
+
+
+
+
+
+    private List<BS3Row> rows = Lists.newArrayList();
+
+    // no wrapper
+    @XmlElement(name = "row", required = true)
+    public List<BS3Row> getRows() {
+        return rows;
+    }
+
+    public void setRows(final List<BS3Row> rows) {
+        this.rows = rows;
+    }
+
+
+
+    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;
+
+
+
+    public interface Visitor extends Grid.Visitor {
+        void preVisit(final BS3Grid bs3Grid);
+        void visit(final BS3Grid bs3Grid);
+        void postVisit(final BS3Grid bs3Grid);
+        void preVisit(final BS3Row bs3Row);
+        void visit(final BS3Row bs3Row);
+        void postVisit(final BS3Row bs3Row);
+        void preVisit(final BS3Col bs3Col);
+        void visit(final BS3Col bs3Col);
+        void postVisit(final BS3Col bs3Col);
+        void visit(final BS3ClearFix bs3ClearFix);
+        void preVisit(final BS3TabGroup bs3TabGroup);
+        void visit(final BS3TabGroup bs3TabGroup);
+        void postVisit(final BS3TabGroup bs3TabGroup);
+        void preVisit(final BS3Tab bs3Tab);
+        void visit(final BS3Tab bs3Tab);
+        void postVisit(final BS3Tab bs3Tab);
+    }
+
+    public static class VisitorAdapter extends Grid.VisitorAdapter implements Visitor {
+        @Override public void preVisit(final BS3Grid bs3Grid) { }
+        @Override public void visit(final BS3Grid bs3Grid) { }
+        @Override public void postVisit(final BS3Grid bs3Grid) { }
+
+        @Override public void preVisit(final BS3Row bs3Row) { }
+        @Override public void visit(final BS3Row bs3Row) { }
+        @Override public void postVisit(final BS3Row bs3Row) { }
+
+        @Override public void preVisit(final BS3Col bs3Col) { }
+        @Override public void visit(final BS3Col bs3Col) { }
+        @Override public void postVisit(final BS3Col bs3Col) { }
+
+        @Override public void visit(final BS3ClearFix bs3ClearFix) { }
+
+        @Override public void preVisit(final BS3TabGroup bs3TabGroup) { }
+        @Override public void visit(final BS3TabGroup bs3TabGroup) { }
+        @Override public void postVisit(final BS3TabGroup bs3TabGroup) { }
+
+        @Override public void preVisit(final BS3Tab bs3Tab) { }
+        @Override public void visit(final BS3Tab bs3Tab) { }
+        @Override public void postVisit(final BS3Tab bs3Tab) { }
+    }
+
+    public void visit(final Grid.Visitor visitor) {
+        final BS3Grid.Visitor bs3Visitor = asBs3Visitor(visitor);
+        bs3Visitor.preVisit(this);
+        bs3Visitor.visit(this);
+        traverseRows(this, visitor);
+        bs3Visitor.postVisit(this);
+    }
+
+    protected void traverseRows(final BS3RowOwner rowOwner, final Grid.Visitor visitor) {
+        final BS3Grid.Visitor bs3Visitor = asBs3Visitor(visitor);
+        final List<BS3Row> rows = rowOwner.getRows();
+        for (BS3Row bs3Row : Lists.newArrayList(rows)) {
+            bs3Row.setOwner(this);
+            bs3Visitor.preVisit(bs3Row);
+            bs3Visitor.visit(bs3Row);
+            traverseCols(visitor, bs3Row);
+            bs3Visitor.postVisit(bs3Row);
+        }
+    }
+
+    private void traverseCols(final Grid.Visitor visitor, final BS3Row bs3Row) {
+        final BS3Grid.Visitor bs3Visitor = asBs3Visitor(visitor);
+        final List<BS3RowContent> cols = bs3Row.getCols();
+        for (BS3RowContent rowContent : Lists.newArrayList(cols)) {
+            rowContent.setOwner(bs3Row);
+            if(rowContent instanceof BS3Col) {
+                final BS3Col bs3Col = (BS3Col) rowContent;
+                bs3Visitor.preVisit(bs3Col);
+                bs3Visitor.visit(bs3Col);
+                traverseDomainObject(bs3Col, visitor);
+                traverseTabGroups(bs3Col, visitor);
+                traverseActions(bs3Col, visitor);
+                traverseFieldSets(bs3Col, visitor);
+                traverseCollections(bs3Col, visitor);
+                traverseRows(bs3Col, visitor);
+                bs3Visitor.postVisit(bs3Col);
+            } else if (rowContent instanceof BS3ClearFix) {
+                final BS3ClearFix bs3ClearFix = (BS3ClearFix) rowContent;
+                bs3Visitor.visit(bs3ClearFix);
+            } else {
+                throw new IllegalStateException(
+                        "Unrecognized implementation of BS3RowContent, " + rowContent);
+            }
+        }
+    }
+
+    private void traverseDomainObject(final BS3Col bs3Col, final Grid.Visitor visitor) {
+        final DomainObjectLayoutData domainObject = bs3Col.getDomainObject();
+        if(domainObject == null) {
+            return;
+        }
+        domainObject.setOwner(bs3Col);
+        visitor.visit(domainObject);
+    }
+
+    private void traverseTabGroups(
+            final BS3TabGroupOwner bs3TabGroupOwner,
+            final Grid.Visitor visitor) {
+        final BS3Grid.Visitor bs3Visitor = asBs3Visitor(visitor);
+        final List<BS3TabGroup> tabGroups = bs3TabGroupOwner.getTabGroups();
+        for (BS3TabGroup bs3TabGroup : Lists.newArrayList(tabGroups)) {
+            bs3TabGroup.setOwner(bs3TabGroupOwner);
+            bs3Visitor.preVisit(bs3TabGroup);
+            bs3Visitor.visit(bs3TabGroup);
+            traverseTabs(bs3TabGroup, visitor);
+            bs3Visitor.postVisit(bs3TabGroup);
+        }
+    }
+
+    private void traverseTabs(
+            final BS3TabOwner bs3TabOwner,
+            final Grid.Visitor visitor) {
+        final BS3Grid.Visitor bs3Visitor = asBs3Visitor(visitor);
+        final List<BS3Tab> tabs = bs3TabOwner.getTabs();
+        for (BS3Tab tab : Lists.newArrayList(tabs)) {
+            tab.setOwner(bs3TabOwner);
+            bs3Visitor.preVisit(tab);
+            bs3Visitor.visit(tab);
+            traverseRows(tab, visitor);
+            bs3Visitor.postVisit(tab);
+        }
+    }
+
+    private static Visitor asBs3Visitor(final Grid.Visitor visitor) {
+        return visitor instanceof Visitor? (Visitor) visitor : new BS3Grid.VisitorAdapter() {
+            @Override public void visit(final DomainObjectLayoutData domainObjectLayoutData) {
+                visitor.visit(domainObjectLayoutData);
+            }
+
+            @Override public void visit(final ActionLayoutData actionLayoutData) {
+                visitor.visit(actionLayoutData);
+            }
+
+            @Override public void visit(final PropertyLayoutData propertyLayoutData) {
+                visitor.visit(propertyLayoutData);
+            }
+
+            @Override public void visit(final CollectionLayoutData collectionLayoutData) {
+                visitor.visit(collectionLayoutData);
+            }
+
+            @Override public void visit(final FieldSet fieldSet) {
+                visitor.visit(fieldSet);
+            }
+        };
+    }
+
+
+    @Programmatic
+    @XmlTransient
+    public LinkedHashMap<String, BS3Tab> getAllTabsByName() {
+        final LinkedHashMap<String, BS3Tab> tabsByName = Maps.newLinkedHashMap();
+
+        visit(new BS3Grid.VisitorAdapter() {
+            @Override
+            public void visit(final BS3Tab bS3Tab) {
+                tabsByName.put(bS3Tab.getName(), bS3Tab);
+            }
+        });
+        return tabsByName;
+    }
+
+
+    @Programmatic
+    @XmlTransient
+    public LinkedHashMap<String, HasCssId> getAllCssId() {
+        final LinkedHashMap<String, HasCssId> divsByCssId = Maps.newLinkedHashMap();
+
+        visit(new BS3Grid.VisitorAdapter() {
+            @Override
+            public void visit(final BS3Row bs3Row) {
+                final String id = bs3Row.getId();
+                divsByCssId.put(id, bs3Row);
+            }
+        });
+        return divsByCssId;
+    }
+
+    @Override
+    @Programmatic
+    @XmlTransient
+    public BS3Grid getGrid() {
+        return this;
+    }
+
+}