coliver 2003/04/26 18:57:05
Modified: src/scratchpad/webapp/samples scratchpad-samples.xml Added: src/scratchpad/src/org/apache/cocoon/components/jxforms/flow jxForm.js src/scratchpad/src/org/apache/cocoon/generation JXFormsGenerator.java src/scratchpad/src/org/apache/cocoon/transformation JXFormsTransformer.java src/scratchpad/webapp/samples/jxforms sitemap.xmap src/scratchpad/webapp/samples/jxforms/flow feedbackWizard.js src/scratchpad/webapp/samples/jxforms/schematron wizard-xmlform-sch-report.xml src/scratchpad/webapp/samples/jxforms/stylesheets jxforms-default.xsl jxforms2html.xsl wizard2html.xsl src/scratchpad/webapp/samples/jxforms/view confirm.xml deployment.xml end.xml start.xml system.xml userIdentity.xml Log: First cut of reimplementation of XMLForm to be in line with W3 candidate recommendation. Renamed to JXForms to emphasize its reliance on Apache JXPath Revision Changes Path 1.1 cocoon-2.1/src/scratchpad/src/org/apache/cocoon/components/jxforms/flow/jxForm.js Index: jxForm.js =================================================================== // // JXForms support // /** * Creates a new JavaScript wrapper of a Form object * see org.apache.cocoon.components.xmlform.Form * @param id [String] unique form id * @param validatorNS [String] Namespace of validator * @param validatorDoc [String] Validator document * @param scope [String] either "request" or "session" */ function JXForm(id, validatorNS, validatorDoc, scope) { if (scope == "session") { cocoon.createSession(); } this.cocoon = cocoon; // workaround for Rhino dynamic scope bug this.id = id; this.lastWebContinuation = null; this.validatorNS = validatorNS; this.validatorDoc = validatorDoc; this.submitId = undefined; this.dead = false; } JXForm.jxpathContextFactory = Packages.org.apache.commons.jxpath.JXPathContextFactory.newInstance(); /** * Return the model object of this form * @return [Object] a Java bean, JavaScript, DOM, or JDOM object */ JXForm.prototype.getModel = function() { return this.form.getModel(); } /** * Return the id of the xf:submit element of the current form submission * @return [String] id attribute of the button that caused this form to be submitted */ JXForm.prototype.getSubmitId = function() { return this.submitId; } /** * Set the model object of this form * @param model [Object] Any Java bean, JavaScript, DOM, or JDOM object */ JXForm.prototype.setModel = function(model) { this.form = new Packages.org.apache.cocoon.components.xmlform.Form(this.id, model); this.context = JXForm.jxpathContextFactory.newContext(null, model); this.form.setAutoValidate(false); if (this.validatorNS != undefined && this.validatorDoc != undefined) { this._setValidator(this.validatorNS, this.validatorDoc); } } /** * Creates a new web continuation * @param lastWebCont [WebContinuation] previous web continuation * @param timeToLive [Number] expiration time for this continuation in milliseconds * @return [WebContinuation] a new WebContinuation instance */ JXForm.prototype.start = function(lastWebCont, timeToLive) { var result = this._start(lastWebCont, timeToLive); // // _start() will return an Object when it's called // the first time. However, when its Continuation is invoked it // will return a WebContinuation instead. In the latter case // we're going back to the previous page: so // clear the current page's violations before showing the previous page. // Without this, violations from the current page will // incorrectly be displayed on the previous page. if (result instanceof WebContinuation) { this.form.clearViolations(); return result; } return result.kont; } JXForm.prototype._start = function(lastWebCont, timeToLive) { var k = new Continuation(); var kont = new WebContinuation(this.cocoon, k, lastWebCont, timeToLive); return {kont: kont}; } /** * Adds a violation to this form * @param xpath [String] xpath location of field that contains invalid data * @param message [String] error message */ JXForm.prototype.addViolation = function(xpath, message) { var violation = new Packages.org.apache.cocoon.components.validation.Violation(); violation.path = xpath; violation.message = message; var list = new java.util.LinkedList(); list.add(violation); try { this.form.addViolations(list); } catch (e) { print(e); if (e instanceof java.lang.Throwable) { e.printStackTrace(); } } } /** * Does this form have violations? * @return [Boolean] true if violations have been added to this form */ JXForm.prototype.hasViolations = function() { var set = this.form.violationsAsSortedSet; return set != null && set.size() > 0; } /** * Computes the value of an xpath expression against the model of this form * @param expr [String] xpath expression * @return [Object] result of computing <code>expr</code> */ JXForm.prototype.getValue = function(expr) { return this.context.getValue(expr); } /** * Returns an iterator over a nodeset value of an xpath expression evaluated * against the model of this form * @param expr [String] xpath expression * @return [java.util.Iterator] representing a nodeset */ JXForm.prototype.iterate = function(expr) { return this.context.iterate(expr); } JXForm.prototype._sendView = function(uri, lastCont, timeToLive) { var k = new Continuation(); var wk = new WebContinuation(this.cocoon, k, lastCont, timeToLive); var bizData = this.form.getModel(); if (bizData == undefined) { bizData = null; } this.cocoon.forwardTo("cocoon://" + this.cocoon.environment.getURIPrefix() + uri, bizData, wk); suicide(); } /** * Sends view to presentation pipeline and waits for subsequent submission. * Automatically resends view if validation fails. * Creates two continuations: one immediately before the page is sent * and one immediately after. These are used to implement automated support * for back/forward navigation in the form. When you move forward in the * form the second continuation is invoked. When you move back from the * following page the first continuation is invoked. * @param phase [String] phase to validate * @param uri [String] presentation pipeline resource identifier of view * @param validator [Function] optional function invoked to perform validation */ JXForm.prototype.sendView = function(view, uri, validator) { var lastWebCont = this.lastWebContinuation; var wk = this.start(lastWebCont); while (true) { // create a continuation, the invocation of which will resend // the page: this is used to implement <xf:submit continuation="back"> if (this.cocoon.request == null) { // this continuation has been invalidated this.dead = true; handleInvalidContinuation(); suicide(); } // reset the view in case this is a re-invocation of a continuation this.cocoon.request.setAttribute("view", view); this.form.remove(this.cocoon.environment.objectModel, this.id); this.form.save(this.cocoon.environment.objectModel, "request"); var thisWebCont = this._sendView(uri, wk); // _sendView creates a continuation, the invocation of which // will return right here: it is used to implement // <xf:submit continuation="forward"> if (this.dead || this.cocoon.request == null) { // this continuation has been invalidated handleInvalidContinuation(); suicide(); } this.form.populate(this.cocoon.environment.objectModel); this.submitId = this.cocoon.request.getAttribute("jxform-submit-id"); if (validator != undefined) { validator(this); } this.form.validate(view); if (!this.hasViolations()) { this.lastWebContinuation = thisWebCont; break; } } } JXForm.prototype._setValidator = function(schNS, schDoc) { // if validator params are not specified, then // there is no validation by default if (schNS == null || schDoc == null ) return null; var resolver = this.cocoon.environment; var schemaSrc = resolver.resolveURI( schDoc ); try { var is = Packages.org.apache.cocoon.components.source.SourceUtil.getInputSource(schemaSrc); var schf = Packages.org.apache.cocoon.components.validation.SchemaFactory.lookup ( schNS ); var sch = schf.compileSchema ( is ); this.form.setValidator(sch.newValidator()); } finally { resolver.release(schemaSrc); } } /** * Sends view to presentation pipeline but doesn't wait for submission * @param uri [String] presentation pipeline uri */ JXForm.prototype.finish = function(uri) { this.form.remove(this.cocoon.environment.objectModel, this.id); this.form.save(this.cocoon.environment.objectModel, "request"); this.cocoon.forwardTo("cocoon://" + this.cocoon.environment.getURIPrefix() + uri, this.form.getModel(), null); this.dead = true; if (this.lastWebContinuation != null) { this.lastWebContinuation.invalidate(); this.lastWebContinuation = null; } } /** * Entry point to a flow-based JXForm application. Replaces the functionality * of XMLForm actions. * @param application [String] Name of a JavaScript function that represents the page flow for a form * @param id [String] Form id * @param validator_ns [String] XML namespace of validator * @param validator_doc [String] Validator document * @param scope [String] one of "request" or "session" */ function jxForm(application, id, validator_ns, validator_doc, scope) { if (cocoon.request == null) { handleInvalidContinuation(""); return; } function getCommand() { var enum_ = cocoon.request.parameterNames; var command = undefined; while (enum_.hasMoreElements()) { var paramName = enum_.nextElement(); // search for the command if (paramName.startsWith(Packages.org.apache.cocoon.Constants.ACTION_PARAM_PREFIX)) { command = paramName.substring(Packages.org.apache.cocoon.Constants.ACTION_PARAM_PREFIX.length(), paramName.length()); break; } } // command encodes the continuation id for "back" or "next" actions return command; } var command = getCommand(); if (command != undefined) { // invoke a continuation // command looks like kontId:id var id = ""; var kontId = command; var index = command.indexOf(java.lang.String(":").charAt(0)); if (index > 0) { var kontId = command.substring(0, index); if (index + 1 < command.length()) { id = command.substring(index + 1); } } cocoon.request.setAttribute("jxform-submit-id", id); cocoon.interpreter.handleContinuation(kontId, null, cocoon.environment); return; } if (id != null) { // Just start a new instance of the application var args = new Array(arguments.length - 5 + 1); args[0] = new JXForm(id, validator_ns, validator_doc, scope); for (var i = 5; i < arguments.length; i++) { args[i-4] = arguments[i]; } this[application].apply(this, args); } else { handleInvalidContinuation(command); } } 1.1 cocoon-2.1/src/scratchpad/src/org/apache/cocoon/generation/JXFormsGenerator.java Index: JXFormsGenerator.java =================================================================== /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- ============================================================================ The Apache Software License, Version 1.1 ============================================================================ Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modifica- tion, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by the Apache Software Foundation (http://www.apache.org/)." Alternately, this acknowledgment may appear in the software itself, if and wherever such third-party acknowledgments normally appear. 4. The names "Apache Cocoon" and "Apache Software Foundation" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact [EMAIL PROTECTED] 5. Products derived from this software may not be called "Apache", nor may "Apache" appear in their name, without prior written permission of the Apache Software Foundation. THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. This software consists of voluntary contributions made by many individuals on behalf of the Apache Software Foundation and was originally created by Stefano Mazzocchi <[EMAIL PROTECTED]>. For more information on the Apache Software Foundation, please see <http://www.apache.org/>. */ package org.apache.cocoon.generation; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Stack; import org.apache.cocoon.components.xmlform.Form; import org.apache.cocoon.components.validation.Violation; import org.apache.avalon.framework.parameters.Parameters; import org.apache.cocoon.ProcessingException; import org.apache.cocoon.transformation.AbstractTransformer; import org.apache.cocoon.components.flow.WebContinuation; import org.apache.cocoon.components.source.SourceUtil; import org.apache.cocoon.environment.Environment; import org.apache.cocoon.environment.ObjectModelHelper; import org.apache.cocoon.environment.Request; import org.apache.cocoon.environment.Response; import org.apache.cocoon.environment.SourceResolver; import org.apache.cocoon.xml.XMLConsumer; import org.apache.commons.jxpath.CompiledExpression; import org.apache.commons.jxpath.JXPathContext; import org.apache.commons.jxpath.JXPathContextFactory; import org.apache.commons.jxpath.Pointer; import org.apache.excalibur.source.Source; import org.apache.excalibur.source.SourceException; import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; import org.xml.sax.Locator; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import org.xml.sax.ext.LexicalHandler; import org.xml.sax.helpers.AttributesImpl; import org.xml.sax.helpers.LocatorImpl; /** * <p><a href="http://jakarta.apache.org/commons/jxpath"><em>JX</em>Path</a> based implementation of <a href="http://www.w3.org/TR/xforms"><em>XForms</em></a></p> */ public class JXFormsGenerator extends AbstractGenerator { private static final JXPathContextFactory jxpathContextFactory = JXPathContextFactory.newInstance(); private static final char[] EMPTY_CHARS = "".toCharArray(); private static final Attributes EMPTY_ATTRS = new AttributesImpl(); private static final Iterator EMPTY_ITER = new Iterator() { public boolean hasNext() { return false; } public Object next() { return null; } public void remove() { } }; private static final Iterator NULL_ITER = new Iterator() { public boolean hasNext() { return true; } public Object next() { return null; } public void remove() { } }; final static String NS = "http://cocoon.apache.org/jxforms/2002/cr"; // Non XForms elements final static String FORM = "form"; final static String VIOLATIONS = "violations"; final static String VIOLATION = "violation"; final static String HIDDEN = "hidden"; /* Form Controls */ final static String INPUT = "input"; final static String SECRET = "secret"; final static String TEXTAREA = "textarea"; final static String OUTPUT = "output"; final static String UPLOAD = "upload"; final static String RANGE = "range"; final static String TRIGGER = "trigger"; final static String SUBMIT = "submit"; final static String SELECT = "select"; final static String SELECT1 = "select1"; /* Selection Controls */ final static String CHOICES = "choices"; final static String ITEM = "item"; final static String VALUE = "value"; /* Additional Elements */ final static String FILENAME = "filename"; final static String MEDIATYPE = "mediatype"; final static String LABEL = "label"; final static String HELP = "help"; final static String HINT = "hint"; final static String ALERT = "alert"; /* Group Module */ final static String GROUP = "group"; /* Switch Module */ final static String SWITCH = "switch"; final static String CASE = "case"; final static String TOGGLE = "toggle"; /* Repeat Module */ final static String REPEAT = "repeat"; final static String ITEMSET = "itemset"; final static String COPY = "copy"; final static String INSERT = "insert"; final static String DELETE = "delete"; final static String SETINDEX = "setindex"; /* Attributes */ final static String NODESET = "nodeset"; final static String REF = "ref"; final static String ID = "id"; final static String VIEW = "view"; final static String BACK = "back"; final static String FORWARD = "forward"; final static String CONTINUATION = "continuation"; /** * Compile a single XPath expression */ static private CompiledExpression compileExpr(JXPathContext context, String expr, Locator location) throws SAXParseException { if (expr == null) return null; try { return context.compile(expr); } catch (Exception exc) { throw new SAXParseException(exc.getMessage(), location, exc); } catch (Error err) { throw new SAXParseException(err.getMessage(), location, null); } } static class Event { final Locator location; Event next; Event(Locator location) { this.location = new LocatorImpl(location); } public String locationString() { String result = ""; String systemId = location.getSystemId(); if (systemId != null) { result += systemId + ", "; } result += "Line " + location.getLineNumber(); int col = location.getColumnNumber(); if (col > 0) { result += "." + col; } return result; } } static class TextEvent extends Event { TextEvent(Locator location, char[] chars, int start, int length) throws SAXException { super(location); this.chars = new char[length]; System.arraycopy(chars, start, this.chars, 0, length); } final char[] chars; } static class Characters extends TextEvent { Characters(Locator location, char[] chars, int start, int length) throws SAXException { super(location, chars, start, length); } } static class StartDocument extends Event { StartDocument(Locator location) { super(location); } long compileTime; EndDocument endDocument; // null if document fragment } static class EndDocument extends Event { EndDocument(Locator location) { super(location); } } static class EndElement extends Event { EndElement(Locator location, StartElement startElement) { super(location); this.startElement = startElement; } final StartElement startElement; } static class EndPrefixMapping extends Event { EndPrefixMapping(Locator location, String prefix) { super(location); this.prefix = prefix; } final String prefix; } static class IgnorableWhitespace extends TextEvent { IgnorableWhitespace(Locator location, char[] chars, int start, int length) throws SAXException { super(location, chars, start, length); } } static class ProcessingInstruction extends Event { ProcessingInstruction(Locator location, String target, String data) { super(location); this.target = target; this.data = data; } final String target; final String data; } static class SkippedEntity extends Event { SkippedEntity(Locator location, String name) { super(location); this.name = name; } final String name; } static class StartElement extends Event { StartElement(Locator location, String namespaceURI, String localName, String raw, Attributes attrs) throws SAXException { super(location); this.namespaceURI = namespaceURI; this.localName = localName; this.raw = raw; this.attributes = new AttributesImpl(attrs); } final String namespaceURI; final String localName; final String raw; final Attributes attributes; EndElement endElement; } static class StartPrefixMapping extends Event { StartPrefixMapping(Locator location, String prefix, String uri) { super(location); this.prefix = prefix; this.uri = uri; } final String prefix; final String uri; } static class Comment extends TextEvent { Comment(Locator location, char[] chars, int start, int length) throws SAXException { super(location, chars, start, length); } } static class EndCDATA extends Event { EndCDATA(Locator location) { super(location); } } static class EndDTD extends Event { EndDTD(Locator location) { super(location); } } static class EndEntity extends Event { EndEntity(Locator location, String name) { super(location); this.name = name; } final String name; } static class StartCDATA extends Event { StartCDATA(Locator location) { super(location); } } static class StartDTD extends Event { StartDTD(Locator location, String name, String publicId, String systemId) { super(location); this.name = name; this.publicId = publicId; this.systemId = systemId; } final String name; final String publicId; final String systemId; } static class StartEntity extends Event { public StartEntity(Locator location, String name) { super(location); this.name = name; } final String name; } /* Form Controls */ static final String[] INPUT_CONTROLS = { INPUT, SECRET, TEXTAREA, SELECT, SELECT1 }; static final String[] READONLY_INPUT_CONTROLS = { HINT, VALUE, HELP, LABEL }; private static boolean isInputControl(String name) { for (int i = 0; i < INPUT_CONTROLS.length; i++) { if (INPUT_CONTROLS[i].equals(name)) { return true; } } return false; } private static boolean isReadonlyInputControl(String name) { for (int i = 0; i < READONLY_INPUT_CONTROLS.length; i++) { if (READONLY_INPUT_CONTROLS[i].equals(name)) { return true; } } return false; } // input, secret, textarea, select1, select static class StartInputControl extends Event { StartInputControl(Locator location, CompiledExpression ref, StartElement startElement) throws SAXException { super(location); this.ref = ref; this.startElement = startElement; } final CompiledExpression ref; final StartElement startElement; EndInputControl endInputControl; } static class EndInputControl extends Event { EndInputControl(Locator location, StartInputControl start) { super(location); this.startInputControl = start; start.endInputControl = this; } final StartInputControl startInputControl; } // hint, value, label, help static class StartReadonlyInputControl extends Event { StartReadonlyInputControl(Locator location, CompiledExpression ref, StartElement startElement) throws SAXException { super(location); this.ref = ref; this.startElement = startElement; } final CompiledExpression ref; final StartElement startElement; EndReadonlyInputControl endReadonlyInputControl; } static class EndReadonlyInputControl extends Event { EndReadonlyInputControl(Locator location, StartReadonlyInputControl start) { super(location); this.startReadonlyInputControl = start; start.endReadonlyInputControl = this; } final StartReadonlyInputControl startReadonlyInputControl; } static class StartForm extends Event { StartForm(Locator location, StartElement start) throws SAXException { super(location); this.startElement = start; this.formId = start.attributes.getValue("id"); } final StartElement startElement; final String formId; EndForm endForm; } static class EndForm extends Event { EndForm(Locator location, StartForm start) { super(location); start.endForm = this; this.startForm = start; } final StartForm startForm; } static class StartViolations extends Event { StartViolations(Locator location, Event parent, StartElement start) throws SAXException { super(location); this.startElement = start; this.parent = parent; this.formId = start.attributes.getValue("id"); } final StartElement startElement; final Event parent; final String formId; EndViolations endViolations; } static class EndViolations extends Event { EndViolations(Locator location, StartViolations start) { super(location); start.endViolations = this; this.startViolations = start; } final StartViolations startViolations; } static class StartRepeat extends Event { StartRepeat(Locator location, String namespaceURI, String localName, String raw, Attributes attrs, CompiledExpression nodeset) throws SAXException { super(location); this.startElement = new StartElement(location, namespaceURI, localName, raw, attrs); this.nodeset = nodeset; } final CompiledExpression nodeset; final StartElement startElement; EndRepeat endRepeat; } static class EndRepeat extends Event { EndRepeat(Locator location) { super(location); } } static class StartItemSet extends Event { StartItemSet(Locator location, String namespaceURI, String localName, String raw, Attributes attrs, CompiledExpression nodeset) throws SAXException { super(location); this.startElement = new StartElement(location, namespaceURI, localName, raw, attrs); this.nodeset = nodeset; } final CompiledExpression nodeset; final StartElement startElement; EndItemSet endItemSet; } static class EndItemSet extends Event { EndItemSet(Locator location) { super(location); } } static class StartSubmission extends Event { StartSubmission(Locator location, StartElement startElement) { super(location); this.startElement = startElement; } StartElement startElement; EndSubmission endSubmission; } static class EndSubmission extends Event { EndSubmission(Locator location, StartSubmission start) { super(location); start.endSubmission = this; this.startSubmission = start; } final StartSubmission startSubmission; } static class StartSubmit extends Event { StartSubmit(Locator location, StartElement startElement) { super(location); this.startElement = startElement; this.submissionName = startElement.attributes.getValue("submission"); } final StartElement startElement; final String submissionName; StartSubmission submission; EndSubmit endSubmit; } static class EndSubmit extends Event { EndSubmit(Locator location, StartSubmit start) { super(location); start.endSubmit = this; this.startSubmit = start; } final StartSubmit startSubmit; } static class StartItem extends Event { StartItem(Locator location, StartElement startElement) { super(location); this.startElement = startElement; } final StartElement startElement; EndItem endItem; } static class EndItem extends Event { EndItem(Locator location, StartItem start) { super(location); start.endItem = this; this.startItem = start; } final StartItem startItem; } static class StartChoices extends Event { StartChoices(Locator location, StartElement startElement) { super(location); this.startElement = startElement; } final StartElement startElement; EndChoices endChoices; } static class EndChoices extends Event { EndChoices(Locator location, StartChoices start) { super(location); start.endChoices = this; this.startChoices = start; } final StartChoices startChoices; } static class StartValue extends Event { StartValue(Locator location, StartElement startElement) { super(location); this.startElement = startElement; } final StartElement startElement; EndValue endValue; } static class EndValue extends Event { EndValue(Locator location, StartValue start) { super(location); start.endValue = this; this.startValue = start; } final StartValue startValue; } static class StartOutput extends Event { StartOutput(Locator location, CompiledExpression ref, CompiledExpression value, StartElement startElement) { super(location); this.startElement = startElement; this.ref = ref; this.value = value; } final CompiledExpression ref; final CompiledExpression value; final StartElement startElement; EndOutput endOutput; } static class EndOutput extends Event { EndOutput(Locator location, StartOutput start) { super(location); start.endOutput = this; this.startOutput = start; } final StartOutput startOutput; } static class StartGroup extends Event { StartGroup(Locator location, CompiledExpression ref, StartElement startElement) { super(location); this.ref = ref; this.startElement = startElement; } final CompiledExpression ref; final StartElement startElement; EndGroup endGroup; } static class EndGroup extends Event { EndGroup(Locator location, StartGroup start) { super(location); start.endGroup = this; this.startGroup = start; } final StartGroup startGroup; } static class StartHidden extends Event { StartHidden(Locator location, CompiledExpression ref, StartElement startElement) { super(location); this.ref = ref; this.startElement = startElement; } final CompiledExpression ref; final StartElement startElement; EndHidden endHidden; } static class EndHidden extends Event { EndHidden(Locator location, StartHidden start) { super(location); start.endHidden = this; this.startHidden = start; } final StartHidden startHidden; } static class Parser implements ContentHandler, LexicalHandler { JXPathContext context; StartDocument startEvent; Event lastEvent; Stack stack = new Stack(); Locator locator; Locator charLocation; StringBuffer charBuf; public Parser(JXPathContext context) { this.context = context; } StartDocument getStartEvent() { return startEvent; } private void addEvent(Event ev) throws SAXException { if (ev == null) { throw new NullPointerException("null event"); } if (charBuf != null) { char[] chars = new char[charBuf.length()]; charBuf.getChars(0, charBuf.length(), chars, 0); Characters charEvent = new Characters(charLocation, chars, 0, chars.length); lastEvent.next = charEvent; lastEvent = charEvent; charLocation = null; charBuf = null; } if (lastEvent == null) { lastEvent = startEvent = new StartDocument(locator); } lastEvent.next = ev; lastEvent = ev; } public void characters(char[] ch, int start, int length) throws SAXException { if (charBuf == null) { charBuf = new StringBuffer(); charLocation = new LocatorImpl(locator); } charBuf.append(ch, start, length); } public void endDocument() throws SAXException { StartDocument startDoc = (StartDocument)stack.pop(); EndDocument endDoc = new EndDocument(locator); startDoc.endDocument = endDoc; addEvent(endDoc); } public void endElement(String namespaceURI, String localName, String raw) throws SAXException { Event start = (Event)stack.pop(); Event newEvent = null; if (NS.equals(namespaceURI)) { if (start instanceof StartRepeat) { StartRepeat startRepeat = (StartRepeat)start; newEvent = startRepeat.endRepeat = new EndRepeat(locator); } else if (start instanceof StartItemSet) { StartItemSet startItemSet = (StartItemSet)start; newEvent = startItemSet.endItemSet = new EndItemSet(locator); } else if (start instanceof StartInputControl) { StartInputControl startInputControl = (StartInputControl)start; newEvent = new EndInputControl(locator, startInputControl); } else if (start instanceof StartReadonlyInputControl) { StartReadonlyInputControl startInputControl = (StartReadonlyInputControl)start; newEvent = new EndReadonlyInputControl(locator, startInputControl); } else if (start instanceof StartSubmit) { StartSubmit startSubmit = (StartSubmit)start; newEvent = startSubmit.endSubmit = new EndSubmit(locator, startSubmit); } else if (start instanceof StartForm) { StartForm startForm = (StartForm)start; newEvent = startForm.endForm = new EndForm(locator, startForm); } else if (start instanceof StartViolations) { StartViolations startViolations = (StartViolations)start; newEvent = startViolations.endViolations = new EndViolations(locator, startViolations); } else if (start instanceof StartItem) { StartItem startItem = (StartItem)start; newEvent = startItem.endItem = new EndItem(locator, startItem); } else if (start instanceof StartChoices) { StartChoices startChoices = (StartChoices)start; newEvent = startChoices.endChoices = new EndChoices(locator, startChoices); } else if (start instanceof StartValue) { StartValue startValue = (StartValue)start; newEvent = startValue.endValue = new EndValue(locator, startValue); } else if (start instanceof StartOutput) { StartOutput startOutput = (StartOutput)start; newEvent = startOutput.endOutput = new EndOutput(locator, startOutput); } else if (start instanceof StartGroup) { StartGroup startGroup = (StartGroup)start; newEvent = startGroup.endGroup = new EndGroup(locator, startGroup); } else if (start instanceof StartHidden) { StartHidden startHidden = (StartHidden)start; newEvent = startHidden.endHidden = new EndHidden(locator, startHidden); } else { throw new SAXParseException("unrecognized tag: " + raw, locator, null); } } else { StartElement startElement = (StartElement)start; newEvent = startElement.endElement = new EndElement(locator, startElement); } addEvent(newEvent); } public void endPrefixMapping(String prefix) throws SAXException { EndPrefixMapping endPrefixMapping = new EndPrefixMapping(locator, prefix); addEvent(endPrefixMapping); } public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { Event ev = new IgnorableWhitespace(locator, ch, start, length); addEvent(ev); } public void processingInstruction(String target, String data) throws SAXException { Event pi = new ProcessingInstruction(locator, target, data); addEvent(pi); } public void setDocumentLocator(Locator locator) { this.locator = locator; } public void skippedEntity(String name) throws SAXException { addEvent(new SkippedEntity(locator, name)); } public void startDocument() { startEvent = new StartDocument(locator); lastEvent = startEvent; stack.push(lastEvent); } public void startElement(String namespaceURI, String localName, String raw, Attributes attrs) throws SAXException { Event newEvent = null; if (NS.equals(namespaceURI)) { if (localName.equals(REPEAT)) { String items = attrs.getValue(NODESET); CompiledExpression expr = compileExpr(context, items, locator); StartRepeat startRepeat = new StartRepeat(locator, namespaceURI, localName, raw, attrs, expr); newEvent = startRepeat; } else if (localName.equals(ITEMSET)) { String items = attrs.getValue(NODESET); CompiledExpression expr = compileExpr(context, items, locator); StartItemSet startItemSet = new StartItemSet(locator, namespaceURI, localName, raw, attrs, expr); newEvent = startItemSet; } else if (isReadonlyInputControl(localName)) { String refStr = attrs.getValue("ref"); CompiledExpression ref = compileExpr(context, refStr, locator); StartReadonlyInputControl startInputControl = new StartReadonlyInputControl(locator, ref, new StartElement(locator, namespaceURI, localName, raw, attrs)); newEvent = startInputControl; } else if (isInputControl(localName)) { String refStr = attrs.getValue("ref"); CompiledExpression ref = compileExpr(context, refStr, locator); StartInputControl startInputControl = new StartInputControl(locator, ref, new StartElement(locator, namespaceURI, localName, raw, attrs)); newEvent = startInputControl; } else if (SUBMIT.equals(localName)) { StartSubmit startSubmit = new StartSubmit(locator, new StartElement(locator, namespaceURI, localName, raw, attrs)); newEvent = startSubmit; } else if (ITEM.equals(localName)) { StartItem startItem = new StartItem(locator, new StartElement(locator, namespaceURI, localName, raw, attrs)); newEvent = startItem; } else if (CHOICES.equals(localName)) { StartChoices startChoices = new StartChoices(locator, new StartElement(locator, namespaceURI, localName, raw, attrs)); newEvent = startChoices; } else if (VALUE.equals(localName)) { StartValue startValue = new StartValue(locator, new StartElement(locator, namespaceURI, localName, raw, attrs)); newEvent = startValue; } else if (OUTPUT.equals(localName)) { String refStr = attrs.getValue(REF); String valueStr = attrs.getValue(VALUE); if (refStr != null && valueStr != null) { throw new SAXParseException("ref and value are mutually exclusive", locator, null); } CompiledExpression ref = compileExpr(context, refStr, locator); CompiledExpression value = compileExpr(context, valueStr, locator); StartOutput startOutput = new StartOutput(locator, ref, value, new StartElement(locator, namespaceURI, localName, raw, attrs)); newEvent = startOutput; } else if (FORM.equals(localName)) { StartForm startForm = new StartForm(locator, new StartElement(locator, namespaceURI, localName, raw, attrs)); newEvent = startForm; } else if (VIOLATIONS.equals(localName)) { StartViolations startViolations = new StartViolations(locator, (Event)stack.peek(), new StartElement(locator, namespaceURI, localName, raw, attrs)); newEvent = startViolations; } else if (GROUP.equals(localName)) { String refStr = attrs.getValue(REF); CompiledExpression ref = compileExpr(context, refStr, locator); StartGroup startGroup = new StartGroup(locator, ref, new StartElement(locator, namespaceURI, localName, raw, attrs)); newEvent = startGroup; } else if (HIDDEN.equals(localName)) { String refStr = attrs.getValue(REF); CompiledExpression ref = compileExpr(context, refStr, locator); StartHidden startHidden = new StartHidden(locator, ref, new StartElement(locator, namespaceURI, localName, raw, attrs)); newEvent = startHidden; } else { throw new SAXParseException("unrecognized tag: " + localName, locator, null); } } else { StartElement startElem = new StartElement(locator, namespaceURI, localName, raw, attrs); newEvent = startElem; } stack.push(newEvent); addEvent(newEvent); } public void startPrefixMapping(String prefix, String uri) throws SAXException { addEvent(new StartPrefixMapping(locator, prefix, uri)); } public void comment(char ch[], int start, int length) throws SAXException { addEvent(new Comment(locator, ch, start, length)); } public void endCDATA() throws SAXException { addEvent(new EndCDATA(locator)); } public void endDTD() throws SAXException { addEvent(new EndDTD(locator)); } public void endEntity(String name) throws SAXException { addEvent(new EndEntity(locator, name)); } public void startCDATA() throws SAXException { addEvent(new StartCDATA(locator)); } public void startDTD(String name, String publicId, String systemId) throws SAXException { addEvent(new StartDTD(locator, name, publicId, systemId)); } public void startEntity(String name) throws SAXException { addEvent(new StartEntity(locator, name)); } } /** * Adapter that makes this generator usable as a transformer * (Note there is a performance penalty for this however: * you effectively recompile the template for every instance document) */ public static class TransformerAdapter extends AbstractTransformer { static class TemplateConsumer extends Parser implements XMLConsumer { JXFormsGenerator template; public TemplateConsumer(SourceResolver resolver, Map objectModel, String src, Parameters parameters) throws ProcessingException, SAXException, IOException { super(jxpathContextFactory.newContext(null, null)); this.template = new JXFormsGenerator(); this.template.setup(resolver, objectModel, null, parameters); } public void endDocument() throws SAXException { super.endDocument(); template.execute(template.getConsumer(), null, null, context, getStartEvent(), null); } void setConsumer(XMLConsumer consumer) { template.setConsumer(consumer); } } TemplateConsumer templateConsumer; public void recycle() { super.recycle(); templateConsumer = null; } public void setup(SourceResolver resolver, Map objectModel, String src, Parameters parameters) throws ProcessingException, SAXException, IOException { templateConsumer = new TemplateConsumer(resolver, objectModel, src, parameters); } public void setConsumer(XMLConsumer xmlConsumer) { super.setConsumer(templateConsumer); templateConsumer.setConsumer(xmlConsumer); } } private static Map cache = new HashMap(); private XMLConsumer consumer; private Source inputSource; WebContinuation kont; Object bean; Map objectModel; private XMLConsumer getConsumer() { return consumer; } public void recycle() { super.recycle(); consumer = null; inputSource = null; bean = null; kont = null; objectModel = null; } public void setup(SourceResolver resolver, Map objectModel, String src, Parameters parameters) throws ProcessingException, SAXException, IOException { super.setup(resolver, objectModel, src, parameters); if (src != null) { try { this.inputSource = resolver.resolveURI(src); } catch (SourceException se) { throw SourceUtil.handle("Error during resolving of '" + src + "'.", se); } long lastMod = inputSource.getLastModified(); String uri = inputSource.getURI(); synchronized (cache) { StartDocument startEvent = (StartDocument)cache.get(uri); if (startEvent != null && lastMod > startEvent.compileTime) { cache.remove(uri); } } } // FIX ME: When we decide proper way to pass "bean" and "kont" bean = ((Environment)resolver).getAttribute("bean-dict"); kont = (WebContinuation)((Environment)resolver).getAttribute("kont"); this.objectModel = objectModel; } public void setConsumer(XMLConsumer consumer) { this.consumer = consumer; } public void generate() throws IOException, SAXException, ProcessingException { StartDocument startEvent; synchronized (cache) { startEvent = (StartDocument)cache.get(inputSource.getURI()); } if (startEvent == null) { long compileTime = inputSource.getLastModified(); Parser parser = new Parser(jxpathContextFactory.newContext(null, null)); this.resolver.toSAX(this.inputSource, parser); startEvent = parser.getStartEvent(); startEvent.compileTime = compileTime; synchronized (cache) { cache.put(inputSource.getURI(), startEvent); } } execute(consumer, null, null, jxpathContextFactory.newContext(null, null), startEvent, null); } private void execute(final XMLConsumer consumer, Form form, String contextPath, JXPathContext jxpathContext, Event startEvent, Event endEvent) throws SAXException { String currentView = null; Event ev = startEvent; while (ev != endEvent) { consumer.setDocumentLocator(ev.location); if (ev instanceof Characters) { TextEvent text = (TextEvent)ev; consumer.characters(text.chars, 0, text.chars.length); } else if (ev instanceof IgnorableWhitespace) { TextEvent text = (TextEvent)ev; consumer.ignorableWhitespace(text.chars, 0, text.chars.length); } else if (ev instanceof EndDocument) { consumer.endDocument(); } else if (ev instanceof EndElement) { EndElement endElement = (EndElement)ev; StartElement startElement = (StartElement)endElement.startElement; consumer.endElement(startElement.namespaceURI, startElement.localName, startElement.raw); } else if (ev instanceof EndPrefixMapping) { EndPrefixMapping endPrefixMapping = (EndPrefixMapping)ev; consumer.endPrefixMapping(endPrefixMapping.prefix); } else if (ev instanceof ProcessingInstruction) { ProcessingInstruction pi = (ProcessingInstruction)ev; consumer.processingInstruction(pi.target, pi.data); } else if (ev instanceof SkippedEntity) { SkippedEntity skippedEntity = (SkippedEntity)ev; consumer.skippedEntity(skippedEntity.name); } else if (ev instanceof StartDocument) { StartDocument startDoc = (StartDocument)ev; if (startDoc.endDocument != null) { // if this isn't a document fragment consumer.startDocument(); } } else if (ev instanceof StartPrefixMapping) { StartPrefixMapping startPrefixMapping = (StartPrefixMapping)ev; consumer.startPrefixMapping(startPrefixMapping.prefix, startPrefixMapping.uri); } else if (ev instanceof Comment) { TextEvent text = (TextEvent)ev; consumer.comment(text.chars, 0, text.chars.length); } else if (ev instanceof EndCDATA) { consumer.endCDATA(); } else if (ev instanceof EndDTD) { consumer.endDTD(); } else if (ev instanceof EndEntity) { consumer.endEntity(((EndEntity)ev).name); } else if (ev instanceof StartCDATA) { consumer.startCDATA(); } else if (ev instanceof StartDTD) { StartDTD startDTD = (StartDTD)ev; consumer.startDTD(startDTD.name, startDTD.publicId, startDTD.systemId); } else if (ev instanceof StartEntity) { consumer.startEntity(((StartEntity)ev).name); //////////////////////////////////////////////// } else if (ev instanceof StartElement) { StartElement startElement = (StartElement)ev; consumer.startElement(startElement.namespaceURI, startElement.localName, startElement.raw, startElement.attributes); } else if (ev instanceof StartRepeat) { StartRepeat startRepeat = (StartRepeat)ev; final CompiledExpression nodeset = startRepeat.nodeset; Iterator iter = null; try { if (nodeset == null) { iter = NULL_ITER; } else { iter = nodeset.iteratePointers(jxpathContext); } } catch (Exception exc) { throw new SAXParseException(exc.getMessage(), ev.location, exc); } catch (Error err) { throw new SAXParseException(err.getMessage(), ev.location, null); } while (iter.hasNext()) { Object value; Pointer ptr = (Pointer)iter.next(); try { value = ptr.getNode(); } catch (Exception exc) { throw new SAXParseException(exc.getMessage(), ev.location, exc); } JXPathContext localJXPathContext = jxpathContextFactory.newContext(null, value); String path = ""; if (contextPath != null) { path = contextPath + "/."; } path += ptr.asPath(); execute(consumer, form, path, localJXPathContext, startRepeat.next, startRepeat.endRepeat); } ev = startRepeat.endRepeat.next; continue; } else if (ev instanceof StartGroup) { StartGroup startGroup = (StartGroup)ev; StartElement startElement = startGroup.startElement; consumer.startElement(startElement.namespaceURI, startElement.localName, startElement.raw, startElement.attributes); final CompiledExpression ref = startGroup.ref; if (ref != null) { Object value; try { value = ref.getValue(jxpathContext); } catch (Exception exc) { throw new SAXParseException(exc.getMessage(), ev.location, exc); } JXPathContext localJXPathContext = jxpathContextFactory.newContext(null, value); String path = ""; if (contextPath != null) { path = contextPath + "/."; } path += startElement.attributes.getValue(REF); execute(consumer, form, path, localJXPathContext, startGroup.next, startGroup.endGroup); ev = startGroup.endGroup; continue; } } else if (ev instanceof StartItemSet) { StartItemSet startItemSet = (StartItemSet)ev; final CompiledExpression nodeset = startItemSet.nodeset; Iterator iter = null; try { if (nodeset == null) { iter = NULL_ITER; } else { iter = nodeset.iteratePointers(jxpathContext); } } catch (Exception exc) { throw new SAXParseException(exc.getMessage(), ev.location, exc); } catch (Error err) { throw new SAXParseException(err.getMessage(), ev.location, null); } while (iter.hasNext()) { Object value; Pointer ptr = (Pointer)iter.next(); try { value = ptr.getNode(); } catch (Exception exc) { throw new SAXParseException(exc.getMessage(), ev.location, exc); } JXPathContext localJXPathContext = jxpathContextFactory.newContext(null, value); AttributesImpl attrs = new AttributesImpl(); attrs.addAttribute(NS, "ref", "ref", "CDATA", ptr.asPath()); consumer.startElement(NS, "item", "item", attrs); String path = ""; if (contextPath != null) { path = contextPath + "/."; } path += ptr.asPath(); execute(consumer, form, ptr.asPath(), localJXPathContext, startItemSet.next, startItemSet.endItemSet); consumer.endElement(NS, "item", "item"); } ev = startItemSet.endItemSet.next; continue; } else if (ev instanceof StartInputControl) { // // input, textarea, secret, select1, selectMany // StartInputControl startInputControl = (StartInputControl)ev; CompiledExpression ref = startInputControl.ref; StartElement startElement = startInputControl.startElement; String refStr = startElement.attributes.getValue("ref"); consumer.startElement(startElement.namespaceURI, startElement.localName, startElement.raw, startElement.attributes); if (ref != null) { Iterator iter = ref.iteratePointers(jxpathContext); while (iter.hasNext()) { Pointer ptr = (Pointer)iter.next(); AttributesImpl attrs = new AttributesImpl(); attrs.addAttribute(NS, REF, REF, "CDATA", ptr.asPath()); consumer.startElement(NS, VALUE, VALUE, EMPTY_ATTRS); Object val = ptr.getNode(); String str = String.valueOf(val); consumer.characters(str.toCharArray(), 0, str.length()); consumer.endElement(NS, VALUE, VALUE); } } } else if (ev instanceof EndInputControl) { StartInputControl startInputControl = ((EndInputControl)ev).startInputControl; StartElement startElement = startInputControl.startElement; consumer.endElement(startElement.namespaceURI, startElement.localName, startElement.raw); } else if (ev instanceof StartReadonlyInputControl) { // // label, hint, help, value // // substitute "ref" if present StartReadonlyInputControl startReadonlyInputControl = (StartReadonlyInputControl)ev; StartElement startElement = startReadonlyInputControl.startElement; Object refValue = null; if (startReadonlyInputControl.ref != null) { refValue = startReadonlyInputControl.ref.getValue(jxpathContext); } consumer.startElement(startElement.namespaceURI, startElement.localName, startElement.raw, startElement.attributes); if (refValue != null) { String v = String.valueOf(refValue); consumer.characters(v.toCharArray(), 0, v.length()); } } else if (ev instanceof EndReadonlyInputControl) { StartReadonlyInputControl startReadonlyInputControl = ((EndReadonlyInputControl)ev).startReadonlyInputControl; StartElement startElement = startReadonlyInputControl.startElement; consumer.endElement(startElement.namespaceURI, startElement.localName, startElement.raw); } else if (ev instanceof StartForm) { StartForm startForm = (StartForm)ev; StartElement startElement = startForm.startElement; currentView = startElement.attributes.getValue(VIEW); String id = startElement.attributes.getValue(ID); Form newForm = Form.lookup(objectModel, id); consumer.startElement(startElement.namespaceURI, startElement.localName, startElement.raw, startElement.attributes); execute(consumer, newForm, contextPath, jxpathContextFactory.newContext(null, newForm.getModel()), startForm.next, startForm.endForm); consumer.endElement(startElement.namespaceURI, startElement.localName, startElement.raw); ev = startForm.endForm.next; continue; } else if (ev instanceof EndForm) { StartElement startElement = ((EndForm)ev).startForm.startElement; consumer.endElement(startElement.namespaceURI, startElement.localName, startElement.raw); } else if (ev instanceof StartSubmit) { StartElement startElement = ((StartSubmit)ev).startElement; Attributes attrs = startElement.attributes; if (kont != null) { String id = startElement.attributes.getValue(ID); if (id == null) { id = ""; } String cont = startElement.attributes.getValue(CONTINUATION); int level = 0; if (BACK.equals(cont)) { level = 3; } String kontId = kont.getContinuation(level).getId(); AttributesImpl newAttrs = new AttributesImpl(startElement.attributes); int i = newAttrs.getIndex(ID); if (i >= 0) { newAttrs.setValue(i, kontId + ":" + id); } else { newAttrs.addAttribute("", ID, ID, "CDATA", kontId + ":" + id); } attrs = newAttrs; } consumer.startElement(startElement.namespaceURI, startElement.localName, startElement.raw, attrs); } else if (ev instanceof EndSubmit) { StartElement startElement = ((EndSubmit)ev).startSubmit.startElement; consumer.endElement(startElement.namespaceURI, startElement.localName, startElement.raw); } else if (ev instanceof StartItem) { StartElement startElement = ((StartItem)ev).startElement; consumer.startElement(startElement.namespaceURI, startElement.localName, startElement.raw, startElement.attributes); } else if (ev instanceof EndItem) { StartElement startElement = ((EndItem)ev).startItem.startElement; consumer.endElement(startElement.namespaceURI, startElement.localName, startElement.raw); } else if (ev instanceof StartChoices) { StartElement startElement = ((StartChoices)ev).startElement; consumer.startElement(startElement.namespaceURI, startElement.localName, startElement.raw, startElement.attributes); } else if (ev instanceof EndChoices) { StartElement startElement = ((EndChoices)ev).startChoices.startElement; consumer.endElement(startElement.namespaceURI, startElement.localName, startElement.raw); } else if (ev instanceof StartValue) { StartElement startElement = ((StartValue)ev).startElement; consumer.startElement(startElement.namespaceURI, startElement.localName, startElement.raw, startElement.attributes); } else if (ev instanceof EndValue) { StartElement startElement = ((EndValue)ev).startValue.startElement; consumer.endElement(startElement.namespaceURI, startElement.localName, startElement.raw); } else if (ev instanceof StartHidden) { StartElement startElement = ((StartHidden)ev).startElement; consumer.startElement(startElement.namespaceURI, startElement.localName, startElement.raw, startElement.attributes); } else if (ev instanceof EndHidden) { StartElement startElement = ((EndHidden)ev).startHidden.startElement; consumer.endElement(startElement.namespaceURI, startElement.localName, startElement.raw); } else if (ev instanceof StartOutput) { StartOutput startOutput = (StartOutput)ev; StartElement startElement = startOutput.startElement; JXPathContext ctx = jxpathContext; String formId = startElement.attributes.getValue(FORM); if (formId != null) { Form theForm = Form.lookup(objectModel, formId); if (theForm == null) { throw new SAXParseException("form not found: " + formId, ev.location, null); } ctx = jxpathContextFactory.newContext(null, theForm.getModel()); } consumer.startElement(startElement.namespaceURI, startElement.localName, startElement.raw, startElement.attributes); Object val = null; if (startOutput.ref != null) { val = startOutput.ref.getValue(ctx); } else if (startOutput.value != null) { val = startOutput.value.getValue(ctx); } if (val != null) { consumer.startElement(NS, VALUE, VALUE, EMPTY_ATTRS); String str = String.valueOf(val); consumer.characters(str.toCharArray(), 0, str.length()); consumer.endElement(NS, VALUE, VALUE); } } else if (ev instanceof EndOutput) { StartElement startElement = ((EndOutput)ev).startOutput.startElement; consumer.endElement(startElement.namespaceURI, startElement.localName, startElement.raw); } else if (ev instanceof EndGroup) { StartElement startElement = ((EndGroup)ev).startGroup.startElement; consumer.endElement(startElement.namespaceURI, startElement.localName, startElement.raw); } else if (ev instanceof StartViolations) { StartViolations startViolations = (StartViolations)ev; StartElement startElement = startViolations.startElement; Attributes attrs = startElement.attributes; String formAttr = attrs.getValue(FORM); Form theForm = form; if (formAttr != null) { theForm = Form.lookup(objectModel, formAttr); } Set violations = form.getViolationsAsSortedSet(); String mypath = null; if (startViolations.parent instanceof StartInputControl) { StartInputControl control = (StartInputControl)startViolations.parent; mypath = control.startElement.attributes.getValue(REF); if (contextPath != null) { if (!mypath.startsWith("/")) { mypath = contextPath + "/" + mypath; } } } if (violations != null) { for (Iterator iter = violations.iterator(); iter.hasNext();) { Violation violation = (Violation)iter.next(); String path = violation.getPath(); if (mypath == null || path.equals(mypath)) { String message = violation.getMessage(); AttributesImpl newAttrs = new AttributesImpl(startElement.attributes); newAttrs.addAttribute(null, REF, REF, "CDATA", path); consumer.startElement(NS, VIOLATION, VIOLATION, newAttrs); consumer.characters(message.toCharArray(), 0, message.length()); consumer.endElement(NS, VIOLATION, VIOLATION); } } } } else if (ev instanceof EndViolations) { /* No action */ } ev = ev.next; } } } 1.1 cocoon-2.1/src/scratchpad/src/org/apache/cocoon/transformation/JXFormsTransformer.java Index: JXFormsTransformer.java =================================================================== package org.apache.cocoon.transformation; import org.apache.cocoon.generation.JXFormsGenerator; /** * Transformer adapter for [EMAIL PROTECTED] org.apache.cocoon.generation.JXFormsGenerator} */ public class JXFormsTransformer extends JXFormsGenerator.TransformerAdapter { /** * This class is just a placeholder to provide a class name you * can easily reference from your Sitemap. All of its functionality is * provided by its base class. */ } 1.6 +7 -1 cocoon-2.1/src/scratchpad/webapp/samples/scratchpad-samples.xml Index: scratchpad-samples.xml =================================================================== RCS file: /home/cvs/cocoon-2.1/src/scratchpad/webapp/samples/scratchpad-samples.xml,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- scratchpad-samples.xml 24 Apr 2003 12:54:13 -0000 1.5 +++ scratchpad-samples.xml 27 Apr 2003 01:57:04 -0000 1.6 @@ -13,6 +13,12 @@ The Cocoon flowscript version of the J2EE PetStore. </sample> </group> + + <group name="JXForms"> + <sample name="JXForms" href="jxforms/"> + JXForms Feedback Wizard Sample + </sample> + </group> <group name="Castor"> <sample name="CastorTransformer" href="castor/"> 1.1 cocoon-2.1/src/scratchpad/webapp/samples/jxforms/sitemap.xmap Index: sitemap.xmap =================================================================== <?xml version="1.0"?> <map:sitemap xmlns:map="http://apache.org/cocoon/sitemap/1.0"> <!-- =========================== Components ================================ --> <map:components> <map:generators default="file"> <map:generator name="jxforms" src="org.apache.cocoon.generation.JXFormsGenerator" logger="jxforms.sitemap.generator"/> </map:generators> <map:flow-interpreters default="JavaScript"/> <map:serializers default="html"/> <map:matchers default="wildcard"/> </map:components> <!-- =========================== Views =================================== --> <!-- The debug view can be used to output an intermediate snapshot of the pipeline. Pass cocoon-view=debug as a URL parameter to see the pipeline output produced by the transofrmer labeled "debug". You can move the label to different transformers to understand each processing stage better. --> <map:views> <map:view name="debug" from-label="debug"> <map:serialize type="xml"/> </map:view> <map:view name="xml" from-label="xml"> <map:serialize type="xml"/> </map:view> </map:views> <!-- =========================== Resources ================================= --> <map:resources> </map:resources> <!-- =========================== Pipelines ================================= --> <map:flow language="JavaScript"> <map:script src="flow/feedbackWizard.js"/> </map:flow> <map:pipelines> <map:pipeline> <map:match pattern=""> <map:call function="jxForm"> <map:parameter name="function" value="feedbackWizard"/> <map:parameter name="id" value="form-feedback"/> <map:parameter name="schema-ns" value="http://www.ascc.net/xml/schematron"/> <map:parameter name="validator-schema" value="schematron/wizard-xmlform-sch-report.xml"/> <map:parameter name="scope" value="session"/> </map:call> </map:match> <map:match pattern="view/*.xml"> <!-- original XMLForm document --> <map:generate type="jxforms" src="view/{1}.xml"/> <!-- Personalize the look and feel of the form controls --> <map:transform type="xalan" src="stylesheets/wizard2html.xsl" /> <!-- Transform the JXForms controls to HTML controls --> <map:transform type="xalan" src="stylesheets/jxforms-default.xsl" /> <map:transform type="xalan" src="stylesheets/jxforms2html.xsl" /> <!-- sending the HTML back to the browser --> <map:serialize type="html" label="debug"/> </map:match> </map:pipeline> </map:pipelines> </map:sitemap> <!-- end of file --> 1.1 cocoon-2.1/src/scratchpad/webapp/samples/jxforms/flow/feedbackWizard.js Index: feedbackWizard.js =================================================================== // Feedback Wizard Sample cocoon.load("resource://org/apache/cocoon/components/jxforms/flow/jxForm.js"); function feedbackWizard(form) { var bean = { firstName: "Donald", lastName: "Duck", email: "[EMAIL PROTECTED]", age: 5, number: 1, liveUrl: "http://", publish: true, hidden: true, count: 1, notes: "<your notes here>", favorite: ["http://xml.apache/org/cocoon", "http://jakarta.apache.org", "http://www.google.com", "http://www.slashdot.com", "http://www.yahoo.com"], hobby: ["swim", "movies", "ski", "gym", "soccer"], allHobbies: [ { key: "swim", value: "Swimming" }, { key: "gym", value: "Body Building" }, { key: "ski", value: "Skiing" }, { key: "run", value: "Running" }, { key: "football", value: "Football" }, { key: "read", value: "Reading" }, { key: "write", value: "Writing" }, { key: "soccer:", value: "Soccer" }, { key: "blog", value: "Blogging" }], role: ["Hacker", "Executive"], system: { os: "Unix", processor: "p4", ram: 512, servletEngine: "Tomcat", javaVersion: "1.3", } } form.setModel(bean); form.sendView("userIdentity", "view/userIdentity.xml", function(form) { var bean = form.getModel(); print("I can also do validation in JavaScript"); print("age = "+form.getValue("number(/age)")); print("role = "+bean.role); if (bean.age > 40) { form.addViolation("/age", "Hey, you're too old"); } }); print("handling user identity"); form.sendView("deployment", "view/deployment.xml", function(form) { var bean = form.getModel(); print("I can also do validation in JavaScript"); if (bean.publish) { form.addViolation("/publish", "Sorry, I won't let you publish"); } }); print("handling deployment"); form.sendView("system", "view/system.xml"); print("handling system"); form.sendView("confirm", "view/confirm.xml"); print("handling confirm"); form.finish("view/end.xml"); print("done"); } 1.1 cocoon-2.1/src/scratchpad/webapp/samples/jxforms/schematron/wizard-xmlform-sch-report.xml Index: wizard-xmlform-sch-report.xml =================================================================== <?xml version="1.0" ?> <!-- Validating Schematron schema for the xmlform example wizard Schematron Schema language home page: http://www.ascc.net/xml/schematron/ Author: Ivelin Ivanov, [EMAIL PROTECTED], April 2002 --> <schema ns="http://xml.apache.cocoon/xmlform" xmlns="http://www.ascc.net/xml/schematron"> <title>Schema for the XML Form example</title> <phase id="userIdentity"> <p>For user identity information.</p> <active pattern="user"/> </phase> <phase id="deployment"> <p>For deployment info page.</p> <active pattern="dep" /> </phase> <phase id="system"> <p>For system info page.</p> <active pattern="sys" /> </phase> <phase id="confirm"> <p>For final total validation and tracking some tricky problems.</p> <active pattern="user" /> <active pattern="dep" /> <active pattern="sys" /> </phase> <pattern name="User Info Validation Pattern" id="user"> <rule context="/firstName"> <assert test="string-length(.) > 3">First name <anametag/> <wrapper>should</wrapper> be at least 4 characters.</assert> <assert test="string-length(.) < 20">First name should be less than 20 characters.</assert> </rule> <rule context="/lastName"> <assert test="string-length(.) > 3">Last name should be at least 4 characters.</assert> <assert test="string-length(.) < 20">Last name should be less than 20 characters.</assert> </rule> <rule context="/email"> <assert test="contains( string(.),'@')">Email format is invalid.</assert> </rule> <rule context="/age"> <assert test="number() > 0 and number(.) < 200">Age should be a reasonably big positive number.</assert> </rule> </pattern> <pattern name="Deployment Information Validation Pattern" id="dep"> <rule context="/number"> <assert test="number() > 0">The number of deployments must be non-negative ( hopefully positive :-> ) .</assert> </rule> <rule context="/"> <!-- If the site is to be published, then verify the URL. Note: This assertion demonstrates the unique ability of Schematron to test document node dependencies. This is not possible to do with XML Schema and Relax NG. --> <assert test="not(string(publish) = 'true') or (starts-with(liveUrl, 'http://') and contains( string(liveUrl),'.') ) " >The URL of the published site is invalid.</assert> </rule> </pattern> <pattern name="System Information Validation Pattern" id="sys"> <rule context="/system/@ram"> <assert test="number() > 0">The RAM value should be a positive number, denoting the memory in MB (e.g. 128, 512, etc.).</assert> </rule> </pattern> </schema> 1.1 cocoon-2.1/src/scratchpad/webapp/samples/jxforms/stylesheets/jxforms-default.xsl Index: jxforms-default.xsl =================================================================== <?xml version="1.0" encoding="UTF-8"?> <!-- This stylesheet merges a JXForms document into a final document. It includes other presentational parts of a page orthogonal to the xmlform. author: Ivelin Ivanov, [EMAIL PROTECTED], May 2002 author: Konstantin Piroumian <[EMAIL PROTECTED]>, September 2002 author: Simon Price <[EMAIL PROTECTED]>, September 2002 --> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xf="http://cocoon.apache.org/jxforms/2002/cr" exclude-result-prefixes="xalan" > <xsl:template match="/"> <xsl:apply-templates /> </xsl:template> <xsl:template match="xf:form"> <xf:form method="post"> <xsl:copy-of select="@*" /> <br/> <br/> <br/> <br/> <table align="center" border="0"> <tr> <td align="center" colspan="3"> <h1> <xsl:value-of select="xf:label"/> <hr/> </h1> </td> </tr> <xsl:if test="count(error/xf:violation) > 0"> <tr> <td align="left" colspan="3" class="{error/xf:violation[1]/@class}"> <p>* There are [<b><xsl:value-of select="count(error/xf:violation)"/></b>] errors. Please fix these errors and submit the form again.</p> <p> <xsl:variable name="localViolations" select=".//xf:*[ child::xf:violation ]"/> <xsl:for-each select="error/xf:violation"> <xsl:variable name="eref" select="./@ref"/> <xsl:if test="count ($localViolations[ @ref=$eref ]) = 0" >* <xsl:value-of select="." /> <br/> </xsl:if> </xsl:for-each> </p> <p/> </td> </tr> </xsl:if> <xsl:for-each select="*[name() != 'xf:submit']"> <xsl:choose> <xsl:when test="name() = 'error'"/> <xsl:when test="name() = 'xf:label'"/> <xsl:when test="xf:*"> <xsl:apply-templates select="."/> </xsl:when> <xsl:otherwise> <xsl:copy-of select="."/> </xsl:otherwise> </xsl:choose> </xsl:for-each> <tr> <td align="center" colspan="3"> <xsl:for-each select="*[name() = 'xf:submit']"> <xsl:copy-of select="." /> <xsl:text> </xsl:text> </xsl:for-each> </td> </tr> </table> </xf:form> </xsl:template> <xsl:template match="xf:repeat"> <tr width="100%"> <td colspan="3" width="100%"> <table class="repeat"> <xsl:apply-templates select="*"/> </table> </td> </tr> </xsl:template> <xsl:template match="xf:group"> <tr width="100%"> <td width="100%" colspan="2"> <table class="group" border="0"> <tr> <td align="left"> <xsl:value-of select="xf:label" /> </td> </tr> <xsl:apply-templates select="*"/> </table> </td> </tr> </xsl:template> <xsl:template match="xf:[EMAIL PROTECTED]"> <div align="center"> <hr width="30%"/> <br/> <font size="-1"> <code> <xsl:value-of select="xf:label" /> : <xsl:copy-of select="." /> </code> </font> <br/> </div> </xsl:template> <xsl:template match="xf:label"/> <xsl:template match="xf:*"> <tr> <td align="left" valign="top"> <p class="label"> <xsl:value-of select="xf:label" /> </p> </td> <td align="left"> <table class="plaintable"> <tr> <td align="left"> <xsl:copy-of select="." /> </td> <xsl:if test="xf:violation"> <td align="left" class="{xf:violation[1]/@class}" width="100%"> <xsl:for-each select="xf:violation">* <xsl:value-of select="." /> <br/> </xsl:for-each> </td> </xsl:if> </tr> </table> <xsl:if test="xf:help"> <div class="help"> <xsl:value-of select="xf:help" /> </div> <br /> </xsl:if> </td> </tr> </xsl:template> <!-- copy all the rest of the markup which is not recognized above --> <xsl:template match="*"> <xsl:copy><xsl:copy-of select="@*" /><xsl:apply-templates /></xsl:copy> </xsl:template> <xsl:template match="text()"> <xsl:value-of select="." /> </xsl:template> </xsl:stylesheet> 1.1 cocoon-2.1/src/scratchpad/webapp/samples/jxforms/stylesheets/jxforms2html.xsl Index: jxforms2html.xsl =================================================================== <?xml version="1.0" encoding="iso-8859-1" ?> <!-- Basic XMLForm processing stylesheet. Converts XMLForm tags to HTML tags. Syntax is borrowed from the XForms standard. http://www.w3.org/TR/2002/WD-xforms-20020118/ This stylesheet is usually applied at the end of a transformation process after laying out the jxform tags on the page is complete. At this stage jxform tags are rendered in device specific format. Different widgets are broken into templates to allow customization in importing stylesheets author: Ivelin Ivanov, [EMAIL PROTECTED], June 2002 author: Andrew Timberlake <[EMAIL PROTECTED]>, June 2002 author: Michael Ratliff, [EMAIL PROTECTED] <[EMAIL PROTECTED]>, May 2002 author: Torsten Curdt, [EMAIL PROTECTED], March 2002 author: Simon Price <[EMAIL PROTECTED]>, September 2002 author: Konstantin Piroumian <[EMAIL PROTECTED]>, September 2002 author: Robert Ellis Parrott <[EMAIL PROTECTED]>, October 2002 --> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xf="http://cocoon.apache.org/jxforms/2002/cr"> <xsl:output method = "xml" omit-xml-declaration = "no" /> <xsl:template match="/"> <xsl:apply-templates /> </xsl:template> <xsl:template match="xf:form"> <form> <xsl:copy-of select="@*"/> <!-- the xf:form/@view attributed is sent back to the server as a hidden field --> <input type="hidden" name="cocoon-xmlform-view" value="[EMAIL PROTECTED]"/> <!-- render the child form controls --> <xsl:apply-templates /> </form> </xsl:template> <xsl:template match="xf:output"> [<xsl:value-of select="xf:value/text()"/>] </xsl:template> <xsl:template match="xf:input"> <!-- the ref attribute is assigned to html:name, which is how it is linked to the model --> <input name="[EMAIL PROTECTED]" type="text" value="{xf:value/text()}"> <!-- copy all attributes from the original markup, except for "ref" --> <xsl:copy-of select="@*[not(name()='ref')]"/> <xsl:apply-templates select="xf:hint"/> </input> </xsl:template> <xsl:template match="xf:textarea"> <textarea name="[EMAIL PROTECTED]" > <xsl:copy-of select="@*[not(name()='ref')]"/> <xsl:value-of select="xf:value/text()"/> <xsl:apply-templates select="xf:hint"/> </textarea> </xsl:template> <xsl:template match="xf:repeat"> <tr width="100%"> <td colspan="3" width="100%"> <table class="repeat"> <xsl:apply-templates select="*"/> </table> </td> </tr> </xsl:template> <xsl:template match="xf:group"> <tr width="100%"> <td width="100%" colspan="2"> <table class="group" border="0"> <tr> <td align="left"> <xsl:value-of select="xf:label" /> </td> </tr> <xsl:apply-templates select="*"/> </table> </td> </tr> </xsl:template> <xsl:template match="xf:secret"> <input name="[EMAIL PROTECTED]" type="password" value="{xf:value/text()}"> <xsl:copy-of select="@*[not(name()='ref')]"/> <xsl:apply-templates select="xf:hint"/> </input> </xsl:template> <xsl:template match="xf:hidden"> <input name="[EMAIL PROTECTED]" type="hidden" value="{xf:value/text()}"> <xsl:copy-of select="@*[not(name()='ref')]"/> </input> </xsl:template> <xsl:template match="xf:select1 | xf:[EMAIL PROTECTED]'compact']"> <select name="[EMAIL PROTECTED]"> <xsl:copy-of select="@*[not(name()='ref')]"/> <!-- all currently selected nodes are listed as value elements --> <xsl:variable name="selected" select="xf:value"/> <xsl:for-each select="xf:item"> <option value="{xf:value}"> <!-- If the current item value matches one of the selected values --> <!-- mark it as selected in the listbox --> <xsl:if test="$selected = xf:value"> <xsl:attribute name="selected"/> </xsl:if> <xsl:value-of select="xf:label"/> </option> </xsl:for-each> </select> </xsl:template> <xsl:template match="xf:[EMAIL PROTECTED]'full']"> <xsl:variable name="selected" select="xf:value"/> <xsl:variable name="ref" select="@ref"/> <xsl:for-each select="xf:item"> <input name="{$ref}" type="radio" value="{xf:value}"> <xsl:copy-of select="@*[not(name()='ref')]"/> <xsl:if test="xf:value = $selected"> <xsl:attribute name="checked"/> </xsl:if> </input> <xsl:value-of select="xf:label"/> <br/> </xsl:for-each> </xsl:template> <xsl:template match="xf:select | xf:[EMAIL PROTECTED]'compact']"> <xsl:variable name="selected" select="xf:value"/> <select name="[EMAIL PROTECTED]"> <xsl:copy-of select="@*[not(name()='ref')]"/> <xsl:attribute name="multiple"/> <xsl:for-each select="xf:item"> <option value="{xf:value}"> <xsl:if test="xf:value = $selected"> <xsl:attribute name="selected"/> </xsl:if> <xsl:value-of select="xf:label"/> </option> </xsl:for-each> </select> </xsl:template> <xsl:template match="xf:[EMAIL PROTECTED]'full']"> <xsl:variable name="selected" select="xf:value"/> <xsl:variable name="ref" select="@ref"/> <xsl:for-each select="xf:item"> <input name="{$ref}" type="checkbox" value="{xf:value}"> <xsl:copy-of select="@*[not(name()='ref')]"/> <xsl:if test="xf:value = $selected"> <xsl:attribute name="checked"/> </xsl:if> </input> <xsl:value-of select="xf:label"/> <br/> </xsl:for-each> </xsl:template> <xsl:template match="xf:submit"> <!-- the id attribute of the submit control is sent to the server --> <!-- as a conventional Cocoon Action parameter of the form cocoon-action-* --> <input name="[EMAIL PROTECTED]" type="submit" value="{xf:label/text()}"> <xsl:copy-of select="@*[not(name()='id')]"/> <xsl:apply-templates select="xf:hint"/> </input> </xsl:template> <xsl:template match="xf:hint"> <xsl:attribute name="title"><xsl:value-of select="."/></xsl:attribute> </xsl:template> <!-- copy all the rest of the markup which is not recognized above --> <xsl:template match="*"> <xsl:copy><xsl:copy-of select="@*" /><xsl:apply-templates /></xsl:copy> </xsl:template> <xsl:template match="text()"> <xsl:value-of select="." /> </xsl:template> </xsl:stylesheet> 1.1 cocoon-2.1/src/scratchpad/webapp/samples/jxforms/stylesheets/wizard2html.xsl Index: wizard2html.xsl =================================================================== <?xml version="1.0" encoding="UTF-8"?> <!-- Cocoon Feedback Wizard XMLForm processing and displaying stylesheet. This stylesheet merges an XMLForm document into a final document. It includes other presentational parts of a page orthogonal to the xmlform. author: Ivelin Ivanov, [EMAIL PROTECTED], May 2002 author: Konstantin Piroumian <[EMAIL PROTECTED]>, September 2002 author: Simon Price <[EMAIL PROTECTED]>, September 2002 --> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xf="http://cocoon.apache.org/jxforms/2002/cr" exclude-result-prefixes="xalan" > <xsl:template match="document"> <html> <head> <title>JXForms - Cocoon Feedback Wizard</title> <style type="text/css"> <![CDATA[ H1{font-family : sans-serif,Arial,Tahoma;color : white;background-color : #0086b2;} BODY{font-family : sans-serif,Arial,Tahoma;color : black;background-color : white;} B{color : white;background-color : blue;} HR{color : #0086b2;} input { background-color: #FFFFFF; color: #000099; border: 1px solid #0000FF; } table { background-color: #EEEEEE; color: #000099; font-size: x-small; border: 2px solid brown;} select { background-color: #FFFFFF; color: #000099 } .caption { line-height: 195% } .error { color: #FF0000; } .help { color: #0000FF; font-style: italic; } .invalid { color: #FF0000; border: 2px solid #FF0000; } .info { color: #0000FF; border: 1px solid #0000FF; } .repeat { border: 0px inset #999999;border: 1px inset #999999; width: 100%; } .group { border: 0px inset #999999;border: 0px inset #999999; width: 100%; } .sub-table { border: none; } .button { background-color: #FFFFFF; color: #000099; border: 1px solid #666666; width: 70px; } .plaintable { border: 0px inset black;border: 0px inset black; width: 100%; } ]]> </style> </head> <body> <xsl:apply-templates /> </body> </html> </xsl:template> <xsl:template match="*"> <xsl:copy-of select="." /> </xsl:template> </xsl:stylesheet> 1.1 cocoon-2.1/src/scratchpad/webapp/samples/jxforms/view/confirm.xml Index: confirm.xml =================================================================== <?xml version="1.0"?> <document xmlns:xf="http://cocoon.apache.org/jxforms/2002/cr"> <xf:form id="form-feedback" view="confirm" action=""> <xf:label>Confirm Input</xf:label> <!-- from page1 --> <xf:output ref="firstName"> <xf:label>First Name</xf:label> </xf:output> <xf:output ref="lastName"> <xf:label>Last Name</xf:label> </xf:output> <xf:output ref="email"> <xf:label>Email</xf:label> </xf:output> <xf:output ref="age"> <xf:label>Age</xf:label> <xf:violations class="error"/> </xf:output> <xf:group ref="/"> <xf:label>Professional roles</xf:label> <xf:repeat nodeset="role"> <xf:output ref="."/> </xf:repeat> </xf:group> <xf:group ref="/"> <xf:label>Personal hobbies</xf:label> <xf:repeat nodeset="hobby"> <xf:output ref="."/> </xf:repeat> </xf:group> <xf:output ref="hidden"> <xf:label>Hidden attribute</xf:label> </xf:output> <!-- from page2 --> <xf:output ref="number"> <xf:label>Number of installations</xf:label> </xf:output> <xf:output ref="liveUrl"> <xf:label>Live URL</xf:label> </xf:output> <xf:output ref="publish"> <xf:label>Publish URL</xf:label> </xf:output> <!-- from page3 --> <xf:output ref="system/os"> <xf:label>OS</xf:label> </xf:output> <xf:output ref="system/processor"> <xf:label>Processor</xf:label> </xf:output> <xf:output ref="system/@ram"> <xf:label>RAM</xf:label> </xf:output> <xf:output ref="system/servletEngine"> <xf:label>Servlet Engine</xf:label> </xf:output> <xf:output ref="system/javaVersion"> <xf:label>Java Version</xf:label> </xf:output> <xf:group ref="/" id="favorites_group"> <xf:label>Favorite web sites</xf:label> <xf:repeat nodeset="favorite[position() <= 3]" id="favorites"> <xf:output ref="." class="info"> <xf:label>URL: </xf:label> </xf:output> </xf:repeat> </xf:group> <!-- submit --> <xf:submit id="prev" continuation="back" class="button"> <xf:label>Prev</xf:label> <xf:hint>Go to previous page</xf:hint> </xf:submit> <xf:submit id="next" continuation="forward" class="button"> <xf:label>Finish</xf:label> <xf:hint>Finish the wizard</xf:hint> </xf:submit> </xf:form> <xf:output ref="count" id="show_count" form="form-feedback" class="info"> <xf:label>Visits Count</xf:label> </xf:output> </document> 1.1 cocoon-2.1/src/scratchpad/webapp/samples/jxforms/view/deployment.xml Index: deployment.xml =================================================================== <?xml version="1.0"?> <document xmlns:xf="http://cocoon.apache.org/jxforms/2002/cr"> <xf:form id="form-feedback" view="deployment" action="" method="GET"> <xf:label>Cocoon Deployment Information</xf:label> <error> <xf:violations class="error"/> </error> <xf:input ref="/number"> <xf:label>Number of deployments</xf:label> <xf:violations class="error"/> </xf:input> <xf:input ref="/liveUrl"> <xf:label>Live URL</xf:label> <xf:help>You must enter a valid URL</xf:help> <xf:violations class="error"/> </xf:input> <xf:select1 ref="/publish" appearance="full"> <xf:label>Publish</xf:label> <xf:item> <xf:label>Yes</xf:label> <xf:value>true</xf:value> </xf:item> <xf:item> <xf:label>No</xf:label> <xf:value></xf:value> </xf:item> </xf:select1> <xf:group nodeset="" id="favorites_group"> <xf:label>Favorite web sites</xf:label> <!-- repeat is a very powerful iterator tag, because it iterates over a nodeset resulting from the 'nodeset' selector attribute. Very similar to xslt's for-each tag. In this case we iterate over the top three favorite web sites. --> <xf:repeat nodeset="favorite[position() <= 3]" id="favorites"> <xf:input ref="." class="info"> <xf:label>URL:</xf:label> </xf:input> </xf:repeat> </xf:group> <xf:submit id="prev" continuation="back" class="button"> <xf:label>Prev</xf:label> <xf:hint>Go to previous page</xf:hint> </xf:submit> <xf:submit id="next" continuation="forward" class="button"> <xf:label>Next</xf:label> <xf:hint>Go to next page</xf:hint> </xf:submit> </xf:form> <xf:output ref="count" id="show_count" form="form-feedback" class="info"> <xf:label>Visits Count</xf:label> </xf:output> </document> 1.1 cocoon-2.1/src/scratchpad/webapp/samples/jxforms/view/end.xml Index: end.xml =================================================================== <?xml version="1.0" ?> <document> <br/><br/><br/> <table align="center" width="50%" cellspacing="20"> <tr> <td align="center"> <h1> Congratulations, Wizard Complete! </h1> </td> </tr> <tr> <td align="center" class="info"> <code> Your feedback form was processed successfully. </code> </td> </tr> <tr> <td align="center"> <h3> <a href="..">Go to home page.</a> </h3> </td> </tr> </table> </document> 1.1 cocoon-2.1/src/scratchpad/webapp/samples/jxforms/view/start.xml Index: start.xml =================================================================== <?xml version="1.0" ?> <document> <br/><br/><br/> <table align="center" width="50%" cellspacing="20"> <tr> <td align="center"> <h1> Welcome ! </h1> </td> </tr> <tr> <td align="center" class="info"> <p> This wizard will collect feedback information for the <a href="http://xml.apache.org/cocoon/">Apache Cocoon</a> project. </p> <p> See <a href="overview.html">overview</a> documentation. </p> </td> </tr> <tr> <td align="center"> <h3> <a href="flow?cocoon-action-start=true"> Start! </a> </h3> </td> </tr> </table> </document> 1.1 cocoon-2.1/src/scratchpad/webapp/samples/jxforms/view/system.xml Index: system.xml =================================================================== <?xml version="1.0"?> <document xmlns:xf="http://cocoon.apache.org/jxforms/2002/cr"> <xf:form id="form-feedback" view="system" action="" method="GET"> <xf:label>System Information</xf:label> <error> <xf:violations class="error"/> </error> <xf:group ref="/system"> <xf:select1 ref="os" appearance="full"> <xf:label>OS</xf:label> <xf:item id="unix"> <xf:label>Unix/Linux</xf:label> <xf:value>Unix</xf:value> </xf:item> <xf:item id="mac"> <xf:label>Mac OS/X</xf:label> <xf:value>Mac OS/X</xf:value> </xf:item> <xf:item id="win"> <xf:label>Windows 95/98/NT/2000/XP</xf:label> <xf:value>Windows</xf:value> </xf:item> <xf:item id="other"> <xf:label>Other</xf:label> <xf:value>Other</xf:value> </xf:item> </xf:select1> <xf:select1 ref="processor"> <xf:label>Processor</xf:label> <xf:item> <xf:label>AMD/Athlon</xf:label> <xf:value>Athlon</xf:value> </xf:item> <xf:item> <xf:label>AMD/Duron</xf:label> <xf:value>Duron</xf:value> </xf:item> <xf:item> <xf:label>Pentium Celeron</xf:label> <xf:value>Celeron</xf:value> </xf:item> <xf:item> <xf:label>Pentium III</xf:label> <xf:value>p3</xf:value> </xf:item> <xf:item> <xf:label>Pentium IV</xf:label> <xf:value>p4</xf:value> </xf:item> <xf:item> <xf:label>Other</xf:label> <xf:value>other</xf:value> </xf:item> </xf:select1> <xf:input ref="@ram"> <xf:label>RAM</xf:label> <xf:violations class="error"/> </xf:input> <xf:select1 ref="servletEngine"> <xf:label>Servlet Engine</xf:label> <xf:item> <xf:label>Tomcat</xf:label> <xf:value>Tomcat</xf:value> </xf:item> <xf:item> <xf:label>Jetty</xf:label> <xf:value>Jetty</xf:value> </xf:item> <xf:item> <xf:label>Resin</xf:label> <xf:value>Resin</xf:value> </xf:item> <xf:item> <xf:label>Weblogic</xf:label> <xf:value>weblogic</xf:value> </xf:item> <xf:item> <xf:label>WebSphere</xf:label> <xf:value>WebSphere</xf:value> </xf:item> <xf:item> <xf:label>Other</xf:label> <xf:value>other</xf:value> </xf:item> </xf:select1> <xf:select1 ref="javaVersion"> <xf:label>Java Version</xf:label> <xf:item> <xf:label>1.1</xf:label> <xf:value>1.1</xf:value> </xf:item> <xf:item> <xf:label>1.2</xf:label> <xf:value>1.2</xf:value> </xf:item> <xf:item> <xf:label>1.3</xf:label> <xf:value>1.3</xf:value> </xf:item> <xf:item> <xf:label>1.4</xf:label> <xf:value>1.4</xf:value> </xf:item> <xf:item> <xf:label>Other</xf:label> <xf:value>Other</xf:value> </xf:item> </xf:select1> </xf:group> <xf:submit id="prev" continuation="back" class="button"> <xf:label>Prev</xf:label> <xf:hint>Go to previous page</xf:hint> </xf:submit> <xf:submit id="next" continuation="forward" class="button"> <xf:label>Next</xf:label> <xf:hint>Go to next page</xf:hint> </xf:submit> </xf:form> <xf:output ref="count" id="show_count" form="form-feedback" class="info"> <xf:label>Visits Count</xf:label> </xf:output> </document> 1.1 cocoon-2.1/src/scratchpad/webapp/samples/jxforms/view/userIdentity.xml Index: userIdentity.xml =================================================================== <?xml version="1.0"?> <document xmlns:xf="http://cocoon.apache.org/jxforms/2002/cr"> <xf:form id="form-feedback" view="userIdentity" action="" method="GET"> <xf:label>Personal Information</xf:label> <error> <xf:violations class="error"/> </error> <xf:input ref="/firstName"> <xf:label>First Name</xf:label> <xf:violations class="error"/> </xf:input> <xf:input ref="/lastName"> <xf:label>Last Name</xf:label> <xf:violations class="error"/> </xf:input> <xf:input ref="/email"> <xf:label>Email</xf:label> <xf:help>Please check this carefully</xf:help> <xf:violations class="error"/> </xf:input> <xf:input ref="/age"> <xf:label>Age</xf:label> <xf:violations class="error"/> </xf:input> <xf:select ref="/role" appearance="compact"> <xf:label>Professional roles</xf:label> <xf:help>Select one or more</xf:help> <xf:item> <xf:label>Geek</xf:label> <xf:value>Geek</xf:value> </xf:item> <xf:item> <xf:label>Hacker</xf:label> <xf:value>Hacker</xf:value> </xf:item> <xf:item> <xf:label>Student</xf:label> <xf:value>Student</xf:value> </xf:item> <xf:item> <xf:label>University Professor</xf:label> <xf:value>University Professor</xf:value> </xf:item> <xf:item> <xf:label>Software Developer</xf:label> <xf:value>Developer</xf:value> </xf:item> <xf:item> <xf:label>Technical Leader</xf:label> <xf:value>Tech Lead</xf:value> </xf:item> <xf:item> <xf:label>Development Manager</xf:label> <xf:value>Development Manager</xf:value> </xf:item> <xf:item> <xf:label>Executive</xf:label> <xf:value>Executive</xf:value> </xf:item> <xf:item> <xf:label>Heir of the Apache tribe</xf:label> <xf:value>Heir of the Apache tribe</xf:value> </xf:item> </xf:select> <xf:select ref="/hobby" appearance="full"> <xf:label>Hobbies</xf:label> <xf:itemset nodeset="allHobbies"> <xf:label ref="value"/> <xf:value ref="key"/> </xf:itemset> </xf:select> <xf:textarea ref="notes" style="width:8cm; height:3cm"> <xf:label>Additional Notes</xf:label> </xf:textarea> <!-- hidden model attribute --> <xf:hidden ref="hidden"> <xf:value>true</xf:value> </xf:hidden> <xf:submit id="next" continuation="forward" class="button"> <xf:label>Next</xf:label> <xf:hint>Go to next page</xf:hint> </xf:submit> </xf:form> <xf:output ref="count" id="show_count" form="form-feedback" class="info"> <xf:label>Visits Count</xf:label> </xf:output> </document>