You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by rm...@apache.org on 2013/03/24 18:45:18 UTC
[21/24] Restructuring Scimpi to remove dependencies and enable easier
testing.
http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/Collection.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/Collection.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/Collection.java
index 20e0cc9..e139836 100644
--- a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/Collection.java
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/Collection.java
@@ -27,22 +27,23 @@ import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
import org.apache.isis.core.runtime.system.context.IsisContext;
import org.apache.isis.viewer.scimpi.ScimpiException;
import org.apache.isis.viewer.scimpi.dispatcher.context.Request;
+import org.apache.isis.viewer.scimpi.dispatcher.context.RequestState;
import org.apache.isis.viewer.scimpi.dispatcher.context.Request.Scope;
-import org.apache.isis.viewer.scimpi.dispatcher.processor.TagProcessor;
-import org.apache.isis.viewer.scimpi.dispatcher.processor.TagProcessor.RepeatMarker;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.TemplateProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.TemplateProcessor.RepeatMarker;
import org.apache.isis.viewer.scimpi.dispatcher.view.AbstractElementProcessor;
public class Collection extends AbstractElementProcessor {
@Override
- public void process(final TagProcessor tagProcessor) {
- final Request context = tagProcessor.getContext();
+ public void process(final TemplateProcessor templateProcessor, RequestState state) {
+ final Request context = templateProcessor.getContext();
ObjectAdapter collection;
- final String field = tagProcessor.getOptionalProperty(FIELD);
+ final String field = templateProcessor.getOptionalProperty(FIELD);
if (field != null) {
- final String id = tagProcessor.getOptionalProperty(OBJECT);
+ final String id = templateProcessor.getOptionalProperty(OBJECT);
final ObjectAdapter object = context.getMappedObjectOrResult(id);
final ObjectAssociation objectField = object.getSpecification().getAssociation(field);
if (!objectField.isOneToManyAssociation()) {
@@ -51,16 +52,16 @@ public class Collection extends AbstractElementProcessor {
IsisContext.getPersistenceSession().resolveField(object, objectField);
collection = objectField.get(object);
} else {
- final String id = tagProcessor.getOptionalProperty(COLLECTION);
+ final String id = templateProcessor.getOptionalProperty(COLLECTION);
collection = context.getMappedObjectOrResult(id);
}
- final RepeatMarker marker = tagProcessor.createMarker();
+ final RepeatMarker marker = templateProcessor.createMarker();
- final String variable = tagProcessor.getOptionalProperty(ELEMENT_NAME);
- final String scopeName = tagProcessor.getOptionalProperty(SCOPE);
+ final String variable = templateProcessor.getOptionalProperty(ELEMENT_NAME);
+ final String scopeName = templateProcessor.getOptionalProperty(SCOPE);
final Scope scope = Request.scope(scopeName, Scope.REQUEST);
- final String rowClassesList = tagProcessor.getOptionalProperty(ROW_CLASSES, ODD_ROW_CLASS + "|" + EVEN_ROW_CLASS);
+ final String rowClassesList = templateProcessor.getOptionalProperty(ROW_CLASSES, ODD_ROW_CLASS + "|" + EVEN_ROW_CLASS);
String[] rowClasses = new String[0];
if (rowClassesList != null) {
rowClasses = rowClassesList.split("[,|/]");
@@ -68,7 +69,7 @@ public class Collection extends AbstractElementProcessor {
final CollectionFacet facet = collection.getSpecification().getFacet(CollectionFacet.class);
if (facet.size(collection) == 0) {
- tagProcessor.skipUntilClose();
+ templateProcessor.skipUntilClose();
} else {
final Iterator<ObjectAdapter> iterator = facet.iterator(collection);
int row = 0;
@@ -80,7 +81,7 @@ public class Collection extends AbstractElementProcessor {
}
context.addVariable(variable, context.mapObject(element, scope), scope);
marker.repeat();
- tagProcessor.processUtilCloseTag();
+ templateProcessor.processUtilCloseTag();
row++;
}
}
http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/CountElements.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/CountElements.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/CountElements.java
new file mode 100644
index 0000000..086977d
--- /dev/null
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/CountElements.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.isis.viewer.scimpi.dispatcher.view.collection;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.TemplateProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.view.AbstractObjectProcessor;
+
+public class CountElements extends AbstractObjectProcessor {
+
+ @Override
+ protected void process(final TemplateProcessor templateProcessor, final ObjectAdapter collection) {
+ final CollectionFacet facet = collection.getSpecification().getFacet(CollectionFacet.class);
+ final int size = facet.size(collection);
+ if (size == 0) {
+ templateProcessor.appendHtml(templateProcessor.getOptionalProperty("none", "0"));
+ } else if (size == 1) {
+ templateProcessor.appendHtml(templateProcessor.getOptionalProperty("one", "1"));
+ } else {
+ final String text = templateProcessor.getOptionalProperty("many", "" + size);
+ templateProcessor.appendHtml(String.format(text, size));
+ }
+ }
+
+ @Override
+ protected String checkFieldType(final ObjectAssociation objectField) {
+ return objectField.isOneToManyAssociation() ? null : "must be a collection";
+ }
+
+ @Override
+ public String getName() {
+ return "count";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/ElementType.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/ElementType.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/ElementType.java
new file mode 100644
index 0000000..8038658
--- /dev/null
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/ElementType.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.isis.viewer.scimpi.dispatcher.view.collection;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.viewer.scimpi.ScimpiException;
+import org.apache.isis.viewer.scimpi.dispatcher.context.Request;
+import org.apache.isis.viewer.scimpi.dispatcher.context.RequestState;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.TemplateProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.view.AbstractElementProcessor;
+
+public class ElementType extends AbstractElementProcessor {
+
+ @Override
+ public void process(final TemplateProcessor templateProcessor, RequestState state) {
+ ObjectAdapter collection;
+ final String field = templateProcessor.getOptionalProperty(FIELD);
+ final Request context = templateProcessor.getContext();
+ if (field != null) {
+ final String id = templateProcessor.getRequiredProperty(OBJECT);
+ final ObjectAdapter object = context.getMappedObjectOrResult(id);
+ final ObjectAssociation objectField = object.getSpecification().getAssociation(field);
+ if (!objectField.isOneToManyAssociation()) {
+ throw new ScimpiException("Field " + objectField.getId() + " is not a collection");
+ }
+ collection = objectField.get(object);
+ } else {
+ final String id = templateProcessor.getOptionalProperty(COLLECTION);
+ collection = context.getMappedObjectOrResult(id);
+ }
+
+ final ObjectSpecification elementSpecification = collection.getElementSpecification();
+ final String name = elementSpecification.getSingularName();
+
+ templateProcessor.appendAsHtmlEncoded(name);
+ }
+
+ @Override
+ public String getName() {
+ return "element-type";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/ListView.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/ListView.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/ListView.java
new file mode 100644
index 0000000..1e4627b
--- /dev/null
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/ListView.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.isis.viewer.scimpi.dispatcher.view.collection;
+
+import java.util.Iterator;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.viewer.scimpi.Names;
+import org.apache.isis.viewer.scimpi.dispatcher.context.Request;
+import org.apache.isis.viewer.scimpi.dispatcher.context.Request.Scope;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.TemplateProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.view.AbstractObjectProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.view.determine.LinkedObject;
+
+public class ListView extends AbstractObjectProcessor {
+
+ @Override
+ public String checkFieldType(final ObjectAssociation objectField) {
+ return objectField.isOneToManyAssociation() ? null : "is not a collection";
+ }
+
+ @Override
+ public void process(final TemplateProcessor templateProcessor, final ObjectAdapter object) {
+ final String linkRowView = templateProcessor.getOptionalProperty(LINK_VIEW);
+ final String linkObjectName = templateProcessor.getOptionalProperty(ELEMENT_NAME, Names.RESULT);
+ final String linkObjectScope = templateProcessor.getOptionalProperty(SCOPE, Scope.INTERACTION.toString());
+ LinkedObject linkedRow = null;
+ if (linkRowView != null) {
+ linkedRow = new LinkedObject(linkObjectName, linkObjectScope, templateProcessor.getContext().fullUriPath(linkRowView));
+ }
+ final String bulletType = templateProcessor.getOptionalProperty("type");
+ write(templateProcessor, object, linkedRow, bulletType);
+ }
+
+ public static void write(final TemplateProcessor templateProcessor, final ObjectAdapter collection, final LinkedObject linkRow, final String bulletType) {
+
+ if (bulletType == null) {
+ templateProcessor.appendHtml("<ol>");
+ } else {
+ templateProcessor.appendHtml("<ul type=\"" + bulletType + "\">");
+ }
+
+ final CollectionFacet facet = collection.getSpecification().getFacet(CollectionFacet.class);
+ final Iterator<ObjectAdapter> iterator = facet.iterator(collection);
+ while (iterator.hasNext()) {
+ final ObjectAdapter element = iterator.next();
+
+ templateProcessor.appendHtml("<li>");
+ if (linkRow != null) {
+ final Scope scope = linkRow == null ? Scope.INTERACTION : Request.scope(linkRow.getScope());
+ final String rowId = templateProcessor.getContext().mapObject(element, scope);
+ templateProcessor.appendHtml("<a class=\"item-select\" href=\"" + linkRow.getForwardView() + "?" + linkRow.getVariable() + "=" + rowId + "\">");
+ }
+ templateProcessor.appendAsHtmlEncoded(element.titleString());
+ if (linkRow != null) {
+ templateProcessor.appendHtml("</a>");
+ }
+
+ templateProcessor.appendHtml("</li>\n");
+ }
+ if (bulletType == null) {
+ templateProcessor.appendHtml("</ol>");
+ } else {
+ templateProcessor.appendHtml("</ul>");
+ }
+
+ }
+
+ @Override
+ public String getName() {
+ return "list";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/RemoveElement.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/RemoveElement.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/RemoveElement.java
new file mode 100644
index 0000000..0d3830e
--- /dev/null
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/RemoveElement.java
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.isis.viewer.scimpi.dispatcher.view.collection;
+
+import java.util.List;
+
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.applib.filter.Filter;
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociationFilters;
+import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.scimpi.ForbiddenException;
+import org.apache.isis.viewer.scimpi.Names;
+import org.apache.isis.viewer.scimpi.ScimpiException;
+import org.apache.isis.viewer.scimpi.dispatcher.action.RemoveAction;
+import org.apache.isis.viewer.scimpi.dispatcher.context.Request;
+import org.apache.isis.viewer.scimpi.dispatcher.context.RequestState;
+import org.apache.isis.viewer.scimpi.dispatcher.context.Request.Scope;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.TemplateProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.util.MethodsUtils;
+import org.apache.isis.viewer.scimpi.dispatcher.view.AbstractElementProcessor;
+
+public class RemoveElement extends AbstractElementProcessor {
+
+ // REVIEW: should provide this rendering context, rather than hardcoding.
+ // the net effect currently is that class members annotated with
+ // @Hidden(where=Where.ANYWHERE) or @Disabled(where=Where.ANYWHERE) will indeed
+ // be hidden/disabled, but will be visible/enabled (perhaps incorrectly)
+ // for any other value for Where
+ private final static Where where = Where.ANYWHERE;
+
+ @Override
+ public void process(final TemplateProcessor templateProcessor, RequestState state) {
+ final String title = templateProcessor.getOptionalProperty(BUTTON_TITLE, "Remove From List");
+ final String cls = templateProcessor.getOptionalProperty(CLASS, "action in-line delete confirm");
+ final String object = templateProcessor.getOptionalProperty(OBJECT);
+ final String resultOverride = templateProcessor.getOptionalProperty(RESULT_OVERRIDE);
+ final Request context = templateProcessor.getContext();
+ final String objectId = object != null ? object : (String) context.getVariable(Names.RESULT);
+ final ObjectAdapter adapter = MethodsUtils.findObject(context, objectId);
+
+ final String element = templateProcessor.getOptionalProperty(ELEMENT, (String) context.getVariable(ELEMENT));
+ final ObjectAdapter elementId = MethodsUtils.findObject(context, element);
+
+ final String fieldName = templateProcessor.getRequiredProperty(FIELD);
+
+ String view = templateProcessor.getOptionalProperty(VIEW);
+ view = context.fullFilePath(view == null ? context.getResourceFile() : view);
+ String error = templateProcessor.getOptionalProperty(ERROR);
+ error = context.fullFilePath(error == null ? context.getResourceFile() : error);
+
+ templateProcessor.processUtilCloseTag();
+
+ write(templateProcessor, adapter, fieldName, elementId, resultOverride, view, error, title, cls);
+ }
+
+ @Override
+ public String getName() {
+ return "remove-element";
+ }
+
+ public static void write(final TemplateProcessor templateProcessor, final ObjectAdapter adapter, final String fieldName, final ObjectAdapter element, final String resultOverride, final String view, final String error, final String title, final String cssClass) {
+ final ObjectAssociation field = adapter.getSpecification().getAssociation(fieldName);
+ if (field == null) {
+ throw new ScimpiException("No field " + fieldName + " in " + adapter.getSpecification().getFullIdentifier());
+ }
+ if (!field.isOneToManyAssociation()) {
+ throw new ScimpiException("Field " + fieldName + " not a collection, in " + adapter.getSpecification().getFullIdentifier());
+ }
+ if (field.isVisible(IsisContext.getAuthenticationSession(), adapter, where).isVetoed()) {
+ throw new ForbiddenException(field, ForbiddenException.VISIBLE);
+ }
+ IsisContext.getPersistenceSession().resolveField(adapter, field);
+
+ Consent usable = field.isUsable(IsisContext.getAuthenticationSession(), adapter, where);
+ if (usable.isAllowed()) {
+ usable = ((OneToManyAssociation) field).isValidToRemove(adapter, element);
+ }
+
+ if (usable.isVetoed()) {
+ templateProcessor.appendHtml("<div class=\"" + cssClass + " disabled-form\">");
+ templateProcessor.appendHtml("<div class=\"button disabled\" title=\"");
+ templateProcessor.appendAsHtmlEncoded(usable.getReason());
+ templateProcessor.appendHtml("\" >" + title);
+ templateProcessor.appendHtml("</div>");
+ templateProcessor.appendHtml("</div>");
+ } else {
+ if (valid(templateProcessor, adapter)) {
+ final String classSegment = " class=\"" + cssClass + "\"";
+
+ final String objectId = templateProcessor.getContext().mapObject(adapter, Scope.INTERACTION);
+ final String elementId = templateProcessor.getContext().mapObject(element, Scope.INTERACTION);
+ final String action = RemoveAction.ACTION + Names.COMMAND_ROOT;
+ templateProcessor.appendHtml("<form" + classSegment + " method=\"post\" action=\"" + action + "\" >");
+ templateProcessor.appendHtml("<input type=\"hidden\" name=\"" + OBJECT + "\" value=\"" + objectId + "\" />");
+ templateProcessor.appendHtml("<input type=\"hidden\" name=\"" + FIELD + "\" value=\"" + fieldName + "\" />");
+ templateProcessor.appendHtml("<input type=\"hidden\" name=\"" + ELEMENT + "\" value=\"" + elementId + "\" />");
+ if (resultOverride != null) {
+ templateProcessor.appendHtml("<input type=\"hidden\" name=\"" + RESULT_OVERRIDE + "\" value=\"" + resultOverride + "\" />");
+ }
+ templateProcessor.appendHtml("<input type=\"hidden\" name=\"" + VIEW + "\" value=\"" + view + "\" />");
+ templateProcessor.appendHtml("<input type=\"hidden\" name=\"" + ERROR + "\" value=\"" + error + "\" />");
+ templateProcessor.appendHtml(templateProcessor.getContext().interactionFields());
+ templateProcessor.appendHtml("<input class=\"button\" type=\"submit\" value=\"" + title + "\" />");
+ templateProcessor.appendHtml("</form>");
+ }
+ }
+ }
+
+ private static boolean valid(final TemplateProcessor templateProcessor, final ObjectAdapter adapter) {
+ // TODO is this check valid/necessary?
+
+ // TODO check is valid to remove element
+ final AuthenticationSession session = IsisContext.getAuthenticationSession();
+ final Filter<ObjectAssociation> filter = ObjectAssociationFilters.dynamicallyVisible(session, adapter, where);
+ final List<ObjectAssociation> visibleFields = adapter.getSpecification().getAssociations(filter);
+ if (visibleFields.size() == 0) {
+ return false;
+ }
+
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableBlock.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableBlock.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableBlock.java
new file mode 100644
index 0000000..7671317
--- /dev/null
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableBlock.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.isis.viewer.scimpi.dispatcher.view.collection;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.BlockContent;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.TemplateProcessor.RepeatMarker;
+
+public class TableBlock implements BlockContent {
+
+ // {{ collection
+ private ObjectAdapter collection;
+
+ public void setCollection(final ObjectAdapter collection) {
+ this.collection = collection;
+ }
+
+ public ObjectAdapter getCollection() {
+ return collection;
+ }
+ // }}
+
+ // {{ linkView
+ private String linkView;
+
+ public String getlinkView() {
+ return linkView;
+ }
+
+ public void setlinkView(final String linkView) {
+ this.linkView = linkView;
+ }
+ // }}
+
+ // {{ linkName
+ private String linkName;
+
+ public String getlinkName() {
+ return linkName;
+ }
+
+ public void setlinkName(final String linkName) {
+ this.linkName = linkName;
+ }
+ // }}
+
+ // {{ elementName
+ private String elementName;
+
+ public String getElementName() {
+ return elementName;
+ }
+
+ public void setElementName(final String linkObject) {
+ this.elementName = linkObject;
+ }
+ // }}
+
+ private RepeatMarker marker;
+
+ public RepeatMarker getMarker() {
+ return marker;
+ }
+
+ public void setMarker(final RepeatMarker marker) {
+ this.marker = marker;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableBuilder.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableBuilder.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableBuilder.java
new file mode 100644
index 0000000..7809e74
--- /dev/null
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableBuilder.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.isis.viewer.scimpi.dispatcher.view.collection;
+
+import java.util.List;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.viewer.scimpi.dispatcher.context.Request;
+import org.apache.isis.viewer.scimpi.dispatcher.context.Request.Scope;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.PageWriter;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.TemplateProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.TemplateProcessor.RepeatMarker;
+
+public class TableBuilder extends AbstractTableView {
+
+ @Override
+ protected TableContentWriter createRowBuilder(final TemplateProcessor templateProcessor, final Request context, final String parent, final List<ObjectAssociation> allFields, final ObjectAdapter collection) {
+
+ final String title = templateProcessor.getOptionalProperty(TABLE_TITLE);
+ final String variable = templateProcessor.getOptionalProperty(ELEMENT_NAME, ELEMENT);
+ final String headerClass = templateProcessor.getOptionalProperty("head-" + CLASS);
+
+ final TableBlock block = new TableBlock();
+ block.setCollection(collection);
+ block.setElementName(variable);
+ templateProcessor.pushBlock(block);
+ templateProcessor.pushNewBuffer();
+ templateProcessor.processUtilCloseTag();
+ final String headers = templateProcessor.popBuffer();
+ return new TableContentWriter() {
+
+ @Override
+ public void writeFooters(final PageWriter writer) {
+ }
+
+ public void tidyUp() {
+ templateProcessor.popBlock();
+ }
+
+ @Override
+ public void writeCaption(PageWriter writer) {
+ if (title != null) {
+ writer.appendHtml("<caption>");
+ writer.appendHtml(title);
+ writer.appendHtml("</thead>");
+ }
+ }
+
+ @Override
+ public void writeHeaders(final PageWriter writer) {
+ final String headerSegment = headerClass == null ? "" : (" class=\"" + headerClass + "\"");
+ writer.appendHtml("<thead" + headerSegment + ">");
+ writer.appendHtml(headers);
+ writer.appendHtml("</thead>");
+ }
+
+ @Override
+ public void writeElement(final TemplateProcessor templateProcessor, final Request context, final ObjectAdapter element) {
+ context.addVariable(variable, context.mapObject(element, Scope.REQUEST), Scope.REQUEST);
+ final RepeatMarker end = templateProcessor.createMarker();
+ final RepeatMarker marker = block.getMarker();
+ marker.repeat();
+ templateProcessor.processUtilCloseTag();
+ end.repeat();
+ }
+ };
+ }
+
+ @Override
+ public String getName() {
+ return "table-builder";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableCell.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableCell.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableCell.java
new file mode 100644
index 0000000..9160a0a
--- /dev/null
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableCell.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.isis.viewer.scimpi.dispatcher.view.collection;
+
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.scimpi.Names;
+import org.apache.isis.viewer.scimpi.ScimpiException;
+import org.apache.isis.viewer.scimpi.dispatcher.context.Request;
+import org.apache.isis.viewer.scimpi.dispatcher.context.RequestState;
+import org.apache.isis.viewer.scimpi.dispatcher.context.Request.Scope;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.TemplateProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.view.AbstractElementProcessor;
+
+public class TableCell extends AbstractElementProcessor {
+
+ // REVIEW: should provide this rendering context, rather than hardcoding.
+ // the net effect currently is that class members annotated with
+ // @Hidden(where=Where.ALL_TABLES) or @Disabled(where=Where.ALL_TABLES) will indeed
+ // be hidden from all tables but will be visible/enabled (perhaps incorrectly)
+ // if annotated with Where.PARENTED_TABLE or Where.STANDALONE_TABLE
+ private final Where where = Where.ALL_TABLES;
+
+ @Override
+ public void process(final TemplateProcessor templateProcessor, RequestState state) {
+ final TableBlock tableBlock = (TableBlock) templateProcessor.peekBlock();
+ final String id = templateProcessor.getOptionalProperty(OBJECT);
+ final String fieldName = templateProcessor.getRequiredProperty(FIELD);
+ final String linkView = templateProcessor.getOptionalProperty(LINK_VIEW);
+ String className = templateProcessor.getOptionalProperty(CLASS);
+ className = className == null ? "" : " class=\"" + className + "\"";
+ Request context = templateProcessor.getContext();
+ final ObjectAdapter object = context.getMappedObjectOrVariable(id, tableBlock.getElementName());
+ final ObjectAssociation field = object.getSpecification().getAssociation(fieldName);
+ if (field == null) {
+ throw new ScimpiException("No field " + fieldName + " in " + object.getSpecification().getFullIdentifier());
+ }
+ templateProcessor.appendHtml("<td" + className + ">");
+ if (field.isVisible(IsisContext.getAuthenticationSession(), object, where).isAllowed()) {
+ final ObjectAdapter fieldReference = field.get(object);
+ final String source = fieldReference == null ? "" : context.mapObject(fieldReference, Scope.REQUEST);
+ final String name = templateProcessor.getOptionalProperty(RESULT_NAME, fieldName);
+ context.addVariable(name, templateProcessor.encodeHtml(source), Scope.REQUEST);
+
+ if (linkView != null) {
+ final String linkId = context.mapObject(object, Scope.REQUEST);
+ final String linkName = templateProcessor.getOptionalProperty(LINK_NAME, Names.RESULT);
+ final String linkObject = templateProcessor.getOptionalProperty(LINK_OBJECT, linkId);
+ templateProcessor.appendHtml("<a href=\"" + linkView + "?" + linkName + "=" + linkObject + context.encodedInteractionParameters() + "\">");
+ } else if(tableBlock.getlinkView() != null) {
+ String linkObjectInVariable = tableBlock.getElementName();
+ final String linkId = (String) context.getVariable(linkObjectInVariable);
+ templateProcessor.appendHtml("<a href=\"" + tableBlock.getlinkView() + "?" + tableBlock.getlinkName() + "=" + linkId + context.encodedInteractionParameters() + "\">");
+ }
+ templateProcessor.pushNewBuffer();
+ templateProcessor.processUtilCloseTag();
+ final String buffer = templateProcessor.popBuffer();
+ if (buffer.trim().length() == 0) {
+ templateProcessor.appendAsHtmlEncoded(fieldReference == null ? "" : fieldReference.titleString());
+ } else {
+ templateProcessor.appendHtml(buffer);
+ }
+ if (linkView != null) {
+ templateProcessor.appendHtml("</a>");
+ }
+ } else {
+ templateProcessor.skipUntilClose();
+ }
+ templateProcessor.appendHtml("</td>");
+ }
+
+ @Override
+ public String getName() {
+ return "table-cell";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableContentWriter.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableContentWriter.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableContentWriter.java
new file mode 100644
index 0000000..5683264
--- /dev/null
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableContentWriter.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.viewer.scimpi.dispatcher.view.collection;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.viewer.scimpi.dispatcher.context.Request;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.PageWriter;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.TemplateProcessor;
+
+public interface TableContentWriter {
+
+ void writeCaption(PageWriter writer);
+
+ void writeHeaders(PageWriter writer);
+
+ void writeFooters(PageWriter writer);
+
+ void writeElement(TemplateProcessor templateProcessor, Request context, ObjectAdapter element);
+
+ void tidyUp();
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableEmpty.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableEmpty.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableEmpty.java
new file mode 100644
index 0000000..4b918bc
--- /dev/null
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableEmpty.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.isis.viewer.scimpi.dispatcher.view.collection;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
+import org.apache.isis.viewer.scimpi.dispatcher.context.RequestState;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.TemplateProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.view.AbstractElementProcessor;
+
+public class TableEmpty extends AbstractElementProcessor {
+
+ @Override
+ public void process(final TemplateProcessor templateProcessor, RequestState state) {
+ final TableBlock tableBlock = (TableBlock) templateProcessor.peekBlock();
+ final ObjectAdapter collection = tableBlock.getCollection();
+ final CollectionFacet facet = collection.getSpecification().getFacet(CollectionFacet.class);
+ if (facet.size(collection) == 0) {
+ String className = templateProcessor.getOptionalProperty(CLASS);
+ className = className == null ? "" : " class=\"" + className + "\"";
+ templateProcessor.appendHtml("<tr" + className + ">");
+ templateProcessor.pushNewBuffer();
+ templateProcessor.processUtilCloseTag();
+ final String buffer = templateProcessor.popBuffer();
+ templateProcessor.appendHtml(buffer);
+ templateProcessor.appendHtml("</td>");
+ } else {
+ templateProcessor.skipUntilClose();
+ }
+ }
+
+ @Override
+ public String getName() {
+ return "table-empty";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableHeader.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableHeader.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableHeader.java
new file mode 100644
index 0000000..c3d15f4
--- /dev/null
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableHeader.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.isis.viewer.scimpi.dispatcher.view.collection;
+
+import org.apache.isis.viewer.scimpi.dispatcher.context.RequestState;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.TemplateProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.view.AbstractElementProcessor;
+
+public class TableHeader extends AbstractElementProcessor {
+
+ @Override
+ public String getName() {
+ return "table-header";
+ }
+
+ @Override
+ public void process(final TemplateProcessor templateProcessor, RequestState state) {
+ templateProcessor.appendHtml("<thead><tr>");
+ templateProcessor.processUtilCloseTag();
+ templateProcessor.appendHtml("</tr></thead>");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableRow.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableRow.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableRow.java
new file mode 100644
index 0000000..46b7c03
--- /dev/null
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableRow.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.isis.viewer.scimpi.dispatcher.view.collection;
+
+import org.apache.isis.viewer.scimpi.Names;
+import org.apache.isis.viewer.scimpi.dispatcher.context.RequestState;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.TemplateProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.TemplateProcessor.RepeatMarker;
+import org.apache.isis.viewer.scimpi.dispatcher.view.AbstractElementProcessor;
+
+public class TableRow extends AbstractElementProcessor {
+
+ @Override
+ public String getName() {
+ return "table-row";
+ }
+
+ @Override
+ public void process(final TemplateProcessor templateProcessor, RequestState state) {
+ final TableBlock block = (TableBlock) templateProcessor.peekBlock();
+
+ final RepeatMarker start = templateProcessor.createMarker();
+ block.setMarker(start);
+
+ final String linkView = templateProcessor.getOptionalProperty(LINK_VIEW);
+ if (linkView != null) {
+ block.setlinkView(linkView);
+ block.setlinkName(templateProcessor.getOptionalProperty(LINK_NAME, Names.RESULT));
+ }
+
+ templateProcessor.skipUntilClose();
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableView.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableView.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableView.java
new file mode 100644
index 0000000..72baeaf
--- /dev/null
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/TableView.java
@@ -0,0 +1,328 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.isis.viewer.scimpi.dispatcher.view.collection;
+
+import java.util.List;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facets.object.parseable.ParseableFacet;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.runtime.persistence.ObjectNotFoundException;
+import org.apache.isis.viewer.scimpi.Names;
+import org.apache.isis.viewer.scimpi.dispatcher.context.Request;
+import org.apache.isis.viewer.scimpi.dispatcher.context.Request.Scope;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.PageWriter;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.TemplateProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.view.determine.LinkedFieldsBlock;
+import org.apache.isis.viewer.scimpi.dispatcher.view.determine.LinkedObject;
+
+public class TableView extends AbstractTableView {
+
+ public static final class SimpleTableBuilder implements TableContentWriter {
+ private final String parent;
+ private final boolean includeHeader;
+ private final boolean includeFooter;
+ private final String title;
+ private final String[] headers;
+ private final List<ObjectAssociation> fields;
+ private final boolean showTitle;
+ private final boolean showIcons;
+ private final boolean showSelectOption;
+ private final boolean showDeleteOption;
+ private final boolean showEditOption;
+ private final String fieldName;
+ private final LinkedObject[] linkedFields;
+ private final LinkedObject linkRow;
+ private final int noColumns;
+
+ public SimpleTableBuilder(
+ final String parent,
+ final boolean includeHeader,
+ final boolean includeFooter,
+ final String title,
+ final int noColumns,
+ final String[] headers,
+ final List<ObjectAssociation> fields,
+ final boolean showTitle,
+ final boolean showIcons,
+ final boolean showSelectOption,
+ final boolean showDeleteOption,
+ final boolean showEditOption,
+ final String fieldName,
+ final LinkedObject[] linkedFields,
+ final LinkedObject linkRow) {
+ this.parent = parent;
+ this.includeHeader = includeHeader;
+ this.includeFooter = includeFooter;
+ this.title = title;
+ this.showTitle = showTitle;
+ this.noColumns = noColumns < 1 ? fields.size() : noColumns;
+ this.headers = headers;
+ this.fields = fields;
+ this.showIcons = showIcons;
+ this.showSelectOption = showSelectOption;
+ this.showDeleteOption = showDeleteOption;
+ this.showEditOption = showEditOption;
+ this.fieldName = fieldName;
+ this.linkedFields = linkedFields;
+ this.linkRow = linkRow;
+ }
+
+ @Override
+ public void writeFooters(final PageWriter writer) {
+ if (includeFooter) {
+ writer.appendHtml("<tfoot>");
+ columnHeaders(writer, headers);
+ writer.appendHtml("</tfoot>");
+ }
+ }
+
+ @Override
+ public void writeCaption(PageWriter writer) {
+ if (title != null) {
+ writer.appendHtml("<caption>");
+ writer.appendHtml(title);
+ writer.appendHtml("</caption>");
+ }
+ }
+
+ @Override
+ public void writeHeaders(final PageWriter writer) {
+ if (includeHeader) {
+ writer.appendHtml("<thead>");
+ columnHeaders(writer, headers);
+ writer.appendHtml("</thead>");
+ }
+ }
+
+ private void columnHeaders(final PageWriter writer, final String[] headers) {
+ writer.appendHtml("<tr class=\"column-headers\">");
+ if (showTitle) {
+ writer.appendHtml("<th></th>");
+ }
+ final String[] columnHeaders = headers;
+ for (final String columnHeader : columnHeaders) {
+ if (columnHeader != null) {
+ writer.appendHtml("<th>");
+ writer.appendAsHtmlEncoded(columnHeader);
+ writer.appendHtml("</th>");
+ }
+ }
+ writer.appendHtml("<th class=\"controls\"></th>");
+ writer.appendHtml("</tr>");
+ }
+
+ public void tidyUp() {
+ // request.popBlockContent();
+
+ // Is it the block that is left over, or is the collection form not being closed?
+ }
+
+ @Override
+ public void writeElement(final TemplateProcessor templateProcessor, final Request context, final ObjectAdapter element) {
+ final String rowId = context.mapObject(element, Scope.INTERACTION);
+ final String scope = linkRow == null ? "" : "&" + SCOPE + "=" + linkRow.getScope();
+ String result = "";
+ result = context.encodedInteractionParameters();
+
+ if (noColumns == 0) {
+ templateProcessor.appendHtml("<td>");
+ if (linkRow != null) {
+ templateProcessor.appendHtml("<td><a href=\"" + linkRow.getForwardView() + "?" + linkRow.getVariable() + "=" + rowId + result + scope + "\">");
+ templateProcessor.appendAsHtmlEncoded(element.titleString());
+ templateProcessor.appendHtml("</a>");
+ } else {
+ templateProcessor.appendAsHtmlEncoded(element.titleString());
+ }
+ templateProcessor.appendHtml("</td>");
+
+ } else {
+ if (showTitle) {
+ templateProcessor.appendHtml("<td>");
+ templateProcessor.appendAsHtmlEncoded(element.titleString());
+ templateProcessor.appendHtml("</td>");
+ }
+
+ for (int i = 0; i < noColumns; i++) {
+ if (fields.get(i).isOneToManyAssociation()) {
+ continue;
+ }
+ templateProcessor.appendHtml("<td>");
+ final ObjectAdapter field = fields.get(i).get(element);
+ if (field != null) {
+ if (showIcons && !fields.get(i).getSpecification().containsFacet(ParseableFacet.class)) {
+ templateProcessor.appendHtml("<img class=\"" + "small-icon" + "\" src=\"" + templateProcessor.getContext().imagePath(field) + "\" alt=\"" + fields.get(i).getSpecification().getShortIdentifier() + "\"/>");
+ }
+ if (linkRow != null) {
+ templateProcessor.appendHtml("<a href=\"" + linkRow.getForwardView() + "?" + linkRow.getVariable() + "=" + rowId + result + scope + "\">");
+ } else if (linkedFields[i] != null) {
+ final ObjectAdapter fieldObject = fields.get(i).get(element);
+ final String id = context.mapObject(fieldObject, Scope.INTERACTION);
+ templateProcessor.appendHtml("<a href=\"" + linkedFields[i].getForwardView() + "?" + linkedFields[i].getVariable() + "=" + id + "\">");
+ context.mapObject(fieldObject, Request.scope(linkedFields[i].getScope()));
+
+ }
+ try {
+ templateProcessor.appendAsHtmlEncoded(field.titleString());
+ } catch (final ObjectNotFoundException e) {
+ templateProcessor.appendAsHtmlEncoded(e.getMessage());
+ }
+ if (linkRow != null || linkedFields[i] != null) {
+ templateProcessor.appendHtml("</a>");
+ }
+ }
+ templateProcessor.appendHtml("</td>");
+
+ }
+ }
+ templateProcessor.appendHtml("<td class=\"controls\">");
+ if (showSelectOption) {
+ templateProcessor.appendHtml("<a class=\"button element-select\" href=\"" + "_generic." + Names.EXTENSION + "?" + Names.RESULT + "=" + rowId + result + scope + "\">view</a>");
+ }
+ if (showEditOption) {
+ templateProcessor.appendHtml(" <a class=\"button element-edit\" href=\"" + "_generic_edit." + Names.EXTENSION + "?" + Names.RESULT + "=" + rowId + result + scope + "\">edit</a>");
+ }
+
+ if (showDeleteOption && parent != null) {
+ String view = templateProcessor.getViewPath();
+ view = context.fullFilePath(view == null ? context.getResourceFile() : view);
+ RemoveElement.write(templateProcessor, context.getMappedObject(parent), fieldName, element, null, view, view, "delete", "action in-line element-delete confirm");
+ }
+
+ templateProcessor.appendHtml("</td>");
+
+ }
+ }
+
+ @Override
+ protected TableContentWriter createRowBuilder(
+ final TemplateProcessor templateProcessor,
+ final Request context,
+ final String parent,
+ final List<ObjectAssociation> allFields,
+ final ObjectAdapter collection) {
+ final String fieldName = templateProcessor.getOptionalProperty(FIELD);
+ final String title = templateProcessor.getOptionalProperty(FORM_TITLE);
+ return rowBuilder(templateProcessor, context, title, parent, fieldName, allFields, showIconByDefault());
+ }
+
+ private static TableContentWriter rowBuilder(
+ final TemplateProcessor templateProcessor,
+ final Request context,
+ final String title,
+ final String object,
+ final String fieldName,
+ final List<ObjectAssociation> allFields,
+ final boolean showIconByDefault) {
+ final String linkRowView = templateProcessor.getOptionalProperty(LINK_VIEW);
+ final String linkObjectName = templateProcessor.getOptionalProperty(ELEMENT_NAME, Names.RESULT);
+ final String linkObjectScope = templateProcessor.getOptionalProperty(SCOPE, Scope.INTERACTION.toString());
+ final LinkedObject linkRow = linkRowView == null ? null : new LinkedObject(linkObjectName, linkObjectScope, context.fullUriPath(linkRowView));
+ final boolean includeHeader = templateProcessor.isRequested(HEADER, true);
+ final boolean includeFooter = templateProcessor.isRequested(FOOTER, false);
+
+ final boolean linkFields = templateProcessor.isRequested("link-fields", true);
+ final boolean showTitle = templateProcessor.isRequested(SHOW_TITLE, false);
+ final boolean showIcons = templateProcessor.isRequested(SHOW_ICON, showIconByDefault);
+ final boolean showSelectOption = templateProcessor.isRequested(SHOW_SELECT, true);
+ final boolean showEditOption = templateProcessor.isRequested(SHOW_EDIT, true);
+ final boolean showDeleteOption = templateProcessor.isRequested(SHOW_DELETE, true);
+
+ final String noColumnsString = templateProcessor.getOptionalProperty("no-columns", "3");
+
+ final LinkedFieldsBlock block = new LinkedFieldsBlock();
+ templateProcessor.pushBlock(block);
+ templateProcessor.processUtilCloseTag();
+ final List<ObjectAssociation> fields = block.includedFields(allFields);
+ final LinkedObject[] linkedFields = block.linkedFields(fields);
+ for (int i = 0; i < linkedFields.length; i++) {
+ if (linkedFields[i] == null && linkFields && !fields.get(i).getSpecification().containsFacet(ParseableFacet.class)) {
+ linkedFields[i] = new LinkedObject("_generic.shtml");
+ }
+ if (linkedFields[i] != null) {
+ linkedFields[i].setForwardView(context.fullUriPath(linkedFields[i].getForwardView()));
+ }
+ }
+
+ int noColumns;
+ if (noColumnsString.equalsIgnoreCase("all")) {
+ noColumns = fields.size();
+ } else {
+ noColumns = Math.min(fields.size(), Integer.valueOf(noColumnsString));
+ }
+
+ final String headers[] = new String[noColumns];
+ int h = 0;
+ for (int i = 0; i < noColumns; i++) {
+ if (fields.get(i).isOneToManyAssociation()) {
+ continue;
+ }
+ headers[h++] = fields.get(i).getName();
+ }
+
+ templateProcessor.popBlock();
+
+ return new SimpleTableBuilder(object, includeHeader, includeFooter, title, noColumns, headers, fields, showTitle,
+ showIcons, showSelectOption, showDeleteOption, showEditOption, fieldName, linkedFields, linkRow);
+ }
+
+ public static void write(
+ final TemplateProcessor templateProcessor,
+ final String summary,
+ final ObjectAdapter object,
+ final ObjectAssociation field,
+ final ObjectAdapter collection,
+ final int noColumns,
+ final List<ObjectAssociation> fields,
+ final boolean linkAllFields,
+ final boolean showIconByDefault,
+ final String tableClass,
+ final String[] rowClasses,
+ LinkedObject linkedObject) {
+ final LinkedObject[] linkedFields = new LinkedObject[fields.size()];
+ if (linkAllFields) {
+ for (int i = 0; i < linkedFields.length; i++) {
+ if (fields.get(i).isOneToOneAssociation()) {
+ linkedFields[i] = linkedObject == null ? new LinkedObject("_generic.shtml") : linkedObject;
+ }
+ }
+ }
+
+ final String headers[] = new String[fields.size()];
+ int h = 0;
+ for (int i = 0; i < fields.size(); i++) {
+ if (fields.get(i).isOneToManyAssociation()) {
+ continue;
+ }
+ headers[h++] = fields.get(i).getName();
+ }
+
+ final Request context = templateProcessor.getContext();
+ final TableContentWriter rowBuilder = rowBuilder(templateProcessor, context, null, context.mapObject(object, Scope.REQUEST), field.getIdentifier().getMemberName(), fields,
+ showIconByDefault);
+ write(templateProcessor, collection, summary, rowBuilder, null, null, null);
+ }
+
+ @Override
+ public String getName() {
+ return "table";
+ }
+
+}