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:32 UTC

[03/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/simple/AbstractConditionalBlock.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/AbstractConditionalBlock.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/AbstractConditionalBlock.java
new file mode 100644
index 0000000..dc5b39a
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/AbstractConditionalBlock.java
@@ -0,0 +1,565 @@
+/*
+ *  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.simple;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.applib.filter.Filters;
+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.facets.actcoll.typeof.TypeOfFacet;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
+import org.apache.isis.core.metamodel.spec.ActionType;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.Contributed;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+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.processor.Request;
+import org.apache.isis.viewer.scimpi.dispatcher.util.MethodsUtils;
+
+public abstract class AbstractConditionalBlock extends AbstractElementProcessor {
+
+    private static Map<String, Test> tests = new HashMap<String, Test>();
+
+    static {
+        addNormal(new TestHasRole(), "has-role");
+        addNegated(new TestHasRole(), "has-not-role");
+
+        addNormal(new TestVariableExists(), "variable-exists");
+        addNegated(new TestVariableExists(), "variable-missing");
+        addNormal(new TestVariableTrue(), "variable-true");
+        addNegated(new TestVariableTrue(), "variable-false");
+
+        addNormal(new TestObjectPersistent(), "object-persistent");
+        addNegated(new TestObjectPersistent(), "object-transient");
+        addNormal(new TestObjectType(), "object-type");
+        /*
+         * addNormal(new TestObjectIs(), "object-is"); addNegated(new
+         * TestObjectIs(), "object-is-not"); addNormal(new TestObjectType(),
+         * "object-type"); addNormal(new TestObjectType(),
+         * "object-title-equals"); addNegated(new TestObjectType(),
+         * "object-title-not-equals"); addNormal(new TestObjectType(),
+         * "object-title-contains"); addNegated(new TestObjectType(),
+         * "object-title-not-contains");
+         */
+        addNormal(new TestCollectionFull(), "collection-full");
+        addNegated(new TestCollectionFull(), "collection-empty");
+        addNormal(new TestCollectionType(), "collection-type");
+        // addNormal(new TestCollectionSize(), "collection-size-equal");
+        // addNormal(new TestCollectionSize(), "collection-size-less-than");
+        // addNormal(new TestCollectionSize(), "collection-size-greater-than");
+
+        addNormal(new TestFieldValue(), "test-field");
+        addNegated(new TestFieldValue(), "test-field");
+           
+        addNormal(new TestFieldExists(), "field-exists");
+        addNegated(new TestFieldExists(), "field-missing");
+        addNormal(new TestFieldVisible(), "field-visible");
+        addNegated(new TestFieldVisible(), "field-hidden");
+        addNormal(new TestFieldEditable(), "field-editable");
+        addNegated(new TestFieldEditable(), "field-not-editable");
+        addNormal(new TestFieldType(), "field-type");
+        addNormal(new TestFieldSet(), "field-set");
+        addNegated(new TestFieldSet(), "field-empty");
+        // empty/set etc
+
+        addNormal(new TestMethodExists(), "method-exists");
+        addNegated(new TestMethodExists(), "method-missing");
+        addNormal(new TestMethodVisible(), "method-visible");
+        addNegated(new TestMethodVisible(), "method-hidden");
+        addNormal(new TestMethodUseable(), "method-useable");
+        addNegated(new TestMethodUseable(), "method-not-useable");
+
+    }
+
+    private static void addNegated(final Test test, final String name) {
+        test.name = name;
+        test.negateResult = true;
+        tests.put(name, test);
+    }
+
+    private static void addNormal(final Test test, final String name) {
+        test.name = name;
+        tests.put(name, test);
+    }
+
+    @Override
+    public void process(final Request request) {
+        final String id = request.getOptionalProperty(OBJECT);
+
+        boolean checkMade = false;
+        boolean allConditionsMet = true;
+
+        final String[] propertyNames = request.getAttributes().getPropertyNames(new String[] { "object", "collection" });
+        for (final String propertyName : propertyNames) {
+            boolean result;
+            if (propertyName.equals("set")) {
+                result = request.isPropertySet("set");
+            } else {
+                final Test test = tests.get(propertyName);
+                if (test == null) {
+                    throw new ScimpiException("No such test: " + propertyName);
+                }
+                final String attributeValue = request.getOptionalProperty(propertyName, false);
+                result = test.test(request, attributeValue, id);
+                if (test.negateResult) {
+                    result = !result;
+                }
+            }
+            checkMade = true;
+            allConditionsMet &= result;
+        }
+
+        /*
+         * 
+         * // Check variables if
+         * (request.isPropertySpecified("variable-exists")) { boolean
+         * valuePresent = request.isPropertySet("variable-exists"); checkMade =
+         * true; allConditionsMet &= valuePresent; }
+         * 
+         * String variable = request.getOptionalProperty("variable-true"); if
+         * (variable != null) { String value = (String)
+         * request.getContext().getVariable(variable); checkMade = true;
+         * allConditionsMet &= Attributes.isTrue(value); }
+         * 
+         * variable = request.getOptionalProperty("variable-equals"); if
+         * (variable != null) { String value = (String)
+         * request.getContext().getVariable(variable); checkMade = true;
+         * allConditionsMet &= variable.equals(value); }
+         */
+        // Check Object
+
+        /*
+         * // Check Collection String collection =
+         * request.getOptionalProperty("collection-" + TYPE); if (collection !=
+         * null) { ObjectAdapter object =
+         * MethodsUtils.findObject(request.getContext(), collection); Class<?>
+         * cls = forClass(request); TypeOfFacet facet =
+         * object.getSpecification().getFacet(TypeOfFacet.class); boolean
+         * hasType = object != null && (cls == null ||
+         * cls.isAssignableFrom(facet.value())); checkMade = true;
+         * allConditionsMet &= hasType;; }
+         * 
+         * collection = request.getOptionalProperty("collection-" + "empty"); if
+         * (collection != null) { ObjectAdapter object =
+         * MethodsUtils.findObject(request.getContext(), id); CollectionFacet
+         * facet = object.getSpecification().getFacet(CollectionFacet.class);
+         * boolean isEmpty = facet != null && facet.size(object) == 0;
+         * processTags(isEmpty, request); allConditionsMet &= isEmpty; }
+         */
+
+        // Check Methods
+        /*
+         * String method = request.getOptionalProperty(METHOD + "-exists"); if
+         * (method != null) { ObjectAdapter object =
+         * MethodsUtils.findObject(request.getContext(), id); List<? extends
+         * ObjectAction> objectActions =
+         * object.getSpecification().getObjectActions(ActionType.USER); boolean
+         * methodExists = false; for (ObjectAction objectAssociation :
+         * objectActions) { if (objectAssociation.getId().equals(method)) {
+         * methodExists = true; break; } } checkMade = true; allConditionsMet &=
+         * methodExists; }
+         * 
+         * method = request.getOptionalProperty(METHOD + "-visible"); if (method
+         * != null) { ObjectAdapter object =
+         * MethodsUtils.findObject(request.getContext(), id); // TODO needs to
+         * work irrespective of parameters ObjectAction objectAction =
+         * object.getSpecification().getObjectAction(ActionType.USER, method,
+         * ObjectSpecification.EMPTY_LIST); Consent visible =
+         * objectAction.isVisible(IsisContext.getAuthenticationSession(),
+         * object); checkMade = true; allConditionsMet &= visible.isAllowed(); }
+         * 
+         * method = request.getOptionalProperty(METHOD + "-usable"); if (method
+         * != null) { ObjectAdapter object =
+         * MethodsUtils.findObject(request.getContext(), id); // TODO needs to
+         * work irrespective of parameters ObjectAction objectAction =
+         * object.getSpecification().getObjectAction(ActionType.USER, method,
+         * ObjectSpecification.EMPTY_LIST); Consent usable =
+         * objectAction.isUsable(IsisContext.getAuthenticationSession(),
+         * object); checkMade = true; allConditionsMet &= usable.isAllowed(); }
+         * 
+         * 
+         * // Check Fields String field = request.getOptionalProperty(FIELD +
+         * "-exists"); if (field != null) { ObjectAdapter object =
+         * MethodsUtils.findObject(request.getContext(), id); List<? extends
+         * ObjectAssociation> objectFields =
+         * object.getSpecification().getAssociations(); boolean fieldExists =
+         * false; for (ObjectAssociation objectAssociation : objectFields) { if
+         * (objectAssociation.getId().equals(field)) { fieldExists = true;
+         * break; } } checkMade = true; allConditionsMet &= fieldExists; }
+         * 
+         * field = request.getOptionalProperty(FIELD + "-visible"); if (field !=
+         * null) { ObjectAdapter object =
+         * MethodsUtils.findObject(request.getContext(), id); ObjectAssociation
+         * objectField = object.getSpecification().getAssociation(field);
+         * Consent visible =
+         * objectField.isVisible(IsisContext.getAuthenticationSession(),
+         * object); checkMade = true; allConditionsMet &= visible.isAllowed(); }
+         * 
+         * field = request.getOptionalProperty(FIELD + "-editable"); if (field
+         * != null) { ObjectAdapter object =
+         * MethodsUtils.findObject(request.getContext(), id); ObjectAssociation
+         * objectField = object.getSpecification().getAssociation(field);
+         * Consent usable =
+         * objectField.isUsable(IsisContext.getAuthenticationSession(), object);
+         * checkMade = true; allConditionsMet &= usable.isAllowed(); }
+         * 
+         * field = request.getOptionalProperty(FIELD + "-empty"); if (field !=
+         * null) { ObjectAdapter object =
+         * MethodsUtils.findObject(request.getContext(), id); ObjectAssociation
+         * objectField = object.getSpecification().getAssociation(field);
+         * IsisContext.getPersistenceSession().resolveField(object,
+         * objectField); ObjectAdapter fld = objectField.get(object); if (fld ==
+         * null) { checkMade = true; allConditionsMet &= true; } else {
+         * CollectionFacet facet =
+         * fld.getSpecification().getFacet(CollectionFacet.class); boolean
+         * isEmpty = facet != null && facet.size(fld) == 0; processTags(isEmpty,
+         * request); allConditionsMet &= isEmpty; } }
+         * 
+         * field = request.getOptionalProperty(FIELD + "-set"); if (field !=
+         * null) { ObjectAdapter object =
+         * MethodsUtils.findObject(request.getContext(), id); ObjectAssociation
+         * objectField = object.getSpecification().getAssociation(field);
+         * IsisContext.getPersistenceSession().resolveField(object,
+         * objectField); ObjectAdapter fld = objectField.get(object); if (fld ==
+         * null) { throw new ScimpiException("No object for field-set " +
+         * field); } Object fieldValue = fld.getObject(); if (fieldValue
+         * instanceof Boolean) { checkMade = true; allConditionsMet &=
+         * ((Boolean) fieldValue).booleanValue(); } else { checkMade = true;
+         * allConditionsMet &= true; } }
+         */
+
+        // Check User
+        /*
+         * String hasRole = request.getOptionalProperty("has-role"); if (hasRole
+         * != null) { AuthenticationSession session =
+         * IsisContext.getSession().getAuthenticationSession(); List<String>
+         * roles = session.getRoles(); boolean hasMatchingRole = false; for
+         * (String role : roles) { if (role.equals(hasRole.trim())) {
+         * hasMatchingRole = true; break; } } checkMade = true; allConditionsMet
+         * &= hasMatchingRole; }
+         */
+
+        final String persistent = request.getOptionalProperty("persistent");
+        if (persistent != null) {
+            final ObjectAdapter object = request.getContext().getMappedObjectOrResult(persistent);
+            checkMade = true;
+            allConditionsMet &= object.representsPersistent();
+        }
+        /*
+         * String type = request.getOptionalProperty(TYPE); if (type != null) {
+         * ObjectAdapter object = MethodsUtils.findObject(request.getContext(),
+         * id); Class<?> cls = forClass(request); boolean hasType = object !=
+         * null && (cls == null ||
+         * cls.isAssignableFrom(object.getObject().getClass())); checkMade =
+         * true; allConditionsMet &= hasType;; }
+         */
+        if (request.isPropertySpecified("empty")) {
+            if (request.isPropertySet("empty")) {
+                final String collection = request.getOptionalProperty("empty");
+                if (collection != null) {
+                    final ObjectAdapter object = request.getContext().getMappedObjectOrResult(collection);
+                    final CollectionFacet facet = object.getSpecification().getFacet(CollectionFacet.class);
+                    checkMade = true;
+                    allConditionsMet &= facet.size(object) == 0;
+                }
+            } else {
+                checkMade = true;
+                allConditionsMet &= true;
+            }
+        }
+
+        if (request.isPropertySpecified("set")) {
+            final boolean valuePresent = request.isPropertySet("set");
+            checkMade = true;
+            allConditionsMet &= valuePresent;
+        }
+
+        if (checkMade) {
+            processTags(allConditionsMet, request);
+        } else {
+            throw new ScimpiException("No condition in " + getName());
+        }
+    }
+
+    protected abstract void processTags(boolean isSet, Request request);
+
+}
+
+abstract class Test {
+    String name;
+    boolean negateResult;
+
+    abstract boolean test(Request request, String attributeName, String targetId);
+
+    protected Class<?> forClass(final String className) {
+        Class<?> cls = null;
+        if (className != null) {
+            try {
+                cls = Class.forName(className);
+            } catch (final ClassNotFoundException e) {
+                throw new ScimpiException("No class for " + className, e);
+            }
+        }
+        return cls;
+    }
+    
+    protected ObjectAction findMethod(final String attributeName, final ObjectAdapter object) {
+        final ObjectAction objectAction = object.getSpecification().getObjectAction(ActionType.USER, attributeName, ObjectSpecification.EMPTY_LIST);
+        if (objectAction == null) {
+            throw new ScimpiException("No such method found in " + object.getSpecification().getIdentifier().getClassName() + " : " + attributeName);
+        }
+        return objectAction;
+    }
+
+    protected ObjectAssociation findProperty(final String attributeName, final ObjectAdapter object) {
+        final ObjectAssociation objectField = object.getSpecification().getAssociation(attributeName);
+        if (objectField == null) {
+            throw new ScimpiException("No such property found in " + object.getSpecification().getIdentifier().getClassName() + ": " + attributeName);
+        }
+        return objectField;
+    }
+
+}
+
+class TestVariableExists extends Test {
+    @Override
+    boolean test(final Request request, final String attributeName, final String targetId) {
+        Object variable = request.getContext().getVariable(attributeName);
+        if (variable instanceof String && ((String) variable).equals("")) {
+            return false;
+        }
+        return variable != null;
+    }
+}
+
+class TestVariableTrue extends Test {
+    @Override
+    boolean test(final Request request, final String attributeName, final String targetId) {
+        final Object variable = request.getContext().getVariable(attributeName);
+        final Boolean value = variable instanceof Boolean ? (Boolean) variable : Boolean.valueOf((String) variable);
+        return value != null && value.booleanValue();
+    }
+}
+
+class TestObjectPersistent extends Test {
+    @Override
+    boolean test(final Request request, final String attributeName, final String targetId) {
+        final ObjectAdapter object = request.getContext().getMappedObjectOrResult(attributeName);
+        return object.representsPersistent();
+    }
+}
+
+class TestObjectType extends TestObjectPersistent {
+    @Override
+    boolean test(final Request request, final String attributeName, final String targetId) {
+        final ObjectAdapter object = MethodsUtils.findObject(request.getContext(), targetId);
+        final Class<?> cls = forClass(attributeName);
+        final boolean hasType = object != null && (cls == null || cls.isAssignableFrom(object.getObject().getClass()));
+        return hasType;
+    }
+}
+
+class TestCollectionType extends Test {
+    @Override
+    boolean test(final Request request, final String attributeName, final String targetId) {
+        final ObjectAdapter object = MethodsUtils.findObject(request.getContext(), targetId);
+        final Class<?> cls = forClass(attributeName);
+        final TypeOfFacet facet = object.getSpecification().getFacet(TypeOfFacet.class);
+        final boolean hasType = object != null && (cls == null || cls.isAssignableFrom(facet.value()));
+        return hasType;
+    }
+}
+
+class TestCollectionFull extends Test {
+    @Override
+    boolean test(final Request request, final String attributeName, final String targetId) {
+        final ObjectAdapter object = MethodsUtils.findObject(request.getContext(), attributeName);
+        final CollectionFacet facet = object.getSpecification().getFacet(CollectionFacet.class);
+        final boolean isEmpty = facet != null && facet.size(object) == 0;
+        return !isEmpty;
+    }
+}
+
+class TestMethodExists extends Test {
+    @Override
+    boolean test(final Request request, final String attributeName, final String targetId) {
+        final ObjectAdapter object = MethodsUtils.findObject(request.getContext(), targetId);
+        final List<? extends ObjectAction> objectActions = object.getSpecification().getObjectActions(ActionType.USER, Contributed.INCLUDED, Filters.<ObjectAction>any());
+        boolean methodExists = false;
+        for (final ObjectAction objectAssociation : objectActions) {
+            if (objectAssociation.getId().equals(attributeName)) {
+                methodExists = true;
+                break;
+            }
+        }
+        return methodExists;
+    }
+}
+
+class TestMethodVisible extends Test {
+    @Override
+    boolean test(final Request request, final String attributeName, final String targetId) {
+        final ObjectAdapter object = MethodsUtils.findObject(request.getContext(), targetId);
+        // TODO needs to work irrespective of parameters
+        final ObjectAction objectAction = findMethod(attributeName, object);
+        final Consent visible = objectAction.isVisible(IsisContext.getAuthenticationSession(), object, Where.ANYWHERE);
+        return visible.isAllowed();
+    }
+}
+
+class TestMethodUseable extends Test {
+    @Override
+    boolean test(final Request request, final String attributeName, final String targetId) {
+        final ObjectAdapter object = MethodsUtils.findObject(request.getContext(), targetId);
+        // TODO needs to work irrespective of parameters
+        final ObjectAction objectAction = findMethod(attributeName, object);
+        final Consent usable = objectAction.isUsable(IsisContext.getAuthenticationSession(), object, Where.ANYWHERE);
+        return usable.isAllowed();
+    }
+}
+
+class TestFieldExists extends Test {
+    @Override
+    boolean test(final Request request, final String attributeName, final String targetId) {
+        final ObjectAdapter object = MethodsUtils.findObject(request.getContext(), targetId);
+        final List<? extends ObjectAssociation> objectFields = object.getSpecification().getAssociations(Contributed.EXCLUDED);
+        boolean fieldExists = false;
+        for (final ObjectAssociation objectAssociation : objectFields) {
+            if (objectAssociation.getId().equals(attributeName)) {
+                fieldExists = true;
+                break;
+            }
+        }
+        return fieldExists;
+    }
+}
+
+class TestFieldVisible extends Test {
+    @Override
+    boolean test(final Request request, final String attributeName, final String targetId) {
+        final ObjectAdapter object = MethodsUtils.findObject(request.getContext(), targetId);
+        final ObjectAssociation objectField = findProperty(attributeName, object);
+        final Consent visible = objectField.isVisible(IsisContext.getAuthenticationSession(), object, Where.ANYWHERE);
+        return visible.isAllowed();
+    }
+}
+
+class TestFieldEditable extends Test {
+    @Override
+    boolean test(final Request request, final String attributeName, final String targetId) {
+        final ObjectAdapter object = MethodsUtils.findObject(request.getContext(), targetId);
+        final ObjectAssociation objectField = findProperty(attributeName, object);
+        final Consent usable = objectField.isUsable(IsisContext.getAuthenticationSession(), object, Where.ANYWHERE);
+        return usable.isAllowed();
+    }
+}
+
+class TestFieldType extends Test {
+    @Override
+    boolean test(final Request request, final String attributeName, final String targetId) {
+        final ObjectAdapter object = MethodsUtils.findObject(request.getContext(), targetId);
+        final Class<?> cls = forClass(attributeName);
+        final boolean hasType = object != null && (cls == null || cls.isAssignableFrom(object.getObject().getClass()));
+        return hasType;
+    }
+}
+
+class TestFieldSet extends Test {
+    @Override
+    boolean test(final Request request, final String attributeName, final String targetId) {
+        final ObjectAdapter object = MethodsUtils.findObject(request.getContext(), targetId);
+        final ObjectAssociation objectField = findProperty(attributeName, object);
+
+        ResolveFieldUtil.resolveField(object, objectField);
+        final ObjectAdapter fld = objectField.get(object);
+        if (fld != null) {
+            final Object fieldValue = fld.getObject();
+            if (fieldValue instanceof Boolean) {
+                return ((Boolean) fieldValue).booleanValue();
+            } else if (fld.getSpecification().containsFacet(CollectionFacet.class)) {
+                final CollectionFacet facet = fld.getSpecification().getFacet(CollectionFacet.class);
+                final boolean isEmpty = facet != null && facet.size(fld) == 0;
+                return !isEmpty;
+            } else {
+                return true;
+            }
+        }
+        return false;
+    }
+}
+
+class TestFieldValue extends Test {
+    @Override
+    boolean test(Request request, String attributeName, String targetId) {
+        int pos = attributeName.indexOf("==");
+        // TODO test for other comparators
+        // TODO fail properly if none found
+        String fieldName = attributeName.substring(0, pos);
+        String fieldValue = attributeName.substring(pos + 2);
+        
+        final ObjectAdapter object = MethodsUtils.findObject(request.getContext(), targetId);
+        final ObjectAssociation objectField = findProperty(fieldName, object);
+        ResolveFieldUtil.resolveField(object, objectField);
+        final ObjectAdapter fld = objectField.get(object);
+        
+        // TODO test for reference or value
+        final ObjectAdapter object2 = MethodsUtils.findObject(request.getContext(), fieldValue);
+        
+        if (fld == object2) {
+            return true;
+        }
+        return false;
+    }
+    
+}
+
+class TestHasRole extends Test {
+    @Override
+    boolean test(final Request request, final String attributeName, final String targetId) {
+        final String[] requiredRoles = attributeName.split("\\|");
+        final AuthenticationSession session = IsisContext.getSession().getAuthenticationSession();
+        final List<String> sessionRoles = session.getRoles();
+        for (final String sessionRole : sessionRoles) {
+            for (final String requiredRole : requiredRoles) {
+                if (requiredRole.trim().equals(sessionRole)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+}
+
+class TestSet extends Test {
+    @Override
+    boolean test(final Request request, final String attributeName, final String targetId) {
+        final boolean valuePresent = request.isPropertySet("set");
+        return valuePresent;
+    }
+}
+

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/simple/AbstractLink.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/AbstractLink.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/AbstractLink.java
new file mode 100644
index 0000000..b6798be
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/AbstractLink.java
@@ -0,0 +1,121 @@
+/*
+ *  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.simple;
+
+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.dispatcher.AbstractElementProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.ForbiddenException;
+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.util.MethodsUtils;
+
+public abstract class AbstractLink extends AbstractElementProcessor {
+
+    @Override
+    public void process(final Request request) {
+        final String title = request.getOptionalProperty(FORM_TITLE);
+        final String name = request.getOptionalProperty(NAME);
+        final boolean showAsButton = request.isRequested("show-as-button", false);
+        final String linkClass = request.getOptionalProperty(CLASS, showAsButton ? "button" : defaultLinkClass());
+        final String containerClass = request.getOptionalProperty(CONTAINER_CLASS, "action");
+        final String object = request.getOptionalProperty(OBJECT);
+        final RequestContext context = request.getContext();
+        String objectId = object != null ? object : (String) context.getVariable(RequestContext.RESULT);
+        ObjectAdapter adapter = MethodsUtils.findObject(context, objectId);
+
+        // REVIEW this is common used code
+        final String fieldName = request.getOptionalProperty(FIELD);
+        if (fieldName != null) {
+            final ObjectAssociation field = adapter.getSpecification().getAssociation(fieldName);
+            if (field == null) {
+                throw new ScimpiException("No field " + fieldName + " in " + adapter.getSpecification().getFullIdentifier());
+            }
+            
+            // 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
+            final Where where = Where.ANYWHERE;
+            
+            if (field.isVisible(IsisContext.getAuthenticationSession(), adapter, where).isVetoed()) {
+                throw new ForbiddenException(field, ForbiddenException.VISIBLE);
+            }
+            ResolveFieldUtil.resolveField(adapter, field);
+            adapter = field.get(adapter);
+            if (adapter != null) {
+                objectId = context.mapObject(adapter, Scope.INTERACTION);
+            }
+        }
+
+        if (adapter != null && valid(request, adapter)) {
+            final String variable = request.getOptionalProperty("param-name", RequestContext.RESULT);
+            final String variableSegment = variable + "=" + objectId;
+
+            String view = request.getOptionalProperty(VIEW);
+            if (view == null) {
+                view = defaultView();
+            }
+            view = context.fullUriPath(view);
+            final String classSegment = " class=\"" + linkClass + "\"";
+            final String titleSegment = title == null ? "" : (" title=\"" + title + "\"");
+            String additionalSegment = additionalParameters(request);
+            additionalSegment = additionalSegment == null ? "" : "&amp;" + additionalSegment;
+            if (showAsButton) {
+                request.appendHtml("<div class=\"" + containerClass + "\">");
+            }
+            request.appendHtml("<a" + classSegment + titleSegment + " href=\"" + view + "?" + variableSegment + context.encodedInteractionParameters() + additionalSegment + "\">");
+            request.pushNewBuffer();
+            request.processUtilCloseTag();
+            final String buffer = request.popBuffer();
+            if (buffer.trim().length() > 0) {
+                request.appendHtml(buffer);
+            } else {
+                request.appendAsHtmlEncoded(linkLabel(name, adapter));
+            }
+            request.appendHtml("</a>");
+            if (showAsButton) {
+                request.appendHtml("</div>");
+            }
+        } else {
+            request.skipUntilClose();
+        }
+    }
+
+    private String defaultLinkClass() {
+        return "action";
+    }
+
+    protected abstract String linkLabel(String name, ObjectAdapter object);
+
+    protected String additionalParameters(final Request request) {
+        return null;
+    }
+
+    protected abstract boolean valid(Request request, ObjectAdapter adapter);
+
+    protected abstract String defaultView();
+}

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/simple/BlockDefine.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/BlockDefine.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/BlockDefine.java
new file mode 100644
index 0000000..cea5d11
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/BlockDefine.java
@@ -0,0 +1,42 @@
+/*
+ *  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.simple;
+
+import org.apache.isis.viewer.scimpi.dispatcher.AbstractElementProcessor;
+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 BlockDefine extends AbstractElementProcessor {
+
+    @Override
+    public String getName() {
+        return "block";
+    }
+
+    @Override
+    public void process(final Request request) {
+        final String name = request.getOptionalProperty(NAME, "unamed");
+        final RepeatMarker start = request.createMarker();
+        request.skipUntilClose();
+        request.getContext().addVariable("_block-" + name, start, Scope.REQUEST);
+    }
+
+}

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/simple/BlockUse.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/BlockUse.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/BlockUse.java
new file mode 100644
index 0000000..efd6128
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/BlockUse.java
@@ -0,0 +1,46 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.viewer.scimpi.dispatcher.view.simple;
+
+import org.apache.isis.viewer.scimpi.dispatcher.AbstractElementProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.Request;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.Request.RepeatMarker;
+
+public class BlockUse extends AbstractElementProcessor {
+
+    @Override
+    public String getName() {
+        return "use-block";
+    }
+
+    @Override
+    public void process(final Request request) {
+        final String name = request.getOptionalProperty(NAME, "unamed");
+        request.closeEmpty();
+        final RepeatMarker end = request.createMarker();
+
+        final RepeatMarker marker = (RepeatMarker) request.getContext().getVariable("_block-" + name);
+        marker.repeat();
+
+        request.processUtilCloseTag();
+        end.repeat();
+    }
+
+}

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/simple/Commit.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/Commit.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/Commit.java
new file mode 100644
index 0000000..4106fd9
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/Commit.java
@@ -0,0 +1,45 @@
+/*
+ *  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.simple;
+
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
+import org.apache.isis.viewer.scimpi.dispatcher.AbstractElementProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.Request;
+
+public class Commit extends AbstractElementProcessor {
+
+    @Override
+    public String getName() {
+        return "commit";
+    }
+
+    @Override
+    public void process(final Request request) {
+        // Note - the session will have changed since the earlier call if a user
+        // has logged in or out in the action
+        // processing above.
+        final IsisTransactionManager transactionManager = IsisContext.getPersistenceSession().getTransactionManager();
+        if (transactionManager.getTransaction().getState().canCommit()) {
+            transactionManager.endTransaction();
+            transactionManager.startTransaction();
+        }
+    }
+
+}

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/simple/ContentTag.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/ContentTag.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/ContentTag.java
new file mode 100644
index 0000000..ddda339
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/ContentTag.java
@@ -0,0 +1,36 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.scimpi.dispatcher.view.simple;
+
+import org.apache.isis.viewer.scimpi.dispatcher.ElementProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.Request;
+
+public class ContentTag implements ElementProcessor {
+
+    @Override
+    public String getName() {
+        return "content";
+    }
+
+    @Override
+    public void process(final Request request) {
+        request.appendHtml("<!--  apply content  -->");
+    }
+
+}

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/simple/CookieValue.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/CookieValue.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/CookieValue.java
new file mode 100644
index 0000000..09e56b0
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/CookieValue.java
@@ -0,0 +1,46 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.viewer.scimpi.dispatcher.view.simple;
+
+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;
+
+public class CookieValue extends AbstractElementProcessor {
+
+    @Override
+    public void process(final Request request) {
+        String name = request.getRequiredProperty(NAME);
+        String resultName = request.getOptionalProperty(RESULT_NAME, name);
+        final String scopeName = request.getOptionalProperty(SCOPE);
+        final Scope scope = RequestContext.scope(scopeName, Scope.REQUEST);
+        
+        String cookieString = request.getContext().getCookie(name);
+        
+        request.appendDebug("    " + resultName + " (" + scope + ") set to " + cookieString + " from cookie " + name);
+        request.getContext().addVariable(resultName, cookieString, scope);
+    }
+
+    @Override
+    public String getName() {
+        return "cookie-value";
+    }
+}

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/simple/DefaultValue.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/DefaultValue.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/DefaultValue.java
new file mode 100644
index 0000000..2cd9593
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/DefaultValue.java
@@ -0,0 +1,52 @@
+/*
+ *  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.simple;
+
+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;
+
+public class DefaultValue extends AbstractElementProcessor {
+
+    @Override
+    public void process(final Request request) {
+        // String sourceObjectId = objectOrResult(request);
+        final String variableName = request.getRequiredProperty(NAME);
+        final String defaultValue = request.getOptionalProperty(VALUE);
+        final String scopeName = request.getOptionalProperty(SCOPE);
+        final Scope scope = RequestContext.scope(scopeName, Scope.REQUEST);
+
+        final RequestContext context = request.getContext();
+        final Object currentValue = context.getVariable(variableName);
+        if (currentValue == null) {
+            request.appendDebug("     " + variableName + " set to " + defaultValue + " (" + scope + ")");
+            context.addVariable(variableName, defaultValue, scope);
+        } else {
+            request.appendDebug("     " + variableName + " alreadt set to " + currentValue);
+        }
+    }
+
+    @Override
+    public String getName() {
+        return "default";
+    }
+
+}

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/simple/EditLink.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/EditLink.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/EditLink.java
new file mode 100644
index 0000000..ab43eb6
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/EditLink.java
@@ -0,0 +1,71 @@
+/*
+ *  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.simple;
+
+import java.util.List;
+
+import org.apache.isis.applib.annotation.When;
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facets.object.immutable.ImmutableFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.Contributed;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.scimpi.dispatcher.Dispatcher;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.Request;
+
+public class EditLink extends AbstractLink {
+
+    // 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
+    protected boolean valid(final Request request, final ObjectAdapter adapter) {
+        final ObjectSpecification specification = adapter.getSpecification();
+        final AuthenticationSession session = IsisContext.getAuthenticationSession();
+        final List<ObjectAssociation> visibleFields = specification.getAssociations(Contributed.EXCLUDED, ObjectAssociation.Filters.dynamicallyVisible(session, adapter, where));
+        final ImmutableFacet facet = specification.getFacet(ImmutableFacet.class);
+        final boolean isImmutable = facet != null && facet.when() == When.ALWAYS;
+        final boolean isImmutableOncePersisted = facet != null && facet.when() == When.ONCE_PERSISTED && adapter.representsPersistent();
+        return visibleFields.size() > 0 && !isImmutable && !isImmutableOncePersisted;
+    }
+
+    @Override
+    protected String linkLabel(final String name, final ObjectAdapter object) {
+        return "edit";
+    }
+
+    @Override
+    protected String defaultView() {
+        return Dispatcher.GENERIC + Dispatcher.EDIT + "." + Dispatcher.EXTENSION;
+    }
+
+    @Override
+    public String getName() {
+        return "edit-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/simple/EndSession.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/EndSession.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/EndSession.java
new file mode 100644
index 0000000..1a37f99
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/EndSession.java
@@ -0,0 +1,36 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.viewer.scimpi.dispatcher.view.simple;
+
+import org.apache.isis.viewer.scimpi.dispatcher.AbstractElementProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.Request;
+
+public class EndSession extends AbstractElementProcessor {
+
+    @Override
+    public void process(final Request request) {
+        request.getContext().endHttpSession();
+    }
+
+    @Override
+    public String getName() {
+        return "end-session";
+    }
+}

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/simple/Forward.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/Forward.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/Forward.java
new file mode 100644
index 0000000..e63ec92
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/Forward.java
@@ -0,0 +1,37 @@
+/*
+ *  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.simple;
+
+import org.apache.isis.viewer.scimpi.dispatcher.AbstractElementProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.Request;
+
+public class Forward extends AbstractElementProcessor {
+
+    @Override
+    public String getName() {
+        return "forward";
+    }
+
+    @Override
+    public void process(final Request request) {
+        final String view = request.getRequiredProperty(VIEW);
+        request.getContext().forward(view);
+    }
+
+}

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/simple/GetCookie.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/GetCookie.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/GetCookie.java
new file mode 100644
index 0000000..f58b13f
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/GetCookie.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.simple;
+
+import org.apache.isis.viewer.scimpi.dispatcher.AbstractElementProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.Request;
+
+public class GetCookie extends AbstractElementProcessor {
+
+    @Override
+    public void process(final Request request) {
+        final String name = request.getRequiredProperty("name");
+        final String cookie = request.getContext().getCookie(name);
+
+        request.appendHtml(cookie);
+    }
+
+    @Override
+    public String getName() {
+        return "get-cookie";
+    }
+}

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/simple/Import.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/Import.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/Import.java
new file mode 100644
index 0000000..1b66290
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/Import.java
@@ -0,0 +1,37 @@
+/*
+ *  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.simple;
+
+import org.apache.isis.viewer.scimpi.dispatcher.AbstractElementProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.Request;
+
+public class Import extends AbstractElementProcessor {
+
+    @Override
+    public void process(final Request request) {
+        request.appendHtml("<!-- " + " import " + request.getOptionalProperty("file") + " -->");
+    }
+
+    @Override
+    public String getName() {
+        return "import";
+    }
+
+}

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/simple/InitializeFromCookie.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/InitializeFromCookie.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/InitializeFromCookie.java
new file mode 100644
index 0000000..1e3f47e
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/InitializeFromCookie.java
@@ -0,0 +1,80 @@
+/*
+ *  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.simple;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.runtime.persistence.ObjectNotFoundException;
+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;
+
+public class InitializeFromCookie extends AbstractElementProcessor {
+    private static final String SEVEN_DAYS = Integer.toString(60 * 24 * 7);
+
+    @Override
+    public void process(final Request request) {
+        final String name = request.getRequiredProperty(NAME);
+
+        final RequestContext context = request.getContext();
+        if (context.getVariable(name) != null) {
+            request.skipUntilClose();
+        } else {
+            final String scopeName = request.getOptionalProperty(SCOPE);
+            final Scope scope = RequestContext.scope(scopeName, Scope.SESSION);
+
+            final String cookieName = request.getOptionalProperty("cookie", name);
+            final String cookieValue = context.getCookie(cookieName);
+            boolean hasObject;
+            if (cookieValue != null) {
+                try {
+                    context.getMappedObject(cookieValue);
+                    hasObject = true;
+                } catch (final ObjectNotFoundException e) {
+                    hasObject = false;
+                }
+            } else {
+                hasObject = false;
+            }
+
+            if (hasObject) {
+                request.skipUntilClose();
+                context.addVariable(name, cookieValue, scope);
+            } else {
+                final String expiresString = request.getOptionalProperty("expires", SEVEN_DAYS);
+                request.pushNewBuffer();
+                request.processUtilCloseTag();
+                request.popBuffer();
+                final String id = (String) context.getVariable(RequestContext.RESULT);
+                final ObjectAdapter variable = context.getMappedObject(id);
+                if (variable != null) {
+                    context.addCookie(cookieName, id, Integer.valueOf(expiresString));
+                    context.addVariable(name, id, scope);
+                }
+            }
+        }
+    }
+
+    @Override
+    public String getName() {
+        return "initialize-from-cookie";
+    }
+
+}

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/simple/InitializeFromResult.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/InitializeFromResult.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/InitializeFromResult.java
new file mode 100644
index 0000000..375fdd2
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/InitializeFromResult.java
@@ -0,0 +1,77 @@
+/*
+ *  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.simple;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.viewer.scimpi.dispatcher.AbstractElementProcessor;
+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;
+
+public class InitializeFromResult extends AbstractElementProcessor {
+
+    @Override
+    public void process(final Request request) {
+        disallowSourceAndDefault(request);
+        final String sourceObjectId = objectOrResult(request);
+        final Class<?> cls = forClass(request);
+        final String variableName = request.getRequiredProperty(NAME);
+        final String defaultObjectId = request.getOptionalProperty(DEFAULT);
+        final String scopeName = request.getOptionalProperty(SCOPE);
+        final Scope scope = RequestContext.scope(scopeName, Scope.REQUEST);
+
+        final RequestContext context = request.getContext();
+        final ObjectAdapter sourceObject = context.getMappedObject(sourceObjectId);
+        final boolean isSourceSet = sourceObject != null;
+        final boolean isSourceAssignable = isSourceSet && (cls == null || cls.isAssignableFrom(sourceObject.getObject().getClass()));
+        if (isSourceAssignable) {
+            request.appendDebug("     " + variableName + " set to " + sourceObjectId + " (" + scope + ")");
+            context.addVariable(variableName, sourceObjectId, scope);
+        } else {
+            request.appendDebug("     " + variableName + " set to " + sourceObjectId + " (" + scope + ")");
+            if (defaultObjectId != null) {
+                context.addVariable(variableName, defaultObjectId, scope);
+            }
+            context.changeScope(variableName, scope);
+        }
+    }
+
+    private String objectOrResult(final Request request) {
+        final String sourceObjectId = request.getOptionalProperty(OBJECT);
+        if (sourceObjectId == null) {
+            return (String) request.getContext().getVariable(RequestContext.RESULT);
+        } else {
+            return sourceObjectId;
+        }
+    }
+
+    private void disallowSourceAndDefault(final Request request) {
+        if (request.getOptionalProperty(DEFAULT) != null && request.getOptionalProperty(OBJECT) != null) {
+            throw new ScimpiException("Cannot specify both " + OBJECT + " and " + DEFAULT + " for the " + getName() + " element");
+        }
+    }
+
+    @Override
+    public String getName() {
+        return "initialize";
+    }
+
+}

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/simple/Localization.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/Localization.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/Localization.java
new file mode 100644
index 0000000..fe1474b
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/Localization.java
@@ -0,0 +1,64 @@
+/*
+ *  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.simple;
+
+import java.util.Locale;
+import java.util.TimeZone;
+
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.scimpi.dispatcher.AbstractElementProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.Request;
+
+/**
+ * Displays the localization data for the current user.
+ */
+public class Localization extends AbstractElementProcessor {
+
+    @Override
+    public void process(final Request request) {
+        request.closeEmpty();
+
+        org.apache.isis.applib.profiles.Localization localization = IsisContext.getLocalization();
+        if (localization != null) {
+            Locale locale = localization.getLocale();
+            String country = locale.getDisplayName();
+         //   country = locale.toString();
+            String timeZone = localization.getTimeZone().getDisplayName();
+            
+            request.appendAsHtmlEncoded(country + ", " + timeZone);
+        } else {
+            request.appendAsHtmlEncoded("No localization data!");
+        }
+        
+        Locale locale = Locale.getDefault();
+        String country = locale.getDisplayName();
+      //  country = locale.toString();
+        String timeZone = TimeZone.getDefault().getDisplayName();
+        
+        request.appendAsHtmlEncoded("\n (Default " + country + ", " + timeZone +")");
+
+    }
+
+    @Override
+    public String getName() {
+        return "alpha-localization";
+    }
+
+}

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/simple/Mark.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/Mark.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/Mark.java
new file mode 100644
index 0000000..febafb6
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/Mark.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.simple;
+
+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;
+
+public class Mark extends AbstractElementProcessor {
+
+    // TODO the return points should be pushed on to a stack so that there is
+    // traceable history.
+    @Override
+    public void process(final Request request) {
+        // String name = request.getOptionalProperty(NAME);
+        final RequestContext context = request.getContext();
+        context.addVariable("_return-to", context.getUri(), Scope.SESSION);
+    }
+
+    @Override
+    public String getName() {
+        return "mark";
+    }
+
+}

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/simple/NewActionLink.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/NewActionLink.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/NewActionLink.java
new file mode 100644
index 0000000..5929f81
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/NewActionLink.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.simple;
+
+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.viewer.scimpi.dispatcher.Dispatcher;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.Request;
+import org.apache.isis.viewer.scimpi.dispatcher.util.MethodsUtils;
+
+public class NewActionLink extends AbstractLink {
+
+    // REVIEW: confirm this rendering context
+    private final Where where = Where.OBJECT_FORMS;
+
+    @Override
+    protected boolean valid(final Request request, final ObjectAdapter object) {
+        final String method = request.getRequiredProperty(METHOD);
+        final ObjectAction action = MethodsUtils.findAction(object, method);
+        return MethodsUtils.isVisibleAndUsable(object, action, where);
+    }
+
+    @Override
+    protected String linkLabel(final String name, final ObjectAdapter object) {
+        return "run";
+    }
+
+    @Override
+    protected String defaultView() {
+        return "_generic_action." + Dispatcher.EXTENSION;
+    }
+
+    @Override
+    protected String additionalParameters(final Request request) {
+        final String method = request.getRequiredProperty(METHOD);
+        return "method=" + method;
+    }
+
+    @Override
+    public String getName() {
+        return "new-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/simple/ObjectLink.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/ObjectLink.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/ObjectLink.java
new file mode 100644
index 0000000..f2726bf
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/ObjectLink.java
@@ -0,0 +1,68 @@
+/*
+ *  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.simple;
+
+import java.util.List;
+
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.feature.Contributed;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.scimpi.dispatcher.Dispatcher;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.Request;
+
+public class ObjectLink extends AbstractLink {
+
+    // 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
+    protected boolean valid(final Request request, final ObjectAdapter object) {
+        final AuthenticationSession session = IsisContext.getAuthenticationSession();
+        final List<ObjectAssociation> visibleFields = object.getSpecification().getAssociations(Contributed.EXCLUDED, ObjectAssociation.Filters.dynamicallyVisible(session, object, where));
+        return visibleFields.size() > 0;
+    }
+
+    @Override
+    protected String linkLabel(final String name, final ObjectAdapter object) {
+        if (name == null) {
+            return object.titleString();
+        } else {
+            return name;
+        }
+    }
+
+    @Override
+    protected String defaultView() {
+        return Dispatcher.GENERIC + "." + Dispatcher.EXTENSION;
+    }
+
+    @Override
+    public String getName() {
+        return "object-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/simple/PageTitle.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/PageTitle.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/PageTitle.java
new file mode 100644
index 0000000..10c3b13
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/PageTitle.java
@@ -0,0 +1,35 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.viewer.scimpi.dispatcher.view.simple;
+
+import org.apache.isis.viewer.scimpi.dispatcher.context.RequestContext.Scope;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.Request;
+
+public class PageTitle extends Variable {
+    @Override
+    public void process(final Request request) {
+        process(request, "title", null, null, false, Scope.REQUEST);
+    }
+
+    @Override
+    public String getName() {
+        return "page-title";
+    }
+}

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/simple/Redirect.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/Redirect.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/Redirect.java
new file mode 100644
index 0000000..6f3b0d8
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/simple/Redirect.java
@@ -0,0 +1,37 @@
+/*
+ *  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.simple;
+
+import org.apache.isis.viewer.scimpi.dispatcher.AbstractElementProcessor;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.Request;
+
+public class Redirect extends AbstractElementProcessor {
+
+    @Override
+    public String getName() {
+        return "redirect";
+    }
+
+    @Override
+    public void process(final Request request) {
+        final String view = request.getRequiredProperty(VIEW);
+        request.getContext().redirectTo(view);
+    }
+
+}