cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Konstantin Piroumian <KPiroum...@protek.com>
Subject RE: HEADS UP - cocoon form handling (long!!)
Date Wed, 10 Apr 2002 09:51:31 GMT
> 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.

> 
> > > }
> > >
> > > /**  the constraint actually checks the the values of a node.
> > >    *  it's usually a wrapper to existing "restrictions,rules,..."
> > >    */
> > > interface Constraint {
> > >    public boolean isSatifiedBy( Object value, Context context );
> > >    public String getId();
> > > }
> >
> > Shoudn't it be used inside of validate to iterate through and get
> > ConstraintViolation or ValidationError objects?
> 
> true... "validate" gets the constraints for the nodes it is checking
> and "validate" returns failed constraints.

How would you use Contraint object to display error messages? They should
also contain additional information about the node that failed. I think
about Contraint object as a contraint descriptor and not a helper class for
validation and error signaling. Isn't it more intuitive to separate the
descriptor and notificator?

> 
> > > /**  the phase resolver returns the xpaths for for phase
> > >    */
> > > interface PhaseResolver {
> > >    public String[] lookupNodesForPhase( String phase );
> > > }
> >
> > IMO, 'getRelevantNodes()' sounds a little better.
> 
> whatever ;-) ...it needed a name...

Ok ;)

> 
> > > Puh! Now it's your time ;)
> > > Any comments are welcome!!!
> >
> > See above. More to come after looking closer to your samples.
> 
> looking forward on that...

Uh... Too much writing... Real life meetings are definitely much better ;)

--
Konstantin

> --
> Torsten
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: cocoon-dev-unsubscribe@xml.apache.org
> For additional commands, email: cocoon-dev-help@xml.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