Parallel track on transform development. Currently 'transforms' work, but not with a version of ADL which is formalisable, documented specified; and 'transforms01' very nearly work on a vocabulary which is very nearly as rich as 'transforms' but which is formalised, specified and documented.

This commit is contained in:
sb 2008-01-31 17:06:35 +00:00
parent 98756d2211
commit eba7fa3afb
7 changed files with 3702 additions and 0 deletions

View file

@ -0,0 +1,539 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
C1873 SRU Hospitality
adl2controllerclasses.xsl
(c) 2007 Cygnet Solutions Ltd
Transform ADL into (partial) controller classes
$Author: sb $
$Revision: 1.1 $
$Date: 2008-01-31 17:06:35 $
-->
<!-- WARNING WARNING WARNING: Do NOT reformat this file!
Whitespace (or lack of it) is significant! -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="UTF-8" method="text"/>
<!-- The locale for which these controllers are generated
TODO: Controllers should NOT be locale specific. Instead, the
controller should render views and generate messages based on the
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="locale" select="en-UK"/>
<!-- The C# namespace within which I shall generate controllers -->
<xsl:param name="controllerns" select="Unset"/>
<!-- The C# namespace used by the entities for this project -->
<xsl:param name="entityns" select="Unset"/>
<xsl:template match="application">
<xsl:apply-templates select="entity"/>
</xsl:template>
<xsl:template match="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 -->
<xsl:variable name="transform-rev1"
select="substring( '$Revision: 1.1 $', 11)"/>
<xsl:variable name="transform-revision"
select="substring( $transform-rev1, 0, string-length( $transform-rev1) - 1)"/>
<xsl:variable name="key">
<xsl:call-template name="primary-key">
<xsl:with-param name="entityname" select="@name"/>
</xsl:call-template>
</xsl:variable>
/* ---- [ cut here: next file '<xsl:value-of select="@name"/>Controller.auto.cs'] ---------------- */
//------------------------------------------------------------------
//
// Application Description Framework
// <xsl:value-of select="@name"/>Controller.auto.cs
//
// (c) 2007 Cygnet Solutions Ltd
//
// Controller for auto-generated forms for editing <xsl:value-of select="@name"/>s
// Automatically generated from application description using
// adl2controllerclass.xsl version <xsl:value-of select="$transform-revision"/>
//
// This file is automatically generated; DO NOT EDIT IT.
//
//------------------------------------------------------------------
using System;
using System.Data;
using System.Collections.Generic;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using Castle.MonoRail.Framework.Helpers;
using Cygnet.Web.Helpers;
using Cygnet.Web.Controllers;
using NHibernate;
using NHibernate.Expression;
using Castle.MonoRail.Framework;
using Cygnet.Exceptions;
using Iesi.Collections.Generic;
using SRU.Hospitality.Helpers;
using SRU.Hospitality.Entities;
namespace <xsl:value-of select="$controllerns"/> {
/// &lt;summary&gt;
/// Automatically generated partial controller class following 'thin controller'
/// strategy, for entity <xsl:value-of select="@name"/>. Note that part of this
/// class may be defined in a separate file called
/// <xsl:value-of select="@name"/>Controller.manual.cs, q.v.
///
/// DO NOT EDIT THIS FILE!
/// &lt;/summary&gt;
public partial class <xsl:value-of select="@name"/>Controller : BaseController {
/// &lt;summary&gt;
/// Store the record represented by the parameters passed in an HTTP service
/// Without Id -&gt; it's new, I create a new persistent object;
/// With Id -&gt; it's existing, I update the existing persistent object.
/// NOTE: Should only be called from a handler for method 'POST', never 'GET'.
/// &lt;/summary&gt;
private void Store()
{
ISession hibernator =
NHibernateHelper.GetCurrentSession( Session[ NHibernateHelper.USERTOKEN],
Session[NHibernateHelper.PASSTOKEN]);
List&lt;string&gt; messages = new List&lt;string&gt;();
<xsl:value-of select="$entityns"/>.<xsl:value-of select="@name"/> record;
<xsl:apply-templates select="property"/>
string id = Form["<xsl:value-of select="concat( 'instance.', $key)"/>"];
if ( String.IsNullOrEmpty( id))
{
/* it's new, create persistent object */
record = new <xsl:value-of select="$entityns"/>.<xsl:value-of select="@name"/>(<xsl:for-each select="property[@distinct='system']">Form[<xsl:value-of select="concat( 'instance.', @name)"/>]<xsl:choose>
<xsl:when test="position() = last()"/>
<xsl:otherwise>, </xsl:otherwise>
</xsl:choose>
</xsl:for-each>);
/* perform any domain knowledge behaviour on the new record
* after instantiation */
record.AfterCreationHook( hibernator);
messages.Add( "New <xsl:value-of select="@name"/> record created");
}
else
{
/* it's existing, retrieve it */
record =
hibernator.CreateCriteria(typeof(<xsl:value-of select="@name"/>))
.Add(Expression.Eq("<xsl:value-of select="$key"/>", Int32.Parse(id)))
.UniqueResult&lt;<xsl:value-of select="$entityns"/>.<xsl:value-of select="@name"/>&gt;();
}
if ( record != null)
{
try
{
/* actually update the record */
BindObjectInstance( record, ParamStore.Form, "instance");
<xsl:for-each select="property[@type='entity']">
/* for properties of type 'entity', it should not be necessary to do anything
* special - BindObjectInstance /should/ do it all. Unfortunately it sometimes
* doesn't, and I haven't yet characterised why not. TODO: Fix this! */
record.<xsl:value-of select="@name"/> =
hibernator.CreateCriteria(typeof(<xsl:value-of select="@entity"/>))
.Add(Expression.Eq("<xsl:call-template name="primary-key">
<xsl:with-param name="entityname" select="@entity"/>
</xsl:call-template>", Int32.Parse(Form["<xsl:value-of select="concat( 'instance.', @name)"/>"])))
.UniqueResult&lt;<xsl:value-of select="$entityns"/>.<xsl:value-of select="@entity"/>&gt;();
</xsl:for-each>
<xsl:for-each select="property[@type='link']">
/* to update a link table which has no other data than the near and far keys, it is
* sufficient to smash the existing values and create new ones. It's also a lot easier! */
string[] <xsl:value-of select="concat(@name, 'Values')"/> = Form.GetValues( "<xsl:value-of select="concat( 'instance.', @name)"/>");
if ( <xsl:value-of select="concat(@name, 'Values')"/> != null)
{
/* update the linking table for my <xsl:value-of select="@name"/>; first smash the old values */
if ( <xsl:value-of select="concat( 'record.', @name)"/> != null)
{
<xsl:value-of select="concat( 'record.', @name)"/>.Clear();
}
else
{
<xsl:value-of select="concat( 'record.', @name)"/> = new HashedSet&lt;<xsl:value-of select="@entity"/>&gt;();
}
/* then reinstate the values from the indexes passed */
foreach ( string index in <xsl:value-of select="concat(@name, 'Values')"/>)
{
<!-- todo: won't work for entities having natural keys -->
<xsl:value-of select="concat( 'record.', @name)"/>.Add(
hibernator.CreateCriteria(typeof(<xsl:value-of select="@entity"/>))
.Add(Expression.Eq("<xsl:value-of select="@entity"/>Id", Int32.Parse(index)))
.UniqueResult&lt;<xsl:value-of select="$entityns"/>.<xsl:value-of select="@entity"/>&gt;());
}
}
</xsl:for-each>
<xsl:for-each select="property[@type='list']">
/* with a list we cannot just smash the old values! Instead we need to check
* each one and exclude it if no longer required */
if ( Form.GetValues( "<xsl:value-of select="concat( 'instance.', @name)"/>") != null)
{
string[] <xsl:value-of select="concat(@name, 'Values')"/> = Form.GetValues( "<xsl:value-of select="concat( 'instance.', @name)"/>");
/* updating <xsl:value-of select="@name"/> child records; first remove any not on the submitted list */
foreach ( <xsl:value-of select="@entity"/> item in record.<xsl:value-of select="@name"/>)
{
String itemId = item.Key.ToString();
bool found = false;
foreach ( string index in <xsl:value-of select="concat(@name, 'Values')"/>)
{
<!-- TODO: this could definitely be made more efficient -->
if ( index.Equals( itemId))
{
found = true;
}
}
if ( ! found)
{
record.<xsl:value-of select="@name"/>.Remove( item);
}
}
/* then add any on the included list which are not already members */
foreach ( string index in <xsl:value-of select="concat(@name, 'Values')"/>)
{
<xsl:value-of select="@entity"/> item =
hibernator.CreateCriteria(typeof(<xsl:value-of select="@entity"/>))
.Add(Expression.Eq("<xsl:value-of select="@entity"/>Id", Int32.Parse(index)))
.UniqueResult&lt;<xsl:value-of select="$entityns"/>.<xsl:value-of select="@entity"/>&gt;();
if ( ! record.<xsl:value-of select="@name"/>.Contains( item))
{
record.<xsl:value-of select="@name"/>.Add( item);
}
}
}
</xsl:for-each>
/* perform any domain knowledge behaviour on the record prior to updating */
record.BeforeUpdateHook( hibernator);
/* write the record to the database, in order to guarantee we have a valid key */
hibernator.Save(record);
hibernator.Flush();
/* perform any domain knowledge behaviour on the record after updating */
record.AfterUpdateHook( hibernator);
messages.Add( "Record saved successfully");
}
catch ( DataSuitabilityException dse)
{
AddError( dse.Message);
}
catch ( ApplicationException axe)
{
AddError( axe.Message);
}
PropertyBag["messages"] = messages;
PropertyBag["username"] = Session[ NHibernateHelper.USERTOKEN];
PropertyBag["instance"] = record;
<xsl:call-template name="menus">
<xsl:with-param name="entity" select="."/>
</xsl:call-template>
RenderViewWithFailover("<xsl:value-of select="concat( form[position()=1]/@name, '.vm')"/>", "<xsl:value-of select="concat( form[position()=1]/@name, '.auto.vm')"/>");
}
else
{
throw new Exception( String.Format( "No record of type <xsl:value-of select="@name"/> with key value {0} found", id));
}
}
/// &lt;summary&gt;
/// Actually delete the selected record
/// &lt;/summary&gt;
[AccessibleThrough(Verb.Get)]
public void Delete()
{
ISession hibernator =
NHibernateHelper.GetCurrentSession( Session[ NHibernateHelper.USERTOKEN],
Session[NHibernateHelper.PASSTOKEN]);
string id = Params["<xsl:value-of select="concat( 'instance.', $key)"/>"];
string reallydelete = Params["reallydelete"];
if ( "true".Equals( reallydelete))
{
<xsl:value-of select="@name"/> record =
hibernator.CreateCriteria(typeof(<xsl:value-of select="@name"/>))
.Add(Expression.Eq("<xsl:value-of select="$key"/>", Int32.Parse(id)))
.UniqueResult&lt;<xsl:value-of select="$entityns"/>.<xsl:value-of select="@name"/>&gt;();
if ( record != null)
{
record.BeforeDeleteHook( hibernator);
hibernator.Delete(
hibernator.CreateCriteria(typeof(<xsl:value-of select="@name"/>))
.Add(Expression.Eq("<xsl:value-of select="$key"/>", Int32.Parse(id)))
.UniqueResult&lt;<xsl:value-of select="$entityns"/>.<xsl:value-of select="@name"/>&gt;());
hibernator.Flush();
}
else
{
throw new ApplicationException( "No such record?");
}
}
<xsl:choose>
<xsl:when test="list">
InternalShowList();
</xsl:when>
<xsl:otherwise>
Redirect( FormsAuthentication.DefaultUrl);
</xsl:otherwise>
</xsl:choose>
}
<xsl:apply-templates select="form"/>
<xsl:if test="list">
<xsl:variable name="listname" select="list[position()=1]/@name"/>
<xsl:apply-templates select="list"/>
/// &lt;summary&gt;
/// list all instances of this entity to allow the user to select one for editing
/// this method invokes the default list view - which is probably what you want unless
/// you've a special reason for doing something different
/// &lt;/summary&gt;
public void InternalShowList()
{
InternalShowList( "<xsl:value-of select="$listname"/>");
}
/// &lt;summary&gt;
/// list all instances of this entity to allow the user to select one for editing
/// &lt;/summary&gt;
/// &lt;param name="view"&gt;The name of the list view to show&lt;/param&gt;
public void InternalShowList( String view)
{
ISession hibernator =
NHibernateHelper.GetCurrentSession( Session[ NHibernateHelper.USERTOKEN],
Session[NHibernateHelper.PASSTOKEN]);
IList&lt;<xsl:value-of select="@name"/>&gt; instances =
hibernator.CreateCriteria(typeof(<xsl:value-of select="@name"/>))<xsl:for-each select="property[@distinct='user']">
<xsl:value-of select="concat( '.AddOrder( new Order( &#34;', @name, '&#34;, true))')"/>
</xsl:for-each>.List&lt;<xsl:value-of select="@name"/>&gt;();
PropertyBag["username"] = Session[ NHibernateHelper.USERTOKEN];
PropertyBag["instances"] =
PaginationHelper.CreatePagination( this, instances, 25);
RenderViewWithFailover(view + ".vm", view + ".auto.vm");
}
</xsl:if>
}
}
</xsl:template>
<xsl:template match="property[@required='true']">
if ( Form[ "<xsl:value-of select="concat( 'instance.', @name)"/>" ] == null)
{
AddError( <xsl:choose>
<xsl:when test="ifmissing[@locale=$locale]">
<xsl:apply-templates select="ifmissing[@locale=$locale]"/>
</xsl:when>
<xsl:otherwise>"You must supply a value for <xsl:value-of select="@name"/>"</xsl:otherwise>
</xsl:choose>);
}
</xsl:template>
<!-- suppress properties otherwise -->
<xsl:template match="property"/>
<xsl:template match="ifmissing">
"<xsl:value-of select="normalize-space(.)"/>"
</xsl:template>
<xsl:template match="form">
<xsl:variable name="key">
<xsl:choose>
<xsl:when test="../@natural-key">
<xsl:value-of select="../@natural-key"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat( ../@name, 'Id')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
/// &lt;summary&gt;
/// Handle the submission of the form named <xsl:value-of select="@name"/>
/// &lt;/summary&gt;
[AccessibleThrough(Verb.Post)]
public void <xsl:value-of select="concat( @name, 'SubmitHandler')"/>( )
{
string command = Form[ "command"];
if ( command == null)
{
throw new Exception( "No command?");
}
else
<xsl:for-each select=".//verb">
if ( command.Equals( "<xsl:value-of select="@verb"/>"))
{
/* NOTE: You must write an implementation of this verb in a
manually maintained partial class file for this class */
<xsl:value-of select="@verb"/>();
}
else
</xsl:for-each>
if ( command.Equals( "delete"))
{
ISession hibernator =
NHibernateHelper.GetCurrentSession( Session[ NHibernateHelper.USERTOKEN],
Session[NHibernateHelper.PASSTOKEN]);
string id = Form["<xsl:value-of select="concat( 'instance.', $key)"/>"];
PropertyBag["username"] = Session[ NHibernateHelper.USERTOKEN];
PropertyBag["instance"] =
hibernator.CreateCriteria(typeof(<xsl:value-of select="../@name"/>))
.Add(Expression.Eq("<xsl:value-of select="$key"/>", Int32.Parse(id)))
.UniqueResult&lt;<xsl:value-of select="$entityns"/>.<xsl:value-of select="../@name"/>&gt;();
RenderViewWithFailover( "maybedelete.vm", "maybedelete.auto.vm");
}
else if ( command.Equals( "store"))
{
Store();
}
else
{
throw new Exception( String.Format("Unrecognised command '{0}'", command));
}
}
/// &lt;summary&gt;
/// Show the form named <xsl:value-of select="@name"/>, with no content
/// &lt;/summary&gt;
[AccessibleThrough(Verb.Get)]
public void <xsl:value-of select="@name"/>( )
{
ISession hibernator =
NHibernateHelper.GetCurrentSession( Session[ NHibernateHelper.USERTOKEN],
Session[NHibernateHelper.PASSTOKEN]);
<xsl:call-template name="menus">
<xsl:with-param name="entity" select=".."/>
</xsl:call-template>
PropertyBag["username"] = Session[ NHibernateHelper.USERTOKEN];
RenderViewWithFailover("<xsl:value-of select="concat( @name, '.vm')"/>", "<xsl:value-of select="concat( @name, '.auto.vm')"/>");
}
/// &lt;summary&gt;
/// Show the form named <xsl:value-of select="@name"/>, containing the indicated record
/// &lt;/summary&gt;
/// &lt;param name="<xsl:value-of select="concat( ../@name, 'Id')"/>"&gt;the key value of the record to show&lt;/param&gt;
[AccessibleThrough(Verb.Get)]
public void <xsl:value-of select="@name"/>( Int32 <xsl:value-of select="concat( ../@name, 'Id')"/>)
{
ISession hibernator =
NHibernateHelper.GetCurrentSession( Session[ NHibernateHelper.USERTOKEN],
Session[NHibernateHelper.PASSTOKEN]);
<xsl:value-of select="$entityns"/>.<xsl:value-of select="../@name"/> record =
hibernator.CreateCriteria(typeof(<xsl:value-of select="../@name"/>))
.Add(Expression.Eq("<xsl:value-of select="concat( ../@name, 'Id')"/>", <xsl:value-of select="../@name"/>Id))
.UniqueResult&lt;<xsl:value-of select="$entityns"/>.<xsl:value-of select="../@name"/>&gt;();
PropertyBag["username"] = Session[ NHibernateHelper.USERTOKEN];
PropertyBag["instance"] = record;
<xsl:call-template name="menus">
<xsl:with-param name="entity" select=".."/>
</xsl:call-template>
RenderViewWithFailover("<xsl:value-of select="concat( @name, '.vm')"/>", "<xsl:value-of select="concat( @name, '.auto.vm')"/>");
}
</xsl:template>
<xsl:template match="list">
/// &lt;summary&gt;
/// list all instances of this entity to allow the user to select one
/// this method invokes the named view.
/// &lt;/summary&gt;
public void <xsl:value-of select="@name"/>()
{
InternalShowList( "<xsl:value-of select="@name"/>");
}
</xsl:template>
<xsl:template name="menus">
<xsl:param name="entity"/>
<xsl:for-each select="$entity/property[@type='entity']">
/* produce a list of <xsl:value-of select="@entity"/> to populate the menu for <xsl:value-of select="@name"/> */
<xsl:call-template name="menu">
<xsl:with-param name="property" select="."/>
</xsl:call-template>
</xsl:for-each>
<xsl:for-each select="$entity/property[@type='link']">
/* produce a list of <xsl:value-of select="@entity"/> to populate the LHS of the shuffle for <xsl:value-of select="@name"/> */
<xsl:call-template name="menu">
<xsl:with-param name="property" select="."/>
</xsl:call-template>
</xsl:for-each>
<xsl:for-each select="$entity/property[@type='list']">
/* produce a list of <xsl:value-of select="@entity"/> to populate the multi-select for <xsl:value-of select="@name"/> */
<xsl:call-template name="menu">
<xsl:with-param name="property" select="."/>
</xsl:call-template>
</xsl:for-each>
</xsl:template>
<xsl:template name="menu">
<xsl:param name="property"/>
<xsl:variable name="ename" select="$property/@entity"/>
<xsl:variable name="entity" select="//entity[@name=$ename]"/>
PropertyBag["<xsl:value-of select="concat('all_', $property/@name)"/>"] =
hibernator.CreateCriteria(typeof(<xsl:value-of select="$property/@entity"/>))<xsl:for-each select="$entity/property[@distinct='user']">
<xsl:value-of select="concat('.AddOrder( new Order( &#34;', @name, '&#34;, true))')"/>
</xsl:for-each>.List&lt;<xsl:value-of select="$property/@entity"/>&gt;();
</xsl:template>
<xsl:template name="primary-key">
<!-- return the name of the primary key of the entity with this name -->
<xsl:param name="entityname"/>
<xsl:choose>
<xsl:when test="//entity[@name=$entityname]/@natural-key">
<xsl:value-of select="//entity[@name=$entityname]/@natural-key"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat( $entityname, 'Id')" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

510
transforms01/adl2entityclass.xslt Executable file
View file

@ -0,0 +1,510 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
C1873 SRU Hospitality
adl2entityclass.xsl
(c) 2007 Cygnet Solutions Ltd
Transform ADL into entity classes
$Author: sb $
$Revision: 1.1 $
$Date: 2008-01-31 17:06:35 $
-->
<!-- WARNING WARNING WARNING: Do NOT reformat this file!
Whitespace (or lack of it) is significant! -->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
xmlns:adl="http://cygnets.co.uk/schemas/adl-1.2"
xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<xsl:output encoding="UTF-8" method="text"/>
<!-- The locale for which these entities are generated
TODO: Entities should NOT be locale specific. Instead, the
entity should generate messages based on the
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="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="adl:application">
<xsl:apply-templates select="adl:entity"/>
</xsl:template>
<xsl:template match="adl:entity">
<xsl:message terminate="no">Matched entity with name <xsl:value-of select="@name"/>
</xsl:message>
<!-- 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 -->
<xsl:variable name="transform-rev1"
select="substring( '$Revision: 1.1 $', 11)"/>
<xsl:variable name="transform-revision"
select="substring( $transform-rev1, 0, string-length( $transform-rev1) - 1)"/>
/* ---- [ cut here: next file '<xsl:value-of select="@name"/>.auto.cs'] ---------------- */
//-------------------------------------------------------------
//
// Application Description Framework
// <xsl:value-of select="@name"/>.auto.cs
//
// (c)2007 Cygnet Solutions Ltd
//
// Automatically generated from application description using
// adl2entityclass.xsl revision <xsl:value-of select="$transform-revision"/>
//
// This file is automatically generated; DO NOT EDIT IT.
//
//-------------------------------------------------------------
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.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 revision <xsl:value-of select="$transform-revision"/>.
/// 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;/remarks&gt;
public partial class <xsl:value-of select="@name"/> : Entity
{
/// &lt;summary&gt;
/// Auto-generated no-args constructor; does nothing (but probably should
/// ensure ID slot is initialised correctly)
/// &lt;/summary&gt;
public <xsl:value-of select="@name"/>() : base(){
<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">
/* composite promary 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: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>
/// &lt;summary&gt;
/// Auto-generated one-arg constructor; initialises Id slot and also all
/// one-to-many slots
/// &lt;/summary&gt;
public <xsl:value-of select="@name"/>( int key)
{
<xsl:call-template name="initialise-lists"/>
_<xsl:value-of select="@name"/>Id = key;
}
/// &lt;summary&gt;
/// Auto-generated iv for Id (abstract primary key) slot
/// &lt;/summary&gt;
private int _<xsl:value-of select="@name"/>Id = -1;
/// &lt;summary&gt;
/// Auto-generated property for Id (abstract primary key) slot
/// &lt;/summary&gt;
public virtual int <xsl:value-of select="@name"/>Id
{
get { return _<xsl:value-of select="@name"/>Id; }
set { _<xsl:value-of select="@name"/>Id = value; }
}
/// &lt;summary&gt;
/// Auto-generated overridden property for the Key slot, maps onto
/// _<xsl:value-of select="@name"/>Id
/// &lt;/summary&gt;
[Obsolete]
public override int Key
{
get { return _<xsl:value-of select="@name"/>Id; }
}
</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="@natural-key">
<xsl:variable name="key" select="@natural-key"/>
<xsl:choose>
<xsl:when test="adl:property[@name=$key]/@type = 'entity'">
<xsl:value-of select="concat( 'return ', adl:property[@name=$key]/@entity, '.KeyString;')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat( 'return ', $key, '.ToString();')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:when test="adl:key">
StringBuilder result = new StringBuilder();
<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:when>
<xsl:otherwise>
<xsl:value-of select="concat( 'return ', @name, 'Id.ToString();')"/>
</xsl:otherwise>
</xsl:choose>
}
}
/// &lt;summary&gt;
/// A user readable distinct identifying string
/// &lt;/summary&gt;
public override string UserIdentifier
{
get {
StringBuilder result = new StringBuilder();
<xsl:choose>
<xsl:when test="adl:property[@distinct='user']">
<xsl:for-each select="adl:property[@distinct='user']">
<xsl:choose>
<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! -->
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 -->
result.Append(<xsl:value-of select="concat( '_', @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 -->
result.Append(<xsl:value-of select="concat( '_', @name)"/>.ToString( "t"));
</xsl:when>
<xsl:otherwise>
result.Append(<xsl:value-of select="concat( '_', @name)"/>);
</xsl:otherwise>
</xsl:choose>
<xsl:choose>
<xsl:when test="position() = last()"/>
<xsl:otherwise>
result.Append( ", ");
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
result.AppendFormat( "<xsl:value-of select="@name"/>#{0}", KeyString);
</xsl:otherwise>
</xsl:choose>
return result.ToString();
}
}
/// &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:for-each select="adl:property[@type='list']|adl:property[@type='link']">
<xsl:choose>
<xsl:when test="@cascade='manual'"/>
<xsl:when test="@cascade='all'"/>
<xsl:when test="@cascade='all-delete-orphan'"/>
<xsl:when test="@cascade='delete'"/>
<xsl:otherwise>
if ( _<xsl:value-of select="@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="@name"/>.Count);
}
</xsl:otherwise>
</xsl:choose>
</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"/>
}
}
</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: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="$base-type='entity'"/>
<xsl:when test="$base-type='string'"/>
<!-- 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="$csharp-type = 'String'">
= "<xsl:value-of select="@default"/>"
</xsl:when>
<xsl:otherwise>
= <xsl:value-of select="@default"/>
</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: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="$csharp-type"/><xsl:value-of select="normalize-space( $nullable-decoration)"/> _<xsl:value-of select="@name"/> <xsl:value-of select="$initialiser"/>;
/// &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="$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="@name"/>; }
set {
<xsl:if test="@required='true'">
if ( value == null)
{
throw new DataRequiredException( <xsl:choose>
<xsl:when test="ifmissing[@locale=$locale]">
<xsl:apply-templates select="ifmissing"/>
</xsl:when>
<xsl:otherwise>
"The value for <xsl:value-of select="@name"/> may not be set to null"
</xsl:otherwise>
</xsl:choose>
);
}
</xsl:if>
<xsl:if test="@type='defined'">
<xsl:variable name="definition">
<xsl:value-of select="@typedef"/>
</xsl:variable>
<xsl:variable name="maximum">
<xsl:value-of select="//adl:typedef[@name=$definition]/@maximum"/>
</xsl:variable>
<xsl:variable name="minimum">
<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"/>)
{
throw new DataRangeException( "The maximum permitted value for <xsl:value-of select="@name"/> is <xsl:value-of select="$maximum"/>");
}
</xsl:if>
<xsl:if test="string-length( $minimum) &gt; 0">
if ( value &lt; <xsl:value-of select="$minimum"/>)
{
throw new DataRangeException( "The minimum permitted value for <xsl:value-of select="@name"/> is <xsl:value-of select="$minimum"/>");
}
</xsl:if>
<xsl:if test="string-length( $validationpattern) &gt; 0">
if ( value != null &amp;&amp; ! <xsl:value-of select="@name"/>Validator.IsMatch( value))
{
throw new DataFormatException( string.Format( "The value supplied ({0}) does not match the format required by <xsl:value-of select="@name"/>", value));
}
</xsl:if>
</xsl:if>
<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="@name"/> = value;
}
}
</xsl:template>
<xsl:template match="adl:help">
<xsl:if test="@locale=$locale">
<!-- might conceivably be more than one line -->
<xsl:text>
/* </xsl:text><xsl:apply-templates/> */
</xsl:if>
</xsl:template>
<xsl:template match="ifmissing">
<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:choose>
<xsl:when test="@concrete='false'"/>
<xsl:otherwise>
_<xsl:value-of select="@name"/> = new HashedSet&lt;<xsl:value-of select="@entity"/>&gt;();
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<xsl:for-each select="property[@type='link']">
<xsl:choose>
<xsl:when test="@concrete='false'"/>
<xsl:otherwise>
_<xsl:value-of select="@name"/> = new HashedSet&lt;<xsl:value-of select="@entity"/>&gt;();
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
<!-- 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:message terminate="no">
Looking for definition of '<xsl:value-of select="$definition"/>';
Found to be defined as type '<xsl:value-of select="/adl:application/adl:typedef[@name=$definition]/@type"/>'
</xsl:message>
<xsl:value-of select="/adl:application/adl:typedef[@name=$definition]/@type"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$property/@type"/>
</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: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="$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'">bool</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:value-of select="$property/@entity"/>
</xsl:when>
<xsl:otherwise>[unknown?]</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

265
transforms01/adl2hibernate.xslt Executable file
View file

@ -0,0 +1,265 @@
<?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">
<!--
Application Description Framework
adl2hibernate.xsl
(c) 2007 Cygnet Solutions Ltd
Transform ADL to Hibernate
$Author: sb $
$Revision: 1.1 $
-->
<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:variable name="namespace">SRU.Hospitality.Entities</xsl:variable>
<xsl:variable name="assembly">SRU.Hospitality.DataModel</xsl:variable>
<xsl:template match="application">
<hibernate-mapping>
<xsl:attribute name="namespace">
<xsl:value-of select="$namespace"/>
</xsl:attribute>
<xsl:attribute name="assembly">
<xsl:value-of select="$assembly"/>
</xsl:attribute>
<xsl:comment>
***************************************************************************
*
* C1873: C1873-SUS-Hospitality.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.1 $', 12)"/>
*
***************************************************************************
</xsl:comment>
<xsl:apply-templates select="entity"/>
</hibernate-mapping>
</xsl:template>
<xsl:template match="entity">
<class>
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
<xsl:attribute name="table">
<xsl:value-of select="@name"/>
</xsl:attribute>
<id type="Int32">
<!-- ADL does not encode the primary key explicitly; instead it is
implicit and its name is always the name of the entity followed by
'Id' -->
<xsl:attribute name="name">
<xsl:value-of select="normalize-space( concat( @name, 'Id'))"/>
</xsl:attribute>
<generator class="native"/>
</id>
<xsl:apply-templates select="property"/>
</class>
</xsl:template>
<xsl:template match="property[@concrete='false']">
<!-- properties which are not concrete are by definition not
stored in the database -->
</xsl:template>
<xsl:template match="property[@type='entity']">
<!-- a property of type entity translates to a Hibernate many-to-one -->
<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: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 -->
</many-to-one>
</xsl:template>
<xsl:template match="property[@type='list']">
<xsl:variable name="farent" select="@entity"/>
<xsl:variable name="nearent" select="ancestor::entity/@name"/>
<xsl:variable name="farkey">
<xsl:choose>
<xsl:when test="@farkey">
<xsl:value-of select="@farkey"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="ancestor::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="//entity[@name=$farent]/property[@name=$farkey and @entity=$nearent]">true</xsl:when>
<xsl:otherwise>false</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<!-- 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:template>
<xsl:template match="property[@type='link']">
<!-- a property of type 'link' maps on to a Hibernate set -->
<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( 'ln_', ../@name, '_', @entity)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat( 'ln_', @entity, '_', ../@name)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<set>
<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:template>
<xsl:template match="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:variable name="type">
<xsl:choose>
<xsl:when test="@type = 'defined'">
<xsl:variable name="definition">
<xsl:value-of select="@definition"/>
</xsl:variable>
<xsl:value-of select="/application/definition[@name=$definition]/@type"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="@type"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:choose>
<xsl:when test="$type = 'date'">DateTime</xsl:when>
<xsl:when test="$type = 'time'">DateTime</xsl:when>
<xsl:when test="$type = 'string'">String</xsl:when>
<xsl:when test="$type = 'text'">String</xsl:when>
<xsl:when test="$type = 'boolean'">Boolean</xsl:when>
<xsl:when test="$type = 'timestamp'">TimeStamp</xsl:when>
<xsl:when test="$type = 'integer'">Int32</xsl:when>
<xsl:when test="$type = 'real'">Double</xsl:when>
<xsl:when test="$type = 'money'">Decimal</xsl:when>
<xsl:otherwise>[unknown?]</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</property>
</xsl:template>
<!--
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>

451
transforms01/adl2mssql.xslt Executable file
View file

@ -0,0 +1,451 @@
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!--
C1873 SRU Hospitality
adl2mssql.xsl
(c) 2007 Cygnet Solutions Ltd
Convert ADL to MS-SQL
$Author: sb $
$Revision: 1.1 $
-->
<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 MS-SQL 2000+ using adl2mssql.xsl $Revision: 1.1 $
--
-- Code generator (c) 2007 Cygnet Solutions Ltd
--
-------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------
-- authentication roles
-------------------------------------------------------------------------------------------------
<xsl:apply-templates select="group"/>
-------------------------------------------------------------------------------------------------
-- tables, views and permissions
-------------------------------------------------------------------------------------------------
<xsl:apply-templates select="entity" mode="table"/>
-------------------------------------------------------------------------------------------------
-- referential integrity constraints
-------------------------------------------------------------------------------------------------
<xsl:for-each select="entity">
<xsl:variable name="nearside" select="@name"/>
<xsl:for-each select="property[@type='entity']">
<xsl:variable name="farside" select="@entity"/>
<xsl:variable name="keyfield" select="@name"/>
<xsl:choose>
<xsl:when test="//entity[@name=$farside]/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="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:for-each>
-------------------------------------------------------------------------------------------------
-- end of file
-------------------------------------------------------------------------------------------------
</xsl:template>
<xsl:template match="group">
execute sp_addrole @rolename = '<xsl:value-of select="@name"/>'
GO
</xsl:template>
<!-- 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'"/>
<!-- set up referential integrity constraints for primary tables -->
ALTER TABLE "<xsl:value-of select="$nearside"/>"
ADD FOREIGN KEY ( "<xsl:value-of select="$keyfield"/>")
REFERENCES "<xsl:value-of select="$farside"/>" ON DELETE <xsl:value-of select="$ondelete"/>
GO
</xsl:template>
<xsl:template match="entity" mode="table">
<xsl:variable name="table" select="@name"/>
-------------------------------------------------------------------------------------------------
-- primary table <xsl:value-of select="@name"/>
-------------------------------------------------------------------------------------------------
CREATE TABLE "<xsl:value-of select="@name"/>"
(
<xsl:apply-templates select="property[@type!='link']"/>
<xsl:value-of select="@name"/>Id INT IDENTITY( 1, 1) PRIMARY KEY
)
GO
---- permissions ------------------------------------------------------------------------------
<xsl:for-each select="permission">
<xsl:call-template name="permission">
<xsl:with-param name="table" select="$table"/>
</xsl:call-template>
</xsl:for-each>
<xsl:if test="property[@type='link']">
---- link tables ------------------------------------------------------------------------------
</xsl:if>
<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>
<xsl:template name="distinctfield">
<xsl:param name="table"/>
<xsl:param name="alias"/>
<!--
print the names of the distinguishing fields in this table,
concatenating into a single string.
-->
<xsl:for-each select="/application/entity[@name=$table]">
<xsl:for-each select="property[@distinct='user' or @distinct='all']">
<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="concat( $alias, '_', @name)"></xsl:with-param>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
"<xsl:value-of select="$alias"/>"."<xsl:value-of
select="@name"/>"<xsl:if test="position() != last()"> + ' ' + </xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
<xsl:template name="permission">
<xsl:param name="table"/>
<!-- decode the permissions for a table -->
<xsl:choose>
<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
select="$table"/>" TO <xsl:value-of select="@group"/>
GO
</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
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
select="$table"/>" TO <xsl:value-of select="@group"/>
GO
</xsl:when>
<xsl:otherwise>
REVOKE ALL ON "<xsl:value-of
select="$table"/>" FROM <xsl:value-of select="@group"/>
GO
</xsl:otherwise>
</xsl:choose>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template name="linktable">
<xsl:param name="nearside"/>
<!-- This is tricky. For any many-to-many relationship between two
entities, we only want to create one link table, even if (as should be)
a property of type 'link' has been declared at both ends -->
<xsl:variable name="farside">
<xsl:choose>
<xsl:when test="@entity = $nearside">
<xsl:value-of select="concat( @entity, '_1')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="@entity"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="comparison">
<xsl:call-template name="stringcompare">
<xsl:with-param name="node1" select="$nearside"/>
<xsl:with-param name="node2" select="@entity"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="farentity" select="/application/entity[@name=$farside]"/>
<!-- 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>
<!-- if we could use the compare( string, string) function this would be a lot simpler, but
unfortunately that's in XSL 2.0, and neither NAnt nor Visual Studio can manage that -->
<!-- if the link is back to me, then obviously I'm responsible -->
<xsl:when test="$comparison = 0">true</xsl:when>
<!-- generally, the entity whose name is later in the default collating sequence
shall not be responsible. -->
<xsl:when test="$comparison = -1">true</xsl:when>
<!-- However if the one that is earlier doesn't have a 'link'
property for this join, however, then later end will have to do it -->
<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:otherwise>true</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>false</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="tablename">
<xsl:choose>
<xsl:when test="$comparison =-1">
<xsl:value-of select="concat( 'LN_', $nearside, '_', @entity)"/>
</xsl:when>
<xsl:otherwise>
<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 -->
-------------------------------------------------------------------------------------------------
-- link table joining <xsl:value-of select="$nearside"/> with <xsl:value-of select="@entity"/>
-------------------------------------------------------------------------------------------------
CREATE TABLE "<xsl:value-of select="$tablename"/>"
(
"<xsl:value-of select="$nearside"/>Id" INT NOT NULL,
"<xsl:value-of select="$farside"/>Id" INT NOT NULL,
)
GO
<xsl:text>
</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 --------------------------------------------------------------------
<xsl:choose>
<xsl:when test="$nearside=@entity">
<xsl:call-template name="foreignkey">
<xsl:with-param name="nearside" select="$tablename"/>
<xsl:with-param name="farside" select="$nearside"/>
<xsl:with-param name="keyfield" select="concat( $nearside, 'Id')"/>
<xsl:with-param name="ondelete" select="'NO ACTION'"/>
</xsl:call-template>
<xsl:call-template name="foreignkey">
<xsl:with-param name="nearside" select="$tablename"/>
<xsl:with-param name="farside" select="$nearside"/>
<xsl:with-param name="keyfield" select="concat( $farside, 'Id')"/>
<xsl:with-param name="ondelete" select="'CASCADE'"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="foreignkey">
<xsl:with-param name="nearside" select="$tablename"/>
<xsl:with-param name="farside" select="$nearside"/>
<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="$tablename"/>
<xsl:with-param name="farside" select="@entity"/>
<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="$tablename"/>, 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']">
-- 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
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>
</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>
</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>
<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>
<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>
<!-- 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. -->
<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>

339
transforms01/adl2psql.xslt Executable file
View file

@ -0,0 +1,339 @@
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
<!-- -->
<!-- adl2psql.xsl -->
<!-- -->
<!-- Purpose: -->
<!-- XSL stylesheet to generate Postgresql [7|8] from ADL. -->
<!-- -->
<!-- Author: Simon Brooke <simon@weft.co.uk> -->
<!-- Created: 24th January 2006 -->
<!-- Copyright: (c) 2006 Simon Brooke. -->
<!-- -->
<!-- This program is free software; you can redistribute it and/or -->
<!-- modify it under the terms of the GNU General Public License as -->
<!-- published by the Free Software Foundation; either version 2 of the -->
<!-- License, or (at your option) any later version. -->
<!-- -->
<!-- This program is distributed in the hope that it will be useful, -->
<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -->
<!-- General Public License for more details. -->
<!-- -->
<!-- You should have received a copy of the GNU General Public License -->
<!-- along with this program; if not, write to the Free Software -->
<!-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -->
<!-- 02111-1307 USA -->
<!-- -->
<!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
<!--
JACQUARD 2 APPLICATION DESCRIPTION LANGUAGE FRAMEWORK
$Revision: 1.1 $
NOTES:
Needless to say this is all hugely experimental.
Running the primary key field last is a hack which gets around the fact that
otherwise it's extremely complex to lose the comma after the last field.
Ideally where there is one 'distinct="system"' property of an entity that
should be the primary key and perhaps we'll achieve that in the long run...
Still to do:
References in convenience views for fields which have their reference value at
two removes (i.e. the 'distinguish' mechanism in ADL
-->
<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 $
--
-- Code generator (c) 2006 Simon Brooke [simon@weft.co.uk]
-- http://www.weft.co.uk/library/jacquard/
--
-------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------
-- authentication roles
-------------------------------------------------------------------------------------------------
<xsl:apply-templates select="group"/>
-------------------------------------------------------------------------------------------------
-- tables, views and permissions
-------------------------------------------------------------------------------------------------
<xsl:apply-templates select="entity"/>
-------------------------------------------------------------------------------------------------
-- referential integrity constraints
-------------------------------------------------------------------------------------------------
<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:for-each>
<xsl:for-each select="property[@type='link']">
<xsl:call-template name="linkintegrity">
<xsl:with-param name="nearside" select="$nearside"/>
</xsl:call-template>
</xsl:for-each>
</xsl:for-each>
-------------------------------------------------------------------------------------------------
-- end of file
-------------------------------------------------------------------------------------------------
</xsl:template>
<xsl:template match="group">
CREATE GROUP <xsl:value-of select="@name"/>;
</xsl:template>
<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"/>
FOREIGN KEY ( <xsl:value-of select="@name"/>) REFERENCES <xsl:value-of select="@entity"/> ON DELETE NO ACTION;
</xsl:template>
<xsl:template name="linkintegrity">
<xsl:param name="nearside"/>
<!-- set up referential integrity constraints for link tables -->
ALTER TABLE ln_<xsl:value-of select="$nearside"/>_<xsl:value-of select="@entity"/>
ADD CONSTRAINT ri_<xsl:value-of select="$nearside"/>_<xsl:value-of select="@entity"/>_<xsl:value-of select="$nearside"/>_id
FOREIGN KEY ( <xsl:value-of select="$nearside"/>_id) REFERENCES <xsl:value-of select="$nearside"/> ON DELETE CASCADE;
ALTER TABLE ln_<xsl:value-of select="$nearside"/>_<xsl:value-of select="@entity"/>
ADD CONSTRAINT ri_<xsl:value-of select="$nearside"/>_<xsl:value-of select="@entity"/>_<xsl:value-of select="@entity"/>_id
FOREIGN KEY ( <xsl:value-of select="@entity"/>_id) REFERENCES <xsl:value-of select="@entity"/> ON DELETE CASCADE;
</xsl:template>
<xsl:template match="entity">
<xsl:variable name="table" select="@name"/>
-------------------------------------------------------------------------------------------------
-- primary table <xsl:value-of select="@name"/>
-------------------------------------------------------------------------------------------------
CREATE TABLE <xsl:value-of select="@name"/>
(
<xsl:apply-templates select="property[@type!='link']"/>
<xsl:value-of select="@name"/>_id SERIAL NOT NULL PRIMARY KEY
);
---- permissions ------------------------------------------------------------------------------
<xsl:for-each select="permission">
<xsl:call-template name="permission">
<xsl:with-param name="table" select="$table"/>
</xsl:call-template>
</xsl:for-each>
-------------------------------------------------------------------------------------------------
-- convenience view lv_<xsl:value-of select="@name"/> for lists
-------------------------------------------------------------------------------------------------
CREATE VIEW lv_<xsl:value-of select="@name"/> AS
SELECT <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>;
---- 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>
---- permissions ------------------------------------------------------------------------------
<xsl:variable name="farside" select="@entity"/>
<xsl:for-each select="../permission">
<xsl:call-template name="permission">
<xsl:with-param name="table">ln_<xsl:value-of select="$table"/>_<xsl:value-of select="$farside"/></xsl:with-param>
</xsl:call-template>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
<xsl:template name="distinctfield">
<xsl:param name="table"/>
<xsl:param name="alias"/>
<!--
print the names of the distinguishing fields in this table,
concatenating into a single string.
-->
<xsl:for-each select="/application/entity[@name=$table]">
<xsl:for-each select="property[@distinct='user' or @distinct='all']">
<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="concat( $alias, '_', @name)"></xsl:with-param>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$alias"/>.<xsl:value-of
select="@name"/><xsl:if test="position() != last()"> | ' ' | </xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
<xsl:template name="permission">
<xsl:param name="table"/>
<!-- decode the permissions for a table -->
<xsl:choose>
<xsl:when test="@permission='read'">GRANT SELECT ON <xsl:value-of
select="$table"/> TO GROUP <xsl:value-of select="@group"/>;</xsl:when>
<xsl:when test="@permission='insert'">GRANT INSERT ON <xsl:value-of
select="$table"/> TO GROUP <xsl:value-of select="@group"/>;</xsl:when>
<xsl:when test="@permission='noedit'">GRANT SELECT, INSERT ON <xsl:value-of
select="$table"/> TO GROUP <xsl:value-of select="@group"/>;</xsl:when>
<xsl:when test="@permission='edit'">GRANT SELECT, INSERT, UPDATE ON <xsl:value-of
select="$table"/> TO GROUP <xsl:value-of select="@group"/>;</xsl:when>
<xsl:when test="@permission='all'">GRANT SELECT, INSERT, UPDATE, DELETE ON <xsl:value-of
select="$table"/> TO GROUP <xsl:value-of select="@group"/>;</xsl:when>
<xsl:otherwise>REVOKE ALL ON <xsl:value-of
select="$table"/> FROM GROUP <xsl:value-of select="@group"/>;</xsl:otherwise>
</xsl:choose>
<xsl:text>
</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 lv_<xsl:value-of
select="$table"/> FROM GROUP <xsl:value-of select="@group"/>;</xsl:when>
<xsl:when test="@permission='insert'">REVOKE ALL ON lv_<xsl:value-of
select="$table"/> FROM GROUP <xsl:value-of select="@group"/>;</xsl:when>
<xsl:otherwise>GRANT SELECT ON lv_<xsl:value-of
select="$table"/> TO GROUP <xsl:value-of select="@group"/>;</xsl:otherwise>
</xsl:choose>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template name="linktable">
<xsl:param name="nearside"/>
<xsl:variable name="farside">
<xsl:choose>
<xsl:when test="@entity = $nearside"><xsl:value-of select="@entity"/>_1</xsl:when>
<xsl:otherwise>
<xsl:value-of select="@entity"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!-- create a linking table -->
-------------------------------------------------------------------------------------------------
-- link table joining <xsl:value-of select="$nearside"/> with <xsl:value-of select="@entity"/>
-------------------------------------------------------------------------------------------------
CREATE TABLE ln_<xsl:value-of select="$nearside"/>_<xsl:value-of select="@entity"/>
(
<xsl:value-of select="$nearside"/>_id INT NOT NULL,
<xsl:value-of select="$farside"/>_id INT NOT NULL,
);
<xsl:text>
</xsl:text>
<!-- TODO: permissions for link tables! -->
</xsl:template>
<xsl:template match="property[@type='entity']">
<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='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>
</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>
<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>
</xsl:stylesheet>

1172
transforms01/adl2views.xslt Executable file

File diff suppressed because it is too large Load diff

426
transforms01/datadescriber.xslt Executable file
View file

@ -0,0 +1,426 @@
<?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:param name="locale" select="en-UK"/>
<xsl:template match="application">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>
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" />
</head>
<body>
<h1>
Data definition for the <xsl:value-of select="@name"/> application version <xsl:value-of select="@version"/>
</h1>
<xsl:apply-templates select="documentation"/>
<xsl:for-each select="entity">
<h2>
<xsl:value-of select="@name" />
</h2>
<xsl:apply-templates select="documentation"/>
<dl>
<xsl:for-each select="permission">
<dt>
Group:
<xsl:value-of select="@group"/>
</dt>
<dd>
Permissions:
<xsl:value-of select="@permission"/>
</dd>
</xsl:for-each>
</dl>
<table>
<tr class="header">
<th class="white">Property</th>
<th class="white">Type</th>
<th class="white">Req'd</th>
<th class="white">Def'lt</th>
<th class="white">Size</th>
<th class="white">Distinct</th>
<th class="white">Prompt</th>
</tr>
<xsl:for-each select="property" >
<tr>
<xsl:attribute name="class">
<xsl:choose>
<xsl:when test="position() mod 2 = 0">even</xsl:when>
<xsl:otherwise>odd</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<td>
<xsl:value-of select="@name"/>&#160;
</td>
<td>
<xsl:value-of select="@type"/>
<xsl:if test="@type='entity'">
of type <xsl:value-of select="@entity"/>
</xsl:if>
<xsl:if test="@definition">
:
<xsl:variable name="definition">
<xsl:value-of select="@definition"/>
</xsl:variable>
<xsl:variable name="defined-type">
<xsl:value-of select="/application/definition[@name=$definition]/@type"/>
</xsl:variable>
<xsl:choose>
<xsl:when test="$defined-type = 'string'">
String matching
"<xsl:value-of select="/application/definition[@name=$definition]/@pattern"/>"
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="/application/definition[@name=$definition]/@minimum"/> &lt;
<xsl:value-of select="@definition"/> &lt;
<xsl:value-of select="/application/definition[@name=$definition]/@maximum"/>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
&#160;
</td>
<td>
<xsl:value-of select="@required"/>&#160;
</td>
<td>
<xsl:value-of select="@default"/>&#160;
</td>
<td>
<xsl:value-of select="@size"/>&#160;
</td>
<td>
<xsl:value-of select="@distinct"/>&#160;
</td>
<td>
<xsl:for-each select="prompt">
<xsl:apply-templates select="@prompt"/>&#160;
</xsl:for-each>
</td>
</tr>
<xsl:if test="help">
<tr>
<td>
<xsl:apply-templates select="help"/>&#160;
</td>
</tr>
</xsl:if>
<xsl:if test="documentation">
<tr>
<td>
<xsl:apply-templates select="help"/>&#160;
</td>
</tr>
</xsl:if>
</xsl:for-each>
</table>
</xsl:for-each>
<xsl:apply-templates select="form"/>
<xsl:apply-templates select="list"/>
<xsl:apply-templates select="page"/>
</body>
</html>
</xsl:template>
<xsl:template match="prompt">
<!-- If I'm the prompt for the current locale, show me;
if I'm the default prompt, show me only if there isn't
one for the default locale -->
<xsl:choose>
<xsl:when test="@locale=$locale">
<xsl:value-of select="@prompt"/>
</xsl:when>
<xsl:when test="@locale='default'">
<xsl:choose>
<xsl:when test="../prompt[@locale=$locale]"/>
<xsl:otherwise>
<xsl:value-of select="@prompt"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template match="help">
<!-- If I'm the helptext for the current locale, show me;
if I'm the default helptext, show me only if there isn't
one for the default locale -->
<xsl:choose>
<xsl:when test="@locale=$locale">
<xsl:apply-templates/>
</xsl:when>
<xsl:when test="@locale='default'">
<xsl:choose>
<xsl:when test="../help[@locale=$locale]"/>
<xsl:otherwise>
<xsl:apply-templates/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template match="documentation">
<div xmlns="http://www.w3.org/1999/xhtml" class="documentation">
<xsl:apply-templates />
</div>
</xsl:template>
<xsl:template match="form">
<div xmlns="http://www.w3.org/1999/xhtml">
<h3 xmlns="http://www.w3.org/1999/xhtml">
Form <xsl:value-of select="@name"/>
</h3>
<xsl:if test="permission">
<h4 xmlns="http://www.w3.org/1999/xhtml">Permissions</h4>
<ul xmlns="http://www.w3.org/1999/xhtml">
<xsl:apply-templates select="permission"/>
</ul>
</xsl:if>
<xsl:choose>
<xsl:when test="@properties='listed'">
<p>Showing the following properties</p>
<table xmlns="http://www.w3.org/1999/xhtml">
<tr>
<th>&#160;</th>
<th>Property</th>
<th>Prompt</th>
<th>Documentation</th>
</tr>
<xsl:apply-templates select="field|fieldgroup|auxlist|verb"/>
</table>
</xsl:when>
<xsl:otherwise>
<p>Showing all properties</p>
</xsl:otherwise>
</xsl:choose>
</div>
</xsl:template>
<xsl:template match="page">
<div xmlns="http://www.w3.org/1999/xhtml">
<h3 xmlns="http://www.w3.org/1999/xhtml">
Page <xsl:value-of select="@name"/>
</h3>
<xsl:if test="permission">
<ul xmlns="http://www.w3.org/1999/xhtml">
<xsl:apply-templates select="permission"/>
</ul>
</xsl:if>
<xsl:choose>
<xsl:when test="@properties='listed'">
<p>Showing the following properties</p>
<table xmlns="http://www.w3.org/1999/xhtml">
<tr>
<th>&#160;</th>
<th>Property</th>
<th>Prompt</th>
<th>Documentation</th>
</tr>
<xsl:apply-templates select="field|fieldgroup|auxlist|verb"/>
</table>
</xsl:when>
<xsl:otherwise>
<p>Showing all properties</p>
</xsl:otherwise>
</xsl:choose>
</div>
</xsl:template>
<xsl:template match="list">
<div xmlns="http://www.w3.org/1999/xhtml">
<h3 xmlns="http://www.w3.org/1999/xhtml">
List <xsl:value-of select="@name"/>, on select <xsl:value-of select="onselect"/>
</h3>
<xsl:if test="permission">
<ul xmlns="http://www.w3.org/1999/xhtml">
<xsl:apply-templates select="permission"/>
</ul>
</xsl:if>
<xsl:choose>
<xsl:when test="@properties='listed'">
<p>Showing the following properties</p>
<table xmlns="http://www.w3.org/1999/xhtml">
<tr>
<th>&#160;</th>
<th>Property</th>
<th>Prompt</th>
<th>Documentation</th>
</tr>
<xsl:apply-templates select="field|fieldgroup|auxlist|verb"/>
</table>
</xsl:when>
<xsl:otherwise>
<p>Showing all properties</p>
</xsl:otherwise>
</xsl:choose>
</div>
</xsl:template>
<xsl:template match="field">
<tr xmlns="http://www.w3.org/1999/xhtml">
<xsl:attribute name="class">
<xsl:choose>
<xsl:when test="parent::fieldgroup">
<xsl:choose>
<xsl:when test="position() = last()">fieldgroup-end</xsl:when>
<xsl:otherwise>fieldgroup</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:when test="parent::auxlist">
<xsl:choose>
<xsl:when test="position() = last()">auxlist-end</xsl:when>
<xsl:otherwise>auxlist</xsl:otherwise>
</xsl:choose>
</xsl:when>
</xsl:choose>
</xsl:attribute>
<td>Field</td>
<td>
<xsl:value-of select="@property"/>
</td>
<td>
<xsl:apply-templates select="prompt"/>
</td>
<td>
<xsl:apply-templates select="help"/>
</td>
<td>
<xsl:apply-templates select="documentation"/>
</td>
</tr>
<xsl:if test="permission">
<tr xmlns="http://www.w3.org/1999/xhtml">
<td></td>
<td colspan="3">
<xsl:apply-templates select="permission"/>
</td>
</tr>
</xsl:if>
</xsl:template>
<xsl:template match="verb">
<tr xmlns="http://www.w3.org/1999/xhtml">
<xsl:attribute name="class">
<xsl:choose>
<xsl:when test="parent::fieldgroup">
<xsl:choose>
<xsl:when test="position() = last()">fieldgroup-end</xsl:when>
<xsl:otherwise>fieldgroup</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:when test="parent::auxlist">
<xsl:choose>
<xsl:when test="position() = last()">auxlist-end</xsl:when>
<xsl:otherwise>auxlist</xsl:otherwise>
</xsl:choose>
</xsl:when>
</xsl:choose>
</xsl:attribute>
<td>Verb</td>
<td>
<xsl:value-of select="@verb"/>
<xsl:if test="@dangerous='true'">[dangerous]</xsl:if>
</td>
<td>
<xsl:apply-templates select="prompt"/>
</td>
<td>
<xsl:apply-templates select="help"/>
</td>
<td>
<xsl:apply-templates select="documentation"/>
</td>
</tr>
<xsl:if test="permission">
<tr xmlns="http://www.w3.org/1999/xhtml">
<td></td>
<td colspan="3">
<xsl:apply-templates select="permission"/>
</td>
</tr>
</xsl:if>
</xsl:template>
<xsl:template match="auxlist">
<tr xmlns="http://www.w3.org/1999/xhtml" class="auxlist-start">
<th>Auxlist</th>
<th>
<xsl:value-of select="@property"/>
</th>
<th>
<xsl:apply-templates select="prompt"/>
</th>
<th>
<xsl:apply-templates select="help"/>
</th>
<th>
<xsl:apply-templates select="documentation"/>
</th>
</tr>
<tr xmlns="http://www.w3.org/1999/xhtml" class="auxlist">
<th>On select:</th>
<td>
<xsl:value-of select="@onselect"/>
</td>
<td colspan="2">
<xsl:choose>
<xsl:when test="@properties='listed'">
Showing the following properties
</xsl:when>
<xsl:otherwise>
Showing all properties
</xsl:otherwise>
</xsl:choose>
</td>
</tr>
<xsl:apply-templates select="field|fieldgroup|auxlist|verb"/>
</xsl:template>
<xsl:template match="fieldgroup">
<tr xmlns="http://www.w3.org/1999/xhtml" class="fieldgroup-start">
<th>Auxlist</th>
<th>
<xsl:value-of select="@name"/>
</th>
<th>
<xsl:apply-templates select="prompt"/>
</th>
<th>
<xsl:apply-templates select="help"/>
</th>
<th>
<xsl:apply-templates select="documentation"/>
</th>
</tr>
<tr xmlns="http://www.w3.org/1999/xhtml" class="auxlist">
<th>On select:</th>
<td>
<xsl:value-of select="@onselect"/>
</td>
<td colspan="2">
<xsl:choose>
<xsl:when test="@properties='listed'">
Showing the following properties
</xsl:when>
<xsl:otherwise>
Showing all properties
</xsl:otherwise>
</xsl:choose>
</td>
</tr>
<xsl:apply-templates select="field|fieldgroup|auxlist|verb"/>
</xsl:template>
</xsl:stylesheet>