adl/resources/schemas/adl-1.4.rnc

546 lines
23 KiB
Plaintext

# ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
#
# adl-1.4.dtd
#
# Purpose:
# Document Type Description for Application Description
# 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
#
# ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# $Revision: 1.5 $
# ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# Before we start: import XHTML for use in documentation sections
# ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# Before we start: some useful definitions
# ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# some basic character entities inherited from HTML. Actually we probably ought to
# import all the HTML4 character entity files, and possibly the HTML4 Strict DTD (so
# that we can allow HTML block level entities within content elements
# boolean means true or false
Boolean = "true" | "false"
# Locale is a string comprising an ISO 639 language code followed by a space
# followed by an ISO 3166 country code, or else the string 'default'. See:
# <URL:http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt>
# <URL:http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html>
Locale = string
# permissions a group may have on an entity, list, page, form or field
# permissions are deemed to increase as you go right. A group cannot
# have greater permission on a field than on the form it is in, or
# greater permission on form than the entity it belongs to
#
# none: none
# read: select
# insert: insert
# noedit: select, insert
# edit: select, insert, update
# all: select, insert, update, delete
Permissions = "none" | "read" | "insert" | "noedit" | "edit" | "all"
# actions which should be cascaded to dependent objects. All these values except
# 'manual' are taken from Hibernate and should be passed through the adl2hibernate
# mapping transparently. Relevent only for properties with type='entity', type='link'
# and type='list'
#
# all : cascade delete, save and update
# all-delete-orphan : see hibernate documentation; relates to transient objects only
# delete : cascade delete actions, but not save and update
# manual : cascading will be handled in manually managed code, code to
# handle cascading should not be generated
# save-update : cascade save and update actions, but not delete.
CascadeActions =
"all" | "all-delete-orphan" | "delete" | "manual" | "save-update"
# data types which can be used in a typedef to provide validation -
# e.g. a string can be used with a regexp or a scalar can be used with
# min and max values
# string: varchar java.sql.Types.VARCHAR
# integer: int java.sql.Types.INTEGER
# real: double java.sql.Types.DOUBLE
# money: money java.sql.Types.INTEGER
# date: date java.sql.Types.DATE
# time: time java.sql.Types.TIME
# timestamp: timestamp java.sql.Types.TIMESTAMP
# uploadable: varchar java.sql.Types.VARCHAR
# image: varchar java.sql.Types.VARCHAR
#
# uploadable is as string but points to an uploaded file; image is as
# uploadable but points to an uploadable graphical image file
DefinableDataTypes =
"string"
| "integer"
| "real"
| "money"
| "date"
| "time"
| "timestamp"
| "uploadable"
# data types which are fairly straightforward translations of JDBC data types
# boolean: boolean or java.sql.Types.BIT
# char(1) java.sql.Types.CHAR
# text: text or java.sql.Types.LONGVARCHAR
# memo java.sql.Types.CLOB
SimpleDataTypes = DefinableDataTypes | "boolean" | "text"
# data types which are more complex than SimpleDataTypes...
# entity : a foreign key link to another entity (i.e. the 'many' end of a
# one-to-many link);
# list : a list of some other entity that links to me (i.e. the 'one' end of
# a one-to-many link);
# link : a many to many link (via a link table);
# defined : a type defined by a typedef.
ComplexDataTypes = "entity" | "link" | "list" | "defined"
# data types which require special handling - which don't simply map onto
# common SQL data types
# geopos : a latitude/longitude pair (experimental and not yet implemented)
# image : a raster image file, in jpeg|gif|png format (experimental, not yet implemented)
# message : an internationalised message, having different translations for different locales
SpecialDataTypes = "geopos" | "image" | "message"
# all data types
AllDataTypes = ComplexDataTypes | SimpleDataTypes | SpecialDataTypes
# content, for things like pages (i.e. forms, lists, pages)
Content = head | top | foot
FieldStuff = field | fieldgroup | auxlist | verb
PageContent = Content | FieldStuff
PageStuff = PageContent | permission | pragma
# Properties for pages:
# name: obviously, the name (URL stub) of the page
# properties: the properties of the entity the page describes to be shown
# as fields on the page
# all: obviously, all properties (except the abstract primary key, if
# present)
# user-distinct: all properties which are user-distinct (NOTE: Not yet implemented)
# listed: only those properties for which fields are explicitly listed
PageAttrs =
attribute name { text },
attribute properties { "all" | "user-distinct" | "listed" }
# Actions for generators (mainly for keyfields - see entity 'generator', below
# assigned: In manually-maintained code, you contract to assign a value
# to this property before it is persisted.
# guid: The system will supply a unique GUid value to this field
# before it is persisted.
# mannual: You contract to supply a generatos class in manually maintained
# code.
# native: The database will supply a unique value to this field when it
# is persisted; the value will be an integer. RECOMMENDED!
GeneratorActions = "assigned" | "guid" | "manual" | "native"
# sequences for orderings of lists - see entity 'order'
# canonical: Whatever the normal canonical ordering for this datatype is -
# typically alpha-numeric, except for dates, etc.
# reverse-canonical: The reverse of the above
#
# possibly there should be some further values but I have no idea what these are
Sequences = "canonical" | "reverse-canonical"
# ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# Elements
# ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# the application that the document describes: required top level element
#
# name: the name of this application
# version: the version number of this application
# revision: the revision of the ADL document
# currency: the base monetary currency, in the form of an ISO 4217 three-letter code
# xmlns: XML namespace, in case required
application =
element application {
attlist.application,
specification*,
documentation?,
content?,
typedef*,
group*,
entity*
}
attlist.application &=
attribute name { text },
attribute version { text }?,
attribute revision { text }?,
attribute currency { text }?
# 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)
typedef =
element typedef {
attlist.typedef, documentation?, in-implementation*, help*
}
attlist.typedef &=
attribute name { text },
attribute type { DefinableDataTypes }?,
attribute size { text }?,
attribute pattern { text }?,
attribute minimum { text }?,
attribute maximum { text }?
# 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...
in-implementation =
element in-implementation {
attlist.in-implementation, documentation?
}
attlist.in-implementation &=
attribute target { text },
attribute value { text },
attribute kind { text }?
# 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
group = element group { attlist.group, documentation? }
attlist.group &=
attribute name { text },
attribute parent { text }?
# 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
entity =
element entity {
attlist.entity,
documentation?,
prompt*,
content?,
key?,
property*,
permission*,
(form | page | \list)*
}
attlist.entity &=
attribute name { text },
attribute natural-key { text }?,
attribute table { text }?,
attribute foreign { Boolean }?
# contains documentation on the element which immediately contains it. TODO:
# should HTML markup within a documentation element be allowed? If so, are
# there restrictions?
documentation =
element documentation { attlist.documentation, (text | reference)* }
attlist.documentation &= empty
# an explicit primary key, possibly compound
key = element key { attlist.key, property* }
attlist.key &= empty
# 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').
# immutable: if true, once a value has been set it cannot be changed.
# 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. 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
property =
element property {
attlist.property,
documentation?,
generator?,
(permission | option | prompt | help | ifmissing)*
}
attlist.property &=
attribute name { text },
attribute type { AllDataTypes },
attribute default { text }?,
attribute typedef { text }?,
attribute distinct { "none" | "all" | "user" | "system" }?,
attribute entity { text }?,
attribute farkey { text }?,
attribute required { Boolean }?,
attribute immutable { Boolean }?,
attribute size { text }?,
attribute column { text }?,
attribute concrete { Boolean }?,
attribute cascade { CascadeActions }?
# 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
generator =
element generator { attlist.generator, documentation?, param* }
attlist.generator &=
attribute action { GeneratorActions },
attribute class { text }?
# 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
#
# TODO: This needs to be renamed or removed because it conflicts with the
# XHTML element of the same name. In fact it could be simply removed since
# our usage is compatible with the XHTML usage, but it might be less
# ambiguous to rename it.
param = element param { attlist.param, text }
attlist.param &= attribute name { text }
# 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
#
# TODO: This needs to be renamed or removed because it conflicts with the
# XHTML element of the same name. In fact it could be simply removed since
# our usage is compatible with the XHTML usage, but it might be less
# ambiguous to rename it.
option = element option { attlist.option, documentation?, prompt* }
# if the value is different from the prompt the user sees, specify it
attlist.option &= attribute value { text }?
# 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
permission = element permission { attlist.permission, documentation? }
attlist.permission &=
attribute group { text },
attribute permission { Permissions }
# 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.
pragma = element pragma { attlist.pragma, documentation? }
attlist.pragma &=
attribute name { text },
attribute value { text }
# a prompt for a property or field; used as the prompt text for a widget
# which edits it. Typically there will be only 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
prompt = element prompt { attlist.prompt, documentation? }
attlist.prompt &=
attribute prompt { text },
attribute locale { Locale }
# helptext about a property of an entity, or a field of a page, form or
# list, or a typedef. Typically there will be only 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
help = element help { attlist.help, text }
attlist.help &= attribute locale { Locale }
# helpful text to be shown if a property value is missing, typically when
# a form is submitted. Typically there will be only 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.
ifmissing = element ifmissing { attlist.ifmissing, text }
attlist.ifmissing &= attribute locale { Locale }
# a form through which an entity may be added or edited
#
# TODO: This needs to be renamed because it conflicts with the
# XHTML element of the same name.
form = element form { attlist.form, documentation?, PageStuff* }
attlist.form &= PageAttrs
# a page on which an entity may be displayed
page = element page { attlist.page, documentation?, PageStuff* }
attlist.page &= PageAttrs
# an ordering or records in a list
# property: the property on which to order
# sequence: the sequence in which to order
order = element order { attlist.order, documentation? }
attlist.order &=
attribute property { text },
attribute sequence { Sequences }?
# 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
\list =
element list { attlist.list, documentation?, (PageStuff | order)* }
attlist.list &=
PageAttrs,
attribute onselect { text }?
# 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
auxlist =
element auxlist {
attlist.auxlist, documentation?, (prompt | FieldStuff)*
}
attlist.auxlist &=
PageAttrs,
attribute property { text },
attribute onselect { text }?,
attribute canadd { Boolean }?
# 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.
fieldgroup =
element fieldgroup {
attlist.fieldgroup,
documentation?,
(prompt | permission | FieldStuff)*
}
attlist.fieldgroup &= attribute name { text }
# a field in a form or page
#
# property: the property which this field displays/edits
field =
element field {
attlist.field, documentation?, (prompt | help | permission)*
}
attlist.field &= attribute property { text }
# 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
verb =
element verb {
attlist.verb, documentation?, (prompt | help | permission)*
}
attlist.verb &=
attribute verb { text },
attribute dangerous { Boolean }
# a container for global content
content = element content { attlist.content, Content* }
attlist.content &= empty
# 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)
#
# TODO: This needs to be renamed or removed because it conflicts with the
# XHTML element of the same name. In fact it could be simply removed since
# our usage is compatible with the XHTML usage, but it might be less
# ambiguous to rename it.
head = element head { attlist.head, text }
attlist.head &= empty
# 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.
top = element top { attlist.top, text }
attlist.top &= empty
# 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.
foot = element foot { attlist.foot, text }
attlist.foot &= empty
# The 'specification' and 'reference' elements are for documentation only,
# and do not contribute to the engineering of the application described.
#
# A specification element is intended chiefly to declare the reference
# documents which may be used in documentation elements later in the
# document.
#
# url: The URL from which the document referenced can be retrieved
# name: The full name (title) given to this document
# abbr: A convenient abbreviated name
specification =
element specification {
attlist.specification, documentation?, reference*
}
attlist.specification &=
attribute url { text }?,
attribute name { text },
attribute abbr { text }
# The 'specification' and 'reference' elements are for documentation only,
# and do not contribute to the engineering of the application described.
#
# A reference element is a reference to a specifying document.
#
# abbr: The abbreviated name of the specification to which this
# reference refers
# section: The 'anchor part' (part following a hash character) which,
# when appended to the URL, will locate the exact section
# referenced.
# entity: A reference to another entity within this ADL document
# property: A reference to another property within this ADL document;
# if entity is also specified then of that entity, else of
# the ancestor entity if any
reference = element reference { attlist.reference, documentation? }
attlist.reference &=
attribute abbr { text }?,
attribute section { text }?,
attribute entity { text }?,
attribute property { text }?
start = application