You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2016/02/03 22:23:41 UTC
[2/3] isis git commit: ISIS-993: normalizing the BS3 grid,
factoring out commonalities into superclass.
ISIS-993: normalizing the BS3 grid, factoring out commonalities into superclass.
Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/fe46a781
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/fe46a781
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/fe46a781
Branch: refs/heads/ISIS-993
Commit: fe46a781eb7472694e705cfd396e630964c3add3
Parents: 63d03d2
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Tue Feb 2 21:29:22 2016 +0000
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Tue Feb 2 21:29:22 2016 +0000
----------------------------------------------------------------------
.../isis/applib/layout/bootstrap3/BS3Col.java | 26 +-
.../applib/layout/bootstrap3/BS3Element.java | 38 +++
.../layout/bootstrap3/BS3ElementAbstract.java | 5 +-
.../isis/applib/layout/bootstrap3/BS3Grid.java | 248 +++++---------
.../isis/applib/layout/bootstrap3/BS3Row.java | 17 +
.../common/CollectionLayoutDataOwner.java | 25 ++
.../applib/layout/common/FieldSetOwner.java | 25 ++
.../apache/isis/applib/layout/common/Grid.java | 39 ++-
.../isis/applib/layout/common/GridAbstract.java | 164 +++++++++
.../isis/applib/layout/fixedcols/FCColumn.java | 7 +-
.../isis/applib/layout/fixedcols/FCGrid.java | 159 ++-------
.../services/grid/GridNormalizerService.java | 6 +-
.../grid/GridNormalizerServiceAbstract.java | 335 +++++++++++++++++++
.../services/grid/GridNormalizerUtil.java | 38 +++
.../bootstrap3/GridNormalizerServiceBS3.java | 232 +++++++++++--
.../grid/fixedcols/GridNormalizerServiceFC.java | 274 ++-------------
.../ui/components/layout/bs3/BS3GridPanel.java | 5 +-
.../wicket/ui/components/layout/bs3/Util.java | 3 +-
18 files changed, 1049 insertions(+), 597 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/isis/blob/fe46a781/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 cef0f80..752c7e4 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
@@ -31,9 +31,10 @@ 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.CollectionLayoutDataOwner;
import org.apache.isis.applib.layout.common.DomainObjectLayoutData;
import org.apache.isis.applib.layout.common.FieldSet;
-import org.apache.isis.applib.layout.common.MemberRegionOwner;
+import org.apache.isis.applib.layout.common.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.
@@ -60,9 +61,12 @@ import org.apache.isis.applib.layout.common.MemberRegionOwner;
"tabGroups",
"fieldSets",
"collections",
+ "metadataError"
}
)
-public class BS3Col extends BS3RowContent implements ActionLayoutDataOwner, BS3TabGroupOwner, BS3RowOwner, MemberRegionOwner, HasCssId {
+public class BS3Col extends BS3RowContent
+ implements ActionLayoutDataOwner, BS3TabGroupOwner, BS3RowOwner, FieldSetOwner, HasCssId,
+ CollectionLayoutDataOwner {
private static final long serialVersionUID = 1L;
@@ -239,8 +243,26 @@ public class BS3Col extends BS3RowContent implements ActionLayoutDataOwner, BS3T
+
+ 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();
}
+
}
http://git-wip-us.apache.org/repos/asf/isis/blob/fe46a781/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Element.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Element.java b/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Element.java
new file mode 100644
index 0000000..669fcbb
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Element.java
@@ -0,0 +1,38 @@
+/*
+ * 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.io.Serializable;
+
+public interface BS3Element extends 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);
+
+
+ String getPath();
+ void setPath(final String path);
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/fe46a781/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3ElementAbstract.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3ElementAbstract.java b/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3ElementAbstract.java
index 6bcd45a..95aa611 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3ElementAbstract.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3ElementAbstract.java
@@ -18,8 +18,6 @@
*/
package org.apache.isis.applib.layout.bootstrap3;
-import java.io.Serializable;
-
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlTransient;
@@ -28,7 +26,7 @@ import org.apache.isis.applib.annotation.Programmatic;
/**
* Superclass for all layout classes, factoring out the common {@link #getCssClass()} attribute.
*/
-public abstract class BS3ElementAbstract implements Serializable {
+public abstract class BS3ElementAbstract implements BS3Element {
private String cssClass;
@@ -63,5 +61,4 @@ public abstract class BS3ElementAbstract implements Serializable {
}
-
}
http://git-wip-us.apache.org/repos/asf/isis/blob/fe46a781/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Grid.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Grid.java b/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Grid.java
index e3904c4..6360480 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Grid.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/bootstrap3/BS3Grid.java
@@ -22,21 +22,21 @@ import java.util.ArrayList;
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.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.Grid;
+import org.apache.isis.applib.layout.common.GridAbstract;
import org.apache.isis.applib.layout.common.PropertyLayoutData;
import org.apache.isis.applib.services.dto.Dto;
@@ -58,77 +58,67 @@ import org.apache.isis.applib.services.dto.Dto;
, "metadataErrors"
}
)
-public class BS3Grid extends BS3ElementAbstract implements Grid, Dto, BS3RowOwner {
+public class BS3Grid extends GridAbstract implements BS3Element, Dto, BS3RowOwner {
private static final long serialVersionUID = 1L;
- private List<BS3Row> rows = new ArrayList<BS3Row>(){{
- add(new BS3Row());
- }};
- // no wrapper
- @XmlElement(name = "row", required = true)
- public List<BS3Row> getRows() {
- return rows;
+ private String cssClass;
+
+ @XmlAttribute(required = false)
+ public String getCssClass() {
+ return cssClass;
}
- public void setRows(final List<BS3Row> rows) {
- this.rows = rows;
+ public void setCssClass(final String cssClass) {
+ this.cssClass = cssClass;
}
- private boolean normalized;
+ private String path;
@Programmatic
@XmlTransient
- public boolean isNormalized() {
- return normalized;
+ public String getPath() {
+ return path;
}
@Programmatic
- public void setNormalized(final boolean normalized) {
- this.normalized = normalized;
+ public void setPath(final String path) {
+ this.path = path;
}
- private List<String> metadataErrors = Lists.newArrayList();
-
- /**
- * For diagnostics; populated by the framework if and only if a metadata error.
- *
- * <p>
- * For example, if there is not exactly one {@link BS3Col} with the
- * {@link BS3Col#isUnreferencedActions()} attribute set, then this is an error. Ditto for
- * {@link BS3Col#isUnreferencedCollections() collections}
- * and {@link BS3Col#isUnreferencedProperties() properties}.
- * </p>
- */
- @XmlElement(required = false)
- public List<String> getMetadataErrors() {
- return metadataErrors;
+
+
+ private List<BS3Row> rows = new ArrayList<BS3Row>(){{
+ add(new BS3Row());
+ }};
+
+ // no wrapper
+ @XmlElement(name = "row", required = true)
+ public List<BS3Row> getRows() {
+ return rows;
}
- public void setMetadataErrors(final List<String> metadataErrors) {
- this.metadataErrors = metadataErrors;
+ public void setRows(final List<BS3Row> rows) {
+ this.rows = rows;
}
- interface Visitor {
+
+
+ interface Visitor extends Grid.Visitor {
void visit(final BS3Grid 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 {
+ public static class VisitorAdapter extends Grid.VisitorAdapter implements Visitor {
@Override
- public void visit(final BS3Grid bs3Page) { }
+ public void visit(final BS3Grid bs3Grid) { }
@Override
public void visit(final BS3Row bs3Row) { }
@Override
@@ -139,51 +129,48 @@ public class BS3Grid extends BS3ElementAbstract implements Grid, Dto, BS3RowOwne
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 BS3Grid.Visitor visitor) {
- visitor.visit(this);
+ public void visit(final Grid.Visitor visitor) {
+ final BS3Grid.Visitor bs3Visitor = asBs3Visitor(visitor);
+ bs3Visitor.visit(this);
traverseRows(this, visitor);
}
- protected void traverseRows(final BS3RowOwner rowOwner, final Visitor visitor) {
+ protected void traverseRows(final BS3RowOwner rowOwner, final Grid.Visitor visitor) {
+ final BS3Grid.Visitor bs3Visitor = asBs3Visitor(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);
- }
+ bs3Visitor.visit(bs3Row);
+ traverseCols(visitor, 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 : cols) {
+ rowContent.setOwner(bs3Row);
+ if(rowContent instanceof BS3Col) {
+ final BS3Col bs3Col = (BS3Col) rowContent;
+ bs3Visitor.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;
+ bs3Visitor.visit(bs3ClearFix);
+ } else {
+ throw new IllegalStateException(
+ "Unrecognized implementation of BS3RowContent, " + rowContent);
}
}
}
- private void traverseDomainObject(final BS3Col bs3Col, final Visitor visitor) {
+ private void traverseDomainObject(final BS3Col bs3Col, final Grid.Visitor visitor) {
final DomainObjectLayoutData domainObject = bs3Col.getDomainObject();
if(domainObject == null) {
return;
@@ -194,120 +181,50 @@ public class BS3Grid extends BS3ElementAbstract implements Grid, Dto, BS3RowOwne
private void traverseTabGroups(
final BS3TabGroupOwner bs3TabGroupOwner,
- final Visitor visitor) {
+ final Grid.Visitor visitor) {
+ final BS3Grid.Visitor bs3Visitor = asBs3Visitor(visitor);
final List<BS3TabGroup> tabGroups = bs3TabGroupOwner.getTabGroups();
for (BS3TabGroup bs3TabGroup : tabGroups) {
bs3TabGroup.setOwner(bs3TabGroupOwner);
- visitor.visit(bs3TabGroup);
+ bs3Visitor.visit(bs3TabGroup);
traverseTabs(bs3TabGroup, visitor);
}
}
private void traverseTabs(
final BS3TabOwner bs3TabOwner,
- final Visitor visitor) {
+ final Grid.Visitor visitor) {
+ final BS3Grid.Visitor bs3Visitor = asBs3Visitor(visitor);
final List<BS3Tab> tabs = bs3TabOwner.getTabs();
for (BS3Tab tab : tabs) {
tab.setOwner(bs3TabOwner);
- visitor.visit(tab);
+ bs3Visitor.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 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);
}
- }
- }
- 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 BS3Grid.VisitorAdapter() {
- public void visit(final PropertyLayoutData propertyLayoutData) {
- propertiesById.put(propertyLayoutData.getId(), propertyLayoutData);
+ @Override public void visit(final ActionLayoutData actionLayoutData) {
+ visitor.visit(actionLayoutData);
}
- });
- 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);
+ @Override public void visit(final PropertyLayoutData propertyLayoutData) {
+ visitor.visit(propertyLayoutData);
}
- });
- 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);
+ @Override public void visit(final CollectionLayoutData collectionLayoutData) {
+ visitor.visit(collectionLayoutData);
}
- });
- 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);
+ @Override public void visit(final FieldSet fieldSet) {
+ visitor.visit(fieldSet);
}
- });
- return fieldSetsByName;
+ };
}
@@ -326,7 +243,6 @@ public class BS3Grid extends BS3ElementAbstract implements Grid, Dto, BS3RowOwne
}
- // 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() {
http://git-wip-us.apache.org/repos/asf/isis/blob/fe46a781/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 ff75f46..d05dbf8 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
@@ -22,6 +22,7 @@ import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlElementRefs;
import javax.xml.bind.annotation.XmlTransient;
@@ -39,6 +40,7 @@ import javax.xml.bind.annotation.XmlType;
name = "row"
, propOrder = {
"cols"
+ , "metadataError"
}
)
public class BS3Row extends BS3ElementAbstract implements HasCssId, BS3RowContentOwner {
@@ -82,6 +84,21 @@ public class BS3Row extends BS3ElementAbstract implements HasCssId, BS3RowConten
+ 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 BS3RowOwner owner;
/**
http://git-wip-us.apache.org/repos/asf/isis/blob/fe46a781/core/applib/src/main/java/org/apache/isis/applib/layout/common/CollectionLayoutDataOwner.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/common/CollectionLayoutDataOwner.java b/core/applib/src/main/java/org/apache/isis/applib/layout/common/CollectionLayoutDataOwner.java
new file mode 100644
index 0000000..438ae56
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/common/CollectionLayoutDataOwner.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 CollectionLayoutDataOwner extends MemberRegionOwner {
+ List<CollectionLayoutData> getCollections();
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/fe46a781/core/applib/src/main/java/org/apache/isis/applib/layout/common/FieldSetOwner.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/common/FieldSetOwner.java b/core/applib/src/main/java/org/apache/isis/applib/layout/common/FieldSetOwner.java
new file mode 100644
index 0000000..f3e5fd0
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/common/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.common;
+
+import java.util.List;
+
+public interface FieldSetOwner extends MemberRegionOwner {
+ List<FieldSet> getFieldSets();
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/fe46a781/core/applib/src/main/java/org/apache/isis/applib/layout/common/Grid.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/common/Grid.java b/core/applib/src/main/java/org/apache/isis/applib/layout/common/Grid.java
index 92e5a1d..7380a3a 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/common/Grid.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/common/Grid.java
@@ -19,8 +19,10 @@
package org.apache.isis.applib.layout.common;
import java.util.LinkedHashMap;
+import java.util.List;
import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.layout.bootstrap3.BS3Col;
import org.apache.isis.applib.services.layout.GridService;
/**
@@ -36,16 +38,37 @@ public interface Grid {
void setNormalized(final boolean normalized);
- @Programmatic
- LinkedHashMap<String, PropertyLayoutData> getAllPropertiesById();
+ @Programmatic LinkedHashMap<String, PropertyLayoutData> getAllPropertiesById();
- @Programmatic
- LinkedHashMap<String, CollectionLayoutData> getAllCollectionsById();
+ @Programmatic LinkedHashMap<String, CollectionLayoutData> getAllCollectionsById();
- @Programmatic
- LinkedHashMap<String, ActionLayoutData> getAllActionsById();
+ @Programmatic LinkedHashMap<String, ActionLayoutData> getAllActionsById();
- @Programmatic
- LinkedHashMap<String, FieldSet> getAllFieldSetsByName();
+ 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) {
+ }
+ }
+
+ void visit(final Grid.Visitor visitor);
}
http://git-wip-us.apache.org/repos/asf/isis/blob/fe46a781/core/applib/src/main/java/org/apache/isis/applib/layout/common/GridAbstract.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/common/GridAbstract.java b/core/applib/src/main/java/org/apache/isis/applib/layout/common/GridAbstract.java
new file mode 100644
index 0000000..70cee11
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/common/GridAbstract.java
@@ -0,0 +1,164 @@
+/*
+ * 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.LinkedHashMap;
+import java.util.List;
+
+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.bootstrap3.BS3Grid;
+import org.apache.isis.applib.layout.fixedcols.FCColumn;
+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 abstract class GridAbstract implements Grid {
+
+ 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 : 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 : fieldSets) {
+ fieldSet.setOwner(fieldSetOwner);
+ 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);
+ }
+ }
+ }
+
+
+ /**
+ * Convenience for subclasses.
+ */
+ protected void traverseCollections(
+ final CollectionLayoutDataOwner owner, final GridAbstract.Visitor visitor) {
+ final List<CollectionLayoutData> collections = owner.getCollections();
+ for (CollectionLayoutData collection : 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/fe46a781/core/applib/src/main/java/org/apache/isis/applib/layout/fixedcols/FCColumn.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/fixedcols/FCColumn.java b/core/applib/src/main/java/org/apache/isis/applib/layout/fixedcols/FCColumn.java
index 25436ea..4c29f26 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/fixedcols/FCColumn.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/fixedcols/FCColumn.java
@@ -31,10 +31,11 @@ import com.google.common.collect.Lists;
import org.apache.isis.applib.annotation.MemberGroupLayout;
import org.apache.isis.applib.annotation.Programmatic;
import org.apache.isis.applib.layout.common.CollectionLayoutData;
+import org.apache.isis.applib.layout.common.CollectionLayoutDataOwner;
import org.apache.isis.applib.layout.common.FieldSet;
-import org.apache.isis.applib.layout.common.PropertyLayoutData;
-import org.apache.isis.applib.layout.common.MemberRegionOwner;
+import org.apache.isis.applib.layout.common.FieldSetOwner;
import org.apache.isis.applib.layout.common.Owned;
+import org.apache.isis.applib.layout.common.PropertyLayoutData;
/**
* The column contains a mixture of {@link FieldSet}s (of {@link PropertyLayoutData properties}) and also
@@ -52,7 +53,7 @@ import org.apache.isis.applib.layout.common.Owned;
, "collections"
}
)
-public class FCColumn implements Serializable, MemberRegionOwner, Owned<FCColumnOwner> {
+public class FCColumn implements Serializable, FieldSetOwner, CollectionLayoutDataOwner, Owned<FCColumnOwner> {
private static final long serialVersionUID = 1L;
http://git-wip-us.apache.org/repos/asf/isis/blob/fe46a781/core/applib/src/main/java/org/apache/isis/applib/layout/fixedcols/FCGrid.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/fixedcols/FCGrid.java b/core/applib/src/main/java/org/apache/isis/applib/layout/fixedcols/FCGrid.java
index ed32e64..01626dd 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/layout/fixedcols/FCGrid.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/layout/fixedcols/FCGrid.java
@@ -19,23 +19,20 @@
package org.apache.isis.applib.layout.fixedcols;
import java.io.Serializable;
-import java.util.LinkedHashMap;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;
-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.Grid;
+import org.apache.isis.applib.layout.common.GridAbstract;
import org.apache.isis.applib.layout.common.PropertyLayoutData;
import org.apache.isis.applib.services.dto.Dto;
@@ -55,7 +52,7 @@ import org.apache.isis.applib.services.dto.Dto;
, "right"
}
)
-public class FCGrid implements Grid, Dto, ActionLayoutDataOwner, Serializable, FCColumnOwner, FCTabGroupOwner {
+public class FCGrid extends GridAbstract implements Dto, ActionLayoutDataOwner, Serializable, FCColumnOwner, FCTabGroupOwner {
private static final long serialVersionUID = 1L;
@@ -114,18 +111,15 @@ public class FCGrid implements Grid, Dto, ActionLayoutDataOwner, Serializable, F
}
- interface Visitor {
+
+ interface Visitor extends Grid.Visitor {
void visit(final FCGrid 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);
- void visit(final ActionLayoutData actionLayoutData);
}
- public static class VisitorAdapter implements Visitor {
+ public static class VisitorAdapter extends Grid.VisitorAdapter implements Visitor {
@Override
public void visit(final FCGrid fcPage) { }
@Override
@@ -135,8 +129,6 @@ public class FCGrid implements Grid, Dto, ActionLayoutDataOwner, Serializable, F
@Override
public void visit(final FCColumn fcColumn) { }
@Override
- public void visit(final FieldSet fieldSet) {}
- @Override
public void visit(final PropertyLayoutData propertyLayoutData) {}
@Override
public void visit(final CollectionLayoutData collectionLayoutData) {}
@@ -149,18 +141,19 @@ public class FCGrid implements Grid, Dto, ActionLayoutDataOwner, Serializable, F
* Visits all elements of the graph. The {@link Visitor} implementation
* can assume that all "owner" references are populated.
*/
- public void visit(final FCGrid.Visitor visitor) {
- visitor.visit(this);
+ public void visit(final Grid.Visitor visitor) {
+ FCGrid.Visitor fcVisitor = asFcVisitor(visitor);
+ fcVisitor.visit(this);
traverseActions(this, visitor);
traverseColumn(getLeft(), this, visitor);
final List<FCTabGroup> tabGroups = getTabGroups();
for (final FCTabGroup fcTabGroup : tabGroups) {
fcTabGroup.setOwner(this);
- visitor.visit(fcTabGroup);
+ fcVisitor.visit(fcTabGroup);
final List<FCTab> tabs = fcTabGroup.getTabs();
for (final FCTab fcTab : tabs) {
fcTab.setOwner(fcTabGroup);
- visitor.visit(fcTab);
+ fcVisitor.visit(fcTab);
traverseColumn(fcTab.getLeft(), fcTab, visitor);
traverseColumn(fcTab.getMiddle(), fcTab, visitor);
traverseColumn(fcTab.getRight(), fcTab, visitor);
@@ -170,135 +163,41 @@ public class FCGrid implements Grid, Dto, ActionLayoutDataOwner, Serializable, F
}
private void traverseColumn(
- final FCColumn fcColumn, final FCColumnOwner fcColumnOwner, final Visitor visitor) {
+ final FCColumn fcColumn,
+ final FCColumnOwner fcColumnOwner,
+ final Grid.Visitor visitor) {
if(fcColumn == null) {
return;
}
+ FCGrid.Visitor fcVisitor = asFcVisitor(visitor);
fcColumn.setOwner(fcColumnOwner);
- visitor.visit(fcColumn);
+ fcVisitor.visit(fcColumn);
traverseFieldSets(fcColumn, visitor);
traverseCollections(fcColumn, visitor);
}
- 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();
- for (final PropertyLayoutData propertyLayoutData : properties) {
- propertyLayoutData.setOwner(fieldSet);
- visitor.visit(propertyLayoutData);
- traverseActions(propertyLayoutData, visitor);
+ private static Visitor asFcVisitor(final Grid.Visitor visitor) {
+ return visitor instanceof Visitor? (Visitor) visitor : new VisitorAdapter() {
+ @Override public void visit(final DomainObjectLayoutData domainObjectLayoutData) {
+ visitor.visit(domainObjectLayoutData);
}
- }
- }
- 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 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);
- }
- }
-
-
- @Programmatic
- @XmlTransient
- public LinkedHashMap<String, PropertyLayoutData> getAllPropertiesById() {
- final LinkedHashMap<String, PropertyLayoutData> propertiesById = Maps.newLinkedHashMap();
- visit(new FCGrid.VisitorAdapter() {
- public void visit(final PropertyLayoutData propertyLayoutData) {
- propertiesById.put(propertyLayoutData.getId(), propertyLayoutData);
+ @Override public void visit(final ActionLayoutData actionLayoutData) {
+ visitor.visit(actionLayoutData);
}
- });
- return propertiesById;
- }
-
- @Programmatic
- @XmlTransient
- public LinkedHashMap<String, CollectionLayoutData> getAllCollectionsById() {
- final LinkedHashMap<String, CollectionLayoutData> collectionsById = Maps.newLinkedHashMap();
-
- visit(new FCGrid.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 FCGrid.VisitorAdapter() {
- @Override
- public void visit(final ActionLayoutData actionLayoutData) {
- actionsById.put(actionLayoutData.getId(), actionLayoutData);
+ @Override public void visit(final PropertyLayoutData propertyLayoutData) {
+ visitor.visit(propertyLayoutData);
}
- });
- return actionsById;
- }
-
- @Programmatic
- @XmlTransient
- public LinkedHashMap<String, FieldSet> getAllFieldSetsByName() {
- final LinkedHashMap<String, FieldSet> fieldSetsByName = Maps.newLinkedHashMap();
-
- visit(new FCGrid.VisitorAdapter() {
- @Override
- public void visit(final FieldSet fieldSet) {
- fieldSetsByName.put(fieldSet.getName(), fieldSet);
+ @Override public void visit(final CollectionLayoutData collectionLayoutData) {
+ visitor.visit(collectionLayoutData);
}
- });
- return fieldSetsByName;
- }
-
- @Programmatic
- @XmlTransient
- public LinkedHashMap<String, FCTab> getAllTabsByName() {
- final LinkedHashMap<String, FCTab> tabsByName = Maps.newLinkedHashMap();
-
- visit(new FCGrid.VisitorAdapter() {
- @Override
- public void visit(final FCTab fcTab) {
- tabsByName.put(fcTab.getName(), fcTab);
+ @Override public void visit(final FieldSet fieldSet) {
+ visitor.visit(fieldSet);
}
- });
- return tabsByName;
- }
-
-
-
- private boolean normalized;
-
- @Programmatic
- @XmlTransient
- public boolean isNormalized() {
- return normalized;
- }
-
- @Programmatic
- public void setNormalized(final boolean normalized) {
- this.normalized = normalized;
+ };
}
http://git-wip-us.apache.org/repos/asf/isis/blob/fe46a781/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridNormalizerService.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridNormalizerService.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridNormalizerService.java
index d2436db..844168b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridNormalizerService.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridNormalizerService.java
@@ -19,7 +19,7 @@ package org.apache.isis.core.metamodel.services.grid;
import org.apache.isis.applib.annotation.Programmatic;
import org.apache.isis.applib.layout.common.Grid;
-public interface GridNormalizerService {
+public interface GridNormalizerService<G extends Grid> {
@Programmatic
Class<? extends Grid> gridImplementation();
@@ -31,6 +31,8 @@ public interface GridNormalizerService {
String schemaLocation();
@Programmatic
- void normalize(Grid grid, Class<?> domainClass);
+ void normalize(G grid, Class<?> domainClass);
+
+
}
http://git-wip-us.apache.org/repos/asf/isis/blob/fe46a781/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridNormalizerServiceAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridNormalizerServiceAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridNormalizerServiceAbstract.java
new file mode 100644
index 0000000..1c0ab06
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridNormalizerServiceAbstract.java
@@ -0,0 +1,335 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.isis.core.metamodel.services.grid;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Inject;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+import org.apache.isis.applib.annotation.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.FieldSet;
+import org.apache.isis.applib.layout.common.Grid;
+import org.apache.isis.applib.layout.common.MemberRegionOwner;
+import org.apache.isis.applib.layout.common.PropertyLayoutData;
+import org.apache.isis.applib.layout.fixedcols.FCColumn;
+import org.apache.isis.applib.layout.fixedcols.FCColumnOwner;
+import org.apache.isis.applib.layout.fixedcols.FCGrid;
+import org.apache.isis.applib.layout.fixedcols.FCTab;
+import org.apache.isis.applib.services.i18n.TranslationService;
+import org.apache.isis.core.metamodel.facetapi.FacetUtil;
+import org.apache.isis.core.metamodel.facets.actions.layout.ActionPositionFacetForActionXml;
+import org.apache.isis.core.metamodel.facets.actions.layout.BookmarkPolicyFacetForActionXml;
+import org.apache.isis.core.metamodel.facets.actions.layout.CssClassFaFacetForActionXml;
+import org.apache.isis.core.metamodel.facets.actions.layout.CssClassFacetForActionXml;
+import org.apache.isis.core.metamodel.facets.actions.layout.DescribedAsFacetForActionXml;
+import org.apache.isis.core.metamodel.facets.actions.layout.HiddenFacetForActionLayoutXml;
+import org.apache.isis.core.metamodel.facets.actions.layout.NamedFacetForActionXml;
+import org.apache.isis.core.metamodel.facets.collections.layout.CssClassFacetForCollectionXml;
+import org.apache.isis.core.metamodel.facets.collections.layout.DefaultViewFacetForCollectionXml;
+import org.apache.isis.core.metamodel.facets.collections.layout.DescribedAsFacetForCollectionXml;
+import org.apache.isis.core.metamodel.facets.collections.layout.HiddenFacetForCollectionXml;
+import org.apache.isis.core.metamodel.facets.collections.layout.NamedFacetForCollectionXml;
+import org.apache.isis.core.metamodel.facets.collections.layout.PagedFacetForCollectionXml;
+import org.apache.isis.core.metamodel.facets.collections.layout.SortedByFacetForCollectionXml;
+import org.apache.isis.core.metamodel.facets.members.order.annotprop.MemberOrderFacetXml;
+import org.apache.isis.core.metamodel.facets.properties.propertylayout.CssClassFacetForPropertyXml;
+import org.apache.isis.core.metamodel.facets.properties.propertylayout.DescribedAsFacetForPropertyXml;
+import org.apache.isis.core.metamodel.facets.properties.propertylayout.HiddenFacetForPropertyXml;
+import org.apache.isis.core.metamodel.facets.properties.propertylayout.LabelAtFacetForPropertyXml;
+import org.apache.isis.core.metamodel.facets.properties.propertylayout.MultiLineFacetForPropertyXml;
+import org.apache.isis.core.metamodel.facets.properties.propertylayout.NamedFacetForPropertyXml;
+import org.apache.isis.core.metamodel.facets.properties.propertylayout.RenderedAdjustedFacetForPropertyXml;
+import org.apache.isis.core.metamodel.facets.properties.propertylayout.TypicalLengthFacetForPropertyXml;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.SpecificationLoader;
+import org.apache.isis.core.metamodel.spec.feature.Contributed;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
+import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+
+public abstract class GridNormalizerServiceAbstract<G extends Grid> implements GridNormalizerService<G> {
+
+ private final Class<G> gridImplementation;
+ private final String tns;
+ private final String schemaLocation;
+
+ public GridNormalizerServiceAbstract(
+ final Class<G> gridImplementation,
+ final String tns,
+ final String schemaLocation) {
+ this.gridImplementation = gridImplementation;
+ this.tns = tns;
+ this.schemaLocation = schemaLocation;
+ }
+
+ @Programmatic
+ @Override
+ public Class<G> gridImplementation() {
+ return gridImplementation;
+ }
+
+ @Programmatic
+ @Override
+ public String tns() {
+ return tns;
+ }
+
+ @Programmatic
+ @Override
+ public String schemaLocation() {
+ return schemaLocation;
+ }
+
+ @Programmatic
+ @Override
+ public void normalize(final G grid, final Class<?> domainClass) {
+
+ final ObjectSpecification objectSpec = specificationLookup.loadSpecification(domainClass);
+
+ final Map<String, OneToOneAssociation> oneToOneAssociationById =
+ ObjectMember.Util.mapById(getOneToOneAssociations(objectSpec));
+ final Map<String, OneToManyAssociation> oneToManyAssociationById =
+ ObjectMember.Util.mapById(getOneToManyAssociations(objectSpec));
+ final Map<String, ObjectAction> objectActionById =
+ ObjectMember.Util.mapById(objectSpec.getObjectActions(Contributed.INCLUDED));
+
+ final boolean validation = validateAndDerive(grid, oneToOneAssociationById, oneToManyAssociationById, objectActionById);
+ if(validation) {
+ overwrite(grid, oneToOneAssociationById, oneToManyAssociationById, objectActionById);
+ }
+ }
+
+ /**
+ * Ensures that all object members (properties, collections and actions) are in the metadata.
+ */
+ protected abstract boolean validateAndDerive(
+ final Grid grid,
+ final Map<String, OneToOneAssociation> oneToOneAssociationById,
+ final Map<String, OneToManyAssociation> oneToManyAssociationById,
+ final Map<String, ObjectAction> objectActionById);
+
+
+
+
+ protected void overwrite(
+ final G fcGrid,
+ final Map<String, OneToOneAssociation> oneToOneAssociationById,
+ final Map<String, OneToManyAssociation> oneToManyAssociationById,
+ final Map<String, ObjectAction> objectActionById) {
+
+ final Map<String, int[]> propertySequenceByGroup = Maps.newHashMap();
+
+ fcGrid.visit(new FCGrid.VisitorAdapter() {
+ private int collectionSequence = 1;
+ private int actionDomainObjectSequence = 1;
+ private int actionPropertyGroupSequence = 1;
+ private int actionPropertySequence = 1;
+ private int actionCollectionSequence = 1;
+
+ @Override
+ public void visit(final ActionLayoutData actionLayoutData) {
+ final ActionLayoutDataOwner actionLayoutDataOwner = actionLayoutData.getOwner();
+ final ObjectAction objectAction = objectActionById.get(actionLayoutData.getId());
+ if(objectAction == null) {
+ return;
+ }
+
+ final String memberOrderName;
+ final int memberOrderSequence;
+ 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(actionLayoutDataOwner instanceof PropertyLayoutData) {
+ final PropertyLayoutData propertyLayoutData = (PropertyLayoutData) actionLayoutDataOwner;
+ memberOrderName = propertyLayoutData.getId();
+ memberOrderSequence = actionPropertySequence++;
+ } else if(actionLayoutDataOwner instanceof CollectionLayoutData) {
+ final CollectionLayoutData collectionLayoutData = (CollectionLayoutData) actionLayoutDataOwner;
+ memberOrderName = collectionLayoutData.getId();
+ memberOrderSequence = actionCollectionSequence++;
+ } else {
+ // DomainObject
+ memberOrderName = null;
+ memberOrderSequence = actionDomainObjectSequence++;
+ }
+ FacetUtil.addFacet(
+ new MemberOrderFacetXml(memberOrderName, ""+memberOrderSequence, translationService, objectAction));
+
+
+ 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(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) {
+ actionLayoutData.setPosition(org.apache.isis.applib.annotation.ActionLayout.Position.BELOW);
+ }
+ } else {
+ // doesn't do anything for DomainObject or Collection
+ actionLayoutData.setPosition(null);
+ }
+
+ FacetUtil.addFacet(ActionPositionFacetForActionXml.create(actionLayoutData, objectAction));
+ FacetUtil.addFacet(BookmarkPolicyFacetForActionXml.create(actionLayoutData, objectAction));
+ FacetUtil.addFacet(CssClassFacetForActionXml.create(actionLayoutData, objectAction));
+ FacetUtil.addFacet(CssClassFaFacetForActionXml.create(actionLayoutData, objectAction));
+ FacetUtil.addFacet(DescribedAsFacetForActionXml.create(actionLayoutData, objectAction));
+ FacetUtil.addFacet(HiddenFacetForActionLayoutXml.create(actionLayoutData, objectAction));
+ FacetUtil.addFacet(NamedFacetForActionXml.create(actionLayoutData, objectAction));
+ }
+
+ @Override
+ public void visit(final PropertyLayoutData propertyLayoutData) {
+ final OneToOneAssociation oneToOneAssociation = oneToOneAssociationById.get(propertyLayoutData.getId());
+ if(oneToOneAssociation == null) {
+ return;
+ }
+
+ FacetUtil.addFacet(CssClassFacetForPropertyXml.create(propertyLayoutData, oneToOneAssociation));
+ FacetUtil.addFacet(DescribedAsFacetForPropertyXml.create(propertyLayoutData, oneToOneAssociation));
+ FacetUtil.addFacet(HiddenFacetForPropertyXml.create(propertyLayoutData, oneToOneAssociation));
+ FacetUtil.addFacet(LabelAtFacetForPropertyXml.create(propertyLayoutData, oneToOneAssociation));
+ FacetUtil.addFacet(MultiLineFacetForPropertyXml.create(propertyLayoutData, oneToOneAssociation));
+ FacetUtil.addFacet(NamedFacetForPropertyXml.create(propertyLayoutData, oneToOneAssociation));
+ FacetUtil.addFacet(
+ RenderedAdjustedFacetForPropertyXml.create(propertyLayoutData, oneToOneAssociation));
+ FacetUtil.addFacet(TypicalLengthFacetForPropertyXml.create(propertyLayoutData, oneToOneAssociation));
+
+ // @MemberOrder#name based on owning property group, @MemberOrder#sequence monotonically increasing
+ final FieldSet fieldSet = propertyLayoutData.getOwner();
+ final String groupName = fieldSet.getName();
+ final String sequence = nextInSequenceFor(groupName, propertySequenceByGroup);
+ FacetUtil.addFacet(
+ new MemberOrderFacetXml(groupName, sequence, translationService, oneToOneAssociation));
+ }
+
+ @Override
+ public void visit(final CollectionLayoutData collectionLayoutData) {
+ final OneToManyAssociation oneToManyAssociation = oneToManyAssociationById.get(collectionLayoutData.getId());
+ if(oneToManyAssociation == null) {
+ return;
+ }
+
+ FacetUtil.addFacet(CssClassFacetForCollectionXml.create(collectionLayoutData, oneToManyAssociation));
+ FacetUtil.addFacet(
+ DefaultViewFacetForCollectionXml.create(collectionLayoutData, oneToManyAssociation));
+ FacetUtil.addFacet(
+ DescribedAsFacetForCollectionXml.create(collectionLayoutData, oneToManyAssociation));
+ FacetUtil.addFacet(HiddenFacetForCollectionXml.create(collectionLayoutData, oneToManyAssociation));
+ FacetUtil.addFacet(NamedFacetForCollectionXml.create(collectionLayoutData, oneToManyAssociation));
+ FacetUtil.addFacet(PagedFacetForCollectionXml.create(collectionLayoutData, oneToManyAssociation));
+ FacetUtil.addFacet(SortedByFacetForCollectionXml.create(collectionLayoutData, oneToManyAssociation));
+
+ // @MemberOrder#name based on the collection's id (so that each has a single "member group")
+ final String groupName = collectionLayoutData.getId();
+ final String sequence = "" + collectionSequence++;
+ FacetUtil.addFacet(
+ new MemberOrderFacetXml(groupName, sequence, translationService, oneToManyAssociation));
+
+ // if there is only a single column and no other contents, then copy the collection Id onto the tab'
+ final MemberRegionOwner memberRegionOwner = collectionLayoutData.getOwner();
+ if(memberRegionOwner instanceof FCColumn) {
+ final FCColumn FCColumn = (FCColumn) memberRegionOwner;
+ final FCColumnOwner holder = FCColumn.getOwner();
+ if(holder instanceof FCTab) {
+ final FCTab FCTab = (FCTab) holder;
+ if(FCTab.getContents().size() == 1 && Strings.isNullOrEmpty(FCTab.getName()) ) {
+ final String collectionName = oneToManyAssociation.getName();
+ FCTab.setName(collectionName);
+ }
+ }
+ }
+ }
+ });
+ }
+
+
+ protected static List<OneToOneAssociation> getOneToOneAssociations(final ObjectSpecification objectSpec) {
+ List associations = objectSpec.getAssociations(Contributed.INCLUDED, ObjectAssociation.Filters.PROPERTIES);
+ return associations;
+ }
+ protected static List<OneToManyAssociation> getOneToManyAssociations(final ObjectSpecification objectSpec) {
+ List associations = objectSpec.getAssociations(Contributed.INCLUDED, ObjectAssociation.Filters.COLLECTIONS);
+ return associations;
+ }
+
+
+
+ protected static class Tuple<T> {
+ public final T first;
+ public final T second;
+ private Tuple(final T first, final T second) {
+ this.first = first;
+ this.second = second;
+ }
+ public static <T> Tuple<T> of(final T first, final T second) {
+ return new Tuple<>(first, second);
+ }
+ }
+
+
+ /**
+ * Returns a 2-element tuple of [first-second, second-first]
+ */
+ protected static <T> Tuple<List<T>> surplusAndMissing(final Collection<T> first, final Collection<T> second){
+ final List<T> firstNotSecond = Lists.newArrayList(first);
+ firstNotSecond.removeAll(second);
+ final List<T> secondNotFirst = Lists.newArrayList(second);
+ secondNotFirst.removeAll(first);
+ return Tuple.of(firstNotSecond, secondNotFirst);
+ }
+
+
+ protected static String nextInSequenceFor(
+ final String key, final Map<String, int[]> seqByKey) {
+ synchronized (seqByKey) {
+ int[] holder = seqByKey.get(key);
+ if(holder == null) {
+ holder = new int[]{0};
+ seqByKey.put(key, holder);
+ }
+ holder[0]++;
+ return ""+holder[0];
+ }
+ }
+
+
+ @Inject
+ SpecificationLoader specificationLookup;
+ @Inject
+ TranslationService translationService;
+
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/fe46a781/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridNormalizerUtil.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridNormalizerUtil.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridNormalizerUtil.java
new file mode 100644
index 0000000..7f09ee9
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridNormalizerUtil.java
@@ -0,0 +1,38 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.isis.core.metamodel.services.grid;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import com.google.common.collect.Lists;
+
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.Contributed;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+
+public class GridNormalizerUtil {
+
+ private GridNormalizerUtil(){}
+
+
+
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/fe46a781/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridNormalizerServiceBS3.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridNormalizerServiceBS3.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridNormalizerServiceBS3.java
index 0b69210..a4f845a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridNormalizerServiceBS3.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridNormalizerServiceBS3.java
@@ -16,56 +16,230 @@
*/
package org.apache.isis.core.metamodel.services.grid.bootstrap3;
-import javax.inject.Inject;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
import org.apache.isis.applib.annotation.DomainService;
import org.apache.isis.applib.annotation.NatureOfService;
-import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.layout.bootstrap3.BS3Col;
import org.apache.isis.applib.layout.bootstrap3.BS3Grid;
+import org.apache.isis.applib.layout.bootstrap3.BS3Row;
+import org.apache.isis.applib.layout.bootstrap3.BS3Tab;
+import org.apache.isis.applib.layout.bootstrap3.BS3TabGroup;
+import org.apache.isis.applib.layout.common.ActionLayoutData;
+import org.apache.isis.applib.layout.common.CollectionLayoutData;
+import org.apache.isis.applib.layout.common.FieldSet;
import org.apache.isis.applib.layout.common.Grid;
-import org.apache.isis.applib.services.i18n.TranslationService;
-import org.apache.isis.core.metamodel.services.grid.GridNormalizerService;
-import org.apache.isis.core.metamodel.spec.SpecificationLoader;
+import org.apache.isis.applib.layout.common.PropertyLayoutData;
+import org.apache.isis.applib.layout.fixedcols.FCColumn;
+import org.apache.isis.core.metamodel.facets.object.membergroups.MemberGroupLayoutFacet;
+import org.apache.isis.core.metamodel.services.grid.GridNormalizerServiceAbstract;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
@DomainService(
nature = NatureOfService.DOMAIN
)
-public class GridNormalizerServiceBS3 implements GridNormalizerService {
+public class GridNormalizerServiceBS3 extends GridNormalizerServiceAbstract<BS3Grid> {
public static final String TNS = "http://isis.apache.org/schema/applib/layout/bootstrap3";
public static final String SCHEMA_LOCATION = "http://isis.apache.org/schema/applib/layout/bootstrap3/bootstrap3.xsd";
+ public GridNormalizerServiceBS3() {
+ super(BS3Grid.class, TNS, SCHEMA_LOCATION);
+ }
- @Programmatic
@Override
- public Class<? extends Grid> gridImplementation() {
- return BS3Grid.class;
- }
+ protected boolean validateAndDerive(
+ final Grid grid,
+ final Map<String, OneToOneAssociation> oneToOneAssociationById,
+ final Map<String, OneToManyAssociation> oneToManyAssociationById,
+ final Map<String, ObjectAction> objectActionById) {
- @Programmatic
- @Override
- public String tns() {
- return TNS;
- }
+ final BS3Grid bs3Grid = (BS3Grid) grid;
- @Programmatic
- @Override
- public String schemaLocation() {
- return SCHEMA_LOCATION;
- }
+ final LinkedHashMap<String, PropertyLayoutData> propertyIds = bs3Grid.getAllPropertiesById();
+ final LinkedHashMap<String, CollectionLayoutData> collectionIds = bs3Grid.getAllCollectionsById();
+ final LinkedHashMap<String, ActionLayoutData> actionIds = bs3Grid.getAllActionsById();
- @Override
- public void normalize(final Grid grid, final Class<?> domainClass) {
- BS3Grid bs3Grid = (BS3Grid) grid;
- // TODO
- }
+ // find all row and col ids
+ // ensure that all Ids are different
+
+ final LinkedHashMap<String, BS3Row> rowIds = Maps.newLinkedHashMap();
+ final LinkedHashMap<String, BS3Col> colIds = Maps.newLinkedHashMap();
+
+ final AtomicReference<Boolean> duplicateIdDetected = new AtomicReference<>(false);
+
+ bs3Grid.visit(new BS3Grid.VisitorAdapter(){
+ @Override
+ public void visit(final BS3Row bs3Row) {
+ final String id = bs3Row.getId();
+ if(id == null) {
+ return;
+ }
+ if(rowIds.containsKey(id) || colIds.containsKey(id)) {
+ bs3Row.setMetadataError("There is another col with this id");
+ duplicateIdDetected.set(true);
+ return;
+ }
+ rowIds.put(id, bs3Row);
+ }
+
+ @Override
+ public void visit(final BS3Col bs3Col) {
+ final String id = bs3Col.getId();
+ if(id == null) {
+ return;
+ }
+ if(rowIds.containsKey(id) || colIds.containsKey(id)) {
+ bs3Col.setMetadataError("There is another col with this id");
+ duplicateIdDetected.set(true);
+ return;
+ }
+ colIds.put(id, bs3Col);
+ }
+ });
+
+ if(duplicateIdDetected.get()) {
+ return false;
+ }
+
+ // ensure that there is exactly one col with the
+ // unreferencedActions, unreferencedProperties and unreferencedCollections attribute set.
- @Inject
- SpecificationLoader specificationLookup;
- @Inject
- TranslationService translationService;
+ final AtomicReference<BS3Col> colForUnreferencedActionsRef = new AtomicReference<>();
+ final AtomicReference<BS3Col> colForUnreferencedPropertiesRef = new AtomicReference<>();
+ final AtomicReference<FieldSet> fieldSetForUnreferencedPropsRef = new AtomicReference<>();
+ final AtomicReference<BS3Col> colForUnreferencedCollectionsRef = new AtomicReference<>();
+
+ bs3Grid.visit(new BS3Grid.VisitorAdapter(){
+ @Override
+ public void visit(final BS3Col bs3Col) {
+ if(bs3Col.isUnreferencedActions()) {
+ if(colForUnreferencedActionsRef.get() != null) {
+ bs3Col.setMetadataError("More than one col with 'unreferencedActions' attribute set");
+ } else {
+ colForUnreferencedActionsRef.set(bs3Col);
+ }
+ }
+ if(bs3Col.isUnreferencedProperties()) {
+ if(colForUnreferencedPropertiesRef.get() != null) {
+ bs3Col.setMetadataError("More than one col with 'unreferencedProperties' attribute set");
+ } else {
+ final List<FieldSet> fieldSets = bs3Col.getFieldSets();
+ for (FieldSet fieldSet : fieldSets) {
+ if(fieldSet.getName().equals(MemberGroupLayoutFacet.DEFAULT_GROUP)) {
+ fieldSetForUnreferencedPropsRef.set(fieldSet);
+ }
+ }
+ colForUnreferencedPropertiesRef.set(bs3Col);
+ }
+ }
+ if(bs3Col.isUnreferencedCollections()) {
+ if(colForUnreferencedCollectionsRef.get() != null) {
+ bs3Col.setMetadataError("More than one col with 'unreferencedCollections' attribute set");
+ } else {
+ colForUnreferencedCollectionsRef.set(bs3Col);
+ }
+ }
+ }
+ });
+
+ if( colForUnreferencedActionsRef.get() == null ||
+ colForUnreferencedPropertiesRef.get() == null ||
+ colForUnreferencedCollectionsRef.get() == null) {
+ return false;
+ }
+
+
+ // add missing properties will be added to the first fieldset of the specified column
+ final Tuple<List<String>> propertyIdTuple =
+ surplusAndMissing(propertyIds.keySet(), oneToOneAssociationById.keySet());
+ final List<String> surplusPropertyIds = propertyIdTuple.first;
+ final List<String> missingPropertyIds = propertyIdTuple.second;
+
+ for (String surplusPropertyId : surplusPropertyIds) {
+ propertyIds.get(surplusPropertyId).setMetadataError("No such property");
+ }
+
+ if(!missingPropertyIds.isEmpty()) {
+ final BS3Col bs3Col = colForUnreferencedPropertiesRef.get();
+ if(bs3Col != null) {
+ // ensure that there is a field set to use, else create
+ boolean wasSet = fieldSetForUnreferencedPropsRef.compareAndSet(null, new FieldSet(MemberGroupLayoutFacet.DEFAULT_GROUP));
+ final FieldSet fieldSetForUnref = fieldSetForUnreferencedPropsRef.get();
+ if(wasSet) {
+ fieldSetForUnref.setOwner(bs3Col);
+ bs3Col.getFieldSets().add(fieldSetForUnref);
+ }
+ for (final String propertyId : missingPropertyIds) {
+ bs3Col.getFieldSets().get(0).getProperties().add(new PropertyLayoutData(propertyId));
+ }
+ }
+ }
+
+ // any missing collections will be added as tabs to a new TabGroup in the specified column
+ final Tuple<List<String>> collectionIdTuple =
+ surplusAndMissing(collectionIds.keySet(), oneToManyAssociationById.keySet());
+ final List<String> surplusCollectionIds = collectionIdTuple.first;
+ final List<String> missingCollectionIds = collectionIdTuple.second;
+
+ for (String surplusCollectionId : surplusCollectionIds) {
+ collectionIds.get(surplusCollectionId).setMetadataError("No such collection");
+ }
+
+ if(!missingCollectionIds.isEmpty()) {
+ final BS3Col bs3Col = colForUnreferencedCollectionsRef.get();
+ if(bs3Col != null) {
+ final BS3TabGroup tabGroup = new BS3TabGroup();
+ tabGroup.setOwner(bs3Col);
+ bs3Col.getTabGroups().add(tabGroup);
+ for (final String collectionId : missingCollectionIds) {
+ final BS3Tab bs3Tab = new BS3Tab();
+ tabGroup.getTabs().add(bs3Tab);
+ FCColumn left = new FCColumn(12);
+ bs3Tab.setOwner(tabGroup);
+ final CollectionLayoutData layoutMetadata = new CollectionLayoutData(collectionId);
+ layoutMetadata.setDefaultView("table");
+ left.getCollections().add(layoutMetadata);
+ }
+ }
+ }
+
+ // any missing actions will be added as actions in the specified column
+ final Tuple<List<String>> actionIdTuple =
+ surplusAndMissing(actionIds.keySet(), objectActionById.keySet());
+ final List<String> surplusActionIds = actionIdTuple.first;
+ final List<String> missingActionIds = actionIdTuple.second;
+
+ for (String surplusActionId : surplusActionIds) {
+ actionIds.get(surplusActionId).setMetadataError("No such action");
+ }
+
+ if(!missingActionIds.isEmpty()) {
+ final BS3Col bs3Col = colForUnreferencedActionsRef.get();
+ if(bs3Col != null) {
+ for (String actionId : missingActionIds) {
+ List<ActionLayoutData> actions = bs3Col.getActions();
+ if(actions == null) {
+ actions = Lists.newArrayList();
+ bs3Col.setActions(actions);
+ }
+ actions.add(new ActionLayoutData(actionId));
+ }
+ }
+ }
+
+ return true;
+ }
}