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:40 UTC
[11/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/Dispatcher.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/Dispatcher.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/Dispatcher.java
new file mode 100644
index 0000000..82c67c1
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/Dispatcher.java
@@ -0,0 +1,484 @@
+/*
+ * 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;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.Stack;
+import java.util.TimeZone;
+
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.Element;
+import org.dom4j.io.SAXReader;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.commons.config.ConfigurationConstants;
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.commons.exceptions.IsisException;
+import org.apache.isis.core.commons.factory.InstanceUtil;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
+import org.apache.isis.core.metamodel.facets.actcoll.typeof.TypeOfFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
+import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
+import org.apache.isis.viewer.scimpi.dispatcher.action.ActionAction;
+import org.apache.isis.viewer.scimpi.dispatcher.context.RequestContext;
+import org.apache.isis.viewer.scimpi.dispatcher.context.RequestContext.Debug;
+import org.apache.isis.viewer.scimpi.dispatcher.context.RequestContext.Scope;
+import org.apache.isis.viewer.scimpi.dispatcher.debug.DebugAction;
+import org.apache.isis.viewer.scimpi.dispatcher.debug.DebugHtmlWriter;
+import org.apache.isis.viewer.scimpi.dispatcher.debug.DebugUserAction;
+import org.apache.isis.viewer.scimpi.dispatcher.debug.DebugUsers;
+import org.apache.isis.viewer.scimpi.dispatcher.debug.LogAction;
+import org.apache.isis.viewer.scimpi.dispatcher.edit.EditAction;
+import org.apache.isis.viewer.scimpi.dispatcher.edit.RemoveAction;
+import org.apache.isis.viewer.scimpi.dispatcher.logon.LogonAction;
+import org.apache.isis.viewer.scimpi.dispatcher.logon.LogoutAction;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.Encoder;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.HtmlFileParser;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.ProcessorLookup;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.Request;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.SimpleEncoder;
+import org.apache.isis.viewer.scimpi.dispatcher.processor.TagProcessingException;
+import org.apache.isis.viewer.scimpi.dispatcher.util.MethodsUtils;
+import org.apache.isis.viewer.scimpi.dispatcher.view.Snippet;
+
+public class Dispatcher {
+ private static final String SHOW_UNSHOWN_MESSAGES = ConfigurationConstants.ROOT + "scimpi.show-unshown-messages";
+ public static final String ACTION = "_action";
+ public static final String EDIT = "_edit";
+ public static final String REMOVE = "_remove";
+ public static final String GENERIC = "_generic";
+ public static final String EXTENSION = "shtml";
+ private static final Logger LOG = LoggerFactory.getLogger(Dispatcher.class);
+ public static final String COMMAND_ROOT = ".app";
+ private final Map<String, Action> actions = new HashMap<String, Action>();
+ private final Map<String, String> parameters = new HashMap<String, String>();
+ private final ProcessorLookup processors = new ProcessorLookup();
+ private final HtmlFileParser parser = new HtmlFileParser(processors);
+ private final Encoder encoder = new SimpleEncoder();
+ private boolean showUnshownMessages;
+
+ public void process(final RequestContext context, final String servletPath) {
+ LOG.debug("processing request " + servletPath);
+ final AuthenticationSession session = UserManager.startRequest(context);
+ LOG.debug("exsiting session: " + session);
+
+ String language = (String) context.getVariable("user-language");
+ if (language != null) {
+ Locale locale = Util.locale(language);
+ TimeZone timeZone = Util.timeZone((String) context.getVariable("user-time-zone"));
+ // IsisContext.getUserProfile().setLocalization(new UserLocalization(locale, timeZone));
+ }
+
+ IsisContext.getPersistenceSession().getTransactionManager().startTransaction();
+ context.setRequestPath(servletPath);
+ context.startRequest();
+
+ try {
+ processActions(context, false, servletPath);
+ processTheView(context);
+ } catch (final ScimpiNotFoundException e) {
+ if (context.isInternalRequest()) {
+ LOG.error("invalid page request (from within application): " + e.getMessage());
+ ErrorCollator error = new ErrorCollator();
+ error.missingFile("Failed to find page " + servletPath + ".");
+ show500ErrorPage(context, e, error);
+ } else {
+ LOG.info("invalid page request (from outside application): " + e.getMessage());
+ show404ErrorPage(context, servletPath);
+ }
+ } catch (final NotLoggedInException e) {
+ redirectToLoginPage(context);
+ } catch (final Throwable e) {
+ ErrorCollator error = new ErrorCollator();
+ final PersistenceSession checkSession = IsisContext.getPersistenceSession();
+ final IsisTransactionManager transactionManager = checkSession.getTransactionManager();
+ if (transactionManager.getTransaction() != null && transactionManager.getTransaction().getState().canAbort()) {
+ transactionManager.abortTransaction();
+ transactionManager.startTransaction();
+ }
+
+ final Throwable ex = e instanceof TagProcessingException ? e.getCause() : e;
+ if (ex instanceof ForbiddenException) {
+ LOG.error("invalid access to " + servletPath, e);
+ show403ErrorPage(context, error, e, ex);
+ } else {
+ LOG.error("error procesing " + servletPath, e);
+ if (context.getErrorMessage() != null) {
+ fallbackToSimpleErrorPage(context, e);
+ } else {
+ show500ErrorPage(context, e, error);
+ }
+ }
+ } finally {
+ try {
+ UserManager.endRequest(context.getSession());
+ } catch (final Exception e1) {
+ LOG.error("endRequest call failed", e1);
+ }
+ }
+ }
+
+ private void redirectToLoginPage(final RequestContext context) {
+ IsisContext.getMessageBroker().addWarning(
+ "You are not currently logged in! Please log in so you can continue.");
+ context.setRequestPath("/login.shtml");
+ try {
+ processTheView(context);
+ } catch (final IOException e1) {
+ throw new ScimpiException(e1);
+ }
+ }
+
+ private void show404ErrorPage(final RequestContext context, final String servletPath) {
+ ErrorCollator error = new ErrorCollator();
+ error.missingFile("Failed to find page " + servletPath + ".");
+ context.raiseError(404, error);
+ }
+
+ private void show403ErrorPage(final RequestContext context, ErrorCollator error, final Throwable e, final Throwable ex) {
+ DebugBuilder debug = error.getDebug();
+ error.message(e);
+ error.message(ex);
+
+ final List<String> roles = ((ForbiddenException) ex).getRoles();
+ final StringBuffer roleList = new StringBuffer();
+ for (final String role : roles) {
+ if (roleList.length() > 0) {
+ roleList.append("|");
+ }
+ roleList.append(role);
+ }
+ final Identifier identifier = ((ForbiddenException) ex).getIdentifier();
+ if (identifier != null) {
+ debug.appendln("Class", identifier.toClassIdentityString() + ":" + roleList);
+ debug.appendln("Member",identifier.toClassAndNameIdentityString() + ":" + roleList);
+ debug.appendln("Other",identifier.toFullIdentityString() + ":" + roleList);
+ }
+
+ error.compileError(context);
+ context.raiseError(403, error);
+ }
+
+ private void show500ErrorPage(final RequestContext context, final Throwable e, ErrorCollator error) {
+ error.exception(e);
+ error.compileError(context);
+ context.raiseError(500, error);
+ }
+
+ private void fallbackToSimpleErrorPage(final RequestContext context, final Throwable e) {
+ context.setContentType("text/html");
+ final PrintWriter writer = context.getWriter();
+ writer.write("<html><head><title>Error</title></head>");
+ writer.write("<body><h1>Error</h1>");
+ writer.write("<p>Error while processing error</p><pre>");
+ e.printStackTrace(writer);
+ writer.write("</pre></body></html>");
+ writer.close();
+ LOG.error("Error while processing error", e);
+ }
+
+ protected void processTheView(final RequestContext context) throws IOException {
+ IsisTransactionManager transactionManager = IsisContext.getPersistenceSession().getTransactionManager();
+ if (transactionManager.getTransaction().getState().canFlush()) {
+ transactionManager.flushTransaction();
+ }
+ processView(context);
+ // Note - the session will have changed since the earlier call if a user
+ // has logged in or out in the action
+ // processing above.
+ transactionManager = IsisContext.getPersistenceSession().getTransactionManager();
+ if (transactionManager.getTransaction().getState().canCommit()) {
+ IsisContext.getPersistenceSession().getTransactionManager().endTransaction();
+ }
+
+ context.endRequest();
+ UserManager.endRequest(context.getSession());
+ }
+
+ public void addParameter(final String name, final String value) {
+ parameters.put(name, value);
+ }
+
+ private String getParameter(final String name) {
+ return parameters.get(name);
+ }
+
+ private void processActions(final RequestContext context, final boolean userLoggedIn, final String actionName) throws IOException {
+ if (actionName.endsWith(COMMAND_ROOT)) {
+ final int pos = actionName.lastIndexOf('/');
+ final Action action = actions.get(actionName.substring(pos, actionName.length() - COMMAND_ROOT.length()));
+ if (action == null) {
+ throw new ScimpiException("No logic for " + actionName);
+ }
+
+ LOG.debug("processing action: " + action);
+ action.process(context);
+ final String fowardTo = context.forwardTo();
+ if (fowardTo != null) {
+ processActions(context, true, fowardTo);
+ }
+ }
+ }
+
+ private void processView(final RequestContext context) throws IOException {
+ String file = context.getRequestedFile();
+ if (file == null) {
+ LOG.warn("No view specified to process");
+ return;
+ }
+ if (file.endsWith(COMMAND_ROOT)) {
+ return;
+ }
+ file = determineFile(context, file);
+ final String fullPath = context.requestedFilePath(file);
+ LOG.debug("processing file " + fullPath);
+ context.setResourcePath(fullPath);
+
+ context.setContentType("text/html");
+
+ context.addVariable("title", "Untitled Page", Scope.REQUEST);
+ final Stack<Snippet> tags = loadPageTemplate(context, fullPath);
+ final Request request = new Request(file, context, encoder, tags, processors);
+ request.appendDebug("processing " + fullPath);
+ try {
+ request.processNextTag();
+ noteIfMessagesHaveNotBeenDisplay(context);
+ } catch (final RuntimeException e) {
+ IsisContext.getMessageBroker().getMessages();
+ IsisContext.getMessageBroker().getWarnings();
+ throw e;
+ }
+ final String page = request.popBuffer();
+ final PrintWriter writer = context.getWriter();
+ writer.write(page);
+ if (context.getDebug() == Debug.PAGE) {
+ final DebugHtmlWriter view = new DebugHtmlWriter(writer, false);
+ context.append(view);
+ }
+ }
+
+ public void noteIfMessagesHaveNotBeenDisplay(final RequestContext context) {
+ final List<String> messages = IsisContext.getMessageBroker().getMessages();
+ if (showUnshownMessages) {
+ if (messages.size() > 0) {
+ context.getWriter().println("<ol class=\"messages forced\">");
+ for (String message : messages) {
+ context.getWriter().println("<li>" + message + "</li>");
+ }
+ context.getWriter().println("</ol>");
+ }
+ final List<String> warnings = IsisContext.getMessageBroker().getWarnings();
+ if (warnings.size() > 0) {
+ context.getWriter().println("<ol class=\"warnings forced\">");
+ for (String message : warnings) {
+ context.getWriter().println("<li>" + message + "</li>");
+ }
+ context.getWriter().println("</ol>");
+ }
+ }
+ }
+
+ private String determineFile(final RequestContext context, String file) {
+ final String fileName = file.trim();
+ if (fileName.startsWith(GENERIC)) {
+ final Object result = context.getVariable(RequestContext.RESULT);
+ final ObjectAdapter mappedObject = MethodsUtils.findObject(context, (String) result);
+ if (mappedObject == null) {
+ throw new ScimpiException("No object mapping for " + result);
+ }
+ if (fileName.equals(GENERIC + "." + EXTENSION)) {
+ final Facet facet = mappedObject.getSpecification().getFacet(CollectionFacet.class);
+ if (facet != null) {
+ final ObjectSpecification specification = mappedObject.getSpecification();
+ final TypeOfFacet facet2 = specification.getFacet(TypeOfFacet.class);
+ file = findFileForSpecification(context, facet2.valueSpec(), "collection", EXTENSION);
+ } else {
+ final ObjectAdapter mappedObject2 = mappedObject;
+ if (mappedObject2.isTransient()) {
+ file = findFileForSpecification(context, mappedObject.getSpecification(), "edit", EXTENSION);
+ } else {
+ file = findFileForSpecification(context, mappedObject.getSpecification(), "object", EXTENSION);
+ }
+ }
+ } else if (fileName.equals(GENERIC + EDIT + "." + EXTENSION)) {
+ file = findFileForSpecification(context, mappedObject.getSpecification(), "edit", EXTENSION);
+ } else if (fileName.equals(GENERIC + ACTION + "." + EXTENSION)) {
+ final String method = context.getParameter("method");
+ file = findFileForSpecification(context, mappedObject.getSpecification(), method, "action", EXTENSION);
+ }
+ }
+ return file;
+ }
+
+ private String findFileForSpecification(final RequestContext context, final ObjectSpecification specification, final String name, final String extension) {
+ return findFileForSpecification(context, specification, name, name, extension);
+ }
+
+ private String findFileForSpecification(final RequestContext context, final ObjectSpecification specification, final String name, final String defaultName, final String extension) {
+
+ String find = findFile(context, specification, name, extension);
+ if (find == null) {
+ find = "/generic/" + defaultName + "." + extension;
+ }
+ return find;
+ }
+
+ private String findFile(final RequestContext context, final ObjectSpecification specification, final String name, final String extension) {
+ final String className = specification.getShortIdentifier();
+ String fileName = context.findFile("/" + className + "/" + name + "." + extension);
+ if (fileName == null) {
+ final List<ObjectSpecification> interfaces = specification.interfaces();
+ for (int i = 0; i < interfaces.size(); i++) {
+ fileName = findFile(context, interfaces.get(i), name, extension);
+ if (fileName != null) {
+ return fileName;
+ }
+ }
+ if (specification.superclass() != null) {
+ fileName = findFile(context, specification.superclass(), name, extension);
+ }
+ }
+ return fileName;
+ }
+
+ private Stack<Snippet> loadPageTemplate(final RequestContext context, final String path) throws IOException, FileNotFoundException {
+ // TODO cache stacks and check for them first
+ copyParametersToVariableList(context);
+ LOG.debug("parsing source " + path);
+ return parser.parseHtmlFile(path, context);
+ }
+
+ private void copyParametersToVariableList(final RequestContext context) {
+ /*
+ * Enumeration parameterNames = context.getParameterNames(); while
+ * (parameterNames.hasMoreElements()) { String name = (String)
+ * parameterNames.nextElement(); if (!name.equals("view")) {
+ * context.addVariable(name, context.getParameter(name), Scope.REQUEST);
+ * } }
+ */
+ }
+
+ public void init(final String dir, final DebugUsers debugUsers) {
+ addAction(new ActionAction());
+
+ // TODO remove
+ addAction(new DebugAction(this));
+ addAction(new DebugUserAction(debugUsers));
+ addAction(new EditAction());
+ addAction(new RemoveAction());
+ addAction(new LogonAction());
+ addAction(new LogoutAction());
+ addAction(new LogAction());
+
+ final String configFile = getParameter("config");
+ if (configFile != null) {
+ final File file = new File(dir, configFile);
+ if (file.exists()) {
+ loadConfigFile(file);
+ } else {
+ throw new ScimpiException("Configuration file not found: " + configFile);
+ }
+ }
+
+ processors.init();
+ processors.addElementProcessor(new org.apache.isis.viewer.scimpi.dispatcher.view.debug.Debug(this));
+
+ showUnshownMessages = IsisContext.getConfiguration().getBoolean(SHOW_UNSHOWN_MESSAGES, true);
+ }
+
+ private void loadConfigFile(final File file) {
+ try {
+ Document document;
+ final SAXReader reader = new SAXReader();
+ document = reader.read(file);
+ final Element root = document.getRootElement();
+ for (final Iterator i = root.elementIterator(); i.hasNext();) {
+ final Element element = (Element) i.next();
+
+ if (element.getName().equals("actions")) {
+ for (final Iterator actions = element.elementIterator("action"); actions.hasNext();) {
+ final Element action = (Element) actions.next();
+ final String className = action.getText();
+ final Action instance = (Action) InstanceUtil.createInstance(className);
+ addAction(instance);
+ }
+ }
+
+ if (element.getName().equals("processors")) {
+ for (final Iterator processors = element.elementIterator("processor"); processors.hasNext();) {
+ final Element processor = (Element) processors.next();
+ final String className = processor.getText();
+ final ElementProcessor instance = (ElementProcessor) InstanceUtil.createInstance(className);
+ this.processors.addElementProcessor(instance);
+ }
+ }
+
+ }
+ } catch (final DocumentException e) {
+ throw new IsisException(e);
+ }
+
+ }
+
+ private void addAction(final Action action) {
+ actions.put("/" + action.getName(), action);
+ action.init();
+ }
+
+ public void debug(final DebugBuilder debug) {
+ debug.startSection("Actions");
+ final Set<String> keySet = actions.keySet();
+ final ArrayList<String> list = new ArrayList<String>(keySet);
+ Collections.sort(list);
+ for (final String name : list) {
+ debug.appendln(name, actions.get(name));
+ }
+ /*
+ * new ArrayList<E>(actions.keySet().iterator()) Iterator<String> names
+ * = Collections.sort().iterator(); while (names.hasNext()) { String
+ * name = names.next(); view.appendRow(name, actions.get(name)); }
+ */
+ final Iterator<Action> iterator = actions.values().iterator();
+ while (iterator.hasNext()) {
+ iterator.next().debug(debug);
+ }
+
+ processors.debug(debug);
+ }
+}
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/ElementContentProcessor.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/ElementContentProcessor.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/ElementContentProcessor.java
new file mode 100644
index 0000000..eaae2ac
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/ElementContentProcessor.java
@@ -0,0 +1,24 @@
+/*
+ * 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;
+
+public interface ElementContentProcessor extends ElementProcessor {
+
+}
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/ElementProcessor.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/ElementProcessor.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/ElementProcessor.java
new file mode 100644
index 0000000..471ac00
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/ElementProcessor.java
@@ -0,0 +1,30 @@
+/*
+ * 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;
+
+import org.apache.isis.viewer.scimpi.dispatcher.processor.Request;
+
+public interface ElementProcessor {
+
+ String getName();
+
+ void process(Request 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/ErrorCollator.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/ErrorCollator.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/ErrorCollator.java
new file mode 100644
index 0000000..97e297e
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/ErrorCollator.java
@@ -0,0 +1,148 @@
+/*
+ * 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;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.isis.core.commons.config.ConfigurationConstants;
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.commons.debug.DebugHtmlString;
+import org.apache.isis.core.commons.debug.DebugString;
+import org.apache.isis.core.commons.debug.DebugTee;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.scimpi.dispatcher.context.RequestContext;
+import org.apache.isis.viewer.scimpi.dispatcher.debug.DebugHtmlWriter;
+
+public class ErrorCollator {
+ private static final Logger LOG = LoggerFactory.getLogger(ErrorCollator.class);
+
+ private String errorRef;
+ private String message;
+ private final DebugString debugText = new DebugString();
+ private final DebugHtmlString debugHtml = new DebugHtmlString();
+ private final DebugBuilder debug = new DebugTee(debugText, debugHtml);
+
+ public void missingFile(String message) {
+ this.message = message;
+ }
+
+ public void message(final Throwable exception) {
+ LOG.debug(exception.getMessage(), exception);
+ message = exception.getMessage();
+ debug.appendPreformatted(message);
+ }
+
+ public void exception(final Throwable exception) {
+ String messageText = exception.getMessage();
+ LOG.debug(messageText, exception);
+ try {
+ debug.startSection("Exception");
+ debug.appendException(exception);
+ debug.endSection();
+ } catch (final RuntimeException e) {
+ debug.appendln("NOTE - an exception occurred while dumping an exception!");
+ debug.appendException(e);
+ }
+ message = messageText == null ? exception.getClass().getName() : messageText;
+ }
+
+ public DebugBuilder getDebug() {
+ return debug;
+ }
+
+ public void compileError(final RequestContext requestContext) {
+ errorRef = Long.toString(System.currentTimeMillis(), 36).toUpperCase();
+ LOG.info("error " + errorRef);
+
+ captureWarningsAndMessages();
+ dumpDebugDetails(requestContext);
+ writeErrorFile();
+ }
+
+ private void captureWarningsAndMessages() {
+ // Capture warnings/messages
+ if (IsisContext.getCurrentTransaction() != null) {
+ final List<String> messages = IsisContext.getMessageBroker().getMessages();
+ final List<String> warnings = IsisContext.getMessageBroker().getWarnings();
+ if (messages.size() > 0 || messages.size() > 0) {
+ debug.startSection("Warnings/Messages");
+ for (final String message : messages) {
+ debug.appendln("message", message);
+ }
+ for (final String message : warnings) {
+ debug.appendln("warning", message);
+ }
+ }
+ }
+ }
+
+ private void dumpDebugDetails(final RequestContext requestContext) {
+ // Dump page debug details
+ requestContext.append(debug);
+
+ debug.startSection("Processing Trace");
+ debug.appendPreformatted(requestContext.getDebugTrace());
+ debug.endSection();
+ debug.close();
+ }
+
+ private void writeErrorFile() {
+ LOG.error(message + "\n" + debugText.toString());
+
+
+ PrintWriter writer;
+ try {
+ final String directory =
+ IsisContext.getConfiguration().getString(ConfigurationConstants.ROOT + "scimpi.error-snapshots", ".");
+ File dir = new File(directory);
+ if (!dir.exists()) {
+ dir.mkdirs();
+ }
+ writer = new PrintWriter(new File(dir, "error_" + errorRef + ".html"));
+ final DebugHtmlWriter writer2 = new DebugHtmlWriter(writer, true);
+ writer2.concat(debugHtml);
+ writer2.close();
+ writer.close();
+ } catch (final FileNotFoundException e) {
+ LOG.error("Failed to archive error page", e);
+ }
+ }
+
+ public String getReference() {
+ return errorRef;
+ }
+
+ public String getDetails() {
+ return debugHtml.toString();
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+
+}
+
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/ForbiddenException.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/ForbiddenException.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/ForbiddenException.java
new file mode 100644
index 0000000..32d0c0c
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/ForbiddenException.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;
+
+import java.util.List;
+
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.metamodel.facetapi.IdentifiedHolder;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+
+/**
+ * Indicates that request could not complete as it could not access (for
+ * security reasons) some of the content.
+ */
+public class ForbiddenException extends ScimpiException {
+ private static final long serialVersionUID = 1L;
+ public static final boolean VISIBLE_AND_USABLE = true;
+ public static final boolean VISIBLE = false;
+ private final Identifier identifier;
+ private final AuthenticationSession session;
+
+ public ForbiddenException(final String message) {
+ this(IsisContext.getAuthenticationSession(), message);
+ }
+
+ private ForbiddenException(final AuthenticationSession session, final String message) {
+ super(message + " for " + session.getUserName() + " " + session.getRoles());
+ this.session = session;
+ identifier = null;
+ }
+
+ public ForbiddenException(final IdentifiedHolder target, final boolean isVisibleAndUsabable) {
+ this(target.getIdentifier(), IsisContext.getAuthenticationSession(), isVisibleAndUsabable);
+ }
+
+ private ForbiddenException(final Identifier identifier, final AuthenticationSession session, final boolean isVisibleAndUsabable) {
+ super((identifier.getType() == Identifier.Type.PROPERTY_OR_COLLECTION ? "Field" : "Action") + " '" + identifier.getMemberName() + "' in " + identifier.getClassName() + " is not " + (isVisibleAndUsabable ? "visible/usable " : "visible") + " for " + session.getUserName() + " "
+ + session.getRoles());
+ this.identifier = identifier;
+ this.session = session;
+ }
+
+ public Identifier getIdentifier() {
+ return identifier;
+ }
+
+ public List<String> getRoles() {
+ return session.getRoles();
+ }
+}
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/Names.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/Names.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/Names.java
new file mode 100644
index 0000000..29b15e5
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/Names.java
@@ -0,0 +1,91 @@
+/*
+ * 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;
+
+public interface Names {
+ static final String PREFIX = "_logon-";
+
+ static final String BUTTON_TITLE = "button-title";
+ static final String CANCEL_TO = "cancel-to";
+ static final String COLLECTION = "collection";
+ static final String CONFIRM = "confirm";
+ static final String CLASS = "class";
+ static final String CONTAINER_CLASS = "container-" + CLASS;
+ static final String DEFAULT = "default";
+ static final String ELEMENT_NAME = "element-name";
+ static final String ELEMENT = "element";
+ static final String EVEN_ROW_CLASS = "even-row";
+ static final String FALSE = "false";
+ static final String ERROR = "error";
+ static final String FIELD = "field";
+ static final String FIELD_NAME = "field-name";
+ static final String FOOTER = "footer";
+ static final String FORM_ID = "form-id";
+ static final String FORM_TITLE = "title";
+ static final String FORMS = "show-forms";
+ static final String HEADER = "header";
+ static final String ICON_CLASS = "icon";
+ static final String HIDDEN = "hidden";
+ static final String HIDE_UNEDITABLE = "hide-uneditable";
+ static final String HEADER_LEVEL = "header";
+ static final String ID = "id";
+ static final String LABEL_DELIMITER = "label";
+ static final String LINK_VIEW = "link-view";
+ static final String LINK_NAME = "link-name";
+ static final String LINK_OBJECT = "link-object";
+ static final String METHOD = "method";
+ static final String MESSAGE = "message";
+ static final String NAME = "name";
+ static final String ODD_ROW_CLASS = "odd-row";
+ static final String OBJECT = "object";
+ static final String PARAMETER = "param";
+ static final String PARAMETER_NUMBER = "number";
+ static final String PLURAL = "plural";
+ static final String REFERENCE_NAME = "reference-name";
+ static final String RESULT_NAME = "result-name";
+ static final String RESULT_OVERRIDE = "result-override";
+ static final String ROW_CLASSES = "row-classes";
+ static final String SCOPE = "scope";
+ static final String SHOW_ICON = "icon";
+ static final String SHOW_SELECT = "select";
+ static final String SHOW_EDIT = "edit";
+ static final String SHOW_DELETE = "delete";
+ static final String SHOW_MESSAGE = "show-message";
+ static final String SHOW_TITLE = "show-title";
+ static final String TRUNCATE = "truncate";
+ static final String TABLE_TITLE = "title";
+ static final String TYPE = "type";
+ static final String VIEW = "view";
+ static final String VALUE = "value";
+ static final String VERSION = "version";
+ static final String USER = "user";
+ static final String VOID = "void";
+ static final String WHEN = "when";
+ static final String ENTRY_FIELDS = "entry-fields";
+
+
+ static final String LOGON_OBJECT = PREFIX + OBJECT;
+ static final String LOGON_METHOD = PREFIX + METHOD;
+ static final String LOGON_SCOPE = PREFIX + SCOPE;
+ static final String LOGON_RESULT_NAME = PREFIX + RESULT_NAME;
+ static final String LOGON_FORM_ID = PREFIX + "form-id";
+
+
+}
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/NotLoggedInException.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/NotLoggedInException.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/NotLoggedInException.java
new file mode 100644
index 0000000..9cd54a3
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/NotLoggedInException.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;
+
+/**
+ * Indicates that request could not complete as a user was not logged in.
+ */
+public class NotLoggedInException extends ScimpiException {
+ private static final long serialVersionUID = 1L;
+
+ public NotLoggedInException() {
+ }
+
+}
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/ResolveFieldUtil.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/ResolveFieldUtil.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/ResolveFieldUtil.java
new file mode 100644
index 0000000..a0ae5cf
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/ResolveFieldUtil.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;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+
+import static org.apache.isis.core.commons.ensure.Ensure.ensureThatState;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+
+public final class ResolveFieldUtil {
+
+ private ResolveFieldUtil(){}
+
+ /**
+ * Walking the graph.
+ *
+ * <p>
+ * This combines the implementations of both the DN Objectstore
+ * and also the in-memory objectstore.
+ * </p>
+ */
+ public static void resolveField(final ObjectAdapter object, final ObjectAssociation association) {
+
+
+ // DN impl.
+ {
+ final ObjectAdapter referencedCollectionAdapter = association.get(object);
+
+ // this code originally brought in from the JPA impl, but seems reasonable.
+ if (association.isOneToManyAssociation()) {
+ ensureThatState(referencedCollectionAdapter, is(notNullValue()));
+
+ final Object referencedCollection = referencedCollectionAdapter.getObject();
+ ensureThatState(referencedCollection, is(notNullValue()));
+
+ // if a proxy collection, then force it to initialize. just 'touching' the object is sufficient.
+ // REVIEW: I wonder if this is actually needed; does JDO use proxy collections?
+ referencedCollection.hashCode();
+ }
+
+ // the JPA impl used to also call its lifecycle listener on the referenced collection object, eg List,
+ // itself. I don't think this makes sense to do for JDO (the collection is not a PersistenceCapable).
+ }
+
+ // In-memory objectstore impl
+ {
+ final ObjectAdapter referenceAdapter = association.get(object);
+ referenceAdapter.markAsResolvedIfPossible();
+ }
+
+ }
+
+}
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/ScimpiException.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/ScimpiException.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/ScimpiException.java
new file mode 100644
index 0000000..18e7646
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/ScimpiException.java
@@ -0,0 +1,44 @@
+/*
+ * 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;
+
+public class ScimpiException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ public ScimpiException() {
+ }
+
+ public ScimpiException(final String message) {
+ super(message);
+ }
+
+ public ScimpiException(final Throwable cause) {
+ super(cause);
+ }
+
+ public ScimpiException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+
+ public String getHtmlMessage() {
+ return getMessage();
+ }
+
+}
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/ScimpiNotFoundException.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/ScimpiNotFoundException.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/ScimpiNotFoundException.java
new file mode 100644
index 0000000..6b1e77a
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/ScimpiNotFoundException.java
@@ -0,0 +1,41 @@
+/*
+ * 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;
+
+public class ScimpiNotFoundException extends ScimpiException {
+ public ScimpiNotFoundException() {
+ super();
+ }
+
+ public ScimpiNotFoundException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+
+ public ScimpiNotFoundException(final String message) {
+ super(message);
+ }
+
+ public ScimpiNotFoundException(final Throwable cause) {
+ super(cause);
+ }
+
+ private static final long serialVersionUID = 1L;
+
+}
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/TagOrderException.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/TagOrderException.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/TagOrderException.java
new file mode 100644
index 0000000..97e00e4
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/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;
+
+import org.apache.isis.viewer.scimpi.dispatcher.processor.Request;
+
+public class TagOrderException extends ScimpiException {
+ private static final long serialVersionUID = 1L;
+
+ public TagOrderException(final Request request) {
+ super("Invalid tag in this context: " + request.getTag().getName());
+ }
+
+}
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/UserManager.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/UserManager.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/UserManager.java
new file mode 100644
index 0000000..cdb1b04
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/UserManager.java
@@ -0,0 +1,91 @@
+/*
+ * 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;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+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.isis.viewer.scimpi.dispatcher.context.RequestContext;
+
+public class UserManager {
+
+ private static final Logger LOG = LoggerFactory.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 RequestContext context) {
+ AuthenticationSession session = context.getSession();
+ if (session == null) {
+ session = new AnonymousSession();
+ LOG.debug("start anonymous request: " + session);
+ } else {
+ LOG.debug("start request for: " + session.getUserName());
+ }
+ IsisContext.closeSession();
+ IsisContext.openSession(session);
+ return session;
+ }
+
+ 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;
+ }
+}
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/Util.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/Util.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/Util.java
new file mode 100644
index 0000000..b485dd0
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/Util.java
@@ -0,0 +1,105 @@
+/*
+ * 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;
+
+import java.text.DateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.TimeZone;
+
+class Util {
+
+ public static final String DEFAULT_TIME_ZONE = "Europe/London";
+ public static final String DEFAULT_LANGUAGE = "English, United Kingdom (en-gb)";
+
+
+ private Util() {}
+
+ public static boolean hasChanged(String version1, String version2) {
+ return version2 == null && version1 != null || (version2 != null && !version2.equals(version1));
+ }
+
+ public static List<String> languages() {
+ Locale[] locales = DateFormat.getAvailableLocales();
+ List<String> list = new ArrayList<String>(locales.length);
+ for (Locale locale : locales) {
+ list.add(localeName(locale));
+ }
+ Collections.sort(list);
+ return list;
+ }
+
+ public static List<String> timeZones() {
+ List<String> timezones = Arrays.asList(TimeZone.getAvailableIDs());
+ Collections.sort(timezones);
+ return timezones;
+ }
+
+ public static TimeZone timeZone(String timeZoneEntry) {
+ TimeZone timeZone = TimeZone.getTimeZone(timeZoneEntry);
+ return timeZone;
+ }
+
+ public static Locale locale(String localeCode) {
+ String substring[] = localeCode.trim().split("-");
+ Locale locale;
+ switch (substring.length) {
+ case 1:
+ locale = new Locale(substring[0]);
+ break;
+ case 2:
+ locale = new Locale(substring[0], substring[1]);
+ break;
+ case 3:
+ locale = new Locale(substring[0], substring[1], substring[3]);
+ break;
+ default:
+ locale = Locale.getDefault();
+ break;
+ }
+ return locale;
+ }
+
+ public static String languageName(String languageCode) {
+ Locale locale = locale(languageCode);
+ return localeName(locale);
+ }
+
+ public static String codeForLanguage(String language) {
+ Locale[] locales = DateFormat.getAvailableLocales();
+ for (Locale locale : locales) {
+ String name = localeName(locale);
+ if (name.equals(language)) {
+ return locale.toString().toLowerCase().replace('_', '-');
+ }
+ }
+ return null;
+ }
+
+ public static String localeName(Locale locale) {
+ String language = locale.getDisplayLanguage();
+ String country = locale.getDisplayCountry().length() == 0 ? "" : ", " + (locale.getDisplayCountry());
+ return language + country + " (" + locale.toString().toLowerCase().replace('_', '-') + ")";
+ }
+
+}
\ No newline at end of file
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/action/ActionAction.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/action/ActionAction.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/action/ActionAction.java
new file mode 100644
index 0000000..44a9756
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/action/ActionAction.java
@@ -0,0 +1,268 @@
+/*
+ * 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.action;
+
+import java.io.IOException;
+import java.util.List;
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.applib.profiles.Localization;
+import org.apache.isis.core.commons.authentication.AnonymousSession;
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.commons.authentication.MessageBroker;
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.adapter.version.ConcurrencyException;
+import org.apache.isis.core.metamodel.adapter.version.Version;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.metamodel.consent.Veto;
+import org.apache.isis.core.metamodel.facets.object.parseable.ParseableFacet;
+import org.apache.isis.core.metamodel.facets.object.parseable.TextEntryParseException;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.scimpi.dispatcher.Action;
+import org.apache.isis.viewer.scimpi.dispatcher.Dispatcher;
+import org.apache.isis.viewer.scimpi.dispatcher.context.RequestContext;
+import org.apache.isis.viewer.scimpi.dispatcher.context.RequestContext.Scope;
+import org.apache.isis.viewer.scimpi.dispatcher.edit.FieldEditState;
+import org.apache.isis.viewer.scimpi.dispatcher.edit.FormState;
+import org.apache.isis.viewer.scimpi.dispatcher.util.MethodsUtils;
+
+public class ActionAction implements Action {
+
+ public static final String ACTION = "action";
+
+ // REVIEW: should provide this rendering context, rather than hardcoding.
+ // the net effect currently is that class members annotated with
+ // @Hidden(where=Where.ANYWHERE) or @Disabled(where=Where.ANYWHERE) will indeed
+ // be hidden/disabled, but will be visible/enabled (perhaps incorrectly)
+ // for any other value for Where
+ private final Where where = Where.ANYWHERE;
+
+ @Override
+ public String getName() {
+ return ACTION;
+ }
+
+ /**
+ * REVIEW - this and EditAction are very similar - refactor out common code.
+ */
+ @Override
+ public void process(final RequestContext context) throws IOException {
+ final String objectId = context.getParameter("_" + OBJECT);
+ final String version = context.getParameter("_" + VERSION);
+ final String formId = context.getParameter("_" + FORM_ID);
+ final String methodName = context.getParameter("_" + METHOD);
+ final String override = context.getParameter("_" + RESULT_OVERRIDE);
+ String resultName = context.getParameter("_" + RESULT_NAME);
+ final String message = context.getParameter("_" + MESSAGE);
+ resultName = resultName == null ? RequestContext.RESULT : resultName;
+
+ FormState entryState = null;
+ try {
+ final ObjectAdapter object = MethodsUtils.findObject(context, objectId);
+ // FIXME need to find method based on the set of parameters.
+ // otherwise overloaded method may be incorrectly
+ // selected.
+ final ObjectAction action = MethodsUtils.findAction(object, methodName);
+ entryState = validateParameters(context, action, object);
+
+ AuthenticationSession session = context.getSession();
+ if (session == null && action.isVisible(new AnonymousSession(), object, where).isVetoed()) {
+ session = new AnonymousSession();
+ }
+
+ final Version originalVersion = context.getVersion(version);
+ object.checkLock(originalVersion);
+ if (entryState.isValid()) {
+ final boolean hasResult = invokeMethod(context, resultName, object, action, entryState);
+ String view = context.getParameter(hasResult ? "_" + VIEW : "_" + VOID);
+
+ final int questionMark = view == null ? -1 : view.indexOf("?");
+ if (questionMark > -1) {
+ final String params[] = view.substring(questionMark + 1).split("&");
+ for (final String param : params) {
+ final int equals = param.indexOf("=");
+ context.addVariable(param.substring(0, equals), param.substring(equals + 1), Scope.REQUEST);
+ view = view.substring(0, questionMark);
+ }
+ }
+ context.setRequestPath(view);
+ if (message != null) {
+ final MessageBroker messageBroker = getMessageBroker();
+ messageBroker.addMessage(message);
+ }
+ if (override != null) {
+ context.addVariable(resultName, override, Scope.REQUEST);
+ }
+ if (!action.hasReturn() && context.getVariable(resultName) == null) {
+ context.addVariable(resultName, objectId, Scope.REQUEST);
+ }
+ } else {
+ entryState.setForm(formId);
+ context.addVariable(ENTRY_FIELDS, entryState, Scope.REQUEST);
+ context.addVariable(resultName, objectId, Scope.REQUEST);
+ if (override != null) {
+ context.addVariable(resultName, override, Scope.REQUEST);
+ }
+ final String error = entryState.getError();
+ final String view = context.getParameter("_" + ERROR);
+ context.setRequestPath(view, Dispatcher.ACTION);
+
+ final MessageBroker messageBroker = getMessageBroker();
+ messageBroker.addWarning(error);
+ }
+ } catch (final ConcurrencyException e) {
+ final ObjectAdapter adapter = getAdapterManager().getAdapterFor(e.getOid());
+ String user = adapter.getOid().getVersion().getUser();
+ String errorMessage = "The data for '" + adapter.titleString() + "' was changed by " + user
+ + ". Please repeat the action based on those changes.";
+ getMessageBroker().addMessage(errorMessage);
+
+ entryState.setForm(formId);
+ context.addVariable(ENTRY_FIELDS, entryState, Scope.REQUEST);
+ context.addVariable(resultName, objectId, Scope.REQUEST);
+ if (override != null) {
+ context.addVariable(resultName, override, Scope.REQUEST);
+ }
+ final String error = entryState.getError();
+ if (error != null) {
+ context.addVariable(RequestContext.ERROR, error, Scope.REQUEST);
+ }
+
+ final String view = context.getParameter("_" + ERROR);
+ context.setRequestPath(view, Dispatcher.ACTION);
+
+ } catch (final RuntimeException e) {
+ getMessageBroker().getMessages();
+ getMessageBroker().getWarnings();
+ throw e;
+ }
+ }
+
+ private boolean invokeMethod(final RequestContext context, final String variable, final ObjectAdapter object, final ObjectAction action, final FormState entryState) {
+
+ final ObjectAdapter[] parameters = getParameters(action, entryState);
+ final String scopeName = context.getParameter("_" + SCOPE);
+ final Scope scope = RequestContext.scope(scopeName, Scope.REQUEST);
+ return MethodsUtils.runMethod(context, action, object, parameters, variable, scope);
+ }
+
+ private ObjectAdapter[] getParameters(final ObjectAction action, final FormState entryState) {
+ final int parameterCount = action.getParameterCount();
+ final ObjectAdapter[] parameters = new ObjectAdapter[parameterCount];
+ for (int i = 0; i < parameterCount; i++) {
+ parameters[i] = entryState.getField(parameterName(i)).getValue();
+ }
+ return parameters;
+ }
+
+ private FormState validateParameters(final RequestContext context, final ObjectAction action, final ObjectAdapter object) {
+ final FormState formState = new FormState();
+ final List<ObjectActionParameter> parameters2 = action.getParameters();
+ final int parameterCount = action.getParameterCount();
+ for (int i = 0; i < parameterCount; i++) {
+ final String fieldName = parameterName(i);
+ String newEntry = context.getParameter(fieldName);
+
+ if (newEntry != null && newEntry.equals("-OTHER-")) {
+ newEntry = context.getParameter(fieldName + "-other");
+ }
+
+ if (newEntry == null) {
+ // TODO figure out a better way to determine if boolean or a
+ // password
+ final ObjectSpecification spec = parameters2.get(i).getSpecification();
+ if (spec.isOfType(IsisContext.getSpecificationLoader().loadSpecification(boolean.class)) || spec.isOfType(IsisContext.getSpecificationLoader().loadSpecification(Boolean.class))) {
+ newEntry = FALSE;
+ } else {
+ newEntry = "";
+ }
+ }
+ final FieldEditState fieldState = formState.createField(fieldName, newEntry);
+ Consent consent = null;
+
+ if (!parameters2.get(i).isOptional() && newEntry.equals("")) {
+ consent = new Veto(parameters2.get(i).getName() + " required");
+ formState.setError("Not all fields have been set");
+
+ } else if (parameters2.get(i).getSpecification().getFacet(ParseableFacet.class) != null) {
+ try {
+ final ParseableFacet facet = parameters2.get(i).getSpecification().getFacet(ParseableFacet.class);
+ Localization localization = IsisContext.getLocalization();
+ final String message = parameters2.get(i).isValid(object, newEntry, localization);
+ if (message != null) {
+ consent = new Veto(message);
+ formState.setError("Not all fields are valid");
+ }
+ final ObjectAdapter entry = facet.parseTextEntry(null, newEntry, localization);
+ fieldState.setValue(entry);
+ } catch (final TextEntryParseException e) {
+ consent = new Veto(e.getMessage());
+ formState.setError("Not all fields are valid");
+ }
+ } else {
+ fieldState.setValue(newEntry == null ? null : context.getMappedObject(newEntry));
+ }
+ if (consent != null && consent.isVetoed()) {
+ fieldState.setError(consent.getReason());
+ }
+ }
+
+ if (formState.isValid()) {
+ final ObjectAdapter[] parameters = getParameters(action, formState);
+ final Consent consent = action.isProposedArgumentSetValid(object, parameters);
+ if (consent != null && consent.isVetoed()) {
+ formState.setError(consent.getReason());
+ }
+ }
+
+ return formState;
+ }
+
+ public static String parameterName(final int index) {
+ return PARAMETER + (index + 1);
+ }
+
+ @Override
+ public void init() {
+ }
+
+ @Override
+ public void debug(final DebugBuilder debug) {
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // from context
+ ///////////////////////////////////////////////////////////////////////////
+
+ protected MessageBroker getMessageBroker() {
+ return IsisContext.getMessageBroker();
+ }
+
+ protected AdapterManager getAdapterManager() {
+ return IsisContext.getPersistenceSession().getAdapterManager();
+ }
+
+
+}
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/action/Attributes.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/action/Attributes.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/action/Attributes.java
new file mode 100644
index 0000000..67d13e2
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/action/Attributes.java
@@ -0,0 +1,131 @@
+/*
+ * 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.action;
+
+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.RequestContext;
+
+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 RequestContext context;
+
+ public Attributes(final TagNode tagNode, final RequestContext 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/2c7cfbfe/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/action/PropertyException.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/action/PropertyException.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/action/PropertyException.java
new file mode 100644
index 0000000..2e42188
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/action/PropertyException.java
@@ -0,0 +1,44 @@
+/*
+ * 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.action;
+
+import org.apache.isis.viewer.scimpi.dispatcher.ScimpiException;
+
+public class PropertyException extends ScimpiException {
+
+ private static final long serialVersionUID = 1L;
+
+ public PropertyException() {
+ super();
+ }
+
+ public PropertyException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+
+ public PropertyException(final String message) {
+ super(message);
+ }
+
+ public PropertyException(final Throwable cause) {
+ super(cause);
+ }
+
+}
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/action/RequiredPropertyException.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/action/RequiredPropertyException.java b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/action/RequiredPropertyException.java
new file mode 100644
index 0000000..20430d3
--- /dev/null
+++ b/mothballed/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/action/RequiredPropertyException.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.action;
+
+import org.apache.isis.viewer.scimpi.dispatcher.ScimpiException;
+
+public class RequiredPropertyException extends ScimpiException {
+ private static final long serialVersionUID = 1L;
+
+ public RequiredPropertyException() {
+ super();
+ }
+
+ public RequiredPropertyException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+
+ public RequiredPropertyException(final String message) {
+ super(message);
+ }
+
+ public RequiredPropertyException(final Throwable cause) {
+ super(cause);
+ }
+
+}