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 ... :-)