Copied all the currently working transforms from 'transforms01' to 'transforms'; created new schema 'adl-0-1-0.xsd' which once tested should become the new

normative reference.
This commit is contained in:
sb 2008-05-29 16:39:07 +00:00
parent bf13d05877
commit e2130bc4c4
20 changed files with 6161 additions and 3159 deletions

2
.cvsignore Executable file
View file

@ -0,0 +1,2 @@
obj
bin

734
schemas/adl-0-1-0.xsd Executable file
View file

@ -0,0 +1,734 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
<!-- -->
<!-- adl-0-1-0.xsd -->
<!-- -->
<!-- Purpose: -->
<!-- XML Schema for Application Description Language. Note that this -->
<!-- is experimental; the DTD is still normative at this stage -->
<!-- This revision autoconverted using visual studio from -->
<!-- adl-0.dtd revision 1.14 -->
<!-- -->
<!-- Author: Simon Brooke <sb@cygnets.co.uk> -->
<!-- Created: 9th January 2008 -->
<!-- $Revision: 1.1 $ -->
<!-- Copyright: (c) 2008 Cygnet Solutions Ltd -->
<!-- -->
<!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
<xs:schema elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns='http://www.cygnets.co.uk/schemas/adl-0-1-0.xsd'
targetNamespace='http://www.cygnets.co.uk/schemas/adl-0-1-0.xsd'
xmlns:adl='http://www.cygnets.co.uk/schemas/adl-0-1-0.xsd'
xmlns:html='http://www.w3.org/1999/xhtml'>
<!--
the application that the document describes: required top level element
name: the name of this application
version: the version number of this application
xmlns: XML namespace, in case required
-->
<xs:element name="application">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" ref="documentation" />
<xs:element minOccurs="0" maxOccurs="1" ref="content" />
<xs:element minOccurs="0" maxOccurs="unbounded" ref="typedef" />
<xs:element minOccurs="0" maxOccurs="unbounded" ref="group" />
<xs:element minOccurs="0" maxOccurs="unbounded" ref="entity" />
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required" />
<xs:attribute name="version" type="xs:string" />
</xs:complexType>
</xs:element>
<!--
the definition of a defined type. At this stage a defined type is either
a string in which case it must have size and pattern, or
a scalar in which case it must have minimum and/or maximum
pattern must be a regular expression as interpreted by org.apache.regexp.RE
minimum and maximum must be of appropriate format for the datatype specified.
Validation may be done client-side and/or server-side at application layer
and/or server side at database layer.
name: the name of this typedef
type: the simple type on which this defined type is based; must be
present unless in-implementation children are supplied
size: the data size of this defined type
pattern: a regular expression which values for this type must match
minimum: the minimum value for this type (if base type is scalar)
maximum: the maximum value for this type (if base type is scalar)
-->
<xs:element name="typedef">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" ref="documentation" />
<xs:element minOccurs="0" maxOccurs="unbounded" ref="in-implementation" />
<xs:element minOccurs="0" maxOccurs="unbounded" ref="help" />
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required" />
<xs:attribute name="type">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="string" />
<xs:enumeration value="integer" />
<xs:enumeration value="real" />
<xs:enumeration value="money" />
<xs:enumeration value="date" />
<xs:enumeration value="time" />
<xs:enumeration value="timestamp" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="size" type="xs:string" />
<xs:attribute name="pattern" type="xs:string" />
<xs:attribute name="minimum" type="xs:string" />
<xs:attribute name="maximum" type="xs:string" />
</xs:complexType>
</xs:element>
<!--
information about how to translate a type into types known to different target
languages. TODO: Once again I'm not wholly comfortable with the name; I'm not
really comfortable that this belongs in ADL at all.
target: the target language
value: the type to use in that target language
kind: OK, I confess I don't understand this, but Andrew needs it...
-->
<xs:element name="in-implementation">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" ref="documentation" />
</xs:sequence>
<xs:attribute name="target" type="xs:string" use="required" />
<xs:attribute name="value" type="xs:string" use="required" />
<xs:attribute name="kind" type="xs:string" />
</xs:complexType>
</xs:element>
<!--
a group of people with similar permissions to one another
name: the name of this group
parent: the name of a group of which this group is subset
-->
<xs:element name="group">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" ref="documentation" />
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required" />
<xs:attribute name="parent" type="xs:string" />
</xs:complexType>
</xs:element>
<!--
an entity which has properties and relationships; maps onto a database
table or a Java serialisable class - or, of course, various other things
name: obviously, the name of this entity
natural-key: if present, the name of a property of this entity which forms
a natural primary key [NOTE: Only partly implemented. NOTE: much of
the present implementation assumes all primary keys will be
integers. This needs to be fixed!] DEPRECATED: remove; replace with the
'key' element, below.
table: the name of the table in which this entity is stored. Defaults to same
as name of entity. Strongly recommend this is not used unless it needs
to be different from the name of the entity
foreign: this entity is part of some other system; no code will be generated
for it, although code which links to it will be generated
-->
<xs:element name="entity">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" ref="documentation" />
<xs:element minOccurs="0" maxOccurs="1" ref="content" />
<xs:element minOccurs="0" maxOccurs="1" ref="key" />
<xs:element minOccurs="0" maxOccurs="unbounded" ref="property" />
<xs:element minOccurs="0" maxOccurs="unbounded" ref="permission" />
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="form" />
<xs:element ref="page" />
<xs:element ref="list" />
</xs:choice>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required" />
<xs:attribute name="natural-key" type="xs:string" />
<xs:attribute name="table" type="xs:string" />
<xs:attribute name="foreign">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="true" />
<xs:enumeration value="false" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
<!--
contains documentation on the element which immediately contains it. TODO:
should HTML markup within a documentation element be allowed? If so, are
there restrictions?
-->
<xs:element name="documentation">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string" />
</xs:simpleContent>
</xs:complexType>
</xs:element>
<!-- an explicit primary key, possibly compound -->
<xs:element name="key">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="property" />
</xs:sequence>
</xs:complexType>
</xs:element>
<!--
a property (field) of an entity (table)
name: the name of this property.
type: the type of this property.
default: the default value of this property. There will probably be
magic values of this!
typedef: name of the typedef to use, it type = 'defined'.
distinct: distinct='system' required that every value in the system
will be distinct (i.e. natural primary key);
distinct='user' implies that the value may be used by users
in distinguishing entities even if values are not formally
unique;
distinct='all' implies that the values are formally unique
/and/ are user friendly (NOTE: not implemented).
entity: if type='entity', the name of the entity this property is
a foreign key link to.
if type='list', the name of the entity that has a foreign
key link to this entity
farkey: if type='list', the name of farside key in the listed
entity; if type='entity' and the farside field to join to
is not the farside primary key, then the name of that
farside field
required: whether this propery is required (i.e. 'not null').
size: fieldwidth of the property if specified.
concrete: if set to 'false', this property is not stored in the
database but must be computed (manually written code must
be provided to support this)
cascade: what action(s) on the parent entity should be cascaded to
entitie(s) linked on this property. Valid only if type='entity',
type='link' or type='list'.
column: name of the column in a SQL database table in which this property
is stored. If not present, use name. TODO: Think about this.
unsaved-value:
of a property whose persistent value is set on first being
committed to persistent store, the value which it holds before
it has been committed
-->
<xs:element name="property">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" ref="documentation" />
<xs:element minOccurs="0" maxOccurs="1" ref="generator" />
<xs:element minOccurs="0" maxOccurs="unbounded" ref="permission" />
<xs:element minOccurs="0" maxOccurs="unbounded" ref="option" />
<xs:element minOccurs="0" maxOccurs="unbounded" ref="prompt" />
<xs:element minOccurs="0" maxOccurs="unbounded" ref="help" />
<xs:element minOccurs="0" maxOccurs="unbounded" ref="ifmissing" />
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required" />
<xs:attribute name="type" use="required">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="entity" />
<xs:enumeration value="link" />
<xs:enumeration value="list" />
<xs:enumeration value="defined" />
<xs:enumeration value="string" />
<xs:enumeration value="integer" />
<xs:enumeration value="real" />
<xs:enumeration value="money" />
<xs:enumeration value="date" />
<xs:enumeration value="time" />
<xs:enumeration value="timestamp" />
<xs:enumeration value="boolean" />
<xs:enumeration value="text" />
<xs:enumeration value="geopos" />
<xs:enumeration value="image" />
<xs:enumeration value="message" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="default" type="xs:string" />
<xs:attribute name="typedef" type="xs:string" />
<xs:attribute name="distinct">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="none" />
<xs:enumeration value="all" />
<xs:enumeration value="user" />
<xs:enumeration value="system" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="entity" type="xs:string" />
<xs:attribute name="farkey" type="xs:string" />
<xs:attribute name="required">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="true" />
<xs:enumeration value="false" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="size" type="xs:string" />
<xs:attribute name="column" type="xs:string" />
<xs:attribute name="concrete">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="true" />
<xs:enumeration value="false" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="cascade">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="all" />
<xs:enumeration value="all-delete-orphan" />
<xs:enumeration value="delete" />
<xs:enumeration value="manual" />
<xs:enumeration value="save-update" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
<!--
marks a property which is auto-generated by some part of the system.
This is based on the Hibernate construct, except that the Hibernate
implementation folds both its internal generators and custom generators
onto the same attribute. This separates them onto two attributes so we
can police values for Hibernate's 'builtin' generators.
action: one of the supported Hibernate builtin generators, or
'manual'. 'native' is strongly recommended in most instances
class: if action is 'manual', the name of a manually maintained
class conforming to the Hibernate IdentifierGenerator
interface, or its equivalent in other languages
-->
<xs:element name="generator">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" ref="documentation" />
<xs:element minOccurs="0" maxOccurs="unbounded" ref="param" />
</xs:sequence>
<xs:attribute name="action" use="required">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="assigned" />
<xs:enumeration value="guid" />
<xs:enumeration value="manual" />
<xs:enumeration value="native" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="class" type="xs:string" />
</xs:complexType>
</xs:element>
<!--
A parameter passed to the generator. Again, based on the Hibernate
implementation. TODO: #PCDATA is wrong as the content model, as embedded
markup is definitely not allowed!
name: the name of this parameter
-->
<xs:element name="param">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="name" type="xs:string" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<!--
one of an explicit list of optional values a property may have
NOTE: whether options get encoded at application layer or at database layer
is UNDEFINED; either behaviour is correct. If at database layer it's also
UNDEFINED whether they're encoded as a single reference data table or as
separate reference data tables for each property.
value: the value of this option
-->
<xs:element name="option">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" ref="documentation" />
<xs:element minOccurs="0" maxOccurs="unbounded" ref="prompt" />
</xs:sequence>
<xs:attribute name="value" type="xs:string" />
</xs:complexType>
</xs:element>
<!--
permissions policy on an entity, a page, form, list or field
group: the group to which permission is granted
permission: the permission which is granted to that group
-->
<xs:element name="permission">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" ref="documentation" />
</xs:sequence>
<xs:attribute name="group" type="xs:string" use="required" />
<xs:attribute name="permission" use="required">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="none" />
<xs:enumeration value="read" />
<xs:enumeration value="insert" />
<xs:enumeration value="noedit" />
<xs:enumeration value="edit" />
<xs:enumeration value="all" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
<!--
pragmatic advice to generators of lists and forms, in the form of
name/value pairs which may contain anything. Over time some pragmas
will become 'well known', but the whole point of having a pragma
architecture is that it is extensible.
-->
<xs:element name="pragma">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" ref="documentation" />
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required" />
<xs:attribute name="value" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
<!--
a prompt for a property or field; used as the prompt text for a widget
which edits it. Typically there will be at most one of these per property
per locale; if there are more than one all those matching the locale may
be concatenated, or just one may be used.
prompt: the prompt to use
locale: the locale in which to prefer this prompt
-->
<xs:element name="prompt">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" ref="documentation" />
</xs:sequence>
<xs:attribute name="prompt" type="xs:string" use="required" />
<xs:attribute name="locale" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
<!--
helptext about a property of an entity, or a field of a page, form or
list, or a typedef. Typically there will be at most one of these per property
per locale; if there are more than one all those matching the locale may
be concatenated, or just one may be used.
locale: the locale in which to prefer this prompt
-->
<xs:element name="help">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="locale" type="xs:string" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<!--
helpful text to be shown if a property value is missing, typically when
a form is submitted. Typically there will be at most one of these per property
per locale; if there are more than one all those matching the locale may
be concatenated, or just one may be used. Later there may be more sophisticated
behaviour here.
-->
<xs:element name="ifmissing">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="locale" type="xs:string" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<!--
a form through which an entity may be added or edited
-->
<xs:element name="form">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" ref="documentation" />
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="head" />
<xs:element ref="top" />
<xs:element ref="foot" />
<xs:element ref="field" />
<xs:element ref="fieldgroup" />
<xs:element ref="auxlist" />
<xs:element ref="verb" />
<xs:element ref="permission" />
<xs:element ref="pragma" />
</xs:choice>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required" />
<xs:attribute name="properties" use="required">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="all" />
<xs:enumeration value="user-distinct" />
<xs:enumeration value="listed" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
<!-- a page on which an entity may be displayed (i.e. like a form, but read only -->
<xs:element name="page">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" ref="documentation" />
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="head" />
<xs:element ref="top" />
<xs:element ref="foot" />
<xs:element ref="field" />
<xs:element ref="fieldgroup" />
<xs:element ref="auxlist" />
<xs:element ref="verb" />
<xs:element ref="permission" />
<xs:element ref="pragma" />
</xs:choice>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required" />
<xs:attribute name="properties" use="required">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="all" />
<xs:enumeration value="user-distinct" />
<xs:enumeration value="listed" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
<!--
a list on which entities of a given type are listed
onselect: name of form/page/list to go to when
a selection is made from the list
-->
<xs:element name="list">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" ref="documentation" />
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="head" />
<xs:element ref="top" />
<xs:element ref="foot" />
<xs:element ref="field" />
<xs:element ref="fieldgroup" />
<xs:element ref="auxlist" />
<xs:element ref="verb" />
<xs:element ref="permission" />
<xs:element ref="pragma" />
</xs:choice>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required" />
<xs:attribute name="properties" use="required">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="all" />
<xs:enumeration value="user-distinct" />
<xs:enumeration value="listed" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="onselect" type="xs:string" />
</xs:complexType>
</xs:element>
<!--
a subsidiary list, on which entities related to primary
entities in the enclosing page or list are listed
property: the property of the enclosing entity that this
list displays (obviously, must be of type='list')
onselect: the form or page of the listed entity to call
when an item from the list is selected
canadd: true if the user should be able to add records
to this list
-->
<xs:element name="auxlist">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" ref="documentation" />
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="prompt" />
<xs:element ref="field" />
<xs:element ref="fieldgroup" />
<xs:element ref="auxlist" />
<xs:element ref="verb" />
</xs:choice>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required" />
<xs:attribute name="properties" use="required">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="all" />
<xs:enumeration value="user-distinct" />
<xs:enumeration value="listed" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="property" type="xs:string" use="required" />
<xs:attribute name="onselect" type="xs:string" />
<xs:attribute name="canadd">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="true" />
<xs:enumeration value="false" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
<!--
a group of fields and other controls within a form or list, which the
renderer might render as a single pane in a tabbed display, for example.
-->
<xs:element name="fieldgroup">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" ref="documentation" />
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="prompt" />
<xs:element ref="field" />
<xs:element ref="fieldgroup" />
<xs:element ref="auxlist" />
<xs:element ref="verb" />
</xs:choice>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
<!--
a field in a form or page
property: the property which this field displays/edits
-->
<xs:element name="field">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" ref="documentation" />
<xs:element minOccurs="0" maxOccurs="unbounded" ref="prompt" />
<xs:element minOccurs="0" maxOccurs="unbounded" ref="help" />
<xs:element minOccurs="0" maxOccurs="unbounded" ref="permission" />
</xs:sequence>
<xs:attribute name="property" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
<!--
a verb is something that may be done through a form. Probably the verbs 'store'
and 'delete' are implied, but maybe they need to be explicitly declared. The 'verb'
attribute of the verb is what gets returned to the controller
-->
<xs:element name="verb">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" ref="documentation" />
<xs:element minOccurs="0" maxOccurs="unbounded" ref="prompt" />
<xs:element minOccurs="0" maxOccurs="unbounded" ref="help" />
<xs:element minOccurs="0" maxOccurs="unbounded" ref="permission" />
</xs:sequence>
<xs:attribute name="verb" type="xs:string" use="required" />
<xs:attribute name="dangerous" use="required">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="true" />
<xs:enumeration value="false" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
<!-- a container for global content -->
<xs:element name="content">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="head" />
<xs:element ref="top" />
<xs:element ref="foot" />
</xs:choice>
</xs:complexType>
</xs:element>
<!--
content to place in the head of the generated document; this is #PCDATA
because it will almost certainly belong to a different namespace
(usually HTML).
NOTE: things which are legal in HTML HEAD only.
NOTE: it's questionable whether this should really be here at all.
-->
<xs:element name="head">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string" />
</xs:simpleContent>
</xs:complexType>
</xs:element>
<!--
content to place in the top of the body of the generated document;
this should be %Flow; which is any HTML block or inline level element.
-->
<xs:element name="top">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string" />
</xs:simpleContent>
</xs:complexType>
</xs:element>
<!--
content to place at the foot of the body of the generated document;
this should be %Flow; which is any HTML block or inline level element.
-->
<xs:element name="foot">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string" />
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:schema>

View file

@ -4,25 +4,25 @@
<!-- -->
<!-- Purpose: -->
<!-- Document Type Description for Application Description -->
<!-- Language. Normative for now; will be replaced by a schema. -->
<!-- Language. Normative for now; will be replaced by a schema. `-->
<!-- -->
<!-- Author: Simon Brooke <simon@cygnets.co.uk> -->
<!-- Created: 24th January 2006 -->
<!-- Copyright: (c) 2007 Cygnet Solutions Ltd -->
<!-- Copyright: (c) 2007 Cygnet Solutions -->
<!-- -->
<!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
<!--
$Revision: 1.14 $
$Revision: 1.15 $
-->
<!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
<!-- Before we start: import XHTML -->
<!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
<!ENTITY % XHTML PUBLIC
<!-- ENTITY % XHTML PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
%XHTML;
%XHTML; -->
<!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
<!-- Before we start: some useful definitions -->
@ -262,7 +262,7 @@ that we can allow HTML block level entities within content elements -->
should HTML markup within a documentation element be allowed? If so, are
there restrictions?
-->
<!ELEMENT documentation (%Flow;)>
<!ELEMENT documentation (#PCDATA)>
<!ATTLIST documentation
xmlns CDATA #IMPLIED>
@ -646,7 +646,7 @@ property[@type='entity']. TODO: Not complete, not yet strictly convinced it's th
content to place in the top of the body of the generated document;
this is %Flow; which is any HTML block or inline level element.
-->
<!ELEMENT top (%Flow;) >
<!ELEMENT top (#PCDATA) >
<!ATTLIST top
xmlns CDATA #IMPLIED>
@ -654,7 +654,7 @@ property[@type='entity']. TODO: Not complete, not yet strictly convinced it's th
content to place at the foot of the body of the generated document;
this is %Flow; which is any HTML block or inline level element.
-->
<!ELEMENT foot (%Flow;) >
<!ELEMENT foot (#PCDATA) >
<!ATTLIST foot
xmlns CDATA #IMPLIED>

View file

@ -4,7 +4,7 @@
xmlns:adl='http://www.cygnets.co.uk/schemas/adl-0.xsd'
xmlns:html='http://www.w3.org/1999/xhtml'>
<!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
<!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
<!-- -->
<!-- adl-0.xsd -->
<!-- -->
@ -14,12 +14,12 @@
<!-- This revision autoconverted using dtd2xsd.pl from -->
<!-- adl-0.dtd revision 1.2 -->
<!-- -->
<!-- Author: Simon Brooke <simon@cygnets.co.uk> -->
<!-- Author: Simon Brooke <sb@cygnets.co.uk> -->
<!-- Created: 9th January 2008 -->
<!-- $Revision: 1.2 $ -->
<!-- $Revision: 1.3 $ -->
<!-- Copyright: (c) 2008 Cygnet Solutions Ltd -->
<!-- -->
<!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
<!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
<!-- the application that the document describes: required top level element -->
<element name='application'>

View file

@ -1,132 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://cygnets.co.uk/schemas/adl-1.2"
xmlns:a="http://cygnets.co.uk/schemas/adl-1.2"
exclude-result-prefixes="a">
<!--
Application Description Framework
adl2adl.xsl
(c) 2008 Cygnet Solutions Ltd
Transform ADL to Verbose (or canonical) ADL
Most defaults are replaced with their actual values.
$Author: af $
$Revision: 1.1 $
-->
<xsl:import href="types.xslt"/>
<xsl:output indent="yes" method="xml" encoding="utf-8"/>
<xsl:template match="a:application">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:comment>
***************************************************************************
*
* ©2007 Cygnet Solutions Ltd
*
* THIS FILE IS AUTOMATICALLY GENERATED AND SHOULD NOT
* BE MANUALLY EDITED.
*
* Generated using adl2adl.xsl revision <xsl:value-of select="substring('$Revision: 1.1 $', 12)"/>
*
***************************************************************************
</xsl:comment>
<xsl:apply-templates select="a:type | a:typedef | a:entity | comment()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="a:entity">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:if test="not(a:key)">
<xsl:if test=".//a:property[@name='Id']">
<xsl:message terminate="yes">Class "<xsl:value-of select="@name"/>" has an 'Id' field, but no key. This is not allowed.</xsl:message>
</xsl:if>
<key>
<property name="Id" type="Integer-32" access="field.pascalcase-underscore">
<generator class="identity"/>
</property>
</key>
</xsl:if>
<xsl:apply-templates select="*"/>
</xsl:copy>
</xsl:template>
<!-- Expand any 'default' forms -->
<xsl:template match="a:form[not(@properties)]">
<form properties="listed">
<xsl:apply-templates select="@*" />
<xsl:for-each select="../a:key/a:property|../a:property">
<field>
<xsl:attribute name="property">
<xsl:value-of select="@name"/>
</xsl:attribute>
</field>
</xsl:for-each>
</form>
</xsl:template>
<!-- Expand any 'default' lists -->
<xsl:template match="a:list[not(@properties)]">
<list properties="listed">
<xsl:apply-templates select="@*" />
<pragma name="with-pagination-control" value="true"/>
<pragma name="with-can-add" value="true"/>
<xsl:for-each select="../a:key/a:property|../a:property">
<field>
<xsl:attribute name="property">
<xsl:value-of select="@name"/>
</xsl:attribute>
</field>
</xsl:for-each>
</list>
</xsl:template>
<xsl:template match="a:property">
<property>
<xsl:choose>
<xsl:when test="@type='entity' or @type='list' or @type='link'">
<xsl:attribute name="type"><xsl:value-of select="@type" /></xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="typename">
<xsl:call-template name="type-name" />
</xsl:variable>
<xsl:if test="$typename">
<xsl:attribute name="type">
<xsl:value-of select="$typename"/>
</xsl:attribute>
</xsl:if>
<!--xsl:call-template name="add-type-attr-if-avail">
<xsl:with-param name="attr" select="'name'" />
</xsl:call-template-->
</xsl:otherwise>
</xsl:choose>
<xsl:apply-templates select="@*[name()!='type']|*" />
</property>
</xsl:template>
<xsl:template name="add-type-attr-if-avail">
<xsl:param name="attr"/>
<xsl:variable name="val">
<xsl:call-template name="type-attr">
<xsl:with-param name="attr" select="$attr" />
</xsl:call-template>
</xsl:variable>
<xsl:if test="$val">
<xsl:attribute name="{$attr}">
<xsl:value-of select="$val"/>
</xsl:attribute>
</xsl:if>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

427
transforms/adl2canonical.xslt Executable file
View file

@ -0,0 +1,427 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
Application Description Language framework
adl2canonical.xsl
(c) 2007 Cygnet Solutions Ltd
Transform ADL into a canonical form, expanding and making explicit
things left implicit in the manually maintained form. Specifically,
in the canonicalised form
(i) every entity element has a key subelement. If it did not have one
in the supplied ADL, then a formal primary key is auto generated
(ii) every form, page or list has properties='listed'; where the supplied
ADL had properties='all' or properties='user-distinct' the correct fields
are generated.
(iii) TODO: all permissions are fully specified down to field level, by
inheriting where necessary. For every group specified in the ADL, for
every entity, form, page, list or field, the canonical form should
explicitly state the permission, even if it is 'none'.
$Author: sb $
$Revision: 1.1 $
$Date: 2008-05-29 16:39:39 $
-->
<xsl:stylesheet version="1.0"
xmlns="http://cygnets.co.uk/schemas/adl-1.2"
xmlns:adl="http://cygnets.co.uk/schemas/adl-1.2"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
exclude-result-prefixes="adl">
<xsl:output encoding="UTF-8" indent="yes" method="xml" />
<!--
The convention to use for naming auto-generated abstract primary keys. Known values are
Id - the autogenerated primary key, if any, is called just 'Id'
Name - the autogenerated primary key has the same name as the entity
NameId - the name of the auto generated primary key is the name of the entity followed by 'Id'
Name_Id - the name of the auto generated primary key is the name of the entity followed by '_Id'
-->
<xsl:param name="abstract-key-name-convention" select="Id"/>
<!-- the name and version of the product being built -->
<xsl:param name="product-version" select="'Application Description Language Framework'"/>
<!-- a prefix to prepend to all tablenames -->
<xsl:param name="tablename-prefix"/>
<xsl:template match="adl:application">
<xsl:copy>
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:if test="@version">
<xsl:attribute name="version">
<xsl:value-of select="@version"/>
</xsl:attribute>
</xsl:if>
<xsl:comment>
***************************************************************************
*
* <xsl:value-of select="$product-version"/>
* ©2007 Cygnet Solutions Ltd
*
* THIS FILE IS AUTOMATICALLY GENERATED AND SHOULD NOT
* BE MANUALLY EDITED.
*
* Generated using adl2canonical.xslt <xsl:value-of select="substring('$Revision: 1.1 $', 12)"/>
*
***************************************************************************
</xsl:comment>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<!-- an entity which already has a key tag - just copy it through -->
<xsl:template match="adl:entity[adl:key]">
<xsl:if test="not( @table)">
<xsl:attribute name="table">
<xsl:value-of select="concat( $tablename-prefix, @name)"/>
</xsl:attribute>
</xsl:if>
<xsl:comment>
entity <xsl:value-of select="@name"/> already has a key - not generating one
</xsl:comment>
<entity>
<xsl:apply-templates select="@* | node()"/>
</entity>
</xsl:template>
<!-- an entity which has a '@natural-key' attribute.
Since we've got the key tag, I think this should be disallowed -->
<xsl:template match="adl:entity[@natural-key]">
<xsl:if test="not( @table)">
<xsl:attribute name="table">
<xsl:value-of select="concat( $tablename-prefix, @name)"/>
</xsl:attribute>
</xsl:if>
<xsl:message terminate="no">
ADL WARNING: [In entity '<xsl:value-of select="@name"/>']: '@natural-key' is deprecated - use the 'key' sub element instead
</xsl:message>
<entity>
<xsl:variable name="nkey" select="@natural-key"/>
<xsl:apply-templates select="@*"/>
<!-- children copied through in legal order, to ensure the document remains valid -->
<xsl:apply-templates select="adl:documentation"/>
<xsl:apply-templates select="adl:content"/>
<key>
<xsl:apply-templates select="adl:property[@name=$nkey]"/>
<xsl:apply-templates select="adl:key/adl:property"/>
</key>
<xsl:apply-templates select="adl:property[not(@name=$nkey)] | adl:one-to-many | adl:many-to-many | adl:many-to-one"/>
<xsl:variable name="entity" select="."/>
<xsl:for-each select="//adl:group">
<xsl:call-template name="entity-group-permission">
<xsl:with-param name="entity" select="$entity"/>
<xsl:with-param name="group" select="."/>
<xsl:with-param name="descendantname" select="@name"/>
</xsl:call-template>
</xsl:for-each>
<xsl:apply-templates select="adl:form | adl:page | adl:list"/>
</entity>
</xsl:template>
<!-- an entity which has no explicit key: auto-generate one -->
<xsl:template match="adl:entity">
<xsl:comment>
entity <xsl:value-of select="@name"/> has no key - generating one
</xsl:comment>
<entity>
<!-- copy attributes through -->
<xsl:apply-templates select="@*"/>
<xsl:if test="not( @table)">
<xsl:attribute name="table">
<xsl:value-of select="concat( $tablename-prefix, @name)"/>
</xsl:attribute>
</xsl:if>
<!-- children copied through in legal order, to ensure the document remains valid -->
<xsl:apply-templates select="adl:documentation"/>
<xsl:apply-templates select="adl:content"/>
<key>
<!-- autogenerate a key element... -->
<!-- select a name... -->
<xsl:variable name="key">
<xsl:choose>
<xsl:when test="$abstract-key-name-convention='Name'">
<xsl:value-of select="@name"/>
</xsl:when>
<xsl:when test="$abstract-key-name-convention = 'NameId'">
<xsl:value-of select="concat( @name, 'Id')"/>
</xsl:when>
<xsl:when test="$abstract-key-name-convention = 'Name_Id'">
<xsl:value-of select="concat( @name, '_Id')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'Id'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!-- check that it is unique, and abort hard if not... -->
<xsl:if test="descendant::adl:property[@name=$key]">
<xsl:message terminate="yes">
ADL ERROR: Entity '<xsl:value-of select="@name"/>' has a property '<xsl:value-of select="$key"/>' which conflicts
with your chosen key naming convention <xsl:value-of select="$abstract-key-name-convention"/>. Either:
(i) Make property '<xsl:value-of select="$key"/>' an explicit key by putting it in the &lt;key&gt; tag;
(ii) Name property '<xsl:value-of select="$key"/>' something else; or
(iii) Choose a different key naming convention.
</xsl:message>
</xsl:if>
<!-- generate one property, the abstract primary key -->
<property type="integer" distinct="system">
<xsl:attribute name="name">
<xsl:value-of select="normalize-space( $key)"/>
</xsl:attribute>
<generator action="native"/>
<documentation>
Auto-generated abstract primary key
</documentation>
</property>
</key>
<xsl:apply-templates select="adl:property | adl:one-to-many | adl:many-to-many | adl:many-to-one"/>
<xsl:variable name="entity" select="."/>
<xsl:for-each select="//adl:group">
<xsl:call-template name="entity-group-permission">
<xsl:with-param name="entity" select="$entity"/>
<xsl:with-param name="group" select="."/>
<xsl:with-param name="descendantname" select="@name"/>
</xsl:call-template>
</xsl:for-each>
<xsl:apply-templates select="adl:form | adl:page | adl:list"/>
</entity>
</xsl:template>
<xsl:template match="@table">
<xsl:attribute name="table">
<xsl:value-of select="concat( $tablename-prefix, .)"/>
</xsl:attribute>
</xsl:template>
<!-- If properties='all', unroll them into a properties='listed' form.
We need to do this for lists, pages and forms; there's probably some clever
way of doing it all in a oner, but I don't know what that is -->
<xsl:template match="adl:form[ @properties='all']">
<form properties='listed'>
<!-- copy the name attribute through -->
<xsl:apply-templates select="@name"/>
<!-- children copied through in legal order, to ensure the document remains valid -->
<xsl:apply-templates select="adl:documentation"/>
<!-- unroll the properties -->
<xsl:call-template name="unroll-properties"/>
<xsl:apply-templates select="adl:head|adl:top|adl:foot|adl:field|
adl:fieldgroup|adl:auxlist|adl:verb|
adl:permission|adl:pragma"/>
</form>
</xsl:template>
<!-- If properties='all', unroll them into a properties='listed' form.
We need to do this for lists, pages and forms; there's probably some clever
way of doing it all in a oner, but I don't know what that is -->
<xsl:template match="adl:page[ @properties='all']">
<page properties='listed'>
<!-- copy the name attribute through -->
<xsl:apply-templates select="@name"/>
<!-- children copied through in legal order, to ensure the document remains valid -->
<xsl:apply-templates select="adl:documentation"/>
<!-- unroll the properties -->
<xsl:call-template name="unroll-properties"/>
<xsl:apply-templates select="adl:head|adl:top|adl:foot|adl:field|
adl:fieldgroup|adl:auxlist|adl:verb|
adl:permission|adl:pragma"/>
</page>
</xsl:template>
<!-- If properties='all', unroll them into a properties='listed' form.
We need to do this for lists, pages and forms; there's probably some clever
way of doing it all in a oner, but I don't know what that is -->
<xsl:template match="adl:list[ @properties='all']">
<list properties='listed'>
<!-- copy the name attribute through -->
<xsl:apply-templates select="@name"/>
<!-- children copied through in legal order, to ensure the document remains valid -->
<xsl:apply-templates select="adl:documentation"/>
<!-- unroll the properties -->
<xsl:call-template name="unroll-properties"/>
<xsl:apply-templates select="adl:head|adl:top|adl:foot|adl:field|
adl:fieldgroup|adl:auxlist|adl:verb|
adl:permission|adl:pragma"/>
</list>
</xsl:template>
<!-- In practice it's likely only to be lists which have properties='user-distinct',
but the grammar allows this for pages and forms as well so we'll deal with it -->
<xsl:template match="adl:form[ @properties='user-distinct']">
<form properties='listed'>
<!-- copy the name attribute through -->
<xsl:apply-templates select="@name"/>
<!-- children copied through in legal order, to ensure the document remains valid -->
<xsl:apply-templates select="adl:documentation"/>
<!-- unroll the properties -->
<xsl:call-template name="unroll-user-distinct"/>
<xsl:apply-templates select="adl:head|adl:top|adl:foot|adl:field|
adl:fieldgroup|adl:auxlist|adl:verb|
adl:permission|adl:pragma"/>
</form>
</xsl:template>
<!-- In practice it's likely only to be lists which have properties='user-distinct',
but the grammar allows this for pages and forms as well so we'll deal with it -->
<xsl:template match="adl:page[ @properties='user-distinct']">
<page properties='listed'>
<!-- copy the name attribute through -->
<xsl:apply-templates select="@name"/>
<!-- children copied through in legal order, to ensure the document remains valid -->
<xsl:apply-templates select="adl:documentation"/>
<!-- unroll the properties -->
<xsl:call-template name="unroll-user-distinct"/>
<xsl:apply-templates select="adl:head|adl:top|adl:foot|adl:field|
adl:fieldgroup|adl:auxlist|adl:verb|
adl:permission|adl:pragma"/>
</page>
</xsl:template>
<!-- In practice it's likely only to be lists which have properties='user-distinct',
but the grammar allows this for pages and forms as well so we'll deal with it -->
<xsl:template match="adl:list[ @properties='user-distinct']">
<list properties='listed'>
<!-- copy the name attribute through -->
<xsl:apply-templates select="@name"/>
<!-- children copied through in legal order, to ensure the document remains valid -->
<xsl:apply-templates select="adl:documentation"/>
<!-- unroll the properties -->
<xsl:call-template name="unroll-user-distinct"/>
<xsl:apply-templates select="adl:head|adl:top|adl:foot|adl:field|
adl:fieldgroup|adl:auxlist|adl:verb|
adl:permission|adl:pragma"/>
</list>
</xsl:template>
<xsl:template match="adl:typedef[ @type = 'string' and not( @size)]">
<xsl:message terminate="yes">
ADL ERROR: Type definitions of type 'string' must have a valid value for 'size'
Offending typedef: <xsl:value-of select="@name"/>
</xsl:message>
</xsl:template>
<!-- Language constraints -->
<xsl:template match="adl:property[ @type = 'string' and not( @size)]">
<xsl:message terminate="yes">
ADL ERROR: Properties of type 'string' must have a valid value for 'size'
Offending property: <xsl:value-of select="@name"/> of entity <xsl:value-of select="ancestor::adl:entity/@name"/>
</xsl:message>
</xsl:template>
<xsl:template match="adl:property[ @type = 'entity' and not( @entity)]">
<xsl:message terminate="yes">
ADL ERROR: Properties of type 'entity' must have a valid value for 'entity'
Offending property: <xsl:value-of select="@name"/> of entity <xsl:value-of select="ancestor::adl:entity/@name"/>
</xsl:message>
</xsl:template>
<xsl:template match="adl:property[ @type = 'defined' and not( @typedef)]">
<xsl:message terminate="yes">
ADL ERROR: Properties of type 'defined' must have a valid value for 'typedef'
Offending property: <xsl:value-of select="@name"/> of entity <xsl:value-of select="ancestor::adl:entity/@name"/>
</xsl:message>
</xsl:template>
<!-- copy anything that isn't explicitly matched -->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<!-- generate a permission element for this group and this entity -->
<xsl:template name="entity-group-permission">
<xsl:param name="entity"/>
<xsl:param name="group"/>
<xsl:param name="descendantname"/>
<xsl:choose>
<xsl:when test="$entity/adl:permission[@group=$group/@name]">
<!-- there's an explicit permission for this group -->
<permission>
<xsl:attribute name="group">
<xsl:value-of select="$descendantname"/>
</xsl:attribute>
<xsl:attribute name="permission">
<xsl:value-of select="$entity/adl:permission[@group=$group/@name]/@permission"/>
</xsl:attribute>
</permission>
</xsl:when>
<xsl:when test="$group/@parent">
<xsl:choose>
<xsl:when test="$group/@parent = $group/@name">
<xsl:message terminate="yes">
ADL: ERROR: A group may not be its own parent; offending group <xsl:value-of select="$group/@name"/>
</xsl:message>
</xsl:when>
<xsl:when test="//adl:group[@name=$group/@parent]">
<xsl:call-template name="entity-group-permission">
<xsl:with-param name="entity" select="$entity"/>
<xsl:with-param name="group" select="//adl:group[@name=$group/@parent]"/>
<xsl:with-param name="descendantname" select="$descendantname"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:message terminate="yes">
ADL: ERROR: Group specified (<xsl:value-of select="$group/@parent"/> does not exist.
</xsl:message>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<permission permission="none">
<xsl:attribute name="group">
<xsl:value-of select="$descendantname"/>
</xsl:attribute>
</permission>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- unroll all the explicit properties in the ancestor entity of
the context (assumed to be form, page or list) into a list of fields -->
<xsl:template name="unroll-properties">
<xsl:for-each select="ancestor::adl:entity/descendant::adl:property |
ancestor::adl:entity/descendant::adl:one-to-many |
ancestor::adl:entity/descendant::adl:many-to-many |
ancestor::adl:entity/descendant::adl:many-to-one">
<field>
<xsl:attribute name="property">
<xsl:value-of select="@name"/>
</xsl:attribute>
</field>
</xsl:for-each>
</xsl:template>
<!-- unroll all the user-distinct properties in the ancestor entity of
the context (assumed to be form, page or list) into a list of fields.
NOTE that n-to-n properties cannot currently be user-distinct and are
therefore not inspected -->
<xsl:template name="unroll-user-distinct">
<xsl:for-each select="ancestor::adl:entity/descendant::adl:property[@distinct='user' or @distinct='all']">
<field>
<xsl:attribute name="property">
<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:apply-templates select="adl:prompt"/>
<xsl:apply-templates select="adl:help"/>
</field>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
C1873 SRU Hospitality
Application Description Language framework
adl2entityclass.xsl
(c) 2007 Cygnet Solutions Ltd
@ -8,8 +8,8 @@
Transform ADL into entity classes
$Author: sb $
$Revision: 1.4 $
$Date: 2008-02-29 16:28:51 $
$Revision: 1.5 $
$Date: 2008-05-29 16:39:38 $
-->
<!-- WARNING WARNING WARNING: Do NOT reformat this file!
@ -17,10 +17,10 @@
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
xmlns:a="http://cygnets.co.uk/schemas/adl-1.2"
xmlns:adl="http://cygnets.co.uk/schemas/adl-1.2"
xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<xsl:import href="types.xslt"/>
<xsl:include href="csharp-type-include.xslt"/>
<xsl:output encoding="UTF-8" method="text"/>
@ -30,41 +30,38 @@
client's locale. However, there may still need to be a concept of a
'default locale', for when we don't have messages which suit the
client's locale -->
<xsl:param name="lang" select="en-UK"/>
<xsl:param name="locale" select="en-UK"/>
<!-- The C# namespace within which I shall generate controllers -->
<xsl:param name="controllerns" select="Unset"/>
<!-- The C# namespace within which I shall generate entities -->
<xsl:param name="entityns" select="Unset"/>
<xsl:template match="a:application">
<xsl:apply-templates select="a:entity"/>
<!-- the name and version of the product being built -->
<xsl:param name="product-version" select="'Application Description Language Framework'"/>
<xsl:template match="adl:application">
<xsl:apply-templates select="adl:entity"/>
</xsl:template>
<xsl:template match="a:entity">
<!-- what's all this about? the objective is to get the revision number of the
transform into the output, /without/ getting that revision number overwritten
with the revision number of the generated file if the generated file is
stored to CVS -->
<!-- Don't bother generating anything for foreign entities -->
<xsl:template match="adl:entity[@foreign='true']"/>
<xsl:variable name="transform-rev1"
select="substring( '$Revision: 1.4 $', 11)"/>
<xsl:variable name="transform-revision"
select="substring( $transform-rev1, 0, string-length( $transform-rev1) - 1)"/>
<xsl:template match="adl:entity">
<xsl:variable name="keynames" select="a:key/a:property" />
/* ---- [ cut here: next file '<xsl:value-of select="@name"/>.auto.cs'] ---------------- */
/* ---- [ cut here: next file '<xsl:value-of select="@name"/>.auto.cs'] ---------------- */
//-------------------------------------------------------------
//
// Application Description Framework
// <xsl:value-of select="$product-version"/>
// <xsl:value-of select="@name"/>.auto.cs
//
// (c)2007 Cygnet Solutions Ltd
//
// Automatically generated from application description using
// adl2entityclass.xsl version <xsl:value-of select="$transform-revision"/>
// adl2entityclass.xsl revision <xsl:value-of select="substring( '$Revision: 1.5 $', 10)"/>
//
// This file is automatically generated; DO NOT EDIT IT.
//
@ -72,20 +69,26 @@
namespace <xsl:value-of select="$entityns"/>
{
using System;
using System.Configuration;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using Cygnet.Entities;
using Cygnet.Exceptions;
using Cygnet.Entities;
using Iesi.Collections.Generic;
/// &lt;summary&gt;
/// <xsl:value-of select="normalize-space( adl:documentation)"/>
/// &lt;/summary&gt;
/// &lt;remarks&gt;
/// Automatically generated from description of entity <xsl:value-of select="@name"/>
/// using adl2entityclass.xsl. Note that manually maintained parts of this
/// class may be defined in a separate file called <xsl:value-of select="@name"/>.cs, q.v.
/// using adl2entityclass.xsl revision <xsl:value-of select="substring( '$Revision: 1.5 $', 10)"/>.
/// Note that manually maintained parts of this class may be defined in
/// a separate file called <xsl:value-of select="@name"/>.manual.cs, q.v.
///
/// DO NOT EDIT THIS FILE!
/// &lt;/summary&gt;
/// &lt;/remarks&gt;
public partial class <xsl:value-of select="@name"/> : Entity
{
/// &lt;summary&gt;
@ -96,49 +99,105 @@
<xsl:call-template name="initialise-lists"/>
}
<xsl:choose>
<xsl:when test="@natural-key">
/* natural primary key exists - not generating abstract key */
</xsl:when>
<xsl:when test="adl:key">
/* primary key exists - not generating abstract key */
/// &lt;summary&gt;
/// Auto-generated constructor; initialises each of the slots within
/// the primary key and also all one-to-many and many-to-many slots
/// &lt;/summary&gt;
public <xsl:value-of select="@name"/>( <xsl:for-each select="adl:key/adl:property">
<xsl:variable name="csharp-type">
<xsl:call-template name="csharp-type">
<xsl:with-param name="property" select="."/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="concat( $csharp-type, ' ', @name)"/>
<xsl:if test="not( position() = last())">, </xsl:if>
</xsl:for-each>){
<xsl:call-template name="initialise-lists"/>
<xsl:call-template name="initialise-messages"/>
<xsl:for-each select="adl:key/adl:property">
this.<xsl:value-of select="@name"/> = <xsl:value-of select="@name"/>;
</xsl:for-each>
}
</xsl:when>
<xsl:otherwise>
<xsl:message terminate="yes">
ADL: ERROR: Entity '<xsl:value-of select="@name"/>' has no key. Was the
canonicalise stage missed in the build process?
</xsl:message>
</xsl:otherwise>
</xsl:choose>
/// &lt;summary&gt;
/// Auto-generated overridden property for the Key slot, maps onto
/// &lt;/summary&gt;
public override string KeyString {
get {
<xsl:choose>
<xsl:when test="count($keynames)=0">
return null; // No primary key; return null.
</xsl:when>
<xsl:when test="count($keynames)=1">
return <xsl:value-of select="$keynames[1]/@name"/>.ToString(); // Single key.
</xsl:when>
<xsl:otherwise>
StringBuilder result = new StringBuilder();
<xsl:for-each select="$keynames">
<xsl:for-each select="adl:key/adl:property">
result.Append(<xsl:value-of select="@name"/><xsl:if test="@type='entity'">.KeyString</xsl:if>);
<xsl:if test="position()!=last()">
result.Append('|');
</xsl:if>
</xsl:for-each>
return result.ToString();
</xsl:otherwise>
</xsl:choose>
}
}
/// &lt;summary&gt;
/// A user readable distinct identifying string
/// &lt;/summary&gt;
public override string UserIdentifier {
public override string UserIdentifier
{
get {
StringBuilder result = new StringBuilder();
<xsl:choose>
<xsl:when test="a:key/a:property">
<xsl:for-each select="a:key/a:property">
result.Append(<xsl:value-of select="@name"/><xsl:if test="@type='entity'">.UserIdentifier</xsl:if>);
<xsl:if test="position() != last()">
<xsl:when test="descendant::adl:property[@distinct='user' or @distinct='all']">
<xsl:for-each select="descendant::adl:property[@distinct='user' or @distinct='all']">
<xsl:choose>
<xsl:when test="@type='message'">
if ( <xsl:value-of select="@name"/> != null)
result.Append( <xsl:value-of select="concat( @name, '.LocalText')"/>);
</xsl:when>
<xsl:when test="@type='entity'">
<!-- TODO: this is dangerous and could potentially give rise to
infinite loops; find a way of stopping it running away! -->
if ( <xsl:value-of select="@name"/> != null)
result.Append( <xsl:value-of select="concat( @name, '.UserIdentifier')"/>);
</xsl:when>
<xsl:when test="@type='date'">
<!-- if what we've got is just a date, we only want to see the date part of it -->
if ( <xsl:value-of select="@name"/> != null)
result.Append(<xsl:value-of select="@name"/>.ToString( "d"));
</xsl:when>
<xsl:when test="@type='time'">
<!-- if what we've got is just a time, we only want to see the time part of it -->
if ( <xsl:value-of select="@name"/> != null)
result.Append(<xsl:value-of select="@name"/>.ToString( "t"));
</xsl:when>
<xsl:otherwise>
if ( <xsl:value-of select="@name"/> != null)
result.Append(<xsl:value-of select="@name"/>);
</xsl:otherwise>
</xsl:choose>
<xsl:choose>
<xsl:when test="position() = last()"/>
<xsl:otherwise>
result.Append( ", ");
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
result.AppendFormat( "<xsl:value-of select="@name"/>#{0}", <xsl:call-template name="list-properties"/>);
result.AppendFormat( "<xsl:value-of select="@name"/>#{0}", KeyString);
</xsl:otherwise>
</xsl:choose>
@ -146,66 +205,87 @@
}
}
<xsl:apply-templates select="a:key/a:property|a:property|a:set|a:one-to-one"/>
}
}
/// &lt;summary&gt;
/// If I should not be deleted, return a message explaining why I should not be deleted; else null.
/// &lt;/summary&gt;
/// &lt;returns&gt;a message explaining why I should not be deleted; else null&lt;/returns&gt;
public override string NoDeleteReason {
get {
string result = null;
<xsl:if test="adl:property[@type='list']|adl:property[@type='link']">
StringBuilder bob = new StringBuilder();
<!-- TODO: we ought to start worrying about internationalisation NOW, not later! -->
</xsl:template>
<!-- Creates a comma-separated list of all the properties passed in, or all the key properties by default. -->
<xsl:template name="list-properties">
<xsl:param name="props" select="a:key/a:property"/>
<xsl:if test="count($props)!=0">
<xsl:value-of select="$props[1]/@name"/>
<xsl:if test="count($props)!=1">, </xsl:if>
<xsl:call-template name="list-properties">
<xsl:with-param name="props" select="$props[position()!=1]"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template match="a:property[@concrete='false']">
<!-- generate nothing for non-concrete properties -->
</xsl:template>
<xsl:template match="a:property">
// auto generating iv/property pair for slot with name <xsl:value-of select="@name"/>
<xsl:apply-templates select="a:help"/>
<xsl:variable name="type-nullable">
<xsl:for-each select="adl:property[@type='list']|adl:property[@type='link']">
<xsl:choose>
<xsl:when test="@type='link' or @type='list' or @type='entity'">true</xsl:when>
<xsl:when test="@cascade='manual'"/>
<xsl:when test="@cascade='all'"/>
<xsl:when test="@cascade='all-delete-orphan'"/>
<xsl:when test="@cascade='delete'"/>
<xsl:when test="@concrete='false'"/>
<xsl:otherwise>
<xsl:call-template name="type-nullable">
</xsl:call-template>
if ( <xsl:value-of select="concat( ' _', @name)"/> != null &amp;&amp; <xsl:value-of select="concat( ' _', @name)"/>.Count > 0) {
bob.AppendFormat("Cannot delete this <xsl:value-of select="../@name"/> as it has {0} dependent <xsl:value-of select="@name"/>; ", <xsl:value-of select="concat( ' _', @name)"/>.Count);
}
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
</xsl:for-each>
if (bob.Length > 0) {
result = bob.ToString();
}
</xsl:if>
return result;
}
}
<!-- 'descendant' to catch properties inside keys as well as properties which are direct children -->
<xsl:apply-templates select="descendant::adl:property"/>
}
}
/* ---- [ cut here: next file 'junk'] ------------------------- */
<xsl:variable name="type">
<xsl:choose>
<xsl:when test="@type = 'link'">
ICollection&lt;<xsl:value-of select="@entity"/>&gt;
</xsl:when>
<xsl:when test="@type = 'list'">
ICollection&lt;<xsl:value-of select="@entity"/>&gt;
</xsl:when>
<xsl:when test="@type = 'entity'">
<xsl:value-of select="@entity"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="type-declarator">
<xsl:with-param name="nullable" select="@not-null!='true'"/>
</xsl:template>
<xsl:template match="adl:property[@concrete='false']">
<!-- generate nothing for non-concrete properties -->
/* NOTE: property '<xsl:value-of select="@name"/>' is marked as being abstract; it must
* be supported by manually maintained code */
</xsl:template>
<xsl:template match="adl:property">
// auto generating iv/property pair for slot with name <xsl:value-of select="@name"/>
<xsl:apply-templates select="help"/>
<xsl:variable name="base-type">
<xsl:call-template name="base-type">
<xsl:with-param name="property" select="."/>
</xsl:call-template>
</xsl:otherwise>
</xsl:variable>
<xsl:variable name="csharp-type">
<xsl:call-template name="csharp-type">
<xsl:with-param name="property" select="."/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="nullable-decoration">
<xsl:choose>
<xsl:when test="@required='true'"/>
<!-- when required is 'true' null is not permitted anyway; otherwise... -->
<xsl:when test="@type='message'"/>
<xsl:when test="$base-type='entity'"/>
<xsl:when test="$base-type='string'"/>
<xsl:when test="$base-type='text'"/>
<!-- entities and strings are always nullable, don't need decoration -->
<xsl:when test="$base-type='list'"/>
<xsl:when test="$base-type='link'"/>
<!-- things which are collections are not nullable -->
<xsl:otherwise>?</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="initialiser">
<xsl:choose>
<xsl:when test="@default">
<xsl:choose>
<xsl:when test="$type = 'String'">
<xsl:when test="$csharp-type = 'String'">
= "<xsl:value-of select="@default"/>"
</xsl:when>
<xsl:otherwise>
@ -213,31 +293,57 @@
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:when test="normalize-space( $nullable-decoration) = '?'"> = null</xsl:when>
<xsl:when test="$base-type = 'Boolean'"> = false</xsl:when>
<xsl:when test="$base-type = 'int'"> = 0</xsl:when>
<xsl:when test="$csharp-type = 'Decimal'"> = 0.0M</xsl:when>
<xsl:when test="$base-type = 'real'"> = 0.0</xsl:when>
<xsl:when test="$base-type='String'"> = null</xsl:when>
</xsl:choose>
</xsl:variable>
<xsl:variable name="validationpattern">
<xsl:if test="not(@type='link' or @type='list' or @type='entity')">
<xsl:call-template name="type-attr">
<xsl:with-param name="attr" select="'pattern'" />
</xsl:call-template>
</xsl:if>
<xsl:choose>
<xsl:when test="@type='defined'">
<xsl:variable name="definition">
<xsl:value-of select="@typedef"/>
</xsl:variable>
<xsl:value-of select="//adl:typedef[@name=$definition]/@pattern"/>
</xsl:when>
</xsl:choose>
</xsl:variable>
<xsl:if test="string-length( $validationpattern) &gt; 0">
private Regex <xsl:value-of select="@name"/>Validator = new Regex( "<xsl:value-of select="$validationpattern"/>");
</xsl:if>
private <xsl:value-of select="$type"/> <xsl:value-of select="concat( '_', @name)"/> <xsl:value-of select="$initialiser"/>;
private <xsl:value-of select="normalize-space( $csharp-type)"/><xsl:value-of select="normalize-space( $nullable-decoration)"/> <xsl:value-of select="concat( ' _', @name)"/> <xsl:value-of select="normalize-space( $initialiser)"/>;
public virtual <xsl:value-of select="$type"/><xsl:text> </xsl:text> <xsl:value-of select="@name"/>
/// &lt;summary&gt;
/// <xsl:choose>
<xsl:when test="adl:documentation">
<xsl:value-of select="normalize-space( adl:documentation)"/>
</xsl:when>
<xsl:otherwise>Auto generated property for field <xsl:value-of select="@name"/></xsl:otherwise>
</xsl:choose><xsl:if test="help[@locale=$locale]">:
/// <xsl:value-of select="normalize-space( help[@locale=$locale])"/></xsl:if>
/// &lt;/summary&gt;
public virtual <xsl:value-of select="normalize-space( $csharp-type)"/><xsl:value-of select="normalize-space( $nullable-decoration)"/><xsl:text> </xsl:text> <xsl:value-of select="@name"/>
{
get { return <xsl:value-of select="concat( '_', @name)"/>; }
get {
<xsl:if test="$base-type='list'">
if ( <xsl:value-of select="concat( ' _', @name)"/> == null) {
<xsl:value-of select="concat( '_', @name)"/> = new HashedSet&lt;<xsl:value-of select="@entity"/>&gt;();
}
</xsl:if>
return <xsl:value-of select="concat( ' _', @name)"/>;
}
set {
<xsl:if test="@not-null='true' and $type-nullable='true'">
<xsl:if test="@required='true'">
if ( value == null)
{
throw new DataRequiredException( <xsl:choose>
<xsl:when test="ifmissing[@locale=$lang]">
<xsl:when test="ifmissing[@locale=$locale]">
<xsl:apply-templates select="ifmissing"/>
</xsl:when>
<xsl:otherwise>
@ -247,16 +353,15 @@
);
}
</xsl:if>
<xsl:if test="not(@type='link' or @type='list' or @type='entity')">
<xsl:if test="@type='defined'">
<xsl:variable name="definition">
<xsl:value-of select="@typedef"/>
</xsl:variable>
<xsl:variable name="maximum">
<xsl:call-template name="type-attr">
<xsl:with-param name="attr" select="'maximum'" />
</xsl:call-template>
<xsl:value-of select="//adl:typedef[@name=$definition]/@maximum"/>
</xsl:variable>
<xsl:variable name="minimum">
<xsl:call-template name="type-attr">
<xsl:with-param name="attr" select="'minimum'" />
</xsl:call-template>
<xsl:value-of select="//adl:typedef[@name=$definition]/@minimum"/>
</xsl:variable>
<xsl:if test="string-length( $maximum) &gt; 0">
if ( value &gt; <xsl:value-of select="$maximum"/>)
@ -277,84 +382,43 @@
}
</xsl:if>
</xsl:if>
<xsl:if test="@size and $type='String'">
<xsl:if test="@size and $csharp-type='String'">
if ( value != null &amp;&amp; value.Length > <xsl:value-of select="@size"/>)
{
value = value.Substring( 0, <xsl:value-of select="@size"/>);
}
</xsl:if>
<xsl:value-of select="concat( '_', @name)"/> = value;
<xsl:value-of select="concat( ' _', @name)"/> = value;
}
}
</xsl:template>
<xsl:template match="a:one-to-one">
// auto generating for one-to-one with name <xsl:value-of select="@name"/>
private <xsl:value-of select="@class"/><xsl:text> </xsl:text>_<xsl:value-of select="@name"/>;
public virtual <xsl:value-of select="@class"/><xsl:text> </xsl:text><xsl:value-of select="@name"/>
{
get { return _<xsl:value-of select="@name"/>; }
set { _<xsl:value-of select="@name"/> = value; }
}
</xsl:template>
<xsl:template match="a:set[a:many-to-many]">
// auto generating for set with name <xsl:value-of select="@name"/>, having many-to-many child
private ICollection&lt;<xsl:value-of
select="a:many-to-many/@entity"/>&gt;<xsl:text> </xsl:text><xsl:value-of select="concat( '_', @name)"/>;
public virtual ICollection&lt;<xsl:value-of select="a:many-to-many/@entity"/>&gt; <xsl:value-of select="@name"/>
{
get { return <xsl:value-of select="concat( '_', @name)"/>; }
set { <xsl:value-of select="concat( '_', @name)"/> = value; }
}
</xsl:template>
<xsl:template match="a:set[a:one-to-many]">
// auto generating for set with name <xsl:value-of select="@name"/>, having one-to-many child
private ICollection&lt;<xsl:value-of
select="a:one-to-many/@entity"/>&gt;<xsl:text> </xsl:text><xsl:value-of select="concat( '_', @name)"/>;
public virtual ICollection&lt;<xsl:value-of select="a:one-to-many/@entity"/>&gt; <xsl:value-of select="@name"/>
{
get { return <xsl:value-of select="concat( '_', @name)"/>; }
set { <xsl:value-of select="concat( '_', @name)"/> = value; }
}
</xsl:template>
<xsl:template name="type-declarator">
<xsl:param name="nullable" select="false()"/>
<xsl:call-template name="type-attr">
<xsl:with-param name="attr" select="'dotnet'"/>
</xsl:call-template>
<xsl:variable name="kind">
<xsl:call-template name="type-attr">
<xsl:with-param name="attr" select="'dotnet-kind'"/>
<xsl:if test="parent::adl:key and @type='entity'">
/* generate primitive value getter/setter for key property of type entity (experimental) */
<xsl:variable name="csharp-base-type">
<xsl:call-template name="csharp-base-type">
<xsl:with-param name="property" select="."/>
</xsl:call-template>
</xsl:variable>
<xsl:if test="$nullable and $kind='value'">?</xsl:if>
private <xsl:value-of select="concat( $csharp-base-type, ' _', @name, '_Value')"/> <xsl:choose>
<xsl:when test="$csharp-base-type = 'Boolean'"> = false</xsl:when>
<xsl:when test="$csharp-base-type = 'int'"> = 0</xsl:when>
<xsl:when test="$csharp-base-type = 'Decimal'"> = 0.0M</xsl:when>
<xsl:when test="$csharp-base-type = 'real'"> = 0.0</xsl:when>
<xsl:when test="$csharp-base-type='String'"> = null</xsl:when>
<xsl:otherwise>[unknown? <xsl:value-of select="$csharp-base-type"/>]
</xsl:otherwise>
</xsl:choose>;
public virtual <xsl:value-of select="concat( $csharp-base-type, ' ', @name, '_Value')"/> {
get { return <xsl:value-of select="concat( '_', @name, '_Value')"/>; }
set { <xsl:value-of select="concat( '_', @name, '_Value')"/> = value; }
}
</xsl:if>
</xsl:template>
<xsl:template name="type-nullable">
<xsl:variable name="kind">
<xsl:call-template name="type-attr">
<xsl:with-param name="attr" select="'dotnet-kind'"/>
</xsl:call-template>
</xsl:variable>
<xsl:if test="$kind!='value'">true</xsl:if>
</xsl:template>
<xsl:template match="help">
<xsl:if test="@lang=$lang">
<xsl:template match="adl:help">
<xsl:if test="@locale=$locale">
<!-- might conceivably be more than one line -->
<xsl:text>
/* </xsl:text><xsl:apply-templates/> */
@ -362,26 +426,30 @@
</xsl:template>
<xsl:template match="ifmissing">
<xsl:if test="@lang=$lang">
<xsl:if test="@locale=$locale">
"<xsl:value-of select="normalize-space(.)"/>"
</xsl:if>
</xsl:template>
<xsl:template name="initialise-lists">
<!-- initialise all cocrete lists and links -->
<xsl:for-each select="property[@type='list']">
<xsl:template name="initialise-messages">
<!-- each IV of type message needs to be initialised -->
<xsl:for-each select="adl:property[@type='message']">
<xsl:choose>
<xsl:when test="@concrete='false'"/>
<xsl:otherwise>
<xsl:value-of select="concat( '_', @name)"/> = new HashedSet&lt;<xsl:value-of select="@entity"/>&gt;();
<xsl:value-of select="concat( ' _', @name)"/> = new Message();
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<xsl:for-each select="property[@type='link']">
</xsl:template>
<xsl:template name="initialise-lists">
<!-- initialise all concrete lists and links -->
<xsl:for-each select="adl:property[@type='list' or @type='link']">
<xsl:choose>
<xsl:when test="@concrete='false'"/>
<xsl:otherwise>
<xsl:value-of select="concat( '_', @name)"/> = new HashedSet&lt;<xsl:value-of select="@entity"/>&gt;();
<xsl:value-of select="concat( ' _', @name)"/> = new HashedSet&lt;<xsl:value-of select="@entity"/>&gt;();
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>

View file

@ -1,216 +1,591 @@
<?xml version="1.0" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="urn:nhibernate-mapping-2.2"
xmlns:a="http://cygnets.co.uk/schemas/adl-1.2"
exclude-result-prefixes="a">
xmlns:adl="http://cygnets.co.uk/schemas/adl-1.2"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!--
Application Description Framework
adl2hibernate.xsl
(c) 2007 Cygnet Solutions Ltd
Transform ADL to Verbose (or canonical) ADL
Most defaults are replaced with their actual values.
Transform ADL to Hibernate
$Author: af $
$Revision: 1.2 $
$Author: sb $
$Revision: 1.3 $
-->
<xsl:output indent="no" method="xml" encoding="utf-8"/>
<xsl:param name="namespace"/>
<xsl:param name="assembly"/>
<xsl:param name="database"/>
<!-- the name and version of the product being built -->
<xsl:param name="product-version" select="'Application Description Language Framework'"/>
<xsl:template match="a:application">
<xsl:output indent="no" method="xml" encoding="UTF-8"/>
<!-- NOTE! indent="no" because hibernate falls over if there is whitespace inside
a 'key' or 'one-to-many' element, and the printer used by the NAnt 'style' task
does not tag-minimize on output. If you change this the build will break, you
have been warned! -->
<xsl:include href="csharp-type-include.xslt"/>
<xsl:variable name="dbprefix">
<xsl:choose>
<xsl:when test="string-length( $database) > 0">
<xsl:value-of select="concat( $database, '.dbo.')"/>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:variable>
<!-- define upper and lower case letters to enable case conversion -->
<xsl:variable name="ucase">ABCDEFGHIJKLMNOPQRSTUVWXYZ</xsl:variable>
<xsl:variable name="lcase">abcdefghijklmnopqrstuvwxyz</xsl:variable>
<!-- define SQL keywords to police these out of field names -->
<xsl:variable name="sqlkeywords-multiline">
ADD EXCEPT PERCENT
ALL EXEC PLAN
ALTER EXECUTE PRECISION
AND EXISTS PRIMARY
ANY EXIT PRINT
AS FETCH PROC
ASC FILE PROCEDURE
AUTHORIZATION FILLFACTOR PUBLIC
BACKUP FOR RAISERROR
BEGIN FOREIGN READ
BETWEEN FREETEXT READTEXT
BREAK FREETEXTTABLE RECONFIGURE
BROWSE FROM REFERENCES
BULK FULL REPLICATION
BY FUNCTION RESTORE
CASCADE GOTO RESTRICT
CASE GRANT RETURN
CHECK GROUP REVOKE
CHECKPOINT HAVING RIGHT
CLOSE HOLDLOCK ROLLBACK
CLUSTERED IDENTITY ROWCOUNT
COALESCE IDENTITY_INSERT ROWGUIDCOL
COLLATE IDENTITYCOL RULE
COLUMN IF SAVE
COMMIT IN SCHEMA
COMPUTE INDEX SELECT
CONSTRAINT INNER SESSION_USER
CONTAINS INSERT SET
CONTAINSTABLE INTERSECT SETUSER
CONTINUE INTO SHUTDOWN
CONVERT IS SOME
CREATE JOIN STATISTICS
CROSS KEY SYSTEM_USER
CURRENT KILL TABLE
CURRENT_DATE LEFT TEXTSIZE
CURRENT_TIME LIKE THEN
CURRENT_TIMESTAMP LINENO TO
CURRENT_USER LOAD TOP
CURSOR NATIONAL TRAN
DATABASE NOCHECK TRANSACTION
DBCC NONCLUSTERED TRIGGER
DEALLOCATE NOT TRUNCATE
DECLARE NULL TSEQUAL
DEFAULT NULLIF UNION
DELETE OF UNIQUE
DENY OFF UPDATE
DESC OFFSETS UPDATETEXT
DISK ON USE
DISTINCT OPEN USER
DISTRIBUTED OPENDATASOURCE VALUES
DOUBLE OPENQUERY VARYING
DROP OPENROWSET VIEW
DUMMY OPENXML WAITFOR
DUMP OPTION WHEN
ELSE OR WHERE
END ORDER WHILE
ERRLVL OUTER WITH
ESCAPE OVER WRITETEXT
</xsl:variable>
<xsl:variable name="sqlkeywords" select="concat(' ', normalize-space($sqlkeywords-multiline), ' ')"/>
<xsl:template match="adl:application">
<hibernate-mapping>
<xsl:apply-templates select="@namespace|@assembly|@schema" />
<xsl:attribute name="namespace">
<xsl:value-of select="$namespace"/>
</xsl:attribute>
<xsl:attribute name="assembly">
<xsl:value-of select="$assembly"/>
</xsl:attribute>
<xsl:comment>
***************************************************************************
*
* <xsl:value-of select="$product-version"/>
* <xsl:value-of select="@name"/>.auto.hbm.xml
*
* ©2007 Cygnet Solutions Ltd
*
* THIS FILE IS AUTOMATICALLY GENERATED AND SHOULD NOT
* BE MANUALLY EDITED.
*
* Generated using adl2hibernate-mapping.xsl revision <xsl:value-of select="substring('$Revision: 1.2 $', 12)"/>
* Generated using adl2hibernate.xslt revision <xsl:value-of select="substring('$Revision: 1.3 $', 12)"/>
*
***************************************************************************
</xsl:comment>
<xsl:apply-templates select="a:entity|comment()"/>
<xsl:apply-templates select="adl:entity"/>
</hibernate-mapping>
</xsl:template>
<xsl:template match="a:entity">
<xsl:template match="adl:entity[@foreign='true']"/>
<xsl:template match="adl:entity">
<xsl:apply-templates select="adl:documentation"/>
<xsl:variable name="prefix">
<xsl:choose>
<xsl:when test="string-length( $database) &gt; 0">
<xsl:value-of select="concat( $database, '.dbo.')"/>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:variable>
<class>
<xsl:apply-templates select="@name|@table" />
<xsl:apply-templates select="a:key" />
<xsl:apply-templates select="a:property|a:set|a:bag|a:subclass|a:component|a:discriminator|a:one-to-one" />
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:attribute name="table">
<xsl:choose>
<xsl:when test="@table">
<xsl:value-of select="concat( $prefix, '[', @table, ']')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat( $prefix, '[', @name, ']')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:apply-templates select="adl:key"/>
<xsl:apply-templates select="adl:property"/>
</class>
</xsl:template>
<xsl:template match="a:key">
<xsl:template match="adl:key">
<xsl:choose>
<xsl:when test="count(a:property)=0">
<xsl:message terminate="yes">
Class '<xsl:value-of select="ancestor::a:entity/@name"/>' has no properties in its key
</xsl:message>
<xsl:when test="count( adl:property) = 0">
</xsl:when>
<xsl:when test="count(a:property)=1">
<xsl:when test="count( adl:property) = 1">
<id>
<xsl:apply-templates select="a:property/@*|a:property/node()" />
<xsl:attribute name="name">
<xsl:value-of select="adl:property[position()=1]/@name"/>
</xsl:attribute>
<xsl:attribute name="column">
<xsl:call-template name="property-column-name">
<xsl:with-param name="property" select="adl:property[position()=1]"/>
</xsl:call-template>
</xsl:attribute>
<xsl:attribute name="type">
<xsl:call-template name="csharp-base-type">
<xsl:with-param name="property" select="adl:property[position()=1]"/>
</xsl:call-template>
</xsl:attribute>
<xsl:choose>
<xsl:when test="adl:property[position()=1]/adl:generator">
<xsl:attribute name="name">
<xsl:value-of select="adl:property[position()=1]/@name"/>
</xsl:attribute>
<xsl:apply-templates select="adl:property[position()=1]/adl:generator"/>
</xsl:when>
<xsl:when test="adl:property[position()=1 and @type='entity']">
<xsl:attribute name="name">
<xsl:value-of select="concat( adl:property[position()=1]/@name, '_Value')"/>
</xsl:attribute>
<xsl:variable name="entityname" select="adl:property[position()=1]/@entity"/>
<xsl:variable name="farkey">
<xsl:choose>
<xsl:when test="adl:property[position()=1]/@farkey">
<xsl:value-of select="adl:property[position()=1]/@farkey"/>
</xsl:when>
<xsl:when test="//adl:entity[@name=$entityname]/adl:key/adl:property">
<xsl:value-of select="//adl:entity[@name=$entityname]/adl:key/adl:property[position()=1]/@name"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'[unkown?]'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<generator class="foreign">
<param name="property">
<xsl:value-of select="$farkey"/>
</param>
</generator>
</xsl:when>
<xsl:otherwise>
<xsl:comment>TODO: remember you need to deal with this in manually maintained code</xsl:comment>
<generator class="assigned"/>
</xsl:otherwise>
</xsl:choose>
</id>
<xsl:if test="adl:property[position()=1 and @type='entity']">
<xsl:apply-templates select="adl:property[position()=1]"/>
</xsl:if>
</xsl:when>
<xsl:otherwise>
<composite-id>
<xsl:apply-templates select="a:property" mode="key" />
<!-- xsl:attribute name="name">
<xsl:choose>
<xsl:when test="$abstract-key-name-convention='Name'">
<xsl:value-of select="ancestor::adl:entity/@name"/>
</xsl:when>
<xsl:when test="$abstract-key-name-convention = 'NameId'">
<xsl:value-of select="concat( ancestor::adl:entity/@name, 'Id')"/>
</xsl:when>
<xsl:when test="$abstract-key-name-convention = 'Name_Id'">
<xsl:value-of select="concat( ancestor::adl:entity/@name, '_Id')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'Id'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute -->
<xsl:for-each select="adl:property[not(@type='entity')]">
<key-property>
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:attribute name="column">
<xsl:call-template name="property-column-name">
<xsl:with-param name="property" select="."/>
</xsl:call-template>
</xsl:attribute>
<xsl:attribute name="type">
<xsl:call-template name="csharp-type">
<xsl:with-param name="property" select="."/>
</xsl:call-template>
</xsl:attribute>
<xsl:apply-templates select="adl:documentation"/>
</key-property>
</xsl:for-each>
<xsl:for-each select="adl:property[@type='entity']">
<key-many-to-one>
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:attribute name="column">
<xsl:call-template name="property-column-name">
<xsl:with-param name="property" select="."/>
</xsl:call-template>
</xsl:attribute>
<xsl:attribute name="class">
<xsl:value-of select="@entity"/>
</xsl:attribute>
<xsl:choose>
<xsl:when test="@cascade='manual'"/>
<xsl:when test="@cascade">
<xsl:attribute name="cascade">
<xsl:value-of select="@cascade"/>
</xsl:attribute>
</xsl:when>
</xsl:choose>
<xsl:apply-templates select="adl:documentation"/>
</key-many-to-one>
</xsl:for-each>
</composite-id>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="a:property" mode="key">
<xsl:choose>
<xsl:when test="@type='entity'">
<key-many-to-one>
<xsl:apply-templates select="@name|@column|@entity|node()"/>
</key-many-to-one>
</xsl:when>
<xsl:when test="true()">
<key-property>
<xsl:apply-templates select="@*|node()"/>
</key-property>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template match="a:property">
<xsl:choose>
<xsl:when test="@type='entity'">
<many-to-one>
<xsl:apply-templates select="@name|@column|@entity|node()"/>
</many-to-one>
</xsl:when>
<xsl:when test="true()">
<property><xsl:apply-templates select="@*|node()"/></property>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template match="a:property/@type">
<xsl:attribute name="type">
<xsl:call-template name="type-spec">
<xsl:with-param name="typename" select="../@type"/>
</xsl:call-template>
<xsl:if test="../@size">(<xsl:value-of select="../@size"/>)</xsl:if>
</xsl:attribute>
</xsl:template>
<xsl:template match="a:property/@size"><!--Remove--></xsl:template>
<xsl:template match="a:property/@required">
<xsl:if test="string(.)='true'">
<xsl:attribute name="not-null">true</xsl:attribute>
</xsl:if>
</xsl:template>
<xsl:template match="@entity">
<xsl:attribute name="class">
<xsl:value-of select="."/></xsl:attribute>
</xsl:template>
<xsl:template match="a:set">
<set>
<xsl:apply-templates select="@*|node()" />
</set>
</xsl:template>
<xsl:template match="a:bag">
<bag>
<xsl:apply-templates select="@*|node()" />
</bag>
</xsl:template>
<xsl:template match="a:subclass">
<subclass>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="node()"/>
</subclass>
</xsl:template>
<xsl:template match="a:discriminator">
<discriminator>
<xsl:apply-templates select="@*|node()" />
</discriminator>
</xsl:template>
<xsl:template match="a:component">
<component>
<xsl:apply-templates select="@*|node()" />
</component>
</xsl:template>
<xsl:template match="a:foreign-key">
<key>
<xsl:apply-templates select="@*|node()" />
</key>
</xsl:template>
<xsl:template match="a:one-to-many">
<one-to-many>
<xsl:apply-templates select="@*|node()" />
</one-to-many>
</xsl:template>
<xsl:template match="a:one-to-one">
<one-to-one>
<xsl:apply-templates select="@*|node()" />
</one-to-one>
</xsl:template>
<xsl:template match="a:many-to-many">
<many-to-many>
<xsl:apply-templates select="@*|node()" />
</many-to-many>
</xsl:template>
<xsl:template match="a:generator">
<xsl:template match="adl:generator">
<generator>
<xsl:apply-templates select="@*|node()" />
<xsl:attribute name="class">
<xsl:choose>
<xsl:when test="@action='manual'">
<xsl:value-of select="@class"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="@action"/>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</generator>
</xsl:template>
<xsl:template match="a:param">
<param>
<xsl:apply-templates select="@*|node()" />
</param>
<xsl:template match="adl:property[@concrete='false']">
<!-- properties which are not concrete are by definition not
stored in the database -->
</xsl:template>
<xsl:template name="type-spec">
<xsl:param name="typename"/>
<xsl:param name="nullable" select="false()"/>
<xsl:variable name="type0" select="/a:application/a:type[@name=$typename]|document('types.xml')/types/type[@name=$typename]"/>
<xsl:variable name="type" select="$type0[1]"/>
<xsl:template match="adl:property[@type='message']">
<xsl:choose>
<xsl:when test="$type/@hibernate">
<xsl:value-of select="$type/@hibernate" />
<xsl:when test="@concrete='false'"/>
<xsl:otherwise>
<many-to-one class="Message">
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:if test="@column">
<xsl:attribute name="column">
<xsl:call-template name="property-column-name">
<xsl:with-param name="property" select="."/>
</xsl:call-template>
</xsl:attribute>
</xsl:if>
</many-to-one>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="adl:property[@type='entity']">
<!-- a property of type entity translates to a Hibernate many-to-one,
unless it's part of the key, in which case it translates as one-to-one.
TODO: Check this logic! -->
<!-- xsl:choose>
<xsl:when test="parent::adl:key">
<one-to-one>
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:attribute name="class">
<xsl:value-of select="@entity"/>
</xsl:attribute>
<xsl:if test="@farkey">
<xsl:attribute name="property-ref">
<xsl:value-of select="@farkey"/>
</xsl:attribute>
</xsl:if>
<xsl:choose>
<xsl:when test="@cascade='manual'"/>
<xsl:when test="@cascade">
<xsl:attribute name="cascade">
<xsl:value-of select="@cascade"/>
</xsl:attribute>
</xsl:when>
<xsl:when test="$type/@dotnet">
<xsl:value-of select="$type/@dotnet" />
</xsl:choose>
<xsl:apply-templates select="adl:documentation"/>
</one-to-one>
</xsl:when>
<xsl:when test="$type">
<xsl:message terminate="yes">Error! Found type "<xsl:value-of select="$typename"/>" but cannot find 'dotnet' or 'hibernate' attributes.</xsl:message>
<xsl:otherwise -->
<xsl:choose>
<xsl:when test="@concrete='false'"/>
<xsl:otherwise>
<many-to-one>
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:attribute name="class">
<xsl:value-of select="@entity"/>
</xsl:attribute>
<xsl:attribute name="column">
<xsl:call-template name="property-column-name">
<xsl:with-param name="property" select="."/>
</xsl:call-template>
</xsl:attribute>
<xsl:if test="@farkey">
<xsl:attribute name="property-ref">
<xsl:value-of select="@farkey"/>
</xsl:attribute>
</xsl:if>
<xsl:choose>
<xsl:when test="@cascade='manual'"/>
<xsl:when test="@cascade">
<xsl:attribute name="cascade">
<xsl:value-of select="@cascade"/>
</xsl:attribute>
</xsl:when>
</xsl:choose>
<xsl:apply-templates select="adl:documentation"/>
</many-to-one>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="adl:property[@type='list']">
<xsl:choose>
<xsl:when test="@concrete='false'"/>
<xsl:otherwise>
<xsl:variable name="farent" select="@entity"/>
<xsl:variable name="nearent" select="ancestor::adl:entity/@name"/>
<xsl:variable name="farkey">
<xsl:choose>
<xsl:when test="@farkey">
<xsl:value-of select="@farkey"/>
</xsl:when>
<xsl:otherwise>
<xsl:message terminate="yes">Error! Type "<xsl:value-of select="$typename"/>" not found.</xsl:message>
<xsl:value-of select="ancestor::adl:entity/@name"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<set>
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:attribute name="inverse">
<!-- true if the other end of the link is described in the ADL (which it normally will be) -->
<xsl:choose>
<xsl:when test="//adl:entity[@name=$farent]/adl:property[@name=$farkey and @entity=$nearent]">true</xsl:when>
<xsl:otherwise>false</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:apply-templates select="adl:documentation"/>
<!-- careful with reformatting here:
'The element cannot contain white space. Content model is empty.' -->
<key>
<xsl:attribute name="column">
<!-- this is the name of the farside foreign key field which points to me -->
<xsl:value-of select="$farkey"/>
</xsl:attribute>
</key>
<one-to-many>
<xsl:attribute name="class">
<xsl:value-of select="@entity"/>
</xsl:attribute>
</one-to-many>
<xsl:choose>
<xsl:when test="@cascade='manual'"/>
<xsl:when test="@cascade">
<xsl:attribute name="cascade">
<xsl:value-of select="@cascade"/>
</xsl:attribute>
</xsl:when>
</xsl:choose>
</set>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="adl:property[@type='link']">
<!-- a property of type 'link' maps on to a Hibernate set -->
<xsl:choose>
<xsl:when test="@concrete='false'"/>
<xsl:otherwise>
<xsl:variable name="comparison">
<xsl:call-template name="stringcompare">
<xsl:with-param name="node1" select="../@name"/>
<xsl:with-param name="node2" select="@entity"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="tablename">
<xsl:choose>
<xsl:when test="$comparison =-1">
<xsl:value-of select="concat( $dbprefix, 'ln_', ../@name, '_', @entity)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat( $dbprefix, 'ln_', @entity, '_', ../@name)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<set>
<xsl:apply-templates select="adl:documentation"/>
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:attribute name="table">
<xsl:value-of select="$tablename"/>
</xsl:attribute>
<key>
<xsl:attribute name="column">
<xsl:value-of select="concat( ../@name, 'Id')"/>
</xsl:attribute>
</key>
<many-to-many>
<xsl:attribute name="column">
<xsl:choose>
<xsl:when test="../@name = @entity">
<xsl:value-of select="concat( @entity, '_1Id')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat( @entity, 'Id')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:attribute name="class">
<xsl:value-of select="@entity"/>
</xsl:attribute>
</many-to-many>
</set>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="adl:property">
<!-- tricky, this, because we're translating between ADL properties and
Hibernate properties, which are (slightly) different. There's potential
for confusion -->
<property>
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:attribute name="type">
<xsl:call-template name="csharp-type">
<xsl:with-param name="property" select="."/>
</xsl:call-template>
</xsl:attribute>
<xsl:attribute name="column">
<xsl:call-template name="property-column-name">
<xsl:with-param name="property" select="."/>
</xsl:call-template>
</xsl:attribute>
<xsl:apply-templates select="adl:documentation"/>
</property>
</xsl:template>
<xsl:template match="adl:documentation">
<xsl:comment>
<xsl:apply-templates/>
</xsl:comment>
</xsl:template>
<!-- consistent, repeatable way of getting the column name for a given property -->
<xsl:template name="property-column-name">
<!-- a property element -->
<xsl:param name="property"/>
<xsl:variable name="unescaped">
<xsl:choose>
<xsl:when test="$property/@column">
<xsl:value-of select="$property/@column"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$property/@name"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:choose>
<xsl:when test="contains( $sqlkeywords, concat(' ', translate( $unescaped, $lcase, $ucase),' '))">
<xsl:value-of select="concat( '[', $unescaped, ']')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$unescaped"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
<!--
horrible, horrible hackery. Compare two strings and return
* 0 if they are identical,
* -1 if the first is earlier in the default collating sequence,
* 1 if the first is later.
In XSL 2.0 this could be done using the compare(string, string) function.
TODO: probably should be an include file
-->
<xsl:template name="stringcompare">
<xsl:param name="node1"/>
<xsl:param name="node2"/>
<xsl:choose>
<xsl:when test="string($node1)=string($node2)">
<xsl:text>0</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:for-each select="$node1 | $node2">
<xsl:sort select="."/>
<xsl:if test="position()=1">
<xsl:choose>
<xsl:when test="string(.) = string($node1)">
<xsl:text>-1</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>1</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

View file

@ -1,150 +1,280 @@
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:stylesheet version="1.0"
xmlns="http://cygnets.co.uk/schemas/adl-1.2"
xmlns:adl="http://cygnets.co.uk/schemas/adl-1.2"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!--
C1873 SRU Hospitality
Application Description Language framework
adl2mssql.xsl
(c) 2007 Cygnet Solutions Ltd
Convert ADL to MS-SQL
$Author: af $
$Revision: 1.1 $
$Author: sb $
$Revision: 1.2 $
-->
<xsl:output indent="no" encoding="utf-8" method="text"/>
<xsl:output indent="no" encoding="UTF-8" method="text"/>
<xsl:include href="base-type-include.xslt"/>
<xsl:template match="application">
<!--
The convention to use for naming auto-generated abstract primary keys. Known values are
Id - the autogenerated primary key, if any, is called just 'Id'
Name - the autogenerated primary key has the same name as the entity
NameId - the name of the auto generated primary key is the name of the entity followed by 'Id'
Name_Id - the name of the auto generated primary key is the name of the entity followed by '_Id'
-->
<xsl:param name="abstract-key-name-convention" select="Id"/>
<xsl:param name="database"/>
<!-- the name and version of the product being built -->
<xsl:param name="product-version" select="'Application Description Language Framework'"/>
<!-- define upper and lower case letters to enable case conversion -->
<xsl:variable name="ucase">ABCDEFGHIJKLMNOPQRSTUVWXYZ</xsl:variable>
<xsl:variable name="lcase">abcdefghijklmnopqrstuvwxyz</xsl:variable>
<!-- define SQL keywords to police these out of field names -->
<xsl:variable name="sqlkeywords-multiline">
ADD EXCEPT PERCENT
ALL EXEC PLAN
ALTER EXECUTE PRECISION
AND EXISTS PRIMARY
ANY EXIT PRINT
AS FETCH PROC
ASC FILE PROCEDURE
AUTHORIZATION FILLFACTOR PUBLIC
BACKUP FOR RAISERROR
BEGIN FOREIGN READ
BETWEEN FREETEXT READTEXT
BREAK FREETEXTTABLE RECONFIGURE
BROWSE FROM REFERENCES
BULK FULL REPLICATION
BY FUNCTION RESTORE
CASCADE GOTO RESTRICT
CASE GRANT RETURN
CHECK GROUP REVOKE
CHECKPOINT HAVING RIGHT
CLOSE HOLDLOCK ROLLBACK
CLUSTERED IDENTITY ROWCOUNT
COALESCE IDENTITY_INSERT ROWGUIDCOL
COLLATE IDENTITYCOL RULE
COLUMN IF SAVE
COMMIT IN SCHEMA
COMPUTE INDEX SELECT
CONSTRAINT INNER SESSION_USER
CONTAINS INSERT SET
CONTAINSTABLE INTERSECT SETUSER
CONTINUE INTO SHUTDOWN
CONVERT IS SOME
CREATE JOIN STATISTICS
CROSS KEY SYSTEM_USER
CURRENT KILL TABLE
CURRENT_DATE LEFT TEXTSIZE
CURRENT_TIME LIKE THEN
CURRENT_TIMESTAMP LINENO TO
CURRENT_USER LOAD TOP
CURSOR NATIONAL TRAN
DATABASE NOCHECK TRANSACTION
DBCC NONCLUSTERED TRIGGER
DEALLOCATE NOT TRUNCATE
DECLARE NULL TSEQUAL
DEFAULT NULLIF UNION
DELETE OF UNIQUE
DENY OFF UPDATE
DESC OFFSETS UPDATETEXT
DISK ON USE
DISTINCT OPEN USER
DISTRIBUTED OPENDATASOURCE VALUES
DOUBLE OPENQUERY VARYING
DROP OPENROWSET VIEW
DUMMY OPENXML WAITFOR
DUMP OPTION WHEN
ELSE OR WHERE
END ORDER WHILE
ERRLVL OUTER WITH
ESCAPE OVER WRITETEXT
</xsl:variable>
<xsl:variable name="sqlkeywords" select="concat(' ', normalize-space($sqlkeywords-multiline), ' ')"/>
<xsl:template match="adl:application">
-------------------------------------------------------------------------------------------------
--
-- <xsl:value-of select="$product-version"/>
--
-- Database for application <xsl:value-of select="@name"/> version <xsl:value-of select="@version"/>
-- Generated for MS-SQL 2000+ using adl2mssql.xsl $Revision: 1.1 $
-- Generated for MS-SQL 2000+ using adl2mssql.xslt <xsl:value-of select="substring('$Revision: 1.2 $', 12)"/>
--
-- Code generator (c) 2007 Cygnet Solutions Ltd
--
-------------------------------------------------------------------------------------------------
<xsl:if test="string-length( $database) &gt; 0">
use <xsl:value-of select="$database"/>;
</xsl:if>
-------------------------------------------------------------------------------------------------
-- authentication roles
-------------------------------------------------------------------------------------------------
<xsl:apply-templates select="group"/>
<xsl:apply-templates select="adl:group"/>
-------------------------------------------------------------------------------------------------
-- tables, views and permissions
-- primary tables, views and permissions
-------------------------------------------------------------------------------------------------
<xsl:apply-templates select="entity" mode="table"/>
<xsl:apply-templates select="entity" mode="view"/>
<xsl:apply-templates select="adl:entity" mode="table"/>
-------------------------------------------------------------------------------------------------
-- referential integrity constraints
-- link tables
-------------------------------------------------------------------------------------------------
<xsl:for-each select="entity">
<xsl:variable name="nearside" select="@name"/>
<xsl:for-each select="property[@type='entity']">
<xsl:call-template name="referentialintegrity">
<xsl:with-param name="nearside" select="$nearside"/>
</xsl:call-template>
<xsl:apply-templates select="adl:entity" mode="links"/>
</xsl:for-each>
</xsl:for-each>
-------------------------------------------------------------------------------------------------
-- primary referential integrity constraints
-------------------------------------------------------------------------------------------------
<xsl:apply-templates select="adl:entity" mode="refinteg"/>
-------------------------------------------------------------------------------------------------
-- end of file
-------------------------------------------------------------------------------------------------
</xsl:template>
<xsl:template match="group">
<xsl:template match="adl:group">
execute sp_addrole @rolename = '<xsl:value-of select="@name"/>'
GO
</xsl:template>
<!-- return the table name for the entity with this entity name -->
<xsl:template name="tablename">
<xsl:param name="entityname"/>
<xsl:choose>
<xsl:when test="//adl:entity[@name=$entityname]/@table">
<xsl:value-of select="//adl:entity[@name=$entityname]/@table"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$entityname"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="referentialintegrity">
<!-- generate a foreign key referential integrity check -->
<xsl:template name="foreignkey">
<xsl:param name="nearside"/>
<xsl:param name="farside"/>
<xsl:param name="keyfield"/>
<xsl:param name="ondelete" select="'NO ACTION'"/>
<xsl:variable name="neartable">
<xsl:call-template name="tablename">
<xsl:with-param name="entityname" select="$nearside"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="fartable">
<xsl:call-template name="tablename">
<xsl:with-param name="entityname" select="$farside"/>
</xsl:call-template>
</xsl:variable>
<!-- set up referential integrity constraints for primary tables -->
ALTER TABLE "<xsl:value-of select="$nearside"/>"
ADD FOREIGN KEY ( "<xsl:value-of select="@name"/>")
REFERENCES "<xsl:value-of select="@entity"/>" ON DELETE NO ACTION
ALTER TABLE "<xsl:value-of select="$neartable"/>"
ADD FOREIGN KEY ( "<xsl:value-of select="$keyfield"/>")
REFERENCES "<xsl:value-of select="$fartable"/>" ON DELETE <xsl:value-of select="$ondelete"/>
GO
</xsl:template>
<!-- generate referential integrity constraints -->
<xsl:template match="adl:entity" mode="refinteg">
<xsl:variable name="nearside" select="@name"/>
<xsl:for-each select="descendant::adl:property[@type='entity']">
<xsl:variable name="farside" select="@entity"/>
<xsl:variable name="keyfield">
<xsl:call-template name="property-column-name">
<xsl:with-param name="property" select="."/>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="//adl:entity[@name=$farside]//adl:property[@farkey=$keyfield and @entity=$nearside]">
<!-- there's a 'list' property pointing the other way; let it do the heavy hauling -->
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="foreignkey">
<xsl:with-param name="nearside" select="$nearside"/>
<xsl:with-param name="farside" select="$farside"/>
<xsl:with-param name="keyfield" select="$keyfield"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<xsl:for-each select="descendant::adl:property[@type='list']">
<xsl:variable name="farkey">
<xsl:choose>
<xsl:when test="@farkey">
<xsl:value-of select="@farkey"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="../@name"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:call-template name="foreignkey">
<xsl:with-param name="nearside" select="@entity"/>
<xsl:with-param name="farside" select="../@name"/>
<xsl:with-param name="keyfield" select="$farkey"/>
<xsl:with-param name="ondelete">
<xsl:choose>
<xsl:when test="@cascade='all'">CASCADE</xsl:when>
<xsl:when test="@cascade='all-delete-orphan'">CASCADE</xsl:when>
<xsl:when test="@cascade='delete'">CASCADE</xsl:when>
<xsl:otherwise>NO ACTION</xsl:otherwise>
</xsl:choose>
</xsl:with-param>
</xsl:call-template>
</xsl:for-each>
</xsl:template>
<xsl:template match="entity" mode="table">
<xsl:variable name="table" select="@name"/>
<!-- don't generate foreign tables - although we will generate ref integ constraints for them -->
<xsl:template match="adl:entity[@foreign='true']" mode="table"/>
<xsl:template match="adl:entity" mode="table">
<xsl:variable name="table">
<xsl:call-template name="tablename">
<xsl:with-param name="entityname" select="@name"/>
</xsl:call-template>
</xsl:variable>
-------------------------------------------------------------------------------------------------
-- primary table <xsl:value-of select="@name"/>
-- primary table <xsl:value-of select="$table"/>
-------------------------------------------------------------------------------------------------
CREATE TABLE "<xsl:value-of select="@name"/>"
CREATE TABLE "<xsl:value-of select="$table"/>"
(
<xsl:apply-templates select="property[@type!='link']"/>
<xsl:value-of select="@name"/>Id INT IDENTITY( 1, 1) PRIMARY KEY
<xsl:for-each select="descendant::adl:property[not( @type='link' or @type = 'list' or @concrete='false')]">
<xsl:apply-templates select="."/>
<xsl:if test="position() != last()">,</xsl:if>
</xsl:for-each>
<xsl:apply-templates select="adl:key"/>
)
GO
---- permissions ------------------------------------------------------------------------------
<xsl:for-each select="permission">
<xsl:for-each select="adl:permission">
<xsl:call-template name="permission">
<xsl:with-param name="table" select="$table"/>
<xsl:with-param name="entity" select="ancestor::adl:entity"/>
</xsl:call-template>
</xsl:for-each>
</xsl:template>
<xsl:template match="entity" mode="view">
<xsl:variable name="table" select="@name"/>
-------------------------------------------------------------------------------------------------
-- convenience view VW_DL_<xsl:value-of select="@name"/> for default list
-------------------------------------------------------------------------------------------------
CREATE VIEW "VW_DL_<xsl:value-of select="@name"/>" AS
SELECT "<xsl:value-of select="@name"/>"."<xsl:value-of select="@name"/>Id",
<xsl:for-each select="property[@type!='link']">
<xsl:choose>
<xsl:when test="@type='entity'">
<xsl:call-template name="distinctfield">
<xsl:with-param name="table" select="@entity"/>
<xsl:with-param name="alias" select="@name"/>
</xsl:call-template> AS <xsl:value-of select="@name"/></xsl:when>
<xsl:otherwise>"<xsl:value-of select="$table"/>"."<xsl:value-of select="@name"/>"</xsl:otherwise>
</xsl:choose><xsl:choose>
<xsl:when test="position() = last()"></xsl:when>
<xsl:otherwise>,
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
FROM "<xsl:value-of select="@name"/>" <xsl:for-each
select="property[@type='entity']">, "<xsl:value-of select="@entity"/>" AS "<xsl:value-of select="@name"/>"</xsl:for-each>
<xsl:text>
</xsl:text>
<xsl:for-each select="property[@type='entity']">
<xsl:choose>
<xsl:when test="position() = 1">WHERE </xsl:when>
<xsl:otherwise>AND </xsl:otherwise>
</xsl:choose>"<xsl:value-of select="$table"/>"."<xsl:value-of
select="@name"/>" = "<xsl:value-of select="@name"/>"."<xsl:value-of select="@entity"/>Id"
</xsl:for-each>
GO
---- permissions ------------------------------------------------------------------------------
<xsl:for-each select="permission">
<xsl:call-template name="viewpermission">
<xsl:with-param name="table" select="$table"/>
</xsl:call-template>
</xsl:for-each>
<!-- link tables -->
<xsl:for-each select="property[@type='link']">
<xsl:call-template name="linktable">
<xsl:with-param name="nearside" select="$table"/>
</xsl:call-template>
</xsl:for-each>
<xsl:template match="adl:key">
<xsl:if test="adl:property[not( @concrete='false')]">
,
PRIMARY KEY( <xsl:for-each select="adl:property[not( @concrete='false')]">"<xsl:call-template name="property-column-name">
<xsl:with-param name="property" select="."/>
</xsl:call-template>"<xsl:if test="position() != last()">, </xsl:if></xsl:for-each>)
</xsl:if>
</xsl:template>
<xsl:template name="distinctfield">
@ -173,63 +303,59 @@
</xsl:for-each>
</xsl:template>
<!-- fix up linking tables. Donoe after all primary tables have been created,
because otherwise some links may fail -->
<xsl:template match="adl:entity" mode="links">
<xsl:variable name="entityname" select="@name"/>
<xsl:for-each select="adl:property[@type='link']">
<xsl:call-template name="linktable">
<xsl:with-param name="nearside" select="$entityname"/>
</xsl:call-template>
</xsl:for-each>
</xsl:template>
<xsl:template name="permission">
<xsl:param name="table"/>
<xsl:param name="entity"/>
<!-- decode the permissions for a table -->
<xsl:variable name="table">
<xsl:call-template name="tablename">
<xsl:with-param name="entityname" select="$entity/@name"/>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="@permission='read'">GRANT SELECT ON "<xsl:value-of
<xsl:when test="@permission='read'">
GRANT SELECT ON "<xsl:value-of
select="$table"/>" TO <xsl:value-of select="@group"/>
GO</xsl:when>
<xsl:when test="@permission='insert'">GRANT INSERT ON "<xsl:value-of
</xsl:when>
<xsl:when test="@permission='insert'">
GRANT INSERT ON "<xsl:value-of
select="$table"/>" TO <xsl:value-of select="@group"/>
GO</xsl:when>
<xsl:when test="@permission='noedit'">GRANT SELECT, INSERT ON "<xsl:value-of
</xsl:when>
<xsl:when test="@permission='noedit'">
GRANT SELECT, INSERT ON "<xsl:value-of
select="$table"/>" TO <xsl:value-of select="@group"/>
GO</xsl:when>
<xsl:when test="@permission='edit'">GRANT SELECT, INSERT, UPDATE ON "<xsl:value-of
</xsl:when>
<xsl:when test="@permission='edit'">
GRANT SELECT, INSERT, UPDATE ON "<xsl:value-of
select="$table"/>" TO <xsl:value-of select="@group"/>
GO</xsl:when>
<xsl:when test="@permission='all'">GRANT SELECT, INSERT, UPDATE, DELETE ON "<xsl:value-of
</xsl:when>
<xsl:when test="@permission='all'">
GRANT SELECT, INSERT, UPDATE, DELETE ON "<xsl:value-of
select="$table"/>" TO <xsl:value-of select="@group"/>
GO</xsl:when>
<xsl:otherwise>REVOKE ALL ON "<xsl:value-of
</xsl:when>
<xsl:otherwise>
REVOKE ALL ON "<xsl:value-of
select="$table"/>" FROM <xsl:value-of select="@group"/>
GO</xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
<xsl:text>
GO
</xsl:text>
</xsl:template>
<xsl:template name="viewpermission">
<xsl:param name="table"/>
<!-- decode the permissions for a convenience view -->
<xsl:choose>
<xsl:when test="@permission='none'">REVOKE ALL ON "VW_DL_<xsl:value-of
select="$table"/>" FROM <xsl:value-of select="@group"/>
GO</xsl:when>
<xsl:when test="@permission='insert'">REVOKE ALL ON "VW_DL_<xsl:value-of
select="$table"/>" FROM <xsl:value-of select="@group"/>
GO</xsl:when>
<xsl:otherwise>GRANT SELECT ON "VW_DL_<xsl:value-of
select="$table"/>" TO <xsl:value-of select="@group"/>
GO</xsl:otherwise>
</xsl:choose>
<xsl:text>
</xsl:text>
</xsl:template>
<!-- expects to be called in the context of an entity; probably should make this explicit.
TODO: this is a mess; refactor. -->
<xsl:template name="linktable">
<xsl:param name="nearside"/>
<!-- This is tricky. For any many-to-many relationship between two
@ -251,15 +377,9 @@
<xsl:with-param name="node2" select="@entity"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="farentity" select="/application/entity[@name=$farside]"/>
<xsl:variable name="farentityname" select="@entity"/>
<xsl:variable name="farentity" select="//adl:entity[@name=$farentityname]"/>
-- Problems with responsibility for generating link tables:
-- @entity = <xsl:value-of select="@entity"/>
-- $nearside = <xsl:value-of select="$nearside"/>
-- $farside = <xsl:value-of select="$farside"/>
-- $farentity = <xsl:value-of select="count( $farentity/property)"/>
-- farlink = <xsl:value-of select="$farentity/property[@type='link' and @entity=$nearside]/@name"/>
-- comparison = '<xsl:value-of select="$comparison"/>'
<xsl:variable name="myresponsibility">
<xsl:choose>
@ -275,24 +395,31 @@
<xsl:when test="$comparison = 1">
<xsl:choose>
<!-- the far side is doing it... -->
<xsl:when test="$farentity/property[@type='link' and @entity=$nearside]">false</xsl:when>
<xsl:when test="$farentity/adl:property[@type='link' and @entity=$nearside]">false</xsl:when>
<xsl:otherwise>true</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>false</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="tablename">
<!-- Problems with responsibility for generating link tables: -->
-- Problems with responsibility for generating link tables:
-- @entity = <xsl:value-of select="@entity"/>
-- $nearside = <xsl:value-of select="$nearside"/>
-- $farside = <xsl:value-of select="$farside"/>
-- farlink = <xsl:value-of select="$farentity/adl:property[@type='link' and @entity=$nearside]/@name"/>
-- comparison = '<xsl:value-of select="$comparison"/>'
-- my responsibility = <xsl:value-of select="$myresponsibility"/>
<xsl:variable name="linktablename">
<xsl:choose>
<xsl:when test="$comparison =-1">
<xsl:value-of select="concat( 'ln_', $nearside, '_', @entity)"/>
<xsl:value-of select="concat( 'LN_', $nearside, '_', @entity)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat( 'ln_', @entity, '_', $nearside)"/>
<xsl:value-of select="concat( 'LN_', @entity, '_', $nearside)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
-- Responsibility = '<xsl:value-of select="$myresponsibility"/>'
<xsl:choose>
<xsl:when test="$myresponsibility='true'">
<!-- create a linking table -->
@ -300,10 +427,14 @@
-------------------------------------------------------------------------------------------------
-- link table joining <xsl:value-of select="$nearside"/> with <xsl:value-of select="@entity"/>
-------------------------------------------------------------------------------------------------
CREATE TABLE "<xsl:value-of select="$tablename"/>"
CREATE TABLE "<xsl:value-of select="$linktablename"/>"
(
"<xsl:value-of select="$nearside"/>Id" INT NOT NULL,
"<xsl:value-of select="$farside"/>Id" INT NOT NULL,
"<xsl:value-of select="concat( $nearside, 'Link')"/>" <xsl:call-template name="sql-type">
<xsl:with-param name="property" select="//adl:entity[@name=$nearside]/adl:key/adl:property[position()=1]"/>
</xsl:call-template> NOT NULL,
"<xsl:value-of select="concat( $farside, 'Link')"/>" <xsl:call-template name="sql-type">
<xsl:with-param name="property" select="$farentity/adl:key/adl:property[position()=1]"/>
</xsl:call-template> NOT NULL
)
GO
@ -311,130 +442,270 @@
</xsl:text>
---- permissions ------------------------------------------------------------------------------
<xsl:for-each select="../permission">
<xsl:call-template name="permission">
<xsl:with-param name="table" select="$tablename"/>
</xsl:call-template>
</xsl:for-each>
<xsl:text>
</xsl:text>
---- referential integrity --------------------------------------------------------------------
<!-- only two levels of permission really matter for a link table. If you can read both of the
parent tables, then you can read the link table. If you can edit either of the parent tables,
then you need full CRUD permissions on the link table. -->
<xsl:for-each select="//adl:group">
<xsl:variable name="groupname" select="@name"/>
<xsl:choose>
<xsl:when test="$nearside=@entity">
ALTER TABLE "<xsl:value-of select="$tablename"/>"
ADD FOREIGN KEY ( "<xsl:value-of select="$nearside"/>Id")
REFERENCES "<xsl:value-of select="$nearside"/>" ON DELETE NO ACTION
GO
ALTER TABLE "<xsl:value-of select="$tablename"/>"
ADD FOREIGN KEY ( "<xsl:value-of select="$farside"/>Id")
REFERENCES "<xsl:value-of select="$nearside"/>" ON DELETE NO ACTION
GO
<xsl:when test="//adl:entity[@name=$nearside]/adl:permission[@group=$groupname and @permission='all']">
GRANT SELECT,INSERT,UPDATE,DELETE ON <xsl:value-of select="$linktablename"/> TO <xsl:value-of select="$groupname"/>
</xsl:when>
<xsl:when test="//adl:entity[@name=$nearside]/adl:permission[@group=$groupname and @permission='edit']">
GRANT SELECT,INSERT,UPDATE,DELETE ON <xsl:value-of select="$linktablename"/> TO <xsl:value-of select="$groupname"/>
</xsl:when>
<xsl:when test="//adl:entity[@name=$farside]/adl:permission[@group=$groupname and @permission='all']">
GRANT SELECT,INSERT,UPDATE,DELETE ON <xsl:value-of select="$linktablename"/> TO <xsl:value-of select="$groupname"/>
</xsl:when>
<xsl:when test="//adl:entity[@name=$farside]/adl:permission[@group=$groupname and @permission='edit']">
GRANT SELECT,INSERT,UPDATE,DELETE ON <xsl:value-of select="$linktablename"/> TO <xsl:value-of select="$groupname"/>
</xsl:when>
<xsl:when test="//adl:entity[@name=$nearside]/adl:permission[@group=$groupname and @permission='none']">
REVOKE ALL ON <xsl:value-of select="$linktablename"/> FROM <xsl:value-of select="$groupname"/>
</xsl:when>
<xsl:when test="//adl:entity[@name=$farside]/adl:permission[@group=$groupname and @permission='none']">
REVOKE ALL ON <xsl:value-of select="$linktablename"/> FROM <xsl:value-of select="$groupname"/>
</xsl:when>
<xsl:otherwise>
ALTER TABLE "<xsl:value-of select="$tablename"/>"
ADD FOREIGN KEY ( "<xsl:value-of select="$nearside"/>Id")
REFERENCES "<xsl:value-of select="$nearside"/>" ON DELETE CASCADE
GO
ALTER TABLE "<xsl:value-of select="$tablename"/>"
ADD FOREIGN KEY ( "<xsl:value-of select="@entity"/>Id")
REFERENCES "<xsl:value-of select="@entity"/>" ON DELETE CASCADE
GO
GRANT SELECT ON <xsl:value-of select="$linktablename"/> TO <xsl:value-of select="$groupname"/>
</xsl:otherwise>
</xsl:choose>
GO
</xsl:for-each>
---- referential integrity --------------------------------------------------------------------
<xsl:variable name="neartable">
<xsl:call-template name="tablename">
<xsl:with-param name="entityname" select="$nearside"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="fartable">
<xsl:call-template name="tablename">
<xsl:with-param name="entityname" select="$farentityname"/>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="$nearside=@entity">
<xsl:call-template name="foreignkey">
<xsl:with-param name="nearside" select="$linktablename"/>
<xsl:with-param name="farside" select="$neartable"/>
<xsl:with-param name="keyfield" select="concat( $nearside, 'Link')"/>
<xsl:with-param name="ondelete" select="'NO ACTION'"/>
</xsl:call-template>
<xsl:call-template name="foreignkey">
<xsl:with-param name="nearside" select="$linktablename"/>
<xsl:with-param name="farside" select="$fartable"/>
<xsl:with-param name="keyfield" select="concat( $farside, 'Link')"/>
<xsl:with-param name="ondelete" select="'CASCADE'"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
-- Suppressing generation of <xsl:value-of select="$tablename"/>, as it is not my responsibility
<xsl:call-template name="foreignkey">
<xsl:with-param name="nearside" select="$linktablename"/>
<xsl:with-param name="farside" select="$neartable"/>
<xsl:with-param name="keyfield" select="concat( $nearside, 'Id')"/>
<xsl:with-param name="ondelete" select="'CASCADE'"/>
</xsl:call-template>
<xsl:call-template name="foreignkey">
<xsl:with-param name="nearside" select="$linktablename"/>
<xsl:with-param name="farside" select="$fartable"/>
<xsl:with-param name="keyfield" select="concat( @entity, 'Id')"/>
<xsl:with-param name="ondelete" select="'CASCADE'"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
-- Suppressing generation of <xsl:value-of select="$linktablename"/>, as it is not my responsibility
</xsl:otherwise>
</xsl:choose>
<xsl:if test="myresponsibility='true'">
</xsl:if>
</xsl:template>
<xsl:template match="property[@type='list']">
<xsl:template match="adl:property[@type='list']">
-- Suppressing output of property <xsl:value-of select="@name"/>,
-- as it is the 'one' end of a one-to-many relationship
</xsl:template>
<xsl:template match="property[@type='entity']">
"<xsl:value-of select="@name"/>" INT<xsl:if
<xsl:template match="adl:generator[@action='native']">
IDENTITY( 1, 1)
</xsl:template>
<xsl:template match="adl:generator"/>
<!-- the grand unified property handler, using the sql-type template to
generate the correct types for each field -->
<xsl:template match="adl:property">
<xsl:variable name="column">
<xsl:call-template name="property-column-name">
<xsl:with-param name="property" select="."/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="type">
<xsl:call-template name="sql-type">
<xsl:with-param name="property" select="."/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="base-type">
<xsl:call-template name="base-type">
<xsl:with-param name="property" select="."/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="generator">
<xsl:apply-templates select="adl:generator"/>
</xsl:variable>
"<xsl:value-of select="$column"/>" <xsl:value-of
select="concat( normalize-space( $type), ' ', normalize-space( $generator))"/><xsl:if
test="@required='true'"> NOT NULL</xsl:if><xsl:if
test="string(@default)"> DEFAULT <xsl:choose>
<xsl:when test="$base-type = 'integer' or $base-type = 'real' or $base-type = 'money'">
<xsl:value-of select="@default"/>
</xsl:when>
<xsl:otherwise>'<xsl:value-of select="@default"/>'</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
<!-- properties of type 'entity' are supposed to be being handled by the
grand unified property handler. Unfortunately it gets them wrong and I'm not
sure why. So temporarily this special case template fixes the problem. TODO:
work out what's wrong with the grand unified version -->
<xsl:template match="adl:property[@type='entity']">
<xsl:variable name="column">
<xsl:call-template name="property-column-name">
<xsl:with-param name="property" select="."/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="type">
<xsl:call-template name="sql-type">
<xsl:with-param name="property" select="."/>
</xsl:call-template>
</xsl:variable>
"<xsl:value-of select="$column"/>" <xsl:value-of select="$type"/><xsl:if
test="string(@default)"> DEFAULT <xsl:value-of select="@default"/></xsl:if><xsl:if
test="@required='true'"> NOT NULL</xsl:if>,<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="property[@type='defined']">
<xsl:variable name="name"><xsl:value-of select="@definition"/></xsl:variable>
<xsl:variable name="definitiontype"><xsl:value-of select="/application/definition[@name=$name]/@type"/></xsl:variable>
"<xsl:value-of select="@name"/>"<xsl:text> </xsl:text><xsl:choose>
<xsl:when test="$definitiontype='string'">VARCHAR( <xsl:value-of
select="/application/definition[@name=$name]/@size"/>)</xsl:when>
<xsl:when test="$definitiontype='integer'">INT</xsl:when>
<xsl:when test="$definitiontype='real'">DOUBLE PRECISION</xsl:when>
<xsl:otherwise><xsl:value-of select="$definitiontype"/></xsl:otherwise>
</xsl:choose><xsl:if
test="string(@default)"> DEFAULT <xsl:value-of select="@default"/></xsl:if><xsl:if
test="@required='true'"> NOT NULL</xsl:if>,<xsl:text>
</xsl:text>
test="@required='true'"> NOT NULL</xsl:if>
</xsl:template>
<xsl:template match="property[@type='boolean']">
-- SQL Server doesn't have proper booleans!
"<xsl:value-of select="@name"/>" BIT<xsl:choose>
<xsl:when test="@default='true'"> DEFAULT 1</xsl:when>
<xsl:when test="@default='false'"> DEFAULT 0</xsl:when>
</xsl:choose><xsl:if test="@required='true'"> NOT NULL</xsl:if>,<xsl:text>
</xsl:text>
<!-- consistent, repeatable way of getting the column name for a given property -->
<xsl:template name="property-column-name">
<!-- a property element -->
<xsl:param name="property"/>
<xsl:variable name="unescaped">
<xsl:choose>
<xsl:when test="$property/@column">
<xsl:value-of select="$property/@column"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$property/@name"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:choose>
<xsl:when test="contains( $sqlkeywords, concat(' ', translate( $unescaped, $lcase, $ucase),' '))">
<xsl:value-of select="concat( '[', $unescaped, ']')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$unescaped"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="property[@type='string']">
"<xsl:value-of select="@name"/>" VARCHAR( <xsl:value-of select="@size"/>)<xsl:if
test="string(@default)"> DEFAULT '<xsl:value-of select="@default"/>'</xsl:if><xsl:if
test="@required='true'"> NOT NULL</xsl:if>,<xsl:text>
</xsl:text>
<xsl:template name="primary-key-name">
<xsl:param name="entityname"/>
<xsl:choose>
<xsl:when test="//adl:entity[@name=$entityname]/@natural-key">
<xsl:value-of select="//adl:entity[@name=$entityname]/@natural-key"/>
</xsl:when>
<xsl:when test="//adl:entity[@name=$entityname]/key">
<xsl:choose>
<xsl:when test="count(//adl:entity[@name=$entityname]/adl:key/adl:property) &gt; 1">
<xsl:message terminate="no">
ADL: WARNING: entity '<xsl:value-of select="$entityname"/>' has a compound primary key;
adl2mssql is not yet clever enough to generate appropriate code
</xsl:message>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="//adl:entity[@name=$entityname]/adl:key/adl:property[position()=1]"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="$abstract-key-name-convention='Name'">
<xsl:value-of select="@name"/>
</xsl:when>
<xsl:when test="$abstract-key-name-convention = 'NameId'">
<xsl:value-of select="concat( $entityname, 'Id')"/>
</xsl:when>
<xsl:when test="$abstract-key-name-convention = 'Name_Id'">
<xsl:value-of select="concat( $entityname, '_Id')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'Id'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="property[@type='date' or @type = 'time']">
"<xsl:value-of select="@name"/>" DATETIME<xsl:if
test="string(@default)"> DEFAULT <xsl:value-of select="@default"/>
</xsl:if><xsl:if
test="@required='true'"> NOT NULL</xsl:if>,<xsl:text>
</xsl:text>
</xsl:template>
<!-- return the SQL type of the property which is passed as a parameter -->
<xsl:template name="sql-type">
<xsl:param name="property"/>
<xsl:variable name="base-type">
<xsl:call-template name="base-type">
<xsl:with-param name="property" select="$property"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="base-size">
<xsl:call-template name="base-size">
<xsl:with-param name="property" select="$property"/>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="$base-type = 'entity'">
<xsl:variable name="entity" select="$property/@entity"/>
<xsl:choose>
<xsl:when test="//adl:entity[@name=$entity]">
<xsl:choose>
<xsl:when test="//adl:entity[@name=$entity]/adl:key/adl:property">
<xsl:call-template name="sql-type">
<xsl:with-param name="property"
select="//adl:entity[@name=$entity]/adl:key/adl:property[position()=1]"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:message terminate="yes">
ADL: ERROR: property '<xsl:value-of select="$property/@name"/>' refers to
entity '<xsl:value-of select="$property/@entity"/>', but this entity has no key.
</xsl:message>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:message terminate="yes">
ADL: ERROR: property '<xsl:value-of select="$property/@name"/>' refers to
entity '<xsl:value-of select="$property/@entity"/>', but no such entity exists.
</xsl:message>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:when test="$base-type = 'date'">DATETIME</xsl:when>
<xsl:when test="$base-type = 'time'">DATETIME</xsl:when>
<!-- TODO: if the type was 'defined' then the size should probably come from the typedef -->
<xsl:when test="$base-type = 'string'">VARCHAR( <xsl:value-of select="$base-size"/>)</xsl:when>
<xsl:when test="$base-type = 'text'">TEXT</xsl:when>
<xsl:when test="$base-type = 'boolean'">BIT</xsl:when>
<xsl:when test="$base-type = 'timestamp'">TIMESTAMP</xsl:when>
<xsl:when test="$base-type = 'integer'">INT</xsl:when>
<xsl:when test="$base-type = 'real'">DOUBLE PRECISION</xsl:when>
<xsl:when test="$base-type = 'money'">DECIMAL</xsl:when>
<xsl:otherwise>[sql:unknown? [<xsl:value-of select="$base-type"/>]]</xsl:otherwise>
</xsl:choose>
<xsl:template match="property[@type='integer']">
"<xsl:value-of select="@name"/>" INT<xsl:if
test="string(@default)"> DEFAULT <xsl:value-of select="@default"/></xsl:if><xsl:if
test="@required='true'"> NOT NULL</xsl:if>,<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="property[@type='real']">
"<xsl:value-of select="@name"/>" DOUBLE PRECISION<xsl:if
test="string(@default)"> DEFAULT <xsl:value-of select="@default"/></xsl:if><xsl:if
test="@required='true'"> NOT NULL</xsl:if>,<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="property">
"<xsl:value-of select="@name"/>" <xsl:text> </xsl:text><xsl:value-of select="@type"/><xsl:if
test="string(@default)"> DEFAULT <xsl:value-of select="@default"/></xsl:if><xsl:if
test="@required='true'"> NOT NULL</xsl:if>,<xsl:text>
</xsl:text>
</xsl:template>

View file

@ -7,13 +7,18 @@
<!-- Purpose: -->
<!-- XSL stylesheet to generate Postgresql [7|8] from ADL. -->
<!-- -->
<!-- Author: Simon Brooke <sb@cygnets.co.uk> -->
<!-- Author: Simon Brooke <simon@weft.co.uk> -->
<!-- Created: 24th January 2006 -->
<!-- Copyright: (c) 2008 Cygnet Solutions -->
<!-- Copyright: (c) 2006 Simon Brooke. -->
<!-- -->
<!-- This file is presently not up to date with changes in ADL -->
<!-- -->
<!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
<!--
JACQUARD 2 APPLICATION DESCRIPTION LANGUAGE FRAMEWORK
$Revision: 1.1 $
$Revision: 1.2 $
NOTES:
@ -30,15 +35,15 @@
two removes (i.e. the 'distinguish' mechanism in ADL
-->
<xsl:output indent="no" encoding="utf-8" method="text"/>
<xsl:output indent="no" encoding="UTF-8" method="text"/>
<xsl:template match="application">
-------------------------------------------------------------------------------------------------
--
-- Database for application <xsl:value-of select="@name"/> version <xsl:value-of select="@version"/>
-- Generated for PostgreSQL [7|8] using adl2psql.xsl $Revision: 1.1 $
-- Generated for PostgreSQL [7|8] using adl2psql.xsl $Revision: 1.2 $
--
-- Code generator (c) 2006 Simon Brooke [sb@cygnets.co.uk]
-- Code generator (c) 2006 Simon Brooke [simon@weft.co.uk]
-- http://www.weft.co.uk/library/jacquard/
--
-------------------------------------------------------------------------------------------------
@ -84,7 +89,7 @@
<xsl:template name="referentialintegrity">
<xsl:param name="nearside"/>
<!-- set up referential integrity constraints for primary tables -->
ALTER TABLE <xsl:value-of select="$nearside"/> ADD CONSTRAINT ri_<xsl:value-of select="$nearside"/>_<xsl:value-of select="@name"/>
ALTER TABLE <xsl:value-of select="$nearside"/> ADD CONSTRAINT ri_<xsl:value-of select="$nearside"/><xsl:value-of select="concat( '_', @name)"/>
FOREIGN KEY ( <xsl:value-of select="@name"/>) REFERENCES <xsl:value-of select="@entity"/> ON DELETE NO ACTION;
</xsl:template>
@ -122,9 +127,9 @@
</xsl:call-template>
</xsl:for-each>
-------------------------------------------------------------------------------------------------
-- convenience view lv_<xsl:value-of select="@name"/> for lists
-- convenience view lv<xsl:value-of select="concat( '_', @name)"/> for lists
-------------------------------------------------------------------------------------------------
CREATE VIEW lv_<xsl:value-of select="@name"/> AS
CREATE VIEW lv<xsl:value-of select="concat( '_', @name)"/> AS
SELECT <xsl:for-each select="property[@type!='link']">
<xsl:choose>
<xsl:when test="@type='entity'">

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
Application Description Language framework
base-type-include.xslt
(c) 2007 Cygnet Solutions Ltd
An xsl transform intended to be included into other XSL stylesheets,
intended to keep lookup of the ADL base type from ADL properties in
one place for ease of maintenance
$Author: sb $
$Revision: 1.1 $
$Date: 2008-05-29 16:40:09 $
-->
<xsl:stylesheet version="1.0"
xmlns="http://cygnets.co.uk/schemas/adl-1.2"
xmlns:adl="http://cygnets.co.uk/schemas/adl-1.2"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
exclude-result-prefixes="adl">
<!-- return the base ADL type of the property which is passed as a parameter -->
<xsl:template name="base-type">
<xsl:param name="property"/>
<xsl:choose>
<xsl:when test="$property/@type='defined'">
<xsl:variable name="definition">
<xsl:value-of select="$property/@typedef"/>
</xsl:variable>
<xsl:value-of select="/adl:application/adl:typedef[@name=$definition]/@type"/>
</xsl:when>
<xsl:when test="$property/@type='serial'">integer</xsl:when>
<xsl:when test="$property/@type='message'">integer</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$property/@type"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- return the size of the type of the property which is passed as a parameter -->
<xsl:template name="base-size">
<xsl:param name="property"/>
<xsl:variable name="base-type">
<xsl:call-template name="base-type">
<xsl:with-param name="property" select="$property"/>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="$property/@type='defined'">
<xsl:variable name="definition">
<xsl:value-of select="$property/@typedef"/>
</xsl:variable>
<xsl:value-of select="/adl:application/adl:typedef[@name=$definition]/@size"/>
</xsl:when>
<!-- type='text' should really be unlimited, but in the real world it isn't.
Furthermore, setting null values may currently break the smart form components
parser -->
<xsl:when test="$base-type='text'">4294967296</xsl:when>
<xsl:when test="$base-type='integer'">8</xsl:when>
<xsl:when test="$base-type='real'">8</xsl:when>
<xsl:when test="$base-type='money'">10</xsl:when>
<xsl:when test="$base-type='date'">10</xsl:when>
<xsl:when test="$base-type='time'">8</xsl:when>
<xsl:when test="$property/@size &gt; 0">
<xsl:value-of select="$property/@size"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$base-type"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

View file

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
Application Description Language framework
csharp-type-include.xslt
(c) 2007 Cygnet Solutions Ltd
An XSL transform intended to be included into other XSL stylesheets,
intended to keep lookup of the C# type from ADL properties in
one place for ease of maintenance
$Author: sb $
$Revision: 1.1 $
$Date: 2008-05-29 16:40:09 $
-->
<xsl:stylesheet version="1.0"
xmlns="http://cygnets.co.uk/schemas/adl-1.2"
xmlns:adl="http://cygnets.co.uk/schemas/adl-1.2"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
exclude-result-prefixes="adl">
<xsl:include href="base-type-include.xslt"/>
<!-- return the primitive C# type of the property which is passed as
a parameter - i.e. if csharp-type is an entity, then the csharp-type
of the keyfield of that entity, and so on. -->
<xsl:template name="csharp-base-type">
<xsl:param name="property"/>
<xsl:param name="entityns"/>
<xsl:choose>
<xsl:when test="$property/@type = 'entity'">
<xsl:variable name="entityname" select="$property/@entity"/>
<xsl:choose>
<xsl:when test="//adl:entity[@name=$entityname]/adl:key/adl:property">
<!-- recurse... -->
<xsl:call-template name="csharp-base-type">
<xsl:with-param name="property"
select="//adl:entity[@name=$entityname]/adl:key/adl:property[position()=1]"/>
<xsl:with-param name="entityns" select="$entityns"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:message terminate="yes">
ADL: ERROR: could not find C# base type of property <xsl:value-of select="$property/@name"/>
</xsl:message>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="csharp-type">
<xsl:with-param name="property" select="$property"/>
<xsl:with-param name="entityns" select="$entityns"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- return the C# type of the property which is passed as a parameter -->
<xsl:template name="csharp-type">
<xsl:param name="property"/>
<xsl:param name="entityns"/>
<xsl:variable name="base-type">
<xsl:call-template name="base-type">
<xsl:with-param name="property" select="$property"/>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="$property/@type = 'message'">Message</xsl:when>
<xsl:when test="$base-type = 'link'">
ICollection&lt;<xsl:value-of select="@entity"/>&gt;
</xsl:when>
<xsl:when test="$base-type = 'list'">
ICollection&lt;<xsl:value-of select="@entity"/>&gt;
</xsl:when>
<xsl:when test="$base-type = 'date'">DateTime</xsl:when>
<xsl:when test="$base-type = 'time'">DateTime</xsl:when>
<xsl:when test="$base-type = 'string'">String</xsl:when>
<xsl:when test="$base-type = 'text'">String</xsl:when>
<xsl:when test="$base-type = 'boolean'">Boolean</xsl:when>
<xsl:when test="$base-type = 'timestamp'">DateTime</xsl:when>
<xsl:when test="$base-type = 'integer'">int</xsl:when>
<xsl:when test="$base-type = 'real'">double</xsl:when>
<xsl:when test="$base-type = 'money'">Decimal</xsl:when>
<xsl:when test="$base-type = 'entity'">
<xsl:choose>
<xsl:when test="$entityns">
<xsl:value-of select="concat( $entityns, '.', $property/@entity)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$property/@entity"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>[unknown?]</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="utf-8" method="html" indent="yes" />
<xsl:output encoding="UTF-8" method="html" indent="yes" />
<xsl:param name="locale" select="en-UK"/>
@ -12,7 +12,7 @@
Data definition for the <xsl:value-of select="@name"/> application
version <xsl:value-of select="@version"/>
</title>
<link href="styles/default.css" rel="stylesheet" type="text/css" />
<link href="../styles/default.css" rel="stylesheet" type="text/css" />
</head>
<body>
<h1>

View file

@ -1,202 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:h="urn:nhibernate-mapping-2.2">
<!--
Application Description Framework
hibernate2adl.xsl
(c) 2007 Cygnet Solutions Ltd
Transforms hibernate mapping file into partial ADL file. Not complete,
because the whole point of having an ADL is that the hibernate mapping
is not sufficiently rich.
$Author: af $
$Revision: 1.1 $
-->
<xsl:output indent="yes" method="xml" encoding="utf-8"
/>
<xsl:variable name="entityns" select="/h:hibernate-mapping/@namespace"/>
<xsl:template match="h:hibernate-mapping">
<application name="unset" version="unset">
<xsl:apply-templates select="h:class"/>
</application>
</xsl:template>
<xsl:template match="h:class">
<entity>
<xsl:attribute name="name">
<xsl:call-template name="last-part">
<xsl:with-param name="full" select="@name"/>
</xsl:call-template>
</xsl:attribute>
<xsl:if test="@table">
<xsl:attribute name="table">
<xsl:value-of select="@table"/>
</xsl:attribute>
</xsl:if>
<xsl:apply-templates/>
<form name="edit" properties="listed">
<xsl:for-each select="h:property|h:composite-id/*|h:many-to-one">
<field>
<xsl:attribute name="property">
<xsl:value-of select="@name"/>
</xsl:attribute>
</field>
</xsl:for-each>
</form>
<list name="list" onselect="edit" properties="listed">
<pragma name="with-pagination-control" value="true"/>
<pragma name="with-can-add" value="true"/>
<xsl:for-each select="h:property[@type!='list' and @type!='link']|h:composite-id/*">
<field>
<xsl:attribute name="property">
<xsl:value-of select="@name"/>
</xsl:attribute>
</field>
</xsl:for-each>
</list>
</entity>
</xsl:template>
<xsl:template match="h:id">
<key name="primary">
<property distinct="system" required="true">
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:attribute name="type">
<xsl:call-template name="type-attr">
<xsl:with-param name="t" select="@type" />
</xsl:call-template>
</xsl:attribute>
</property>
</key>
</xsl:template>
<xsl:template match="h:composite-id">
<key name="primary">
<xsl:apply-templates select="*"/>
</key>
</xsl:template>
<xsl:template match="h:property|h:key-property">
<property>
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:attribute name="type">
<xsl:call-template name="type-attr">
<xsl:with-param name="t" select="@type" />
</xsl:call-template>
</xsl:attribute>
<xsl:choose>
<xsl:when test="contains(name(..),'composite-id')">
<xsl:attribute name="required">true</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="required">
<xsl:choose>
<xsl:when test="@not-null = 'true'">true</xsl:when>
<xsl:otherwise>false</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xsl:otherwise>
</xsl:choose>
</property>
</xsl:template>
<xsl:template name="type-attr">
<xsl:param name="t"/>
<xsl:choose>
<xsl:when test="$t = 'DateTime'">date</xsl:when>
<xsl:when test="$t = 'Decimal'">real</xsl:when>
<xsl:when test="$t = 'String' or $t='string'">string</xsl:when>
<xsl:when test="starts-with($t,'String(')">string</xsl:when>
<xsl:when test="$t = 'bool' or $t='Boolean'">boolean</xsl:when>
<xsl:when test="$t = 'TimeStamp'">timestamp</xsl:when>
<xsl:when test="$t = 'int' or $t='Int32'">integer</xsl:when>
<xsl:when test="substring($t, string-length($t) - 3)='Type'">
<xsl:value-of select="substring($t, 1, string-length($t)-4)"/>
</xsl:when>
<xsl:otherwise>[unknown!<xsl:value-of select="$t"/>]</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="last-part">
<xsl:param name="full"/>
<xsl:choose>
<xsl:when test="starts-with($full, concat($entityns, '.'))">
<xsl:value-of select="substring($full, string-length($entityns)+2)"/>
</xsl:when>
<xsl:otherwise><xsl:value-of select="$full"/></xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="h:many-to-one|h:key-many-to-one">
<property>
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:attribute name="type">entity</xsl:attribute>
<xsl:attribute name="entity">
<xsl:call-template name="last-part">
<xsl:with-param name="full" select="@class"/>
</xsl:call-template>
</xsl:attribute>
<xsl:choose>
<xsl:when test="contains(name(..),'composite-id')">
<xsl:attribute name="required">true</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="required">
<xsl:choose>
<xsl:when test="@not-null = 'true'">true</xsl:when>
<xsl:otherwise>false</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xsl:otherwise>
</xsl:choose>
</property>
</xsl:template>
<xsl:template match="h:set/h:many-to-many">
<property>
<xsl:attribute name="name">
<xsl:value-of select="../@name"/>
</xsl:attribute>
<xsl:attribute name="type">link</xsl:attribute>
<xsl:attribute name="entity">
<xsl:call-template name="last-part">
<xsl:with-param name="full" select="@class"/>
</xsl:call-template>
</xsl:attribute>
</property>
</xsl:template>
<xsl:template match="h:set/h:one-to-many">
<property>
<xsl:attribute name="name">
<xsl:value-of select="../@name"/>
</xsl:attribute>
<xsl:attribute name="type">list</xsl:attribute>
<xsl:attribute name="entity">
<xsl:call-template name="last-part">
<xsl:with-param name="full" select="@class"/>
</xsl:call-template>
</xsl:attribute>
</property>
</xsl:template>
<!-- xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template -->
</xsl:stylesheet>

View file

@ -0,0 +1,192 @@
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns="http://cygnets.co.uk/schemas/adl-1.2"
xmlns:adl="http://cygnets.co.uk/schemas/adl-1.2"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<!--
Application Description Language framework
i18n-en-GB-include.xslt
(c) 2007 Cygnet Solutions Ltd
Internationalisation support for British English; use
this as a template to provide internationalisation support
for other natural languages.
In general all templates in this file are
(i) named;
(ii) have names starting with 'i18n-';
(iii) take arguments which are strings only, not nodesets.
Templates are listed in alphabetical order.
$Author: sb $
$Revision: 1.1 $
$Date: 2008-05-29 16:40:09 $
-->
<xsl:output method="xml" indent="yes"/>
<xsl:template name="i18n-add-a-new">
<!-- a string, presumed to be the name of a domain entity -->
<xsl:param name="entity-name"/>
<xsl:value-of select="concat( 'Add a new ', $entity-name)"/>
</xsl:template>
<xsl:template name="i18n-bad-format">
<!-- a string, presumed to be the name of a format definition -->
<xsl:param name="format-name"/>
<xsl:value-of select="concat( 'Does not meet the format requirements for', $format-name)"/>
</xsl:template>
<xsl:template name="i18n-command-not-found">
<xsl:param name="command"/>
<xsl:choose>
<xsl:when test="$command">
<xsl:value-of select="concat( 'Unrecognised command ', $command)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'No command?'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="i18n-delete-prompt">
<xsl:value-of select="'To delete this record'"/>
</xsl:template>
<xsl:template name="i18n-indefinite-article">
<!-- a string, presumed to be a noun - e.g. the name of a domain entity -->
<xsl:param name="noun"/>
<xsl:variable name="initial" select="substring( $noun, 1, 1)"/>
<xsl:choose>
<xsl:when test="$initial = 'A' or $initial = 'a'">
<xsl:value-of select="concat( 'an ', $noun)"/>
</xsl:when>
<xsl:when test="$initial = 'E' or $initial = 'e'">
<xsl:value-of select="concat( 'an ', $noun)"/>
</xsl:when>
<xsl:when test="$initial = 'I' or $initial = 'i'">
<xsl:value-of select="concat( 'an ', $noun)"/>
</xsl:when>
<xsl:when test="$initial = 'O' or $initial = 'o'">
<xsl:value-of select="concat( 'an ', $noun)"/>
</xsl:when>
<xsl:when test="$initial = 'U' or $initial = 'u'">
<xsl:value-of select="concat( 'an ', $noun)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat( 'a ', $noun)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="i18n-list">
<!-- a string, presumed to be the name of a domain entity -->
<xsl:param name="entity-name"/>
<xsl:variable name="plural">
<xsl:call-template name="i18n-plural">
<xsl:with-param name="noun" select="entity-name"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="concat( 'List', $plural)"/>
</xsl:template>
<!-- English-laguage syntactic sugar of entity name -->
<xsl:template name="i18n-plural">
<!-- a string, presumed to be a noun -->
<xsl:param name="noun"/>
<xsl:choose>
<xsl:when test="$noun='Person'">People</xsl:when>
<!-- add other special cases here -->
<xsl:when test="starts-with( substring($noun, string-length($noun) ), 's')">
<xsl:value-of select="concat( $noun, 'es')"/>
</xsl:when>
<xsl:when test="starts-with( substring($noun, string-length($noun) ), 'y')">
<xsl:value-of select="concat( substring( $noun, string-length($noun)), 'ies')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat( $noun, 's')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- the 'really delete' message, used in two-phase delete process -->
<xsl:template name="i18n-really-delete">
<xsl:value-of select="'Really delete'"/>
</xsl:template>
<!-- the 'cancel delete' message, used in two-phase delete process -->
<xsl:template name="i18n-really-delete-no">
<xsl:value-of select="'No, do not delete it'"/>
</xsl:template>
<!-- the 'confirm delete' message, used in two-phase delete process -->
<xsl:template name="i18n-really-delete-yes">
<xsl:value-of select="'Yes, do delete it'"/>
</xsl:template>
<xsl:template name="i18n-record-not-found">
<xsl:param name="entity-name"/>
<xsl:value-of select="concat( 'No record of type ', $entity-name, ' with the key values supplied was found')"/>
</xsl:template>
<xsl:template name="i18n-record-not-saved">
<xsl:value-of select="'Record not saved'"/>
</xsl:template>
<xsl:template name="i18n-record-saved">
<xsl:value-of select="'Record saved successfully'"/>
</xsl:template>
<xsl:template name="i18n-save-prompt">
<xsl:value-of select="'To save this record'"/>
</xsl:template>
<xsl:template name="i18n-value-defined">
<!-- a string, presumed to be the name of a property -->
<xsl:param name="property-name"/>
<!-- a string, presumed to be the name of a defined type -->
<xsl:param name="definition-name"/>
<xsl:variable name="aoran">
<xsl:call-template name="i18n-indefinite-article">
<xsl:with-param name="noun" select="$definition-name"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="concat( 'The value for ', $property-name, ' must be ', $aoran)"/>
</xsl:template>
<xsl:template name="i18n-value-entity">
<!-- a string, presumed to be the name of a property -->
<xsl:param name="property-name"/>
<!-- a string, presumed to be the name of a domain entity -->
<xsl:param name="entity-name"/>
<xsl:variable name="aoran">
<xsl:call-template name="i18n-indefinite-article">
<xsl:with-param name="noun" select="$entity-name"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="concat( 'The value for ', $property-name, ' must be ', $aoran)"/>
</xsl:template>
<xsl:template name="i18n-value-required">
<!-- a string, presumed to be the name of a property -->
<xsl:param name="property-name"/>
<xsl:value-of select="concat( 'You must provide a value for', $property-name)"/>
</xsl:template>
<xsl:template name="i18n-value-type">
<!-- a string, presumed to be the name of a property -->
<xsl:param name="property-name"/>
<!-- a string, presumed to be the name of a type -->
<xsl:param name="type-name"/>
<xsl:variable name="aoran">
<xsl:call-template name="i18n-indefinite-article">
<xsl:with-param name="noun" select="$type-name"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="concat( 'The value for ', $property-name, ' must be ', $aoran)"/>
</xsl:template>
</xsl:stylesheet>

View file

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xslo="http://www.w3.org/1999/XSL/TransformAlias"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<!--
Application Description Language framework
localise-transform.xslt
(c) 2007 Cygnet Solutions Ltd
Highly experiemental.
It is not possible in XSLT to do conditional includes, so you can't do, for example
<xsl:include href="concat( 'i18n-', $locale, '-include.xslt')"/>
The object of this file is to take an xslt transform and rewrite the localisation
for the specified locale, passing everything else through unaltered.
$Author: sb $
$Revision: 1.1 $
$Date: 2008-05-29 16:40:09 $
-->
<xsl:namespace-alias stylesheet-prefix="xslo" result-prefix="xsl"/>
<xsl:output method="xml" indent="yes"/>
<!-- The locale for which the localised transforms are generated. -->
<xsl:param name="locale" select="en-GB"/>
<!-- in practice, en-GB is our default locale for now -->
<xsl:template match="xsl:include[href='i18n-en-GB-include.xslt']">
<xslo:include>
<xsl:attribute name="href">
<xsl:value-of select="concat( 'i18n-', $locale, '-include.xslt')"/>
</xsl:attribute>
</xslo:include>
</xsl:template>
<!-- if this works, we may use a magic token in the master file(s) -->
<xsl:template match="xsl:include[href='replace-with-localisation-include-name']">
<xslo:include>
<xsl:attribute name="href">
<xsl:value-of select="concat( 'i18n-', $locale, '-include.xslt')"/>
</xsl:attribute>
</xslo:include>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

View file

@ -1,15 +0,0 @@
<types>
<type name="Integer-32" dotnet="Int32" sql="INTEGER" dotnet-kind="value" default="0" />
<type name="Real-64" dotnet="Double" sql="REAL" dotnet-kind="value" default="0.0"/>
<type name="Boolean" dotnet="Boolean" sql="BIT" dotnet-kind="value" default="false"/>
<type name="DateTime" dotnet="DateTime" sql="DATETIME" dotnet-kind="value" />
<type name="Date" dotnet="DateTime" sql="DATETIME" dotnet-kind="value" />
<type name="Time" dotnet="TimeSpan" sql="DECIMAL" dotnet-kind="value" />
<type name="Money" dotnet="Decimal" sql="MONEY" dotnet-kind="value" />
<type name="String" dotnet="String" sql="NVARCHAR" dotnet-kind="reference" />
<typedef name="Integer" type="Integer-32" />
<typedef name="Real" type="Real-64" />
</types>

View file

@ -1,74 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://cygnets.co.uk/schemas/adl-1.2"
xmlns:a="http://cygnets.co.uk/schemas/adl-1.2"
exclude-result-prefixes="a">
<!--
Application Description Framework
types.xslt
(c) 2008 Cygnet Solutions Ltd
Deals with looking up type information.
$Author: af $
$Revision: 1.1 $
-->
<xsl:output indent="yes" method="xml" encoding="utf-8"/>
<!-- Convenience (if you can use that word with XSLT) to obtain a type name. -->
<xsl:template name="type-name">
<xsl:call-template name="type-attr">
<xsl:with-param name="attr" select="'name'" />
</xsl:call-template>
</xsl:template>
<!-- Retrieve a particular attribute from a type, possibly recursively through typedefs. -->
<xsl:template name="type-attr">
<xsl:param name="attr"/>
<!-- The attribute we want-->
<xsl:choose>
<xsl:when test="name()='type'">
<xsl:value-of select="@*[name()=$attr]"/>
</xsl:when>
<!-- Can we can resolve this immediately? -->
<xsl:when test="$attr!='name' and @*[name()=$attr]">
<xsl:value-of select="@*[name()=$attr]"/>
</xsl:when>
<!-- Otherwise look it up in the referred type -->
<xsl:otherwise>
<xsl:variable name="typename" select="@type" />
<xsl:choose>
<!-- Look up in the source document -->
<xsl:when test="/a:application/a:type[@name=$typename]|/a:application/a:typedef[@name=$typename]">
<xsl:for-each select="/a:application/a:type[@name=$typename]|/a:application/a:typedef[@name=$typename]">
<xsl:call-template name="type-attr">
<xsl:with-param name="attr" select="$attr"/>
</xsl:call-template>
</xsl:for-each>
</xsl:when>
<!-- Look up in global types.xml -->
<xsl:when test="document('types.xml')/types/*[@name=$typename]">
<xsl:for-each select="document('types.xml')/types/*[@name=$typename]">
<xsl:call-template name="type-attr">
<xsl:with-param name="attr" select="$attr"/>
</xsl:call-template>
</xsl:for-each>
</xsl:when>
<!-- Cannot find the type -->
<xsl:otherwise>
<xsl:message terminate="yes">
Cannot find type "<xsl:value-of select="$typename"/>".
</xsl:message>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>