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 2015/03/30 14:56:36 UTC

[07/22] isis git commit: ISIS-720: mothballing scimpi

http://git-wip-us.apache.org/repos/asf/isis/blob/2c7cfbfe/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionForm.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionForm.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionForm.java
new file mode 100644
index 0000000..469b99d
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionForm.java
@@ -0,0 +1,262 @@
+/*
+ *  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.action;
+
+import java.util.List;
+
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
+import org.apache.isis.viewer.scimpi.dispatcher.AbstractElementProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.ScimpiException;
+import org.apache.isis.viewer.scimpi.dispatcher.action.ActionAction;
+import org.apache.isis.viewer.scimpi.dispatcher.context.RequestContext;
+import org.apache.isis.viewer.scimpi.dispatcher.context.RequestContext.Scope;
+import org.apache.isis.viewer.scimpi.dispatcher.edit.FieldEditState;
+import org.apache.isis.viewer.scimpi.dispatcher.edit.FormState;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.Request;
+import org.apache.isis.viewer.scimpi.dispatcher.util.MethodsUtils;
+import org.apache.isis.viewer.scimpi.dispatcher.view.edit.FieldFactory;
+import org.apache.isis.viewer.scimpi.dispatcher.view.edit.FormFieldBlock;
+import org.apache.isis.viewer.scimpi.dispatcher.view.form.HiddenInputField;
+import org.apache.isis.viewer.scimpi.dispatcher.view.form.HtmlFormBuilder;
+import org.apache.isis.viewer.scimpi.dispatcher.view.form.InputField;
+
+public class ActionForm extends AbstractElementProcessor {
+
+    // REVIEW: confirm this rendering context
+    private final static Where where = Where.OBJECT_FORMS;
+
+    @Override
+    public void process(final Request request) {
+        final CreateFormParameter parameters = new CreateFormParameter();
+        parameters.objectId = request.getOptionalProperty(OBJECT);
+        parameters.methodName = request.getRequiredProperty(METHOD);
+        parameters.forwardResultTo = request.getOptionalProperty(VIEW);
+        parameters.forwardVoidTo = request.getOptionalProperty(VOID);
+        parameters.forwardErrorTo = request.getOptionalProperty(ERROR);
+        parameters.cancelTo = request.getOptionalProperty(CANCEL_TO); 
+        parameters.showIcon = request.isRequested(SHOW_ICON, showIconByDefault());
+        parameters.buttonTitle = request.getOptionalProperty(BUTTON_TITLE);
+        parameters.formTitle = request.getOptionalProperty(FORM_TITLE);
+        parameters.labelDelimiter = request.getOptionalProperty(LABEL_DELIMITER, ":");
+        parameters.formId = request.getOptionalProperty(FORM_ID, request.nextFormId());
+        parameters.resultName = request.getOptionalProperty(RESULT_NAME);
+        parameters.resultOverride = request.getOptionalProperty(RESULT_OVERRIDE);
+        parameters.scope = request.getOptionalProperty(SCOPE);
+        parameters.className = request.getOptionalProperty(CLASS, "action full");
+        parameters.showMessage = request.isRequested(SHOW_MESSAGE, false);
+        parameters.completionMessage = request.getOptionalProperty(MESSAGE);
+        parameters.id = request.getOptionalProperty(ID, parameters.methodName);
+        createForm(request, parameters);
+    }
+
+    public static void createForm(final Request request, final CreateFormParameter parameterObject) {
+        createForm(request, parameterObject, false);
+    }
+
+    protected static void createForm(final Request request, final CreateFormParameter parameterObject, final boolean withoutProcessing) {
+        final RequestContext context = request.getContext();
+        final ObjectAdapter object = MethodsUtils.findObject(context, parameterObject.objectId);
+        final String version = request.getContext().mapVersion(object);
+        final ObjectAction action = MethodsUtils.findAction(object, parameterObject.methodName);
+        // TODO how do we distinguish between overloaded methods?
+
+        // REVIEW Is this useful?
+        if (action.getParameterCount() == 0) {
+            throw new ScimpiException("Action form can only be used for actions with parameters");
+        }
+        if (parameterObject.showMessage && MethodsUtils.isVisible(object, action, where)) {
+            final String notUsable = MethodsUtils.isUsable(object, action, where);
+            if (notUsable != null) {
+                if (!withoutProcessing) {
+                    request.skipUntilClose();
+                }
+                request.appendHtml("<div class=\"" + parameterObject.className + "-message\" >");
+                request.appendAsHtmlEncoded(notUsable);
+                request.appendHtml("</div>");
+                return;
+            }
+        }
+        if (!MethodsUtils.isVisibleAndUsable(object, action, where)) {
+            if (!withoutProcessing) {
+                request.skipUntilClose();
+            }
+            return;
+        }
+        final String objectId = context.mapObject(object, Scope.INTERACTION);
+        final String errorView = context.fullFilePath(parameterObject.forwardErrorTo == null ? context.getResourceFile() : parameterObject.forwardErrorTo);
+        final String voidView = context.fullFilePath(parameterObject.forwardVoidTo == null ? context.getResourceFile() : parameterObject.forwardVoidTo);
+        if (false /* action.isContributed() && !action.hasReturn() && parameterObject.resultOverride == null */) {
+            parameterObject.resultOverride = objectId;
+        }
+        final HiddenInputField[] hiddenFields = new HiddenInputField[] { new HiddenInputField("_" + OBJECT, objectId), new HiddenInputField("_" + VERSION, version), new HiddenInputField("_" + FORM_ID, parameterObject.formId), new HiddenInputField("_" + METHOD, parameterObject.methodName),
+                parameterObject.forwardResultTo == null ? null : new HiddenInputField("_" + VIEW, context.fullFilePath(parameterObject.forwardResultTo)), new HiddenInputField("_" + VOID, voidView), new HiddenInputField("_" + ERROR, errorView),
+                parameterObject.completionMessage == null ? null : new HiddenInputField("_" + MESSAGE, parameterObject.completionMessage), parameterObject.scope == null ? null : new HiddenInputField("_" + SCOPE, parameterObject.scope),
+                parameterObject.resultOverride == null ? null : new HiddenInputField("_" + RESULT_OVERRIDE, parameterObject.resultOverride), parameterObject.resultName == null ? null : new HiddenInputField("_" + RESULT_NAME, parameterObject.resultName),
+                parameterObject.resultName == null ? null : new HiddenInputField(RequestContext.RESULT, (String) request.getContext().getVariable(RequestContext.RESULT)) };
+
+        // TODO when the block contains a selector tag it doesn't disable it if
+        // the field cannot be edited!!!
+        final FormFieldBlock containedBlock = new FormFieldBlock() {
+            @Override
+            public boolean isNullable(final String name) {
+                final int index = Integer.parseInt(name.substring(5)) - 1;
+                final ObjectActionParameter param = action.getParameters().get(index);
+                return param.isOptional();
+            }
+        };
+        request.setBlockContent(containedBlock);
+        if (!withoutProcessing) {
+            request.processUtilCloseTag();
+        }
+
+        final FormState entryState = (FormState) context.getVariable(ENTRY_FIELDS);
+
+        // TODO the list of included fields should be considered in the next
+        // method (see EditObject)
+        final InputField[] formFields = createFields(action, object);
+        containedBlock.hideExcludedParameters(formFields);
+        containedBlock.setUpValues(formFields);
+        initializeFields(context, object, action, formFields);
+        setDefaults(context, object, action, formFields, entryState, parameterObject.showIcon);
+        String errors = null;
+        if (entryState != null && entryState.isForForm(parameterObject.formId)) {
+            copyEntryState(context, object, action, formFields, entryState);
+            errors = entryState.getError();
+        }
+        overrideWithHtml(context, containedBlock, formFields);
+
+        String formTitle;
+        if (parameterObject.formTitle == null) {
+            formTitle = action.getName();
+        } else {
+            formTitle = parameterObject.formTitle;
+        }
+
+        String buttonTitle = parameterObject.buttonTitle;
+        if (buttonTitle == null) {
+            buttonTitle = action.getName();
+        } else if (buttonTitle.equals("")) {
+            buttonTitle = "Ok";
+        }
+
+        HtmlFormBuilder.createForm(request, ActionAction.ACTION + ".app", hiddenFields, formFields, parameterObject.className,
+                parameterObject.id, formTitle, parameterObject.labelDelimiter, action.getDescription(), action.getHelp(), buttonTitle, errors, parameterObject.cancelTo);
+
+        request.popBlockContent();
+    }
+
+    private static InputField[] createFields(final ObjectAction action, final ObjectAdapter object) {
+        final int parameterCount = action.getParameterCount();
+        final InputField[] fields = new InputField[parameterCount];
+        for (int i = 0; i < fields.length; i++) {
+            fields[i] = new InputField(ActionAction.parameterName(i));
+        }
+        return fields;
+    }
+
+    private static void initializeFields(final RequestContext context, final ObjectAdapter object, final ObjectAction action, final InputField[] fields) {
+        final List<ObjectActionParameter> parameters = action.getParameters();
+        for (int i = 0; i < fields.length; i++) {
+            final InputField field = fields[i];
+            final ObjectActionParameter param = parameters.get(i);
+            if (false /*action.isContributed() && i == 0*/) {
+                // fields[i].setValue(context.mapObject(object,
+                // Scope.INTERACTION));
+                fields[i].setType(InputField.REFERENCE);
+                fields[i].setHidden(true);
+            } else {
+
+                fields[i].setHelpReference("xxxhelp");
+                final ObjectAdapter[] optionsForParameter = action.getChoices(object)[i];
+                FieldFactory.initializeField(context, object, param, optionsForParameter, !param.isOptional(), field);
+            }
+        }
+    }
+
+    /**
+     * Sets up the fields with their initial values
+     * 
+     * @param showIcon
+     */
+    private static void setDefaults(final RequestContext context, final ObjectAdapter object, final ObjectAction action, final InputField[] fields, final FormState entryState, final boolean showIcon) {
+        final ObjectAdapter[] defaultValues = action.getDefaults(object);
+        if (defaultValues == null) {
+            return;
+        }
+
+        for (int i = 0; i < fields.length; i++) {
+            final InputField field = fields[i];
+            final ObjectAdapter defaultValue = defaultValues[i];
+
+            final String title = defaultValue == null ? "" : defaultValue.titleString();
+            if (field.getType() == InputField.REFERENCE) {
+                final ObjectSpecification objectSpecification = action.getParameters().get(i).getSpecification();
+                if (defaultValue != null) {
+                    final String imageSegment = showIcon ? "<img class=\"small-icon\" src=\"" + context.imagePath(objectSpecification) + "\" alt=\"" + objectSpecification.getShortIdentifier() + "\"/>" : "";
+                    final String html = imageSegment + title;
+                    final String value = context.mapObject(defaultValue, Scope.INTERACTION);
+                    field.setValue(value);
+                    field.setHtml(html);
+                }
+            } else {
+                field.setValue(title);
+            }
+        }
+    }
+
+    private static void copyEntryState(final RequestContext context, final ObjectAdapter object, final ObjectAction action, final InputField[] fields, final FormState entryState) {
+
+        for (final InputField field : fields) {
+            final FieldEditState fieldState = entryState.getField(field.getName());
+            if (fieldState != null) {
+                if (field.isEditable()) {
+                    String entry;
+                    entry = fieldState.getEntry();
+                    field.setValue(entry);
+                }
+
+                field.setErrorText(fieldState.getError());
+            }
+        }
+    }
+
+    private static void overrideWithHtml(final RequestContext context, final FormFieldBlock containedBlock, final InputField[] formFields) {
+        for (int i = 0; i < formFields.length; i++) {
+            final String id = ActionAction.parameterName(i);
+            if (containedBlock.hasContent(id)) {
+                final String content = containedBlock.getContent(id);
+                if (content != null) {
+                    formFields[i].setHtml(content);
+                    formFields[i].setType(InputField.HTML);
+                }
+            }
+        }
+    }
+
+    @Override
+    public String getName() {
+        return "action-form";
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/2c7cfbfe/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionLink.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionLink.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionLink.java
new file mode 100644
index 0000000..520e2bc
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionLink.java
@@ -0,0 +1,179 @@
+/*
+ *  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.action;
+
+import java.net.URLEncoder;
+
+import org.apache.commons.lang.StringEscapeUtils;
+
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.applib.profiles.Localization;
+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.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.scimpi.dispatcher.AbstractElementProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.context.RequestContext;
+import org.apache.isis.viewer.scimpi.dispatcher.context.RequestContext.Scope;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.Request;
+import org.apache.isis.viewer.scimpi.dispatcher.util.MethodsUtils;
+import org.apache.isis.viewer.scimpi.dispatcher.view.HelpLink;
+
+public class ActionLink extends AbstractElementProcessor {
+
+    // REVIEW: confirm this rendering context
+    private final Where where = Where.OBJECT_FORMS;
+
+    @Override
+    public void process(final Request request) {
+        String objectId = request.getOptionalProperty(OBJECT);
+        final String method = request.getOptionalProperty(METHOD);
+        final String forwardResultTo = request.getOptionalProperty(VIEW);
+        final String forwardVoidTo = request.getOptionalProperty(VOID);
+        String resultOverride = request.getOptionalProperty(RESULT_OVERRIDE);
+        
+        final String resultName = request.getOptionalProperty(RESULT_NAME);
+        final String resultNameSegment = resultName == null ? "" : "&amp;" + RESULT_NAME + "=" + resultName;
+        final String scope = request.getOptionalProperty(SCOPE);
+        final String scopeSegment = scope == null ? "" : "&amp;" + SCOPE + "=" + scope;
+        final String confirm = request.getOptionalProperty(CONFIRM);
+        final String completionMessage = request.getOptionalProperty(MESSAGE);
+        final String idName = request.getOptionalProperty(ID, method);
+        final String className = request.getOptionalProperty(CLASS);
+
+        
+        // TODO need a mechanism for globally dealing with encoding; then use
+        // the new encode method
+        final String confirmSegment = confirm == null ? "" : "&amp;" + "_" + CONFIRM + "=" + URLEncoder.encode(confirm);
+        final String messageSegment = completionMessage == null ? "" : "&amp;" + "_" + MESSAGE + "=" + URLEncoder.encode(completionMessage);
+
+        final RequestContext context = request.getContext();
+        final ObjectAdapter object = MethodsUtils.findObject(context, objectId);
+        final String version = context.mapVersion(object);
+        final ObjectAction action = MethodsUtils.findAction(object, method);
+
+        final ActionContent parameterBlock = new ActionContent(action);
+        request.setBlockContent(parameterBlock);
+        request.pushNewBuffer();
+        request.processUtilCloseTag();
+        final String text = request.popBuffer();
+        
+        final String[] parameters = parameterBlock.getParameters();
+        final String target;
+        /*
+        if (action.isContributed()) {
+            System.arraycopy(parameters, 0, parameters, 1, parameters.length - 1);
+            parameters[0] = request.getContext().mapObject(object, Scope.REQUEST);
+            target =  request.getContext().mapObject(action.realTarget(object), Scope.REQUEST);
+            if (!action.hasReturn() && resultOverride == null) {
+                resultOverride = parameters[0];
+            }
+        } else {
+            target =  StringEscapeUtils.escapeHtml(request.getContext().mapObject(object, Scope.INTERACTION));
+        }
+         */
+        
+        final ObjectAdapter[] objectParameters;
+        
+        // TODO copied from ActionButton
+        //final ObjectAdapter target;
+        if (false /*action.isContributed() */) {
+//            objectParameters= null;
+//            System.arraycopy(parameters, 0, parameters, 1, parameters.length - 1);
+//            parameters[0] = request.getContext().mapObject(object, Scope.REQUEST);
+//            target =  request.getContext().mapObject(action.realTarget(object), Scope.REQUEST);
+//            if (!action.hasReturn() && resultOverride == null) {
+//                resultOverride = parameters[0];
+//            }
+        } else {
+            objectParameters = new ObjectAdapter[parameters.length];
+            // target = object;
+            target =  StringEscapeUtils.escapeHtml(request.getContext().mapObject(object, Scope.INTERACTION));
+            int i = 0;
+            for (final ObjectActionParameter spec : action.getParameters()) {
+                final ObjectSpecification type = spec.getSpecification();
+                if (parameters[i] == null) {
+                    objectParameters[i] = null;
+                } else if (type.getFacet(ParseableFacet.class) != null) {
+                    final ParseableFacet facet = type.getFacet(ParseableFacet.class);
+                    Localization localization = IsisContext.getLocalization(); 
+                    objectParameters[i] = facet.parseTextEntry(null, parameters[i], localization); 
+                } else {
+                    objectParameters[i] = MethodsUtils.findObject(request.getContext(), parameters[i]);
+                }
+                i++;
+            }
+        }
+
+        if (MethodsUtils.isVisibleAndUsable(object, action, where)  && MethodsUtils.canRunMethod(object, action, objectParameters).isAllowed()) {
+            writeLink(request, idName, className, target, version, method, forwardResultTo, forwardVoidTo, resultNameSegment, resultOverride, scopeSegment,
+                    confirmSegment, messageSegment, context, action, parameters, text);
+        }
+        request.popBlockContent();
+    }
+
+    public static void writeLink(
+            final Request request,
+            final String idName,
+            final String className,
+            final String objectId,
+            final String version,
+            final String method,
+            final String forwardResultTo,
+            final String forwardVoidTo,
+            final String resultNameSegment,
+            final String resultOverride,
+            final String scopeSegment,
+            final String confirmSegment,
+            final String messageSegment,
+            final RequestContext context,
+            final ObjectAction action,
+            final String[] parameters,
+            String text) {
+        text = text == null || text.trim().equals("") ? action.getName() : text;
+
+        String parameterSegment = "";
+        for (int i = 0; i < parameters.length; i++) {
+            parameterSegment += "&param" + (i + 1) + "=" + parameters[i];
+        }
+
+        final String idSegment = idName == null ? "" : ("id=\"" + idName + "\" ");
+        final String classSegment = "class=\"" + (className == null ? "action in-line" : className) + "\"";
+        final String interactionParamters = context.encodedInteractionParameters();
+        final String forwardResultSegment = forwardResultTo == null ? "" : "&amp;" + "_" + VIEW + "=" + context.fullFilePath(forwardResultTo);
+        final String resultOverrideSegment = resultOverride == null ? "" : "&amp;" + "_" + RESULT_OVERRIDE + "=" + resultOverride;
+        final String voidView = context.fullFilePath(forwardVoidTo == null ? context.getResourceFile() : forwardVoidTo);
+        final String forwardVoidSegment = "&amp;" + "_" + VOID + "=" + voidView;
+        request.appendHtml("<a " + idSegment + classSegment + " href=\"action.app?" + "_" + OBJECT + "=" + objectId + "&amp;" + "_" + VERSION + "=" + version
+                + "&amp;" + "_" + METHOD + "=" + method + resultOverrideSegment + forwardResultSegment + forwardVoidSegment + resultNameSegment
+                + parameterSegment + scopeSegment + confirmSegment + messageSegment + interactionParamters + "\">");
+        request.appendHtml(text);
+        request.appendHtml("</a>");
+        HelpLink.append(request, action.getDescription(), action.getHelp());
+    }
+
+    @Override
+    public String getName() {
+        return "action-link";
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/2c7cfbfe/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/CreateFormParameter.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/CreateFormParameter.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/CreateFormParameter.java
new file mode 100644
index 0000000..2628449
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/CreateFormParameter.java
@@ -0,0 +1,43 @@
+/*
+ *  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.action;
+
+public class CreateFormParameter {
+    public String methodName;
+    public String forwardResultTo;
+    public String forwardVoidTo;
+    public String forwardErrorTo;
+    public String buttonTitle;
+    public String formTitle;
+    public String formId;
+    public String resultName;
+    public String scope;
+    public String objectId;
+    public String description;
+    public String helpReference;
+    public String className;
+    public String id;
+    public String resultOverride;
+    public boolean showMessage;
+    public boolean showIcon;
+    public String completionMessage;
+    public String cancelTo;
+    public String labelDelimiter;
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/2c7cfbfe/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/Methods.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/Methods.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/Methods.java
new file mode 100644
index 0000000..21cff4e
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/Methods.java
@@ -0,0 +1,192 @@
+/*
+ *  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.action;
+
+import java.util.List;
+
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.applib.filter.Filters;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.ActionType;
+import org.apache.isis.core.metamodel.spec.feature.Contributed;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.scimpi.dispatcher.AbstractElementProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.Dispatcher;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.Request;
+import org.apache.isis.viewer.scimpi.dispatcher.util.MethodsUtils;
+import org.apache.isis.viewer.scimpi.dispatcher.view.field.InclusionList;
+
+public class Methods 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 Request request) {
+        String objectId = request.getOptionalProperty(OBJECT);
+        final String view = request.getOptionalProperty(VIEW, "_generic_action." + Dispatcher.EXTENSION);
+        final String cancelTo = request.getOptionalProperty(CANCEL_TO);
+        final boolean showForms = request.isRequested(FORMS, false);
+        final ObjectAdapter object = MethodsUtils.findObject(request.getContext(), objectId);
+        if (objectId == null) {
+            objectId = request.getContext().mapObject(object, null);
+        }
+
+        final InclusionList inclusionList = new InclusionList();
+        request.setBlockContent(inclusionList);
+        request.processUtilCloseTag();
+
+        request.appendHtml("<div class=\"actions\">");
+        if (inclusionList.includes("edit") && !object.getSpecification().isService()) {
+            request.appendHtml("<div class=\"action\">");
+            request.appendHtml("<a class=\"button\" href=\"_generic_edit." + Dispatcher.EXTENSION + "?_result=" + objectId + "\">Edit...</a>");
+            request.appendHtml("</div>");
+        }
+        writeMethods(request, objectId, object, showForms, inclusionList, view, "_generic.shtml?_result=" + objectId);
+        request.popBlockContent();
+        request.appendHtml("</div>");
+    }
+
+    public static void writeMethods(
+            final Request request,
+            final String objectId,
+            final ObjectAdapter adapter,
+            final boolean showForms,
+            final InclusionList inclusionList,
+            final String view,
+            final String cancelTo) {
+        List<ObjectAction> actions = adapter.getSpecification().getObjectActions(ActionType.USER, Contributed.INCLUDED, Filters.<ObjectAction>any());
+        writeMethods(request, adapter, actions, objectId, showForms, inclusionList, view, cancelTo);
+        // TODO determine if system is set up to display exploration methods
+        if (true) {
+            actions = adapter.getSpecification().getObjectActions(ActionType.EXPLORATION, Contributed.INCLUDED, Filters.<ObjectAction>any());
+            writeMethods(request, adapter, actions, objectId, showForms, inclusionList, view, cancelTo);
+        }
+        // TODO determine if system is set up to display debug methods
+        if (true) {
+            actions = adapter.getSpecification().getObjectActions(ActionType.DEBUG, Contributed.INCLUDED, Filters.<ObjectAction>any());
+            writeMethods(request, adapter, actions, objectId, showForms, inclusionList, view, cancelTo);
+        }
+    }
+
+    private static void writeMethods(
+            final Request request,
+            final ObjectAdapter adapter,
+            List<ObjectAction> actions,
+            final String objectId,
+            final boolean showForms,
+            final InclusionList inclusionList,
+            final String view,
+            final String cancelTo) {
+        actions = inclusionList.includedActions(actions);
+        for (int j = 0; j < actions.size(); j++) {
+            final ObjectAction action = actions.get(j);
+            if (false /* action instanceof ObjectActionSet */) {
+//                request.appendHtml("<div class=\"actions\">");
+//                writeMethods(request, adapter, action.getActions(), objectId, showForms, inclusionList, view, cancelTo);
+//                request.appendHtml("</div>");
+            } else if (false /*action.isContributed()*/) {
+//                if (action.getParameterCount() == 1 && adapter.getSpecification().isOfType(action.getParameters().get(0).getSpecification())) {
+//                    if (objectId != null) {
+//                        final ObjectAdapter target = request.getContext().getMappedObject(objectId);
+//                        final ObjectAdapter realTarget = action.realTarget(target);
+//                        final String realTargetId = request.getContext().mapObject(realTarget, Scope.INTERACTION);
+//                        writeMethod(request, adapter, new String[] { objectId }, action, realTargetId, showForms, view, cancelTo);
+//                    } else {
+//                        request.appendHtml("<div class=\"action\">");
+//                        request.appendAsHtmlEncoded(action.getName());
+//                        request.appendHtml("???</div>");
+//                    }
+//                } else if (!adapter.getSpecification().isService()) {
+//                    writeMethod(request, adapter, new String[0], action, objectId, showForms, view, cancelTo);
+//                }
+            } else {
+                writeMethod(request, adapter, new String[0], action, objectId, showForms, view, cancelTo);
+            }
+        }
+    }
+
+    private static void writeMethod(
+            final Request request,
+            final ObjectAdapter adapter,
+            final String[] parameters,
+            final ObjectAction action,
+            final String objectId,
+            final boolean showForms,
+            final String view,
+            final String cancelTo) {
+        // if (action.isVisible(IsisContext.getSession(), null) &&
+        // action.isVisible(IsisContext.getSession(), adapter))
+        // {
+        if (action.isVisible(IsisContext.getAuthenticationSession(), adapter, where).isAllowed()) {
+            request.appendHtml("<div class=\"action\">");
+            if (IsisContext.getSession() == null) {
+                request.appendHtml("<span class=\"disabled\" title=\"no user logged in\">");
+                request.appendAsHtmlEncoded(action.getName());
+                request.appendHtml("</span>");
+                /*
+                 * } else if (action.isUsable(IsisContext.getSession(),
+                 * null).isVetoed()) {
+                 * request.appendHtml("<span class=\"disabled\" title=\"" +
+                 * action.isUsable(IsisContext.getSession(), null).getReason() +
+                 * "\">"); request.appendHtml(action.getName());
+                 * request.appendHtml("</span>");
+                 */} else if (action.isUsable(IsisContext.getAuthenticationSession(), adapter, where).isVetoed()) {
+                request.appendHtml("<span class=\"disabled\" title=\"" + action.isUsable(IsisContext.getAuthenticationSession(), adapter, where).getReason() + "\">");
+                request.appendAsHtmlEncoded(action.getName());
+                request.appendHtml("</span>");
+            } else {
+                final String version = request.getContext().mapVersion(adapter);
+                if (action.getParameterCount() == 0 || (false /*action.isContributed() && action.getParameterCount() == 1*/ )) {
+                    ActionButton.write(request, adapter, action, parameters, version, "_generic." + Dispatcher.EXTENSION, null, null, null, null, null, null, null, null, null);
+                } else if (showForms) {
+                    final CreateFormParameter params = new CreateFormParameter();
+                    params.objectId = objectId;
+                    params.methodName = action.getId();
+                    params.forwardResultTo = "_generic." + Dispatcher.EXTENSION;
+                    params.buttonTitle = "OK";
+                    params.formTitle = action.getName();
+                    ActionForm.createForm(request, params, true);
+                } else {
+                    request.appendHtml("<a class=\"button\" href=\"" + view + "?_result=" + objectId + "&amp;_" + VERSION + "=" + version + "&amp;_" + METHOD + "=" + action.getId());
+                    if (cancelTo != null) {
+                        request.appendHtml("&amp;_cancel-to=");
+                        request.appendAsHtmlEncoded("cancel-to=\"" + cancelTo + "\"");
+                    }
+                    request.appendHtml("\" title=\"" + action.getDescription() + "\">");
+                    request.appendAsHtmlEncoded(action.getName() + "...");
+                    request.appendHtml("</a>");
+                }
+            }
+            request.appendHtml("</div>");
+        }
+    }
+
+    @Override
+    public String getName() {
+        return "methods";
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/2c7cfbfe/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/Parameter.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/Parameter.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/Parameter.java
new file mode 100644
index 0000000..69be5c5
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/Parameter.java
@@ -0,0 +1,47 @@
+/*
+ *  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.action;
+
+import org.apache.isis.viewer.scimpi.dispatcher.AbstractElementProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.BlockContent;
+import org.apache.isis.viewer.scimpi.dispatcher.TagOrderException;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.Request;
+
+public class Parameter extends AbstractElementProcessor {
+
+    @Override
+    public void process(final Request request) {
+        final BlockContent blockContent = request.getBlockContent();
+        if (!(blockContent instanceof ActionContent)) {
+            throw new TagOrderException(request);
+        }
+
+        final String field = request.getOptionalProperty(PARAMETER_NUMBER);
+        final String value = request.getRequiredProperty(VALUE);
+        final ActionContent block = (ActionContent) blockContent;
+        block.setParameter(field, value);
+    }
+
+    @Override
+    public String getName() {
+        return "parameter";
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/2c7cfbfe/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/RunAction.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/RunAction.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/RunAction.java
new file mode 100644
index 0000000..9610457
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/RunAction.java
@@ -0,0 +1,87 @@
+/*
+ *  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.action;
+
+import java.util.List;
+
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
+import org.apache.isis.viewer.scimpi.dispatcher.AbstractElementProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.ForbiddenException;
+import org.apache.isis.viewer.scimpi.dispatcher.context.RequestContext;
+import org.apache.isis.viewer.scimpi.dispatcher.context.RequestContext.Scope;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.Request;
+import org.apache.isis.viewer.scimpi.dispatcher.util.MethodsUtils;
+
+public class RunAction 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 Where where = Where.ANYWHERE;
+
+    @Override
+    public void process(final Request request) {
+        final RequestContext context = request.getContext();
+
+        final String objectId = request.getOptionalProperty(OBJECT);
+        final ObjectAdapter object = MethodsUtils.findObject(context, objectId);
+
+        final String methodName = request.getRequiredProperty(METHOD);
+        final ObjectAction action = MethodsUtils.findAction(object, methodName);
+
+        final String variableName = request.getOptionalProperty(RESULT_NAME);
+        final String scopeName = request.getOptionalProperty(SCOPE);
+
+        final ActionContent parameterBlock = new ActionContent(action);
+        request.setBlockContent(parameterBlock);
+        request.processUtilCloseTag();
+        final ObjectAdapter[] parameters = parameterBlock.getParameters(request);
+
+        if (!MethodsUtils.isVisibleAndUsable(object, action, where)) {
+            throw new ForbiddenException(action, ForbiddenException.VISIBLE_AND_USABLE);
+        }
+
+        // swap null parameter of the object's type to run a contributed method
+        if (false /*action.isContributed()*/) {
+            final List<ObjectActionParameter> parameterSpecs = action.getParameters();
+            for (int i = 0; i < parameters.length; i++) {
+                if (parameters[i] == null && object.getSpecification().isOfType(parameterSpecs.get(i).getSpecification())) {
+                    parameters[i] = object;
+                    break;
+                }
+            }
+        }
+
+        final Scope scope = RequestContext.scope(scopeName, Scope.REQUEST);
+        MethodsUtils.runMethod(context, action, object, parameters, variableName, scope);
+        request.popBlockContent();
+    }
+
+    @Override
+    public String getName() {
+        return "run-action";
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/2c7cfbfe/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/Services.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/Services.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/Services.java
new file mode 100644
index 0000000..2a621f1
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/Services.java
@@ -0,0 +1,67 @@
+/*
+ *  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.action;
+
+import java.util.List;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
+import org.apache.isis.viewer.scimpi.dispatcher.AbstractElementProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.Dispatcher;
+import org.apache.isis.viewer.scimpi.dispatcher.context.RequestContext.Scope;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.Request;
+import org.apache.isis.viewer.scimpi.dispatcher.view.field.InclusionList;
+
+public class Services extends AbstractElementProcessor {
+
+    @Override
+    public void process(final Request request) {
+        final boolean showForms = request.isRequested(FORMS, false);
+        final String view = request.getOptionalProperty(VIEW, "_generic_action." + Dispatcher.EXTENSION);
+        final String cancelTo = request.getOptionalProperty(CANCEL_TO);
+
+        final InclusionList inclusionList = new InclusionList();
+        request.setBlockContent(inclusionList);
+        request.processUtilCloseTag();
+
+        final List<ObjectAdapter> serviceAdapters = getPersistenceSession().getServices();
+        for (final ObjectAdapter adapter : serviceAdapters) {
+            final String serviceId = request.getContext().mapObject(adapter, Scope.REQUEST);
+            request.appendHtml("<div class=\"actions\">");
+            request.appendHtml("<h3>");
+            request.appendAsHtmlEncoded(adapter.titleString());
+            request.appendHtml("</h3>");
+            Methods.writeMethods(request, serviceId, adapter, showForms, inclusionList, view, cancelTo);
+            request.appendHtml("</div>");
+        }
+        request.popBlockContent();
+    }
+
+    @Override
+    public String getName() {
+        return "services";
+    }
+
+    private static PersistenceSession getPersistenceSession() {
+        return IsisContext.getPersistenceSession();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/2c7cfbfe/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/Collection.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/Collection.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/Collection.java
new file mode 100644
index 0000000..1002c9f
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/collection/Collection.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.dispatcher.AbstractElementProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.ResolveFieldUtil;
+import org.apache.isis.viewer.scimpi.dispatcher.ScimpiException;
+import org.apache.isis.viewer.scimpi.dispatcher.context.RequestContext;
+import org.apache.isis.viewer.scimpi.dispatcher.context.RequestContext.Scope;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.Request;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.Request.RepeatMarker;
+
+public class Collection extends AbstractElementProcessor {
+
+    @Override
+    public void process(final Request request) {
+        final RequestContext context = request.getContext();
+
+        ObjectAdapter collection;
+
+        final String field = request.getOptionalProperty(FIELD);
+        if (field != null) {
+            final String id = request.getOptionalProperty(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");
+            }
+            ResolveFieldUtil.resolveField(object, objectField);
+            collection = objectField.get(object);
+        } else {
+            final String id = request.getOptionalProperty(COLLECTION);
+            collection = context.getMappedObjectOrResult(id);
+        }
+
+        final RepeatMarker marker = request.createMarker();
+
+        final String variable = request.getOptionalProperty(ELEMENT_NAME);
+        final String scopeName = request.getOptionalProperty(SCOPE);
+        final Scope scope = RequestContext.scope(scopeName, Scope.REQUEST);
+        final String rowClassesList = request.getOptionalProperty(ROW_CLASSES, ODD_ROW_CLASS + "|" + EVEN_ROW_CLASS);
+        String[] rowClasses = new String[0];
+        if (rowClassesList != null) {
+            rowClasses = rowClassesList.split("[,|/]");
+        }
+
+        final CollectionFacet facet = collection.getSpecification().getFacet(CollectionFacet.class);
+        if (facet.size(collection) == 0) {
+            request.skipUntilClose();
+        } else {
+            final Iterator<ObjectAdapter> iterator = facet.iterator(collection);
+            int row = 0;
+            while (iterator.hasNext()) {
+                final ObjectAdapter element = iterator.next();
+                context.addVariable("row", "" + (row + 1), Scope.REQUEST);
+                if (rowClassesList != null) {
+                    context.addVariable("row-class", rowClasses[row % rowClasses.length], Scope.REQUEST);
+                }
+                context.addVariable(variable, context.mapObject(element, scope), scope);
+                marker.repeat();
+                request.processUtilCloseTag();
+                row++;
+            }
+        }
+    }
+
+    @Override
+    public String getName() {
+        return COLLECTION;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/2c7cfbfe/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/debug/Debug.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/debug/Debug.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/debug/Debug.java
new file mode 100644
index 0000000..c1a01b4
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/debug/Debug.java
@@ -0,0 +1,479 @@
+/*
+ *  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.debug;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import org.apache.isis.applib.filter.Filter;
+import org.apache.isis.applib.filter.Filters;
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.commons.debug.DebugHtmlString;
+import org.apache.isis.core.commons.debug.DebugString;
+import org.apache.isis.core.commons.debug.DebuggableWithTitle;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.spec.ActionType;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
+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.ObjectActionParameter;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
+import org.apache.isis.core.metamodel.util.Dump;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.scimpi.dispatcher.AbstractElementProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.Dispatcher;
+import org.apache.isis.viewer.scimpi.dispatcher.context.RequestContext;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.Request;
+
+public class Debug extends AbstractElementProcessor {
+
+    private final Dispatcher dispatcher;
+
+    public Debug(final Dispatcher dispatcher) {
+        this.dispatcher = dispatcher;
+    }
+
+    @Override
+    public void process(final Request request) {
+        if (request.getContext().isDebugDisabled()) {
+            return;
+        }
+        
+        final String type = request.getOptionalProperty(TYPE);
+
+        final boolean alwaysShow = request.isRequested("force", false);
+        if (type != null) {
+            if (type.equals("system")) {
+                displaySystem(request);
+            } else if (type.equals("session")) {
+                displaySession(request);
+            } else if (type.equals("test")) {
+                final DebugBuilder debug = new DebugHtmlString();
+                debug.appendTitle("Title");
+                debug.appendln("boolean", true);
+                debug.appendln("number", 213);
+                debug.startSection("Section 1");
+                debug.appendln("boolean", false);
+                debug.appendln("number", 12348);
+                debug.endSection();
+                debug.startSection("Section 2");
+                debug.appendln("boolean", false);
+                debug.appendln("number", 12348);
+                debug.appendTitle("Another title");
+                debug.appendln("boolean", false);
+                debug.appendln("number", 12348);
+                debug.endSection();
+
+                debug.startSection("Section 3");
+                debug.appendln("boolean", false);
+                debug.appendln("number", 89878);
+                debug.endSection();
+                debug.startSection("Subsection 2");
+                debug.appendln("boolean", false);
+                debug.appendln("number", 12348);
+                debug.endSection();
+
+                debug.startSection("Section 4");
+                debug.appendln("boolean", false);
+                debug.indent();
+                debug.appendln("boolean", false);
+                debug.appendln("number", 12348);
+                debug.unindent();
+                debug.appendln("number", 12348);
+                debug.appendPreformatted("code", "line 1\nline 2\nline 3");
+                debug.appendln("A lot of text etc.");
+                debug.endSection();
+
+                request.appendHtml(debug.toString());
+                //request.appendHtml("<pre>" + debug.toString() + "</pre>");
+                
+                debug.close();
+                
+            } else if (type.equals("variables")) {
+                displayVariables(request);
+            } else if (type.equals("dispatcher")) {
+                displayDispatcher(request);
+            } else if (type.equals("context")) {
+                displayContext(request);
+            } else if (type.equals("specifications")) {
+                listSpecifications(request);
+            } else if (type.equals("specification-for")) {
+                specificationFor(request);
+            } else if (type.equals("specification")) {
+                specification(request);
+            } else if (type.equals("specification-graph")) {
+                specificationGraph(request);
+            } else if (type.equals("object-graph")) {
+                objectGraph(request);
+
+            } else if (type.equals("object")) {
+                final String value = request.getOptionalProperty(VALUE);
+                final RequestContext context = request.getContext();
+                final ObjectAdapter object = context.getMappedObject(value);
+                final DebugString str = new DebugString();
+                Dump.adapter(object, str);
+                Dump.graph(object, IsisContext.getAuthenticationSession(), str);
+                request.appendHtml("<h2>" + object.getSpecification().getFullIdentifier() + "</h2>");
+                request.appendHtml("<pre class=\"debug\">" + str + "</pre>");
+            }
+
+        }
+
+        if (alwaysShow || request.getContext().getDebug() == RequestContext.Debug.ON) {
+
+            final RequestContext context = request.getContext();
+
+            final String id = request.getOptionalProperty("object");
+            if (id != null) {
+                final ObjectAdapter object = context.getMappedObject(id);
+                if (object instanceof DebuggableWithTitle) {
+                    final DebugString debug = new DebugString();
+                    ((DebuggableWithTitle) object).debugData(debug);
+                    request.appendHtml("<pre class=\"debug\">" + debug + "</pre>");
+                } else {
+                    request.appendHtml(object.toString());
+                }
+            }
+
+            final String variable = request.getOptionalProperty("variable");
+            if (variable != null) {
+                final Object object = context.getVariable(variable);
+                request.appendHtml(variable + " => " + (object == null ? "null" : object.toString()));
+            }
+
+            final String list = request.getOptionalProperty("list");
+            if (list != null) {
+                final DebugString debug = new DebugString();
+                context.append(debug, list);
+                request.appendHtml(debug.toString());
+            }
+
+            final String uri = request.getOptionalProperty("uri");
+            if (uri != null) {
+                request.appendHtml("<pre class=\"debug\">");
+                request.appendHtml(context.getUri());
+                request.appendHtml("</pre>");
+            }
+
+        }
+    }
+
+    protected void objectGraph(final Request request) {
+        final String id = request.getOptionalProperty(VALUE);
+        final ObjectAdapter object = request.getContext().getMappedObjectOrResult(id);
+        request.appendHtml("<h1>Object Graph - " + object + "</h1>");
+        request.appendHtml("<pre>");
+        final DebugBuilder debug = new DebugString();
+        Dump.graph(object, null, debug);
+        request.appendHtml(debug.toString());
+        request.appendHtml("</pre>");
+    }
+
+    protected void specificationFor(final Request request) {
+        final String id = request.getOptionalProperty(VALUE);
+        final ObjectAdapter object = request.getContext().getMappedObjectOrResult(id);
+        specification(request, object.getSpecification());
+    }
+
+    protected void specification(final Request request) {
+        final String name = request.getOptionalProperty(VALUE);
+        final ObjectSpecification spec = getSpecificationLoader().loadSpecification(name);
+        specification(request, spec);
+    }
+
+    private void specification(final Request request, final ObjectSpecification spec) {
+        request.appendHtml("<h1>Specification - " + spec.getFullIdentifier() + "</h1>");
+        request.appendHtml("<p><a href=\"./debug.shtml?type=specification-graph&value=" + spec.getFullIdentifier() + "\">Specification Graph</a></p>");
+        final DebugBuilder debug = new DebugHtmlString();
+        specification(spec, debug);
+        request.appendHtml(debug.toString());
+    }
+
+    protected void specificationGraph(final Request request) {
+        final String name = request.getOptionalProperty(VALUE);
+        final ObjectSpecification spec = getSpecificationLoader().loadSpecification(name);
+        request.appendHtml("<h1>Specification Graph - " + spec.getFullIdentifier() + "</h1>");
+        request.appendHtml("<p><a href=\"./debug.shtml?type=specification&value=" + spec.getFullIdentifier() + "\">Full Specification</a></p>");
+        request.appendHtml("<pre>");
+        final DebugBuilder debug = new DebugString();
+        debug.appendln(spec.getFullIdentifier());
+        debug.indent();
+        specificationGraph(spec, debug, new ArrayList<ObjectSpecification>());
+        debug.unindent();
+        request.appendHtml(debug.toString());
+        request.appendHtml("</pre>");
+    }
+
+    private void displayContext(final Request request) {
+        request.appendHtml("<h1>Context</h1>");
+        final DebugHtmlString debugString = new DebugHtmlString();
+        request.getContext().append(debugString);
+        debugString.close();
+        request.appendHtml(debugString.toString());
+    }
+
+    private void displayDispatcher(final Request request) {
+        request.appendHtml("<h1>Dispatcher</h1>");
+        final DebugHtmlString debugString = new DebugHtmlString();
+        dispatcher.debug(debugString);
+        debugString.close();
+        request.appendHtml(debugString.toString());
+    }
+
+    protected void displayVariables(final Request request) {
+        request.appendHtml("<h1>Variables</h1>");
+        final DebugHtmlString debug = new DebugHtmlString();
+        final RequestContext context = request.getContext();
+        context.append(debug, "variables");
+        debug.close();
+        request.appendHtml(debug.toString());
+    }
+
+    protected void displaySystem(final Request request) {
+        request.appendHtml("<h1>System</h1>");
+        final DebuggableWithTitle[] debugItems = IsisContext.debugSystem();
+        for (final DebuggableWithTitle debug : debugItems) {
+            final DebugHtmlString debugBuffer = new DebugHtmlString();
+            debugBuffer.startSection(debug.debugTitle());
+            debug.debugData(debugBuffer);
+            debugBuffer.endSection();
+            debugBuffer.close();
+            request.appendHtml(debugBuffer.toString());
+        }
+    }
+
+    protected void displaySession(final Request request) {
+        request.appendHtml("<h1>Session</h1>");
+        final DebuggableWithTitle[] debugItems = IsisContext.debugSession();
+        for (final DebuggableWithTitle debug : debugItems) {
+            final DebugHtmlString debugBuffer = new DebugHtmlString();
+            debugBuffer.startSection(debug.debugTitle());
+            debug.debugData(debugBuffer);
+            debugBuffer.endSection();
+            debugBuffer.close();
+            request.appendHtml(debugBuffer.toString());
+        }
+    }
+
+    protected void listSpecifications(final Request request) {
+        request.appendHtml("<h1>Specifications</h1>");
+        final List<ObjectSpecification> fullIdentifierList = new ArrayList<ObjectSpecification>(getSpecificationLoader().allSpecifications());
+        Collections.sort(fullIdentifierList, ObjectSpecification.COMPARATOR_SHORT_IDENTIFIER_IGNORE_CASE);
+        final DebugHtmlString debug = new DebugHtmlString();
+        for (final ObjectSpecification spec : fullIdentifierList) {
+            final String name = spec.getSingularName();
+            debug.appendln(name, specificationLink(spec));
+        }
+        debug.close();
+        request.appendHtml(debug.toString());
+    }
+
+    private String specificationLink(final ObjectSpecification specification) {
+        if (specification == null) {
+            return "none";
+        } else {
+            final String name = specification.getFullIdentifier();
+            return "<a href=\"./debug.shtml?type=specification&value=" + name + "\">" + name + "</a>";
+        }
+    }
+
+    protected SpecificationLoaderSpi getSpecificationLoader() {
+        return IsisContext.getSpecificationLoader();
+    }
+
+    @Override
+    public String getName() {
+        return "debug";
+    }
+
+    private void specificationGraph(final ObjectSpecification spec, final DebugBuilder view, final ArrayList<ObjectSpecification> visited) {
+        final List<ObjectAssociation> fields = new ArrayList<ObjectAssociation>(spec.getAssociations(Contributed.EXCLUDED));
+        Collections.sort(fields, new Comparator<ObjectAssociation>() {
+            @Override
+            public int compare(final ObjectAssociation o1, final ObjectAssociation o2) {
+                return o1.getName().compareTo(o2.getName());
+            }
+        });
+        for (int i = 0; i < fields.size(); i++) {
+            final ObjectAssociation field = fields.get(i);
+            final ObjectSpecification specification = field.getSpecification();
+            if (!specification.isValue()) {
+                final boolean contains = visited.contains(specification);
+                final String aggregated = specification.isParented() ? "++" : "";
+                view.appendln(aggregated + field.getName() + "  (<a href=\"./debug.shtml?type=specification-graph&value=" + specification.getFullIdentifier() + "\">" + specification.getFullIdentifier() + "</a>" + (contains ? "..." : "") + ")");
+                if (!contains) {
+                    visited.add(specification);
+                    view.indent();
+                    specificationGraph(specification, view, visited);
+                    view.unindent();
+                }
+            }
+        }
+
+    }
+
+    private void specification(final ObjectSpecification spec, final DebugBuilder view) {
+        view.startSection("Summary");
+        view.appendln("Hash code", "#" + Integer.toHexString(spec.hashCode()));
+        view.appendln("ID", spec.getIdentifier());
+        view.appendln("Full name", spec.getFullIdentifier());
+        view.appendln("Short name", spec.getShortIdentifier());
+        view.appendln("Singular name", spec.getSingularName());
+        view.appendln("Plural name", spec.getPluralName());
+        view.appendln("Description", spec.getDescription());
+
+        view.appendln("Type", "?");
+        view.appendln("Value/aggregated", String.valueOf(!spec.isValueOrIsParented()));
+
+        view.appendln("Parent specification", specificationLink(spec.superclass()));
+        specificationClasses(view, "Child specifications", spec.subclasses());
+        specificationClasses(view, "Implemented interfaces", spec.interfaces());
+        speficationFacets(view, spec);
+
+        final List<ObjectAssociation> fields = spec.getAssociations(Contributed.EXCLUDED);
+        specificationMembers(view, "Fields", fields);
+        final List<ObjectAction> userActions = spec.getObjectActions(ActionType.USER, Contributed.INCLUDED, Filters.<ObjectAction>any());
+        specificationMembers(view, "User Actions", userActions);
+        specificationMembers(view, "Exploration Actions", spec.getObjectActions(ActionType.EXPLORATION, Contributed.INCLUDED, Filters.<ObjectAction>any()));
+        specificationMembers(view, "Prototype Actions", spec.getObjectActions(ActionType.PROTOTYPE, Contributed.INCLUDED, Filters.<ObjectAction>any()));
+        specificationMembers(view, "Debug Actions", spec.getObjectActions(ActionType.DEBUG, Contributed.INCLUDED, Filters.<ObjectAction>any()));
+        view.endSection();
+
+        view.startSection("Fields");
+        for (int i = 0; i < fields.size(); i++) {
+            final ObjectAssociation field = fields.get(i);
+            view.appendTitle("<span id=\"" + field.getId() + "\"><em>Field:</em> " + field.getId() + "</span>");
+            view.appendln("ID", field.getIdentifier());
+            view.appendln("Short ID", field.getId());
+            view.appendln("Name", field.getName());
+            view.appendln("Specification", specificationLink(field.getSpecification()));
+
+            view.appendln("Type", field.isOneToManyAssociation() ? "Collection" : field.isOneToOneAssociation() ? "Object" : "Unknown");
+            view.appendln("Flags", (field.isAlwaysHidden() ? "" : "Visible ") + (field.isNotPersisted() ? "Not-Persisted " : " ") + (field.isMandatory() ? "Mandatory " : ""));
+
+            speficationFacets(view, field);
+        }
+        view.endSection();
+
+        view.startSection("Actions");
+        for (int i = 0; i < userActions.size(); i++) {
+            final ObjectAction action = userActions.get(i);
+            view.appendTitle("<span id=\"" + action.getId() + "\"><em>Action:</em> " + action.getId() + "</span>");
+            view.appendln("ID", action.getIdentifier());
+            view.appendln("Short ID", action.getId());
+            view.appendln("Name", action.getName());
+            view.appendln("Specification", specificationLink(action.getSpecification()));
+
+            view.appendln("On type", specificationLink(action.getOnType()));
+
+            final ObjectSpecification returnType = action.getReturnType();
+            view.appendln("Returns", returnType == null ? "VOID" : specificationLink(returnType));
+
+            speficationFacets(view, action);
+
+            final List<ObjectActionParameter> parameters = action.getParameters();
+            if (parameters.size() == 0) {
+                view.appendln("Parameters", "none");
+            } else {
+                final StringBuffer buffer = new StringBuffer();
+                final List<ObjectActionParameter> p = action.getParameters();
+                for (int j = 0; j < parameters.size(); j++) {
+                    buffer.append(p.get(j).getName());
+                    buffer.append(" (");
+                    buffer.append(specificationLink(parameters.get(j).getSpecification()));
+                    buffer.append(")");
+                    view.appendln("Parameters", buffer.toString());
+
+                    view.indent();
+                    final Class<? extends Facet>[] parameterFacets = p.get(j).getFacetTypes();
+                    for (final Class<? extends Facet> parameterFacet : parameterFacets) {
+                        view.append(p.get(j).getFacet(parameterFacet).toString());
+                    }
+                    view.unindent();
+                }
+            }
+        }
+    }
+
+    private void specificationClasses(final DebugBuilder view, final String label, final List<ObjectSpecification> subclasses) {
+        final StringBuffer buffer = new StringBuffer();
+        if (subclasses.size() == 0) {
+            buffer.append("none");
+        } else {
+            for (int i = 0; i < subclasses.size(); i++) {
+                buffer.append(specificationLink(subclasses.get(i)) + "<br>");
+            }
+        }
+        view.appendln(label, buffer.toString());
+    }
+
+    private void specificationMembers(final DebugBuilder view, final String label, final List<? extends ObjectMember> members) {
+        final StringBuffer buffer = new StringBuffer();
+        if (members.size() == 0) {
+            buffer.append("none");
+        } else {
+            for (int i = 0; i < members.size(); i++) {
+                final ObjectMember member = members.get(i);
+                buffer.append("<a href=\"#" + members.get(i).getId() + "\">" + member.getId() + "</a>   <small>");
+                buffer.append(member.isAlwaysHidden() ? "" : "Visible ");
+                if (member.isPropertyOrCollection()) {
+                    buffer.append(((ObjectAssociation) member).isNotPersisted() ? "Not-Persisted " : " ");
+                    buffer.append(((ObjectAssociation) member).isMandatory() ? "Mandatory " : "");
+                }
+                buffer.append("</small></a><br>");
+            }
+        }
+        view.appendln(label, buffer.toString());
+    }
+
+    private void speficationFacets(final DebugBuilder view, final FacetHolder facetHolder) {
+        final List<Facet> facets = facetHolder.getFacets(new Filter<Facet>() {
+            @Override
+            public boolean accept(final Facet facet) {
+                return true;
+            }
+        });
+        final StringBuffer buffer = new StringBuffer();
+        if (facets == null || facets.size() == 0) {
+            buffer.append("none");
+        } else {
+            Collections.sort(facets, new Comparator<Facet>() {
+                @Override
+                public int compare(final Facet o1, final Facet o2) {
+                    final String facetType1 = o1.facetType().getName();
+                    final String facetType2 = o2.facetType().getName();
+                    return facetType1.substring(facetType1.lastIndexOf('.') + 1).compareTo(facetType2.substring(facetType2.lastIndexOf('.') + 1));
+                }
+            });
+            for (final Facet facet : facets) {
+                final String facetType = facet.facetType().getName();
+                buffer.append("<span class=\"facet-type\">" + facetType.substring(facetType.lastIndexOf('.') + 1) + "</span>:  " + facet + "<br>");
+            }
+        }
+        view.appendln("Facets", buffer.toString());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/2c7cfbfe/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/debug/DebugAccessCheck.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/debug/DebugAccessCheck.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/debug/DebugAccessCheck.java
new file mode 100644
index 0000000..796faf0
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/debug/DebugAccessCheck.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.debug;
+
+import org.apache.isis.viewer.scimpi.dispatcher.AbstractElementProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.ForbiddenException;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.Request;
+
+public class DebugAccessCheck extends AbstractElementProcessor {
+
+    @Override
+    public void process(final Request request) {
+        if (request.getContext().isDebugDisabled()) {
+            throw new ForbiddenException("Debug is disabled");
+        }
+    }
+
+    @Override
+    public String getName() {
+        return "debug-access-check";
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/2c7cfbfe/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/debug/DebugCollectionView.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/debug/DebugCollectionView.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/debug/DebugCollectionView.java
new file mode 100644
index 0000000..9137783
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/debug/DebugCollectionView.java
@@ -0,0 +1,110 @@
+/*
+ *  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.debug;
+
+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.AbstractObjectProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.Request;
+import org.apache.isis.viewer.scimpi.dispatcher.view.HelpLink;
+import org.apache.isis.viewer.scimpi.dispatcher.view.field.LinkedObject;
+
+public class DebugCollectionView extends AbstractObjectProcessor {
+
+    @Override
+    public void process(final Request request, final ObjectAdapter object) {
+        final String cls = request.getOptionalProperty(CLASS, "form");
+        final String classString = " class=\"" + cls + "\"";
+        String title = request.getOptionalProperty(FORM_TITLE);
+        final String oddRowClass = request.getOptionalProperty(ODD_ROW_CLASS);
+        final String evenRowClass = request.getOptionalProperty(EVEN_ROW_CLASS);
+        final boolean showIcons = request.isRequested(SHOW_ICON, true);
+
+    }
+
+    private void write(final Request request, final ObjectAdapter object, final List<ObjectAssociation> fields,
+        final LinkedObject[] linkFields, final String classString, final String title, final String oddRowClass,
+        final String evenRowClass, final boolean showIcons) {
+        request.appendHtml("<div" + classString + ">");
+        if (title != null) {
+            request.appendHtml("<div class=\"title\">");
+            request.appendAsHtmlEncoded(title);
+            request.appendHtml("</div>");
+            HelpLink.append(request, object.getSpecification().getDescription(), object.getSpecification().getHelp());
+        }
+     /*   
+        final List<ObjectAssociation> fields =
+                tag.includedFields(object.getSpecification().getAssociations(
+                    ObjectAssociationFilters.STATICALLY_VISIBLE_ASSOCIATIONS));
+            final LinkedObject[] linkFields = tag.linkedFields(fields);
+
+            String linkAllView = request.getOptionalProperty(LINK);
+            if (linkAllView != null) {
+                linkAllView = request.getContext().fullUriPath(linkAllView);
+                for (int i = 0; i < linkFields.length; i++) {
+                    final boolean isObject = fields.get(i).isOneToOneAssociation();
+                    final boolean isNotParseable =
+                        !fields.get(i).getSpecification().containsFacet(ParseableFacet.class);
+                    linkFields[i] = isObject && isNotParseable ? new LinkedObject(linkAllView) : null;
+                }
+            }
+
+        
+        
+        int row = 1;
+        for (int i = 0; i < fields.size(); i++) {
+            final ObjectAssociation field = fields.get(i);
+            if (ignoreField(field)) {
+                continue;
+            }
+            if (field.isVisible(IsisContext.getAuthenticationSession(), object).isVetoed()) {
+                continue;
+            }
+
+            final String description =
+                field.getDescription().equals("") ? "" : "title=\"" + field.getDescription() + "\"";
+            String cls;
+            if (row++ % 2 == 1) {
+                cls = " class=\"field " + (oddRowClass == null ? ODD_ROW_CLASS : oddRowClass) + "\"";
+            } else {
+                cls = " class=\"field " + (evenRowClass == null ? EVEN_ROW_CLASS : evenRowClass) + "\"";
+            }
+            request.appendHtml("<div " + cls + description + "><span class=\"label\">");
+            request.appendAsHtmlEncoded(field.getName());
+            request.appendHtml(":</span>");
+            final LinkedObject linkedObject = linkFields[i];
+            addField(request, object, field, linkedObject, showIcons);
+            HelpLink.append(request, field.getDescription(), field.getHelp());
+            request.appendHtml("</div>");
+        }
+        */
+        request.appendHtml("</div>");
+        
+    }
+
+
+    @Override
+    public String getName() {
+        return "debug-collection";
+    }
+
+}