On Thu, 25 Nov 2004 19:41:01 +0100, Sylvain Wallez <[EMAIL PROTECTED]> wrote:
> Peter Hunsberger wrote:
> 
> >On Wed, 24 Nov 2004 23:57:13 +0100, Sylvain Wallez <[EMAIL PROTECTED]> wrote:
> >
> >
> >>[catching up the list - guys, you were so verbose lately !]
> >>
> >>Reinhard Poetz wrote:
> >>
> >>>Just wondering why in the examples always the FormsTransformer is used
> >>>although the use of the FormsGenerator is possible. Does this have a
> >>>special reason?
> >>>
> >>>
> 
> <snip/>
> 
> >>Ah, and the FormGenerator can also be used for some webservice-style
> >>clients where no layout is needed.
> >
> >The way we attack this is to aggregate the output of two generators:
> >one creates the object model and the other creates the layout model.
> >Conceptually, a XSLT then walks the object model and annotates it with
> >the layout data.  A second XSLT then takes the combined model and
> >pumps out the actual xhtml (or whatever). In some cases  this simply
> >means adding class attributes since much of our actual styling is left
> >to CSS, but in other cases we do create gobs of xhtml...
> >
> 
> Looks complex, but you certainly have good reasons for it. So could you
> elaborate on this and give some examples of what the layout model and
> the annotated model look like?

Sure, but I have to remind you that we have our own proprietary forms
model implemented before cforms (or Woody for that matter) came on the
scene.  Also, let me point out that we have a somewhat unusual set of
circumstances: our object model is common to many different layout's. 
We have many different clinical trials (over 200 open trials) that all
potentially use the same metadata object model to describe things. 
Eg. a transplant or a radiation treatment.  Various different clinical
trials and treatment protocols may want different parts of this
metadata, eg. the radiation model describes over 30 fields and in some
non-radiation related trials you may only need 4 or 5 of them. We
roughly map a set of clinical trials to what we call a "service" and
users sign on to various services (eg. http://server/logon/tgt where
tgt is transplant gene therapy)

As a result, what we needed was a way for business analysts to
describe object models in metadata then be able to build different
layouts for the same metadata. We knew we where going to build a
metadata editor and a layout editor for each of these separate tasks. 
The metadata gets stored in a relational database, the layout also is
stored there as a XML blob.

The generated XML metadata looks something like:

<metadata>
   <transplant type="Therapy" title="Transplant" fromData="false"
metaType="true" isGlobal="false" collectionKeyName="therapyId">
       <transplantId title="Primary Key" type="Hidden"
mandatory="true" desc="The value associated with this object should
uniquely identify an instance of data."/>
       <diagnosisId title="diagnosisId fkey" desc="Foreign Key to
transplant" type="Key" mandatory="true"/>
       <phaseId title="phaseId fkey" desc="Foreign Key to Phase"
type="Key" mandatory="true"/>
       <trnsplntnbr title="Transplant Number" desc="" type="Number"
mandatory="true" passPrimaryKey="true" forwardCollectionTemplate=""
forwardCollectionSystemName="trnsplntinf">
           <comparisonParameter>trnsplntnbr</comparisonParameter>
       </trnsplntnbr>
       <trnsplntdte title="Transplant Date" desc="Transplant"
type="Date" mandatory="false"/>
       <subPhaseId title="subPhaseId fkey" desc="Foreign Key to
subPhase (generated)" type="Key" mandatory="true"/>
       <protocolId title="Protocol Id fkey" desc="" type="Key"
mandatory="true"/>
   </transplant>
   <objectRelationships/>
</metadata>

I've snipped name spaces and a bunch of attributes that aren't really
relevant to the layout discussion.  A typical layout for this simple
example might look like:

<layout type="grid">
       <title>Transplant</title>
       <transplant>
           <diagnosisId order="0" active="true"/>
           <phaseId order="1" active="true"/>
           <trnsplntnbr title="Transplant Number" order="2" active="true"/>
           <trnsplntdte title="Transplant Date" order="3" active="true"/>
       </transplant>
</layout>

Again I've snipped namespaces and attributes.

Note that the layout (not the metdata) specifies the presentation
order.  However,  mandatory elements in the metadata not specified in
the layout will be added at the end of the layout.  Usually these are
hidden fields (like keys).  This is only half the picture.  There is
also a CSS that will travel with this layout that specifies other
styling details, thus the XML half of the layout is mainly concerned
with augmenting and overriding the object model.

The other thing that get's picked up when these two models are
combined is authorizations which look like:

<authorizations>
   <transplant>
       <authorization service="1">Read</authorization>
       <authorization service="1">Write</authorization>
       <authorization service="1">Update</authorization>
       <authorization service="1">Delete</authorization>
       <authorization service="2">Read</authorization>
                         .....

but can also be specified down to the element level.  If you're not
authorized to see a given element you won't see it even if it is
mandatory.  If you have Read only authorizations you won't be able to
edit it, etc...  A given user may have different authorizations in
different services and a given screen may contain different data from
different services relevant to a given patient.  Thus a user might be
able to edit a row of data from his own service but see a row of data
from a companion protocol as read only.

Finally, we also have validation rules which will be consumed by
Schematron on the POST side of things, but are used for additional
annotations at styling time:

   <validation>
       <pattern name="Collection Validation">
           <trnsplntnbr dataRequirement="required" message="Transplant
number must be entered"/>
           <trnsplntdte dataRequirement="required" message="Transplant
date must be entered"/>
       </pattern>
       <pattern name="Object Validation">
           <rule dataType="Date_Type" name="trnsplntdte">
               <assert failtype="">Transplate date must be a valid date.
                   <expression object="trnsplntdte"
object_expression="" operator="" value="" value_expression="isDate"
value_object="" rowlevel="" dataRequirement="" linker=""/>
               </assert>
           </rule>
       </pattern>
   </validation>

We will mark required elements with different styles (and the CSS
might also add other styling), and we have other validation rules that
can result in other annotations.

Each of these XML fragments is created by a different generator
depending on it's cache validity life cycle.  Object models are global
across all services.  Layouts are cached by service, authorizations
are cached by individual (and invalidated by group).  Validation
models are cached by service. etc.  I almost forgot, there is other
global metadata at both the service and the application level and
these are also generated and cached separately as appropriate.

So yes, this is all somewhat complex but it works out very well.  It
has pretty good performance, but the main thing is that it is very
flexible.  When you're doing research data collection you simply don't
know from day to day exactly what your data collection requirements
will be.  You can't use a fixed schema and you can't require custom
coding for each change to a protocol or clinical trial.

Currently we're working on conditional layout templates that allow you
to create template fragments attached to a filter.  Consider a drug
screen where the first fields are the drug, the data and the question
"Was drug administered as planned?"  If the user enters yes you then
present fields for dose,  etc.  If not you present a field for
explanation. So attached to a given layout you might see something
like:

<filter object="administered" contains"yes"/>

this will generate client side Javascript to expose or hide various
layouts as required and generate server side sets of validation rules
to match the various conditions. We're also normalizing layouts across
services so that a service can reuse a layout from another service
(eg. not every service needs a custom layout for the logon screen.)

Final note, combining the object models and the layout models is done
separately from generating the presentation model.  There are two
separate XSLTs.  The first combines the various models into a given
set of instance data.  The second XSLT generates the actual output for
target device (xhtml or PDF or whatever).

Feel free to ask for more details, this only starts to skim the
surface of what we are doing...

-- 
Peter Hunsberger
(Careful what you ask for, you might get it ...  :-)

Reply via email to