diff --git a/ADL.NET/ADL.csproj b/ADL.NET/ADL.csproj
new file mode 100755
index 0000000..b2b9933
--- /dev/null
+++ b/ADL.NET/ADL.csproj
@@ -0,0 +1,84 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.50727</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{7D9E1F28-3F9C-4675-A02C-C9B2E98A839E}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>ADL</RootNamespace>
+    <AssemblyName>ADL</AssemblyName>
+    <StartupObject>
+    </StartupObject>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Exceptions\DataSuitabilityException.cs" />
+    <Compile Include="Exceptions\DataFormatException.cs" />
+    <Compile Include="Exceptions\DataRangeException.cs" />
+    <Compile Include="Exceptions\DataRequiredException.cs" />
+    <Compile Include="Exceptions\DomainKnowledgeViolationException.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>Resources.resx</DependentUpon>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="j2adl.dtd" />
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="Trans\adl2controllerclasses.xsl" />
+    <Content Include="Trans\adl2entityclass.xsl" />
+    <Content Include="Trans\adl2hibernate.xsl" />
+    <Content Include="Trans\adl2views.xsl" />
+    <Content Include="Trans\adl2mssql.xsl" />
+    <Content Include="Trans\adl2psql.xsl" />
+    <Content Include="Trans\datadescriber.xsl" />
+    <Content Include="Trans\hibernate2adl.xsl" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\CygnetToolkit\CygnetToolkit.csproj">
+      <Project>{77FB7DE5-1F33-4DDC-8A2E-79EF4728705E}</Project>
+      <Name>CygnetToolkit</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <SubType>Designer</SubType>
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/ADL.NET/Exceptions/DataFormatException.cs b/ADL.NET/Exceptions/DataFormatException.cs
new file mode 100755
index 0000000..cf93118
--- /dev/null
+++ b/ADL.NET/Exceptions/DataFormatException.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+/*
+ *    Application Description Framework
+ *    DataRangeException.cs
+ *     
+ *    (c) 2007 Cygnet Solutions Ltd
+ *    
+ *    $Author: af $
+ *    $Revision: 1.1 $
+ */
+
+namespace ADL.Exceptions {
+    /// <summary>
+    /// An exception to be thrown if an attempt is made to set a property to a 
+    /// value which is unsuitably formatted for the data type
+    /// </summary>
+    public class DataFormatException : DataSuitabilityException {
+        public DataFormatException(String message) : base(message) {}
+    }
+}
diff --git a/ADL.NET/Exceptions/DataRangeException.cs b/ADL.NET/Exceptions/DataRangeException.cs
new file mode 100755
index 0000000..9906b6e
--- /dev/null
+++ b/ADL.NET/Exceptions/DataRangeException.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+/*
+ *    Application Description Framework
+ *    DataRangeException.cs
+ *     
+ *    (c) 2007 Cygnet Solutions Ltd
+ *    
+ *    $Author: af $
+ *    $Revision: 1.1 $
+ */
+
+namespace ADL.Exceptions {
+    /// <summary>
+    /// An exception to be thrown if an attempt is made to set a scalar property with a 
+    /// defined range to a value which is outside that range
+    /// </summary>
+    public class DataRangeException : DataSuitabilityException {
+        public DataRangeException(String message) : base(message) {}
+    }
+}
diff --git a/ADL.NET/Exceptions/DataRequiredException.cs b/ADL.NET/Exceptions/DataRequiredException.cs
new file mode 100755
index 0000000..1857b63
--- /dev/null
+++ b/ADL.NET/Exceptions/DataRequiredException.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+/*
+ *    Application Description Framework
+ *    DataRequiredException.cs
+ *     
+ *    (c) 2007 Cygnet Solutions Ltd
+ *    
+ *    $Author: af $
+ *    $Revision: 1.1 $
+ */
+namespace ADL.Exceptions {
+    /// <summary>
+    /// An exception to be thrown if an attempt is made to set a required property to null
+    /// </summary>
+    public class DataRequiredException : DataSuitabilityException {
+        public DataRequiredException(String message) : base(message){}
+    }
+}
diff --git a/ADL.NET/Exceptions/DataSuitabilityException.cs b/ADL.NET/Exceptions/DataSuitabilityException.cs
new file mode 100755
index 0000000..377181c
--- /dev/null
+++ b/ADL.NET/Exceptions/DataSuitabilityException.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+/*
+ *    Application Description Framework
+ *    DataRangeException.cs
+ *     
+ *    (c) 2007 Cygnet Solutions Ltd
+ *    
+ *    $Author: af $
+ *    $Revision: 1.1 $
+ */
+
+namespace ADL.Exceptions {
+    /// <summary>
+    /// An exception to be thrown if an attempt is made to set a property 
+    /// to a value which is unsuitable
+    /// </summary>
+    public abstract class DataSuitabilityException : Exception {
+        public DataSuitabilityException(String message) : base(message) {}
+    }
+}
diff --git a/ADL.NET/Exceptions/DomainKnowledgeViolationException.cs b/ADL.NET/Exceptions/DomainKnowledgeViolationException.cs
new file mode 100755
index 0000000..67d0006
--- /dev/null
+++ b/ADL.NET/Exceptions/DomainKnowledgeViolationException.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+/*
+ *    Application Description Framework
+ *    DomainKnowledgeViolationException.cs
+ *     
+ *    (c) 2007 Cygnet Solutions Ltd
+ *    
+ *    $Author: af $
+ *    $Revision: 1.1 $
+ */
+
+namespace ADL.Exceptions {
+    /// <summary>
+    /// An exception to be thrown if a state arises which violates 
+    /// some specific knowledge about the application domain (i.e. 
+    /// a 'business rule' violation)
+    /// </summary>
+    public class DomainKnowledgeViolationException : Exception {
+        public DomainKnowledgeViolationException(String message) : base(message) { }
+    }
+}
diff --git a/ADL.NET/Properties/AssemblyInfo.cs b/ADL.NET/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..2e82949
--- /dev/null
+++ b/ADL.NET/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("ADL")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("ADL")]
+[assembly: AssemblyCopyright("Copyright © 2007 Cygnet Solutions Ltd")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("6be1b0e7-f012-44ee-a35f-892f53b627ad")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/ADL.NET/Trans/adl2controllerclasses.xsl b/ADL.NET/Trans/adl2controllerclasses.xsl
new file mode 100755
index 0000000..68bec4b
--- /dev/null
+++ b/ADL.NET/Trans/adl2controllerclasses.xsl
@@ -0,0 +1,542 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+  <!--
+    C1873 SRU Hospitality
+    adl2controllerclasses.xsl
+    
+    (c) 2007 Cygnet Solutions Ltd
+    
+    Transform ADL into (partial) controller classes
+    
+    $Author: af $
+    $Revision: 1.1 $
+    $Date: 2008-01-09 15:01:45 $
+  -->
+
+  <!-- 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 SRU.Hospitality.Entities;
+using SRU.Hospitality.Helpers;
+using ADL.Exceptions;
+using Iesi.Collections.Generic;
+
+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;
+  [
+      Helper(typeof(ShuffleWidgetHelper), "ShuffleWidgetHelper"),
+  ]
+  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>
\ No newline at end of file
diff --git a/ADL.NET/Trans/adl2entityclass.xsl b/ADL.NET/Trans/adl2entityclass.xsl
new file mode 100755
index 0000000..cd09d89
--- /dev/null
+++ b/ADL.NET/Trans/adl2entityclass.xsl
@@ -0,0 +1,378 @@
+<?xml version="1.0" encoding="UTF-8" ?>  
+  <!--
+    C1873 SRU Hospitality
+    adl2entityclass.xsl
+    
+    (c) 2007 Cygnet Solutions Ltd
+    
+    Transform ADL into entity classes
+    
+    $Author: af $
+    $Revision: 1.1 $
+    $Date: 2008-01-09 15:01:45 $
+  -->
+
+  <!-- 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 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="application">
+    <xsl:apply-templates select="entity"/>
+  </xsl:template>
+
+  <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)"/>
+
+    /* ---- [ 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 version <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 ADL.Exceptions;
+      using Iesi.Collections.Generic;
+
+      /// &lt;summary&gt;
+      /// Automatically generated from description of entity <xsl:value-of select="@name"/>
+      /// using adl2entityclass.xsl. Note that manually maintained parts of this
+      /// class may be defined in a separate file called <xsl:value-of select="@name"/>.cs, q.v.
+      ///
+      /// DO NOT EDIT THIS FILE!
+      /// &lt;/summary&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"/>
+        }
+
+        /// &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:choose>
+          <xsl:when test="@natural-key">
+          /* natural primary key exists - not initialising abstract key */
+          </xsl:when>
+          <xsl:otherwise>
+          _<xsl:value-of select="@name"/>Id = key;
+          </xsl:otherwise>
+        </xsl:choose>
+        }
+
+        <xsl:choose>
+          <xsl:when test="@natural-key">
+        /* natural primary key exists - not generating abstract key */
+          </xsl:when>
+          <xsl:otherwise>
+        /// &lt;summary&gt;
+        /// Auto-generated iv/property for Id slot
+        /// &lt;/summary&gt;
+        private int _<xsl:value-of select="@name"/>Id = -1;
+
+        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;
+        public override int Key
+        {
+          get { return _<xsl:value-of select="@name"/>Id; }
+        }
+          </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="property[@distinct='user']">
+              <xsl:for-each select="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: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}[", _<xsl:value-of select="@name"/>Id);
+            </xsl:otherwise>
+          </xsl:choose>
+          
+            return result.ToString();
+          }
+        }
+    
+    <xsl:apply-templates select="property"/>
+      }
+    }
+
+
+  </xsl:template>
+
+  <xsl:template match="property[@concrete='false']">
+    <!-- generate nothing for non-concrete properties -->
+  </xsl:template>
+  
+  <xsl:template match="property">
+        // auto generating iv/property pair for slot with name <xsl:value-of select="@name"/>
+    <xsl:apply-templates select="help"/>
+
+    <xsl:variable name="defined-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:choose>
+    </xsl:variable>
+
+    <xsl:variable name="type">
+      <xsl:choose>
+        <xsl:when test="@type = 'link'">
+          ICollection&lt;<xsl:value-of select="@entity"/>&gt;
+        </xsl:when>
+        <xsl:when test="@type = 'list'">
+          ICollection&lt;<xsl:value-of select="@entity"/>&gt;
+        </xsl:when>
+        <xsl:when test="@type = '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'">bool</xsl:when>
+        <xsl:when test="@type = 'timestamp'">TimeStamp</xsl:when>
+        <xsl:when test="@type = 'integer'">int</xsl:when>
+        <xsl:when test="@type = 'real'">double</xsl:when>
+        <xsl:when test="@type = 'money'">Decimal</xsl:when>
+        <xsl:when test="@type = 'entity'">
+          <xsl:value-of select="@entity"/>
+        </xsl:when>
+        <xsl:when test="@type='defined'">
+          <!-- MUCH more complicated... find the right definition, then map its type onto a C# type -->
+          <xsl:choose>
+            <!-- DefinableDataTypes are string|integer|real|money|date|time|timestamp -->
+            <xsl:when test="$defined-type = 'string'">String</xsl:when>
+            <xsl:when test="$defined-type = 'integer'">int</xsl:when>
+            <xsl:when test="$defined-type = 'real'">double</xsl:when>
+            <xsl:when test="$defined-type = 'money'">Decimal</xsl:when>
+            <xsl:when test="$defined-type = 'date'">DateTime</xsl:when>
+            <xsl:when test="$defined-type = 'time'">DateTime</xsl:when>
+            <xsl:when test="$defined-type = 'timestamp'">TimeStamp</xsl:when>
+          </xsl:choose>
+        </xsl:when>
+        <xsl:otherwise>[unknown?]</xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    <xsl:variable name="nullable-decoration">
+      <xsl:choose>
+        <xsl:when test="@required='true'"/>
+        <!-- when required is 'true' null is not permitted anyway; otherwise... -->
+        <xsl:when test="$type = 'int'">?</xsl:when>
+        <xsl:when test="@type = 'boolean'">?</xsl:when>
+        <xsl:when test="$type = 'double'">?</xsl:when>
+        <xsl:when test="$type = 'Double'">?</xsl:when>
+        <xsl:when test="$type = 'DateTime'">?</xsl:when>
+        <xsl:when test="$type = 'TimeStamp'">?</xsl:when>
+        <xsl:otherwise/>
+      </xsl:choose>
+    </xsl:variable>
+    <xsl:variable name="initialiser">
+      <xsl:choose>
+        <xsl:when test="@default">
+          <xsl:choose>
+            <xsl:when test="$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="$nullable-decoration = '?'"> = null</xsl:when>
+        <xsl:when test="@type = 'boolean'"> = false</xsl:when>
+        <xsl:when test="$type = 'int'"> = 0</xsl:when>
+        <xsl:when test="$type = 'double'"> = 0.0</xsl:when>
+        <xsl:when test="$type = 'Decimal'"> = 0.0M</xsl:when>
+        <xsl:when test="$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="@definition"/>
+          </xsl:variable>
+          <xsl:value-of select="/application/definition[@name=$definition]/@pattern"/>
+        </xsl:when>
+      </xsl:choose>
+    </xsl:variable>
+    <xsl:if test="string-length( $validationpattern) &gt; 0">
+        private Regex <xsl:value-of select="@name"/>Validator = new Regex( "<xsl:value-of select="$validationpattern"/>");
+    </xsl:if>
+
+        private <xsl:value-of select="$type"/><xsl:value-of select="$nullable-decoration"/> _<xsl:value-of select="@name"/> <xsl:value-of select="$initialiser"/>;
+
+        public virtual <xsl:value-of select="$type"/><xsl:value-of select="$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="@definition"/>
+    </xsl:variable>
+    <xsl:variable name="maximum">
+      <xsl:value-of select="/application/definition[@name=$definition]/@maximum"/>
+    </xsl:variable>
+    <xsl:variable name="minimum">
+      <xsl:value-of select="/application/definition[@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 $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="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>
+  
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/ADL.NET/Trans/adl2hibernate.xsl b/ADL.NET/Trans/adl2hibernate.xsl
new file mode 100755
index 0000000..18e2a57
--- /dev/null
+++ b/ADL.NET/Trans/adl2hibernate.xsl
@@ -0,0 +1,247 @@
+<?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: af $
+      $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>
+    </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>
+    </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>
\ No newline at end of file
diff --git a/ADL.NET/Trans/adl2mssql.xsl b/ADL.NET/Trans/adl2mssql.xsl
new file mode 100755
index 0000000..ed6242c
--- /dev/null
+++ b/ADL.NET/Trans/adl2mssql.xsl
@@ -0,0 +1,471 @@
+<?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: af $
+      $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"/>
+
+        <xsl:apply-templates select="entity" mode="view"/>
+
+        -------------------------------------------------------------------------------------------------
+        --    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>
+      
+        -------------------------------------------------------------------------------------------------
+        --    end of file
+        -------------------------------------------------------------------------------------------------
+    </xsl:template>
+    
+    <xsl:template match="group">
+        execute sp_addrole @rolename = '<xsl:value-of select="@name"/>' 
+        
+        GO
+    </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 FOREIGN KEY ( "<xsl:value-of select="@name"/>") 
+            REFERENCES "<xsl:value-of select="@entity"/>" ON DELETE NO ACTION
+            
+        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:template>
+  
+      <xsl:template match="entity" mode="view">
+        <xsl:variable name="table" select="@name"/>
+        -------------------------------------------------------------------------------------------------
+        --    convenience view VW_DL_<xsl:value-of select="@name"/> for default list
+        -------------------------------------------------------------------------------------------------
+        
+        CREATE VIEW "VW_DL_<xsl:value-of select="@name"/>" AS
+        SELECT "<xsl:value-of select="@name"/>"."<xsl:value-of select="@name"/>Id",
+        <xsl:for-each select="property[@type!='link']">
+            <xsl:choose>
+               <xsl:when test="@type='entity'">
+                   <xsl:call-template name="distinctfield">
+                       <xsl:with-param name="table" select="@entity"/>
+                       <xsl:with-param name="alias" select="@name"/>
+                   </xsl:call-template> AS <xsl:value-of select="@name"/></xsl:when>
+                <xsl:otherwise>"<xsl:value-of select="$table"/>"."<xsl:value-of select="@name"/>"</xsl:otherwise>
+            </xsl:choose><xsl:choose>
+                <xsl:when test="position() = last()"></xsl:when>
+                <xsl:otherwise>,
+                </xsl:otherwise>
+            </xsl:choose>
+        </xsl:for-each>
+        FROM  "<xsl:value-of select="@name"/>" <xsl:for-each 
+          select="property[@type='entity']">, "<xsl:value-of select="@entity"/>" AS "<xsl:value-of select="@name"/>"</xsl:for-each>
+        <xsl:text>
+        </xsl:text>
+        <xsl:for-each select="property[@type='entity']">
+            <xsl:choose>
+            <xsl:when test="position() = 1">WHERE </xsl:when>
+            <xsl:otherwise>AND   </xsl:otherwise>
+            </xsl:choose>"<xsl:value-of select="$table"/>"."<xsl:value-of 
+                select="@name"/>" = "<xsl:value-of select="@name"/>"."<xsl:value-of select="@entity"/>Id"
+        </xsl:for-each>
+        
+        GO
+
+        ----  permissions  ------------------------------------------------------------------------------
+        <xsl:for-each select="permission">
+            <xsl:call-template name="viewpermission">
+                <xsl:with-param name="table" select="$table"/>
+            </xsl:call-template>
+        </xsl:for-each>
+        
+        <!-- link tables -->
+        <xsl:for-each select="property[@type='link']">
+            <xsl:call-template name="linktable">
+                <xsl:with-param name="nearside" select="$table"/>
+            </xsl:call-template>
+        </xsl:for-each>
+        
+    </xsl:template>
+     
+    <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="viewpermission">
+        <xsl:param name="table"/>
+        <!-- decode the permissions for a convenience view -->
+        <xsl:choose>
+            <xsl:when test="@permission='none'">REVOKE ALL ON "VW_DL_<xsl:value-of 
+                select="$table"/>" FROM <xsl:value-of select="@group"/> 
+              
+                GO</xsl:when>
+            <xsl:when test="@permission='insert'">REVOKE ALL ON "VW_DL_<xsl:value-of 
+                select="$table"/>" FROM <xsl:value-of select="@group"/> 
+              
+                GO</xsl:when>
+            <xsl:otherwise>GRANT SELECT ON "VW_DL_<xsl:value-of 
+                select="$table"/>" TO <xsl:value-of select="@group"/> 
+              
+                GO</xsl:otherwise>
+        </xsl:choose>
+        <xsl:text>
+            
+        </xsl:text>
+    </xsl:template>
+    
+    
+    <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">
+          ALTER TABLE "<xsl:value-of select="$tablename"/>"
+          ADD FOREIGN KEY ( "<xsl:value-of select="$nearside"/>Id")
+          REFERENCES "<xsl:value-of select="$nearside"/>" ON DELETE NO ACTION
+
+          GO
+
+          ALTER TABLE "<xsl:value-of select="$tablename"/>"
+          ADD FOREIGN KEY ( "<xsl:value-of select="$farside"/>Id")
+          REFERENCES "<xsl:value-of select="$nearside"/>" ON DELETE NO ACTION
+
+          GO
+
+            </xsl:when>
+            <xsl:otherwise>
+          ALTER TABLE "<xsl:value-of select="$tablename"/>"
+          ADD FOREIGN KEY ( "<xsl:value-of select="$nearside"/>Id")
+          REFERENCES "<xsl:value-of select="$nearside"/>" ON DELETE CASCADE
+
+          GO
+
+          ALTER TABLE "<xsl:value-of select="$tablename"/>"
+          ADD FOREIGN KEY ( "<xsl:value-of select="@entity"/>Id")
+          REFERENCES "<xsl:value-of select="@entity"/>" ON DELETE CASCADE
+
+          GO
+
+
+            </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>
diff --git a/ADL.NET/Trans/adl2psql.xsl b/ADL.NET/Trans/adl2psql.xsl
new file mode 100755
index 0000000..fc2707b
--- /dev/null
+++ b/ADL.NET/Trans/adl2psql.xsl
@@ -0,0 +1,321 @@
+<?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 <sb@cygnets.co.uk>							-->
+    <!--	Created:	24th January 2006										-->
+    <!--	Copyright:	(c) 2008 Cygnet Solutions									-->
+    <!--
+        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 [sb@cygnets.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>
diff --git a/ADL.NET/Trans/adl2views.xsl b/ADL.NET/Trans/adl2views.xsl
new file mode 100755
index 0000000..e9caa45
--- /dev/null
+++ b/ADL.NET/Trans/adl2views.xsl
@@ -0,0 +1,1135 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+  <!--
+    C1873 SRU Hospitality
+    adl2views.xsl
+    
+    (c) 2007 Cygnet Solutions Ltd
+    
+    Transform ADL into velocity view templates
+    
+    $Author: af $
+    $Revision: 1.1 $
+    $Date: 2008-01-09 15:01:45 $
+  -->
+  <!-- WARNING WARNING WARNING: Do NOT reformat this file! 
+     Whitespace (or lack of it) is significant! -->
+
+  <!--
+    TODO: this transform BADLY needs to be refactored! It is /crap/!
+  -->
+  <xsl:output method="xml" indent="yes" encoding="UTF-8" omit-xml-declaration="yes"/>
+
+  <!-- The locale for which these views are generated 
+      TODO: we need to generate views for each available locale, but this is not
+      yet implemented. When it is we will almost certainly still need a 'default locale' -->
+  <xsl:param name="locale" select="en-UK"/>
+
+  <!-- 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 when 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:template match="application">
+    <output>
+      <xsl:apply-templates select="entity"/>
+      <!-- make sure extraneous junk doesn't get into the last file generated,
+      by putting it into a separate file -->
+      <xsl:comment> [ cut here: next file 'tail.txt' ] </xsl:comment>
+    </output>
+  </xsl:template>
+
+  <xsl:template match="entity">
+    <xsl:apply-templates select="form"/>
+    <xsl:apply-templates select="list"/>
+    <xsl:text>
+    </xsl:text>
+    <xsl:comment> [ cut here: next file '<xsl:value-of select="concat( @name, '/maybedelete.auto.vm')"/>' ] </xsl:comment>
+    <xsl:text>
+    </xsl:text>
+    <html>
+      <xsl:comment>
+        #set( $title = "<xsl:value-of select="concat( 'Really delete ', @name)"/> $instance.UserIdentifier")
+      </xsl:comment>
+      <head>
+        <xsl:call-template name="head"/>
+        <xsl:comment>
+          Auto generated Velocity maybe-delete form for <xsl:value-of select="@name"/>,
+          generated from ADL.
+
+          Generated using adl2views.xsl <xsl:value-of select="$transform-revision"/>
+        </xsl:comment>
+        ${Ajax.InstallScripts()}
+        ${FormHelper.InstallScripts()}
+        ${Validation.InstallScripts()}
+        ${Scriptaculous.InstallScripts()}
+      </head>
+      <body>
+        <xsl:call-template name="top"/>
+        <form action="delete.rails">
+          <xsl:choose>
+            <xsl:when test="@natural-key">
+              <!-- create a hidden widget for the natural primary key -->
+              ${FormHelper.HiddenField( "instance.<xsl:value-of select="@natural-key"/>")}
+            </xsl:when>
+            <xsl:otherwise>
+              <!-- there isn't a natural primary key; create a hidden widget 
+                  for the abstract primary key -->
+              ${FormHelper.HiddenField( "instance.<xsl:value-of select="@name"/>Id")}
+            </xsl:otherwise>
+          </xsl:choose>
+          <table>
+            <tr align="left" valign="top" class="actionDangerous">
+              <td class="actionDangerous">
+                Really delete?
+              </td>
+              <td class="widget">
+                <select name="reallydelete">
+                  <option value="false">No, don't delete it</option>
+                  <option value="true">Yes, do delete it</option>
+                </select>
+              </td>
+              <td class="actionDangerous" style="text-align:right">
+                <input type="submit" name="command" value="Go!" />
+              </td>
+            </tr>
+          </table>
+        </form>
+        <xsl:call-template name="foot"/>
+      </body>
+    </html>
+  </xsl:template>
+
+  <!-- layout of forms -->
+
+  <xsl:template match="form">
+    <xsl:variable name="formname" select="@name"/>
+    <xsl:variable name="aoran">
+      <xsl:variable name="initial" select="substring( ancestor::entity/@name, 1, 1)"/>
+      <xsl:choose>
+        <xsl:when test="$initial = 'A'">an</xsl:when>
+        <xsl:when test="$initial = 'E'">an</xsl:when>
+        <xsl:when test="$initial = 'I'">an</xsl:when>
+        <xsl:when test="$initial = 'O'">an</xsl:when>
+        <xsl:when test="$initial = 'U'">an</xsl:when>
+        <xsl:otherwise>a</xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    <xsl:text>
+    </xsl:text>
+    <xsl:comment> [ cut here: next file '<xsl:value-of select="concat( ancestor::entity/@name, '/', @name)"/>.auto.vm' ] </xsl:comment>
+    <xsl:text>
+    </xsl:text>
+    <html>
+      <xsl:comment>
+        #if ( $instance)
+        #set( $title = "<xsl:value-of select="concat( 'Edit ', ' ', ancestor::entity/@name)"/> $instance.UserIdentifier")
+        #else
+        #set( $title = "Add a new <xsl:value-of select="ancestor::entity/@name"/>")
+        #end
+      </xsl:comment>
+      <head>
+        <xsl:call-template name="head"/>
+        <xsl:comment>
+          Auto generated Velocity form for <xsl:value-of select="@name"/>,
+          generated from ADL.
+
+          Generated using adl2views.xsl <xsl:value-of select="$transform-revision"/>
+        </xsl:comment>
+        ${Ajax.InstallScripts()}
+        ${FormHelper.InstallScripts()}
+        ${Validation.InstallScripts()}
+        ${Scriptaculous.InstallScripts()}
+        ${DateTime.InstallScripts()}
+        ${ShuffleWidgetHelper.InstallScripts()}
+        <script type="text/javascript" language='JavaScript1.2' src="../script/panes.js"></script>
+
+        <script type='text/javascript' language='JavaScript1.2'>
+          var panes = new Array( <xsl:for-each select='fieldgroup'>
+            "<xsl:value-of select='@name'/>"<xsl:choose>
+              <xsl:when test="position() = last()"/>
+              <xsl:otherwise>,</xsl:otherwise>
+            </xsl:choose></xsl:for-each> );
+
+          function performInitialisation()
+          {
+          <xsl:for-each select="../property[@type='link']">
+            document.<xsl:value-of select="$formname"/>.<xsl:value-of select="@name"/>.submitHandler = shuffleSubmitHandler;
+          </xsl:for-each>
+            var validator = new Validation('<xsl:value-of select="$formname"/>', {immediate : true, useTitles : true});
+          <xsl:if test="fieldgroup">
+            switchtab( '<xsl:value-of select="fieldgroup[1]/@name"/>');
+          </xsl:if>
+          }
+
+        </script>
+        <style type="text/css">
+          <xsl:for-each select="../property[@required='true']">
+            #<xsl:value-of select="concat( 'advice-required-instance_', @name)"/>
+            {
+            color: white;
+            background-color: rgb( 198, 0, 57);
+            font-style: italic;
+            }
+          </xsl:for-each>
+        </style>
+      </head>
+      <body onload="performInitialisation()">
+        <xsl:call-template name="top"/>
+        <div class="content">
+          #if ( $Flash.errors)
+          <div class="warning">
+          <h2>Errors were encountered</h2>
+          
+          <ul>
+            #foreach ($error in $Flash.errors)
+            <li>
+              $error
+            </li>
+            #end
+          </ul>
+          </div>
+          #end
+          #if ( $messages.Count == 0)
+          <!-- if I try to test for $messages.Count &gt; 0,  I get the &gt; copied straight through to 
+          the output instead of the entity value being substituted(?) -->
+          #else
+          <div class="information">
+            #foreach ( $message in $messages)
+            <p>
+              $message
+            </p>
+            #end
+          </div>
+          #end
+          <form method="post" onsubmit="invokeSubmitHandlers( this)">
+            <xsl:attribute name="action">
+              <xsl:value-of select="concat( $formname, 'SubmitHandler.rails')"/>
+            </xsl:attribute>
+            <xsl:attribute name="name">
+              <xsl:value-of select="$formname"/>
+            </xsl:attribute>
+            <xsl:attribute name="id">
+              <xsl:value-of select="$formname"/>
+            </xsl:attribute>
+            <xsl:choose>
+              <xsl:when test="ancestor::entity/@natural-key">
+                <xsl:variable name="keyfield" select="ancestor::entity/@natural-key"/>
+                <xsl:choose>
+                  <xsl:when test="@properties='all'">
+                    <!-- no need to emit a hidden widget for the natural key, as there will be a 
+                      non-hidden one anyway -->
+                  </xsl:when>
+                  <xsl:when test="field[@name=$keyfield]">
+                    <!-- no need to emit a hidden widget for the natural key, as there will be a 
+                      non-hidden one anyway -->
+                  </xsl:when>
+                  <xsl:otherwise>
+                    <!-- create a hidden widget for the natural primary key -->
+                    ${FormHelper.HiddenField( "instance.<xsl:value-of select="$keyfield"/>")}
+                  </xsl:otherwise>
+                </xsl:choose>
+              </xsl:when>
+              <xsl:otherwise>
+                <!-- there isn't a natural primary key; create a hidden widget 
+                  for the abstract primary key -->
+                ${FormHelper.HiddenField( "instance.<xsl:value-of select="ancestor::entity/@name"/>Id")}
+              </xsl:otherwise>
+            </xsl:choose>
+            <xsl:if test="fieldgroup">
+              <div id="tabbar">
+                <xsl:for-each select="fieldgroup">
+                  <span class="tab">
+                    <xsl:attribute name="id">
+                      <xsl:value-of select="concat( @name, 'tab')"/>
+                    </xsl:attribute>
+                    <a>
+                      <xsl:attribute name="href">
+                        <xsl:value-of select="concat( '#', @name, 'anchor')"/>
+                      </xsl:attribute>
+                      <xsl:attribute name="onclick">switchtab( '<xsl:value-of select="@name"/>'); return false;</xsl:attribute>
+                      <xsl:call-template name="showprompt">
+                        <xsl:with-param name="fallback" select="@name"/>
+                      </xsl:call-template>
+                    </a>
+                  </span>
+                </xsl:for-each>
+              </div>
+            </xsl:if>
+            <xsl:apply-templates select="fieldgroup"/>
+            <div class="pane">
+              <table>
+                <xsl:choose>
+                  <xsl:when test="@properties='listed'">
+                    <xsl:apply-templates select="field|auxlist|verb"/>
+                  </xsl:when>
+                  <xsl:otherwise>
+                    <xsl:apply-templates select="ancestor::entity/property"/>
+                  </xsl:otherwise>
+                </xsl:choose>
+                <tr class="actionSafe">
+                  <td class="actionSafe" colspan="2">
+                    To save this record
+                  </td>
+                  <td class="actionSafe" style="text-align:right">
+                    <button type="submit" name="command" value="store">Save this!</button>
+                  </td>
+                </tr>
+                <tr align="left" valign="top" class="actionDangerous">
+
+                  <td class="actionDangerous" colspan="2">
+                    To delete this record
+                  </td>
+                  <td class="actionDangerous" style="text-align:right">
+                    <button type="submit" name="command" value="delete">Delete this!</button>
+                  </td>
+                </tr>
+              </table>
+            </div>
+          </form>
+        </div>
+        <xsl:call-template name="foot"/>
+      </body>
+    </html>
+  </xsl:template>
+
+  <xsl:template match="fieldgroup">
+    <div class="pane">
+      <xsl:attribute name="id">
+        <xsl:value-of select="concat( @name, 'pane')"/>
+      </xsl:attribute>
+      <xsl:attribute name="style">
+        <xsl:choose>
+          <xsl:when test="position() = 1"/>
+          <xsl:otherwise>display: none</xsl:otherwise>
+        </xsl:choose>
+      </xsl:attribute>
+      <a>
+        <xsl:attribute name="name">
+          <xsl:value-of select="concat( @name, 'anchor')"/>
+        </xsl:attribute>
+        <h3>
+          <xsl:call-template name="showprompt">
+            <xsl:with-param name="fallback" select="@name"/>
+          </xsl:call-template>
+        </h3>
+      </a>
+      <table>
+        <xsl:apply-templates select="field|verb|auxlist"/>
+      </table>
+    </div>
+  </xsl:template>
+
+  <xsl:template match="auxlist">
+    <xsl:variable name="listprop" select="@property"/>
+    <xsl:variable name="farent" select="ancestor::entity/property[@name=$listprop]/@entity"/>
+    <xsl:variable name="nearent" select="ancestor::entity/@name"/>
+    <xsl:variable name="farid">
+      <xsl:choose>
+        <xsl:when test="//entity[@name=$farent]/@natural-key">
+          <xsl:value-of select="//entity[@name=$farent]/@natural-key"/>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:value-of select="concat( $farent, 'Id')"/>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    <xsl:variable name="farkey">
+      <xsl:value-of select="//entity[@name=$farent]/property[@entity=$nearent]/@name"/>
+    </xsl:variable>
+    <xsl:variable name="nearkey">
+      <xsl:choose>
+        <xsl:when test="ancestor::entity[@natural-key]">
+          <xsl:value-of select="ancestor::entity[@natural-key]"/>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:value-of select="concat( $nearent, 'Id')"/>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    <xsl:variable name="action" select="concat( '../', $farent, '/', @onselect)"/>
+    <xsl:if test="@canadd='true'">
+      <tr>
+        <td>
+          <xsl:attribute name="colspan">
+            <xsl:value-of select="count( field)"/>
+          </xsl:attribute>
+          <a>
+            <xsl:attribute name="href">
+              <xsl:value-of select="concat( $action, '.rails?', $farkey, '=$instance.', $nearkey)"/>
+            </xsl:attribute>
+            Add a new <xsl:value-of select="$farent"/>
+          </a>
+        </td>
+      </tr>
+    </xsl:if>
+    <xsl:choose>
+      <xsl:when test="@properties='listed'">
+        <tr>
+          <xsl:for-each select="field">
+            <xsl:variable name="fieldprop" select="@property"/>
+            <th>
+              <!-- Getting the prompt for the field from a property of another entity is a bit 
+                complex... -->
+              <xsl:call-template name="showprompt">
+                <xsl:with-param name="node" select="//entity[@name=$farent]/property[@name=$fieldprop]"/>
+                <xsl:with-param name="fallback" select="@property"/>
+              </xsl:call-template>
+            </th>
+          </xsl:for-each>
+          <th>
+            -
+          </th>
+        </tr>
+        #foreach( $item in $instance.<xsl:value-of select="@property"/>)
+        #if ( $velocityCount % 2 == 0)
+        #set( $oddity = "even")
+        #else
+        #set( $oddity = "odd")
+        #end
+        <tr class="$oddity">
+          <xsl:for-each select="field">
+            <xsl:variable name="fieldprop" select="@property"/>
+            <td>
+              <xsl:choose>
+                <xsl:when test="//entity[@name=$farent]/property[@name=$fieldprop]/@type='entity'">
+                  #if ( $item.<xsl:value-of select="@property"/>)
+                  $item.<xsl:value-of select="@property"/>.UserIdentifier
+                  #end
+                </xsl:when>
+                <xsl:when test="//entity[@name=$farent]/property[@name=$fieldprop]/option">
+                  <!-- if we can get a prompt value for the option, it would be better to 
+                  show it than the raw value-->
+                  <xsl:for-each select="//entity[@name=$farent]/property[@name=$fieldprop]/option">
+                    #if ( $item.<xsl:value-of select="$fieldprop"/> == '<xsl:value-of select="@value"/>')
+                    <xsl:call-template name="showprompt">
+                      <xsl:with-param name="fallback" select="@value"/>
+                    </xsl:call-template>
+                    #end
+                  </xsl:for-each>
+                </xsl:when>
+                <xsl:otherwise>
+                  $!item.<xsl:value-of select="@property"/>
+                </xsl:otherwise>
+              </xsl:choose>
+            </td>
+          </xsl:for-each>
+          <td>
+            <a>
+              <xsl:attribute name="href">
+                <xsl:value-of select="concat( $action, '.rails?', $farid, '=$item.', $farid)"/>
+              </xsl:attribute>
+              Edit!
+            </a>
+          </td>
+        </tr>
+        #end
+      </xsl:when>
+      <xsl:otherwise>
+        <!-- properties not listed, so therefore presumably all. TODO: This won't work, rewrite. Need to
+        find the entity of the property this auxlist depends on, and then interrogate that -->
+        <tr>
+          <xsl:for-each select="ancestor::entity/property[@distinct='user']">
+            <th>
+              <xsl:choose>
+                <xsl:when test="prompt[@locale=$locale]">
+                  <xsl:value-of select="prompt[@locale=$locale]/@prompt"/>
+                </xsl:when>
+                <xsl:otherwise>
+                  <xsl:value-of select="@name"/>
+                </xsl:otherwise>
+              </xsl:choose>
+            </th>
+          </xsl:for-each>
+          <th>-</th>
+        </tr>
+        #foreach( $instance in $instances)
+        #if ( $velocityCount % 2 == 0)
+        #set( $oddity = "even")
+        #else
+        #set( $oddity = "odd")
+        #end
+        <tr class="$oddity">
+          <xsl:for-each select="ancestor::entity/property[@distinct='user']">
+            <td>
+              $!instance.<xsl:value-of select="@name"/>
+            </td>
+          </xsl:for-each>
+          <td>
+            <a>
+              <xsl:attribute name="href">
+                <xsl:value-of select="concat( $action, '.rails?', ../@name, 'Id=$instance.', ../@name, 'Id')"/>
+              </xsl:attribute>
+              Edit!
+            </a>
+          </td>
+        </tr>
+        #end
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template match="verb">
+    <xsl:variable name="class">
+      <xsl:choose>
+        <xsl:when test="@dangerous='true'">actionDangerous</xsl:when>
+        <xsl:otherwise>actionSafe</xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    <tr>
+      <xsl:attribute name="class"><xsl:value-of select="$class"/></xsl:attribute>
+      <td colspan="2">
+        <xsl:attribute name="class">
+          <xsl:value-of select="$class"/>
+        </xsl:attribute>
+        <xsl:apply-templates select="help[@locale = $locale]"/>
+      </td>
+      <td style="text-align:right">
+        <xsl:attribute name="class">
+          <xsl:value-of select="$class"/>
+        </xsl:attribute>
+        <button name="command">
+          <xsl:attribute name="value">
+            <xsl:value-of select="@verb"/>
+          </xsl:attribute>
+          <xsl:call-template name="showprompt">
+            <xsl:with-param name="fallback" select="@verb"/>
+          </xsl:call-template>
+        </button>
+      </td>
+    </tr>
+  </xsl:template>
+
+  <xsl:template match="field">
+    <xsl:variable name="propname">
+      <xsl:value-of select="@property"/>
+    </xsl:variable>
+    <xsl:choose>
+      <xsl:when test="ancestor::entity/property[@name=$propname]">
+        <!-- there is a real property -->
+        <xsl:apply-templates select="ancestor::entity/property[@name=$propname]">
+          <xsl:with-param name="oddness">
+            <xsl:choose>
+              <xsl:when test="position() mod 2 = 0">even</xsl:when>
+              <xsl:otherwise>odd</xsl:otherwise>
+            </xsl:choose>
+          </xsl:with-param>
+        </xsl:apply-templates>
+      </xsl:when>
+      <xsl:otherwise>
+        <!-- it's presumably intended to be a computed field -->
+        Computed field? TODO: Not yet implememented
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  
+  <xsl:template match="property[@type='link']">
+    <!-- note! this template is only intended to match properties in the context of a form:
+      it may be we need to add a mode to indicate this! -->
+    <!-- for links we implement a shuffle widget, which extends over both columns -->
+    <!-- TODO: Permissions! -->
+    <xsl:param name="oddness" select="odd"/>
+    <tr>
+      <xsl:attribute name="class">
+        <xsl:value-of select="$oddness"/>
+      </xsl:attribute>
+      <td class="label" rowspan="2">
+        ${FormHelper.LabelFor( "instance.<xsl:value-of select="@name"/>", "<xsl:call-template name="showprompt">
+          <xsl:with-param name="fallback" select="@name"/>
+        </xsl:call-template>")}
+      </td>
+      <td class="widget" colspan="2">
+        <table>
+          <tr>
+            <td class="widget" rowspan="2">
+              ${ShuffleWidgetHelper.UnselectedOptions( "<xsl:value-of select="concat( @name, '_unselected')"/>", <xsl:value-of select="concat( '$all_', @name)"/>, $instance.<xsl:value-of select="@name"/>)}
+            </td>            
+            <td class="widget">
+              <input type="button" value="include &gt;&gt;">
+                <xsl:attribute name="onclick">
+                  <xsl:value-of select="concat( 'shuffle(', @name, '_unselected, ', @name, ')')"/>
+                </xsl:attribute>
+              </input>
+            </td>
+            <td class="widget" rowspan="2">
+              ${ShuffleWidgetHelper.SelectedOptions( "<xsl:value-of select="@name"/>", $instance.<xsl:value-of select="@name"/>)}
+            </td>
+          </tr>
+          <tr>
+            <td class="widget">
+              <input type="button" value="&lt;&lt; exclude">
+                <xsl:attribute name="onclick">
+                  <xsl:value-of select="concat( 'shuffle(', @name, ', ', @name, '_unselected)')"/>
+                </xsl:attribute>
+              </input>
+            </td>
+          </tr>
+        </table>
+      </td>
+    </tr>
+    <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 class="help" colspan="2">
+        <xsl:apply-templates select="help[@locale = $locale]"/>
+      </td>
+    </tr>
+  </xsl:template>
+
+
+  <xsl:template match="property[@type='text']">
+    <!-- note! this template is only intended to match properties in the context of a form:
+      it may be we need to add a mode to indicate this! -->
+    <!-- text box widgets, like shuffle widgets, extend over both columns -->
+    <!-- TODO: Permissions! -->
+    <xsl:param name="oddness" select="odd"/>
+    <xsl:variable name="if-missing">
+      <xsl:choose>
+        <xsl:when test="if-missing[@locale = $locale]">
+          <xsl:value-of select="if-missing[@locale = $locale]"/>
+        </xsl:when>
+        <xsl:when test="required='true'">You must provide a value for <xsl:value-of select="@name"/></xsl:when>
+        <xsl:otherwise>Enter a value for <xsl:value-of select="@name"/></xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    <tr>
+      <xsl:attribute name="class">
+        <xsl:value-of select="$oddness"/>
+      </xsl:attribute>
+      <td class="label" rowspan="2">
+        ${FormHelper.LabelFor( "instance.<xsl:value-of select="@name"/>", "<xsl:choose>
+          <xsl:when test="prompt[@locale = $locale]">
+            <xsl:apply-templates select="prompt[@locale = $locale]"/>
+          </xsl:when>
+          <xsl:otherwise>
+            <xsl:value-of select="@name"/>
+          </xsl:otherwise>
+        </xsl:choose>")}
+      </td>
+      <td class="widget" colspan="2">
+        ${FormHelper.TextArea( "instance.<xsl:value-of select="@name"/>", "%{rows='8' cols='60' title='<xsl:value-of select="$if-missing"/>'}")}
+      </td>
+    </tr>
+    <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 class="help" colspan="2">
+        <xsl:apply-templates select="help[@locale = $locale]"/>
+      </td>
+    </tr>
+  </xsl:template>
+
+  <xsl:template match="property">
+    <xsl:param name="oddness" select="odd"/>
+    <!-- note! this template is only intended to match properties in the context of a form:
+      it may be we need to add a mode to indicate this! -->
+    <!-- TODO: This really needs to be refactored -->
+    <!-- TODO: we really need to be able to handle different permissions for different 
+    groups. If the current user is not a member of a group which has read access to 
+    this widget, the widget shouldn't even appear (unless they have write but not read?); 
+    if they are not a member of a group which has write access, the widget should be 
+    disabled. I don't have time to implement this now as it is not trivial, but it is 
+    important! -->
+    <xsl:variable name="if-missing">
+      <xsl:choose>
+        <xsl:when test="if-missing[@locale = $locale]">
+          <xsl:value-of select="if-missing[@locale = $locale]"/>
+        </xsl:when>
+        <xsl:when test="@required='true'">
+          You must provide a value for <xsl:value-of select="@name"/>
+        </xsl:when>
+        <xsl:when test="@type='defined'">
+          The value for <xsl:value-of select="@name"/> must be <xsl:value-of select="@definition"/>
+        </xsl:when>
+        <xsl:when test="@type='entity'">
+          The value for <xsl:value-of select="@name"/> must be an instance of <xsl:value-of select="@entity"/>
+        </xsl:when>
+        <xsl:otherwise>
+          The value for <xsl:value-of select="@name"/> must be <xsl:value-of select="@type"/>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    <!-- TODO: this is a one-database-role permission model, because that's all SRU needs. 
+        Different permissions for different database groups is much more complex! Also, this 
+        handles permissions on only properties and entities, not on forms. Perhaps we need a 
+        Helper class? -->
+    <xsl:variable name="permission">
+      <xsl:choose>
+        <xsl:when test="permission">
+          <xsl:value-of select="permission[position()=1]/@permission"/>
+        </xsl:when>
+        <xsl:when test="../permission">
+          <xsl:value-of select="../permission[position()=1]/@permission"/>
+        </xsl:when>
+        <xsl:otherwise>none</xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    <tr>
+      <xsl:attribute name="class">
+        <xsl:value-of select="$oddness"/>
+      </xsl:attribute>
+      <td class="label">
+        ${FormHelper.LabelFor( "instance.<xsl:value-of select="@name"/>", "<xsl:call-template name="showprompt">
+          <xsl:with-param name="fallback" select="@name"/>
+        </xsl:call-template>")}
+      </td>
+      <td class="widget">
+        <xsl:choose>
+          <xsl:when test="$permission='none'">
+            [You are not authorised to see this data]
+          </xsl:when>
+          <xsl:when test="$permission='read'">
+            <xsl:choose>
+              <xsl:when test="@type='entity'">
+                <xsl:value-of select="concat('$instance.', @name, '.UserIdentifier')"/>
+              </xsl:when>
+              <!-- TODO: if @type='list' or 'link', should generate Velocity to generate ul list
+                of UserIdentifiers
+              -->
+              <xsl:otherwise>
+                <xsl:value-of select="concat('$instance.', @name)"/>
+              </xsl:otherwise>
+            </xsl:choose>
+          </xsl:when>
+          <!-- TODO: if $permission='insert', then you should get an editable widget if there 
+          is no current value, else a 'not authorised' message -->
+          <!-- TODO: if $permission='noedit', then you should get an editable widget if there 
+          is no current value, else just the value -->
+          <xsl:when test="@type='entity'">
+            <!-- a menu of the appropriate entity -->
+            #if ( $instance)
+              ${FormHelper.Select( "instance.<xsl:value-of select="@name"/>", $instance.<xsl:value-of select="@name"/>, <xsl:value-of select="concat( '$all_', @name)"/>, "%{firstoption='[unset]' firstoptionvalue='-1' text='UserIdentifier' value='<xsl:value-of select="concat( @entity, 'Id')"/>' title='<xsl:value-of select="normalize-space( $if-missing)"/>'}" )}
+            #else
+              ${FormHelper.Select( "instance.<xsl:value-of select="@name"/>", $<xsl:value-of select="@name"/>, <xsl:value-of select="concat( '$all_', @name)"/>, "%{firstoption='[unset]' firstoptionvalue='-1' text='UserIdentifier' value='<xsl:value-of select="concat( @entity, 'Id')"/>' title='<xsl:value-of select="normalize-space( $if-missing)"/>'}" )}
+            #end
+          </xsl:when>
+          <xsl:when test="@type='list'">
+            <!-- a multi-select menu of the appropriate entity -->
+            ${FormHelper.Select( "instance.<xsl:value-of select="@name"/>", $instance.<xsl:value-of select="@name"/>, <xsl:value-of select="concat( '$all_', @name)"/>, "%{multiple='multiple' size='8' text='UserIdentifier' value='<xsl:value-of select="concat( @entity, 'Id')"/>' title='<xsl:value-of select="normalize-space( $if-missing)"/>'}" )}
+          </xsl:when>
+          <xsl:when test="@type='defined'">
+            <!-- likely to be hardest of all... -->
+            <xsl:variable name="definition">
+              <xsl:value-of select="@definition"/>
+            </xsl:variable>
+            <xsl:variable name="maximum">
+              <xsl:value-of select="/application/definition[@name=$definition]/@maximum"/>
+            </xsl:variable>
+            <xsl:variable name="minimum">
+              <xsl:value-of select="/application/definition[@name=$definition]/@minimum"/>
+            </xsl:variable>
+            <xsl:variable name="validationpattern">
+              <xsl:value-of select="/application/definition[@name=$definition]/@pattern"/>
+            </xsl:variable>
+            <xsl:variable name="definedtype">
+              <xsl:value-of select="/application/definition[@name=$definition]/@type"/>
+            </xsl:variable>
+            <xsl:variable name="definedsize">
+              <xsl:value-of select="/application/definition[@name=$definition]/@size"/>
+            </xsl:variable>
+            <input type="text">
+              <xsl:attribute name="class">
+                <xsl:if test="@required='true'">required </xsl:if>
+                <xsl:choose>
+                  <xsl:when test="$definedtype='integer'">validate-digits</xsl:when>
+                  <xsl:when test="$definedtype='real'">validate-number</xsl:when>
+                  <xsl:when test="$definedtype='money'">validate-number</xsl:when>
+                  <xsl:when test="$definedtype='date'">date-field validate-date</xsl:when>
+                </xsl:choose>
+              </xsl:attribute>
+              <xsl:attribute name="id">
+                <xsl:value-of select="concat( 'instance_', @name)"/>
+              </xsl:attribute>
+              <xsl:attribute name="name">
+                <xsl:value-of select="concat( 'instance.', @name)"/>
+              </xsl:attribute>
+              <xsl:choose>
+                <xsl:when test="$definedsize &lt; 60">
+                  <xsl:attribute name="size">
+                    <xsl:value-of select="$definedsize"/>
+                  </xsl:attribute>
+                  <xsl:attribute name="maxlength">
+                    <xsl:value-of select="$definedsize"/>
+                  </xsl:attribute>
+                </xsl:when>
+                <xsl:when test="$definedsize &gt;= 60">
+                  <xsl:attribute name="size">
+                    <xsl:value-of select="60"/>
+                  </xsl:attribute>
+                  <xsl:attribute name="maxlength">
+                    <xsl:value-of select="$definedsize"/>
+                  </xsl:attribute>
+                </xsl:when>
+              </xsl:choose>
+              <xsl:attribute name="value">$!instance.<xsl:value-of select="@name"/></xsl:attribute>
+              <xsl:attribute name="title">
+                <xsl:value-of select="normalize-space( $if-missing)"/>
+              </xsl:attribute>
+            </input>
+            <xsl:if test="string-length( $minimum) &gt; 0 and string-length( $maximum) &gt; 0">
+              <div style="width:200px; height:20px; background: transparent url(../images/slider-images-track-right.png) no-repeat top right;">
+                <xsl:attribute name="id">
+                  <xsl:value-of select="concat( @name, '-track')"/>
+                </xsl:attribute>
+                <div style="position: absolute; width: 5px; height: 20px; background: transparent url(../images/slider-images-track-left.png) no-repeat top left">
+                  <xsl:attribute name="id">
+                    <xsl:value-of select="concat( @name, '-track-left')"/>
+                  </xsl:attribute>
+                </div>
+                <div style="width:19px; height:20px;">
+                  <xsl:attribute name="id">
+                    <xsl:value-of select="concat( @name, '-slider')"/>
+                  </xsl:attribute>
+                  <img src="../images/slider-images-handle.png" alt="" style="float: left;" />
+                </div>
+              </div>
+              <script type="text/javascript" language="javascript">
+                // &lt;![CDATA[
+                new Control.Slider('<xsl:value-of select="@name"/>-slider','<xsl:value-of select="@name"/>-track',{
+                  onSlide:function(v){$('<xsl:value-of select="concat( 'instance_', @name)"/>').value = <xsl:value-of select="$minimum"/>+ Math.floor(v*(<xsl:value-of select="$maximum - $minimum"/>))}
+                })
+                // ]]&gt;
+              </script>
+            </xsl:if>
+            <!-- TODO: generate javascript to do client-side validation -->
+          </xsl:when>
+          <xsl:when test="option">
+            <!-- if a property has options, we definitely want a select widget-->
+            <select>
+              <xsl:attribute name="id">
+                <xsl:value-of select="concat( 'instance_', @name)"/>
+              </xsl:attribute>
+              <xsl:attribute name="name">
+                <xsl:value-of select="concat( 'instance.', @name)"/>
+              </xsl:attribute>
+              <xsl:attribute name="title">
+                <xsl:value-of select="normalize-space( $if-missing)"/>
+              </xsl:attribute>
+              <xsl:apply-templates select="option"/>
+            </select>
+            <script type="text/javascript" language="javascript">
+                #set ( <xsl:value-of select="concat( '$', @name, '_sel_opt')"/>="<xsl:value-of select="concat( @name, '-$instance.', @name)"/>")
+                option = document.getElementById( "<xsl:value-of select="concat( '$', @name, '_sel_opt')"/>");
+
+                if ( option != null)
+                {
+                  option.selected = true;
+                }
+            </script>
+          </xsl:when>
+          <xsl:when test="@type='boolean'">
+            ${FormHelper.CheckboxField( "instance.<xsl:value-of select="@name"/>")}
+          </xsl:when>
+          <xsl:when test="@type='date'">
+            <xsl:variable name="class"><xsl:if test="@required='true'">required </xsl:if>date-field validate-date</xsl:variable>
+            ${FormHelper.TextField( "instance.<xsl:value-of select="@name"/>", "%{class='<xsl:value-of select="$class"/>' size='10' maxlength='10'}")}
+          </xsl:when>
+          <xsl:otherwise>
+            <xsl:variable name="class">
+              <xsl:if test="@required='true'">required </xsl:if><xsl:choose>
+                <xsl:when test="@type='integer'">validate-digits</xsl:when>
+                <xsl:when test="@type='real'">validate-number</xsl:when>
+                <xsl:when test="@type='money'">validate-number</xsl:when>
+              </xsl:choose>
+            </xsl:variable>
+            <xsl:variable name="size">
+              <xsl:choose>
+                <xsl:when test="@size &lt; 60">
+                  <xsl:value-of select="@size"/>
+                </xsl:when>
+                <xsl:when test="@type='integer'">8</xsl:when>
+                <xsl:when test="@type='real'">8</xsl:when>
+                <xsl:when test="@type='money'">8</xsl:when>
+                <xsl:otherwise>60</xsl:otherwise>
+              </xsl:choose>
+            </xsl:variable>
+            ${FormHelper.TextField( "instance.<xsl:value-of select="@name"/>", "%{class='<xsl:value-of select="$class"/>' title='<xsl:value-of select="normalize-space( $if-missing)"/>' size='<xsl:value-of select="$size"/>' maxlength='<xsl:value-of select="@size"/>'}")}
+         </xsl:otherwise>
+      </xsl:choose>        
+      </td>
+      <td class="help">
+        <xsl:apply-templates select="help[@locale = $locale]"/>
+      </td>
+    </tr>
+  </xsl:template>
+
+  <xsl:template match="prompt">
+    <xsl:value-of select="@prompt"/>
+  </xsl:template>
+  
+  <xsl:template match="help">
+    <xsl:apply-templates/>
+  </xsl:template>
+
+  <xsl:template match="option">
+    <option>
+      <xsl:attribute name="id"><xsl:value-of select="../@name"/>-<xsl:value-of select="@value"/></xsl:attribute>
+      <xsl:attribute name="value">
+        <xsl:value-of select="@value"/>
+      </xsl:attribute>
+      <xsl:choose>
+        <xsl:when test="prompt[@locale=$locale]">
+          <xsl:value-of select="prompt[@locale=$locale]/@prompt"/>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:value-of select="@value"/>
+        </xsl:otherwise>
+      </xsl:choose>
+    </option>
+  </xsl:template>
+    
+  <!-- layout of lists -->
+
+  <xsl:template match="list">
+    <xsl:variable name="action" select="@onselect"/>
+    <xsl:text>
+    </xsl:text>
+    <xsl:comment> [ cut here: next file '<xsl:value-of select="concat( ../@name, '/', @name)"/>.auto.vm' ] </xsl:comment>
+    <xsl:text>
+    </xsl:text>
+    <xsl:variable name="withpluralsuffix">
+      <!-- English-laguage syntactic sugar of entity name -->
+      <xsl:choose>
+        <xsl:when test="../@name='Person'">People</xsl:when>
+        <xsl:when test="starts-with( substring(../@name, string-length(../@name) ), 's')">
+          <xsl:value-of select="../@name"/>es
+        </xsl:when>
+        <xsl:when test="starts-with( substring(../@name, string-length(../@name) ), 'y')">
+          <xsl:value-of select="substring( ../@name, 0, string-length(../@name) )"/>ies
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:value-of select="../@name"/>s
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    <html>
+      <head>
+        #set( $title = "<xsl:value-of select="normalize-space( concat( 'List ', $withpluralsuffix))"/>")
+        <xsl:call-template name="head"/>
+        <xsl:comment>
+          Auto generated Velocity list for <xsl:value-of select="@name"/>,
+          generated from ADL.
+
+          Generated using adl2listview.xsl <xsl:value-of select="$transform-revision"/>
+        </xsl:comment>
+        ${Ajax.InstallScripts()}
+        ${FormHelper.InstallScripts()}
+        ${Validation.InstallScripts()}
+        ${Scriptaculous.InstallScripts()}
+        ${DateTime.InstallScripts()}
+      </head>
+      <body>
+
+        <xsl:call-template name="top"/>
+        <div class="content">
+          <xsl:if test="@name='list'">
+            <!-- this is a hack. There shouldn't be anything magic about a list named 'list'. 
+          We need lists (and forms) to have some sort of pragma to guide the transformation 
+          process -->
+            <div class="controls">
+              <span class="pagination status">
+                Showing $instances.FirstItem - $instances.LastItem of $instances.TotalItems
+              </span>
+              <span class="pagination control">
+                #if($instances.HasFirst) $PaginationHelper.CreatePageLink( 1, "&lt;&lt;" ) #end
+                #if(!$instances.HasFirst) &lt;&lt; #end
+              </span>
+              <span class="pagination control">
+                #if($instances.HasPrevious) $PaginationHelper.CreatePageLink( $instances.PreviousIndex, "&lt;" ) #end
+                #if(!$instances.HasPrevious) &lt; #end
+              </span>
+              <span class="pagination control">
+                #if($instances.HasNext) $PaginationHelper.CreatePageLink( $instances.NextIndex, "&gt;" ) #end
+                #if(!$instances.HasNext) &gt; #end
+              </span>
+              <span class="pagination control">
+                #if($instances.HasLast) $PaginationHelper.CreatePageLink( $instances.LastIndex, "&gt;&gt;" ) #end
+                #if(!$instances.HasLast) &gt;&gt; #end
+              </span>
+              <xsl:if test="../form">
+                <span class="add">
+                  <a>
+                    <xsl:attribute name="href">
+                      <xsl:value-of select="concat( ../form[position() = 1]/@name, '.rails')"/>
+                    </xsl:attribute>
+                    Add a new <xsl:value-of select="../@name"/>
+                  </a>
+                </span>
+              </xsl:if>
+              <div class="search">
+                <form method="get">
+                  <xsl:attribute name="action">
+                    <xsl:value-of select="@name"/>.rails
+                  </xsl:attribute>
+                  <label for="searchexpr">Search:</label>
+                  <input type="text" id="searchexpr" name="searchexpr" size="12"/>
+                </form>
+              </div>
+            </div>
+          </xsl:if>
+          <table>
+            <xsl:choose>
+              <xsl:when test="@properties='listed'">
+                <tr>
+                  <xsl:for-each select="field">
+                    <th>
+                      <xsl:variable name="pname" select="@property"/>
+                      <xsl:variable name="property" select="ancestor::entity/property[@name=$pname]"/>
+                      <xsl:choose>
+                        <xsl:when test="$property/prompt[@locale=$locale]">
+                          <xsl:value-of select="$property/prompt[@locale=$locale]/@prompt"/>
+                        </xsl:when>
+                        <xsl:otherwise>
+                          <xsl:value-of select="@property"/>
+                        </xsl:otherwise>
+                      </xsl:choose>
+                    </th>
+                  </xsl:for-each>
+                  <th>-</th>
+                </tr>
+                #foreach( $instance in $instances)
+                #if ( $velocityCount % 2 == 0)
+                #set( $oddity = "even")
+                #else
+                #set( $oddity = "odd")
+                #end
+                <tr class="$oddity">
+                  <xsl:for-each select="field">
+                    <td>
+                      $!instance.<xsl:value-of select="@property"/>
+                    </td>
+                  </xsl:for-each>
+                  <td>
+                    <a>
+                      <xsl:attribute name="href">
+                        <xsl:value-of select="concat( $action, '.rails?', ../@name, 'Id=$instance.', ../@name, 'Id')"/>
+                      </xsl:attribute>
+                      Edit!
+                    </a>
+                  </td>
+                </tr>
+                #end
+              </xsl:when>
+              <xsl:otherwise>
+                <tr>
+                  <xsl:for-each select="ancestor::entity/property[@distinct='user']">
+                    <th>
+                      <xsl:choose>
+                        <xsl:when test="prompt[@locale=$locale]">
+                          <xsl:value-of select="prompt[@locale=$locale]/@prompt"/>
+                        </xsl:when>
+                        <xsl:otherwise>
+                          <xsl:value-of select="@name"/>
+                        </xsl:otherwise>
+                      </xsl:choose>
+                    </th>
+                  </xsl:for-each>
+                  <th>-</th>
+                </tr>
+                #foreach( $instance in $instances)
+                #if ( $velocityCount % 2 == 0)
+                #set( $oddity = "even")
+                #else
+                #set( $oddity = "odd")
+                #end
+                <tr class="$oddity">
+                  <xsl:for-each select="ancestor::entity/property[@distinct='user']">
+                <td>
+                  $!instance.<xsl:value-of select="@name"/>
+                </td>
+              </xsl:for-each>
+              <td>
+                <a>
+                  <xsl:attribute name="href">
+                    <xsl:value-of select="concat( $action, '.rails?', ../@name, 'Id=$instance.', ../@name, 'Id')"/>
+                  </xsl:attribute>
+                  Edit!
+                </a>
+              </td>
+            </tr>
+            #end
+          </xsl:otherwise>
+        </xsl:choose>
+      </table>
+      </div>
+      <xsl:call-template name="foot"/>
+    </body>
+    </html>
+  </xsl:template>
+
+  <!-- overall page layout -->
+  
+  <xsl:template name="head">
+    <xsl:choose>
+      <xsl:when test="head">
+        <xsl:apply-templates select="head/*"/>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:apply-templates select="/application/content/head/*"/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  
+  <xsl:template name="top">
+    <xsl:choose>
+      <xsl:when test="top">
+        <xsl:apply-templates select="top/*"/>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:apply-templates select="/application/content/top/*"/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template name="foot">
+    <xsl:choose>
+      <xsl:when test="foot">
+        <xsl:apply-templates select="foot/*"/>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:apply-templates select="/application/content/foot/*"/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <!-- if this node (default to current node) has a child of type prompt for the current locale, 
+    show that prompt; else show the first prompt child with locale='default' if any;
+    else show the value of the fallback param -->
+  <xsl:template name="showprompt">
+    <xsl:param name="fallback" select="Unknown"/>
+    <xsl:param name="node" select="."/>
+    <xsl:choose>
+      <xsl:when test="$node/prompt[@locale=$locale]">
+        <xsl:value-of select="$node/prompt[@locale=$locale][1]/@prompt"/>
+      </xsl:when>
+      <xsl:when test="$node/prompt[@locale='default']">
+        <xsl:value-of select="$node/prompt[@locale='default'][1]/@prompt"/>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:value-of select="$fallback"/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <!-- just copy anything we can't match -->
+  <xsl:template match="@* | node()">
+    <xsl:copy>
+      <xsl:apply-templates select="@* | node()"/>
+    </xsl:copy>
+  </xsl:template>
+
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/ADL.NET/Trans/datadescriber.xsl b/ADL.NET/Trans/datadescriber.xsl
new file mode 100755
index 0000000..8b1d8dd
--- /dev/null
+++ b/ADL.NET/Trans/datadescriber.xsl
@@ -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>
diff --git a/ADL.NET/Trans/hibernate2adl.xsl b/ADL.NET/Trans/hibernate2adl.xsl
new file mode 100755
index 0000000..90f1b7d
--- /dev/null
+++ b/ADL.NET/Trans/hibernate2adl.xsl
@@ -0,0 +1,100 @@
+<?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
+      hibernate2adl.xsl
+      
+      (c) 2007 Cygnet Solutions Ltd
+      
+      Transforms hibernate mapping file into partial ADL file. Not complete,
+      because the whole point of having an ADL is that the hibernate mapping
+      is not sufficiently rich.
+      
+      $Author: af $
+      $Revision: 1.1 $
+  -->
+
+  <xsl:output indent="yes" method="xml" encoding="utf-8" doctype-system="file:../j2adl.dtd"/>
+  
+  <xsl:template match="hibernate-mapping">
+    <application name="unset" version="unset">
+      <xsl:apply-templates select="class"/>
+    </application>  
+  </xsl:template>
+
+  <xsl:template match="class">
+    <entity>
+      <xsl:attribute name="name">
+        <xsl:value-of select="@name"/>
+      </xsl:attribute>
+      <xsl:apply-templates/>
+    </entity>
+  </xsl:template>
+
+  <xsl:template match="property">
+    <property>
+      <xsl:attribute name="name">
+        <xsl:value-of select="@name"/>
+      </xsl:attribute>
+      <xsl:attribute name="type">
+        <xsl:choose>
+          <xsl:when test="@type = 'DateTime'">date</xsl:when>
+          <xsl:when test="@type = 'String'">string</xsl:when>
+          <xsl:when test="@type = 'bool'">boolean</xsl:when>
+          <xsl:when test="@type = 'TimeStamp'">timestamp</xsl:when>
+          <xsl:when test="@type = 'int'">integer</xsl:when>
+          <xsl:otherwise>[unknown?]</xsl:otherwise>
+        </xsl:choose>
+      </xsl:attribute>
+      <xsl:attribute name="required">
+        <xsl:choose>
+          <xsl:when test="@not-null = 'true'">true</xsl:when>
+          <xsl:otherwise>false</xsl:otherwise>
+        </xsl:choose>
+      </xsl:attribute>
+      <xsl:attribute name="size">
+        <xsl:value-of select="@length"/>
+      </xsl:attribute> 
+    </property>
+
+  </xsl:template>
+
+  <xsl:template match="id">
+    <property distinct="system" required="true">
+      <xsl:attribute name="name">
+        <xsl:value-of select="@name"/>
+      </xsl:attribute>
+      <xsl:attribute name="type">
+        <xsl:choose>
+          <xsl:when test="@type = 'DateTime'">date</xsl:when>
+          <xsl:when test="@type = 'String'">string</xsl:when>
+          <xsl:when test="@type = 'bool'">boolean</xsl:when>
+          <xsl:when test="@type = 'TimeStamp'">timestamp</xsl:when>
+          <xsl:when test="@type = 'int'">integer</xsl:when>
+          <xsl:otherwise>[unknown?]</xsl:otherwise>
+        </xsl:choose>
+      </xsl:attribute>
+      <xsl:attribute name="size">
+        <xsl:value-of select="@length"/>
+      </xsl:attribute>
+    </property>
+  </xsl:template>
+
+  <xsl:template match="many-to-one">
+    <property type="entity">
+      <xsl:attribute name="name">
+        <xsl:value-of select="@name"/>
+      </xsl:attribute>
+      <xsl:attribute name="entity">
+        <xsl:value-of select="@class"/>
+      </xsl:attribute>
+    </property>
+  </xsl:template>
+
+  <xsl:template match="@* | node()">
+    <xsl:copy>
+      <xsl:apply-templates select="@* | node()"/>
+    </xsl:copy>
+    
+  </xsl:template>
+</xsl:stylesheet>
\ No newline at end of file