You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by rm...@apache.org on 2013/03/24 18:45:20 UTC

[23/24] Restructuring Scimpi to remove dependencies and enable easier testing.

http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/debug/DebugUsersView.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/debug/DebugUsersView.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/debug/DebugUsersView.java
deleted file mode 100644
index 3243d92..0000000
--- a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/debug/DebugUsersView.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- *  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.debug;
-
-import org.apache.isis.viewer.scimpi.dispatcher.processor.TagProcessor;
-import org.apache.isis.viewer.scimpi.dispatcher.view.AbstractElementProcessor;
-
-public class DebugUsersView extends AbstractElementProcessor {
-
-    @Override
-    public String getName() {
-        return "debug-users";
-    }
-
-    @Override
-    public void process(final TagProcessor tagProcessor) {
-        final String view = tagProcessor.getContext().getContextPath() + tagProcessor.getContext().getResourceParentPath() + tagProcessor.getContext().getResourceFile();
-
-        tagProcessor.appendHtml("<form class=\"generic action\" action=\"debug-user.app\" method=\"post\" accept-charset=\"ISO-8859-1\">\n");
-        tagProcessor.appendHtml("<div class=\"title\">Add Debug User</div>\n");
-        tagProcessor.appendHtml("<div class=\"field\"><label>User Name:</label><input type=\"text\" name=\"name\" size=\"30\" /></div>\n");
-        tagProcessor.appendHtml("<input type=\"hidden\" name=\"method\" value=\"add\" />\n");
-        tagProcessor.appendHtml("<input type=\"hidden\" name=\"view\" value=\"" + view + "\" />\n");
-        tagProcessor.appendHtml("<input class=\"button\" type=\"submit\" value=\"Add User\" />\n");
-        tagProcessor.appendHtml("</form>\n");
-
-        tagProcessor.appendHtml("<table class=\"debug\">\n<tr><th class=\"title\">Name</th><th class=\"title\"></th></tr>\n");
-        for (final String name : tagProcessor.getContext().getDebugUsers()) {
-            tagProcessor.appendHtml("<tr><th>" + name + "</th><th><a href=\"debug-user.app?method=remove&name=" + name + "&view=" + view + " \">remove</a></th></tr>\n");
-        }
-        tagProcessor.appendHtml("</table>\n");
-    }
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/debug/ErrorDetails.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/debug/ErrorDetails.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/debug/ErrorDetails.java
deleted file mode 100644
index 0459390..0000000
--- a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/debug/ErrorDetails.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- *  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.debug;
-
-import org.apache.isis.viewer.scimpi.dispatcher.processor.TagProcessor;
-import org.apache.isis.viewer.scimpi.dispatcher.view.AbstractElementProcessor;
-
-
-public class ErrorDetails extends AbstractElementProcessor {
-
-    public String getName() {
-        return "error-details";
-    }
-
-    public void process(final TagProcessor tagProcessor) {
-        tagProcessor.appendHtml(tagProcessor.getContext().getErrorDetails());
-    }
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/debug/ErrorMessage.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/debug/ErrorMessage.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/debug/ErrorMessage.java
deleted file mode 100644
index dfc48cf..0000000
--- a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/debug/ErrorMessage.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- *  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.debug;
-
-import org.apache.isis.viewer.scimpi.dispatcher.processor.TagProcessor;
-import org.apache.isis.viewer.scimpi.dispatcher.view.AbstractElementProcessor;
-
-
-public class ErrorMessage extends AbstractElementProcessor {
-
-    public String getName() {
-        return "error-message";
-    }
-
-    public void process(final TagProcessor tagProcessor) {
-        tagProcessor.appendAsHtmlEncoded(tagProcessor.getContext().getErrorMessage());
-    }
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/debug/ErrorReference.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/debug/ErrorReference.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/debug/ErrorReference.java
deleted file mode 100644
index 49e0b24..0000000
--- a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/debug/ErrorReference.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- *  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.debug;
-
-import org.apache.isis.viewer.scimpi.dispatcher.processor.TagProcessor;
-import org.apache.isis.viewer.scimpi.dispatcher.view.AbstractElementProcessor;
-
-
-public class ErrorReference extends AbstractElementProcessor {
-
-    public String getName() {
-        return "error-reference";
-    }
-
-    public void process(final TagProcessor tagProcessor) {
-        tagProcessor.appendAsHtmlEncoded(tagProcessor.getContext().getErrorReference());
-    }
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/form/FieldEditState.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/form/FieldEditState.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/form/FieldEditState.java
new file mode 100644
index 0000000..db13178
--- /dev/null
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/form/FieldEditState.java
@@ -0,0 +1,57 @@
+/*
+ *  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.form;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+
+public class FieldEditState {
+    private final String entry;
+    private String reason;
+    private ObjectAdapter value;
+
+    public FieldEditState(final String entry) {
+        this.entry = entry;
+    }
+
+    public void setError(final String reason) {
+        this.reason = reason;
+    }
+
+    public boolean isEntryValid() {
+        return reason == null;
+    }
+
+    public String getEntry() {
+        return entry;
+    }
+
+    public String getError() {
+        return reason;
+    }
+
+    public ObjectAdapter getValue() {
+        return value;
+    }
+
+    public void setValue(final ObjectAdapter value) {
+        this.value = value;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/form/FormState.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/form/FormState.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/form/FormState.java
new file mode 100644
index 0000000..2bc81ec
--- /dev/null
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/form/FormState.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.form;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+public class FormState {
+    private final Map<String, FieldEditState> fields = new HashMap<String, FieldEditState>();
+    private String error;
+    private String formId;
+
+    public FieldEditState createField(final String name, final String entry) {
+        final FieldEditState fieldEditState = new FieldEditState(entry);
+        fields.put(name, fieldEditState);
+        return fieldEditState;
+    }
+
+    public boolean isValid() {
+        final Iterator<FieldEditState> iterator = fields.values().iterator();
+        while (iterator.hasNext()) {
+            if (!iterator.next().isEntryValid()) {
+                return false;
+            }
+        }
+        return error == null;
+    }
+
+    public FieldEditState getField(final String name) {
+        return fields.get(name);
+    }
+
+    public void setError(final String error) {
+        this.error = error;
+    }
+
+    public String getError() {
+        return error;
+    }
+
+    public void setForm(final String formId) {
+        this.formId = formId;
+    }
+
+    public boolean isForForm(final String formId) {
+        return this.formId == null || this.formId.equals(formId);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/Attributes.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/Attributes.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/Attributes.java
deleted file mode 100644
index 86fd17e..0000000
--- a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/Attributes.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- *  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.processor;
-
-import java.util.Enumeration;
-import java.util.Vector;
-
-import org.htmlparser.Attribute;
-import org.htmlparser.nodes.TagNode;
-
-import org.apache.isis.viewer.scimpi.dispatcher.context.PropertyException;
-import org.apache.isis.viewer.scimpi.dispatcher.context.Request;
-
-public class Attributes {
-    private static final String TRUE = " true yes on ";
-    private static final String FALSE = " false no off ";
-    private final TagNode tagNode;
-    private final Request context;
-
-    public Attributes(final TagNode tagNode, final Request context) {
-        this.tagNode = tagNode;
-        this.context = context;
-    }
-
-    public boolean isPropertySet(final String name) {
-        final String attribute = tagNode.getAttribute(name);
-        int end = attribute.length() - 1;
-        final int pos = attribute.indexOf(':');
-        end = pos == -1 ? end : pos;
-        final String variabelName = attribute.substring(2, end);
-        final Object value = context.getVariable(variabelName);
-        return value != null;
-        // return attribute != null &&
-        // !context.replaceVariables(attribute).equals("");
-    }
-
-    public boolean isPropertySpecified(final String name) {
-        final String attribute = tagNode.getAttribute(name);
-        return attribute != null;
-    }
-
-    public String getOptionalProperty(final String name, final boolean ensureVariablesExists) {
-        return getOptionalProperty(name, null, ensureVariablesExists);
-    }
-
-    public String getOptionalProperty(final String name, final String defaultValue, final boolean ensureVariablesExists) {
-        final String attribute = tagNode.getAttribute(name);
-        return attribute == null ? defaultValue : context.replaceVariables(attribute);
-    }
-
-    public String getRequiredProperty(final String name, final boolean ensureVariablesExists) {
-        final String attribute = tagNode.getAttribute(name);
-        if (attribute == null) {
-            throw new RequiredPropertyException("Missing property: " + name);
-        } else if (attribute.equals("")) {
-            throw new RequiredPropertyException("Property not set: " + name);
-        } else {
-            return context.replaceVariables(attribute);
-        }
-    }
-
-    public String[] getPropertyNames(final String excluding[]) {
-        final Vector attributes = tagNode.getAttributesEx();
-        final String[] names = new String[attributes.size()];
-        int i = 0;
-        names: for (final Enumeration e = attributes.elements(); e.hasMoreElements();) {
-            final String name = ((Attribute) e.nextElement()).getName();
-            if (name == null) {
-                continue;
-            }
-            for (int j = 0; j < excluding.length; j++) {
-                if (name.equals(excluding[j])) {
-                    continue names;
-                }
-            }
-            if (tagNode.getAttribute(name) != null) {
-                names[i++] = name;
-            }
-        }
-
-        final String[] array = new String[i];
-        System.arraycopy(names, 0, array, 0, i);
-        return array;
-    }
-
-    @Override
-    public String toString() {
-        return tagNode.toHtml(); // getAttributesEx().toString();
-    }
-
-    public boolean isRequested(final String name) {
-        return isRequested(name, false);
-    }
-
-    public boolean isRequested(final String name, final boolean defaultValue) {
-        final String flag = getOptionalProperty(name, true);
-        if (flag == null) {
-            return defaultValue;
-        } else {
-            return isTrue(flag);
-        }
-    }
-
-    public static boolean isTrue(final String flag) {
-        final String value = " " + flag.toLowerCase().trim() + " ";
-        if (TRUE.indexOf(value) >= 0) {
-            return true;
-        } else if (FALSE.indexOf(value) >= 0) {
-            return false;
-        } else {
-            throw new PropertyException("Illegal flag value: " + flag);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/BlockContent.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/BlockContent.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/BlockContent.java
index 0d91bdf..561bf5e 100644
--- a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/BlockContent.java
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/BlockContent.java
@@ -19,5 +19,10 @@
 
 package org.apache.isis.viewer.scimpi.dispatcher.processor;
 
+/**
+ * BlockContent is an interface that proides a way of sharing information bettween elements. A parent element
+ * creates content object of its particular type and the sub element then picks up that object to access or
+ * set the data.
+ */
 public interface BlockContent {
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/ElementContentProcessor.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/ElementContentProcessor.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/ElementContentProcessor.java
deleted file mode 100644
index 65e0bcf..0000000
--- a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/ElementContentProcessor.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- *  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.processor;
-
-
-public interface ElementContentProcessor extends ElementProcessor {
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/ElementProcessor.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/ElementProcessor.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/ElementProcessor.java
index 37fa0e1..91605c0 100644
--- a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/ElementProcessor.java
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/ElementProcessor.java
@@ -19,11 +19,22 @@
 
 package org.apache.isis.viewer.scimpi.dispatcher.processor;
 
+import org.apache.isis.viewer.scimpi.ScimpiContext;
+import org.apache.isis.viewer.scimpi.dispatcher.context.RequestState;
+
 
 public interface ElementProcessor {
 
+    /**
+     * The name of the tag for the element to be processed by this processor.
+     */
     String getName();
 
-    void process(TagProcessor tagProcessor);
+    /**
+     * Called during initialisation of the Scimpi framework to allow each processor to set itself up.
+     */
+    void init(ScimpiContext context);
+
+    void process(TemplateProcessor templateProcessor, RequestState state);
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/ElementProcessorLookup.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/ElementProcessorLookup.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/ElementProcessorLookup.java
new file mode 100644
index 0000000..8fd7af4
--- /dev/null
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/ElementProcessorLookup.java
@@ -0,0 +1,57 @@
+/*
+ *  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.processor;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.TreeSet;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.viewer.scimpi.ScimpiContext;
+
+public class ElementProcessorLookup {
+    private final Map<String, ElementProcessor> swfElementProcessors = new HashMap<String, ElementProcessor>();
+    private final ScimpiContext context;
+
+    public ElementProcessorLookup(ScimpiContext context){
+        this.context = context;
+    }
+    
+    public void addElementProcessor(final ElementProcessor action) {
+        action.init(context);
+        swfElementProcessors.put("SWF:" + action.getName().toUpperCase(), action);
+    }
+
+    public void debug(final DebugBuilder debug) {
+        debug.startSection("Recognised tags");
+        final Iterator<String> it2 = new TreeSet<String>(swfElementProcessors.keySet()).iterator();
+        while (it2.hasNext()) {
+            final String name = it2.next();
+            debug.appendln(name.toLowerCase(), swfElementProcessors.get(name));
+        }
+        debug.endSection();
+    }
+
+    public ElementProcessor getFor(final String name) {
+        return swfElementProcessors.get(name);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/Encoder.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/Encoder.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/Encoder.java
deleted file mode 100644
index 1efe91e..0000000
--- a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/Encoder.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- *  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.processor;
-
-public interface Encoder {
-
-    String encoder(String text);
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/HtmlEncoder.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/HtmlEncoder.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/HtmlEncoder.java
new file mode 100644
index 0000000..ca9389e
--- /dev/null
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/HtmlEncoder.java
@@ -0,0 +1,26 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.viewer.scimpi.dispatcher.processor;
+
+public interface HtmlEncoder {
+
+    String encodeHtml(String text);
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/HtmlFileParser.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/HtmlFileParser.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/HtmlFileParser.java
index 354af87..fd98c6d 100644
--- a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/HtmlFileParser.java
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/HtmlFileParser.java
@@ -38,9 +38,9 @@ import org.apache.isis.viewer.scimpi.dispatcher.context.Request;
 
 public class HtmlFileParser {
     private static final Logger LOG = Logger.getLogger(HtmlFileParser.class);
-    private final ProcessorLookup processors;
+    private final ElementProcessorLookup processors;
 
-    public HtmlFileParser(final ProcessorLookup processors) {
+    public HtmlFileParser(final ElementProcessorLookup processors) {
         this.processors = processors;
     }
 
@@ -90,7 +90,7 @@ public class HtmlFileParser {
                     // TODO remove context & request from Attributes -- the tags
                     // will be re-used across
                     // requests
-                    final Attributes attributes = new Attributes(tagNode, context);
+                    final TagAttributes tagAttributes = new TagAttributes(tagNode, context);
                     int type = 0;
                     if (tagNode.isEndTag()) {
                         type = SwfTag.END;
@@ -99,7 +99,7 @@ public class HtmlFileParser {
                     }
                     testForProcessorForTag(lexer, tagName);
                     lineNumbers = lineNumbering(node);
-                    final SwfTag tag = new SwfTag(tagName, attributes, type, lineNumbers, loadFile.getCanonicalPath());
+                    final SwfTag tag = new SwfTag(tagName, tagAttributes, type, lineNumbers, loadFile.getCanonicalPath());
                     tags.push(tag);
 
                     if (tagName.equals("SWF:IMPORT")) {

http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/ProcessorLookup.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/ProcessorLookup.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/ProcessorLookup.java
deleted file mode 100644
index 132e1ac..0000000
--- a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/ProcessorLookup.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- *  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.processor;
-
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.TreeSet;
-
-import org.apache.isis.core.commons.debug.DebugBuilder;
-
-public class ProcessorLookup {
-    private final Map<String, ElementProcessor> swfElementProcessors = new HashMap<String, ElementProcessor>();
-
-    public void addElementProcessor(final ElementProcessor action) {
-        swfElementProcessors.put("SWF:" + action.getName().toUpperCase(), action);
-    }
-
-    public void debug(final DebugBuilder debug) {
-        debug.startSection("Recognised tags");
-        final Iterator<String> it2 = new TreeSet<String>(swfElementProcessors.keySet()).iterator();
-        while (it2.hasNext()) {
-            final String name = it2.next();
-            debug.appendln(name.toLowerCase(), swfElementProcessors.get(name));
-        }
-        debug.endSection();
-    }
-
-    public ElementProcessor getFor(final String name) {
-        return swfElementProcessors.get(name);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/SimpleEncoder.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/SimpleEncoder.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/SimpleEncoder.java
deleted file mode 100644
index 8b7a2d5..0000000
--- a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/SimpleEncoder.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- *  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.processor;
-
-import org.apache.commons.lang.StringEscapeUtils;
-
-public class SimpleEncoder implements Encoder {
-
-    @Override
-    public String encoder(final String text) {
-        return StringEscapeUtils.escapeHtml(text);
-        // text.replace("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">",
-        // "&gt;").replace("\"", "&quot;");
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/Snippet.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/Snippet.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/Snippet.java
index 9622fe4..0f3a77a 100644
--- a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/Snippet.java
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/Snippet.java
@@ -19,6 +19,10 @@
 
 package org.apache.isis.viewer.scimpi.dispatcher.processor;
 
+/**
+ * A Snippet is a part of the template and will either be segment of HTML, which can be output directly (after variable 
+ * substitution, or a SWF (a Scimpi) element  that will typically be replaced by generated HTML code.
+ */
 public interface Snippet {
 
     String getHtml();

http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/SwfTag.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/SwfTag.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/SwfTag.java
index dd86d2b..6a6b34d 100644
--- a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/SwfTag.java
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/SwfTag.java
@@ -27,13 +27,13 @@ public class SwfTag implements Snippet {
     public static final int START = 2;
     private final String tagName;
     private final int type;
-    private final Attributes attributes;
+    private final TagAttributes tagAttributes;
     private final String lineNumbers;
     private final String path;
 
-    public SwfTag(final String tagName, final Attributes attributes, final int type, final String lineNumbers, final String path) {
+    public SwfTag(final String tagName, final TagAttributes tagAttributes, final int type, final String lineNumbers, final String path) {
         this.tagName = tagName;
-        this.attributes = attributes;
+        this.tagAttributes = tagAttributes;
         this.type = type;
         this.lineNumbers = lineNumbers;
         this.path = path;
@@ -56,8 +56,8 @@ public class SwfTag implements Snippet {
         return tagName;
     }
 
-    public Attributes getAttributes() {
-        return attributes;
+    public TagAttributes getAttributes() {
+        return tagAttributes;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/TagAttributes.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/TagAttributes.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/TagAttributes.java
new file mode 100644
index 0000000..78a477b
--- /dev/null
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/TagAttributes.java
@@ -0,0 +1,137 @@
+/*
+ *  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.processor;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.htmlparser.Attribute;
+import org.htmlparser.nodes.TagNode;
+
+import org.apache.isis.viewer.scimpi.dispatcher.context.PropertyException;
+import org.apache.isis.viewer.scimpi.dispatcher.context.Request;
+import org.apache.isis.viewer.scimpi.dispatcher.context.RequestState;
+
+/**
+ * All the attributes provided by a tag.
+ */
+public class TagAttributes {
+    private static final String TRUE = " true yes on ";
+    private static final String FALSE = " false no off ";
+    private final TagNode tagNode;
+//    private final Request context;
+
+    public TagAttributes(final TagNode tagNode, final Request context) {
+        this.tagNode = tagNode;
+   //     this.context = context;
+    }
+
+    public boolean isPropertySet(Request context, final String name) {
+        final String attribute = tagNode.getAttribute(name);
+        int end = attribute.length() - 1;
+        final int pos = attribute.indexOf(':');
+        end = pos == -1 ? end : pos;
+        final String variabelName = attribute.substring(2, end);
+        final Object value = context.getVariable(variabelName);
+        return value != null;
+        // return attribute != null &&
+        // !context.replaceVariables(attribute).equals("");
+    }
+
+    public boolean isPropertySpecified(final String name) {
+        final String attribute = tagNode.getAttribute(name);
+        return attribute != null;
+    }
+
+    public String getOptionalProperty(final String name, final boolean ensureVariablesExists) {
+        return getOptionalProperty(name, null, ensureVariablesExists);
+    }
+
+    public String getOptionalProperty(final String name, final String defaultValue, final boolean ensureVariablesExists) {
+        final String attribute = tagNode.getAttribute(name);
+        return attribute == null ? defaultValue : attribute;
+//        return attribute == null ? defaultValue : context.replaceVariables(attribute);
+    }
+
+    public String getRequiredProperty(RequestState context, final String name, final boolean ensureVariablesExists) {
+        final String attribute = tagNode.getAttribute(name);
+        if (attribute == null) {
+            throw new RequiredPropertyException("Missing property: " + name);
+        } else if (attribute.equals("")) {
+            throw new RequiredPropertyException("Property not set: " + name);
+        } else {
+            return context.replaceVariables(attribute);
+        }
+    }
+
+    public String[] getPropertyNames(final String excluding[]) {
+        final Vector attributes = tagNode.getAttributesEx();
+        final String[] names = new String[attributes.size()];
+        int i = 0;
+        names: for (final Enumeration e = attributes.elements(); e.hasMoreElements();) {
+            final String name = ((Attribute) e.nextElement()).getName();
+            if (name == null) {
+                continue;
+            }
+            for (int j = 0; j < excluding.length; j++) {
+                if (name.equals(excluding[j])) {
+                    continue names;
+                }
+            }
+            if (tagNode.getAttribute(name) != null) {
+                names[i++] = name;
+            }
+        }
+
+        final String[] array = new String[i];
+        System.arraycopy(names, 0, array, 0, i);
+        return array;
+    }
+
+    @Override
+    public String toString() {
+        return tagNode.toHtml(); // getAttributesEx().toString();
+    }
+
+    public boolean isRequested(final String name) {
+        return isRequested(name, false);
+    }
+
+    public boolean isRequested(final String name, final boolean defaultValue) {
+        final String flag = getOptionalProperty(name, true);
+        if (flag == null) {
+            return defaultValue;
+        } else {
+            return isTrue(flag);
+        }
+    }
+
+    public static boolean isTrue(final String flag) {
+        final String value = " " + flag.toLowerCase().trim() + " ";
+        if (TRUE.indexOf(value) >= 0) {
+            return true;
+        } else if (FALSE.indexOf(value) >= 0) {
+            return false;
+        } else {
+            throw new PropertyException("Illegal flag value: " + flag);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/TagOrderException.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/TagOrderException.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/TagOrderException.java
new file mode 100644
index 0000000..d7ebf43
--- /dev/null
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/TagOrderException.java
@@ -0,0 +1,31 @@
+/*
+ *  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.processor;
+
+import org.apache.isis.viewer.scimpi.ScimpiException;
+
+public class TagOrderException extends ScimpiException {
+    private static final long serialVersionUID = 1L;
+
+    public TagOrderException(final TemplateProcessor templateProcessor) {
+        super("Invalid tag in this context: " + templateProcessor.getTag().getName());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/TagProcessingException.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/TagProcessingException.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/TagProcessingException.java
deleted file mode 100644
index 4c0ae6a..0000000
--- a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/TagProcessingException.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- *  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.processor;
-
-import org.apache.isis.viewer.scimpi.ScimpiException;
-
-public class TagProcessingException extends ScimpiException {
-    private static final long serialVersionUID = 1L;
-    private String context;
-
-    public TagProcessingException() {
-        super();
-    }
-
-    public TagProcessingException(final String message, final String context, final Throwable cause) {
-        super(message, cause);
-        this.context = context;
-    }
-
-    public TagProcessingException(final String message, final String context) {
-        super(message);
-        this.context = context;
-    }
-
-    public TagProcessingException(final Throwable cause) {
-        super(cause);
-    }
-
-    public String getContext() {
-        return context;
-    }
-
-    @Override
-    public String getMessage() {
-        return super.getMessage() + "\n" + getContext();
-    }
-
-    @Override
-    public String getHtmlMessage() {
-        return super.getMessage() + "<pre>" + getContext() + "</pre>";
-    }
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/TagProcessor.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/TagProcessor.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/TagProcessor.java
deleted file mode 100644
index 8caf2a5..0000000
--- a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/TagProcessor.java
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- *  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.processor;
-
-import java.util.Stack;
-
-import org.apache.log4j.Logger;
-
-import org.apache.isis.viewer.scimpi.ScimpiException;
-import org.apache.isis.viewer.scimpi.dispatcher.context.Request;
-
-public class TagProcessor implements PageWriter {
-
-    public class RepeatMarker {
-        private final int index;
-
-        private RepeatMarker(final int index) {
-            this.index = index;
-        }
-
-        public void repeat() {
-            TagProcessor.this.index = index;
-        }
-    }
-
-    private static Logger LOG = Logger.getLogger(TagProcessor.class);
-    public static final boolean ENSURE_VARIABLES_EXIST = true;
-    public static final boolean NO_VARIABLE_CHECKING = false;
-    private static Encoder encoder;
-
-    public static Encoder getEncoder() {
-        return encoder;
-    }
-
-    private final Request context;
-    private final Stack<Snippet> snippets;
-    private final Stack<StringBuffer> buffers;
-    private final Stack<BlockContent> blocks;
-    private final ProcessorLookup processors;
-    private int nextFormId;
-    private int index = -1;
-    private final String path;
-
-    public TagProcessor(final String path, final Request context, final Encoder encoder, final Stack<Snippet> snippets, final ProcessorLookup processors) {
-        this.path = path;
-        this.context = context;
-        TagProcessor.encoder = encoder;
-        this.snippets = snippets;
-        this.processors = processors;
-
-        buffers = new Stack<StringBuffer>();
-        blocks = new Stack<BlockContent>();
-        pushNewBuffer();
-    }
-
-    public void processNextTag() {
-        while (index < snippets.size() - 1) {
-            index++;
-            final Snippet snippet = snippets.get(index);
-            if (snippet instanceof HtmlSnippet) {
-                appendSnippet((HtmlSnippet) snippet);
-            } else {
-                final SwfTag tag = (SwfTag) snippet;
-                final String name = tag.getName();
-                final ElementProcessor processor = processors.getFor(name);
-                process(tag, processor);
-                if (context.isAborted()) {
-                    return;
-                }
-            }
-        }
-    }
-
-    private void appendSnippet(final HtmlSnippet snippet) {
-        String html = snippet.getHtml();
-        try {
-            if (snippet.isContainsVariable()) {
-                html = context.replaceVariables(html);
-            }
-            appendHtml(html);
-        } catch (final TagProcessingException e) {
-            throw e;
-        } catch (final RuntimeException e) {
-            final String replace = "<";
-            final String withReplacement = "&lt;";
-            html = html.replaceAll(replace, withReplacement);
-
-            throw new TagProcessingException("Error while processing html block at " + snippet.errorAt() + " - " + e.getMessage(), html, e);
-        }
-    }
-
-    @Override
-    public void appendAsHtmlEncoded(final String string) {
-        appendHtml(encodeHtml(string));
-        // appendHtml(string);
-    }
-
-    @Override
-    public void appendHtml(final String html) {
-        final StringBuffer buffer = buffers.peek();
-        buffer.append(html);
-    }
-
-    public void appendDebug(final String line) {
-        context.appendDebugTrace(encodeHtml(line));
-    }
-
-    private String encodeHtml(final String text) {
-        return encoder.encoder(text);
-    }
-
-    public void appendTruncated(String text, final int truncateTo) {
-        if (truncateTo > 0 && text.length() > truncateTo) {
-            text = text.substring(0, truncateTo) + "...";
-        }
-        appendAsHtmlEncoded(text);
-    }
-
-    private void process(final SwfTag tag, final ElementProcessor processor) {
-        try {
-            LOG.debug("processing " + processor.getName() + " " + tag);
-            appendDebug("\n" + tag.debug());
-            if (tag.getType() == SwfTag.END) {
-                throw new TagProcessingException(tag.errorAt() + " - end tag mistaken for a start tag", tag.toString());
-            }
-            processor.process(this);
-        } catch (final TagProcessingException e) {
-            throw e;
-        } catch (final RuntimeException e) {
-            throw new TagProcessingException("Error while processing " + tag.getName().toLowerCase() + " element at " + tag.errorAt() + " - " + e.getMessage(), tag.toString(), e);
-        }
-    }
-
-    public void processUtilCloseTag() {
-        final SwfTag tag = getTag();
-        if (tag.getType() == SwfTag.EMPTY) {
-            return;
-        }
-        while (index < snippets.size() - 1) {
-            index++;
-            final Snippet snippet = snippets.get(index);
-            if (snippet instanceof HtmlSnippet) {
-                appendSnippet((HtmlSnippet) snippet);
-            } else {
-                final SwfTag nextTag = (SwfTag) snippet;
-                if (tag.getName().equals(nextTag.getName())) {
-                    if (nextTag.getType() == SwfTag.START) {
-                    } else {
-                        return;
-                    }
-                }
-                final String name = nextTag.getName();
-                if (nextTag.getType() == SwfTag.END && !tag.getName().equals(name)) {
-                    throw new TagProcessingException("Expected " + nextTag.getName().toLowerCase() + " tag but found " + tag.getName().toLowerCase() + " tag at " + nextTag.errorAt(), tag.toString());
-                }
-                final ElementProcessor processor = processors.getFor(name);
-                process(nextTag, processor);
-            }
-        }
-    }
-
-    public void skipUntilClose() {
-        final SwfTag tag = getTag();
-        if (tag.getType() == SwfTag.EMPTY) {
-            if (context.isDebug()) {
-                appendHtml("<!-- " + "skipped " + tag + " -->");
-            }
-            return;
-        }
-        int depth = 1;
-        while (index < snippets.size() - 1) {
-            index++;
-            final Snippet snippet = snippets.get(index);
-            if (snippet instanceof SwfTag) {
-                final SwfTag nextTag = (SwfTag) snippet;
-                if (tag.getName().equals(nextTag.getName())) {
-                    if (nextTag.getType() == SwfTag.START) {
-                        depth++;
-                    } else {
-                        depth--;
-                        if (depth == 0) {
-                            return;
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    public void closeEmpty() {
-        final SwfTag tag = getTag();
-        if (tag.getType() == SwfTag.EMPTY) {
-            return;
-        }
-        if (index < snippets.size()) {
-            final Snippet snippet = snippets.get(index);
-            if (snippet instanceof SwfTag) {
-                final SwfTag nextTag = (SwfTag) snippet;
-                if (nextTag.getType() == SwfTag.EMPTY) {
-                    return;
-                }
-            }
-        }
-        throw new ScimpiException("Empty tag not closed");
-    }
-
-    public void pushNewBuffer() {
-        final StringBuffer buffer = new StringBuffer();
-        buffers.push(buffer);
-    }
-
-    public String popBuffer() {
-        final String content = buffers.pop().toString();
-        return content;
-    }
-
-    public SwfTag getTag() {
-        return (SwfTag) snippets.get(index);
-    }
-
-    public Request getContext() {
-        return context;
-    }
-
-    // TODO rename to pushBlock()
-    public void setBlockContent(final BlockContent content) {
-        blocks.add(content);
-    }
-
-    public BlockContent popBlockContent() {
-        return blocks.pop();
-    }
-
-    public BlockContent getBlockContent() {
-        return blocks.peek();
-    }
-
-    public String getViewPath() {
-        return path;
-    }
-
-    public String nextFormId() {
-        return String.valueOf(nextFormId++);
-    }
-
-    public String getOptionalProperty(final String name, final String defaultValue) {
-        return getOptionalProperty(name, defaultValue, true);
-    }
-
-    public String getOptionalProperty(final String name, final String defaultValue, final boolean ensureVariablesExists) {
-        final Attributes attributes = getTag().getAttributes();
-        return attributes.getOptionalProperty(name, defaultValue, ensureVariablesExists);
-    }
-
-    public String getOptionalProperty(final String name) {
-        return getOptionalProperty(name, true);
-    }
-
-    public String getOptionalProperty(final String name, final boolean ensureVariablesExists) {
-        final Attributes attributes = getTag().getAttributes();
-        return attributes.getOptionalProperty(name, ensureVariablesExists);
-    }
-
-    public Attributes getAttributes() {
-        return getTag().getAttributes();
-    }
-
-    public String getRequiredProperty(final String name) {
-        return getRequiredProperty(name, true);
-    }
-
-    public String getRequiredProperty(final String name, final boolean ensureVariablesExists) {
-        final Attributes attributes = getTag().getAttributes();
-        return attributes.getRequiredProperty(name, ensureVariablesExists);
-    }
-
-    public boolean isRequested(final String name) {
-        final Attributes attributes = getTag().getAttributes();
-        return attributes.isRequested(name);
-    }
-
-    public boolean isRequested(final String name, final boolean defaultValue) {
-        final Attributes attributes = getTag().getAttributes();
-        return attributes.isRequested(name, defaultValue);
-    }
-
-    public boolean isPropertySet(final String name) {
-        final Attributes attributes = getTag().getAttributes();
-        return attributes.isPropertySet(name);
-    }
-
-    public boolean isPropertySpecified(final String name) {
-        final Attributes attributes = getTag().getAttributes();
-        return attributes.isPropertySpecified(name);
-    }
-
-    public RepeatMarker createMarker() {
-        return new RepeatMarker(index);
-    }
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/TemplateProcessingException.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/TemplateProcessingException.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/TemplateProcessingException.java
new file mode 100644
index 0000000..c1c0ac1
--- /dev/null
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/TemplateProcessingException.java
@@ -0,0 +1,59 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.viewer.scimpi.dispatcher.processor;
+
+import org.apache.isis.viewer.scimpi.ScimpiException;
+
+public class TemplateProcessingException extends ScimpiException {
+    private static final long serialVersionUID = 1L;
+    private String context;
+
+    public TemplateProcessingException() {
+        super();
+    }
+
+    public TemplateProcessingException(final String message, final String context, final Throwable cause) {
+        super(message, cause);
+        this.context = context;
+    }
+
+    public TemplateProcessingException(final String message, final String context) {
+        super(message);
+        this.context = context;
+    }
+
+    public TemplateProcessingException(final Throwable cause) {
+        super(cause);
+    }
+
+    public String getContext() {
+        return context;
+    }
+
+    @Override
+    public String getMessage() {
+        return super.getMessage() + "\n" + getContext();
+    }
+
+    @Override
+    public String getHtmlMessage() {
+        return super.getMessage() + "<pre>" + getContext() + "</pre>";
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/TemplateProcessor.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/TemplateProcessor.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/TemplateProcessor.java
new file mode 100644
index 0000000..5097e7e
--- /dev/null
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/processor/TemplateProcessor.java
@@ -0,0 +1,318 @@
+/*
+ *  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.processor;
+
+import java.util.Stack;
+
+import org.apache.log4j.Logger;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.isis.viewer.scimpi.ScimpiException;
+import org.apache.isis.viewer.scimpi.dispatcher.context.Request;
+import org.apache.isis.viewer.scimpi.dispatcher.context.RequestState;
+
+public class TemplateProcessor implements PageWriter, HtmlEncoder {
+
+    public class RepeatMarker {
+        private final int index;
+
+        private RepeatMarker(final int index) {
+            this.index = index;
+        }
+
+        public void repeat() {
+            TemplateProcessor.this.index = index;
+        }
+    }
+
+    private static Logger LOG = Logger.getLogger(TemplateProcessor.class);
+    public static final boolean ENSURE_VARIABLES_EXIST = true;
+    public static final boolean NO_VARIABLE_CHECKING = false;
+
+    private final RequestState state;
+    private final Request context;
+    private final Stack<Snippet> snippets;
+    private final Stack<StringBuffer> buffers;
+    private final Stack<BlockContent> blocks;
+    private final ElementProcessorLookup processors;
+    private int nextFormId;
+    private int index = 0;
+    private final String path;
+
+    public TemplateProcessor(final String path, final RequestState state, final Request context, final Stack<Snippet> snippets, final ElementProcessorLookup processors) {
+        this.path = path;
+        this.state = state;
+        this.context = context;
+        this.snippets = snippets;
+        this.processors = processors;
+
+        buffers = new Stack<StringBuffer>();
+        blocks = new Stack<BlockContent>();
+        pushNewBuffer();
+    }
+
+    public void processNextTag() {
+        while (index < snippets.size() - 1) {
+            index++;
+            final Snippet snippet = snippets.get(index);
+            if (snippet instanceof HtmlSnippet) {
+                appendSnippet((HtmlSnippet) snippet);
+            } else {
+                final SwfTag tag = (SwfTag) snippet;
+                final String name = tag.getName();
+                final ElementProcessor processor = processors.getFor(name);
+                process(tag, processor);
+                if (context.isAborted()) {
+                    return;
+                }
+            }
+        }
+    }
+
+    private void appendSnippet(final HtmlSnippet snippet) {
+        String html = snippet.getHtml();
+        try {
+            if (snippet.isContainsVariable()) {
+                html = context.replaceVariables(html);
+            }
+            appendHtml(html);
+        } catch (final TemplateProcessingException e) {
+            throw e;
+        } catch (final RuntimeException e) {
+            final String replace = "<";
+            final String withReplacement = "&lt;";
+            html = html.replaceAll(replace, withReplacement);
+
+            throw new TemplateProcessingException("Error while processing html block at " + snippet.errorAt() + " - " + e.getMessage(), html, e);
+        }
+    }
+
+    @Override
+    public void appendAsHtmlEncoded(final String string) {
+        appendHtml(encodeHtml(string));
+        // appendHtml(string);
+    }
+
+    @Override
+    public void appendHtml(final String html) {
+        final StringBuffer buffer = buffers.peek();
+        buffer.append(html);
+    }
+
+    public void appendDebug(final String line) {
+        context.appendDebugTrace(encodeHtml(line));
+    }
+
+    public String encodeHtml(final String text) {
+        return StringEscapeUtils.escapeHtml(text);
+    }
+
+    public void appendTruncated(String text, final int truncateTo) {
+        if (truncateTo > 0 && text.length() > truncateTo) {
+            text = text.substring(0, truncateTo) + "...";
+        }
+        appendAsHtmlEncoded(text);
+    }
+
+    private void process(final SwfTag tag, final ElementProcessor processor) {
+        try {
+            LOG.debug("processing " + processor.getName() + " " + tag);
+            appendDebug("\n" + tag.debug());
+            if (tag.getType() == SwfTag.END) {
+                throw new TemplateProcessingException(tag.errorAt() + " - end tag mistaken for a start tag", tag.toString());
+            }
+            processor.process(this, state);
+        } catch (final TemplateProcessingException e) {
+            throw e;
+        } catch (final RuntimeException e) {
+            throw new TemplateProcessingException("Error while processing " + tag.getName().toLowerCase() + " element at " + tag.errorAt() + " - " + e.getMessage(), tag.toString(), e);
+        }
+    }
+
+    public void processUtilCloseTag() {
+        final SwfTag tag = getTag();
+        if (tag.getType() == SwfTag.EMPTY) {
+            return;
+        }
+        while (index < snippets.size() - 1) {
+            index++;
+            final Snippet snippet = snippets.get(index);
+            if (snippet instanceof HtmlSnippet) {
+                appendSnippet((HtmlSnippet) snippet);
+            } else {
+                final SwfTag nextTag = (SwfTag) snippet;
+                if (tag.getName().equals(nextTag.getName())) {
+                    if (nextTag.getType() == SwfTag.START) {
+                    } else {
+                        return;
+                    }
+                }
+                final String name = nextTag.getName();
+                if (nextTag.getType() == SwfTag.END && !tag.getName().equals(name)) {
+                    throw new TemplateProcessingException("Expected " + nextTag.getName().toLowerCase() + " tag but found " + tag.getName().toLowerCase() + " tag at " + nextTag.errorAt(), tag.toString());
+                }
+                final ElementProcessor processor = processors.getFor(name);
+                process(nextTag, processor);
+            }
+        }
+    }
+
+    public void skipUntilClose() {
+        final SwfTag tag = getTag();
+        if (tag.getType() == SwfTag.EMPTY) {
+            if (context.isDebug()) {
+                appendHtml("<!-- " + "skipped " + tag + " -->");
+            }
+            return;
+        }
+        int depth = 1;
+        while (index < snippets.size() - 1) {
+            index++;
+            final Snippet snippet = snippets.get(index);
+            if (snippet instanceof SwfTag) {
+                final SwfTag nextTag = (SwfTag) snippet;
+                if (tag.getName().equals(nextTag.getName())) {
+                    if (nextTag.getType() == SwfTag.START) {
+                        depth++;
+                    } else {
+                        depth--;
+                        if (depth == 0) {
+                            return;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    public void closeEmpty() {
+        final SwfTag tag = getTag();
+        if (tag.getType() == SwfTag.EMPTY) {
+            return;
+        }
+        if (index < snippets.size()) {
+            final Snippet snippet = snippets.get(index);
+            if (snippet instanceof SwfTag) {
+                final SwfTag nextTag = (SwfTag) snippet;
+                if (nextTag.getType() == SwfTag.EMPTY) {
+                    return;
+                }
+            }
+        }
+        throw new ScimpiException("Empty tag not closed");
+    }
+
+    public void pushNewBuffer() {
+        final StringBuffer buffer = new StringBuffer();
+        buffers.push(buffer);
+    }
+
+    public String popBuffer() {
+        final String content = buffers.pop().toString();
+        return content;
+    }
+
+    public SwfTag getTag() {
+        return (SwfTag) snippets.get(index);
+    }
+
+    public Request getContext() {
+        return context;
+    }
+
+    public void pushBlock(final BlockContent content) {
+        blocks.add(content);
+    }
+
+    public BlockContent popBlock() {
+        return blocks.pop();
+    }
+
+    public BlockContent peekBlock() {
+        return blocks.peek();
+    }
+
+    public String getViewPath() {
+        return path;
+    }
+
+    public String nextFormId() {
+        return String.valueOf(nextFormId++);
+    }
+
+    public String getOptionalProperty(final String name, final String defaultValue) {
+        return getOptionalProperty(name, defaultValue, true);
+    }
+
+    public String getOptionalProperty(final String name, final String defaultValue, final boolean ensureVariablesExists) {
+        final TagAttributes tagAttributes = getTag().getAttributes();
+//        return tagAttributes.getOptionalProperty(name, defaultValue, ensureVariablesExists);
+        String attribute = tagAttributes.getOptionalProperty(name, defaultValue, ensureVariablesExists);
+        return attribute == null ? null : state.replaceVariables(attribute);
+    }
+
+    public String getOptionalProperty(final String name) {
+        return getOptionalProperty(name, true);
+    }
+
+    public String getOptionalProperty(final String name, final boolean ensureVariablesExists) {
+        final TagAttributes tagAttributes = getTag().getAttributes();
+        // return tagAttributes.getOptionalProperty(name, ensureVariablesExists);
+        String attribute = tagAttributes.getOptionalProperty(name, ensureVariablesExists);
+        return attribute == null ? null : state.replaceVariables(attribute);
+    }
+
+    public TagAttributes getAttributes() {
+        return getTag().getAttributes();
+    }
+
+    public String getRequiredProperty(final String name) {
+        return getRequiredProperty(name, true);
+    }
+
+    public String getRequiredProperty(final String name, final boolean ensureVariablesExists) {
+        final TagAttributes tagAttributes = getTag().getAttributes();
+        return tagAttributes.getRequiredProperty(state, name, ensureVariablesExists);
+    }
+
+    public boolean isRequested(final String name) {
+        final TagAttributes tagAttributes = getTag().getAttributes();
+        return tagAttributes.isRequested(name);
+    }
+
+    public boolean isRequested(final String name, final boolean defaultValue) {
+        final TagAttributes tagAttributes = getTag().getAttributes();
+        return tagAttributes.isRequested(name, defaultValue);
+    }
+
+    public boolean isPropertySet(final String name) {
+        final TagAttributes tagAttributes = getTag().getAttributes();
+        return tagAttributes.isPropertySet(context, name);
+    }
+
+    public boolean isPropertySpecified(final String name) {
+        final TagAttributes tagAttributes = getTag().getAttributes();
+        return tagAttributes.isPropertySpecified(name);
+    }
+
+    public RepeatMarker createMarker() {
+        return new RepeatMarker(index);
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/structure/FieldEditState.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/structure/FieldEditState.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/structure/FieldEditState.java
deleted file mode 100644
index 1ccf2bb..0000000
--- a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/structure/FieldEditState.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- *  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.structure;
-
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-
-public class FieldEditState {
-    private final String entry;
-    private String reason;
-    private ObjectAdapter value;
-
-    public FieldEditState(final String entry) {
-        this.entry = entry;
-    }
-
-    public void setError(final String reason) {
-        this.reason = reason;
-    }
-
-    public boolean isEntryValid() {
-        return reason == null;
-    }
-
-    public String getEntry() {
-        return entry;
-    }
-
-    public String getError() {
-        return reason;
-    }
-
-    public ObjectAdapter getValue() {
-        return value;
-    }
-
-    public void setValue(final ObjectAdapter value) {
-        this.value = value;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/structure/FormState.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/structure/FormState.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/structure/FormState.java
deleted file mode 100644
index 589ee29..0000000
--- a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/structure/FormState.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- *  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.structure;
-
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-
-public class FormState {
-    private final Map<String, FieldEditState> fields = new HashMap<String, FieldEditState>();
-    private String error;
-    private String formId;
-
-    public FieldEditState createField(final String name, final String entry) {
-        final FieldEditState fieldEditState = new FieldEditState(entry);
-        fields.put(name, fieldEditState);
-        return fieldEditState;
-    }
-
-    public boolean isValid() {
-        final Iterator<FieldEditState> iterator = fields.values().iterator();
-        while (iterator.hasNext()) {
-            if (!iterator.next().isEntryValid()) {
-                return false;
-            }
-        }
-        return error == null;
-    }
-
-    public FieldEditState getField(final String name) {
-        return fields.get(name);
-    }
-
-    public void setError(final String error) {
-        this.error = error;
-    }
-
-    public String getError() {
-        return error;
-    }
-
-    public void setForm(final String formId) {
-        this.formId = formId;
-    }
-
-    public boolean isForForm(final String formId) {
-        return this.formId == null || this.formId.equals(formId);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/util/MethodsUtils.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/util/MethodsUtils.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/util/MethodsUtils.java
index 5d66630..f63a3bd 100644
--- a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/util/MethodsUtils.java
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/util/MethodsUtils.java
@@ -38,6 +38,7 @@ import org.apache.isis.viewer.scimpi.Names;
 import org.apache.isis.viewer.scimpi.ScimpiException;
 import org.apache.isis.viewer.scimpi.dispatcher.context.Request;
 import org.apache.isis.viewer.scimpi.dispatcher.context.Request.Scope;
+import org.apache.isis.viewer.scimpi.dispatcher.context.RequestState;
 
 public class MethodsUtils {
     public static final String SERVICE_PREFIX = "service:";
@@ -103,7 +104,7 @@ public class MethodsUtils {
         return null;
     }
 
-    public static ObjectAdapter findObject(final Request context, String objectId) {
+    public static ObjectAdapter findObject(final RequestState context, String objectId) {
         if (objectId == null) {
             objectId = context.getStringVariable(Names.RESULT);
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/7700b437/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/util/UserManager.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/util/UserManager.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/util/UserManager.java
new file mode 100644
index 0000000..3fc1e10
--- /dev/null
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/util/UserManager.java
@@ -0,0 +1,89 @@
+/*
+ *  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.util;
+
+import org.apache.isis.core.commons.authentication.AnonymousSession;
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.runtime.authentication.AuthenticationManager;
+import org.apache.isis.core.runtime.authentication.AuthenticationRequestPassword;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.log4j.Logger;
+
+public class UserManager {
+
+    private static final Logger LOG = Logger.getLogger(UserManager.class);
+    private static UserManager instance;
+
+    private static AuthenticationManager getAuthenticationManager() {
+        if (instance == null) {
+            throw new IllegalStateException("Server initialisation failed, or not defined as a context listener");
+        }
+        return instance.authenticationManager;
+    }
+
+    public static AuthenticationSession startRequest(final AuthenticationSession session) {
+        AuthenticationSession useSession;
+        if (session == null) {
+            useSession = new AnonymousSession();
+            LOG.debug("start anonymous request: " + session);
+        } else {
+            useSession = session;
+            LOG.debug("start request for: " + session.getUserName());
+        }
+        IsisContext.closeSession();
+        IsisContext.openSession(useSession);
+        return useSession;
+    }
+
+    public static AuthenticationSession authenticate(final AuthenticationRequestPassword passwordAuthenticationRequest) {
+        final AuthenticationSession session = getAuthenticationManager().authenticate(passwordAuthenticationRequest);
+        if (session != null) {
+            LOG.info("log on user " + session.getUserName());
+            IsisContext.closeSession();
+            IsisContext.openSession(session);
+        }
+        return session;
+    }
+
+    public static void endRequest(final AuthenticationSession session) {
+        if (session == null) {
+            LOG.debug("end anonymous request");
+        } else {
+            LOG.debug("end request for: " + session.getUserName());
+        }
+        IsisContext.closeSession();
+    }
+
+    public static void logoffUser(final AuthenticationSession session) {
+        LOG.info("log off user " + session.getUserName());
+        IsisContext.closeSession();
+        getAuthenticationManager().closeSession(session);
+
+        final AnonymousSession replacementSession = new AnonymousSession();
+        IsisContext.openSession(replacementSession);
+    }
+
+    private final AuthenticationManager authenticationManager;
+
+    public UserManager(final AuthenticationManager authenticationManager) {
+        this.authenticationManager = authenticationManager;
+        UserManager.instance = this;
+    }
+}