Daniel, I added parts of your email to the current readme.txt which ships with XMLForm. Hope you don't mind. Included author reference of course.
see below... ----- Original Message ----- From: "Daniel Fagerstrom" <[EMAIL PROTECTED]> To: <[EMAIL PROTECTED]> Sent: Saturday, May 04, 2002 10:39 AM Subject: RE: Flow and XMLForm > [EMAIL PROTECTED] wrote: > > Hi Ivelin, > > > > On Mon, 29 Apr 2002 08:22:55 -0500, "Ivelin Ivanov" > > <[EMAIL PROTECTED]> wrote: > > > > > one of the action items on your list a couple weeks ago was to > > > evaluate the possibility of integration between Schecoon and the > > > XMLForm framework. Have you had time to do that yet? > > > > I looked at the code in scratchpad, but it's unclear to me how this > > integration could proceed with the current incarnations of XMLForm and > > the flow layer. I still need to spend more time thinking about this. > > > > Do you have any ideas about it? > > I'm not Ivelin, but I have some ideas anyhow ;) > > Background > ---------- > The aim of XMLForm, AFAIU, is to build and edit an xml document (called the > instance), subject to constraints from some schema (XMLSchema, Schematron, > ...), through a sequence of form pages. The instance is either a > dom-document or a Java bean-structure or a mix. XMLForm consist, AFAIU, of > three main components: > > * Form - is responsible for the instance and validation of it. Form objects > are stored in request attributes for one page forms and session attributes > for wizards (multi page forms). A Form can be populated from the request > parameters. > > * XMLFormTransformer - takes a form descriptor, (similar to XForms) as input > and fill it with data and error messages from a Form object that is > referred in an attribute "view". > > * AbstractXMLFormAction, (WizardAction) - creates the Form object if > necessary and populates it with data based on the request parameters. It can > also take care of flow handling and checkbox state. This is so well stated, that I couldn't help adding it to the README.txt Check it out and let me know if it's fine with you. > > > XMLForm - flow layer integration > -------------------------------- > > As we assume that there is anything to integrate, I guess that it is obvious > that the flow layer should be responsible for the flow handling. For wizards > there are two levels of flow handling: if a form is filled in in a faulty > way it should be resend with the faulty content and error messages. There is > also page flow where the choice of the next form page might depend on > earlier input. > > The next question is: who should be responsible for handling the Form > object? In XMLForm, actions that inherit from AbstractXMLFormAction, e.g. > WizardAction is responsible for this. In an XMLForm - flow layer > integration, handling of the Form object should IMHO be the responsibility > for the flow layer. After all, the aim of a wizard flow script is to > (possibly through several form pages) update the state of an instance. If > this should be obvious from reading the flow script, the handling of the > Form object should be explicit in it. > > One-page forms > -------------- > > To take care of a one-page form we need to: > 1. Create and configure a Form object. > 2. Create and send an html form page and prefill it with data from the form > object, return address (continuation), and possibly add error messages. > 3. Read the input from a POST, populate the Form object with the input and > go back to step 2. if the input is invalid. > > This could be coded as: > > function getUserInput(form, view) > { > do { > sendPage("wizard/"+ view + ".html", {"id" : form.getId()}); > form.populate(cocoon.request()); > } while (!form.valid()); > } Thanks for the example. It helps me understand the flow concepts further. Question: Where would you handle business logic? For exampe if the next step in a wizard depends on what was selected in the current step, and some data has to be pulled out from an external resource and made available to the next wizard page. > > Here, the parameter "form" is a Form object and "view" is a string. I don't > follow the interfaces in XMLForm in every detail. Note that thanks to the > continuations, we can group together the form page code, followed by the > code that takes care of its output and not the other way around: take care > of input from last form followed by generating the next form page, as in the > sitemap. > > <map:match pattern="*.html"> > <map:generate src="{1}.xml"/> > <map:transform type="xmlform"> > <map:parameter name="id" value="{id}"/> > <map:parameter name="action" value="{continuation}"/> > <map:transform/> > <map:transform src="stylesheets/wizard2html.xsl"/> > <map:transform src="stylesheets/xmlform2html.xsl"/> > <map:serialize type="html"/> > </map:match> > > This is like in the example sitemap for XMLForm, with the differences that: > We have no XMLFormAction, its responsibilities are moved to the flow layer. > The XMLFormTransformer uses the continuation parameter, (from the flow > layer) for setting the "action" attribute of the form, and "id" for setting > the "id" attribute for referring to the Form object. The later part is not > necessary but I think it gives a better SoC if the form descriptors doesn't > know what instance they are supposed to update, if they know, you can't > reuse e.g. a "fill in user data form" between wizards. > > Multi page forms > ---------------- > > A wizard could be coded like: > > function cocoonSurvey() > { > form = new Form(...); > > getUserInput(form, "userIdentity"); > getUserInput(form, "deployment"); > getUserInput(form, "system"); > if (form.getValue("/system/os") == "Linux") > getUserInput(form, "linuxDetails"); > else if (form.getValue("/system/os") == "MacOSX") > getUserInput(form, "macOSXDetails"); > else if (form.getValue("/system/os") == "Windows") > getUserInput(form, "windowsDetails"); > getUserInput(form, "confirm"); > > storeResults(form, db); > } > > Where the form constructor get default values, schema etc as input. I also > assume, (as I guess one generally assume while using the flow layer?), that > there is a submit button on each form page. If one want to edit earlier form > pages in the flow one is supposed to press submit on the current one before > using the backward button on the browser if one want to save the content of > the current form. > > In Ivelins example there is a next and a previous button in the form pages. > If we want something like that in the flow layer the code gets a little bit > less neat: > > ... > userIdentity: getUserInput(form, "userIdentity"); > deployment: getUserInput(form, "deployment"); > if (cocoon.request.getParameter("action") == "previous") > goto userIdentity; > system: getUserInput(form, "system"); > if (cocoon.request.getParameter("action") == "previous") > goto deployment; > ... > > I'm not certain about the goto syntax in JS, but I guess you get the idea. > Is there a better way to code it? I would be curious to learn how validation can be kept flexible as well. In the next release of XMLForm I will apply a request made by Konstantin to not do validation on Previous. > I think there are at least three ways to attack this problem, (except for > writing something as ugly as the above code): > * Don't care about it and use a "submit" button instead of "next" and > "previous" buttons - I think this is the cleanest solution and I tend to > prefer it. On the other hand, after having met all kind of lousy > implementations of multi page forms I am a little bit reluctant to use the > "backward" button in my browser while filling in forms, I guess most people > have similar experience. Some of the real-life apps which my team builds needs to deal with Prev. > * Using finite state machines for describing the flow :( > * Adding some ingenious mechanism to the flow layer that handle > "previous"-buttons automagically. > > Conclusion > ---------- > > If I didn't miss anything important above, I think that XMLForm and the flow > layer can be integrated with a fairly small effort. In the example code > above I used some small additions to the Form class, but I don't think any > of them are necessary, the only thing that is necessary is to insert the > continuation address in the action attribute in the html form. This could be > done either in the XMLTransformer, as above or in one of the following > XSLTTransformers or maybe even by writing the form descriptors in XSP. Great summary. There is no way I could have responded better to Ovidiu's message. I agree that these two frameworks can and should integrate. I am strugglinng big time with cleanly separating the responsibilites between the two at this point though. Will greatly appreciate further suggestions in this direction. Cheers, Ivelin > > What do you think? > > /Daniel Fagerstrom > > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, email: [EMAIL PROTECTED] > --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]