cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Sylvain Wallez <sylvain.wal...@anyware-tech.com>
Subject Re: HEADS UP - cocoon form handling (long!!)
Date Thu, 11 Apr 2002 13:17:42 GMT
Konstantin Piroumian wrote:

>>From: Torsten Curdt [mailto:tcurdt@dff.st] 
>>
>>>>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:sylvain@apache.org




---------------------------------------------------------------------
To unsubscribe, e-mail: cocoon-dev-unsubscribe@xml.apache.org
For additional commands, email: cocoon-dev-help@xml.apache.org


Mime
View raw message