Konstantin Piroumian wrote: >>From: Torsten Curdt [mailto:[EMAIL PROTECTED]] >> >>>>HEADS UP - cocoon form handling >>>>------------------------------- >>>> >>>[...] >>> >>>Personally I would stay as close to XForms specification as >>> >>possible (in all >> >>>markup parts, including contraints and events), although >>> >>several parts are >> >>>not possible on the server side or would require too much >>> >>client code >> >>>(JavaScript XPath, etc.). >>> >>That's fine with me... but keep in mind we don't try a XForms >>implementation here... I'm still not yet convinced it's will >>be working >>that great on the server side. (it's not possible to write an >>XForms2HTML >>stylesheet currently without XSLT extension functions!) >> > >This is true if we use XForms markup for the presentation part (view). I >thought about it in a little different way: we use XForms syntax to describe >to data model (schema), bindings (contraints), input fields (UI). Then we >use that as meta-data to initialize form fields with values, error messages, >perform constraint validation, etc. To display a form we can use a >transformer that will transform XForms markup to an intermediate one that >will allow to avoid XSLT extensions. > >When XSLT 2.0 will be out we can rewrite our stylesheets and remove >additional transformation step. > >>So we should limit ourselfs to that syntax where it is not so straight >>forward or makes things too complicated... >> >>we are in the XML world. For a later migration one can easily >>set up an >>ant task for that! >> > >Agree. So let's keep our markup close to XForms and extend/limit when >needed. > >>>Reasons are: >>> - it is a specification that addresses most of the >>> >>possible cases >> >>> - there is a hope that some day XForms would replace >>> >>HTML forms and >> >>>in that case it'll be possible to use Cocoon forms as-is without any >>>additional transformation >>> >>Well, I'm sure this will not happen until Cocoon 3 ;-) >>It has been really quite on the xforms list... >> > >Yes, that's true. Although, there are already several browser >implementations of XForms on the client-side, but they are not wide-used. > >>> - we need an agreement on terms and processing models >>> >>and this can >> >>>be achieved without reinventing the wheel >>> >>aggreed... >> >><snip/> >> >>>>The view maps values from the instance to controls. >>>> >>Syntax reminds on >> >>>>XForms: >>>> >>>> <i:instance id="feedback-form"> >>>> <i:textbox ref="user/firstname"/> >>>> <i:textbox ref="user/lastname"/> >>>> ... >>>> </i:instance> >>>> >>>Why input fields are children of instance? And should we >>> >>support multiple >> >>>instances? Why not use pure XForms syntax? It will look like this: >>> >>> <xforms:group ref="feedback-form"> >>> <xforms:input ref="user/firstname"/> >>> <xforms:input ref="user/lastname"/> >>> ... >>> </xforms:group> >>> >>>(Field captions as well as other possible elements and >>> >>attributes are >> >>>omitted). >>> >>I am fine that, too... The XForms spec has changed quite a >>lot since the >>last time I had look... IIRC it was something like to above before... >>anyway. Children of the instance means use instance id=".." >>as reference. >>We can use can use xforms syntax for that, too :) >> > >Let's agree on one instance per form. I don't see any real need for multiple >instances support, at least for the first time. > >> >>>> -o- >>>> Populating >>>> >>>>Taken from the ExFormular project we call this saving into >>>>the instance >>>>on a POST "populating". There are two different approaches when >>>>populating. Direct and indirect. While the direct populating >>>>method is >>>>quite straight forward on the first glance: "go through the >>>>request and >>>>save the request parameters into the instance" it has some major >>>>problems as of the POST behaviour of checkboxes: on "true" >>>>there will be >>>>a request parameter, on "false" there will be no request >>>> >>parameter at >> >>>>all. So with direct population you cannot set checkboxes to >>>>"false". The >>>>other method is indirect population. With this approach >>>> >>you actually >> >>>>*know* what parameters *should* come with the request. So >>>> >>a missing >> >>>>checkbox parameter means "set this checkbox to false". >>>>Although we could >>>>use the direct population (with some workarounds) we >>>> >>aggreed on using >> >>>>indirect populating as it is the cleaner approach in the >>>> >>long run. No >> >>>>hidden field or something like that... >>>> >>>That's good. And this will require to create an object >>> >>model of the form to >> >>>be able to iterate through its fields, according >>> >>constraints, etc. This will >> >>>also help in cases, when there are not 'relevant' (see >>> >>XForms 'relevant' >> >>>constraint) fields. This means, that not all the fields are >>> >>necessary to be >> >>>taken into account for the current request depending on >>> >>values of some other >> >>>fields (not sure that it's easy to implement, though). >>> >>what do mean by "object model of the form"? I actually don't >>want to have >>always beans behind my forms. Is this what you are at? >> > >Yes, that was the idea. Anyway, we need to know, as you've said, what to >expect from the current request. There are two possibilities: create a >separate description (say, phases) or use the form description itself. If we >create an object model of the form (not only UI, but also bindings) then we >can simply iterate through form fields, validate according values from >request against a schema, then we can validate request against binding >contraints. > >We can use 'visible', 'relevant' attributes of bindings (maybe also some >other means) to find out which params from request are relevant. Seems to me >not very complicated, although requires a bunch of classes for every >possible element: input, select*, output, binding, etc. > >> >>>> -o- >>>> Phases >>>> >>>>A phase defines a set of nodes of an instance. Phases are >>>> >>usally used >> >>>>in the validation and population process. >>>> >>>Would we need this if we knew which fields are relevant for >>> >>the current >> >>>request? >>> >>for population: >>since we have chosen indirect populating we need to know what >>to expect >>from a specific POST. >> >>for validation: >>we could use it to know what is relevant... >> > >See above > >>>> -o- >>>> Preceptor >>>> >>>>Our instance can be expressed in XML. Directly when it's a >>>>DOM or mapped >>>>via Castor when we have beans. This means we should be >>>> >>able to use the >> >>>>commonly used validation methods to validate our instance >>>> >>(= data of a >> >>>>form). We would usually call them Schemas but since the term >>>>collides with short form of the W3C XML Schema validation we >>>>aggreed on >>>>"preceptor" for a general validity description of an XML >>>>document. Such >>>>a desciption will be served via pipeline and then "compiled" >>>>and saved >>>>into the scope of the instance. The JARV project shares >>>>almost the same >>>>idea here. Unfortunately they do not have support for partial >>>>validation >>>>yet, too. >>>> >>>I would keep Schema as it is also used in XForms to >>> >>describe to model schema >> >>>(which is not required to be W3C XML Schema). Preceptor is >>> >>not obvious and >> >>>is difficult to pronounce ;) >>> >>hm... don't know :-/ >> > >Ok, it's not a big issue, so let's keep Preceptor if you like it more. We >can change it in future. > >>(do you really think it's difficult to pronounce?? Cannot be harder >>than you lastname ;-) >> > >This is a i18n problem ;) >Btw, my lastname is pronounced like "pee - ru - myan". > >>>>There are two different parts of XML document validity: >>>> a) structure of the document >>>> b) content of nodes >>>> >>>c) data dependency >>> >>oh... yes >> >>>> -o- >>>> Content Validation >>>> >>>>Let's focus on the content first. It's the most important >>>>thing for form >>>>validation. Each preceptor defines some kind of rules, >>>> >>restrictions, >> >>>>assertations for the content of nodes of the instance. As >>>>general term >>>>we will call them "constraints". Probably the most important >>>>constraints >>>>from the grammar based world (schema,relaxng) are >>>> >>>> *) regular expressions constraint >>>> *) enumeration or choice constraint >>>> *) minimum number value constraint >>>> *) maxmimum number value constraint >>>> *) minimum string length constraint >>>> *) maximum string length constraint >>>> *) ... >>>> >>>>While schematron only has a single but very powerful >>>> >>constraint that >> >>>>combines all the above into the >>>> >>>> *) XPath expression constraint (except for regex until >>>> >>XPath 2.0) >> >>>We can use XForms markup for model schema description and >>> >>use Schematron for >> >>>validation. Although, I'm not sure for other implementations. >>> >>I need to have a look at that... but I'd still prefer my >>people to be able >>to use XMLspy to define our forms and their validation. >>That's possible >>nice for XSD and I bet they soon come up with relaxng support, too. >> > >This is not a problem as XForms allow XSD for model description along with >its own simplified schema. > >>>> -o- >>>> Structure Validation >>>> >>>>The structure validation takes care of the instance to >>>> >>conform to a >> >>>>described xml structure. We have not yet aggreed if the >>>>structure should >>>>be fully described by the preceptor or a partial >>>> >>describtion may be >> >>>>sufficient. This decision has a major impact on the >>>> >>building of the >> >>>>instance and the implementation details. >>>> >>>What about the validation against contraints? Say, >>> >>'required' fields? Maybe >> >>>we can develop our own validator for XForms binding contraints? >>> >>>> -o- >>>> Building the Instance >>>> >>>>At the start of the flow an instance needs to be created >>>> >>to take the >> >>>>values of the POSTs. If we want to support structure >>>>validation we need >>>>to make sure that already the empty instance conforms to the >>>>preceptor. >>>>As of this we need to create all the required nodes in this >>>>instance then. >>>> >>>How do we deteremine required nodes? >>> >>Well, the preceptor should know about it... it defines what >>is required >>and what is optional. >> > >Hm... So, what are the all tasks that are performed by the preceptor? > >[...] > >>>Flow controller also should determine that the process is >>> >>finished and >> >>>perform some business logic calls with collected data, >>> >>isn't it? After that >> >>>some default (success page) should be displayed. >>> >>why finished?? can you elaborate a bit more, please? >> > >What happens when user has entered all the required feedback information >then wishes to click on the final 'Submit' (or 'Done' or 'Send') button? The >flow process should be finished after the data is stored somewhere and some >notification should be displayed to the user after that. Am I wrong? > >>>>Unfortunately this looks much easier at the first glance than >>>>it is. We >>>>will now try to talk about the problems we have encounter so far. >>>>(and there possible sollutions ;) >>>> >>>>on 1) >>>> How do we specify an introspection for a flow? >>>> >>>> This can easily be done either with schecoon or with the >>>>multiaction >>>> that comes with precept. But the question is: Should >>>>this be modeled >>>> in XML, in java or a scripting language? >>>> >>>Form descriptor can be dynamic and have special tags for this, e.g.: >>><instance> >>> <castor:insertBean .../> >>><instance> >>>Then it will be used as source for IntrospectionAction: >>> >>><map:act type="init"> >>> <map:parameter name="form-descriptor" >>>value="cocoon:/get-form?form-id=102" /> >>></map:act> >>> >>>Seems a little complicated... >>> >>Sorry, you've lost me... >> > >Yes, I see... > >>>>on 2) >>>> How does the controller know which view is the first >>>> >>one and what >> >>>> views are actually available? >>>> >>>For a good wizard it would be also needed to know what >>> >>actions are available >> >>>('next', 'previous', 'done', etc.). >>> >>Well, I see this bound to a button in the view markup... or in a >>descriptor... >> > >I the flow descriptor or where? >I'd prefer dynamic navigation buttons in future. I'd implemented something >like that with C1 and buttons appeard depending on the user position in >wizard. This can be easily added after we implement everything with static >buttons. > >>>> This could be set from the introspection. If not >>>>specified the first >>>> view from a possible descriptor could be taken. >>>> See also "VIEWS AND PHASES". >>>> >>>This depends on the flow engine. Should we focus on this now? >>> >>focus on what? on the flow engine? >> > >Yes. We can have a stub (maybe hard coded) for everything that needs a flow >controller and first of all implement form >population/validation/presentation parts. > >>>>on 3) >>>> How does the controller know what to populate and validate on a >>>> submit? >>>> >>>> Inside the views or in a descriptor like it is in Struts >>>>we should >>>> probably have a mapping of the phases to buttons. >>>> See "VIEWS AND PHASES". >>>> >>>This can be addressed by using XForms 'relevant' contraint >>> >>and some of the >> >>>events. Say, treat a button as event, then go through the >>> >>form description >> >>>to find out which fields are affected with this event. >>> >>ok.. but how and where do you want to define relevance then? >> > >In XForms bindings. E.g.: ><bind ref="customer/car-info/issue-year" relevant="customer/has-car='true'" >required="true" /> > >You should have seen this in my XForms sample. > >[...] > >>>> How can we only validate parts of an instance? >>>> >>>> Unfortunately most current validation implementations don't >>>> support partial validation of documents yet. Schematron is >>>> one exception. Maybe some of the authors can assist here. >>>> >>>Maybe we can validate the document in whole, but ignore >>> >>irrelevant parts? >> >>I have been thinking about this, too... This way we adopt validation >>implementations more quickly... unfortunately validation >>itself will be >>much slower... >> > >After we have any validation we will have the community power to optimize it >;) > >[...] > >>>>a) within the view >>>><view> >>>> <instance id=".."> >>>> <textbox ref="user/firstname"/> >>>> <textbox ref="user/lastname"/> >>>> <button> >>>> <caption>Next</caption> >>>> <populate>phase2</populate> >>>> <validate>phase2</validate> >>>> </button> >>>> </instance> >>>></view> >>>> >>>Hm... Absolutely not XForms synax. Are we going to invent >>> >>our own markup? >> >>Not really... but I fear we have to compromise... I'll have >>look into the >>XForms draft again but IIRC I didn't like their approach on >>the buttons... >> > >Me too. They are using submit info elements and their event model. I'll look >at it too... > >>>>b) within a descriptor >>>> >>>> <no syntax yet/> >>>> >>>Maybe XForms bindings can solve this one? >>> >>I have to have a look into the spec again... >> >>>>Currently only schematron comes with a native phases >>>> >>support. All the >> >>>>others don't support partial validation yet. Although Torsten >>>>is not so >>>>sure if this should be really part of the preceptor. >>>>(Torsten: as soon as you move a textbox from one view into >>>>another one >>>>you need alter your preceptor because the phases have >>>>changed. For SoC >>>>this should not be IMHO) >>>> >>>I am agree with Ivelin on this one. >>> >>...so you think it should be part of the preceptor?? >> > >No!!! Exactly the opposite. Sorry, didn't notice that it was your comment ;) > >>>>But the question still remains: how can we implement phases for >>>>preceptor other than schematron? All we came up was some kind of >>>>PhaseResolver than can takes the same schematron file as >>>>input for the >>>>SchemtronPhaseResolver and other descriptors (to be >>>> >>defined) for e.g. >> >>>>the RelaxNGPhaseResolver. >>>> >>>Seems to me a little artificial, it's not a good sign ;) >>> >>well, then we need come up with something better... >> > >Speaking frankly, I don't like the phase idea at all. It adds another >configuration file that should be supported and kept in sync with form >descriptors. >Let's find answer on this: is form description (descriptor) itself enough to >determine the phase or simply the request params that should be taken into >account during validation and instance update? Or: are the phase and >relevant params the same thing? > >> >>>> IMPLEMENTATION DETAILS >>>> >>>> From the above we came up with some minimalistic interfaces: >>>> >>>>/** the instance save and retrieves values based on an xpath >>>> */ >>>>interface Instance { >>>> public void setValue( String xpath, Object value, >>>> >>Context context); >> >>>> public Object getValue( String xpath ); >>>>} >>>> >>>What about the >>>addValue(...) >>>removeValue(...) >>> >>whatfor? >> > >For multiselect fields. E.g.: > ><user-servers> > <server>Tomcat 3.3</server> > <server>WebLogic 6.1</server> > ... ></user-servers> > >This is only one case. Also depending on the received event you would need >to add or remove nodes in instance, not only to update. Instance updates are >another story and we should agree on how should we use the event model for >it and should we use it at all? > >>>>/** the preceptor validates nodes from a specific phase >>>>looked up via >>>>the phase resolver >>>> * >>>> */ >>>>interface Preceptor { >>>> public Collection validate( Instance i, PhaseResolver resolver, >>>>String phase, Context context ); >>>> /* or better typesafe? >>>> public Constraint[] validate( Instance i, >>>> >>PhaseResolver resolver, >> >>>>String phase, Context context ); >>>> */ >>>> >>>Why Constraint[] and not ContraintViolation[]? Shouldn't >>> >>validate perform >> >>>validation then return an error list? >>> >>Well, why create ConstraintViolation object. Returning the Constraint >>itself is enough. We know that this Constraint failed... because it is >>returned... >> > >Hm... Not very intuitive. I'd design it in a little different way, say: >return a collection of ValidationViolation objects and each of them can be >of different types or have a field indicating the violation type. E.g.: >incorrect data format, required contraint violation, etc. Then we can use >the violation type to select the appropriate error message (this also takes >into account i18n of errors). > >Also, IIRC you've mentioned that validation should be two phase operation >(again those phases ;) ): > - data types validation > - contraint validation >The second phase should be skipped for those fields that didn't pass the >first one. So, we will need at least two types of objects indicating an >invalid state of data. >
A small input for this particular design point (didn't have the time to read all this however interesting stuff)... In our in-house form validation stuff, the validate method looks like : void validate(Map values, ValidationReport report) throws ValidationException ValidationReport is basically a collection where one can add ReportElements such as constraint violations. If validation fails, the report is filled _if not null_ and a ValidationException is thrown. This allows the following : - consistency with Java error-handling : an exception is thrown in case of failure. Using method result for success is error-prone as someone may omit the test and continue with bad data. - allows a fail-fast strategy : if validation occurs in a non-user context (e.g. SOAP request), we want a fast binary ok/not-ok answer and don't care about a detailed explanation, so the first error encountered should stop validation. The trigger for this strategy is the report parameter : if null, then fail fast and don't provide messages. If non null, try to validate as much as possible to give a maximum of information to the user. My little 2 euro-cent... <snip/> Cheers, Sylvain -- Sylvain Wallez Anyware Technologies Apache Cocoon http://www.anyware-tech.com mailto:[EMAIL PROTECTED] --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]