diff --git a/ADL.csproj b/ADL.csproj
deleted file mode 100755
index 9cc4ee5..0000000
--- a/ADL.csproj
+++ /dev/null
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProductVersion>9.0.21022</ProductVersion>
-    <SchemaVersion>2.0</SchemaVersion>
-    <ProjectGuid>{15DF3516-FE95-4BB0-9353-2E1E624303B8}</ProjectGuid>
-    <OutputType>Library</OutputType>
-    <AppDesignerFolder>Properties</AppDesignerFolder>
-    <RootNamespace>ADL</RootNamespace>
-    <AssemblyName>ADL</AssemblyName>
-    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
-    <FileAlignment>512</FileAlignment>
-    <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>
-  <Import Project="$(MSBuildToolsPath)\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>
-  -->
-  <ItemGroup>
-    <Content Include="transforms\adl2canonical.xslt" />
-    <Content Include="transforms\adl2controllerclasses.xslt" />
-    <Content Include="transforms\adl2documentation.xslt" />
-    <Content Include="transforms\adl2entityclasses.xslt" />
-    <Content Include="transforms\adl2hibernate.xslt" />
-    <Content Include="transforms\adl2mssql.xslt" />
-    <Content Include="transforms\adl2psql.xslt" />
-    <Content Include="transforms\adl2views.xslt" />
-    <Content Include="transforms\base-type-include.xslt" />
-    <Content Include="transforms\csharp-type-include.xslt" />
-    <Content Include="transforms\i18n-en-GB-include.xslt" />
-    <Content Include="transforms\localise-transform.xslt" />
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="schemas\adl-1.1.dtd" />
-    <None Include="test.build" />
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/ADL.sln b/ADL.sln
deleted file mode 100755
index a829b97..0000000
--- a/ADL.sln
+++ /dev/null
@@ -1,44 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 10.00
-# Visual Studio 2008
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ADL", "ADL.csproj", "{15DF3516-FE95-4BB0-9353-2E1E624303B8}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CygnetToolkit", "..\CygnetToolkit\CygnetToolkit.csproj", "{77FB7DE5-1F33-4DDC-8A2E-79EF4728705E}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApp", "TestApp\TestApp.csproj", "{45578889-14A2-4A53-8391-0596369CCBA5}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "UnitTests\UnitTests.csproj", "{D705F7CA-EB87-48EF-8F18-7D1AD90660BA}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{83B41EED-23C8-4DEF-B113-46A426346E45}"
-	ProjectSection(SolutionItems) = preProject
-		ADL.vsmdi = ADL.vsmdi
-		LocalTestRun.testrunconfig = LocalTestRun.testrunconfig
-	EndProjectSection
-EndProject
-Global
-	GlobalSection(SolutionConfigurationPlatforms) = preSolution
-		Debug|Any CPU = Debug|Any CPU
-		Release|Any CPU = Release|Any CPU
-	EndGlobalSection
-	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{15DF3516-FE95-4BB0-9353-2E1E624303B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{15DF3516-FE95-4BB0-9353-2E1E624303B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{15DF3516-FE95-4BB0-9353-2E1E624303B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{15DF3516-FE95-4BB0-9353-2E1E624303B8}.Release|Any CPU.Build.0 = Release|Any CPU
-		{77FB7DE5-1F33-4DDC-8A2E-79EF4728705E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{77FB7DE5-1F33-4DDC-8A2E-79EF4728705E}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{77FB7DE5-1F33-4DDC-8A2E-79EF4728705E}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{77FB7DE5-1F33-4DDC-8A2E-79EF4728705E}.Release|Any CPU.Build.0 = Release|Any CPU
-		{45578889-14A2-4A53-8391-0596369CCBA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{45578889-14A2-4A53-8391-0596369CCBA5}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{45578889-14A2-4A53-8391-0596369CCBA5}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{45578889-14A2-4A53-8391-0596369CCBA5}.Release|Any CPU.Build.0 = Release|Any CPU
-		{D705F7CA-EB87-48EF-8F18-7D1AD90660BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{D705F7CA-EB87-48EF-8F18-7D1AD90660BA}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{D705F7CA-EB87-48EF-8F18-7D1AD90660BA}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{D705F7CA-EB87-48EF-8F18-7D1AD90660BA}.Release|Any CPU.Build.0 = Release|Any CPU
-	EndGlobalSection
-	GlobalSection(SolutionProperties) = preSolution
-		HideSolutionNode = FALSE
-	EndGlobalSection
-EndGlobal
diff --git a/TestApp/TestApp.csproj b/TestApp/TestApp.csproj
deleted file mode 100755
index 7883618..0000000
--- a/TestApp/TestApp.csproj
+++ /dev/null
@@ -1,124 +0,0 @@
-<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProductVersion>9.0.21022</ProductVersion>
-    <SchemaVersion>2.0</SchemaVersion>
-    <ProjectGuid>{45578889-14A2-4A53-8391-0596369CCBA5}</ProjectGuid>
-    <ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
-    <OutputType>Library</OutputType>
-    <AppDesignerFolder>Properties</AppDesignerFolder>
-    <RootNamespace>TestApp</RootNamespace>
-    <AssemblyName>TestApp</AssemblyName>
-    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\</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\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-  </PropertyGroup>
-  <ItemGroup>
-    <Reference Include="Castle.Core, Version=1.0.3.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL" />
-    <Reference Include="Castle.MonoRail.Framework, Version=1.0.3.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL" />
-    <Reference Include="Castle.MonoRail.Framework.Views.NVelocity, Version=1.0.3.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL" />
-    <Reference Include="Iesi.Collections, Version=1.0.0.3, Culture=neutral, PublicKeyToken=aa95f207798dfdb4, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>L:\Castle\1.0.3RC3\Iesi.Collections.dll</HintPath>
-    </Reference>
-    <Reference Include="NHibernate, Version=1.2.0.4000, Culture=neutral, PublicKeyToken=aa95f207798dfdb4, processorArchitecture=MSIL" />
-    <Reference Include="System" />
-    <Reference Include="System.Data" />
-    <Reference Include="System.Core">
-      <RequiredTargetFramework>3.5</RequiredTargetFramework>
-    </Reference>
-    <Reference Include="System.Data.DataSetExtensions">
-      <RequiredTargetFramework>3.5</RequiredTargetFramework>
-    </Reference>
-    <Reference Include="System.Web.Extensions">
-      <RequiredTargetFramework>3.5</RequiredTargetFramework>
-    </Reference>
-    <Reference Include="System.Xml.Linq">
-      <RequiredTargetFramework>3.5</RequiredTargetFramework>
-    </Reference>
-    <Reference Include="System.Drawing" />
-    <Reference Include="System.Web" />
-    <Reference Include="System.Xml" />
-    <Reference Include="System.Configuration" />
-    <Reference Include="System.Web.Services" />
-    <Reference Include="System.EnterpriseServices" />
-    <Reference Include="System.Web.Mobile" />
-  </ItemGroup>
-  <ItemGroup>
-    <Content Include="Default.aspx" />
-    <Content Include="testapp.adl.xml" />
-    <Content Include="Web.config" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="Auto\address.auto.cs" />
-    <Compile Include="Auto\person.auto.cs" />
-    <Compile Include="Default.aspx.cs">
-      <DependentUpon>Default.aspx</DependentUpon>
-    </Compile>
-    <Compile Include="Default.aspx.designer.cs">
-      <DependentUpon>Default.aspx</DependentUpon>
-    </Compile>
-    <Compile Include="Properties\AssemblyInfo.cs" />
-    <Compile Include="Web\Controllers\Auto\AbstractadltestappController.auto.cs" />
-    <Compile Include="Web\Controllers\Auto\addressController.auto.cs" />
-    <Compile Include="Web\Controllers\Auto\personController.auto.cs" />
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="Web\Views\Auto\test\address\edit.auto.vm" />
-    <None Include="Web\Views\Auto\test\address\list.auto.vm" />
-    <None Include="Web\Views\Auto\test\address\maybedelete.auto.vm" />
-    <None Include="Web\Views\Auto\test\person\edit.auto.vm" />
-    <None Include="Web\Views\Auto\test\person\maybedelete.auto.vm" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="..\..\CygnetToolkit\CygnetToolkit.csproj">
-      <Project>{77FB7DE5-1F33-4DDC-8A2E-79EF4728705E}</Project>
-      <Name>CygnetToolkit</Name>
-    </ProjectReference>
-  </ItemGroup>
-  <ItemGroup>
-    <Folder Include="App_Data\" />
-    <Folder Include="Web\bin\" />
-  </ItemGroup>
-  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
-  <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v9.0\WebApplications\Microsoft.WebApplication.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>
-  -->
-  <ProjectExtensions>
-    <VisualStudio>
-      <FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
-        <WebProjectProperties>
-          <UseIIS>False</UseIIS>
-          <AutoAssignPort>True</AutoAssignPort>
-          <DevelopmentServerPort>3627</DevelopmentServerPort>
-          <DevelopmentServerVPath>/</DevelopmentServerVPath>
-          <IISUrl>
-          </IISUrl>
-          <NTLMAuthentication>False</NTLMAuthentication>
-          <SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
-        </WebProjectProperties>
-      </FlavorProperties>
-    </VisualStudio>
-  </ProjectExtensions>
-</Project>
\ No newline at end of file
diff --git a/TestApp/Web.config b/TestApp/Web.config
deleted file mode 100755
index fcaa9dc..0000000
--- a/TestApp/Web.config
+++ /dev/null
@@ -1,125 +0,0 @@
-<?xml version="1.0"?>
-
-<configuration>
-
-
-    <configSections>
-      <sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
-        <sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
-          <section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
-          <sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
-            <section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="Everywhere" />
-            <section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" />
-            <section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" />
-            <section name="roleService" type="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" />
-          </sectionGroup>
-        </sectionGroup>
-      </sectionGroup>
-    </configSections>  
-
-  
-    <appSettings/>
-    <connectionStrings/>
-  
-    <system.web>
-        <!-- 
-            Set compilation debug="true" to insert debugging 
-            symbols into the compiled page. Because this 
-            affects performance, set this value to true only 
-            during development.
-        -->
-        <compilation debug="false">
-
-          <assemblies>
-            <add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
-            <add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
-            <add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
-            <add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
-          </assemblies>
-
-        </compilation>
-        <!--
-            The <authentication> section enables configuration 
-            of the security authentication mode used by 
-            ASP.NET to identify an incoming user. 
-        -->
-        <authentication mode="Windows" />
-        <!--
-            The <customErrors> section enables configuration 
-            of what to do if/when an unhandled error occurs 
-            during the execution of a request. Specifically, 
-            it enables developers to configure html error pages 
-            to be displayed in place of a error stack trace.
-
-        <customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
-            <error statusCode="403" redirect="NoAccess.htm" />
-            <error statusCode="404" redirect="FileNotFound.htm" />
-        </customErrors>
-        -->
-
-      <pages>
-        <controls>
-          <add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
-          <add tagPrefix="asp" namespace="System.Web.UI.WebControls" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
-        </controls>
-      </pages>
-
-      <httpHandlers>
-        <remove verb="*" path="*.asmx"/>
-        <add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
-        <add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
-        <add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" validate="false"/>
-      </httpHandlers>
-      <httpModules>
-        <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
-      </httpModules>
-
-    </system.web>
-
-    <system.codedom>
-      <compilers>
-        <compiler language="c#;cs;csharp" extension=".cs" warningLevel="4"
-                  type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
-          <providerOption name="CompilerVersion" value="v3.5"/>
-          <providerOption name="WarnAsError" value="false"/>
-        </compiler>
-     </compilers>
-    </system.codedom>
-    
-    <!-- 
-        The system.webServer section is required for running ASP.NET AJAX under Internet
-        Information Services 7.0.  It is not necessary for previous version of IIS.
-    -->
-    <system.webServer>
-      <validation validateIntegratedModeConfiguration="false"/>
-      <modules>
-        <remove name="ScriptModule" />
-        <add name="ScriptModule" preCondition="managedHandler" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
-      </modules>
-      <handlers>
-        <remove name="WebServiceHandlerFactory-Integrated"/>
-        <remove name="ScriptHandlerFactory" />
-        <remove name="ScriptHandlerFactoryAppServices" />
-        <remove name="ScriptResource" />
-        <add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode"
-             type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
-        <add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode"
-             type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
-        <add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
-      </handlers>
-    </system.webServer>
-
-    <runtime>
-      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
-        <dependentAssembly>
-          <assemblyIdentity name="System.Web.Extensions" publicKeyToken="31bf3856ad364e35"/>
-          <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/>
-        </dependentAssembly>
-        <dependentAssembly>
-          <assemblyIdentity name="System.Web.Extensions.Design" publicKeyToken="31bf3856ad364e35"/>
-          <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/>
-        </dependentAssembly>
-      </assemblyBinding>
-    </runtime>
-
-</configuration>
diff --git a/TestApp/testapp.adl.xml b/TestApp/testapp.adl.xml
index d05b3ec..136379f 100755
--- a/TestApp/testapp.adl.xml
+++ b/TestApp/testapp.adl.xml
@@ -1,115 +1,82 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!-- DOCTYPE application PUBLIC "-//CYGNETS//DTD ADL 0.1//EN" "http://www.cygnets.co.uk/schemas/adl-0.1.1.dtd" -->
-<!-- DOCTYPE application SYSTEM "file:/C:/Projects/ADL/schemas/adl-0.dtd" -->
-
-<!-- 
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE application PUBLIC "-//JOURNEYMAN//DTD ADL 1.4//EN"
+                             "http://bowyer.journeyman.cc/adl/stable/adl/schemas/adl-1.4.dtd">
+<!--  
 	Application Description Language framework
 	testapp.adl.xml
 	
 	the object of this file is to exercise as many aspects of ADL as possible;
-	it isn't expected to describe an application which does anything useful
+	in the first instance, this is an attempt to recreate PRES in ADL
 	
-	Copyright (c) 2008 Cygnet Solutions Ltd
-	
-	$Author: sb $
-	$Revision: 1.2 $
-	$Date: 2008-07-01 16:08:17 $
--->
-
-<application name="ADLTestApp" xmlns="http://cygnets.co.uk/schemas/adl-1.2">
-	<content>
-		<head>
-			
-		</head>
-		<top>
-			
-		</top>
-		<foot>
-			
-		</foot>
-	</content>
-	<typedef name="postcode" type="string" size="10" 
-			 pattern="^([A-PR-UWYZ0-9][A-HK-Y0-9][AEHMNPRTVXY0-9]?[ABEHMNPRVWXY0-9]? {1,2}[0-9][ABD-HJLN-UW-Z]{2}|GIR 0AA)$">
-		<documentation>
-			a postcode follows arcane rules; this specification from
-			http://regexlib.com/REDetails.aspx?regexp_id=260.
+	$Author: simon $
+	$Revision: 1.3 $
+	$Date: 2010-07-20 19:53:40 $
+ -->
+<application name="pres" xmlns="http://bowyer.journeyman.cc/adl/stable/">
+    <specification abbr="regexplib" name="RegexpLib.com" url="http://regexlib.com/"/>
+    <content>
+        <head/>
+        <top/>
+        <foot/>
+    </content>
+    <typedef name="postcode"
+        pattern="^([A-PR-UWYZ0-9][A-HK-Y0-9][AEHMNPRTVXY0-9]?[ABEHMNPRVWXY0-9]? {1,2}[0-9][ABD-HJLN-UW-Z]{2}|GIR 0AA)$"
+        size="10" type="string">
+        <documentation>
+            <reference abbr="regexplib" section="REDetails.aspx?regexp_id=260"/>
+			a postcode follows arcane rules.
 		</documentation>
-	</typedef>
-	<typedef name="age" type="integer" minimum="0" maximum="120">
-		<documentation>
+    </typedef>
+    <typedef maximum="120" minimum="0" name="age" type="integer">
+        <documentation>
 			We don't believe people who claim to be over 120.
 		</documentation>
-	</typedef>
-	<group name="public"/>
-	<group name="admin" parent="public"/>
-	<entity name="Person">
-		<property name="LastName" type="string" required="true" size="100" distinct="user">
-			<prompt locale="en-UK" prompt="Surname"/>
-		</property>
-		<property name="ForeNames" type="string" required="true" size="100" distinct="user">
-			<prompt locale="en-UK" prompt="Fore names"/>
-		</property>
-		<property name="Partner" type="entity" entity="Person"/>
-		<property name="Gender" type="string" size="1" required="true">
-			<option value="M">
-				<prompt locale="en-GB" prompt="Male"/>
-			</option>
-			<option value="F">
-				<prompt locale="en-GB" prompt="Female"/>
-			</option> 
-		</property>
-		<property name="age" type="defined" typedef="age"/>
-		<property name="Address" type="entity" entity="Address" distinct="user"/> 
-		<property name="Friends" type="link" entity="Person"/>
-		<form name="edit" properties="listed">
-			<fieldgroup name="Personal Data">
-				<documentation>
-					Basic data about the person
-				</documentation>
-				<field property="ForeNames">
-					<prompt locale="en-GB" prompt="Fore names"/>
-				</field>
-				<field property="LastName">
-					<prompt locale="en-GB" prompt="Surname"/>
-					<help locale="en-GB">
-						Family name of this person, conventionally their last name
-					</help>
-				</field>
-				<field property="Partner"/>
-				<field property="Gender"/>
-				<field property="Address"/>
-			</fieldgroup>
-			<fieldgroup name="Community">
-				<field property="Friends"/>
-			</fieldgroup>
-		</form>
-	</entity>
-	<entity name="Address">
-		<key>
-			<property name="Number" type="string" size="8" distinct="all">
-				<prompt locale="en-GB" prompt="House number"/>
-				<help locale="en-GB">
-					House or building number
-				</help>
-			</property>
-			<property name="Postcode" type="defined" typedef="postcode" required="false" distinct="all">
-				<prompt locale="en-UK" prompt="Post code"/>
-			</property>
-		</key>
-		<property name="Address1" type="string" required="true" size="255">
-			<prompt locale="en-UK" prompt="Address"/>
-		</property>
-		<property name="Address2" type="string" required="false" size="255">
-			<prompt locale="en-UK" prompt="Line 2"/>
-		</property>
-		<property name="Address3" type="string" required="false" size="255">
-			<prompt locale="en-UK" prompt="Line 3"/>
-		</property>
-		<property name="City" type="string" required="false" size="255">
-			<prompt locale="en-UK" prompt="Post town"/>
-		</property>
-		<property name="County" type="string" required="false" size="255" />
-		<form name="edit" properties="all"/>
-		<list name="list" properties="user-distinct"/>
-	</entity>
-</application>
\ No newline at end of file
+    </typedef>
+    <typedef name="email"
+        pattern="^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$" size="128">
+        <documentation>
+            <reference abbr="regexplib" section="REDetails.aspx?regexp_id=26"/>
+        </documentation>
+    </typedef>
+    <group name="public"/>
+    <group name="admin" parent="public"/>
+    <entity name="Actor">
+        <documentation>
+		A real (administrative) user of this system with a first-class, database layer login, 
+		as opposed to a Subscriber with a second-class, application layer login.
+	</documentation>
+        <property name="Name" size="64" type="string"/>
+        <property name="EMail" type="defined" typedef="email"/>
+        <property name="Approved" type="boolean"/>
+    </entity>
+    <entity name="Article">
+        <property name="Created" type="date"/>
+        <property name="Embargo" type="date"/>
+        <property entity="Category" name="Category" type="entity"/>
+        <property name="Title" size="128" type="string"/>
+        <property entity="Actor" name="Author" type="entity"/>
+	<property name="Location" type="entity" entity="Location"/>
+    </entity>
+    <entity name="Author">
+        <property name="CanonicalName" size="128" type="string"/>
+        <property entity="NomDePlume" name="NomsDePlume" type="list"/>
+        <property name="Disambiguation" size="256" type="string">
+            <documentation>
+		If the canonical name is a common one, or there are known to be two or more authors 
+		with the same canonical name, some brief text about the author to disambiguate.
+	</documentation>
+        </property>
+    </entity>
+    <entity name="Book">
+        <property entity="Article" name="Article" type="entity"/>
+        <property name="AuthorAsEntered" size="128" type="string">
+            <documentation>The name of the author as entered by the original user, prior to being resolved against known authors</documentation>
+        </property>
+        <property entity="Author" name="Authors" type="link"/>
+        <property name="Title" size="128" type="string"/>
+    </entity>
+    <entity name="NomDePlume">
+        <property name="Name" size="128" type="string"/>
+        <property entity="Author" name="Author" type="entity"/>
+    </entity>
+</application>
diff --git a/schemas/adl-1.4.dtd b/schemas/adl-1.4.dtd
index a52cfbf..d8286e3 100755
--- a/schemas/adl-1.4.dtd
+++ b/schemas/adl-1.4.dtd
@@ -1,614 +1,615 @@
-    <!--  ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::  -->
-    <!--						    											                                  -->
-    <!--	adl-1.4.dtd    			    										                          -->
-    <!--																		                                    -->
-    <!--	Purpose:															                                -->
-    <!--	Document Type Description for Application Description				          -->
-    <!--	Language. Normative for now; will be replaced by a schema.     	   `  -->
-    <!--																		                                    -->
-    <!--	Author:		Simon Brooke <stillyet@journeyman.cc>			  			            -->
-    <!--	Created:	24th January 2006				                                    -->
-    <!--	Copyright:	(c) 2007 Cygnet Solutions								                  -->
-    <!--      							      		                                          -->
-    <!--  ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::  -->
-    
-    <!--
-        $Revision: 1.4 $
- 	    -->
-
-<!--  ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::  -->
-<!--  Before we start: import XHTML	for use in documentation sections			-->
-<!--  ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::  -->
-<!--  doesn't work yet  -->
-<!-- ENTITY  % XHTML PUBLIC
-   "-//W3C//DTD XHTML 1.0 Transitional//EN"
-   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-%XHTML; -->
-
-<!--  ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::  -->
-<!--  Before we start: some useful definitions					                -->
-<!--  ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::  -->
-
-<!-- some basic character entities inherited from HTML. Actually we probably ought to 
-import all the HTML4 character entity files, and possibly the HTML4 Strict DTD (so 
-that we can allow HTML block level entities within content elements -->
-<!ENTITY nbsp "&#160;">
-<!ENTITY pound "&#163;">
-<!ENTITY copy "&#169;">
-
-
-<!-- boolean means true or false -->
-<!ENTITY % Boolean "(true|false)" >
-
-<!-- 
-	Locale is a string comprising an ISO 639 language code followed by a space
-	followed by an ISO 3166 country code, or else the string 'default'. See:
-	<URL:http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt>
-	<URL:http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html>
--->
-<!ENTITY % Locale "CDATA" >
-
-<!-- 
-	permissions a group may have on an entity, list, page, form or field
-	permissions are deemed to increase as you go right. A group cannot 
-	have greater permission on a field than on the form it is in, or
-	greater permission on form than the entity it belongs to
-	
-	none:			none
-	read:			select
-	insert:			insert
-	noedit:			select, insert
-	edit:			select, insert, update
-	all:			select, insert, update, delete
--->
-<!ENTITY % Permissions "none|read|insert|noedit|edit|all" >
-
-
-<!--
-  actions which should be cascaded to dependent objects. All these values except
-  'manual' are taken from Hibernate and should be passed through the adl2hibernate 
-  mapping transparently. Relevent only for properties with type='entity', type='link'
-  and type='list'
-  
-  all :       cascade delete, save and update
-  all-delete-orphan : see hibernate documentation; relates to transient objects only
-  delete :    cascade delete actions, but not save and update
-  manual :    cascading will be handled in manually managed code, code to
-              handle cascading should not be generated
-  save-update : cascade save and update actions, but not delete.
--->
-<!ENTITY % CascadeActions "all|all-delete-orphan|delete|manual|save-update">
-
-<!-- 
-	data types which can be used in a typedef to provide validation - 
-	e.g. a string can be used with a regexp or a scalar can be used with 
-	min and max values 
-	string: 		varchar		java.sql.Types.VARCHAR
-	integer:		int			java.sql.Types.INTEGER
-	real:			double		java.sql.Types.DOUBLE
-	money:			money		java.sql.Types.INTEGER
-	date:			date		java.sql.Types.DATE
-	time:			time		java.sql.Types.TIME
-	timestamp:		timestamp	java.sql.Types.TIMESTAMP
-	uploadable:		varchar		java.sql.Types.VARCHAR 
-	image:			varchar		java.sql.Types.VARCHAR
-	
-	uploadable is as string but points to an uploaded file; image is as
-	uploadable but points to an uploadable graphical image file
--->
-<!ENTITY % DefinableDataTypes "string|integer|real|money|date|time|timestamp|uploadable" >
-
-<!-- 
-	data types which are fairly straightforward translations of JDBC data types
-	boolean:		boolean or	java.sql.Types.BIT
-					char(1)		java.sql.Types.CHAR
-	text:			text or		java.sql.Types.LONGVARCHAR 
-					memo		java.sql.Types.CLOB
--->
-<!ENTITY % SimpleDataTypes "%DefinableDataTypes;|boolean|text" >
-
-<!-- 
-	data types which are more complex than SimpleDataTypes...
-	entity : 		a foreign key link to another entity (i.e. the 'many' end of a 
-					one-to-many link);
-	list :			a list of some other entity that links to me (i.e. the 'one' end of
-					a one-to-many link);
-	link : 			a many to many link (via a link table);
-	defined : 		a type defined by a typedef.
--->
-<!ENTITY % ComplexDataTypes "entity|link|list|defined" >
-
-<!--
-  data types which require special handling - which don't simply map onto 
-  common SQL data types
-  geopos :    a latitude/longitude pair (experimental and not yet implemented)
-  image :     a raster image file, in jpeg|gif|png format (experimental, not yet implemented)
-  message :   an internationalised message, having different translations for different locales
--->
-<!ENTITY % SpecialDataTypes "geopos|image|message" >
-
-<!-- all data types -->
-<!ENTITY % AllDataTypes "%ComplexDataTypes;|%SimpleDataTypes;|%SpecialDataTypes;" >
-
-<!-- content, for things like pages (i.e. forms, lists, pages) -->
-<!ENTITY % Content "head|top|foot" >
-
-<!ENTITY % FieldStuff "field|fieldgroup|auxlist|verb">
-
-<!ENTITY % PageContent "%Content;|%FieldStuff;" >
-
-<!ENTITY % PageStuff "%PageContent;|permission|pragma" >
-
-<!-- Properties for pages:
-  name:               obviously, the name (URL stub) of the page
-  properties:         the properties of the entity the page describes to be shown
-                      as fields on the page
-      all:            obviously, all properties (except the abstract primary key, if
-                      present)
-      user-distinct:  all properties which are user-distinct (NOTE: Not yet implemented)
-      listed:         only those properties for which fields are explicitly listed
--->  
-<!ENTITY % PageAttrs 
-	"name CDATA #REQUIRED
-	 properties (all|user-distinct|listed) #REQUIRED" >
-
-<!-- Actions for generators (mainly for keyfields - see entity 'generator', below
-  assigned:           In manually-maintained code, you contract to assign a value 
-                      to this property before it is persisted.
-  guid:               The system will supply a unique GUid value to this field 
-                      before it is persisted.
-  mannual:            You contract to supply a generatos class in manually maintained
-                      code.
-  native:             The database will supply a unique value to this field when it
-                      is persisted; the value will be an integer. RECOMMENDED!
--->
-<!ENTITY % GeneratorActions "assigned|guid|manual|native">
-
-<!-- sequences for orderings of lists - see entity 'order'
-  canonical:          Whatever the normal canonical ordering for this datatype is -
-                      typically alpha-numeric, except for dates, etc.
-  reverse-canonical:  The reverse of the above
-  
-  possibly there should be some further values but I have no idea what these are
--->
-<!ENTITY % Sequences "canonical|reverse-canonical">
-
-<!--  ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::  -->
-<!--  Elements																	                                -->
-<!--  ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::  -->
-
-<!-- 
-  the application that the document describes: required top level element
-  
-  name:     the name of this application
-  version:  the version number of this application
-  revision:	the revision of the ADL document
-  currency: the base monetary currency, in the form of an ISO 4217 three-letter code
-  xmlns:    XML namespace, in case required
--->
-<!ELEMENT application ( specification*, documentation?, content?, typedef*,  group*, entity*)>
-<!ATTLIST application 
-	name 		CDATA 						#REQUIRED
-	version 	CDATA 						#IMPLIED
-	revision	CDATA						#IMPLIED
-	currency	CDATA						#IMPLIED
-	xmlns		CDATA						#IMPLIED>
-
-<!-- 
-	the definition of a defined type. At this stage a defined type is either
-	a string		in which case it must have size and pattern, or
-	a scalar		in which case it must have minimum and/or maximum
-	pattern must be a regular expression as interpreted by org.apache.regexp.RE
-	minimum and maximum must be of appropriate format for the datatype specified.
-	Validation may be done client-side and/or server-side at application layer
-	and/or server side at database layer.
-
-  name:     the name of this typedef
-  type:     the simple type on which this defined type is based; must be
-            present unless in-implementation children are supplied
-  size:     the data size of this defined type
-  pattern:  a regular expression which values for this type must match
-  minimum:  the minimum value for this type (if base type is scalar)
-  maximum:  the maximum value for this type (if base type is scalar)
-  -->
-<!ELEMENT typedef (documentation?, in-implementation*, help*) >
-
-<!ATTLIST typedef 
-	name 		  CDATA 						#REQUIRED
-	type 		  (%DefinableDataTypes;) 		#IMPLIED
-	size 		  CDATA 						#IMPLIED
-	pattern 	CDATA 						#IMPLIED
-	minimum 	CDATA 						#IMPLIED
-	maximum 	CDATA 						#IMPLIED>
-
-<!--
-  information about how to translate a type into types known to different target
-  languages. TODO: Once again I'm not wholly comfortable with the name; I'm not 
-  really comfortable that this belongs in ADL at all.
-  
-  target:     the target language
-  value:      the type to use in that target language
-  kind:       OK, I confess I don't understand this, but Andrew needs it... 
--->
-<!ELEMENT in-implementation (documentation?)>
-
-<!ATTLIST in-implementation
-      target  CDATA           #REQUIRED
-      value   CDATA           #REQUIRED
-      kind    CDATA           #IMPLIED>
-
-<!-- 
-  a group of people with similar permissions to one another 
-  
-  name: the name of this group
-  parent: the name of a group of which this group is subset
-  -->
-<!ELEMENT group (documentation?)>
-
-<!ATTLIST group 
-  name      CDATA             #REQUIRED
-  parent    CDATA             #IMPLIED>
-
-
-
-<!-- 
-	an entity which has properties and relationships; maps onto a database
-	table or a Java serialisable class - or, of course, various other things
-  
-  name:         obviously, the name of this entity
-  natural-key:  if present, the name of a property of this entity which forms
-                a natural primary key [NOTE: Only partly implemented. NOTE: much of
-                the present implementation assumes all primary keys will be 
-                integers. This needs to be fixed!] DEPRECATED: remove; replace with the
-                'key' element, below.
-  table:        the name of the table in which this entity is stored. Defaults to same
-                as name of entity. Strongly recommend this is not used unless it needs
-                to be different from the name of the entity
-  foreign:      this entity is part of some other system; no code will be generated
-                for it, although code which links to it will be generated
--->
-<!ELEMENT entity ( documentation?, prompt*, content?, key?,
-      property*, permission*, (form | page | list)*)>
-<!ATTLIST entity 
-    name      CDATA           #REQUIRED
-    natural-key CDATA         #IMPLIED
-    table     CDATA           #IMPLIED
-    foreign   %Boolean;       #IMPLIED>
-
-<!-- 
-  contains documentation on the element which immediately contains it. TODO:
-  should HTML markup within a documentation element be allowed? If so, are
-  there restrictions?
--->
-<!ELEMENT documentation ( #PCDATA|reference)*>
-<!ATTLIST documentation
-  xmlns     CDATA             #IMPLIED>
-
-
-<!-- an explicit primary key, possibly compound -->
-<!ELEMENT key (property*)>
-
-
-<!-- 
-	a property (field) of an entity (table) 
-	
-	name:			  the name of this property.
-	type:			  the type of this property.
-	default:		the default value of this property. There will probably be 
-					    magic values of this!
-	typedef:	  name of the typedef to use, it type = 'defined'.
-	distinct:		distinct='system' required that every value in the system 
-					    will be distinct (i.e. natural primary key);
-					    distinct='user' implies that the value may be used by users 
-					    in distinguishing entities even if values are not formally 
-					    unique; 
-					    distinct='all' implies that the values are formally unique 
-					    /and/ are user friendly (NOTE: not implemented).
-	entity:	if type='entity', the name of the entity this property is 
-					    a foreign key link to.
-              if type='list', the name of the entity that has a foreign 
-              key link to this entity
-	farkey:   if type='list', the name of farside key in the listed 
-              entity; if type='entity' and the farside field to join to 
-              is not the farside primary key, then the name of that
-              farside field
-	required:		whether this propery is required (i.e. 'not null').
-	immutable:		if true, once a value has been set it cannot be changed.
-	size: 			fieldwidth of the property if specified.
-	concrete: if set to 'false', this property is not stored in the 
-              database but must be computed (manually written code must
-              be provided to support this)
-	cascade:  what action(s) on the parent entity should be cascaded to
-              entitie(s) linked on this property. Valid only if type='entity',
-              type='link' or type='list'.
-	column:   name of the column in a SQL database table in which this property
-              is stored. TODO: Think about this.
-	unsaved-value:
-              of a property whose persistent value is set on first being 
-              committed to persistent store, the value which it holds before
-              it has been committed
--->
-<!ELEMENT property ( documentation?, generator?, (permission|option|prompt|help|ifmissing)*)>
-
-<!ATTLIST property 
-	name 		    CDATA 					#REQUIRED
-	type 		    (%AllDataTypes;)		#REQUIRED
-	default 		CDATA 					#IMPLIED
-	typedef 		CDATA 					#IMPLIED
-	distinct 		(none|all|user|system) 	#IMPLIED
-	entity 			CDATA 					#IMPLIED
-	farkey			CDATA					#IMPLIED
- 	required 		%Boolean; 				#IMPLIED
-	immutable		%Boolean;				#IMPLIED	
-	size 		    CDATA 					#IMPLIED
-	column			CDATA					#IMPLIED
-	concrete		%Boolean;				#IMPLIED
-	cascade			(%CascadeActions;)		#IMPLIED>
-
-
-<!-- 
-  marks a property which is auto-generated by some part of the system. 
-  This is based on the Hibernate construct, except that the Hibernate 
-  implementation folds both its internal generators and custom generators 
-  onto the same attribute. This separates them onto two attributes so we 
-  can police values for Hibernate's 'builtin' generators.
-  
-  action:       one of the supported Hibernate builtin generators, or 
-                'manual'. 'native' is strongly recommended in most instances
-  class:        if action is 'manual', the name of a manually maintained 
-                class conforming to the Hibernate IdentifierGenerator 
-                interface, or its equivalent in other languages
--->
-<!ELEMENT generator (documentation?, param*)>
-<!ATTLIST generator
-      action  (%GeneratorActions;)    #REQUIRED
-      class   CDATA                   #IMPLIED>
-
-<!--
-  A parameter passed to the generator. Again, based on the Hibernate 
-  implementation. TODO: #PCDATA is wrong as the content model, as embedded
-  markup is definitely not allowed!
-  
-  name:   the name of this parameter
-  
-  TODO: This needs to be renamed or removed because it conflicts with the
-  XHTML element of the same name. In fact it could be simply removed since 
-  our usage is compatible with the XHTML usage, but it might be less 
-  ambiguous to rename it.
--->
-<!ELEMENT param (#PCDATA)>
-<!ATTLIST param
-  name        CDATA           #REQUIRED>
-
-
-
-<!-- 
-	one of an explicit list of optional values a property may have 
-	NOTE: whether options get encoded at application layer or at database layer 
-	is UNDEFINED; either behaviour is correct. If at database layer it's also 
-	UNDEFINED whether they're encoded as a single reference data table or as 
-	separate reference data tables for each property.
-	
-	value:	the value of this option
-
-	TODO: This needs to be renamed or removed because it conflicts with the
-	XHTML element of the same name. In fact it could be simply removed since 
-	our usage is compatible with the XHTML usage, but it might be less 
-	ambiguous to rename it.
--->
-<!ELEMENT option (documentation?, prompt*)>
-<!-- if the value is different from the prompt the user sees, specify it -->
-<!ATTLIST option 
-  value       CDATA           #IMPLIED>
-
-
-<!-- 
-	permissions policy on an entity, a page, form, list or field 
-	
-	group: 			the group to which permission is granted
-	permission:		the permission which is granted to that group
--->
-<!ELEMENT permission (documentation?)>
-<!ATTLIST permission 
-	group 		  CDATA 					#REQUIRED
-	permission 	(%Permissions;) #REQUIRED>
-
-
-<!--
-  pragmatic advice to generators of lists and forms, in the form of 
-  name/value pairs which may contain anything. Over time some pragmas
-  will become 'well known', but the whole point of having a pragma
-  architecture is that it is extensible.
--->
-<!ELEMENT pragma (documentation?)>
-<!ATTLIST pragma
-  name        CDATA           #REQUIRED
-  value       CDATA           #REQUIRED>
-
-<!-- 
-	a prompt for a property or field; used as the prompt text for a widget 
-	which edits it. Typically there will be only one of these per property
-  per locale; if there are more than one all those matching the locale may
-  be concatenated, or just one may be used.
-	
-	prompt:			the prompt to use
-	locale:			the locale in which to prefer this prompt	
--->
-<!ELEMENT prompt (documentation?)>
-<!ATTLIST prompt
-	prompt		  CDATA				  	#REQUIRED
-	locale		  %Locale;				#REQUIRED >
-
-<!-- 
-	helptext about a property of an entity, or a field of a page, form or 
-	list, or a typedef. Typically there will be only one of these per property
-  per locale; if there are more than one all those matching the locale may
-  be concatenated, or just one may be used.
-
-	locale:			the locale in which to prefer this prompt	
--->
-<!ELEMENT help (#PCDATA)>
-<!ATTLIST help
-	locale		  %Locale;				#REQUIRED
-  xmlns     CDATA             #IMPLIED >
-
-<!--
-  helpful text to be shown if a property value is missing, typically when 
-  a form is submitted. Typically there will be only one of these per property
-  per locale; if there are more than one all those matching the locale may
-  be concatenated, or just one may be used. Later there may be more sophisticated
-  behaviour here.
--->
-<!ELEMENT ifmissing (#PCDATA)>
-<!ATTLIST ifmissing
-  locale      %Locale;        #REQUIRED
-  xmlns     CDATA             #IMPLIED>
-
-<!-- a form through which an entity may be added or edited
-
-  TODO: This needs to be renamed because it conflicts with the
-  XHTML element of the same name. 
--->
-<!ELEMENT form (documentation?, ( %PageStuff;)*)>
-<!ATTLIST form %PageAttrs;>
-
-
-<!-- a page on which an entity may be displayed -->
-<!ELEMENT page (documentation?, ( %PageStuff;)*)>
-<!ATTLIST page %PageAttrs;>
-
-<!ELEMENT order (documentation?)>
-<!ATTLIST order
-      property  CDATA       #REQUIRED
-      sequence  (%Sequences;)  #IMPLIED>
-
-<!-- 
-	a list on which entities of a given type are listed
-
-	onselect:		name of form/page/list to go to when
-					    a selection is made from the list 
--->
-<!ELEMENT list (documentation?, ( %PageStuff;|order)*)>
-<!ATTLIST list %PageAttrs;
-	onselect	  CDATA 					#IMPLIED >
-
-
-<!--
-  a subsidiary list, on which entities related to primary
-  entities in the enclosing page or list are listed
-  
-  property:   the property of the enclosing entity that this
-              list displays (obviously, must be of type='list')
-  onselect:   the form or page of the listed entity to call
-              when an item from the list is selected
-  canadd:     true if the user should be able to add records
-              to this list
-  -->
-<!ELEMENT auxlist (documentation?, (prompt|%FieldStuff;)*)>
-<!ATTLIST auxlist %PageAttrs;
-  property    CDATA           #REQUIRED
-  onselect    CDATA           #IMPLIED
-  canadd      %Boolean;       #IMPLIED>
-
-<!--
-  a group of fields and other controls within a form or list, which the 
-  renderer might render as a single pane in a tabbed display, for example.
-  -->
-<!ELEMENT fieldgroup (documentation?, (prompt|permission|%FieldStuff;)*)>
-<!ATTLIST fieldgroup
-  name        CDATA           #REQUIRED>
-
-
-<!-- a field in a form or page
-
-  property:   the property which this field displays/edits
-  -->
-<!ELEMENT field (documentation?, (prompt|help|permission)*) >
-<!ATTLIST field 
-  property    CDATA           #REQUIRED >
-
-<!-- a verb is something that may be done through a form. Probably the verbs 'store' 
-  and 'delete' are implied, but maybe they need to be explicitly declared. The 'verb'
-  attribute of the verb is what gets returned to the controller -->
-<!ELEMENT verb (documentation?, (prompt|help|permission)*) >
-<!ATTLIST verb
-  verb        CDATA           #REQUIRED
-  dangerous   %Boolean;       #REQUIRED>
-
-
-<!-- a container for global content -->
-<!ELEMENT content (%Content;)*>
-
-
-<!-- 
-	content to place in the head of the generated document; this is #PCDATA 
-	because it will almost certainly belong to a different namespace 
-	(usually HTML)
-
-	TODO: This needs to be renamed or removed because it conflicts with the
-	XHTML element of the same name. In fact it could be simply removed since 
-	our usage is compatible with the XHTML usage, but it might be less 
-	ambiguous to rename it.
--->
-<!ELEMENT head (#PCDATA) >
-<!ATTLIST head
-  xmlns     CDATA             #IMPLIED>
-
-
-<!-- 
-	content to place in the top of the body of the generated document; 
-	this is %Flow; which is any HTML block or inline level element.
--->
-<!ELEMENT top (#PCDATA) >
-<!ATTLIST top
-  xmlns     CDATA             #IMPLIED>
-
-<!-- 
-	content to place at the foot of the body of the generated document; 
-	this is %Flow; which is any HTML block or inline level element.
--->
-<!ELEMENT foot (#PCDATA) >
-<!ATTLIST foot
-  xmlns     CDATA             #IMPLIED>
-
-<!-- 
-	The 'specification' and 'reference' elements are for documentation only,
-	and do not contribute to the engineering of the application described.
-	
-	A specification element is intended chiefly to declare the reference
-	documents which may be used in documentation elements later in the 
-	document. 
-	
-	url:		The URL from which the document referenced can be retrieved
-	name:		The full name (title) given to this document
-	abbr:		A convenient abbreviated name
--->
-<!ELEMENT specification (documentation?, reference*)>
-<!ATTLIST specification
-		url			CDATA	#IMPLIED
-		name		CDATA	#REQUIRED
-		abbr		CDATA	#REQUIRED>
-
-<!-- 
-	The 'specification' and 'reference' elements are for documentation only,
-	and do not contribute to the engineering of the application described.
-	
-	A reference element is a reference to a specifying document. 
-	
-	abbr:		The abbreviated name of the specification to which this
-				reference refers
-	section:	The 'anchor part' (part following a hash character) which,
-				when appended to the URL, will locate the exact section
-				referenced.
-	entity:		A reference to another entity within this ADL document
-	property:	A reference to another property within this ADL document;
-				if entity is also specified then of that entity, else of
-				the ancestor entity if any
-	-->
-<!ELEMENT reference (documentation?)>
-<!ATTLIST reference
-		abbr		CDATA	#IMPLIED
-		section		CDATA	#IMPLIED
-		entity		CDATA	#IMPLIED
-		property	CDATA	#IMPLIED>
-
+    <!--  ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::  -->
+    <!--						    											                                  -->
+    <!--	adl-1.4.dtd    			    										                          -->
+    <!--																		                                    -->
+    <!--	Purpose:															                                -->
+    <!--	Document Type Description for Application Description				          -->
+    <!--	Language. Normative for now; will be replaced by a schema.     	   `  -->
+    <!--																		                                    -->
+    <!--	Author:		Simon Brooke <simon@cygnets.co.uk>			  			            -->
+    <!--	Created:	24th January 2006				                                    -->
+    <!--	Copyright:	(c) 2007 Cygnet Solutions								                  -->
+    <!--      							      		                                          -->
+    <!--  ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::  -->
+    
+    <!--
+        $Revision: 1.5 $
+ 	    -->
+
+<!--  ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::  -->
+<!--  Before we start: import XHTML	for use in documentation sections			-->
+<!--  ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::  -->
+
+<!--  ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::  -->
+<!--  Before we start: some useful definitions					                -->
+<!--  ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::  -->
+
+<!-- some basic character entities inherited from HTML. Actually we probably ought to 
+import all the HTML4 character entity files, and possibly the HTML4 Strict DTD (so 
+that we can allow HTML block level entities within content elements -->
+<!ENTITY nbsp "&#160;">
+<!ENTITY pound "&#163;">
+<!ENTITY copy "&#169;">
+
+
+<!-- boolean means true or false -->
+<!ENTITY % Boolean "(true|false)" >
+
+<!-- 
+	Locale is a string comprising an ISO 639 language code followed by a space
+	followed by an ISO 3166 country code, or else the string 'default'. See:
+	<URL:http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt>
+	<URL:http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html>
+-->
+<!ENTITY % Locale "CDATA" >
+
+<!-- 
+	permissions a group may have on an entity, list, page, form or field
+	permissions are deemed to increase as you go right. A group cannot 
+	have greater permission on a field than on the form it is in, or
+	greater permission on form than the entity it belongs to
+	
+	none:			none
+	read:			select
+	insert:			insert
+	noedit:			select, insert
+	edit:			select, insert, update
+	all:			select, insert, update, delete
+-->
+<!ENTITY % Permissions "none|read|insert|noedit|edit|all" >
+
+
+<!--
+  actions which should be cascaded to dependent objects. All these values except
+  'manual' are taken from Hibernate and should be passed through the adl2hibernate 
+  mapping transparently. Relevent only for properties with type='entity', type='link'
+  and type='list'
+  
+  all :       cascade delete, save and update
+  all-delete-orphan : see hibernate documentation; relates to transient objects only
+  delete :    cascade delete actions, but not save and update
+  manual :    cascading will be handled in manually managed code, code to
+              handle cascading should not be generated
+  save-update : cascade save and update actions, but not delete.
+-->
+<!ENTITY % CascadeActions "all|all-delete-orphan|delete|manual|save-update">
+
+<!-- 
+	data types which can be used in a typedef to provide validation - 
+	e.g. a string can be used with a regexp or a scalar can be used with 
+	min and max values 
+	string: 		varchar		java.sql.Types.VARCHAR
+	integer:		int			java.sql.Types.INTEGER
+	real:			double		java.sql.Types.DOUBLE
+	money:			money		java.sql.Types.INTEGER
+	date:			date		java.sql.Types.DATE
+	time:			time		java.sql.Types.TIME
+	timestamp:		timestamp	java.sql.Types.TIMESTAMP
+	uploadable:		varchar		java.sql.Types.VARCHAR 
+	image:			varchar		java.sql.Types.VARCHAR
+	
+	uploadable is as string but points to an uploaded file; image is as
+	uploadable but points to an uploadable graphical image file
+-->
+<!ENTITY % DefinableDataTypes "string|integer|real|money|date|time|timestamp|uploadable" >
+
+<!-- 
+	data types which are fairly straightforward translations of JDBC data types
+	boolean:		boolean or	java.sql.Types.BIT
+					char(1)		java.sql.Types.CHAR
+	text:			text or		java.sql.Types.LONGVARCHAR 
+					memo		java.sql.Types.CLOB
+-->
+<!ENTITY % SimpleDataTypes "%DefinableDataTypes;|boolean|text" >
+
+<!-- 
+	data types which are more complex than SimpleDataTypes...
+	entity : 		a foreign key link to another entity (i.e. the 'many' end of a 
+					one-to-many link);
+	list :			a list of some other entity that links to me (i.e. the 'one' end of
+					a one-to-many link);
+	link : 			a many to many link (via a link table);
+	defined : 		a type defined by a typedef.
+-->
+<!ENTITY % ComplexDataTypes "entity|link|list|defined" >
+
+<!--
+  data types which require special handling - which don't simply map onto 
+  common SQL data types
+  geopos :    a latitude/longitude pair (experimental and not yet implemented)
+  image :     a raster image file, in jpeg|gif|png format (experimental, not yet implemented)
+  message :   an internationalised message, having different translations for different locales
+-->
+<!ENTITY % SpecialDataTypes "geopos|image|message" >
+
+<!-- all data types -->
+<!ENTITY % AllDataTypes "%ComplexDataTypes;|%SimpleDataTypes;|%SpecialDataTypes;" >
+
+<!-- content, for things like pages (i.e. forms, lists, pages) -->
+<!ENTITY % Content "head|top|foot" >
+
+<!ENTITY % FieldStuff "field|fieldgroup|auxlist|verb">
+
+<!ENTITY % PageContent "%Content;|%FieldStuff;" >
+
+<!ENTITY % PageStuff "%PageContent;|permission|pragma" >
+
+<!-- Properties for pages:
+  name:               obviously, the name (URL stub) of the page
+  properties:         the properties of the entity the page describes to be shown
+                      as fields on the page
+      all:            obviously, all properties (except the abstract primary key, if
+                      present)
+      user-distinct:  all properties which are user-distinct (NOTE: Not yet implemented)
+      listed:         only those properties for which fields are explicitly listed
+-->  
+<!ENTITY % PageAttrs 
+	"name CDATA #REQUIRED
+	 properties (all|user-distinct|listed) #REQUIRED" >
+
+<!-- Actions for generators (mainly for keyfields - see entity 'generator', below
+  assigned:           In manually-maintained code, you contract to assign a value 
+                      to this property before it is persisted.
+  guid:               The system will supply a unique GUid value to this field 
+                      before it is persisted.
+  mannual:            You contract to supply a generatos class in manually maintained
+                      code.
+  native:             The database will supply a unique value to this field when it
+                      is persisted; the value will be an integer. RECOMMENDED!
+-->
+<!ENTITY % GeneratorActions "assigned|guid|manual|native">
+
+<!-- sequences for orderings of lists - see entity 'order'
+  canonical:          Whatever the normal canonical ordering for this datatype is -
+                      typically alpha-numeric, except for dates, etc.
+  reverse-canonical:  The reverse of the above
+  
+  possibly there should be some further values but I have no idea what these are
+-->
+<!ENTITY % Sequences "canonical|reverse-canonical">
+
+<!--  ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::  -->
+<!--  Elements																	                                -->
+<!--  ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::  -->
+
+<!-- 
+  the application that the document describes: required top level element
+  
+  name:     the name of this application
+  version:  the version number of this application
+  revision:	the revision of the ADL document
+  currency: the base monetary currency, in the form of an ISO 4217 three-letter code
+  xmlns:    XML namespace, in case required
+-->
+<!ELEMENT application ( specification*, documentation?, content?, typedef*,  group*, entity*)>
+<!ATTLIST application 
+	name 		CDATA 						#REQUIRED
+	version 	CDATA 						#IMPLIED
+	revision	CDATA						#IMPLIED
+	currency	CDATA						#IMPLIED
+	xmlns		CDATA						#IMPLIED>
+
+<!-- 
+	the definition of a defined type. At this stage a defined type is either
+	a string		in which case it must have size and pattern, or
+	a scalar		in which case it must have minimum and/or maximum
+	pattern must be a regular expression as interpreted by org.apache.regexp.RE
+	minimum and maximum must be of appropriate format for the datatype specified.
+	Validation may be done client-side and/or server-side at application layer
+	and/or server side at database layer.
+
+  name:     the name of this typedef
+  type:     the simple type on which this defined type is based; must be
+            present unless in-implementation children are supplied
+  size:     the data size of this defined type
+  pattern:  a regular expression which values for this type must match
+  minimum:  the minimum value for this type (if base type is scalar)
+  maximum:  the maximum value for this type (if base type is scalar)
+  -->
+<!ELEMENT typedef (documentation?, in-implementation*, help*) >
+
+<!ATTLIST typedef 
+	name 		  CDATA 						#REQUIRED
+	type 		  (%DefinableDataTypes;) 		#IMPLIED
+	size 		  CDATA 						#IMPLIED
+	pattern 	CDATA 						#IMPLIED
+	minimum 	CDATA 						#IMPLIED
+	maximum 	CDATA 						#IMPLIED>
+
+<!--
+  information about how to translate a type into types known to different target
+  languages. TODO: Once again I'm not wholly comfortable with the name; I'm not 
+  really comfortable that this belongs in ADL at all.
+  
+  target:     the target language
+  value:      the type to use in that target language
+  kind:       OK, I confess I don't understand this, but Andrew needs it... 
+-->
+<!ELEMENT in-implementation (documentation?)>
+
+<!ATTLIST in-implementation
+      target  CDATA           #REQUIRED
+      value   CDATA           #REQUIRED
+      kind    CDATA           #IMPLIED>
+
+<!-- 
+  a group of people with similar permissions to one another 
+  
+  name: the name of this group
+  parent: the name of a group of which this group is subset
+  -->
+<!ELEMENT group (documentation?)>
+
+<!ATTLIST group 
+  name      CDATA             #REQUIRED
+  parent    CDATA             #IMPLIED>
+
+
+
+<!-- 
+	an entity which has properties and relationships; maps onto a database
+	table or a Java serialisable class - or, of course, various other things
+  
+  name:         obviously, the name of this entity
+  natural-key:  if present, the name of a property of this entity which forms
+                a natural primary key [NOTE: Only partly implemented. NOTE: much of
+                the present implementation assumes all primary keys will be 
+                integers. This needs to be fixed!] DEPRECATED: remove; replace with the
+                'key' element, below.
+  table:        the name of the table in which this entity is stored. Defaults to same
+                as name of entity. Strongly recommend this is not used unless it needs
+                to be different from the name of the entity
+  foreign:      this entity is part of some other system; no code will be generated
+                for it, although code which links to it will be generated
+-->
+<!ELEMENT entity ( documentation?, prompt*, content?, key?,
+      property*, permission*, (form | page | list)*)>
+<!ATTLIST entity 
+    name      CDATA           #REQUIRED
+    natural-key CDATA         #IMPLIED
+    table     CDATA           #IMPLIED
+    foreign   %Boolean;       #IMPLIED>
+
+<!-- 
+  contains documentation on the element which immediately contains it. TODO:
+  should HTML markup within a documentation element be allowed? If so, are
+  there restrictions?
+-->
+<!ELEMENT documentation ( #PCDATA|reference)*>
+<!ATTLIST documentation
+  xmlns     CDATA             #IMPLIED>
+
+
+<!-- an explicit primary key, possibly compound -->
+<!ELEMENT key (property*)>
+
+
+<!-- 
+	a property (field) of an entity (table) 
+	
+	name:			  the name of this property.
+	type:			  the type of this property.
+	default:		the default value of this property. There will probably be 
+					    magic values of this!
+	typedef:	  name of the typedef to use, it type = 'defined'.
+	distinct:		distinct='system' required that every value in the system 
+					    will be distinct (i.e. natural primary key);
+					    distinct='user' implies that the value may be used by users 
+					    in distinguishing entities even if values are not formally 
+					    unique; 
+					    distinct='all' implies that the values are formally unique 
+					    /and/ are user friendly (NOTE: not implemented).
+	entity:	if type='entity', the name of the entity this property is 
+					    a foreign key link to.
+              if type='list', the name of the entity that has a foreign 
+              key link to this entity
+	farkey:   if type='list', the name of farside key in the listed 
+              entity; if type='entity' and the farside field to join to 
+              is not the farside primary key, then the name of that
+              farside field
+	required:		whether this propery is required (i.e. 'not null').
+	immutable:		if true, once a value has been set it cannot be changed.
+	size: 			fieldwidth of the property if specified.
+	concrete: if set to 'false', this property is not stored in the 
+              database but must be computed (manually written code must
+              be provided to support this)
+	cascade:  what action(s) on the parent entity should be cascaded to
+              entitie(s) linked on this property. Valid only if type='entity',
+              type='link' or type='list'.
+	column:   name of the column in a SQL database table in which this property
+              is stored. TODO: Think about this.
+	unsaved-value:
+              of a property whose persistent value is set on first being 
+              committed to persistent store, the value which it holds before
+              it has been committed
+-->
+<!ELEMENT property ( documentation?, generator?, (permission|option|prompt|help|ifmissing)*)>
+
+<!ATTLIST property 
+	name 		    CDATA 					#REQUIRED
+	type 		    (%AllDataTypes;)		#REQUIRED
+	default 		CDATA 					#IMPLIED
+	typedef 		CDATA 					#IMPLIED
+	distinct 		(none|all|user|system) 	#IMPLIED
+	entity 			CDATA 					#IMPLIED
+	farkey			CDATA					#IMPLIED
+ 	required 		%Boolean; 				#IMPLIED
+	immutable		%Boolean;				#IMPLIED	
+	size 		    CDATA 					#IMPLIED
+	column			CDATA					#IMPLIED
+	concrete		%Boolean;				#IMPLIED
+	cascade			(%CascadeActions;)		#IMPLIED>
+
+
+<!-- 
+  marks a property which is auto-generated by some part of the system. 
+  This is based on the Hibernate construct, except that the Hibernate 
+  implementation folds both its internal generators and custom generators 
+  onto the same attribute. This separates them onto two attributes so we 
+  can police values for Hibernate's 'builtin' generators.
+  
+  action:       one of the supported Hibernate builtin generators, or 
+                'manual'. 'native' is strongly recommended in most instances
+  class:        if action is 'manual', the name of a manually maintained 
+                class conforming to the Hibernate IdentifierGenerator 
+                interface, or its equivalent in other languages
+-->
+<!ELEMENT generator (documentation?, param*)>
+<!ATTLIST generator
+      action  (%GeneratorActions;)    #REQUIRED
+      class   CDATA                   #IMPLIED>
+
+<!--
+  A parameter passed to the generator. Again, based on the Hibernate 
+  implementation. TODO: #PCDATA is wrong as the content model, as embedded
+  markup is definitely not allowed!
+  
+  name:   the name of this parameter
+  
+  TODO: This needs to be renamed or removed because it conflicts with the
+  XHTML element of the same name. In fact it could be simply removed since 
+  our usage is compatible with the XHTML usage, but it might be less 
+  ambiguous to rename it.
+-->
+<!ELEMENT param (#PCDATA)>
+<!ATTLIST param
+  name        CDATA           #REQUIRED>
+
+
+
+<!-- 
+	one of an explicit list of optional values a property may have 
+	NOTE: whether options get encoded at application layer or at database layer 
+	is UNDEFINED; either behaviour is correct. If at database layer it's also 
+	UNDEFINED whether they're encoded as a single reference data table or as 
+	separate reference data tables for each property.
+	
+	value:	the value of this option
+
+	TODO: This needs to be renamed or removed because it conflicts with the
+	XHTML element of the same name. In fact it could be simply removed since 
+	our usage is compatible with the XHTML usage, but it might be less 
+	ambiguous to rename it.
+-->
+<!ELEMENT option (documentation?, prompt*)>
+<!-- if the value is different from the prompt the user sees, specify it -->
+<!ATTLIST option 
+  value       CDATA           #IMPLIED>
+
+
+<!-- 
+	permissions policy on an entity, a page, form, list or field 
+	
+	group: 			the group to which permission is granted
+	permission:		the permission which is granted to that group
+-->
+<!ELEMENT permission (documentation?)>
+<!ATTLIST permission 
+	group 		  CDATA 					#REQUIRED
+	permission 	(%Permissions;) #REQUIRED>
+
+
+<!--
+  pragmatic advice to generators of lists and forms, in the form of 
+  name/value pairs which may contain anything. Over time some pragmas
+  will become 'well known', but the whole point of having a pragma
+  architecture is that it is extensible.
+-->
+<!ELEMENT pragma (documentation?)>
+<!ATTLIST pragma
+  name        CDATA           #REQUIRED
+  value       CDATA           #REQUIRED>
+
+<!-- 
+	a prompt for a property or field; used as the prompt text for a widget 
+	which edits it. Typically there will be only one of these per property
+  per locale; if there are more than one all those matching the locale may
+  be concatenated, or just one may be used.
+	
+	prompt:			the prompt to use
+	locale:			the locale in which to prefer this prompt	
+-->
+<!ELEMENT prompt (documentation?)>
+<!ATTLIST prompt
+	prompt		  CDATA				  	#REQUIRED
+	locale		  %Locale;				#REQUIRED >
+
+<!-- 
+	helptext about a property of an entity, or a field of a page, form or 
+	list, or a typedef. Typically there will be only one of these per property
+  per locale; if there are more than one all those matching the locale may
+  be concatenated, or just one may be used.
+
+	locale:			the locale in which to prefer this prompt	
+-->
+<!ELEMENT help (#PCDATA)>
+<!ATTLIST help
+	locale		  %Locale;				#REQUIRED
+  xmlns     CDATA             #IMPLIED >
+
+<!--
+  helpful text to be shown if a property value is missing, typically when 
+  a form is submitted. Typically there will be only one of these per property
+  per locale; if there are more than one all those matching the locale may
+  be concatenated, or just one may be used. Later there may be more sophisticated
+  behaviour here.
+-->
+<!ELEMENT ifmissing (#PCDATA)>
+<!ATTLIST ifmissing
+  locale      %Locale;        #REQUIRED
+  xmlns     CDATA             #IMPLIED>
+
+<!-- a form through which an entity may be added or edited
+
+  TODO: This needs to be renamed because it conflicts with the
+  XHTML element of the same name. 
+-->
+<!ELEMENT form (documentation?, ( %PageStuff;)*)>
+<!ATTLIST form %PageAttrs;>
+
+
+<!-- a page on which an entity may be displayed -->
+<!ELEMENT page (documentation?, ( %PageStuff;)*)>
+<!ATTLIST page %PageAttrs;>
+
+<!-- an ordering or records in a list 
+	property:	the property on which to order
+	sequence:	the sequence in which to order
+-->
+<!ELEMENT order (documentation?)>
+<!ATTLIST order
+      property  CDATA       #REQUIRED
+      sequence  (%Sequences;)  #IMPLIED>
+
+<!-- 
+	a list on which entities of a given type are listed
+
+	onselect:		name of form/page/list to go to when
+					    a selection is made from the list 
+-->
+<!ELEMENT list (documentation?, ( %PageStuff;|order)*)>
+<!ATTLIST list %PageAttrs;
+	onselect	  CDATA 					#IMPLIED >
+
+
+<!--
+  a subsidiary list, on which entities related to primary
+  entities in the enclosing page or list are listed
+  
+  property:   the property of the enclosing entity that this
+              list displays (obviously, must be of type='list')
+  onselect:   the form or page of the listed entity to call
+              when an item from the list is selected
+  canadd:     true if the user should be able to add records
+              to this list
+  -->
+<!ELEMENT auxlist (documentation?, (prompt|%FieldStuff;)*)>
+<!ATTLIST auxlist %PageAttrs;
+  property    CDATA           #REQUIRED
+  onselect    CDATA           #IMPLIED
+  canadd      %Boolean;       #IMPLIED>
+
+<!--
+  a group of fields and other controls within a form or list, which the 
+  renderer might render as a single pane in a tabbed display, for example.
+  -->
+<!ELEMENT fieldgroup (documentation?, (prompt|permission|%FieldStuff;)*)>
+<!ATTLIST fieldgroup
+  name        CDATA           #REQUIRED>
+
+
+<!-- a field in a form or page
+
+  property:   the property which this field displays/edits
+  -->
+<!ELEMENT field (documentation?, (prompt|help|permission)*) >
+<!ATTLIST field 
+  property    CDATA           #REQUIRED >
+
+<!-- a verb is something that may be done through a form. Probably the verbs 'store' 
+  and 'delete' are implied, but maybe they need to be explicitly declared. The 'verb'
+  attribute of the verb is what gets returned to the controller -->
+<!ELEMENT verb (documentation?, (prompt|help|permission)*) >
+<!ATTLIST verb
+  verb        CDATA           #REQUIRED
+  dangerous   %Boolean;       #REQUIRED>
+
+
+<!-- a container for global content -->
+<!ELEMENT content (%Content;)*>
+
+
+<!-- 
+	content to place in the head of the generated document; this is #PCDATA 
+	because it will almost certainly belong to a different namespace 
+	(usually HTML)
+
+	TODO: This needs to be renamed or removed because it conflicts with the
+	XHTML element of the same name. In fact it could be simply removed since 
+	our usage is compatible with the XHTML usage, but it might be less 
+	ambiguous to rename it.
+-->
+<!ELEMENT head (#PCDATA) >
+<!ATTLIST head
+  xmlns     CDATA             #IMPLIED>
+
+
+<!-- 
+	content to place in the top of the body of the generated document; 
+	this is %Flow; which is any HTML block or inline level element.
+-->
+<!ELEMENT top (#PCDATA) >
+<!ATTLIST top
+  xmlns     CDATA             #IMPLIED>
+
+<!-- 
+	content to place at the foot of the body of the generated document; 
+	this is %Flow; which is any HTML block or inline level element.
+-->
+<!ELEMENT foot (#PCDATA) >
+<!ATTLIST foot
+  xmlns     CDATA             #IMPLIED>
+
+<!-- 
+	The 'specification' and 'reference' elements are for documentation only,
+	and do not contribute to the engineering of the application described.
+	
+	A specification element is intended chiefly to declare the reference
+	documents which may be used in documentation elements later in the 
+	document. 
+	
+	url:		The URL from which the document referenced can be retrieved
+	name:		The full name (title) given to this document
+	abbr:		A convenient abbreviated name
+-->
+<!ELEMENT specification (documentation?, reference*)>
+<!ATTLIST specification
+		url			CDATA	#IMPLIED
+		name		CDATA	#REQUIRED
+		abbr		CDATA	#REQUIRED
+		>
+
+<!-- 
+	The 'specification' and 'reference' elements are for documentation only,
+	and do not contribute to the engineering of the application described.
+	
+	A reference element is a reference to a specifying document. 
+	
+	abbr:		The abbreviated name of the specification to which this
+				reference refers
+	section:	The 'anchor part' (part following a hash character) which,
+				when appended to the URL, will locate the exact section
+				referenced.
+	entity:		A reference to another entity within this ADL document
+	property:	A reference to another property within this ADL document;
+				if entity is also specified then of that entity, else of
+				the ancestor entity if any
+	-->
+<!ELEMENT reference (documentation?)>
+<!ATTLIST reference
+		abbr		CDATA	#IMPLIED
+		section		CDATA	#IMPLIED
+		entity		CDATA	#IMPLIED
+		property	CDATA	#IMPLIED
+		>
+
diff --git a/test.build b/test.build
deleted file mode 100755
index 4611d9a..0000000
--- a/test.build
+++ /dev/null
@@ -1,165 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<project name="ADL-Test-App" default="build"
-         xmlns="http://nant.sf.net/release/0.85-rc4/nant.xsd"
-         xmlns:nant="http://nant.sf.net/release/0.85-rc4/nant.xsd"
-         >
-	<property name="build.revision" value="$Revision: 1.5 $"/>
-
-	<property name="adl" value="."/>
-	<property name="adl-transforms" value="${adl}/transforms"/>
-	<property name="testapp" value="testapp"/>
-	<property name="rootns" value="Cygnet.ADL.TestApp"/>
-	<property name="entityns" value="${rootns}.Entities"/>
-	<property name="controllerns" value="${rootns}.Controllers"/>
-
-	<property name="controllers" value="testapp/Web/Controllers"/>
-	<property name="views" value="testapp/Web/Views" />
-
-	<property name="formcontroller" value="testapp/Web/Controllers/Form"/>
-	<property name="formview" value="testapp/Web/Views/Form"/>
-	<property name="bindir" value="testapp/Web/bin"/>
-	<property name="tmpdir" value="tmp"/>
-
-	<property name="adl-src" value="${testapp}/testapp.adl.xml" />
-	<property name="canonical" value="${tmpdir}/testapp.adl.xml" />
-	<property name="area-name" value="test"/>
-	<property name="nant-tasks" value="${tmpdir}/NantTasks.dll"/>
-	<property name="nant-contrib-dll" value="C:\Program Files\nantcontrib-0.85\bin\NAnt.Contrib.Tasks.dll"/>
-
-
-	<target name="fetchtasks" depends="prepare"
-		  description="fetches our NantTaks library from the well known place where it resides">
-		<get src="http://libs.cygnets.co.uk/NantTasks.dll" dest="${nant-tasks}"/>
-	</target>
-
-	<target name="canonicalise" description="generates adl for testapp entities">
-		<!-- adl2canonical.xslt -->
-		<style verbose="true" style="${adl-transforms}/adl2canonical.xslt"
-			   in="${adl-src}"
-			   out="${canonical}">
-			<parameters>
-				<parameter name="abstract-key-name-convention" value="Name_Id"/>
-			</parameters>
-		</style>
-	</target>
-
-	<target name="analyse">
-		<loadtasks assembly="${nant-contrib-dll}" />
-		<fxcop directOutputToConsole="true" projectFile="${testapp}/TestApp.fxcop">
-		</fxcop>
-	</target>
-
-	<target name="hbm" description="generates adl for testapp database NHibernate mapping"
-			depends="canonicalise">
-		<style verbose="true" style="${adl-transforms}/adl2hibernate.xslt"
-			   in="${canonical}"
-			   out="${tmpdir}/testapp.hbm.xml">
-			<parameters>
-				<parameter name="namespace" value="${entityns}"/>
-				<parameter name="assembly" value="${rootns}"/>
-			</parameters>
-		</style>
-	</target>
-
-	<target name="sql" description="Generates testapp database initialisation script"
-			depends="canonicalise">
-		<style verbose="true" style="${adl-transforms}/adl2mssql.xslt"
-			   in="${canonical}"
-			   out="${testapp}/testapp.auto.sql">
-			<parameters>
-				<parameter name="abstract-key-name-convention" value="Name_Id"/>
-				<parameter name="database" value="ADL_TestApp"/>
-			</parameters>
-		</style>
-	</target>
-
-	<target name="entities" description="creates C# classes for entities in the database"
-			depends="fetchtasks canonicalise">
-		<loadtasks assembly="${nant-tasks}" />
-
-		<style verbose="true" style="${adl-transforms}/adl2entityclass.xslt"
-			   in="${canonical}"
-			   out="${tmpdir}/classes.auto.cs">
-			<parameters>
-				<parameter name="locale" value="en-UK"/>
-				<parameter name="controllerns" value="${controllerns}"/>
-				<parameter name="entityns" value="${entityns}"/>
-			</parameters>
-		</style>
-		<exec program="c:\Program Files\astyle\bin\astyle.exe"
-			basedir="."
-			commandline="--style=java --indent=tab=4 --indent-namespaces ${tmpdir}/classes.auto.cs"/>
-		<split-regex in="${tmpdir}/classes.auto.cs"
-					 destdir="${testapp}/Auto"
-									 pattern="cut here: next file '([a-zA-Z0-9_.]*)'"/>
-	</target>
-
-	<target name="views" description="creates Velocity templates"
-			depends="fetchtasks canonicalise">
-		<loadtasks assembly="${nant-tasks}" />
-
-		<style verbose="true" style="${adl-transforms}/adl2views.xslt"
-			   in="${canonical}"
-			   out="${tmpdir}/views.auto.vm">
-			<parameters>
-				<parameter name="layout-name" value="default"/>
-				<parameter name="locale" value="en-UK"/>
-				<parameter name="controllerns" value="${controllerns}"/>
-				<parameter name="entityns" value="${entityns}"/>
-				<parameter name="generate-site-navigation" value="false"/>
-				<parameter name="permissions-group" value="partsbookeditors"/>
-				<parameter name="area-name" value="${area-name}"/>
-				<parameter name="show-messages" value="true"/>
-			</parameters>
-		</style>
-		<split-regex in="${tmpdir}/views.auto.vm"
-					 destdir="${views}/Auto/${area-name}" pattern="cut here: next file '([a-zA-Z0-9_./]*)'"/>
-	</target>
-
-	<target name="controllers" description="creates C# controller classes" depends="fetchtasks canonicalise">
-		<loadtasks assembly="${nant-tasks}" />
-		<style verbose="true" style="${adl-transforms}/adl2controllerclasses.xslt"
-			   in="${canonical}"
-			   out="${tmpdir}/controllers.auto.cs">
-
-			<parameters>
-				<parameter name="locale" value="en-UK"/>
-				<parameter name="controllerns" value="${controllerns}"/>
-				<parameter name="entityns" value="${entityns}"/>
-				<parameter name="layout-name" value="default"/>
-				<parameter name="rescue-name" value="generalerror"/>
-				<parameter name="area-name" value="${area-name}"/>
-			</parameters>
-		</style>
-		<exec program="c:\Program Files\astyle\bin\astyle.exe"
-			basedir="."
-			commandline="--style=java --indent=tab=4 --indent-namespaces ${tmpdir}/controllers.auto.cs"/>
-		<split-regex in="${tmpdir}/controllers.auto.cs"
-				   destdir="${controllers}/Auto" pattern="cut here: next file '([a-zA-Z0-9_.]*)'"/>
-	</target>
-
-
-	<target name="prepare" description="prepare directories used during the build">
-		<mkdir dir="${bindir}" failonerror="false"/>
-		<mkdir dir="${tmpdir}" failonerror="false"/>
-	</target>
-
-	<target name="clean" description="removes all products of the build process except the xml-ised database schema">
-		<delete>
-			<fileset>
-				<include name="**/*.auto.*"/>
-			</fileset>
-		</delete>
-		<delete failonerror="false" dir="${bindir}"/>
-		<delete failonerror="false" dir="${tmpdir}"/>
-	</target>
-
-	<target name="build" depends="prepare entities controllers views sql hbm"
-			description="compiles Visual Studio solution using msbuild">
-		<exec program="msbuild.exe"
-			  basedir="c:\windows\microsoft.net\framework\v3.5\"
-			  commandline="ADL.sln"/>
-	</target>
-	<target name="deploy" depends="clean build"/>
-
-</project>
\ No newline at end of file
diff --git a/transforms/adl2canonical.xslt b/transforms/adl2canonical.xslt
index d7482e0..1f381be 100755
--- a/transforms/adl2canonical.xslt
+++ b/transforms/adl2canonical.xslt
@@ -19,14 +19,14 @@
       every entity, form, page, list or field, the canonical form should
       explicitly state the permission, even if it is 'none'.
     
-    $Author: sb $
-    $Revision: 1.9 $
-    $Date: 2010-01-12 17:20:17 $
+    $Author: simon $
+    $Revision: 1.10 $
+    $Date: 2010-07-20 19:53:40 $
   -->
 
 <xsl:stylesheet version="1.0"
-  xmlns="http://libs.cygnets.co.uk/adl/1.4/"
-  xmlns:adl="http://libs.cygnets.co.uk/adl/1.4/"
+  xmlns="http://bowyer.journeyman.cc/adl/1.4/"
+  xmlns:adl="http://bowyer.journeyman.cc/adl/1.4/"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   exclude-result-prefixes="adl">
 
@@ -74,7 +74,7 @@
     *	THIS FILE IS AUTOMATICALLY GENERATED AND SHOULD NOT
     *	BE MANUALLY EDITED.
     *
-    *   Generated using adl2canonical.xslt <xsl:value-of select="substring('$Revision: 1.9 $', 12)"/>
+    *   Generated using adl2canonical.xslt <xsl:value-of select="substring('$Revision: 1.10 $', 12)"/>
 	*
 	***************************************************************************
 			</xsl:comment>
diff --git a/transforms/adl2controllerclasses.xslt b/transforms/adl2controllerclasses.xslt
index c2fdf30..59a3550 100755
--- a/transforms/adl2controllerclasses.xslt
+++ b/transforms/adl2controllerclasses.xslt
@@ -1,1374 +1,1405 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!--
-    Application Description Language framework
-    adl2controllerclasses.xsl
-    
-    (c) 2007 Cygnet Solutions Ltd
-    
-    Transform ADL into (partial) controller classes
-    
-    $Author: sb $
-    $Revision: 1.45 $
-    $Date: 2010-06-01 17:29:02 $
-  -->
-
-<!-- WARNING WARNING WARNING: Do NOT reformat this file! 
-     Whitespace (or lack of it) is significant! -->
-<xsl:stylesheet version="1.0"
-  xmlns="http://libs.cygnets.co.uk/adl/1.4/"
-  xmlns:adl="http://libs.cygnets.co.uk/adl/1.4/"
-  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
-  xmlns:exsl="urn:schemas-microsoft-com:xslt"
-  extension-element-prefixes="exsl">
-
-	<xsl:include href="csharp-type-include.xslt"/>
-	<xsl:include href="permissions-include.xslt"/>
-
-	<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"/>
-
-	<!-- bug 1896 : boilerplate text in views should be tailored to the locale of
-		the expected user. Unfortunately I haven't yet worked out how to do
-		conditional includes in XSLT, so this is a step on the way to a solution,
-		not a solution in itself. -->
-	<xsl:include href="i18n-en-GB-include.xslt"/>
-
-	<!-- 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"/>
-	<!-- Whether to authenticate at application or at database layer. 
-    If not 'Application', then 'Database'. -->
-	<xsl:param name="authentication-layer" select="'Application'"/>
-
-	<!-- the name and version of the product being built -->
-	<xsl:param name="product-version" select="'Application Description Language Framework'"/>
-
-	<!-- bug 1800 : the name of the Velocity layout to use -->
-	<xsl:param name="layout-name" select="adl-default-layout"/>
-	<!-- bug 1800 : the name of the Velocity rescue view to use -->
-	<xsl:param name="rescue-name"/>
-	<!-- bug 1800 : the name of the area (i.e. URL path part) to use -->
-	<xsl:param name="area-name"/>
-  <!-- bug 2883 : number of entries to show per list page (does not affect auxiliary lists) -->
-  <xsl:param name="records-per-page" select="15"/>
-
-	<xsl:template match="adl:application">
-		/* ---- [ cut here: next file '<xsl:value-of select="concat( 'Abstract', /adl:application/@name, 'Controller')"/>.auto.cs'] ---------------- */
-		//------------------------------------------------------------------
-		//
-		//  <xsl:value-of select="$product-version"/>
-		//  <xsl:value-of select="concat( 'Abstract', /adl:application/@name, 'Controller.auto.cs')"/>
-		//
-		// (c) 2007 Cygnet Solutions Ltd
-		//
-		//  Automatically generated abstract super class for controllers for the
-		//	<xsl:value-of select="/adl:application/@name"/> application; generated using
-		//  adl2controllerclasses.xslt version <xsl:value-of select="substring( '$Revision: 1.45 $', 10)"/>
-		//
-		//  <xsl:value-of select="/adl:application/@revision"/>
-		//
-		//  This file is automatically generated; DO NOT EDIT IT.
-		//
-		//------------------------------------------------------------------
-
-		/// &lt;summary&gt;
-		/// \mainpage <xsl:value-of select="concat( @name, ' ', @version)"/>
-		/// <xsl:value-of select="normalize-space(adl:documentation)"/>
-		///
-		/// \package <xsl:value-of select="$controllerns"/>
-		/// MVC Controller classes for <xsl:value-of select='/adl:application/@name'/>
-		/// &lt;/summary&gt;
-		namespace <xsl:value-of select="$controllerns"/> {
-		using System;
-		using System.Data;
-		using System.Collections.Generic;
-		using System.Data.SqlClient;
-		using NHibernate;
-		using NHibernate.Expression;
-		using Cygnet.DBAuth;
-		using Cygnet.Web.Controllers;
-		using Cygnet.Web.Helpers;
-		using Castle.MonoRail.Framework;
-		using <xsl:value-of select="$entityns"/>;
-
-		/// &lt;summary&gt;
-		/// Automatically generated abstract super class for controllers for the
-		/// <xsl:value-of select="/adl:application/@name"/> application
-		///
-		/// DO NOT EDIT THIS FILE!
-		/// &lt;/summary&gt;
-		[ <!-- in the longer term, all the helpers which a given 
-		project needs which not every project needs should be listed here, 
-		with appropriate 'xsl:if' wrappers. -->
-		Helper(typeof(FormatterHelper), "t"), 
-		Helper(typeof(SecurityHelper), "SecurityHelper")
-		]
-		public abstract partial class <xsl:value-of select="concat( 'Abstract', /adl:application/@name, 'Controller')"/> : BaseController {
-
-		<xsl:choose>
-			<xsl:when test="$authentication-layer = 'Application'"/>
-			<xsl:when test="$authentication-layer = 'Database'">
-				/* authentication layer is requested to be 'database', but in fact database-layer 
-				authentication does not work well with NHibernate so this is being ignored. */
-			</xsl:when>
-			<xsl:otherwise>
-				<xsl:message terminate="yes">
-					ADL: ERROR: invalid value (<xsl:value-of select="$authentication-layer"/>) provided for authentication-layer
-				</xsl:message>
-			</xsl:otherwise>
-		</xsl:choose>
-		
-		<xsl:for-each select="//adl:entity">
-			/// &lt;summary&gt;
-			/// Return a list of all instances of <xsl:value-of select="@name"/> for use in menus, etc;
-			/// &lt;/summary&gt;
-			protected IList&lt;<xsl:value-of select="concat( $entityns, '.', @name)"/>&gt; <xsl:value-of select="concat( 'FetchAll', @name)"/>( ) {
-			IList&lt;<xsl:value-of select="concat( $entityns, '.', @name)"/>&gt; result = new List&lt;<xsl:value-of select="concat( $entityns, '.', @name)"/>&gt;();
-
-			<xsl:variable name="readgroups">
-				<xsl:call-template name="entity-read-groups">
-					<xsl:with-param name="entity" select="."/>
-				</xsl:call-template>
-			</xsl:variable>
-			<xsl:if test="$authentication-layer = 'Database'">
-				if (
-				<xsl:for-each select="exsl:node-set( $readgroups)/*">
-					InGroup( "<xsl:value-of select="./@name"/>")<xsl:if test="position() != last()">||</xsl:if>
-				</xsl:for-each>
-				){
-			</xsl:if>
-			result = GetDBSession().CreateCriteria(typeof(<xsl:value-of select="concat( $entityns, '.', @name)"/>))
-			<xsl:for-each select="descendant::adl:property[@distinct='user']">
-				.AddOrder( <xsl:value-of select="concat('new Order( &#34;', @name, '&#34;, true)')"/>)
-			</xsl:for-each>
-			.SetCacheable( true)
-			.SetCacheRegion( "<xsl:value-of select="/adl:application/@name"/>")
-			.List&lt;<xsl:value-of select="concat( $entityns, '.', @name)"/>&gt;();
-			<xsl:if test="$authentication-layer != 'Application'">
-				}
-			</xsl:if>
-			return result;
-			}
-
-		</xsl:for-each>
-		}
-		}
-		<xsl:apply-templates select="adl:entity"/>
-	</xsl:template>
-
-
-	<!-- Don't bother generating anything for foreign entities -->
-	<xsl:template match="adl:entity[@foreign='true']"/>
-
-	<xsl:template match="adl:entity">
-		/*
-		 *	Not generating controller for entity <xsl:value-of select="@name"/>,
-		 *	as it has no forms, pages or lists.
-		 */
-	</xsl:template>
-	<xsl:template match="adl:entity[adl:form|adl:page|adl:list]">
-
-		/* ---- [ cut here: next file '<xsl:value-of select="@name"/>Controller.auto.cs'] ---------------- */
-
-		//------------------------------------------------------------------
-		//
-		//  <xsl:value-of select="$product-version"/>
-		//  <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
-		//  adl2controllerclasses.xslt version <xsl:value-of select="substring( '$Revision: 1.45 $', 10)"/>
-		//
-		//  This file is automatically generated; DO NOT EDIT IT.
-		//
-		//------------------------------------------------------------------
-
-		namespace <xsl:value-of select="$controllerns"/> {
-		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.Entities;
-		using Cygnet.Exceptions;
-		using Cygnet.Web.Helpers;
-		using Cygnet.Web.Controllers;
-		using Cygnet.Web.SmartControls;
-		using Cygnet.Utility;
-		using NHibernate;
-		using NHibernate.Expression;
-		using Castle.MonoRail.Framework;
-		using Iesi.Collections.Generic;
-		using <xsl:value-of select="$entityns"/>;
-
-		/// &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.
-		/// &lt;/summary&gt;
-		///
-		/// &lt;remarks&gt;
-		/// &lt;list type='bullet'&gt;
-		/// &lt;listheader&gt;&lt;description&gt;See also auto-generated Velocity view macros&lt;/description&gt;&lt;/listheader&gt;<xsl:for-each select='adl:form|adl:page|adl:list'>
-		/// &lt;item&gt;
-		/// &lt;term&gt;<xsl:value-of select="concat(@name, '.auto.vm')"/>&lt;/term&gt;
-		/// &lt;description&gt;<xsl:apply-templates select='adl:documentation'/>&lt;/description&gt;
-		/// &lt;/item&gt;</xsl:for-each>
-		/// &lt;/list&gt;
-		///
-		/// DO NOT EDIT THIS FILE!
-		/// &lt;/remarks&gt;
-		[
-		<xsl:if test="$layout-name">
-			Layout("<xsl:value-of select="$layout-name"/>"),
-		</xsl:if>
-		<xsl:if test="$rescue-name">
-			Rescue("<xsl:value-of select="$rescue-name"/>"),
-		</xsl:if>
-		ControllerDetails("<xsl:value-of select="@name"/>",	Area = "<xsl:value-of select="$area-name"/>"),
-		Helper(typeof(StylesHelper), "StylesHelper"),
-		Helper(typeof(<xsl:value-of select="concat( @name, 'FieldHelper')"/>), "<xsl:value-of select="concat( @name, 'FieldHelper')"/>")
-		]
-		public partial class <xsl:value-of select="concat( @name, 'Controller')"/> : <xsl:value-of select="concat( 'Abstract', /adl:application/@name, 'Controller')"/> {
-
-		protected class <xsl:value-of select="concat( @name, 'FieldHelper')"/> : SmartFormHelper {
-		public <xsl:value-of select="concat( @name, 'FieldHelper')"/>() {
-		<xsl:for-each select="descendant::adl:property[@type='entity']">
-			<xsl:variable name="entityname" select="@entity"/>
-			<xsl:variable name="entity" select="//adl:entity[@name=$entityname]"/>
-			<xsl:choose>
-				<xsl:when test="$entity/@foreign='true'">
-					/* Entity <xsl:value-of select="$entityname"/> is foreign..? */
-					<xsl:variable name="foreignkey" select="$entity/adl:key/adl:property[position()=1]/@name"/>
-					<xsl:variable name="userident">
-						<xsl:choose>
-							<xsl:when test="$entity//adl:property[@distinct='user' or @distinct='all']">
-								<xsl:value-of select="$entity//adl:property[@distinct='user' or @distinct='all'][position()=1]/@name"/>
-							</xsl:when>
-							<xsl:otherwise>
-								<xsl:value-of select="$foreignkey"/>
-							</xsl:otherwise>
-						</xsl:choose>
-					</xsl:variable>
-					Register&lt;<xsl:value-of select="concat( $entityns, '.', $entityname)"/>&gt;( "",
-					new TypeMenuControl&lt;<xsl:value-of select="concat( $entityns, '.', $entityname)"/>&gt;( "<xsl:value-of select="$foreignkey"/>","<xsl:value-of select="$userident"/>")); 
-				</xsl:when>
-				<xsl:otherwise>
-					Register&lt;<xsl:value-of select="concat( $entityns, '.', $entityname)"/>&gt;( "", EntityMenuControl&lt;<xsl:value-of select="concat( $entityns, '.', $entityname)"/>&gt;.Instance);
-				</xsl:otherwise>
-			</xsl:choose>
-		</xsl:for-each>
-		<xsl:for-each select="descendant::adl:property[@type='list']">
-			<xsl:variable name="entityname" select="@entity"/>
-			Register&lt;<xsl:value-of select="concat( $entityns, '.', $entityname)"/>&gt;( "", EntityShuffleControl&lt;<xsl:value-of select="concat( $entityns, '.', $entityname)"/>&gt;.Instance);
-		</xsl:for-each>
-
-		}
-		}
-
-		<xsl:if test="adl:property[@type='message']">
-			/// &lt;summary&gt;
-			/// Temporary hack to sort a problem with uninitialised messages
-			/// &lt;/summary&gt;
-			public void fixupMessages() {
-			ISession hibernator = GetDBSession();
-			ICollection&lt;<xsl:value-of select="concat($entityns, '.', @name)"/>&gt; instances =
-			hibernator.CreateCriteria( typeof( <xsl:value-of select="concat($entityns, '.', @name)"/>))
-			.List&lt;<xsl:value-of select="concat($entityns, '.', @name)"/>&gt;();
-
-			foreach ( <xsl:value-of select="concat($entityns, '.', @name)"/> instance in instances) {
-			<xsl:for-each select="adl:property[@type='message']">
-        <xsl:variable name="slot" select="concat( 'instance.', @name)"/>
-				if ( <xsl:value-of select="$slot"/> == null || <xsl:value-of select="concat( $slot, '.MessageId')"/> == 0 ){
-				<xsl:value-of select="$slot"/> = new Message();
-        
-        <xsl:value-of select="$slot"/>.BeforeUpdateHook( hibernator);
-				hibernator.SaveOrUpdate( <xsl:value-of select="$slot"/>);
-        <xsl:value-of select="$slot"/>.AfterUpdateHook( hibernator);
-        }
-      </xsl:for-each>
-      instance.BeforeUpdateHook( hibernator);
-			hibernator.SaveOrUpdate( instance);
-      instance.AfterUpdateHook( hibernator);
-			}
-			hibernator.Flush();
-			<xsl:if test="adl:list[@name='list']">
-				list();
-			</xsl:if>
-			}
-		</xsl:if>
-
-		<xsl:if test="adl:form">
-			<!-- unless there's at least one form, we won't generate a 'store' method -->
-			/// &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 = GetDBSession();
-			List&lt;string&gt; messages = new List&lt;string&gt;();
-      PropertyBag["messages"] = messages;
-			/* A 'newborn' instance can be updated even if the current user doesn't have
-			* update permissions, seeing that we use an update operation to set the
-			* field values and save the entity. */
-			Boolean isnewborn = false;
-
-			/* the instance (record) of type <xsl:value-of select="@name"/> we're dealing with */
-			<xsl:value-of select="concat($entityns, '.', @name)"/> record = null;
-
-			try {
-			<xsl:if test="adl:property[@distinct='system' or @distinct='all']">
-				/* a criteria object to use in distinctness checks */
-				ICriteria matchCriteria = null;
-			</xsl:if>
-
-			record = FetchRecord( hibernator);
-
-			<xsl:apply-templates select="adl:property"/>
-
-			if ( HasNoErrors()) {
-			if ( record == null) {
-			/* it seems to be new, create persistent object - if the user is permitted to */
-			AssertUserCanCreate();
-
-			try {
-			if ( AllKeys()) {
-			record = new <xsl:value-of select="concat($entityns, '.', @name)"/>(<xsl:for-each select="adl:key/adl:property">
-				<xsl:variable name="basetype">
-					<xsl:call-template name="base-type">
-						<xsl:with-param name="property" select="."/>
-					</xsl:call-template>
-				</xsl:variable>
-				<xsl:choose>
-					<xsl:when test="$basetype='integer'">
-						Int32.Parse( Form["<xsl:value-of select="concat( 'instance.', @name)"/>"])
-					</xsl:when>
-					<xsl:when test="$basetype='entity'">
-						<!-- Maybe TODO: this doesn't work recursively - if an entity has a key which is an entity 
-                  and the key of that entity is an entity, you're on your own, mate! -->
-						<xsl:variable name="keyentity" select="@entity"/>
-						<xsl:variable name="keyenttype">
-							<xsl:call-template name="primary-key-csharp-type">
-								<xsl:with-param name="entity" select="//adl:entity[@name=$keyentity]"/>
-							</xsl:call-template>
-						</xsl:variable>
-						hibernator.CreateCriteria( typeof( <xsl:value-of select="concat( $entityns, '.', $keyentity)"/>))
-						<xsl:call-template name="add-hibernate-expression-eq">
-							<xsl:with-param name="property" select="//adl:entity[@name=$keyentity]/adl:key/adl:property[position()=1]"/>
-							<xsl:with-param name="value">
-								Form[ "<xsl:value-of select="concat( 'instance.', @name)"/>"]
-							</xsl:with-param>
-						</xsl:call-template>
-						.UniqueResult&lt;<xsl:value-of select="concat( $entityns, '.', $keyentity)"/>&gt;()
-					</xsl:when>
-					<xsl:otherwise>
-						Form["<xsl:value-of select="concat( 'instance.', @name)"/>"]
-					</xsl:otherwise>
-				</xsl:choose>
-				<xsl:choose>
-					<xsl:when test="position() = last()"/>
-					<xsl:otherwise>, </xsl:otherwise>
-				</xsl:choose>
-			</xsl:for-each>);
-			}
-			else
-			{
-			record = new <xsl:value-of select="concat($entityns, '.', @name)"/>();
-			}
-			}
-			catch ( FormatException) {
-			/* failed to parse a number - not wholly unexpected, since it's most likely
-			* that an empty string was passed in */
-			record = new <xsl:value-of select="concat($entityns, '.', @name)"/>();
-			}
-			catch ( NullReferenceException) {
-			/* again, probably more normal than otherwise */
-			record = new <xsl:value-of select="concat($entityns, '.', @name)"/>();
-			}
-			messages.Add( "New <xsl:value-of select="@name"/> record created");
-      isnewborn = true;
-      }
-
-      if ( record != null) {
-      /* a transaction to ensure our database operations are atomic */
-      ITransaction tx = null;
-
-
-      if ( ! isnewborn) {
-      /* isnewborn cannot be true unless we've already checked user can create
-      * so no need to do it again here */
-      AssertUserCanUpdate();
-      }
-
-      try {
-      /* begin our atomic transaction */
-      tx = hibernator.BeginTransaction();
-      /* list of entities modified in this transaction */
-      List&lt;Entity&gt;  modified = new List&lt;Entity&gt;();
-
-          /* actually update the record */
-          BindObjectInstance( record, ParamStore.Form, "instance");
-          modified.Add( record);
-
-          <xsl:if test="descendant::adl:property[@type='message']">
-				/* there is at least one slot whose value is an internationalised message;
-				* if these have yet to be initialised they must be handled specially */
-				Locale locale = GetBestLocaleForUser();
-				<xsl:for-each select="descendant::adl:property[@type='message']">
-					if ( ! String.IsNullOrEmpty( Form["<xsl:value-of select="concat( 'instance.', @name)"/>"])){
-					/* there's an uninitialised message for this slot */
-					Message mess = record.<xsl:value-of select="@name"/>;
-					if ( mess == null) {
-					mess = new Message();
-					}
-          mess.BeforeUpdateHook( hibernator);
-					hibernator.SaveOrUpdate( mess);
-          mess.AfterUpdateHook( hibernator);
-
-					Translation trans = mess.GetTranslationObject( locale, hibernator);
-					if ( trans == null) {
-					trans = new Translation( mess, locale);
-					}
-					trans.MessageText = Form["<xsl:value-of select="concat( 'instance.', @name)"/>"];
-					record.<xsl:value-of select="@name"/> = mess;
-          trans.BeforeUpdateHook( hibernator);
-          hibernator.SaveOrUpdate( trans);
-          trans.AfterUpdateHook( hibernator);
-          }
-        </xsl:for-each>
-			</xsl:if>
-			<xsl:for-each select="descendant::adl: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. */
-				<xsl:variable name="entityname" select="@entity"/>
-				<xsl:choose>
-					<xsl:when test="//adl:entity[@name=$entityname]">
-						if ( ! String.IsNullOrEmpty( Form["<xsl:value-of select="concat( 'instance.', @name)"/>"]) &amp;&amp;
-						! EntityMenuControl&lt;<xsl:value-of select="concat( $entityns, '.', @entity)"/>&gt;.NULLMARKER.Equals ( Form["<xsl:value-of select="concat( 'instance.', @name)"/>"]))
-						{
-						record.<xsl:value-of select="@name"/> = <xsl:call-template name="fetch-property-instance">
-							<xsl:with-param name="property" select="."/>
-							<xsl:with-param name="value">
-								Form[ "<xsl:value-of select="concat( 'instance.', @name)"/>"]
-							</xsl:with-param>
-						</xsl:call-template>;
-
-            modified.Add( record.<xsl:value-of select="@name"/>);
-						}
-					</xsl:when>
-					<xsl:otherwise>
-						<xsl:message terminate="yes">
-							ADL: ERROR: Could not fix up value of <xsl:value-of select="@name "/>, because no
-							entity was found called <xsl:value-of select="$entityname"/>
-						</xsl:message>
-					</xsl:otherwise>
-				</xsl:choose>
-			</xsl:for-each>
-
-			<xsl:for-each select="descendant::adl:property[@type='link']">
-        <xsl:variable name="nearentityname" select="ancestor::adl:entity/@name"/>
-				<xsl:variable name="farentityname" select="@entity"/>
-				<xsl:variable name="entity" select="//adl:entity[@name=$farentityname]"/>
-				<xsl:variable name="farkey" select="$entity/adl:key/adl:property[position()=1]/@name"/>
-				<xsl:variable name="farkeybasetype">
-					<xsl:call-template name="base-type">
-						<xsl:with-param name="property" select="//adl:entity[@name=$farentityname]/adl:key/adl:property[position()=1]"/>
-					</xsl:call-template>
-				</xsl:variable>
-				<xsl:variable name="deletegroups">
-					<xsl:call-template name="entity-delete-groups">
-						<xsl:with-param name="entity" select="$entity"/>
-					</xsl:call-template>
-				</xsl:variable>
-				/* For a link, collect changes to link table and process them */
-				<xsl:if test="$authentication-layer = 'Database'">
-					if ( <xsl:for-each select="exsl:node-set( $deletegroups)/*">InGroup( "<xsl:value-of select="./@name"/>") ||</xsl:for-each> false) {
-					/* however, we cannot do anything unless we have delete permissions on the table, so
-					* should not try. */
-				</xsl:if>
-        LinkChanges&lt;<xsl:value-of select="concat( $entityns, '.', @entity)"/>&gt; changes = 
-        LinkTableUpdater&lt;<xsl:value-of select="concat( $entityns, '.', @entity)"/>&gt;.Changes( <xsl:value-of select="concat( 'record.', @name)"/>, Form.GetValues( "<xsl:value-of select="concat( 'instance.', @name)"/>"),
-        hibernator);
-
-        foreach ( var item in changes.ToRemove) {
-        modified.Add(item);
-        <xsl:value-of select="concat( 'record.', @name)"/>.Remove(item);
-        <xsl:for-each select="$entity//adl:property[@type='link' and @entity=$nearentityname]">
-          <xsl:value-of select="concat( 'item.', @name)"/>.Remove( record);
-          <xsl:if test="position() != 1">
-            /* WARNING WARNING WARNING! Could not uniquely determine the far side property;
-             * redesign your application or manually maintain this code! */
-           <xsl:message terminate="no">
-             WARNING: Could not uniquely determine far end of link represented by property <xsl:value-of select="@name"/> of <xsl:value-of select="$nearentityname"/>
-           </xsl:message>
-          </xsl:if>
-        </xsl:for-each>
-        }
-        foreach ( var item in changes.ToAdd) {
-        modified.Add(item);
-        <xsl:value-of select="concat( 'record.', @name)"/>.Add(item);
-        <xsl:for-each select="$entity//adl:property[@type='link' and @entity=$nearentityname]">
-          <xsl:value-of select="concat( 'item.', @name)"/>.Add( record);
-          <xsl:if test="position() != 1">
-            /* WARNING WARNING WARNING! Could not uniquely determine the far side property;
-            * redesign your application or manually maintain this code! */
-            <xsl:message terminate="no">
-              WARNING: Could not uniquely determine far end of link represented by property <xsl:value-of select="@name"/> of <xsl:value-of select="$nearentityname"/>
-            </xsl:message>
-          </xsl:if>
-        </xsl:for-each>
-        }
-
-        <xsl:if test="$authentication-layer = 'Database'">
-          } /* if ( <xsl:for-each select="exsl:node-set( $deletegroups)/*">
-            InGroup( "<xsl:value-of select="./@name"/>") ||
-          </xsl:for-each> false) */
-        </xsl:if>
-			</xsl:for-each>
-
-			<xsl:for-each select="descendant::adl:property[@type='list']">
-				<xsl:variable name="farentityname" select="@entity"/>
-				<xsl:variable name="entity" select="//adl:entity[@name=$farentityname]"/>
-				<xsl:variable name="farkey" select="$entity/adl:key/adl:property[position()=1]/@name"/>
-				<xsl:variable name="farkeybasetype">
-					<xsl:call-template name="base-type">
-						<xsl:with-param name="property" select="//adl:entity[@name=$farentityname]/adl:key/adl:property[position()=1]"/>
-					</xsl:call-template>
-				</xsl:variable>
-				<xsl:variable name="foreignkey">
-					<xsl:choose>
-						<xsl:when test="@farkey">
-							<xsl:value-of select="@farkey"/>
-						</xsl:when>
-						<xsl:otherwise>
-							<!-- If I haven't been told what the far side foreign key is, assume it has the
-								name of my entity -->
-							<xsl:value-of select="ancestor::adl:entity/@name"/>
-						</xsl:otherwise>
-					</xsl:choose>
-				</xsl:variable>
-				<xsl:variable name="deletegroups">
-					<xsl:call-template name="entity-delete-groups">
-						<xsl:with-param name="entity" select="$entity"/>
-					</xsl:call-template>
-				</xsl:variable>
-				/* with a list we cannot just smash the old values! Instead we need to check
-				* each one and exclude it if no longer required; */
-				<xsl:if test="$authentication-layer = 'Database'">
-					if ( <xsl:for-each select="exsl:node-set( $deletegroups)/*">
-						InGroup( "<xsl:value-of select="./@name"/>") ||
-					</xsl:for-each> false) {
-					/* but once again only if we can delete and create entities at the far end. */
-				</xsl:if>
-				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.KeyString;
-				bool found = false;
-
-				foreach ( string index in <xsl:value-of select="concat(@name, 'Values')"/>)
-				{
-				if ( index.Equals( itemId))
-				{
-				found = true;
-				break;
-				}
-				} /* foreach ( string index... */
-
-				if ( ! found)
-				{
-				record.<xsl:value-of select="@name"/>.Remove( item);
-        modified.Add( item);
-				break;
-				}
-				} /* foreach ( <xsl:value-of select="@entity"/> 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="concat( $entityns, '.', @entity)"/> item =
-				hibernator.CreateCriteria(typeof(<xsl:value-of select="@entity"/>))
-				<xsl:call-template name="add-hibernate-expression-eq">
-					<xsl:with-param name="property" select="//adl:entity[@name=$farentityname]/adl:key/adl:property[position()=1]"/>
-					<xsl:with-param name="value" select="'index'"/>
-				</xsl:call-template>
-				.UniqueResult&lt;<xsl:value-of select="concat( $entityns, '.', @entity)"/>&gt;();
-
-				if ( ! record.<xsl:value-of select="@name"/>.Contains( item))
-				{
-				/* check whether it's already a child of another <xsl:value-of select="ancestor::adl:entity/@name"/>
-				* and, if it is, remove it */
-				<xsl:value-of select="concat( $entityns, '.', ancestor::adl:entity/@name)"/> oldparent =
-				<xsl:value-of select="concat( 'item.', $foreignkey)"/>;
-				if ( oldparent != null) {
-				oldparent.<xsl:value-of select="@name"/>.Remove( item);
-        
-        modified.Add( oldparent);
-				}
-
-				/* then add it to my <xsl:value-of select="@name"/> */
-				record.<xsl:value-of select="@name"/>.Add( item);
-				<xsl:value-of select="concat( 'item.', $foreignkey)"/> = record;
-        modified.Add( item);
-				}
-				} /* foreach ( string index... */
-				} /* if ( Form.GetValues( "<xsl:value-of select="concat( 'instance.', @name)"/>") != null) */
-				<xsl:if test="$authentication-layer = 'Database'">
-					} /* if ( <xsl:for-each select="exsl:node-set( $deletegroups)/*">InGroup( "<xsl:value-of select="./@name"/>") ||</xsl:for-each> false) */
-				</xsl:if>
- 
-			</xsl:for-each>
-
-      /* write the modified records to the database */
-      foreach ( Entity item in modified) {
-      item.BeforeUpdateHook( hibernator);
-      hibernator.SaveOrUpdate(item);
-      item.AfterUpdateHook( hibernator);
-      }
-      /* and if no exceptions, commit */
-      tx.Commit();
-
-      messages.Add( "<xsl:call-template name="i18n-record-saved"/>");
-			} /* try actually commit */
-			catch ( Exception any) {
-			messages.Add( "<xsl:call-template name="i18n-record-not-saved"/>");
-			AddError( any);
-			try {
-			tx.Rollback();
-			} catch ( ObjectDisposedException ode) {
-			AddError( ode);
-			}
-			} /* catch ( Exception any) */
-			} /* if ( record != null) */
-			else {
-			throw new ApplicationException( String.Format( "<xsl:call-template name="i18n-record-not-found">
-				<xsl:with-param name="entity-name" select="@name"/>
-			</xsl:call-template>"));
-			}
-			} /* if ( HasNoErrors()) */
-			} /* try */
-			catch ( DataSuitabilityException dse)
-			{
-			AddError( dse);
-			}
-			catch ( ApplicationException axe)
-			{
-			AddError( axe.Message);
-			}
-
-			if ( ! HasNoErrors())
-			{
-			/* the session may be polluted; create a new session */
-			CloseDBSession();
-			hibernator = GetDBSession();
-
-			record = FetchRecord( hibernator);
-			} /* if ( ! HasNoErrors()) */
-			<xsl:value-of select="concat( 'this.',adl:form[position()=1]/@name)"/>( record);
-			}
-
-      <!-- unless there's at least one form, we won't generate a 'delete' method -->
-			/// &lt;summary&gt;
-			/// Actually delete the selected record
-			/// &lt;/summary&gt;
-      [AccessibleThrough(Verb.Post)]
-      public void Delete()
-      {
-      AssertUserCanDelete();
-      ISession hibernator = GetDBSession();
-      <xsl:value-of select="concat($entityns, '.', @name)"/> record = null;
-
-      if ( "true".Equals( Params["reallydelete"]))
-      {
-      record = FetchRecord( hibernator);
-
-      if ( record != null)
-      {
-      try {
-      record.BeforeDeleteHook( hibernator);
-      hibernator.Delete( record);
-      hibernator.Flush();
-      } catch ( DomainKnowledgeViolationException dkve) {
-      AddError( dkve);
-      }
-      }
-      else
-      {
-      throw new ApplicationException( "No such record?");
-      }
-      }
-      if ( HasNoErrors()) {
-      <xsl:choose>
-				<xsl:when test="adl:list">
-					Redirect( "<xsl:value-of select="concat(adl:list[position()=1]/@name, '.rails')"/>");
-				</xsl:when>
-				<xsl:otherwise>
-					Redirect( FormsAuthentication.DefaultUrl);
-				</xsl:otherwise>
-			</xsl:choose>
-      } else {
-      PropertyBag[ "instance"] = record;
-      RenderViewWithFailover( "maybedelete.vm", "maybedelete.auto.vm");
-      }
-      }
-    </xsl:if>
-		<xsl:apply-templates select="adl:form"/>
-    <xsl:apply-templates select="adl:list"/>
-
-    /// &lt;summary&gt;
-		/// Check whether values for all my keys are available in the form fields
-		/// &lt;/summary&gt;
-		protected bool AllKeys() {
-		/* whether we have valid values for all the key fields */
-		bool result = true;
-
-		<xsl:for-each select="adl:key/adl:property">
-			if ( String.IsNullOrEmpty( Form["<xsl:value-of select="concat( 'instance.', @name)"/>"])) {
-			result = false;
-			} else if ( "<xsl:value-of select="concat('$instance.', @name)"/>".Equals( Form["<xsl:value-of select="concat( 'instance.', @name)"/>"])) {
-			/* nasty artefact of NVelocity forms - default 'null value' is dollar followed by fieldname */
-			result = false;
-			}
-		</xsl:for-each>
-
-		return result;
-		}
-
-		/// &lt;summary&gt;
-		/// Fetch the record represented by the values in the current Form
-		/// &lt;/summary&gt;
-		protected <xsl:value-of select="concat($entityns, '.', @name)"/> FetchRecord(ISession hibernator) {
-		/* the instance (record) of type <xsl:value-of select="@name"/> we're dealing with */
-		<xsl:value-of select="concat($entityns, '.', @name)"/> record = null;
-
-		if ( AllKeys()){
-		/* it's (probably) existing, retrieve it */
-		record = hibernator.CreateCriteria(typeof(<xsl:value-of select="concat( $entityns, '.', @name)"/>))
-		<xsl:for-each select="adl:key/adl:property">
-			<xsl:call-template name="add-hibernate-expression-eq">
-				<xsl:with-param name="property" select="."/>
-				<xsl:with-param name="value">Form["<xsl:value-of select="concat( 'instance.', @name)"/>"]</xsl:with-param>
-			</xsl:call-template>
-		</xsl:for-each>
-		.UniqueResult&lt;<xsl:value-of select="concat( $entityns, '.', @name)"/>&gt;();
-		}
-
-		return record;
-		}
-		}
-		}
-		/* ---- [ cut here: next file 'junk'] ------------------------- */
-	</xsl:template>
-
-	<xsl:template match="adl:property">
-		<xsl:if test="@required='true'">
-			if ( 
-			<xsl:if test="@immutable='true'">
-				(record == null || <xsl:value-of select="concat( 'record.', @name)"/> == null) &amp;&amp;
-			</xsl:if>
-			String.IsNullOrEmpty( Form[ "<xsl:value-of select="concat( 'instance.', @name)"/>" ]))
-			{
-			AddError( <xsl:choose>
-				<xsl:when test="adl:ifmissing[@locale=$locale]">
-					<xsl:apply-templates select="adl:ifmissing[@locale=$locale]"/>
-				</xsl:when>
-				<xsl:otherwise>
-					"<xsl:call-template name="i18n-value-required">
-						<xsl:with-param name="property-name" select="@name"/>
-					</xsl:call-template>"
-				</xsl:otherwise>
-			</xsl:choose>);
-			} 
-		</xsl:if>
-		<xsl:if test="@distinct='system' or @distinct='all'">
-			<xsl:call-template name="check-property-value-distinct">
-				<xsl:with-param name="property" select="."/>
-			</xsl:call-template>
-		</xsl:if>
-	</xsl:template>
-
-	<xsl:template match="adl:ifmissing">
-		"<xsl:value-of select="normalize-space(.)"/>"
-	</xsl:template>
-
-	<xsl:template match="adl:form">
-		/// &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( "<xsl:call-template name="i18n-command-not-found"/>");
-		}
-		else
-		<xsl:for-each select=".//adl: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 = GetDBSession();
-
-		<xsl:value-of select="concat($entityns, '.', ancestor::adl:entity/@name)"/> record = FetchRecord( hibernator);
-
-		TypedPropertyBag = new {
-		instance = record };
-
-		RenderViewWithFailover( "maybedelete.vm", "maybedelete.auto.vm");
-		}
-		else if ( command.Equals( "store"))
-		{
-		Store();
-		}
-		else
-		{
-		throw new Exception( String.Format("<xsl:call-template name="i18n-command-not-found">
-			<xsl:with-param name="command" select="'{0}'"/>
-		</xsl:call-template>", command));
-		}
-		}
-
-		/// &lt;summary&gt;
-		/// Show the form named <xsl:value-of select="@name"/>, with no existing record
-		/// &lt;/summary&gt;
-		[AccessibleThrough(Verb.Get)]
-		public void <xsl:value-of select="@name"/>( )
-		{
-		AssertUserCanRead();
-		<xsl:value-of select="concat( 'PrototypeFor', ancestor::adl:entity/@name)"/> record = 
-      new <xsl:value-of select="concat( 'PrototypeFor', ancestor::adl:entity/@name)"/>();
-
-    ISession hibernator = GetDBSession();
-
-    TypedPropertyBag = new {
-    <xsl:call-template name="formmenus">
-      <xsl:with-param name="form" select="."/>
-    </xsl:call-template>
-    instance = record };
-
-    RenderViewWithFailover("<xsl:value-of select="concat( @name, '.vm')"/>", "<xsl:value-of select="concat( @name, '.auto.vm')"/>");
-    }
-
-    <xsl:variable name="form" select="."/>
-		<xsl:for-each select="ancestor::adl:entity/adl:property[ @type='entity']">
-		/// &lt;summary&gt;
-		/// Show the form named <xsl:value-of select="$form/@name"/>, for a new record, but with the
-		/// value for <xsl:value-of select="@name"/> already predetermined
-		/// &lt;/summary&gt;
-			[AccessibleThrough(Verb.Get)]
-			public void <xsl:value-of select="concat($form/@name, 'With', @name)"/>( string <xsl:value-of select="@name"/>)
-			{
-			AssertUserCanRead();
-			ISession hibernator = GetDBSession();
-			<xsl:value-of select="ancestor::adl:entity/@name"/> record = new <xsl:value-of select="concat( $entityns, '.', ancestor::adl:entity/@name)"/>();
-
-			record.<xsl:value-of select="@name"/> = <xsl:call-template name="fetch-property-instance">
-				<xsl:with-param name="property" select="."/>
-				<xsl:with-param name="value" select="@name"/>
-			</xsl:call-template>;
-			
-			<xsl:value-of select="concat( 'this.', $form/@name)"/>( record);
-			}
-		</xsl:for-each>
-
-		/// &lt;summary&gt;
-		/// Show the form named <xsl:value-of select="@name"/>, containing the indicated record. As
-		/// the primary key of the record is itself an entity, we need to first fetch that entity
-		/// &lt;/summary&gt;
-		<xsl:for-each select="ancestor::adl:entity/adl:key/adl:property">
-			<xsl:choose>
-				<xsl:when test="@type='entity'">
-					/// &lt;param name="<xsl:value-of select="@name"/>"&gt;the key value of the key value of the record to show&lt;/param&gt;
-				</xsl:when>
-				<xsl:otherwise>
-					/// &lt;param name="<xsl:value-of select="@name"/>"&gt;the key value of the record to show&lt;/param&gt;
-				</xsl:otherwise>
-			</xsl:choose>
-		</xsl:for-each>
-		[AccessibleThrough(Verb.Get)]
-		public void <xsl:value-of select="@name"/>( <xsl:for-each select="ancestor::adl:entity/adl:key/adl:property">
-			<!-- all args are passed as string because that's what hibernate-expression-eq expects -->
-			string <xsl:value-of select="concat( ' ', @name)"/>
-			<xsl:if test="not( position() = last())">,</xsl:if>
-		</xsl:for-each>) {
-		ISession hibernator = GetDBSession();
-		<xsl:value-of select="concat( 'this.', @name)"/>(
-		hibernator.CreateCriteria( typeof(<xsl:value-of select="concat($entityns, '.', ancestor::adl:entity/@name)"/>))
-		<xsl:for-each select="ancestor::adl:entity/adl:key/adl:property">
-			<xsl:call-template name="add-hibernate-expression-eq">
-				<xsl:with-param name="property" select="."/>
-				<xsl:with-param name="value" select="@name"/>
-			</xsl:call-template>
-		</xsl:for-each>
-		.UniqueResult&lt;<xsl:value-of select="concat($entityns, '.', ancestor::adl:entity/@name)"/>&gt;());
-		}
-
-		/// &lt;summary&gt;
-		/// Show the form named <xsl:value-of select="@name"/>, containing the indicated record
-		/// &lt;/summary&gt;
-		/// &lt;param name="record"&gt;the record to show&lt;/param&gt;
-		protected void <xsl:value-of select="@name"/>( <xsl:value-of select="concat($entityns, '.', ancestor::adl:entity/@name)"/> record)
-		{
-		ISession hibernator = GetDBSession();
-
-		TypedPropertyBag = new {
-		<xsl:call-template name="formmenus">
-			<xsl:with-param name="form" select="."/>
-		</xsl:call-template>
-		instance = record };
-
-		RenderViewWithFailover("<xsl:value-of select="concat( @name, '.vm')"/>", "<xsl:value-of select="concat( @name, '.auto.vm')"/>");
-		}
-	</xsl:template>
-
-	<xsl:template match="adl: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"/>()
-    {
-    AssertUserCanRead();
-    
-    string view = "<xsl:value-of select="@name"/>";
-    ISession hibernator = GetDBSession();
-    ICriteria search =
-    hibernator.CreateCriteria(typeof(<xsl:value-of select="concat( $entityns, '.', ancestor::adl:entity/@name)"/>));
-    Boolean withSearchCriteria = false;
-
-    <xsl:for-each select="adl:field">
-      <xsl:variable name="fieldprop" select="@property"/>
-      <xsl:variable name="property" select="ancestor::adl:entity//adl:property[@name=$fieldprop]"/>
-      <xsl:variable name="base-type">
-        <xsl:call-template name="base-type">
-          <xsl:with-param name="property" select="$property"/>
-        </xsl:call-template>
-      </xsl:variable>
-      /* <xsl:value-of select="@property"/> */
-      <xsl:choose>
-        <xsl:when test="$base-type='boolean'"/>
-        <xsl:when test="$base-type='link'"/>
-        <xsl:when test="$base-type='list'"/>
-        <xsl:otherwise>
-          if ( ! String.IsNullOrEmpty( Params[ "<xsl:value-of select="concat( 'search_', $property/@name)"/>"])) {
-          search<xsl:call-template name="add-hibernate-expression-like">
-            <xsl:with-param name="property" select="$property"/>
-            <xsl:with-param name="value">
-              Params["<xsl:value-of select="concat( 'search_', $property/@name)"/>"]
-            </xsl:with-param>
-          </xsl:call-template>;
-          PropertyBag["<xsl:value-of select="concat( 'search_', $property/@name)"/>"] = Params[ "<xsl:value-of select="concat( 'search_', $property/@name)"/>"];
-          withSearchCriteria = true;
-          }
-        </xsl:otherwise>
-      </xsl:choose>
-    </xsl:for-each>
-
-    <xsl:choose>
-      <xsl:when test="adl:order">
-        /* explicit ordering */
-        <xsl:apply-templates select="adl:order"/>
-      </xsl:when>
-      <xsl:otherwise>
-        /* no explicit ordering */
-        <xsl:for-each select="ancestor::adl:entity//adl:property[@distinct='user' or @distinct='all']">
-          search.AddOrder(<xsl:value-of select="concat( ' new Order( &#34;', @name, '&#34;, true)')"/>);
-        </xsl:for-each>
-      </xsl:otherwise>
-    </xsl:choose>
-
-    IList&lt;<xsl:value-of select="concat( $entityns, '.', ancestor::adl:entity/@name)"/>&gt; instances = search.List&lt;<xsl:value-of select="concat( $entityns, '.', ancestor::adl:entity/@name)"/>&gt;();
-
-    /* if no instances, set showRecords to one else we get a division by zero error */
-    int showRecords = instances.Count > 0? instances.Count: 1;
-
-    if ( ! withSearchCriteria) {
-    showRecords = <xsl:value-of select="$records-per-page"/>;
-    }
-
-    PropertyBag["instances"] =
-    PaginationHelper.CreatePagination( this, instances, showRecords);
-
-    RenderViewWithFailover(view + ".vm", view + ".auto.vm");
-    }
-
-  </xsl:template>
-
-  <xsl:template match="adl:order">
-    search.AddOrder( new Order( "<xsl:value-of select="@property"/>", 
-    <xsl:choose>
-      <xsl:when test="@sequence='reverse-canonical'">false</xsl:when>
-      <xsl:otherwise>true</xsl:otherwise>
-    </xsl:choose>));
-  </xsl:template>
-
-	<xsl:template match="adl:documentation">
-		/* <xsl:apply-templates/> */
-	</xsl:template>
-
-
-	<xsl:template match="adl:key">
-		<!-- the key shouldn't be matched directly - at least, not in this implementation -->
-	</xsl:template>
-
-	<!-- for properties with @distinct='all' or @distinct='system', 
-		check that values are indeed distinct -->
-	<xsl:template name="check-property-value-distinct">
-		<xsl:param name="property"/>
-
-		<xsl:variable name="basetype">
-			<xsl:call-template name="base-type">
-				<xsl:with-param name="property" select="."/>
-			</xsl:call-template>
-		</xsl:variable>
-
-		<xsl:choose>
-			<xsl:when test="$property/ancestor::adl:key and not( $property/ancestor::adl:entity/adl:key[position()=2])">
-				<!-- if I'm the property of a key field and it is the only key field of my entity then
-					it is pointless trying to establish my distinctness -->
-			</xsl:when>
-			<xsl:when test="$property/@distinct = 'system' or $property/@distinct='all'">
-				/* <xsl:value-of select="$property/@name"/> should be distinct: check that it is */
-				matchCriteria =
-				hibernator.CreateCriteria(typeof(<xsl:value-of select="$property/ancestor::adl:entity/@name"/>));
-
-				matchCriteria<xsl:call-template name="add-hibernate-expression-eq">
-					<xsl:with-param name="property" select="$property"/>
-					<xsl:with-param name="value">
-						Form["<xsl:value-of select="concat( 'instance.', @name)"/>"]
-					</xsl:with-param>
-				</xsl:call-template>;
-
-				if ( record != null) {
-				/* i.e. we do have values for each of our key fields... */
-				<xsl:for-each select="$property/ancestor::adl:entity/adl:key/adl:property[position()=1]">
-					<xsl:variable name="keybasetype">
-						<xsl:call-template name="base-type">
-							<xsl:with-param name="property" select="."/>
-						</xsl:call-template>
-					</xsl:variable>
-					matchCriteria.Add(Expression.Not(<xsl:call-template name="hibernate-expression-eq">
-						<xsl:with-param name="property" select="."/>
-						<xsl:with-param name="value">
-							Form["<xsl:value-of select="concat( 'instance.', @name)"/>"]
-						</xsl:with-param>
-					</xsl:call-template>));
-				</xsl:for-each>
-				}
-
-				if ( matchCriteria.List&lt;<xsl:value-of select="$property/ancestor::adl:entity/@name"/>&gt;().Count > 0)
-				{
-				AddError(
-				String.Format("There is already a {0} with the {1} '{2}'",
-				"<xsl:value-of select="$property/ancestor::adl:entity/@name"/>", "<xsl:value-of select="$property/@name"/>", Form["<xsl:value-of select="concat('instance.', $property/@name)"/>"]));
-				}
-			</xsl:when>
-		</xsl:choose>
-	</xsl:template>
-
-
-	<!-- produce all menus for a given form: harder, but more efficient -->
-	<xsl:template name="formmenus">
-		<!-- an entity assumed to be of type adl:form -->
-		<xsl:param name="form"/>
-		<xsl:choose>
-			<xsl:when test="$form/@properties = 'all'">
-				<xsl:call-template name="entitymenus">
-					<xsl:with-param name="entity" select="$form/ancestor::adl:entity"/>
-				</xsl:call-template>
-			</xsl:when>
-			<xsl:otherwise>
-				/* form menus */
-				<xsl:for-each select="$form//adl:field">
-					<xsl:variable name="propname" select="@property"/>
-					<xsl:choose>
-						<xsl:when test="parent::adl:auxlist"/>
-						<xsl:when test="$form/ancestor::adl:entity//adl:property[@name=$propname and @type='entity']">
-							/* produce a list of <xsl:value-of select="$form/ancestor::adl:entity//adl:property[@name=$propname]/@entity"/> to populate the select for <xsl:value-of select="$propname"/> */
-							<xsl:call-template name="menu">
-								<xsl:with-param name="property" select="$form/ancestor::adl:entity//adl:property[@name=$propname]"/>
-							</xsl:call-template>
-						</xsl:when>
-						<xsl:when test="$form/ancestor::adl:entity//adl:property[@name=$propname and @type='link']">
-							/* produce a list of <xsl:value-of select="$form/ancestor::adl:entity//adl:property[@name=$propname]/@entity"/> to populate the LHS of the shuffle for <xsl:value-of select="$propname"/> */
-							<xsl:call-template name="menu">
-								<xsl:with-param name="property" select="$form/ancestor::adl:entity//adl:property[@name=$propname]"/>
-							</xsl:call-template>
-						</xsl:when>
-						<xsl:when test="$form/ancestor::adl:entity//adl:property[@name=$propname and @type='list']">
-							/* produce a list of <xsl:value-of select="$form/ancestor::adl:entity//adl:property[@name=$propname]/@entity"/> to populate the multi-select for <xsl:value-of select="@name"/> */
-							<xsl:call-template name="menu">
-								<xsl:with-param name="property" select="$form/ancestor::adl:entity//adl:property[@name=$propname]"/>
-							</xsl:call-template>
-						</xsl:when>
-					</xsl:choose>
-				</xsl:for-each>
-			</xsl:otherwise>
-		</xsl:choose>
-	</xsl:template>
-
-
-	<!-- produce all menus for a given entity: easier, but less efficient -->
-	<xsl:template name="entitymenus">
-		<xsl:param name="entity"/>
-		/* there's no way I can find of producing a set of just those entities
-		* we'll need menus for. So we set up variables for all the menus we might
-		* need, and then only instantiate those we do need. */
-		<xsl:for-each select="$entity/adl:property[@type='entity']">
-			<!-- $entity/adl:property because it is possible to have type='entity' in the key -->
-			<xsl:call-template name="menu">
-				<xsl:with-param name="property" select="."/>
-			</xsl:call-template>
-		</xsl:for-each>
-		<xsl:for-each select="$entity/adl:property[@type='link']">
-			<!-- $entity/adl:property because it is not possible to have type='link' in the key -->
-			/* 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/adl: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="entity" select="//adl:entity[@name=$property/@entity]"/>
-		<xsl:value-of select="concat('all_', $property/@name)"/> =
-		<xsl:value-of select="concat( 'FetchAll', $entity/@name)"/>( ),
-	</xsl:template>
-
-	<xsl:template name="primary-key-csharp-type">
-		<xsl:param name="entity"/>
-		<xsl:if test="not( $entity)">
-			<xsl:message terminate="yes">
-				ADL: ERROR: No entity passed to template primary-key-csharp-type
-			</xsl:message>
-		</xsl:if>
-		<xsl:if test="not($entity/adl:key/adl:property)">
-			<xsl:message terminate="no">
-				ADL: WARNING: entity '<xsl:value-of select="$entity/@name"/>' has no primary key.
-				You will have to manually edit <xsl:value-of select="concat( $entity/@name, 'Controller.auto.cs')"/>
-			</xsl:message>
-		</xsl:if>
-		<xsl:call-template name="csharp-type">
-			<xsl:with-param name="property" select="$entity/adl:key/adl:property[ position() = 1]"/>
-			<xsl:with-param name="entityns" select="$entityns"/>
-		</xsl:call-template>
-	</xsl:template>
-
-	<xsl:template name="primary-key-name">
-		<!-- return the name of the primary key of the entity with this name -->
-		<xsl:param name="entity"/>
-		<xsl:if test="not($entity/adl:key)">
-			<xsl:message terminate="yes">
-				ADL: ERROR: No key for entity: <xsl:value-of select="$entity/@name"/>
-			</xsl:message>
-		</xsl:if>
-		<xsl:choose>
-			<xsl:when test="$entity/adl:key/adl:property[position()=2]">
-				<xsl:message terminate="no">
-					ADL: WARNING: Entity <xsl:value-of select="$entity/@name"/> has a composite primary key.
-					You will need to manually edit <xsl:value-of select="concat( $entity/@name, 'Controller.auto.cs')"/>
-				</xsl:message>
-				<xsl:value-of select="$entity/adl:key/adl:property[position()=1]/@name"/>
-			</xsl:when>
-			<xsl:when test="$entity/adl:key/adl:property">
-				<xsl:value-of select="$entity/adl:key/adl:property[position()=1]/@name"/>
-			</xsl:when>
-			<xsl:otherwise>
-				<xsl:message terminate="no">
-					ADL: WARNING: Entity <xsl:value-of select="$entity/@name"/> has no primary key.
-					You will need to manually edit <xsl:value-of select="concat( $entity/@name, 'Controller.auto.cs')"/>
-				</xsl:message>
-			</xsl:otherwise>
-		</xsl:choose>
-	</xsl:template>
-
-	<!-- it's often convenient to wrap an expression in an Add() -->
-	<xsl:template name="add-hibernate-expression-eq">
-		<xsl:param name="property"/>
-		<xsl:param name="value"/>
-		<xsl:variable name="basetype">
-			<xsl:call-template name="base-type">
-				<xsl:with-param name="property" select="$property"/>
-			</xsl:call-template>
-		</xsl:variable>
-		.Add(<xsl:call-template name="hibernate-expression-eq">
-			<xsl:with-param name="property" select="$property"/>
-			<xsl:with-param name="value" select="$value"/>
-		</xsl:call-template>)
-	</xsl:template>
-
-	<!-- it's often convenient to wrap an expression in an Add() -->
-	<xsl:template name="add-hibernate-expression-like">
-		<xsl:param name="property"/>
-		<xsl:param name="value"/>
-		<xsl:variable name="basetype">
-			<xsl:call-template name="base-type">
-				<xsl:with-param name="property" select="$property"/>
-			</xsl:call-template>
-		</xsl:variable>
-		.Add(<xsl:call-template name="hibernate-expression-like">
-			<xsl:with-param name="property" select="$property"/>
-			<xsl:with-param name="value" select="$value"/>
-		</xsl:call-template>)
-	</xsl:template>
-
-	<!-- generate a hibernate equality expression based on this property,
-		comparing it to this value -->
-	<xsl:template name="hibernate-expression-eq">
-		<!-- an entity of type property -->
-		<xsl:param name="property"/>
-		<!-- an expression which, at run time, will evaluate to a string -->
-		<xsl:param name="value"/>
-		<xsl:variable name="basetype">
-			<xsl:call-template name="base-type">
-				<xsl:with-param name="property" select="$property"/>
-			</xsl:call-template>
-		</xsl:variable>
-		Expression.Eq("<xsl:value-of select="$property/@name"/>", <xsl:choose>
-			<xsl:when test="$basetype = 'string'">
-				<xsl:value-of select="$value"/>
-			</xsl:when>
-			<xsl:when test="$basetype = 'integer'">
-				Int32.Parse( <xsl:value-of select="$value"/>)
-			</xsl:when>
-			<xsl:when test="$basetype = 'money'">
-				Decimal.Parse( <xsl:value-of select="$value"/>)
-			</xsl:when>
-			<xsl:when test="$basetype = 'date'">
-				DateTime.Parse( <xsl:value-of select="$value"/>)
-			</xsl:when>
-			<xsl:when test="$basetype='entity'">
-				<xsl:call-template name="fetch-property-instance">
-					<xsl:with-param name="property" select="$property"/>
-					<xsl:with-param name="value" select="$value"/>
-				</xsl:call-template>
-			</xsl:when>
-			<xsl:otherwise>
-				<xsl:message terminate="yes">
-					ADL: Error: properties of type <xsl:value-of select="$basetype"/> cannot yet be used
-					in equality tests
-				</xsl:message>
-      </xsl:otherwise>
-		</xsl:choose>)
-	</xsl:template>
-
-	<!-- generate a hibernate like expression based on this property,
-		comparing it to this value -->
-	<xsl:template name="hibernate-expression-like">
-		<xsl:param name="property"/>
-		<xsl:param name="value"/>
-		<xsl:variable name="basetype">
-			<xsl:call-template name="base-type">
-				<xsl:with-param name="property" select="$property"/>
-			</xsl:call-template>
-		</xsl:variable>
-		<xsl:choose>
-			<xsl:when test="$basetype='string' or $basetype='text'">
-				Expression.Like( "<xsl:value-of select="$property/@name"/>", "%"+<xsl:value-of select="$value"/>+"%")
-			</xsl:when>
-			<xsl:when test="$basetype='real'">
-				/* match to four significant places */
-				Expression.Between( "<xsl:value-of select="$property/@name"/>", 
-					Double.Parse( <xsl:value-of select="$value"/>) * 1.0001, 
-					Double.Parse( <xsl:value-of select="$value"/>) * 0.9999)
-			</xsl:when>
-			<xsl:otherwise>
-				<xsl:call-template name="hibernate-expression-eq">
-					<xsl:with-param name="property" select="$property"/>
-					<xsl:with-param name="value" select="$value"/>
-				</xsl:call-template>
-			</xsl:otherwise>
-		</xsl:choose>
-	</xsl:template>
-
-	<!-- argument: a property 
-      returns 'true' if that property is of a type which makes it searchable,
-      else 'false'. See also how search fields are generated in adl2views.xsl -->
-	<xsl:template name="is-searchable">
-		<xsl:param name="property"/>
-		<xsl:variable name="base-type">
-			<xsl:call-template name="base-type">
-				<xsl:with-param name="property" select="$property"/>
-			</xsl:call-template>
-		</xsl:variable>
-		<xsl:choose>
-			<xsl:when test="$base-type='string'">true</xsl:when>
-			<xsl:when test="$base-type='integer'">true</xsl:when>
-			<xsl:when test="$base-type='real'">true</xsl:when>
-			<xsl:when test="$base-type='money'">true</xsl:when>
-			<xsl:when test="$base-type='text'">true</xsl:when>
-			<xsl:when test="$base-type='entity'">true</xsl:when>
-			<xsl:otherwise>false</xsl:otherwise>
-		</xsl:choose>
-
-	</xsl:template>
-
-	<xsl:template name="fetch-property-instance">
-		<!-- the property for which the instance is sought; it is assumed that
-			the property passed has type 'entity' -->
-		<xsl:param name="property"/>
-		<!-- the name of the value in the returned values from which the instance
-			must be resolved -->
-		<xsl:param name="value"/>
-		<xsl:variable name="basetype">
-			<xsl:call-template name="base-type">
-				<xsl:with-param name="property" select="$property"/>
-			</xsl:call-template>
-		</xsl:variable>
-		<xsl:if test="not( $basetype='entity')">
-			<xsl:message terminate="yes">
-				ADL: ERROR: property passed to fetch-property-instance whose type is not 'entity'
-			</xsl:message>
-		</xsl:if>
-		hibernator.CreateCriteria(typeof(<xsl:value-of select="concat( $entityns, '.', $property/@entity)"/>))
-		<xsl:for-each select="//adl:entity[@name=$property/@entity]/adl:key/adl:property">
-			<xsl:call-template name="add-hibernate-expression-eq">
-				<xsl:with-param name="property" select="."/>
-				<xsl:with-param name="value" select="$value"/>
-			</xsl:call-template>
-		</xsl:for-each>
-		.UniqueResult&lt;<xsl:value-of select="concat( $entityns, '.', $property/@entity)"/>&gt;()
-	</xsl:template>
-
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+    Application Description Language framework
+    adl2controllerclasses.xsl
+    
+    (c) 2007 Cygnet Solutions Ltd
+    
+    Transform ADL into (partial) controller classes
+    
+    $Author: simon $
+    $Revision: 1.46 $
+    $Date: 2010-07-20 19:53:40 $
+  -->
+
+<!-- WARNING WARNING WARNING: Do NOT reformat this file! 
+     Whitespace (or lack of it) is significant! -->
+<xsl:stylesheet version="1.0"
+  xmlns="http://libs.cygnets.co.uk/adl/1.4/"
+  xmlns:adl="http://libs.cygnets.co.uk/adl/1.4/"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:exsl="urn:schemas-microsoft-com:xslt"
+  extension-element-prefixes="exsl">
+
+	<xsl:include href="csharp-type-include.xslt"/>
+	<xsl:include href="permissions-include.xslt"/>
+
+	<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"/>
+
+	<!-- bug 1896 : boilerplate text in views should be tailored to the locale of
+		the expected user. Unfortunately I haven't yet worked out how to do
+		conditional includes in XSLT, so this is a step on the way to a solution,
+		not a solution in itself. -->
+	<xsl:include href="i18n-en-GB-include.xslt"/>
+
+	<!-- 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"/>
+	<!-- Whether to authenticate at application or at database layer. 
+    If not 'Application', then 'Database'. -->
+	<xsl:param name="authentication-layer" select="'Application'"/>
+
+	<!-- the name and version of the product being built -->
+	<xsl:param name="product-version" select="'Application Description Language Framework'"/>
+
+	<!-- bug 1800 : the name of the Velocity layout to use -->
+	<xsl:param name="layout-name" select="adl-default-layout"/>
+	<!-- bug 1800 : the name of the Velocity rescue view to use -->
+	<xsl:param name="rescue-name"/>
+	<!-- bug 1800 : the name of the area (i.e. URL path part) to use -->
+	<xsl:param name="area-name"/>
+  <!-- bug 2883 : number of entries to show per list page (does not affect auxiliary lists) -->
+  <xsl:param name="records-per-page" select="15"/>
+
+	<xsl:template match="adl:application">
+		/* ---- [ cut here: next file '<xsl:value-of select="concat( 'Abstract', /adl:application/@name, 'Controller')"/>.auto.cs'] ---------------- */
+		//------------------------------------------------------------------
+		//
+		//  <xsl:value-of select="$product-version"/>
+		//  <xsl:value-of select="concat( 'Abstract', /adl:application/@name, 'Controller.auto.cs')"/>
+		//
+		// (c) 2007 Cygnet Solutions Ltd
+		//
+		//  Automatically generated abstract super class for controllers for the
+		//	<xsl:value-of select="/adl:application/@name"/> application; generated using
+		//  adl2controllerclasses.xslt version <xsl:value-of select="substring( '$Revision: 1.46 $', 10)"/>
+		//
+		//  <xsl:value-of select="/adl:application/@revision"/>
+		//
+		//  This file is automatically generated; DO NOT EDIT IT.
+		//
+		//------------------------------------------------------------------
+
+		/// &lt;summary&gt;
+		/// \mainpage <xsl:value-of select="concat( @name, ' ', @version)"/>
+		/// <xsl:value-of select="normalize-space(adl:documentation)"/>
+		///
+		/// \package <xsl:value-of select="$controllerns"/>
+		/// MVC Controller classes for <xsl:value-of select='/adl:application/@name'/>
+		/// &lt;/summary&gt;
+		namespace <xsl:value-of select="$controllerns"/> {
+		using System;
+		using System.Data;
+		using System.Collections.Generic;
+		using System.Data.SqlClient;
+		using NHibernate;
+		using NHibernate.Expression;
+		using Cygnet.DBAuth;
+		using Cygnet.Web.Controllers;
+		using Cygnet.Web.Helpers;
+		using Castle.MonoRail.Framework;
+		using <xsl:value-of select="$entityns"/>;
+
+		/// &lt;summary&gt;
+		/// Automatically generated abstract super class for controllers for the
+		/// <xsl:value-of select="/adl:application/@name"/> application
+		///
+		/// DO NOT EDIT THIS FILE!
+		/// &lt;/summary&gt;
+		[ <!-- in the longer term, all the helpers which a given 
+		project needs which not every project needs should be listed here, 
+		with appropriate 'xsl:if' wrappers. -->
+		Helper(typeof(FormatterHelper), "t"), 
+		Helper(typeof(SecurityHelper), "SecurityHelper")
+		]
+		public abstract partial class <xsl:value-of select="concat( 'Abstract', /adl:application/@name, 'Controller')"/> : BaseController {
+
+		<xsl:choose>
+			<xsl:when test="$authentication-layer = 'Application'"/>
+			<xsl:when test="$authentication-layer = 'Database'">
+				/* authentication layer is requested to be 'database', but in fact database-layer 
+				authentication does not work well with NHibernate so this is being ignored. */
+			</xsl:when>
+			<xsl:otherwise>
+				<xsl:message terminate="yes">
+					ADL: ERROR: invalid value (<xsl:value-of select="$authentication-layer"/>) provided for authentication-layer
+				</xsl:message>
+			</xsl:otherwise>
+		</xsl:choose>
+		
+		<xsl:for-each select="//adl:entity">
+			/// &lt;summary&gt;
+			/// Return a list of all instances of <xsl:value-of select="@name"/> for use in menus, etc;
+			/// &lt;/summary&gt;
+			protected IList&lt;<xsl:value-of select="concat( $entityns, '.', @name)"/>&gt; <xsl:value-of select="concat( 'FetchAll', @name)"/>( ) {
+			IList&lt;<xsl:value-of select="concat( $entityns, '.', @name)"/>&gt; result = new List&lt;<xsl:value-of select="concat( $entityns, '.', @name)"/>&gt;();
+
+			<xsl:variable name="readgroups">
+				<xsl:call-template name="entity-read-groups">
+					<xsl:with-param name="entity" select="."/>
+				</xsl:call-template>
+			</xsl:variable>
+			<xsl:if test="$authentication-layer = 'Database'">
+				if (
+				<xsl:for-each select="exsl:node-set( $readgroups)/*">
+					InGroup( "<xsl:value-of select="./@name"/>")<xsl:if test="position() != last()">||</xsl:if>
+				</xsl:for-each>
+				){
+			</xsl:if>
+			result = GetDBSession().CreateCriteria(typeof(<xsl:value-of select="concat( $entityns, '.', @name)"/>))
+			<xsl:for-each select="descendant::adl:property[@distinct='user']">
+				.AddOrder( <xsl:value-of select="concat('new Order( &#34;', @name, '&#34;, true)')"/>)
+			</xsl:for-each>
+			.SetCacheable( true)
+			.SetCacheRegion( "<xsl:value-of select="/adl:application/@name"/>")
+			.List&lt;<xsl:value-of select="concat( $entityns, '.', @name)"/>&gt;();
+			<xsl:if test="$authentication-layer != 'Application'">
+				}
+			</xsl:if>
+			return result;
+			}
+
+		</xsl:for-each>
+		}
+		}
+		<xsl:apply-templates select="adl:entity"/>
+	</xsl:template>
+
+
+	<!-- Don't bother generating anything for foreign entities -->
+	<xsl:template match="adl:entity[@foreign='true']"/>
+
+	<xsl:template match="adl:entity">
+		/*
+		 *	Not generating controller for entity <xsl:value-of select="@name"/>,
+		 *	as it has no forms, pages or lists.
+		 */
+	</xsl:template>
+	<xsl:template match="adl:entity[adl:form|adl:page|adl:list]">
+
+		/* ---- [ cut here: next file '<xsl:value-of select="@name"/>Controller.auto.cs'] ---------------- */
+
+		//------------------------------------------------------------------
+		//
+		//  <xsl:value-of select="$product-version"/>
+		//  <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
+		//  adl2controllerclasses.xslt version <xsl:value-of select="substring( '$Revision: 1.46 $', 10)"/>
+		//
+		//  This file is automatically generated; DO NOT EDIT IT.
+		//
+		//------------------------------------------------------------------
+
+		namespace <xsl:value-of select="$controllerns"/> {
+		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.Entities;
+		using Cygnet.Exceptions;
+		using Cygnet.Web.Helpers;
+		using Cygnet.Web.Controllers;
+		using Cygnet.Web.SmartControls;
+		using Cygnet.Utility;
+		using NHibernate;
+		using NHibernate.Expression;
+		using Castle.MonoRail.Framework;
+		using Iesi.Collections.Generic;
+		using <xsl:value-of select="$entityns"/>;
+
+		/// &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.
+		/// &lt;/summary&gt;
+		///
+		/// &lt;remarks&gt;
+		/// &lt;list type='bullet'&gt;
+		/// &lt;listheader&gt;&lt;description&gt;See also auto-generated Velocity view macros&lt;/description&gt;&lt;/listheader&gt;<xsl:for-each select='adl:form|adl:page|adl:list'>
+		/// &lt;item&gt;
+		/// &lt;term&gt;<xsl:value-of select="concat(@name, '.auto.vm')"/>&lt;/term&gt;
+		/// &lt;description&gt;<xsl:apply-templates select='adl:documentation'/>&lt;/description&gt;
+		/// &lt;/item&gt;</xsl:for-each>
+		/// &lt;/list&gt;
+		///
+		/// DO NOT EDIT THIS FILE!
+		/// &lt;/remarks&gt;
+		[
+		<xsl:if test="$layout-name">
+			Layout("<xsl:value-of select="$layout-name"/>"),
+		</xsl:if>
+		<xsl:if test="$rescue-name">
+			Rescue("<xsl:value-of select="$rescue-name"/>"),
+		</xsl:if>
+		ControllerDetails("<xsl:value-of select="@name"/>",	Area = "<xsl:value-of select="$area-name"/>"),
+		Helper(typeof(StylesHelper), "StylesHelper"),
+		Helper(typeof(<xsl:value-of select="concat( @name, 'FieldHelper')"/>), "<xsl:value-of select="concat( @name, 'FieldHelper')"/>")
+		]
+		public partial class <xsl:value-of select="concat( @name, 'Controller')"/> : <xsl:value-of select="concat( 'Abstract', /adl:application/@name, 'Controller')"/> {
+
+		protected class <xsl:value-of select="concat( @name, 'FieldHelper')"/> : SmartFormHelper {
+		public <xsl:value-of select="concat( @name, 'FieldHelper')"/>() {
+		<xsl:for-each select="descendant::adl:property[@type='entity']">
+			<xsl:variable name="entityname" select="@entity"/>
+			<xsl:variable name="entity" select="//adl:entity[@name=$entityname]"/>
+			<xsl:choose>
+				<xsl:when test="$entity/@foreign='true'">
+					/* Entity <xsl:value-of select="$entityname"/> is foreign..? */
+					<xsl:variable name="foreignkey" select="$entity/adl:key/adl:property[position()=1]/@name"/>
+					<xsl:variable name="userident">
+						<xsl:choose>
+							<xsl:when test="$entity//adl:property[@distinct='user' or @distinct='all']">
+								<xsl:value-of select="$entity//adl:property[@distinct='user' or @distinct='all'][position()=1]/@name"/>
+							</xsl:when>
+							<xsl:otherwise>
+								<xsl:value-of select="$foreignkey"/>
+							</xsl:otherwise>
+						</xsl:choose>
+					</xsl:variable>
+					Register&lt;<xsl:value-of select="concat( $entityns, '.', $entityname)"/>&gt;( "",
+					new TypeMenuControl&lt;<xsl:value-of select="concat( $entityns, '.', $entityname)"/>&gt;( "<xsl:value-of select="$foreignkey"/>","<xsl:value-of select="$userident"/>")); 
+				</xsl:when>
+				<xsl:otherwise>
+					Register&lt;<xsl:value-of select="concat( $entityns, '.', $entityname)"/>&gt;( "", EntityMenuControl&lt;<xsl:value-of select="concat( $entityns, '.', $entityname)"/>&gt;.Instance);
+				</xsl:otherwise>
+			</xsl:choose>
+		</xsl:for-each>
+		<xsl:for-each select="descendant::adl:property[@type='list']">
+			<xsl:variable name="entityname" select="@entity"/>
+			Register&lt;<xsl:value-of select="concat( $entityns, '.', $entityname)"/>&gt;( "", EntityShuffleControl&lt;<xsl:value-of select="concat( $entityns, '.', $entityname)"/>&gt;.Instance);
+		</xsl:for-each>
+
+		}
+		}
+
+		<xsl:if test="adl:property[@type='message']">
+			/// &lt;summary&gt;
+			/// Temporary hack to sort a problem with uninitialised messages
+			/// &lt;/summary&gt;
+			public void fixupMessages() {
+			ISession hibernator = GetDBSession();
+			ICollection&lt;<xsl:value-of select="concat($entityns, '.', @name)"/>&gt; instances =
+			hibernator.CreateCriteria( typeof( <xsl:value-of select="concat($entityns, '.', @name)"/>))
+			.List&lt;<xsl:value-of select="concat($entityns, '.', @name)"/>&gt;();
+
+			foreach ( <xsl:value-of select="concat($entityns, '.', @name)"/> instance in instances) {
+			<xsl:for-each select="adl:property[@type='message']">
+        <xsl:variable name="slot" select="concat( 'instance.', @name)"/>
+				if ( <xsl:value-of select="$slot"/> == null || <xsl:value-of select="concat( $slot, '.MessageId')"/> == 0 ){
+				<xsl:value-of select="$slot"/> = new Message();
+        
+        <xsl:value-of select="$slot"/>.BeforeUpdateHook( hibernator);
+				hibernator.SaveOrUpdate( <xsl:value-of select="$slot"/>);
+        <xsl:value-of select="$slot"/>.AfterUpdateHook( hibernator);
+        }
+      </xsl:for-each>
+      instance.BeforeUpdateHook( hibernator);
+			hibernator.SaveOrUpdate( instance);
+      instance.AfterUpdateHook( hibernator);
+			}
+			hibernator.Flush();
+			<xsl:if test="adl:list[@name='list']">
+				list();
+			</xsl:if>
+			}
+		</xsl:if>
+
+		<xsl:if test="adl:form">
+			<!-- unless there's at least one form, we won't generate a 'store' method -->
+			/// &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 = GetDBSession();
+			List&lt;string&gt; messages = new List&lt;string&gt;();
+      PropertyBag["messages"] = messages;
+			/* A 'newborn' instance can be updated even if the current user doesn't have
+			* update permissions, seeing that we use an update operation to set the
+			* field values and save the entity. */
+			Boolean isnewborn = false;
+
+			/* the instance (record) of type <xsl:value-of select="@name"/> we're dealing with */
+			<xsl:value-of select="concat($entityns, '.', @name)"/> record = null;
+
+			try {
+			<xsl:if test="adl:property[@distinct='system' or @distinct='all']">
+				/* a criteria object to use in distinctness checks */
+				ICriteria matchCriteria = null;
+			</xsl:if>
+
+			record = FetchRecord( hibernator);
+
+			<xsl:apply-templates select="adl:property" mode="presenceAndValidity"/>
+
+			if ( HasNoErrors()) {
+			if ( record == null) {
+			/* it seems to be new, create persistent object - if the user is permitted to */
+			AssertUserCanCreate();
+
+			try {
+			if ( AllKeys()) {
+			record = new <xsl:value-of select="concat($entityns, '.', @name)"/>(<xsl:for-each select="adl:key/adl:property">
+				<xsl:variable name="basetype">
+					<xsl:call-template name="base-type">
+						<xsl:with-param name="property" select="."/>
+					</xsl:call-template>
+				</xsl:variable>
+				<xsl:choose>
+					<xsl:when test="$basetype='integer'">
+						Int32.Parse( Form["<xsl:value-of select="concat( 'instance.', @name)"/>"])
+					</xsl:when>
+					<xsl:when test="$basetype='entity'">
+						<!-- Maybe TODO: this doesn't work recursively - if an entity has a key which is an entity 
+                  and the key of that entity is an entity, you're on your own, mate! -->
+						<xsl:variable name="keyentity" select="@entity"/>
+						<xsl:variable name="keyenttype">
+							<xsl:call-template name="primary-key-csharp-type">
+								<xsl:with-param name="entity" select="//adl:entity[@name=$keyentity]"/>
+							</xsl:call-template>
+						</xsl:variable>
+						hibernator.CreateCriteria( typeof( <xsl:value-of select="concat( $entityns, '.', $keyentity)"/>))
+						<xsl:call-template name="add-hibernate-expression-eq">
+							<xsl:with-param name="property" select="//adl:entity[@name=$keyentity]/adl:key/adl:property[position()=1]"/>
+							<xsl:with-param name="value">
+								Form[ "<xsl:value-of select="concat( 'instance.', @name)"/>"]
+							</xsl:with-param>
+						</xsl:call-template>
+						.UniqueResult&lt;<xsl:value-of select="concat( $entityns, '.', $keyentity)"/>&gt;()
+					</xsl:when>
+					<xsl:otherwise>
+						Form["<xsl:value-of select="concat( 'instance.', @name)"/>"]
+					</xsl:otherwise>
+				</xsl:choose>
+				<xsl:choose>
+					<xsl:when test="position() = last()"/>
+					<xsl:otherwise>, </xsl:otherwise>
+				</xsl:choose>
+			</xsl:for-each>);
+			}
+			else
+			{
+			record = new <xsl:value-of select="concat($entityns, '.', @name)"/>();
+			}
+			}
+			catch ( FormatException) {
+			/* failed to parse a number - not wholly unexpected, since it's most likely
+			* that an empty string was passed in */
+			record = new <xsl:value-of select="concat($entityns, '.', @name)"/>();
+			}
+			catch ( NullReferenceException) {
+			/* again, probably more normal than otherwise */
+			record = new <xsl:value-of select="concat($entityns, '.', @name)"/>();
+			}
+			messages.Add( "New <xsl:value-of select="@name"/> record created");
+      isnewborn = true;
+      }
+
+      if ( record != null) {
+      /* a transaction to ensure our database operations are atomic */
+      ITransaction tx = null;
+
+
+      if ( ! isnewborn) {
+      /* isnewborn cannot be true unless we've already checked user can create
+      * so no need to do it again here */
+      AssertUserCanUpdate();
+      }
+
+      try {
+      /* begin our atomic transaction */
+      tx = hibernator.BeginTransaction();
+      /* list of entities modified in this transaction */
+      List&lt;Entity&gt;  modified = new List&lt;Entity&gt;();
+
+          /* actually update the record */
+          BindObjectInstance( record, ParamStore.Form, "instance");
+          modified.Add( record);
+
+          <xsl:if test="descendant::adl:property[@type='message']">
+				/* there is at least one slot whose value is an internationalised message;
+				* if these have yet to be initialised they must be handled specially */
+				Locale locale = GetBestLocaleForUser();
+				<xsl:for-each select="descendant::adl:property[@type='message']">
+					if ( ! String.IsNullOrEmpty( Form["<xsl:value-of select="concat( 'instance.', @name)"/>"])){
+					/* there's an uninitialised message for this slot */
+					Message mess = record.<xsl:value-of select="@name"/>;
+					if ( mess == null) {
+					mess = new Message();
+					}
+          mess.BeforeUpdateHook( hibernator);
+					hibernator.SaveOrUpdate( mess);
+          mess.AfterUpdateHook( hibernator);
+
+					Translation trans = mess.GetTranslationObject( locale, hibernator);
+					if ( trans == null) {
+					trans = new Translation( mess, locale);
+					}
+					trans.MessageText = Form["<xsl:value-of select="concat( 'instance.', @name)"/>"];
+					record.<xsl:value-of select="@name"/> = mess;
+          trans.BeforeUpdateHook( hibernator);
+          hibernator.SaveOrUpdate( trans);
+          trans.AfterUpdateHook( hibernator);
+          }
+        </xsl:for-each>
+			</xsl:if>
+
+      <!-- special binding for types which don't bind straightforwardly in BindObjectInstance-->
+      <xsl:apply-templates select="descendant::adl:property" mode="bind"/>
+
+      /* write the modified records to the database */
+      foreach ( Entity item in modified) {
+      item.BeforeUpdateHook( hibernator);
+      hibernator.SaveOrUpdate(item);
+      item.AfterUpdateHook( hibernator);
+      }
+      /* and if no exceptions, commit */
+      tx.Commit();
+
+      messages.Add( "<xsl:call-template name="i18n-record-saved"/>");
+			} /* try actually commit */
+			catch ( Exception any) {
+			messages.Add( "<xsl:call-template name="i18n-record-not-saved"/>");
+			AddError( any);
+			try {
+			tx.Rollback();
+			} catch ( ObjectDisposedException ode) {
+			AddError( ode);
+			}
+			} /* catch ( Exception any) */
+			} /* if ( record != null) */
+			else {
+			throw new ApplicationException( String.Format( "<xsl:call-template name="i18n-record-not-found">
+				<xsl:with-param name="entity-name" select="@name"/>
+			</xsl:call-template>"));
+			}
+			} /* if ( HasNoErrors()) */
+			} /* try */
+			catch ( DataSuitabilityException dse)
+			{
+			AddError( dse);
+			}
+			catch ( ApplicationException axe)
+			{
+			AddError( axe.Message);
+			}
+
+			if ( ! HasNoErrors())
+			{
+			/* the session may be polluted; create a new session */
+			CloseDBSession();
+			hibernator = GetDBSession();
+
+			record = FetchRecord( hibernator);
+			} /* if ( ! HasNoErrors()) */
+			<xsl:value-of select="concat( 'this.',adl:form[position()=1]/@name)"/>( record);
+			}
+
+      <!-- unless there's at least one form, we won't generate a 'delete' method -->
+			/// &lt;summary&gt;
+			/// Actually delete the selected record
+			/// &lt;/summary&gt;
+      [AccessibleThrough(Verb.Post)]
+      public void Delete()
+      {
+      AssertUserCanDelete();
+      ISession hibernator = GetDBSession();
+      <xsl:value-of select="concat($entityns, '.', @name)"/> record = null;
+
+      if ( "true".Equals( Params["reallydelete"]))
+      {
+      record = FetchRecord( hibernator);
+
+      if ( record != null)
+      {
+      try {
+      record.BeforeDeleteHook( hibernator);
+      hibernator.Delete( record);
+      hibernator.Flush();
+      } catch ( DomainKnowledgeViolationException dkve) {
+      AddError( dkve);
+      }
+      }
+      else
+      {
+      throw new ApplicationException( "No such record?");
+      }
+      }
+      if ( HasNoErrors()) {
+      <xsl:choose>
+				<xsl:when test="adl:list">
+					Redirect( "<xsl:value-of select="concat(adl:list[position()=1]/@name, '.rails')"/>");
+				</xsl:when>
+				<xsl:otherwise>
+					Redirect( FormsAuthentication.DefaultUrl);
+				</xsl:otherwise>
+			</xsl:choose>
+      } else {
+      PropertyBag[ "instance"] = record;
+      RenderViewWithFailover( "maybedelete.vm", "maybedelete.auto.vm");
+      }
+      }
+    </xsl:if>
+		<xsl:apply-templates select="adl:form"/>
+    <xsl:apply-templates select="adl:list"/>
+
+    /// &lt;summary&gt;
+		/// Check whether values for all my keys are available in the form fields
+		/// &lt;/summary&gt;
+		protected bool AllKeys() {
+		/* whether we have valid values for all the key fields */
+		bool result = true;
+
+		<xsl:for-each select="adl:key/adl:property">
+			if ( String.IsNullOrEmpty( Form["<xsl:value-of select="concat( 'instance.', @name)"/>"])) {
+			result = false;
+			} else if ( "<xsl:value-of select="concat('$instance.', @name)"/>".Equals( Form["<xsl:value-of select="concat( 'instance.', @name)"/>"])) {
+			/* nasty artefact of NVelocity forms - default 'null value' is dollar followed by fieldname */
+			result = false;
+			}
+		</xsl:for-each>
+
+		return result;
+		}
+
+		/// &lt;summary&gt;
+		/// Fetch the record represented by the values in the current Form
+		/// &lt;/summary&gt;
+		protected <xsl:value-of select="concat($entityns, '.', @name)"/> FetchRecord(ISession hibernator) {
+		/* the instance (record) of type <xsl:value-of select="@name"/> we're dealing with */
+		<xsl:value-of select="concat($entityns, '.', @name)"/> record = null;
+
+		if ( AllKeys()){
+		/* it's (probably) existing, retrieve it */
+		record = hibernator.CreateCriteria(typeof(<xsl:value-of select="concat( $entityns, '.', @name)"/>))
+		<xsl:for-each select="adl:key/adl:property">
+			<xsl:call-template name="add-hibernate-expression-eq">
+				<xsl:with-param name="property" select="."/>
+				<xsl:with-param name="value">Form["<xsl:value-of select="concat( 'instance.', @name)"/>"]</xsl:with-param>
+			</xsl:call-template>
+		</xsl:for-each>
+		.UniqueResult&lt;<xsl:value-of select="concat( $entityns, '.', @name)"/>&gt;();
+		}
+
+		return record;
+		}
+		}
+		}
+		/* ---- [ cut here: next file 'junk'] ------------------------- */
+	</xsl:template>
+
+	<xsl:template match="adl:property" mode="presenceAndValidity">
+		<xsl:if test="@required='true'">
+			if ( 
+			<xsl:if test="@immutable='true'">
+				(record == null || <xsl:value-of select="concat( 'record.', @name)"/> == null) &amp;&amp;
+			</xsl:if>
+			String.IsNullOrEmpty( Form[ "<xsl:value-of select="concat( 'instance.', @name)"/>" ]))
+			{
+			AddError( <xsl:choose>
+				<xsl:when test="adl:ifmissing[@locale=$locale]">
+					<xsl:apply-templates select="adl:ifmissing[@locale=$locale]"/>
+				</xsl:when>
+				<xsl:otherwise>
+					"<xsl:call-template name="i18n-value-required">
+						<xsl:with-param name="property-name" select="@name"/>
+					</xsl:call-template>"
+				</xsl:otherwise>
+			</xsl:choose>);
+			} 
+		</xsl:if>
+		<xsl:if test="@distinct='system' or @distinct='all'">
+			<xsl:call-template name="check-property-value-distinct">
+				<xsl:with-param name="property" select="."/>
+			</xsl:call-template>
+		</xsl:if>
+	</xsl:template>
+
+  <!-- upload and bind an image file to the instance -->
+  <xsl:template match="adl:property[@type='image']" mode="bind">
+    record.<xsl:value-of select="@name"/> = 
+    this.MaybeUploadImage("<xsl:value-of select="concat( 'instance.', @name)"/>");
+  </xsl:template>
+
+  <!-- upload and bind a file to the instance -->
+  <xsl:template match="adl:property[@type='uploadable']" mode="bind">
+    record.<xsl:value-of select="@name"/> =
+    this.MaybeUploadFile("<xsl:value-of select="concat( 'instance.', @name)"/>");
+  </xsl:template>
+
+  <!-- locate and bind the specified instance of this entity -->
+  <xsl:template match="adl:property[@type='entity']" mode="bind">
+    /* 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. */
+    <xsl:variable name="entityname" select="@entity"/>
+    <xsl:choose>
+      <xsl:when test="//adl:entity[@name=$entityname]">
+        if ( ! String.IsNullOrEmpty( Form["<xsl:value-of select="concat( 'instance.', @name)"/>"]) &amp;&amp;
+        ! EntityMenuControl&lt;<xsl:value-of select="concat( $entityns, '.', @entity)"/>&gt;.NULLMARKER.Equals ( Form["<xsl:value-of select="concat( 'instance.', @name)"/>"]))
+        {
+        record.<xsl:value-of select="@name"/> = <xsl:call-template name="fetch-property-instance">
+          <xsl:with-param name="property" select="."/>
+          <xsl:with-param name="value">
+            Form[ "<xsl:value-of select="concat( 'instance.', @name)"/>"]
+          </xsl:with-param>
+        </xsl:call-template>;
+
+        modified.Add( record.<xsl:value-of select="@name"/>);
+        }
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:message terminate="yes">
+          ADL: ERROR: Could not fix up value of <xsl:value-of select="@name "/>, because no
+          entity was found called <xsl:value-of select="$entityname"/>
+        </xsl:message>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <!-- locate and bind the specified linked instances -->
+  <xsl:template match="adl:property[@type='link']" mode="bind">
+    <xsl:variable name="nearentityname" select="ancestor::adl:entity/@name"/>
+    <xsl:variable name="farentityname" select="@entity"/>
+    <xsl:variable name="entity" select="//adl:entity[@name=$farentityname]"/>
+    <xsl:variable name="farkey" select="$entity/adl:key/adl:property[position()=1]/@name"/>
+    <xsl:variable name="farkeybasetype">
+      <xsl:call-template name="base-type">
+        <xsl:with-param name="property" select="//adl:entity[@name=$farentityname]/adl:key/adl:property[position()=1]"/>
+      </xsl:call-template>
+    </xsl:variable>
+    <xsl:variable name="deletegroups">
+      <xsl:call-template name="entity-delete-groups">
+        <xsl:with-param name="entity" select="$entity"/>
+      </xsl:call-template>
+    </xsl:variable>
+    /* For a link, collect changes to link table and process them */
+    <xsl:if test="$authentication-layer = 'Database'">
+      if ( <xsl:for-each select="exsl:node-set( $deletegroups)/*">
+        InGroup( "<xsl:value-of select="./@name"/>") ||
+      </xsl:for-each> false) {
+      /* however, we cannot do anything unless we have delete permissions on the table, so
+      * should not try. */
+    </xsl:if>
+    LinkChanges&lt;<xsl:value-of select="concat( $entityns, '.', @entity)"/>&gt; changes =
+    LinkTableUpdater&lt;<xsl:value-of select="concat( $entityns, '.', @entity)"/>&gt;.Changes( <xsl:value-of select="concat( 'record.', @name)"/>, Form.GetValues( "<xsl:value-of select="concat( 'instance.', @name)"/>"),
+    hibernator);
+
+    foreach ( var item in changes.ToRemove) {
+    modified.Add(item);
+    <xsl:value-of select="concat( 'record.', @name)"/>.Remove(item);
+    <xsl:for-each select="$entity//adl:property[@type='link' and @entity=$nearentityname]">
+      <xsl:value-of select="concat( 'item.', @name)"/>.Remove( record);
+      <xsl:if test="position() != 1">
+        /* WARNING WARNING WARNING! Could not uniquely determine the far side property;
+        * redesign your application or manually maintain this code! */
+        <xsl:message terminate="no">
+          WARNING: Could not uniquely determine far end of link represented by property <xsl:value-of select="@name"/> of <xsl:value-of select="$nearentityname"/>
+        </xsl:message>
+      </xsl:if>
+    </xsl:for-each>
+    }
+    foreach ( var item in changes.ToAdd) {
+    modified.Add(item);
+    <xsl:value-of select="concat( 'record.', @name)"/>.Add(item);
+    <xsl:for-each select="$entity//adl:property[@type='link' and @entity=$nearentityname]">
+      <xsl:value-of select="concat( 'item.', @name)"/>.Add( record);
+      <xsl:if test="position() != 1">
+        /* WARNING WARNING WARNING! Could not uniquely determine the far side property;
+        * redesign your application or manually maintain this code! */
+        <xsl:message terminate="no">
+          WARNING: Could not uniquely determine far end of link represented by property <xsl:value-of select="@name"/> of <xsl:value-of select="$nearentityname"/>
+        </xsl:message>
+      </xsl:if>
+    </xsl:for-each>
+    }
+
+    <xsl:if test="$authentication-layer = 'Database'">
+      } /* if ( <xsl:for-each select="exsl:node-set( $deletegroups)/*"> InGroup( "<xsl:value-of select="./@name"/>") ||</xsl:for-each> false) */
+    </xsl:if>
+  </xsl:template>
+  
+  <!-- locate and bind the specified child instances -->
+  <xsl:template match="adl:property[@type='list']" mode="bind">
+    <xsl:variable name="farentityname" select="@entity"/>
+    <xsl:variable name="entity" select="//adl:entity[@name=$farentityname]"/>
+    <xsl:variable name="farkey" select="$entity/adl:key/adl:property[position()=1]/@name"/>
+    <xsl:variable name="farkeybasetype">
+      <xsl:call-template name="base-type">
+        <xsl:with-param name="property" select="//adl:entity[@name=$farentityname]/adl:key/adl:property[position()=1]"/>
+      </xsl:call-template>
+    </xsl:variable>
+    <xsl:variable name="foreignkey">
+      <xsl:choose>
+        <xsl:when test="@farkey">
+          <xsl:value-of select="@farkey"/>
+        </xsl:when>
+        <xsl:otherwise>
+          <!-- If I haven't been told what the far side foreign key is, assume it has the
+								name of my entity -->
+          <xsl:value-of select="ancestor::adl:entity/@name"/>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    <xsl:variable name="deletegroups">
+      <xsl:call-template name="entity-delete-groups">
+        <xsl:with-param name="entity" select="$entity"/>
+      </xsl:call-template>
+    </xsl:variable>
+    /* with a list we cannot just smash the old values! Instead we need to check
+    * each one and exclude it if no longer required; */
+    <xsl:if test="$authentication-layer = 'Database'">
+      if ( <xsl:for-each select="exsl:node-set( $deletegroups)/*">
+        InGroup( "<xsl:value-of select="./@name"/>") ||
+      </xsl:for-each> false) {
+      /* but once again only if we can delete and create entities at the far end. */
+    </xsl:if>
+    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.KeyString;
+    bool found = false;
+
+    foreach ( string index in <xsl:value-of select="concat(@name, 'Values')"/>)
+    {
+    if ( index.Equals( itemId))
+    {
+    found = true;
+    break;
+    }
+    } /* foreach ( string index... */
+
+    if ( ! found)
+    {
+    record.<xsl:value-of select="@name"/>.Remove( item);
+    modified.Add( item);
+    break;
+    }
+    } /* foreach ( <xsl:value-of select="@entity"/> 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="concat( $entityns, '.', @entity)"/> item =
+    hibernator.CreateCriteria(typeof(<xsl:value-of select="@entity"/>))
+    <xsl:call-template name="add-hibernate-expression-eq">
+      <xsl:with-param name="property" select="//adl:entity[@name=$farentityname]/adl:key/adl:property[position()=1]"/>
+      <xsl:with-param name="value" select="'index'"/>
+    </xsl:call-template>
+    .UniqueResult&lt;<xsl:value-of select="concat( $entityns, '.', @entity)"/>&gt;();
+
+    if ( ! record.<xsl:value-of select="@name"/>.Contains( item))
+    {
+    /* check whether it's already a child of another <xsl:value-of select="ancestor::adl:entity/@name"/>
+    * and, if it is, remove it */
+    <xsl:value-of select="concat( $entityns, '.', ancestor::adl:entity/@name)"/> oldparent =
+    <xsl:value-of select="concat( 'item.', $foreignkey)"/>;
+    if ( oldparent != null) {
+    oldparent.<xsl:value-of select="@name"/>.Remove( item);
+
+    modified.Add( oldparent);
+    }
+
+    /* then add it to my <xsl:value-of select="@name"/> */
+    record.<xsl:value-of select="@name"/>.Add( item);
+    <xsl:value-of select="concat( 'item.', $foreignkey)"/> = record;
+    modified.Add( item);
+    }
+    } /* foreach ( string index... */
+    } /* if ( Form.GetValues( "<xsl:value-of select="concat( 'instance.', @name)"/>") != null) */
+    <xsl:if test="$authentication-layer = 'Database'">
+      } /* if ( <xsl:for-each select="exsl:node-set( $deletegroups)/*">
+        InGroup( "<xsl:value-of select="./@name"/>") ||
+      </xsl:for-each> false) */
+    </xsl:if>
+  </xsl:template>
+  
+  <!-- other properties don't need any special binding -->
+  <xsl:template match="adl:property" mode="bind"/>
+  
+  <xsl:template match="adl:ifmissing">
+		"<xsl:value-of select="normalize-space(.)"/>"
+	</xsl:template>
+
+	<xsl:template match="adl:form">
+		/// &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( "<xsl:call-template name="i18n-command-not-found"/>");
+		}
+		else
+		<xsl:for-each select=".//adl: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 = GetDBSession();
+
+		<xsl:value-of select="concat($entityns, '.', ancestor::adl:entity/@name)"/> record = FetchRecord( hibernator);
+
+		TypedPropertyBag = new {
+		instance = record };
+
+		RenderViewWithFailover( "maybedelete.vm", "maybedelete.auto.vm");
+		}
+		else if ( command.Equals( "store"))
+		{
+		Store();
+		}
+		else
+		{
+		throw new Exception( String.Format("<xsl:call-template name="i18n-command-not-found">
+			<xsl:with-param name="command" select="'{0}'"/>
+		</xsl:call-template>", command));
+		}
+		}
+
+		/// &lt;summary&gt;
+		/// Show the form named <xsl:value-of select="@name"/>, with no existing record
+		/// &lt;/summary&gt;
+		[AccessibleThrough(Verb.Get)]
+		public void <xsl:value-of select="@name"/>( )
+		{
+		AssertUserCanRead();
+		<xsl:value-of select="concat( 'PrototypeFor', ancestor::adl:entity/@name)"/> record = 
+      new <xsl:value-of select="concat( 'PrototypeFor', ancestor::adl:entity/@name)"/>();
+
+    ISession hibernator = GetDBSession();
+
+    TypedPropertyBag = new {
+    <xsl:call-template name="formmenus">
+      <xsl:with-param name="form" select="."/>
+    </xsl:call-template>
+    instance = record };
+
+    RenderViewWithFailover("<xsl:value-of select="concat( @name, '.vm')"/>", "<xsl:value-of select="concat( @name, '.auto.vm')"/>");
+    }
+
+    <xsl:variable name="form" select="."/>
+		<xsl:for-each select="ancestor::adl:entity/adl:property[ @type='entity']">
+		/// &lt;summary&gt;
+		/// Show the form named <xsl:value-of select="$form/@name"/>, for a new record, but with the
+		/// value for <xsl:value-of select="@name"/> already predetermined
+		/// &lt;/summary&gt;
+			[AccessibleThrough(Verb.Get)]
+			public void <xsl:value-of select="concat($form/@name, 'With', @name)"/>( string <xsl:value-of select="@name"/>)
+			{
+			AssertUserCanRead();
+			ISession hibernator = GetDBSession();
+			<xsl:value-of select="ancestor::adl:entity/@name"/> record = new <xsl:value-of select="concat( $entityns, '.', ancestor::adl:entity/@name)"/>();
+
+			record.<xsl:value-of select="@name"/> = <xsl:call-template name="fetch-property-instance">
+				<xsl:with-param name="property" select="."/>
+				<xsl:with-param name="value" select="@name"/>
+			</xsl:call-template>;
+			
+			<xsl:value-of select="concat( 'this.', $form/@name)"/>( record);
+			}
+		</xsl:for-each>
+
+		/// &lt;summary&gt;
+		/// Show the form named <xsl:value-of select="@name"/>, containing the indicated record. As
+		/// the primary key of the record is itself an entity, we need to first fetch that entity
+		/// &lt;/summary&gt;
+		<xsl:for-each select="ancestor::adl:entity/adl:key/adl:property">
+			<xsl:choose>
+				<xsl:when test="@type='entity'">
+					/// &lt;param name="<xsl:value-of select="@name"/>"&gt;the key value of the key value of the record to show&lt;/param&gt;
+				</xsl:when>
+				<xsl:otherwise>
+					/// &lt;param name="<xsl:value-of select="@name"/>"&gt;the key value of the record to show&lt;/param&gt;
+				</xsl:otherwise>
+			</xsl:choose>
+		</xsl:for-each>
+		[AccessibleThrough(Verb.Get)]
+		public void <xsl:value-of select="@name"/>( <xsl:for-each select="ancestor::adl:entity/adl:key/adl:property">
+			<!-- all args are passed as string because that's what hibernate-expression-eq expects -->
+			string <xsl:value-of select="concat( ' ', @name)"/>
+			<xsl:if test="not( position() = last())">,</xsl:if>
+		</xsl:for-each>) {
+		ISession hibernator = GetDBSession();
+		<xsl:value-of select="concat( 'this.', @name)"/>(
+		hibernator.CreateCriteria( typeof(<xsl:value-of select="concat($entityns, '.', ancestor::adl:entity/@name)"/>))
+		<xsl:for-each select="ancestor::adl:entity/adl:key/adl:property">
+			<xsl:call-template name="add-hibernate-expression-eq">
+				<xsl:with-param name="property" select="."/>
+				<xsl:with-param name="value" select="@name"/>
+			</xsl:call-template>
+		</xsl:for-each>
+		.UniqueResult&lt;<xsl:value-of select="concat($entityns, '.', ancestor::adl:entity/@name)"/>&gt;());
+		}
+
+		/// &lt;summary&gt;
+		/// Show the form named <xsl:value-of select="@name"/>, containing the indicated record
+		/// &lt;/summary&gt;
+		/// &lt;param name="record"&gt;the record to show&lt;/param&gt;
+		protected void <xsl:value-of select="@name"/>( <xsl:value-of select="concat($entityns, '.', ancestor::adl:entity/@name)"/> record)
+		{
+		ISession hibernator = GetDBSession();
+
+		TypedPropertyBag = new {
+		<xsl:call-template name="formmenus">
+			<xsl:with-param name="form" select="."/>
+		</xsl:call-template>
+		instance = record };
+
+		RenderViewWithFailover("<xsl:value-of select="concat( @name, '.vm')"/>", "<xsl:value-of select="concat( @name, '.auto.vm')"/>");
+		}
+	</xsl:template>
+
+	<xsl:template match="adl: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"/>()
+    {
+    AssertUserCanRead();
+    
+    string view = "<xsl:value-of select="@name"/>";
+    ISession hibernator = GetDBSession();
+    ICriteria search =
+    hibernator.CreateCriteria(typeof(<xsl:value-of select="concat( $entityns, '.', ancestor::adl:entity/@name)"/>));
+    Boolean withSearchCriteria = false;
+
+    <xsl:for-each select="adl:field">
+      <xsl:variable name="fieldprop" select="@property"/>
+      <xsl:variable name="property" select="ancestor::adl:entity//adl:property[@name=$fieldprop]"/>
+      <xsl:variable name="base-type">
+        <xsl:call-template name="base-type">
+          <xsl:with-param name="property" select="$property"/>
+        </xsl:call-template>
+      </xsl:variable>
+      /* <xsl:value-of select="@property"/> */
+      <xsl:choose>
+        <xsl:when test="$base-type='boolean'"/>
+        <xsl:when test="$base-type='link'"/>
+        <xsl:when test="$base-type='list'"/>
+        <xsl:otherwise>
+          if ( ! String.IsNullOrEmpty( Params[ "<xsl:value-of select="concat( 'search_', $property/@name)"/>"])) {
+          search<xsl:call-template name="add-hibernate-expression-like">
+            <xsl:with-param name="property" select="$property"/>
+            <xsl:with-param name="value">
+              Params["<xsl:value-of select="concat( 'search_', $property/@name)"/>"]
+            </xsl:with-param>
+          </xsl:call-template>;
+          PropertyBag["<xsl:value-of select="concat( 'search_', $property/@name)"/>"] = Params[ "<xsl:value-of select="concat( 'search_', $property/@name)"/>"];
+          withSearchCriteria = true;
+          }
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:for-each>
+
+    <xsl:choose>
+      <xsl:when test="adl:order">
+        /* explicit ordering */
+        <xsl:apply-templates select="adl:order"/>
+      </xsl:when>
+      <xsl:otherwise>
+        /* no explicit ordering */
+        <xsl:for-each select="ancestor::adl:entity//adl:property[@distinct='user' or @distinct='all']">
+          search.AddOrder(<xsl:value-of select="concat( ' new Order( &#34;', @name, '&#34;, true)')"/>);
+        </xsl:for-each>
+      </xsl:otherwise>
+    </xsl:choose>
+
+    IList&lt;<xsl:value-of select="concat( $entityns, '.', ancestor::adl:entity/@name)"/>&gt; instances = search.List&lt;<xsl:value-of select="concat( $entityns, '.', ancestor::adl:entity/@name)"/>&gt;();
+
+    /* if no instances, set showRecords to one else we get a division by zero error */
+    int showRecords = instances.Count > 0? instances.Count: 1;
+
+    if ( ! withSearchCriteria) {
+    showRecords = <xsl:value-of select="$records-per-page"/>;
+    }
+
+    PropertyBag["instances"] =
+    PaginationHelper.CreatePagination( this, instances, showRecords);
+
+    RenderViewWithFailover(view + ".vm", view + ".auto.vm");
+    }
+
+  </xsl:template>
+
+  <xsl:template match="adl:order">
+    search.AddOrder( new Order( "<xsl:value-of select="@property"/>", 
+    <xsl:choose>
+      <xsl:when test="@sequence='reverse-canonical'">false</xsl:when>
+      <xsl:otherwise>true</xsl:otherwise>
+    </xsl:choose>));
+  </xsl:template>
+
+	<xsl:template match="adl:documentation">
+		/* <xsl:apply-templates/> */
+	</xsl:template>
+
+
+	<xsl:template match="adl:key">
+		<!-- the key shouldn't be matched directly - at least, not in this implementation -->
+	</xsl:template>
+
+	<!-- for properties with @distinct='all' or @distinct='system', 
+		check that values are indeed distinct -->
+	<xsl:template name="check-property-value-distinct">
+		<xsl:param name="property"/>
+
+		<xsl:variable name="basetype">
+			<xsl:call-template name="base-type">
+				<xsl:with-param name="property" select="."/>
+			</xsl:call-template>
+		</xsl:variable>
+
+		<xsl:choose>
+			<xsl:when test="$property/ancestor::adl:key and not( $property/ancestor::adl:entity/adl:key[position()=2])">
+				<!-- if I'm the property of a key field and it is the only key field of my entity then
+					it is pointless trying to establish my distinctness -->
+			</xsl:when>
+			<xsl:when test="$property/@distinct = 'system' or $property/@distinct='all'">
+				/* <xsl:value-of select="$property/@name"/> should be distinct: check that it is */
+				matchCriteria =
+				hibernator.CreateCriteria(typeof(<xsl:value-of select="$property/ancestor::adl:entity/@name"/>));
+
+				matchCriteria<xsl:call-template name="add-hibernate-expression-eq">
+					<xsl:with-param name="property" select="$property"/>
+					<xsl:with-param name="value">
+						Form["<xsl:value-of select="concat( 'instance.', @name)"/>"]
+					</xsl:with-param>
+				</xsl:call-template>;
+
+				if ( record != null) {
+				/* i.e. we do have values for each of our key fields... */
+				<xsl:for-each select="$property/ancestor::adl:entity/adl:key/adl:property[position()=1]">
+					<xsl:variable name="keybasetype">
+						<xsl:call-template name="base-type">
+							<xsl:with-param name="property" select="."/>
+						</xsl:call-template>
+					</xsl:variable>
+					matchCriteria.Add(Expression.Not(<xsl:call-template name="hibernate-expression-eq">
+						<xsl:with-param name="property" select="."/>
+						<xsl:with-param name="value">
+							Form["<xsl:value-of select="concat( 'instance.', @name)"/>"]
+						</xsl:with-param>
+					</xsl:call-template>));
+				</xsl:for-each>
+				}
+
+				if ( matchCriteria.List&lt;<xsl:value-of select="$property/ancestor::adl:entity/@name"/>&gt;().Count > 0)
+				{
+				AddError(
+				String.Format("There is already a {0} with the {1} '{2}'",
+				"<xsl:value-of select="$property/ancestor::adl:entity/@name"/>", "<xsl:value-of select="$property/@name"/>", Form["<xsl:value-of select="concat('instance.', $property/@name)"/>"]));
+				}
+			</xsl:when>
+		</xsl:choose>
+	</xsl:template>
+
+
+	<!-- produce all menus for a given form: harder, but more efficient -->
+	<xsl:template name="formmenus">
+		<!-- an entity assumed to be of type adl:form -->
+		<xsl:param name="form"/>
+		<xsl:choose>
+			<xsl:when test="$form/@properties = 'all'">
+				<xsl:call-template name="entitymenus">
+					<xsl:with-param name="entity" select="$form/ancestor::adl:entity"/>
+				</xsl:call-template>
+			</xsl:when>
+			<xsl:otherwise>
+				/* form menus */
+				<xsl:for-each select="$form//adl:field">
+					<xsl:variable name="propname" select="@property"/>
+					<xsl:choose>
+						<xsl:when test="parent::adl:auxlist"/>
+						<xsl:when test="$form/ancestor::adl:entity//adl:property[@name=$propname and @type='entity']">
+							/* produce a list of <xsl:value-of select="$form/ancestor::adl:entity//adl:property[@name=$propname]/@entity"/> to populate the select for <xsl:value-of select="$propname"/> */
+							<xsl:call-template name="menu">
+								<xsl:with-param name="property" select="$form/ancestor::adl:entity//adl:property[@name=$propname]"/>
+							</xsl:call-template>
+						</xsl:when>
+						<xsl:when test="$form/ancestor::adl:entity//adl:property[@name=$propname and @type='link']">
+							/* produce a list of <xsl:value-of select="$form/ancestor::adl:entity//adl:property[@name=$propname]/@entity"/> to populate the LHS of the shuffle for <xsl:value-of select="$propname"/> */
+							<xsl:call-template name="menu">
+								<xsl:with-param name="property" select="$form/ancestor::adl:entity//adl:property[@name=$propname]"/>
+							</xsl:call-template>
+						</xsl:when>
+						<xsl:when test="$form/ancestor::adl:entity//adl:property[@name=$propname and @type='list']">
+							/* produce a list of <xsl:value-of select="$form/ancestor::adl:entity//adl:property[@name=$propname]/@entity"/> to populate the multi-select for <xsl:value-of select="@name"/> */
+							<xsl:call-template name="menu">
+								<xsl:with-param name="property" select="$form/ancestor::adl:entity//adl:property[@name=$propname]"/>
+							</xsl:call-template>
+						</xsl:when>
+					</xsl:choose>
+				</xsl:for-each>
+			</xsl:otherwise>
+		</xsl:choose>
+	</xsl:template>
+
+
+	<!-- produce all menus for a given entity: easier, but less efficient -->
+	<xsl:template name="entitymenus">
+		<xsl:param name="entity"/>
+		/* there's no way I can find of producing a set of just those entities
+		* we'll need menus for. So we set up variables for all the menus we might
+		* need, and then only instantiate those we do need. */
+		<xsl:for-each select="$entity/adl:property[@type='entity']">
+			<!-- $entity/adl:property because it is possible to have type='entity' in the key -->
+			<xsl:call-template name="menu">
+				<xsl:with-param name="property" select="."/>
+			</xsl:call-template>
+		</xsl:for-each>
+		<xsl:for-each select="$entity/adl:property[@type='link']">
+			<!-- $entity/adl:property because it is not possible to have type='link' in the key -->
+			/* 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/adl: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="entity" select="//adl:entity[@name=$property/@entity]"/>
+		<xsl:value-of select="concat('all_', $property/@name)"/> =
+		<xsl:value-of select="concat( 'FetchAll', $entity/@name)"/>( ),
+	</xsl:template>
+
+	<xsl:template name="primary-key-csharp-type">
+		<xsl:param name="entity"/>
+		<xsl:if test="not( $entity)">
+			<xsl:message terminate="yes">
+				ADL: ERROR: No entity passed to template primary-key-csharp-type
+			</xsl:message>
+		</xsl:if>
+		<xsl:if test="not($entity/adl:key/adl:property)">
+			<xsl:message terminate="no">
+				ADL: WARNING: entity '<xsl:value-of select="$entity/@name"/>' has no primary key.
+				You will have to manually edit <xsl:value-of select="concat( $entity/@name, 'Controller.auto.cs')"/>
+			</xsl:message>
+		</xsl:if>
+		<xsl:call-template name="csharp-type">
+			<xsl:with-param name="property" select="$entity/adl:key/adl:property[ position() = 1]"/>
+			<xsl:with-param name="entityns" select="$entityns"/>
+		</xsl:call-template>
+	</xsl:template>
+
+	<xsl:template name="primary-key-name">
+		<!-- return the name of the primary key of the entity with this name -->
+		<xsl:param name="entity"/>
+		<xsl:if test="not($entity/adl:key)">
+			<xsl:message terminate="yes">
+				ADL: ERROR: No key for entity: <xsl:value-of select="$entity/@name"/>
+			</xsl:message>
+		</xsl:if>
+		<xsl:choose>
+			<xsl:when test="$entity/adl:key/adl:property[position()=2]">
+				<xsl:message terminate="no">
+					ADL: WARNING: Entity <xsl:value-of select="$entity/@name"/> has a composite primary key.
+					You will need to manually edit <xsl:value-of select="concat( $entity/@name, 'Controller.auto.cs')"/>
+				</xsl:message>
+				<xsl:value-of select="$entity/adl:key/adl:property[position()=1]/@name"/>
+			</xsl:when>
+			<xsl:when test="$entity/adl:key/adl:property">
+				<xsl:value-of select="$entity/adl:key/adl:property[position()=1]/@name"/>
+			</xsl:when>
+			<xsl:otherwise>
+				<xsl:message terminate="no">
+					ADL: WARNING: Entity <xsl:value-of select="$entity/@name"/> has no primary key.
+					You will need to manually edit <xsl:value-of select="concat( $entity/@name, 'Controller.auto.cs')"/>
+				</xsl:message>
+			</xsl:otherwise>
+		</xsl:choose>
+	</xsl:template>
+
+	<!-- it's often convenient to wrap an expression in an Add() -->
+	<xsl:template name="add-hibernate-expression-eq">
+		<xsl:param name="property"/>
+		<xsl:param name="value"/>
+		<xsl:variable name="basetype">
+			<xsl:call-template name="base-type">
+				<xsl:with-param name="property" select="$property"/>
+			</xsl:call-template>
+		</xsl:variable>
+		.Add(<xsl:call-template name="hibernate-expression-eq">
+			<xsl:with-param name="property" select="$property"/>
+			<xsl:with-param name="value" select="$value"/>
+		</xsl:call-template>)
+	</xsl:template>
+
+	<!-- it's often convenient to wrap an expression in an Add() -->
+	<xsl:template name="add-hibernate-expression-like">
+		<xsl:param name="property"/>
+		<xsl:param name="value"/>
+		<xsl:variable name="basetype">
+			<xsl:call-template name="base-type">
+				<xsl:with-param name="property" select="$property"/>
+			</xsl:call-template>
+		</xsl:variable>
+		.Add(<xsl:call-template name="hibernate-expression-like">
+			<xsl:with-param name="property" select="$property"/>
+			<xsl:with-param name="value" select="$value"/>
+		</xsl:call-template>)
+	</xsl:template>
+
+	<!-- generate a hibernate equality expression based on this property,
+		comparing it to this value -->
+	<xsl:template name="hibernate-expression-eq">
+		<!-- an entity of type property -->
+		<xsl:param name="property"/>
+		<!-- an expression which, at run time, will evaluate to a string -->
+		<xsl:param name="value"/>
+		<xsl:variable name="basetype">
+			<xsl:call-template name="base-type">
+				<xsl:with-param name="property" select="$property"/>
+			</xsl:call-template>
+		</xsl:variable>
+		Expression.Eq("<xsl:value-of select="$property/@name"/>", <xsl:choose>
+			<xsl:when test="$basetype = 'string'">
+				<xsl:value-of select="$value"/>
+			</xsl:when>
+      <xsl:when test="$basetype = 'image'">
+        <!-- image and uplodable are essentially just comparisons of file names -->
+        <xsl:value-of select="$value"/>
+      </xsl:when>
+      <xsl:when test="$basetype = 'uploadable'">
+        <!-- image and uplodable are essentially just comparisons of file names -->
+        <xsl:value-of select="$value"/>
+      </xsl:when>
+      <xsl:when test="$basetype = 'integer'">
+				Int32.Parse( <xsl:value-of select="$value"/>)
+			</xsl:when>
+			<xsl:when test="$basetype = 'money'">
+				Decimal.Parse( <xsl:value-of select="$value"/>)
+			</xsl:when>
+			<xsl:when test="$basetype = 'date'">
+				DateTime.Parse( <xsl:value-of select="$value"/>)
+			</xsl:when>
+			<xsl:when test="$basetype='entity'">
+				<xsl:call-template name="fetch-property-instance">
+					<xsl:with-param name="property" select="$property"/>
+					<xsl:with-param name="value" select="$value"/>
+				</xsl:call-template>
+			</xsl:when>
+			<xsl:otherwise>
+				<xsl:message terminate="yes">
+					ADL: Error: properties of type <xsl:value-of select="$basetype"/> cannot yet be used
+					in equality tests
+				</xsl:message>
+      </xsl:otherwise>
+		</xsl:choose>)
+	</xsl:template>
+
+	<!-- generate a hibernate like expression based on this property,
+		comparing it to this value -->
+	<xsl:template name="hibernate-expression-like">
+		<xsl:param name="property"/>
+		<xsl:param name="value"/>
+		<xsl:variable name="basetype">
+			<xsl:call-template name="base-type">
+				<xsl:with-param name="property" select="$property"/>
+			</xsl:call-template>
+		</xsl:variable>
+		<xsl:choose>
+			<xsl:when test="$basetype='string' or $basetype='text'">
+				Expression.Like( "<xsl:value-of select="$property/@name"/>", "%"+<xsl:value-of select="$value"/>+"%")
+			</xsl:when>
+			<xsl:when test="$basetype='real'">
+				/* match to four significant places */
+				Expression.Between( "<xsl:value-of select="$property/@name"/>", 
+					Double.Parse( <xsl:value-of select="$value"/>) * 1.0001, 
+					Double.Parse( <xsl:value-of select="$value"/>) * 0.9999)
+			</xsl:when>
+			<xsl:otherwise>
+				<xsl:call-template name="hibernate-expression-eq">
+					<xsl:with-param name="property" select="$property"/>
+					<xsl:with-param name="value" select="$value"/>
+				</xsl:call-template>
+			</xsl:otherwise>
+		</xsl:choose>
+	</xsl:template>
+
+	<!-- argument: a property 
+      returns 'true' if that property is of a type which makes it searchable,
+      else 'false'. See also how search fields are generated in adl2views.xsl -->
+	<xsl:template name="is-searchable">
+		<xsl:param name="property"/>
+		<xsl:variable name="base-type">
+			<xsl:call-template name="base-type">
+				<xsl:with-param name="property" select="$property"/>
+			</xsl:call-template>
+		</xsl:variable>
+		<xsl:choose>
+			<xsl:when test="$base-type='string'">true</xsl:when>
+			<xsl:when test="$base-type='integer'">true</xsl:when>
+			<xsl:when test="$base-type='real'">true</xsl:when>
+			<xsl:when test="$base-type='money'">true</xsl:when>
+			<xsl:when test="$base-type='text'">true</xsl:when>
+			<xsl:when test="$base-type='entity'">true</xsl:when>
+			<xsl:otherwise>false</xsl:otherwise>
+		</xsl:choose>
+
+	</xsl:template>
+
+	<xsl:template name="fetch-property-instance">
+		<!-- the property for which the instance is sought; it is assumed that
+			the property passed has type 'entity' -->
+		<xsl:param name="property"/>
+		<!-- the name of the value in the returned values from which the instance
+			must be resolved -->
+		<xsl:param name="value"/>
+		<xsl:variable name="basetype">
+			<xsl:call-template name="base-type">
+				<xsl:with-param name="property" select="$property"/>
+			</xsl:call-template>
+		</xsl:variable>
+		<xsl:if test="not( $basetype='entity')">
+			<xsl:message terminate="yes">
+				ADL: ERROR: property passed to fetch-property-instance whose type is not 'entity'
+			</xsl:message>
+		</xsl:if>
+		hibernator.CreateCriteria(typeof(<xsl:value-of select="concat( $entityns, '.', $property/@entity)"/>))
+		<xsl:for-each select="//adl:entity[@name=$property/@entity]/adl:key/adl:property">
+			<xsl:call-template name="add-hibernate-expression-eq">
+				<xsl:with-param name="property" select="."/>
+				<xsl:with-param name="value" select="$value"/>
+			</xsl:call-template>
+		</xsl:for-each>
+		.UniqueResult&lt;<xsl:value-of select="concat( $entityns, '.', $property/@entity)"/>&gt;()
+	</xsl:template>
+
 </xsl:stylesheet>
\ No newline at end of file
diff --git a/transforms/adl2documentation.xslt b/transforms/adl2documentation.xslt
index 454e113..1ae21b9 100755
--- a/transforms/adl2documentation.xslt
+++ b/transforms/adl2documentation.xslt
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 
 <xsl:stylesheet version="1.0"
-  xmlns="http://libs.cygnets.co.uk/adl/1.4/"
-  xmlns:adl="http://libs.cygnets.co.uk/adl/1.4/"
+  xmlns="http://bowyer.journeyman.cc/adl/1.4/"
+  xmlns:adl="http://bowyer.journeyman.cc/adl/1.4/"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 	<xsl:output encoding="UTF-8" method="xml" indent="yes" />
 
diff --git a/transforms/adl2entityclasses.xslt b/transforms/adl2entityclasses.xslt
index ee022e4..b0f629f 100755
--- a/transforms/adl2entityclasses.xslt
+++ b/transforms/adl2entityclasses.xslt
@@ -7,17 +7,17 @@
     
     Transform ADL into C# entity classes
     
-    $Author: sb $
-    $Revision: 1.28 $
-    $Date: 2010-06-01 17:29:02 $
+    $Author: simon $
+    $Revision: 1.29 $
+    $Date: 2010-07-20 19:53:40 $
   -->
 
 <!-- WARNING WARNING WARNING: Do NOT reformat this file! 
      Whitespace (or lack of it) is significant! -->
 <xsl:stylesheet version="1.0"
-  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:xsl="http://bowyer.journeyman.cc/adl/1.4/"
   xmlns:exsl="http://exslt.org/common"
-  xmlns:adl="http://libs.cygnets.co.uk/adl/1.4/"
+  xmlns:adl="http://bowyer.journeyman.cc/adl/1.4/"
   xmlns:msxsl="urn:schemas-microsoft-com:xslt">
 
 	<xsl:include href="csharp-type-include.xslt"/>
@@ -70,7 +70,7 @@
 		//  (c)2007 Cygnet Solutions Ltd
 		//
 		//  Automatically generated from application description using
-		//  adl2entityclass.xsl revision <xsl:value-of select="substring( '$Revision: 1.28 $', 10)"/>
+		//  adl2entityclass.xsl revision <xsl:value-of select="substring( '$Revision: 1.29 $', 10)"/>
 		//
 		//  <xsl:value-of select="/adl:application/@revision"/>
 		//
@@ -97,7 +97,7 @@
 		/// &lt;/summary&gt;
 		/// &lt;remarks&gt;
 		/// Automatically generated from description of group <xsl:value-of select="@name"/>
-		/// using adl2entityclass.xsl revision <xsl:value-of select="substring( '$Revision: 1.28 $', 10)"/>.
+		/// using adl2entityclass.xsl revision <xsl:value-of select="substring( '$Revision: 1.29 $', 10)"/>.
 		///
 		/// DO NOT EDIT THIS FILE!
 		/// &lt;/remarks&gt;
@@ -123,7 +123,7 @@
 		//  (c)2007 Cygnet Solutions Ltd
 		//
 		//  Automatically generated from application description using
-		//  adl2entityclass.xsl revision <xsl:value-of select="substring( '$Revision: 1.28 $', 10)"/>
+		//  adl2entityclass.xsl revision <xsl:value-of select="substring( '$Revision: 1.29 $', 10)"/>
 		//
 		//  <xsl:value-of select="/adl:application/@revision"/>
 		//
@@ -159,7 +159,7 @@
 		/// &lt;/summary&gt;
 		/// &lt;remarks&gt;
 		/// Automatically generated from description of entity <xsl:value-of select="@name"/>
-		/// using adl2entityclass.xsl revision <xsl:value-of select="substring( '$Revision: 1.28 $', 10)"/>.
+		/// using adl2entityclass.xsl revision <xsl:value-of select="substring( '$Revision: 1.29 $', 10)"/>.
 		/// Note that manually maintained parts of this class may be defined in
 		/// a separate file called <xsl:value-of select="@name"/>.manual.cs, q.v.
 		///
diff --git a/transforms/adl2hibernate.xslt b/transforms/adl2hibernate.xslt
index 8bd0c0c..821d347 100755
--- a/transforms/adl2hibernate.xslt
+++ b/transforms/adl2hibernate.xslt
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <xsl:stylesheet version="1.0"
   xmlns="urn:nhibernate-mapping-2.2"
-  xmlns:adl="http://libs.cygnets.co.uk/adl/1.4/"
+  xmlns:adl="http://bowyer.journeyman.cc/adl/1.4/"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 	<!--
       Application Description Framework
@@ -11,8 +11,8 @@
       
       Transform ADL to Hibernate
       
-      $Author: sb $
-      $Revision: 1.10 $
+      $Author: simon $
+      $Revision: 1.11 $
   -->
 
 	<xsl:param name="namespace"/>
@@ -138,7 +138,7 @@
 	*
 	*	  <xsl:value-of select="@revision"/>
     *
-    *	  Generated using adl2hibernate.xslt revision <xsl:value-of select="substring('$Revision: 1.10 $', 12)"/>
+    *	  Generated using adl2hibernate.xslt revision <xsl:value-of select="substring('$Revision: 1.11 $', 12)"/>
     *
     ***************************************************************************
 			</xsl:comment>
diff --git a/transforms/adl2mssql.xslt b/transforms/adl2mssql.xslt
index 80d3257..b6fc0c4 100755
--- a/transforms/adl2mssql.xslt
+++ b/transforms/adl2mssql.xslt
@@ -1,834 +1,852 @@
-<?xml version="1.0"?>
-<xsl:stylesheet version="1.0" 
-  xmlns="http://libs.cygnets.co.uk/adl/1.4/" 
-  xmlns:adl="http://libs.cygnets.co.uk/adl/1.4/"
-  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
-  <!--
-      Application Description Language framework
-      adl2mssql.xsl
-      
-      (c) 2007 Cygnet Solutions Ltd
-      
-      Convert ADL to MS-SQL
-      
-      $Author: sb $
-      $Revision: 1.20 $
-  -->
-    
-  <xsl:output indent="no" encoding="UTF-8" method="text"/>
-  <xsl:include href="base-type-include.xslt"/>
-
-  <!-- 
-      The convention to use for naming auto-generated abstract primary keys. Known values are
-      Id - the autogenerated primary key, if any, is called just 'Id'
-      Name - the autogenerated primary key has the same name as the entity
-      NameId - the name of the auto generated primary key is the name of the entity followed by 'Id'
-      Name_Id - the name of the auto generated primary key is the name of the entity followed by '_Id'  
-    -->
-  <xsl:param name="abstract-key-name-convention" select="Id"/>
-
-	<!-- the convention to use for fieldnames in link tables:
-		Name - the name of the foreign key is the same as the name of the table linked to
-		NameId - the name of the foreign key is the same as the name of the table linked to, followed by 'Id'
-		Name_Id - the name of the foreign key is the same as the name of the table linked to, followed by '_Id'
-		Name_Link  - the name of the foreign key is the same as the name of the table linked to, followed by '_Link'
-	-->
-	<xsl:param name="linktable-field-name-convention" select="Name"/>
-	
-  <xsl:param name="database"/>
-	<!-- the name and version of the product being built -->
-	<xsl:param name="product-version" select="'Application Description Language Framework'"/>
-
-	<!-- define upper and lower case letters to enable case conversion -->
-  <xsl:variable name="ucase">ABCDEFGHIJKLMNOPQRSTUVWXYZ</xsl:variable>
-  <xsl:variable name="lcase">abcdefghijklmnopqrstuvwxyz</xsl:variable>
-  <!-- define SQL keywords to police these out of field names -->
-  <xsl:variable name="sqlkeywords-multiline">
-	  ADD 				EXCEPT 				PERCENT
-	  ALL 				EXEC 				PLAN
-	  ALTER 				EXECUTE				PRECISION
-	  AND 				EXISTS 				PRIMARY
-	  ANY 				EXIT 				PRINT
-	  AS 					FETCH 				PROC
-	  ASC 				FILE 				PROCEDURE
-	  AUTHORIZATION 		FILLFACTOR 			PUBLIC
-	  BACKUP 				FOR 				RAISERROR
-	  BEGIN 				FOREIGN 			READ
-	  BETWEEN 			FREETEXT 			READTEXT
-	  BREAK 				FREETEXTTABLE 		RECONFIGURE
-	  BROWSE 				FROM 				REFERENCES
-	  BULK 				FULL 				REPLICATION
-	  BY 					FUNCTION 			RESTORE
-	  CASCADE 			GOTO 				RESTRICT
-	  CASE 				GRANT 				RETURN
-	  CHECK 				GROUP 				REVOKE
-	  CHECKPOINT 			HAVING 				RIGHT
-	  CLOSE 				HOLDLOCK		 	ROLLBACK
-	  CLUSTERED 			IDENTITY		 	ROWCOUNT
-	  COALESCE 			IDENTITY_INSERT 	ROWGUIDCOL
-	  COLLATE 			IDENTITYCOL		 	RULE
-	  COLUMN 				IF 					SAVE
-	  COMMIT 				IN 					SCHEMA
-	  COMPUTE 			INDEX			 	SELECT
-	  CONSTRAINT 			INNER 				SESSION_USER
-	  CONTAINS 			INSERT 				SET
-	  CONTAINSTABLE 		INTERSECT		 	SETUSER
-	  CONTINUE 			INTO 				SHUTDOWN
-	  CONVERT 			IS 					SOME
-	  CREATE 				JOIN			 	STATISTICS
-	  CROSS 				KEY					SYSTEM_USER
-	  CURRENT 			KILL			 	TABLE
-	  CURRENT_DATE 		LEFT			 	TEXTSIZE
-	  CURRENT_TIME 		LIKE			 	THEN
-	  CURRENT_TIMESTAMP 	LINENO				TO
-	  CURRENT_USER 		LOAD 				TOP
-	  CURSOR 				NATIONAL 			TRAN
-	  DATABASE 			NOCHECK 			TRANSACTION
-	  DBCC 				NONCLUSTERED 		TRIGGER
-	  DEALLOCATE 			NOT 				TRUNCATE
-	  DECLARE 			NULL 				TSEQUAL
-	  DEFAULT 			NULLIF 				UNION
-	  DELETE 				OF 					UNIQUE
-	  DENY 				OFF 				UPDATE
-	  DESC 				OFFSETS				UPDATETEXT
-	  DISK 				ON 					USE
-	  DISTINCT	 		OPEN 				USER
-	  DISTRIBUTED 		OPENDATASOURCE 		VALUES
-	  DOUBLE 				OPENQUERY 			VARYING
-	  DROP 				OPENROWSET 			VIEW
-	  DUMMY 				OPENXML 			WAITFOR
-	  DUMP 				OPTION 				WHEN
-	  ELSE 				OR 					WHERE
-	  END 				ORDER 				WHILE
-	  ERRLVL 				OUTER				WITH
-	  ESCAPE 				OVER				WRITETEXT
-  </xsl:variable>
-  <xsl:variable name="sqlkeywords" select="concat(' ', normalize-space($sqlkeywords-multiline), ' ')"/>
-
-
-  <xsl:template match="adl:application"> 
-        -------------------------------------------------------------------------------------------------
-        --
-        --    <xsl:value-of select="$product-version"/>
-        --
-        --    Database for application <xsl:value-of select="@name"/> version <xsl:value-of select="@version"/>
-        --    Generated for MS-SQL 2000+ using adl2mssql.xslt <xsl:value-of select="substring('$Revision: 1.20 $', 12)"/>
-	    --    THIS FILE IS AUTOMATICALLY GENERATED: DO NOT EDIT IT.
-		--
-		--    <xsl:value-of select="@revision"/>
-        --
-        --    Code generator (c) 2007 Cygnet Solutions Ltd
-        --
-        -------------------------------------------------------------------------------------------------
-
-    <xsl:if test="string-length( $database) &gt; 0">
-      use "<xsl:value-of select="$database"/>";
-    </xsl:if>
-
-        -------------------------------------------------------------------------------------------------
-        --    authentication roles
-        -------------------------------------------------------------------------------------------------
-    <xsl:apply-templates select="adl:group"/>
-
-	  -------------------------------------------------------------------------------------------------
-	  --	magic view for role membership, used in establishing security credentials
-	  -------------------------------------------------------------------------------------------------
-	  CREATE VIEW RoleMembership AS
-		 SELECT dbuser.name as "dbuser", 
-				dbrole.name as "dbrole"
-		   FROM sysusers AS dbuser, sysmembers, sysusers AS dbrole
-		  WHERE dbuser.uid = sysmembers.memberuid
-			AND dbrole.uid = sysmembers.groupuid
-	  GO
-			
-	  GRANT SELECT on RoleMembership to public
-	  GO
-
-	  -------------------------------------------------------------------------------------------------
-	  --    primary tables, views and permissions
-	  -------------------------------------------------------------------------------------------------
-	  <xsl:apply-templates select="adl:entity" mode="table"/>
-
-        -------------------------------------------------------------------------------------------------
-        --    link tables  
-        -------------------------------------------------------------------------------------------------
-    <xsl:apply-templates select="adl:entity" mode="links"/>
-
-        -------------------------------------------------------------------------------------------------
-        --    primary referential integrity constraints
-        -------------------------------------------------------------------------------------------------
-    <xsl:apply-templates select="adl:entity" mode="refinteg"/>
-      
-        -------------------------------------------------------------------------------------------------
-        --    end of file
-        -------------------------------------------------------------------------------------------------
-  </xsl:template>
-
-	<xsl:template match="adl:documentation">
-		/*    <xsl:apply-templates/> */
-	</xsl:template>
-	
-  <xsl:template match="adl:group">
-		-------------------------------------------------------------------------------------------------
-		--    security group <xsl:value-of select="@name"/>
-		-------------------------------------------------------------------------------------------------
-	  <xsl:apply-templates select="adl:documentation"/>
-		execute sp_addrole @rolename = '<xsl:value-of select="@name"/>'
-		GO
-  </xsl:template>
-
-  <!-- return the table name for the entity with this entity name -->
-  <xsl:template name="tablename">
-    <xsl:param name="entityname"/>
-    <xsl:choose>
-      <xsl:when test="//adl:entity[@name=$entityname]/@table">
-        <xsl:value-of select="//adl:entity[@name=$entityname]/@table"/>
-      </xsl:when>
-      <xsl:otherwise>
-        <xsl:value-of select="$entityname"/>
-      </xsl:otherwise>
-    </xsl:choose>
-  </xsl:template>
-  
-  <!-- generate a foreign key referential integrity check -->
-  <xsl:template name="foreignkey">
-    <xsl:param name="nearside"/>
-    <xsl:param name="farside"/>
-    <xsl:param name="linkfield"/>
-    <xsl:param name="ondelete" select="'NO ACTION'"/>
-
-    <xsl:variable name="neartable">
-      <xsl:call-template name="tablename">
-        <xsl:with-param name="entityname" select="$nearside"/>
-      </xsl:call-template>
-    </xsl:variable>
-    
-    <xsl:variable name="fartable">
-      <xsl:call-template name="tablename">
-        <xsl:with-param name="entityname" select="$farside"/>
-      </xsl:call-template>
-    </xsl:variable>
-    
-    <!-- set up referential integrity constraints for primary tables -->
-        ALTER TABLE "<xsl:value-of select="$neartable"/>"
-            ADD FOREIGN KEY ( "<xsl:value-of select="$linkfield"/>") 
-            REFERENCES "<xsl:value-of select="$fartable"/>" ON DELETE <xsl:value-of select="$ondelete"/>
-            
-        GO
-  </xsl:template>
-
-  <!-- generate referential integrity constraints -->
-  <!-- there's a sort-of problem with this - if we have properties at both 
-	ends of a link (which we often do) we currently generate two identical 
-	constraints. This doesn't seem to cause any major problems but must hurt 
-	efficiency. It would be better if we fixed this. -->
-  <xsl:template match="adl:entity" mode="refinteg">
-    <xsl:variable name="nearside" select="@name"/>
-    <xsl:for-each select="descendant::adl:property[@type='entity']">
-      <xsl:variable name="farside" select="@entity"/>
-      <xsl:variable name="keyfield">
-        <xsl:call-template name="property-column-name">
-          <xsl:with-param name="property" select="."/>
-        </xsl:call-template>
-      </xsl:variable>
-      <xsl:choose>
-        <xsl:when test="//adl:entity[@name=$farside]//adl:property[@farkey=$keyfield and @entity=$nearside]">
-          <!-- there's a 'list' property pointing the other way; let it do the heavy hauling -->
-			<!-- list with farkey -->
-        </xsl:when>
-		  <xsl:when test="//adl:entity[@name=$farside]//adl:property[@entity=$nearside and not( @farkey)]">
-			  <!-- there's a 'list' property pointing the other way; let it do the heavy hauling -->
-			  <!-- list with no farkey -->
-		  </xsl:when>
-		  <xsl:otherwise>
-          <xsl:call-template name="foreignkey">
-            <xsl:with-param name="nearside" select="$nearside"/>
-            <xsl:with-param name="farside" select="$farside"/>
-            <xsl:with-param name="linkfield" select="$keyfield"/>
-          </xsl:call-template>
-        </xsl:otherwise>
-      </xsl:choose>
-    </xsl:for-each>
-    <xsl:for-each select="descendant::adl:property[@type='list']">
-		<xsl:variable name="ns2" select="@entity"/>
-		<xsl:variable name="linkfield">
-			<xsl:call-template name="property-column-name">
-				<xsl:with-param name="property" 
-								select="//adl:entity[@name=$ns2]//adl:property[@entity=$nearside]"/>
-			</xsl:call-template>
-		</xsl:variable>
-		<xsl:if test="string-length( $linkfield) = 0">
-			<xsl:message terminate="yes">
-				ADL: ERROR: Failed to infer link field name whilst processing list property <xsl:value-of select="@name"/> of <xsl:value-of select="ancestor::adl:entity/@name"/>
- Entity is '<xsl:value-of select="$ns2"/>', nearside is '<xsl:value-of select="$nearside"/>'
-			</xsl:message>
-		</xsl:if>
-      <xsl:call-template name="foreignkey">
-        <xsl:with-param name="nearside" select="@entity"/>
-        <xsl:with-param name="farside" select="../@name"/>
-        <xsl:with-param name="linkfield" select="$linkfield"/>
-        <xsl:with-param name="ondelete">
-          <xsl:choose>
-            <xsl:when test="@cascade='all'">CASCADE</xsl:when>
-            <xsl:when test="@cascade='all-delete-orphan'">CASCADE</xsl:when>
-            <xsl:when test="@cascade='delete'">CASCADE</xsl:when>
-            <xsl:otherwise>NO ACTION</xsl:otherwise>
-          </xsl:choose>
-        </xsl:with-param>
-      </xsl:call-template>
-    </xsl:for-each>
-  </xsl:template>
-  
-  
-  <!-- don't generate foreign tables - although we will generate ref integ constraints for them -->
-  <xsl:template match="adl:entity[@foreign='true']" mode="table"/> 
-
-  <xsl:template match="adl:entity" mode="table">
-	  <!-- the name of the entity we're generating -->
-	  <xsl:variable name="entityname" select="@name"/>
-	  <!-- the name of the table to generate -->
-	  <xsl:variable name="table">
-		  <xsl:call-template name="tablename">
-			  <xsl:with-param name="entityname" select="@name"/>
-		  </xsl:call-template>
-	  </xsl:variable>
-	  <!-- the entity we are generating -->
-	  <xsl:variable name="generating-entity" select="."/>
-
-		-------------------------------------------------------------------------------------------------
-		--    primary table <xsl:value-of select="$table"/>
-        -------------------------------------------------------------------------------------------------
- 	  <xsl:apply-templates select="adl:documentation"/>
-		CREATE TABLE  "<xsl:value-of select="$table"/>"
-		(
-	  <xsl:for-each select="descendant::adl:property[not( @type='link' or @type = 'list' or @concrete='false')]">
-		  <xsl:apply-templates select="."/>
-		  <xsl:if test="position() != last()">,</xsl:if>
-	  </xsl:for-each>
-	  <xsl:for-each select="//adl:property[@type='list' and @entity = $entityname]">
-		  <xsl:variable name="referringprop" select="."/>
-		  <xsl:choose>
-			  <xsl:when test="$generating-entity//adl:property[ @type='entity' and @entity=$referringprop/ancestor::adl:entity/@name]">
-				  <!-- if the entity for which I'm currently generating already has a specified property
-				  which links to this foreign entity, I don't have to dummy one up -->
-			  </xsl:when>
-			  <xsl:otherwise>
-				  <!-- dummy up the 'many' end of a one-to-many link -->
-				  , "<xsl:value-of select="ancestor::adl:entity/@name"/>"<xsl:text> </xsl:text><xsl:call-template name="sql-type">
-					  <xsl:with-param name="property" select="ancestor::adl:entity/adl:key/adl:property[position() = 1]"/>
-				  </xsl:call-template>
-			  </xsl:otherwise>
-		  </xsl:choose>
-	  </xsl:for-each>
-    <xsl:apply-templates select="adl:key"/>
-        )
-        GO
-
-        ----  permissions  ------------------------------------------------------------------------------
-    <xsl:for-each select="adl:permission">
-      <xsl:call-template name="permission">
-        <xsl:with-param name="entity" select="ancestor::adl:entity"/>
-      </xsl:call-template>
-    </xsl:for-each>
-
-  </xsl:template>
-
-  <xsl:template match="adl:key">
-    <xsl:if test="adl:property[not( @concrete='false')]">
-          , 
-          PRIMARY KEY( <xsl:for-each select="adl:property[not( @concrete='false')]">"<xsl:call-template name="property-column-name">
-            <xsl:with-param name="property" select="."/>
-          </xsl:call-template>"<xsl:if test="position() != last()">, </xsl:if></xsl:for-each>)
-    </xsl:if>
-  </xsl:template>
-
-  <xsl:template name="distinctfield">
-    <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>
-
-  <!-- fix up linking tables. Donoe after all primary tables have been created, 
-  because otherwise some links may fail -->
-  <xsl:template match="adl:entity" mode="links">
-    <xsl:variable name="entityname" select="@name"/>
-    <xsl:for-each select="adl:property[@type='link']">
-      <xsl:call-template name="linktable">
-        <xsl:with-param name="nearside" select="$entityname"/>
-      </xsl:call-template>
-    </xsl:for-each>
-  </xsl:template>
-
-  <xsl:template name="permission">
-    <xsl:param name="entity"/>
-    <!-- decode the permissions for a table -->
-    <xsl:variable name="table">
-      <xsl:call-template name="tablename">
-        <xsl:with-param name="entityname" select="$entity/@name"/>
-      </xsl:call-template>
-    </xsl:variable>
-    <xsl:choose>
-      <xsl:when test="@permission='read'">
-        GRANT SELECT ON "<xsl:value-of
-                select="$table"/>" TO "<xsl:value-of select="@group"/>"
-      </xsl:when>
-      <xsl:when test="@permission='insert'">
-        GRANT INSERT ON "<xsl:value-of
-                select="$table"/>" TO "<xsl:value-of select="@group"/>"
-      </xsl:when>
-      <xsl:when test="@permission='noedit'">
-        GRANT SELECT, INSERT ON "<xsl:value-of
-                select="$table"/>" TO "<xsl:value-of select="@group"/>"
-      </xsl:when>
-      <xsl:when test="@permission='edit'">
-        GRANT SELECT, INSERT, UPDATE ON "<xsl:value-of
-                select="$table"/>" TO "<xsl:value-of select="@group"/>"
-      </xsl:when>
-      <xsl:when test="@permission='all'">
-        GRANT SELECT, INSERT, UPDATE, DELETE ON "<xsl:value-of
-                select="$table"/>" TO "<xsl:value-of select="@group"/>"
-      </xsl:when>
-      <xsl:otherwise>
-        REVOKE ALL ON "<xsl:value-of
-                select="$table"/>" FROM "<xsl:value-of select="@group"/>"
-      </xsl:otherwise>
-    </xsl:choose>
-    <xsl:text>
-        GO
-        
-    </xsl:text>
-  </xsl:template>
-
-  <!-- expects to be called in the context of an entity; probably should make this explicit. 
-    TODO: this is a mess; refactor. -->
-  <xsl:template name="linktable">
-        <xsl:param name="nearside"/>
-      <!-- This is tricky. For any many-to-many relationship between two 
-      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="farentityname" select="@entity"/>
-      <xsl:variable name="farentity" select="//adl:entity[@name=$farentityname]"/>
-	  <xsl:variable name="linksuffix">
-		  <xsl:choose>
-			  <xsl:when test="$linktable-field-name-convention = 'Name'"/>
-			  <xsl:when test="$linktable-field-name-convention = 'NameId'">
-				  <xsl:value-of select="'Id'"/>
-			  </xsl:when>
-			  <xsl:when test="$linktable-field-name-convention = 'Name_Id'">
-				  <xsl:value-of select="'_Id'"/>
-			  </xsl:when>
-			  <xsl:when test="$linktable-field-name-convention = 'NameLink'">
-				  <xsl:value-of select="'Link'"/>
-			  </xsl:when>
-			  <xsl:when test="$linktable-field-name-convention = 'Name_Link'">
-				  <xsl:value-of select="'_Link'"/>
-			  </xsl:when>
-		  </xsl:choose>
-	  </xsl:variable>
-
-	  <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/adl:property[@type='link' and @entity=$nearside]">false</xsl:when>
-              <xsl:otherwise>true</xsl:otherwise>
-            </xsl:choose>
-          </xsl:when>
-          <xsl:otherwise>false</xsl:otherwise>
-        </xsl:choose>
-      </xsl:variable>
-      <!-- Problems with responsibility for generating link tables: -->
-        -- Problems with responsibility for generating link tables:
-        -- @entity = <xsl:value-of select="@entity"/>
-        -- $nearside = <xsl:value-of select="$nearside"/>
-        -- $farside = <xsl:value-of select="$farside"/>
-        -- farlink = <xsl:value-of select="$farentity/adl:property[@type='link' and @entity=$nearside]/@name"/>
-        -- comparison = '<xsl:value-of select="$comparison"/>' 
-        -- my responsibility = <xsl:value-of select="$myresponsibility"/>
-      <xsl:variable name="linktablename">
-        <xsl:choose>
-          <xsl:when test="$comparison =-1">
-            <xsl:value-of select="concat( 'LN_', $nearside, '_', @entity)"/>
-          </xsl:when>
-          <xsl:otherwise>
-            <xsl:value-of select="concat( 'LN_', @entity, '_', $nearside)"/>
-          </xsl:otherwise>
-        </xsl:choose>
-      </xsl:variable>
-      <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="$linktablename"/>"
-        (
-          "<xsl:value-of select="concat( $nearside, $linksuffix)"/>" <xsl:call-template name="sql-type">
-            <xsl:with-param name="property" select="//adl:entity[@name=$nearside]/adl:key/adl:property[position()=1]"/>
-          </xsl:call-template> NOT NULL,
-          "<xsl:value-of select="concat( $farside, $linksuffix)"/>" <xsl:call-template name="sql-type">
-          <xsl:with-param name="property" select="$farentity/adl:key/adl:property[position()=1]"/>
-          </xsl:call-template> NOT NULL
-        )
-
-        GO
-          <xsl:text>
-            
-          </xsl:text>
-        ----  permissions  ------------------------------------------------------------------------------
-        <!-- only two levels of permission really matter for a link table. If you can read both of the 
-        parent tables, then you can read the link table. If you can edit either of the parent tables, 
-        then you need full CRUD permissions on the link table. Otherwise, you get nothing. -->
-        <xsl:for-each select="//adl:group">
-          <xsl:variable name="groupname" select="@name"/>
-            <xsl:choose>
-              <xsl:when test="//adl:entity[@name=$nearside]/adl:permission[@group=$groupname and @permission='all']">
-        GRANT SELECT,INSERT,UPDATE,DELETE ON "<xsl:value-of select="$linktablename"/>" TO "<xsl:value-of select="$groupname"/>" 
-              </xsl:when>
-              <xsl:when test="//adl:entity[@name=$nearside]/adl:permission[@group=$groupname and @permission='edit']">
-		GRANT SELECT,INSERT,UPDATE,DELETE ON "<xsl:value-of select="$linktablename"/>" TO "<xsl:value-of select="$groupname"/>"
-			  </xsl:when>
-              <xsl:when test="//adl:entity[@name=$farside]/adl:permission[@group=$groupname and @permission='all']">
-		GRANT SELECT,INSERT,UPDATE,DELETE ON "<xsl:value-of select="$linktablename"/>" TO "<xsl:value-of select="$groupname"/>"
-			  </xsl:when>
-              <xsl:when test="//adl:entity[@name=$farside]/adl:permission[@group=$groupname and @permission='edit']">
-		GRANT SELECT,INSERT,UPDATE,DELETE ON "<xsl:value-of select="$linktablename"/>" TO "<xsl:value-of select="$groupname"/>"
-			  </xsl:when>
-              <xsl:when test="//adl:entity[@name=$nearside]/adl:permission[@group=$groupname and @permission='none']">
-		REVOKE ALL ON "<xsl:value-of select="$linktablename"/>" FROM "<xsl:value-of select="$groupname"/>"
-			  </xsl:when>
-              <xsl:when test="//adl:entity[@name=$farside]/adl:permission[@group=$groupname and @permission='none']">
-		REVOKE ALL ON "<xsl:value-of select="$linktablename"/>" FROM "<xsl:value-of select="$groupname"/>"
-			  </xsl:when>
-              <xsl:otherwise>
-        GRANT SELECT ON <xsl:value-of select="$linktablename"/> TO <xsl:value-of select="$groupname"/>
-              </xsl:otherwise>
-            </xsl:choose>
-        GO
-          </xsl:for-each>
-          
-        ----  referential integrity  --------------------------------------------------------------------
-        
-          <xsl:variable name="neartable">
-            <xsl:call-template name="tablename">
-              <xsl:with-param name="entityname" select="$nearside"/>
-            </xsl:call-template>
-          </xsl:variable>
-          <xsl:variable name="fartable">
-            <xsl:call-template name="tablename">
-              <xsl:with-param name="entityname" select="$farentityname"/>
-            </xsl:call-template>
-          </xsl:variable>
-
-          <xsl:choose>
-            <xsl:when test="$nearside=@entity">
-              <xsl:call-template name="foreignkey">
-                <xsl:with-param name="nearside" select="$linktablename"/>
-                <xsl:with-param name="farside" select="$neartable"/>
-                <xsl:with-param name="linkfield" select="concat( $nearside, $linksuffix)"/>
-                <xsl:with-param name="ondelete" select="'NO ACTION'"/>
-              </xsl:call-template>
-              <xsl:call-template name="foreignkey">
-                <xsl:with-param name="nearside" select="$linktablename"/>
-                <xsl:with-param name="farside" select="$fartable"/>
-                <xsl:with-param name="linkfield" select="concat( $farside, $linksuffix)"/>
-                <xsl:with-param name="ondelete" select="'CASCADE'"/>
-              </xsl:call-template>
-            </xsl:when>
-            <xsl:otherwise>
-              <xsl:call-template name="foreignkey">
-                <xsl:with-param name="nearside" select="$linktablename"/>
-                <xsl:with-param name="farside" select="$neartable"/>
-                <xsl:with-param name="linkfield" select="concat( $nearside, $linksuffix)"/>
-                <xsl:with-param name="ondelete" select="'CASCADE'"/>
-              </xsl:call-template>
-              <xsl:call-template name="foreignkey">
-                <xsl:with-param name="nearside" select="$linktablename"/>
-                <xsl:with-param name="farside" select="$fartable"/>
-                <xsl:with-param name="linkfield" select="concat( @entity, $linksuffix)"/>
-                <xsl:with-param name="ondelete" select="'CASCADE'"/>
-              </xsl:call-template>
-            </xsl:otherwise>
-          </xsl:choose>
-        </xsl:when>
-        <xsl:otherwise>
-        -- Suppressing generation of <xsl:value-of select="$linktablename"/>, as it is not my responsibility
-        </xsl:otherwise>
-      </xsl:choose>
-      <xsl:if test="myresponsibility='true'">
-      </xsl:if>
-    </xsl:template>
-  
-  <xsl:template match="adl:property[@type='list']">
-        -- Suppressing output of property <xsl:value-of select="@name"/>,
-        -- as it is the 'one' end of a one-to-many relationship
-  </xsl:template>
-
-  <xsl:template match="adl:generator[@action='native']">
-    IDENTITY( 1, 1)
-  </xsl:template>
-  <xsl:template match="adl:generator"/>
-
-  <!-- the grand unified property handler, using the sql-type template to 
-  generate the correct types for each field -->
-  <xsl:template match="adl:property">
-    <xsl:variable name="column">
-      <xsl:call-template name="property-column-name">
-        <xsl:with-param name="property" select="."/>
-      </xsl:call-template>
-    </xsl:variable>
-    <xsl:variable name="type">
-      <xsl:call-template name="sql-type">
-        <xsl:with-param name="property" select="."/>
-      </xsl:call-template>
-    </xsl:variable>
-    <xsl:variable name="base-type">
-      <xsl:call-template name="base-type">
-        <xsl:with-param name="property" select="."/>
-      </xsl:call-template>
-    </xsl:variable>
-    <xsl:variable name="generator">
-      <xsl:apply-templates select="adl:generator"/>
-    </xsl:variable>
-          "<xsl:value-of select="$column"/>" <xsl:value-of 
-                select="concat( normalize-space( $type), ' ', normalize-space( $generator))"/><xsl:if
-                test="@required='true'"> NOT NULL</xsl:if><xsl:if
-            test="string(@default)"> DEFAULT <xsl:choose>
-              <xsl:when test="$base-type = 'integer' or $base-type = 'real' or $base-type = 'money'">
-                <xsl:value-of select="@default"/>
-              </xsl:when>
-				<xsl:when test="$base-type = 'boolean'">
-					<xsl:choose>
-						<xsl:when test="@default='true'">1</xsl:when>
-						<xsl:otherwise>0</xsl:otherwise>
-					</xsl:choose>
-				</xsl:when>
-              <xsl:otherwise>'<xsl:value-of select="@default"/>'</xsl:otherwise>
-            </xsl:choose>
-    </xsl:if>
-
-  </xsl:template>
-  
-  <!-- properties of type 'entity' are supposed to be being handled by the 
-  grand unified property handler. Unfortunately it gets them wrong and I'm not 
-  sure why. So temporarily this special case template fixes the problem. TODO: 
-  work out what's wrong with the grand unified version -->
-  <xsl:template match="adl:property[@type='entity']">
-    <xsl:variable name="column">
-      <xsl:call-template name="property-column-name">
-        <xsl:with-param name="property" select="."/>
-      </xsl:call-template>
-    </xsl:variable>
-    <xsl:variable name="type">
-      <xsl:call-template name="sql-type">
-        <xsl:with-param name="property" select="."/>
-      </xsl:call-template>
-    </xsl:variable>
-          "<xsl:value-of select="$column"/>" <xsl:value-of select="$type"/><xsl:if 
-            test="string(@default)"> DEFAULT <xsl:value-of select="@default"/></xsl:if><xsl:if 
-                test="@required='true'"> NOT NULL</xsl:if>
-  </xsl:template>
-
-
-  <!-- consistent, repeatable way of getting the column name for a given property -->
-  <xsl:template name="property-column-name">
-    <!-- a property element -->
-    <xsl:param name="property"/>
-    <xsl:variable name="unescaped">
-    <xsl:choose>
-      <xsl:when test="$property/@column">
-        <xsl:value-of select="$property/@column"/>
-      </xsl:when>
-      <xsl:otherwise>
-        <xsl:value-of select="$property/@name"/>
-      </xsl:otherwise>
-    </xsl:choose>
-    </xsl:variable>
-    <xsl:choose>
-      <xsl:when test="contains( $sqlkeywords, concat(' ', translate( $unescaped, $lcase, $ucase),' '))">
-		  <!--
-			names which are keywords need to be escaped /either/ with square
-			brackets /or/ with quotes, but currently we're using quotes for all names
-			so don't need square brackets.
-			xsl:value-of select="concat( '[', $unescaped, ']')"/ -->
-		  <xsl:value-of select="$unescaped"/>
-      </xsl:when>
-      <xsl:otherwise>
-        <xsl:value-of select="$unescaped"/>
-      </xsl:otherwise>
-    </xsl:choose>
-  </xsl:template>
-
-  <xsl:template name="primary-key-name">
-    <xsl:param name="entityname"/>
-    <xsl:choose>
-      <xsl:when test="//adl:entity[@name=$entityname]/@natural-key">
-        <xsl:value-of select="//adl:entity[@name=$entityname]/@natural-key"/>
-      </xsl:when>
-      <xsl:when test="//adl:entity[@name=$entityname]/key">
-        <xsl:choose>
-          <xsl:when test="count(//adl:entity[@name=$entityname]/adl:key/adl:property) &gt; 1">
-            <xsl:message terminate="no">
-              ADL: WARNING: entity '<xsl:value-of select="$entityname"/>' has a compound primary key;
-              adl2mssql is not yet clever enough to generate appropriate code
-            </xsl:message>
-          </xsl:when>
-          <xsl:otherwise>
-            <xsl:value-of select="//adl:entity[@name=$entityname]/adl:key/adl:property[position()=1]"/>
-          </xsl:otherwise>
-        </xsl:choose>
-      </xsl:when>
-      <xsl:otherwise>
-        <xsl:choose>
-          <xsl:when test="$abstract-key-name-convention='Name'">
-            <xsl:value-of select="@name"/>
-          </xsl:when>
-          <xsl:when test="$abstract-key-name-convention = 'NameId'">
-            <xsl:value-of select="concat( $entityname, 'Id')"/>
-          </xsl:when>
-          <xsl:when test="$abstract-key-name-convention = 'Name_Id'">
-            <xsl:value-of select="concat( $entityname, '_Id')"/>
-          </xsl:when>
-          <xsl:otherwise>
-            <xsl:value-of select="'Id'"/>
-          </xsl:otherwise>
-        </xsl:choose>
-      </xsl:otherwise>
-    </xsl:choose>
-  </xsl:template>
-
-  <!-- return the SQL type of the property which is passed as a parameter -->
-  <xsl:template name="sql-type">
-    <xsl:param name="property"/>
-    <xsl:variable name="base-type">
-      <xsl:call-template name="base-type">
-        <xsl:with-param name="property" select="$property"/>
-      </xsl:call-template>
-    </xsl:variable>
-    <xsl:variable name="base-size">
-      <xsl:call-template name="base-size">
-        <xsl:with-param name="property" select="$property"/>
-      </xsl:call-template>
-    </xsl:variable>
-    <xsl:choose>
-      <xsl:when test="$base-type = 'entity'">
-        <xsl:variable name="entity" select="$property/@entity"/>
-        <xsl:choose>
-          <xsl:when test="//adl:entity[@name=$entity]">
-            <xsl:choose>
-              <xsl:when test="//adl:entity[@name=$entity]/adl:key/adl:property">
-                <xsl:call-template name="sql-type">
-                  <xsl:with-param name="property"
-                                  select="//adl:entity[@name=$entity]/adl:key/adl:property[position()=1]"/>
-                </xsl:call-template>
-              </xsl:when>
-              <xsl:otherwise>
-                <xsl:message terminate="yes">
-                  ADL: ERROR: property '<xsl:value-of select="$property/@name"/>' refers to
-                  entity '<xsl:value-of select="$property/@entity"/>', but this entity has no key.
-                </xsl:message>
-              </xsl:otherwise>
-            </xsl:choose>
-          </xsl:when>
-          <xsl:otherwise>
-            <xsl:message terminate="yes">
-              ADL: ERROR: property '<xsl:value-of select="$property/@name"/>' refers to 
-              entity '<xsl:value-of select="$property/@entity"/>', but no such entity exists.
-            </xsl:message>
-          </xsl:otherwise>
-        </xsl:choose>
-      </xsl:when>
-      <xsl:when test="$base-type = 'date'">DATETIME</xsl:when>
-      <xsl:when test="$base-type = 'time'">DATETIME</xsl:when>
-      <!-- TODO: if the type was 'defined' then the size should probably come from the typedef -->
-      <xsl:when test="$base-type = 'string'">VARCHAR( <xsl:value-of select="$base-size"/>)</xsl:when>
-      <xsl:when test="$base-type = 'text'">TEXT</xsl:when>
-      <xsl:when test="$base-type = 'boolean'">BIT</xsl:when>
-      <xsl:when test="$base-type = 'timestamp'">DATETIME</xsl:when>
-      <xsl:when test="$base-type = 'integer'">INT</xsl:when>
-      <xsl:when test="$base-type = 'real'">DOUBLE PRECISION</xsl:when>
-      <xsl:when test="$base-type = 'money'">DECIMAL( 16, 2)</xsl:when>
-      <xsl:otherwise>[sql:unknown? [<xsl:value-of select="$base-type"/>]]</xsl:otherwise>
-    </xsl:choose>
-
-  </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>
+<?xml version="1.0"?>
+<xsl:stylesheet version="1.0" 
+  xmlns="http://libs.cygnets.co.uk/adl/1.4/" 
+  xmlns:adl="http://libs.cygnets.co.uk/adl/1.4/"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+  <!--
+      Application Description Language framework
+      adl2mssql.xsl
+      
+      (c) 2007 Cygnet Solutions Ltd
+      
+      Convert ADL to MS-SQL
+      
+      $Author: simon $
+      $Revision: 1.21 $
+  -->
+    
+  <xsl:output indent="no" encoding="UTF-8" method="text"/>
+  <xsl:include href="base-type-include.xslt"/>
+
+  <!-- 
+      The convention to use for naming auto-generated abstract primary keys. Known values are
+      Id - the autogenerated primary key, if any, is called just 'Id'
+      Name - the autogenerated primary key has the same name as the entity
+      NameId - the name of the auto generated primary key is the name of the entity followed by 'Id'
+      Name_Id - the name of the auto generated primary key is the name of the entity followed by '_Id'  
+    -->
+  <xsl:param name="abstract-key-name-convention" select="Id"/>
+
+	<!-- the convention to use for fieldnames in link tables:
+		Name - the name of the foreign key is the same as the name of the table linked to
+		NameId - the name of the foreign key is the same as the name of the table linked to, followed by 'Id'
+		Name_Id - the name of the foreign key is the same as the name of the table linked to, followed by '_Id'
+		Name_Link  - the name of the foreign key is the same as the name of the table linked to, followed by '_Link'
+	-->
+	<xsl:param name="linktable-field-name-convention" select="Name"/>
+	
+  <xsl:param name="database"/>
+	<!-- the name and version of the product being built -->
+	<xsl:param name="product-version" select="'Application Description Language Framework'"/>
+
+	<!-- define upper and lower case letters to enable case conversion -->
+  <xsl:variable name="ucase">ABCDEFGHIJKLMNOPQRSTUVWXYZ</xsl:variable>
+  <xsl:variable name="lcase">abcdefghijklmnopqrstuvwxyz</xsl:variable>
+  <!-- define SQL keywords to police these out of field names -->
+  <xsl:variable name="sqlkeywords-multiline">
+	  ADD 				EXCEPT 				PERCENT
+	  ALL 				EXEC 				PLAN
+	  ALTER 				EXECUTE				PRECISION
+	  AND 				EXISTS 				PRIMARY
+	  ANY 				EXIT 				PRINT
+	  AS 					FETCH 				PROC
+	  ASC 				FILE 				PROCEDURE
+	  AUTHORIZATION 		FILLFACTOR 			PUBLIC
+	  BACKUP 				FOR 				RAISERROR
+	  BEGIN 				FOREIGN 			READ
+	  BETWEEN 			FREETEXT 			READTEXT
+	  BREAK 				FREETEXTTABLE 		RECONFIGURE
+	  BROWSE 				FROM 				REFERENCES
+	  BULK 				FULL 				REPLICATION
+	  BY 					FUNCTION 			RESTORE
+	  CASCADE 			GOTO 				RESTRICT
+	  CASE 				GRANT 				RETURN
+	  CHECK 				GROUP 				REVOKE
+	  CHECKPOINT 			HAVING 				RIGHT
+	  CLOSE 				HOLDLOCK		 	ROLLBACK
+	  CLUSTERED 			IDENTITY		 	ROWCOUNT
+	  COALESCE 			IDENTITY_INSERT 	ROWGUIDCOL
+	  COLLATE 			IDENTITYCOL		 	RULE
+	  COLUMN 				IF 					SAVE
+	  COMMIT 				IN 					SCHEMA
+	  COMPUTE 			INDEX			 	SELECT
+	  CONSTRAINT 			INNER 				SESSION_USER
+	  CONTAINS 			INSERT 				SET
+	  CONTAINSTABLE 		INTERSECT		 	SETUSER
+	  CONTINUE 			INTO 				SHUTDOWN
+	  CONVERT 			IS 					SOME
+	  CREATE 				JOIN			 	STATISTICS
+	  CROSS 				KEY					SYSTEM_USER
+	  CURRENT 			KILL			 	TABLE
+	  CURRENT_DATE 		LEFT			 	TEXTSIZE
+	  CURRENT_TIME 		LIKE			 	THEN
+	  CURRENT_TIMESTAMP 	LINENO				TO
+	  CURRENT_USER 		LOAD 				TOP
+	  CURSOR 				NATIONAL 			TRAN
+	  DATABASE 			NOCHECK 			TRANSACTION
+	  DBCC 				NONCLUSTERED 		TRIGGER
+	  DEALLOCATE 			NOT 				TRUNCATE
+	  DECLARE 			NULL 				TSEQUAL
+	  DEFAULT 			NULLIF 				UNION
+	  DELETE 				OF 					UNIQUE
+	  DENY 				OFF 				UPDATE
+	  DESC 				OFFSETS				UPDATETEXT
+	  DISK 				ON 					USE
+	  DISTINCT	 		OPEN 				USER
+	  DISTRIBUTED 		OPENDATASOURCE 		VALUES
+	  DOUBLE 				OPENQUERY 			VARYING
+	  DROP 				OPENROWSET 			VIEW
+	  DUMMY 				OPENXML 			WAITFOR
+	  DUMP 				OPTION 				WHEN
+	  ELSE 				OR 					WHERE
+	  END 				ORDER 				WHILE
+	  ERRLVL 				OUTER				WITH
+	  ESCAPE 				OVER				WRITETEXT
+  </xsl:variable>
+  <xsl:variable name="sqlkeywords" select="concat(' ', normalize-space($sqlkeywords-multiline), ' ')"/>
+
+
+  <xsl:template match="adl:application"> 
+        -------------------------------------------------------------------------------------------------
+        --
+        --    <xsl:value-of select="$product-version"/>
+        --
+        --    Database for application <xsl:value-of select="@name"/> version <xsl:value-of select="@version"/>
+        --    Generated for MS-SQL 2000+ using adl2mssql.xslt <xsl:value-of select="substring('$Revision: 1.21 $', 12)"/>
+	    --    THIS FILE IS AUTOMATICALLY GENERATED: DO NOT EDIT IT.
+		--
+		--    <xsl:value-of select="@revision"/>
+        --
+        --    Code generator (c) 2007 Cygnet Solutions Ltd
+        --
+        -------------------------------------------------------------------------------------------------
+
+    <xsl:if test="string-length( $database) &gt; 0">
+      use "<xsl:value-of select="$database"/>";
+    </xsl:if>
+
+        -------------------------------------------------------------------------------------------------
+        --    authentication roles
+        -------------------------------------------------------------------------------------------------
+    <xsl:apply-templates select="adl:group"/>
+
+	  -------------------------------------------------------------------------------------------------
+	  --	magic view for role membership, used in establishing security credentials
+	  -------------------------------------------------------------------------------------------------
+	  CREATE VIEW RoleMembership AS
+		 SELECT dbuser.name as "dbuser", 
+				dbrole.name as "dbrole"
+		   FROM sysusers AS dbuser, sysmembers, sysusers AS dbrole
+		  WHERE dbuser.uid = sysmembers.memberuid
+			AND dbrole.uid = sysmembers.groupuid
+	  GO
+			
+	  GRANT SELECT on RoleMembership to public
+	  GO
+
+	  -------------------------------------------------------------------------------------------------
+	  --    primary tables, views and permissions
+	  -------------------------------------------------------------------------------------------------
+	  <xsl:apply-templates select="adl:entity" mode="table"/>
+
+        -------------------------------------------------------------------------------------------------
+        --    link tables  
+        -------------------------------------------------------------------------------------------------
+    <xsl:apply-templates select="adl:entity" mode="links"/>
+
+        -------------------------------------------------------------------------------------------------
+        --    primary referential integrity constraints
+        -------------------------------------------------------------------------------------------------
+    <xsl:apply-templates select="adl:entity" mode="refinteg"/>
+      
+        -------------------------------------------------------------------------------------------------
+        --    end of file
+        -------------------------------------------------------------------------------------------------
+  </xsl:template>
+
+	<xsl:template match="adl:documentation">
+		/*    <xsl:apply-templates/> */
+	</xsl:template>
+	
+  <xsl:template match="adl:group">
+		-------------------------------------------------------------------------------------------------
+		--    security group <xsl:value-of select="@name"/>
+		-------------------------------------------------------------------------------------------------
+	  <xsl:apply-templates select="adl:documentation"/>
+		execute sp_addrole @rolename = '<xsl:value-of select="@name"/>'
+		GO
+  </xsl:template>
+
+  <!-- return the table name for the entity with this entity name -->
+  <xsl:template name="tablename">
+    <xsl:param name="entityname"/>
+    <xsl:choose>
+      <xsl:when test="//adl:entity[@name=$entityname]/@table">
+        <xsl:value-of select="//adl:entity[@name=$entityname]/@table"/>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:value-of select="$entityname"/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  
+  <!-- generate a foreign key referential integrity check -->
+  <xsl:template name="foreignkey">
+    <xsl:param name="nearside"/>
+    <xsl:param name="farside"/>
+    <xsl:param name="linkfield"/>
+    <xsl:param name="ondelete" select="'NO ACTION'"/>
+
+    <xsl:variable name="neartable">
+      <xsl:call-template name="tablename">
+        <xsl:with-param name="entityname" select="$nearside"/>
+      </xsl:call-template>
+    </xsl:variable>
+    
+    <xsl:variable name="fartable">
+      <xsl:call-template name="tablename">
+        <xsl:with-param name="entityname" select="$farside"/>
+      </xsl:call-template>
+    </xsl:variable>
+    
+    <!-- set up referential integrity constraints for primary tables -->
+        ALTER TABLE "<xsl:value-of select="$neartable"/>"
+            ADD FOREIGN KEY ( "<xsl:value-of select="$linkfield"/>") 
+            REFERENCES "<xsl:value-of select="$fartable"/>" ON DELETE <xsl:value-of select="$ondelete"/>
+            
+        GO
+  </xsl:template>
+
+  <!-- generate referential integrity constraints -->
+  <!-- there's a sort-of problem with this - if we have properties at both 
+	ends of a link (which we often do) we currently generate two identical 
+	constraints. This doesn't seem to cause any major problems but must hurt 
+	efficiency. It would be better if we fixed this. -->
+  <xsl:template match="adl:entity" mode="refinteg">
+    <xsl:variable name="nearside" select="@name"/>
+    <xsl:for-each select="descendant::adl:property[@type='entity']">
+      <xsl:variable name="farside" select="@entity"/>
+      <xsl:variable name="keyfield">
+        <xsl:call-template name="property-column-name">
+          <xsl:with-param name="property" select="."/>
+        </xsl:call-template>
+      </xsl:variable>
+      <xsl:choose>
+        <xsl:when test="//adl:entity[@name=$farside]//adl:property[@farkey=$keyfield and @entity=$nearside]">
+          <!-- there's a 'list' property pointing the other way; let it do the heavy hauling -->
+			<!-- list with farkey -->
+        </xsl:when>
+		  <xsl:when test="//adl:entity[@name=$farside]//adl:property[@entity=$nearside and not( @farkey)]">
+			  <!-- there's a 'list' property pointing the other way; let it do the heavy hauling -->
+			  <!-- list with no farkey -->
+		  </xsl:when>
+		  <xsl:otherwise>
+          <xsl:call-template name="foreignkey">
+            <xsl:with-param name="nearside" select="$nearside"/>
+            <xsl:with-param name="farside" select="$farside"/>
+            <xsl:with-param name="linkfield" select="$keyfield"/>
+          </xsl:call-template>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:for-each>
+    <xsl:for-each select="descendant::adl:property[@type='list']">
+		<xsl:variable name="ns2" select="@entity"/>
+		<xsl:variable name="linkfield">
+			<xsl:call-template name="property-column-name">
+				<xsl:with-param name="property" 
+								select="//adl:entity[@name=$ns2]//adl:property[@entity=$nearside]"/>
+			</xsl:call-template>
+		</xsl:variable>
+		<xsl:if test="string-length( $linkfield) = 0">
+			<xsl:message terminate="yes">
+				ADL: ERROR: Failed to infer link field name whilst processing list property <xsl:value-of select="@name"/> of <xsl:value-of select="ancestor::adl:entity/@name"/>
+ Entity is '<xsl:value-of select="$ns2"/>', nearside is '<xsl:value-of select="$nearside"/>'
+			</xsl:message>
+		</xsl:if>
+      <xsl:call-template name="foreignkey">
+        <xsl:with-param name="nearside" select="@entity"/>
+        <xsl:with-param name="farside" select="../@name"/>
+        <xsl:with-param name="linkfield" select="$linkfield"/>
+        <xsl:with-param name="ondelete">
+          <xsl:choose>
+            <xsl:when test="@cascade='all'">CASCADE</xsl:when>
+            <xsl:when test="@cascade='all-delete-orphan'">CASCADE</xsl:when>
+            <xsl:when test="@cascade='delete'">CASCADE</xsl:when>
+            <xsl:otherwise>NO ACTION</xsl:otherwise>
+          </xsl:choose>
+        </xsl:with-param>
+      </xsl:call-template>
+    </xsl:for-each>
+  </xsl:template>
+  
+  
+  <!-- don't generate foreign tables - although we will generate ref integ constraints for them -->
+  <xsl:template match="adl:entity[@foreign='true']" mode="table"/> 
+
+  <xsl:template match="adl:entity" mode="table">
+	  <!-- the name of the entity we're generating -->
+	  <xsl:variable name="entityname" select="@name"/>
+	  <!-- the name of the table to generate -->
+	  <xsl:variable name="table">
+		  <xsl:call-template name="tablename">
+			  <xsl:with-param name="entityname" select="@name"/>
+		  </xsl:call-template>
+	  </xsl:variable>
+	  <!-- the entity we are generating -->
+	  <xsl:variable name="generating-entity" select="."/>
+
+		-------------------------------------------------------------------------------------------------
+		--    primary table <xsl:value-of select="$table"/>
+        -------------------------------------------------------------------------------------------------
+ 	  <xsl:apply-templates select="adl:documentation"/>
+		CREATE TABLE  "<xsl:value-of select="$table"/>"
+		(
+	  <xsl:for-each select="descendant::adl:property[not( @type='link' or @type = 'list' or @concrete='false')]">
+		  <xsl:apply-templates select="."/>
+		  <xsl:if test="position() != last()">,</xsl:if>
+	  </xsl:for-each>
+	  <xsl:for-each select="//adl:property[@type='list' and @entity = $entityname]">
+		  <xsl:variable name="referringprop" select="."/>
+		  <xsl:choose>
+			  <xsl:when test="$generating-entity//adl:property[ @type='entity' and @entity=$referringprop/ancestor::adl:entity/@name]">
+				  <!-- if the entity for which I'm currently generating already has a specified property
+				  which links to this foreign entity, I don't have to dummy one up -->
+			  </xsl:when>
+			  <xsl:otherwise>
+				  <!-- dummy up the 'many' end of a one-to-many link -->
+				  , "<xsl:value-of select="ancestor::adl:entity/@name"/>"<xsl:text> </xsl:text><xsl:call-template name="sql-type">
+					  <xsl:with-param name="property" select="ancestor::adl:entity/adl:key/adl:property[position() = 1]"/>
+				  </xsl:call-template>
+			  </xsl:otherwise>
+		  </xsl:choose>
+	  </xsl:for-each>
+    <xsl:apply-templates select="adl:key"/>
+        )
+        GO
+
+        ----  permissions  ------------------------------------------------------------------------------
+    <xsl:for-each select="adl:permission">
+      <xsl:call-template name="permission">
+        <xsl:with-param name="entity" select="ancestor::adl:entity"/>
+      </xsl:call-template>
+    </xsl:for-each>
+
+  </xsl:template>
+
+  <xsl:template match="adl:key">
+    <xsl:if test="adl:property[not( @concrete='false')]">
+          , 
+          PRIMARY KEY( <xsl:for-each select="adl:property[not( @concrete='false')]">"<xsl:call-template name="property-column-name">
+            <xsl:with-param name="property" select="."/>
+          </xsl:call-template>"<xsl:if test="position() != last()">, </xsl:if></xsl:for-each>)
+    </xsl:if>
+  </xsl:template>
+
+  <xsl:template name="distinctfield">
+    <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>
+
+  <!-- fix up linking tables. Donoe after all primary tables have been created, 
+  because otherwise some links may fail -->
+  <xsl:template match="adl:entity" mode="links">
+    <xsl:variable name="entityname" select="@name"/>
+    <xsl:for-each select="adl:property[@type='link']">
+      <xsl:call-template name="linktable">
+        <xsl:with-param name="nearside" select="$entityname"/>
+      </xsl:call-template>
+    </xsl:for-each>
+  </xsl:template>
+
+  <xsl:template name="permission">
+    <xsl:param name="entity"/>
+    <!-- decode the permissions for a table -->
+    <xsl:variable name="table">
+      <xsl:call-template name="tablename">
+        <xsl:with-param name="entityname" select="$entity/@name"/>
+      </xsl:call-template>
+    </xsl:variable>
+    <xsl:choose>
+      <xsl:when test="@permission='read'">
+        GRANT SELECT ON "<xsl:value-of
+                select="$table"/>" TO "<xsl:value-of select="@group"/>"
+      </xsl:when>
+      <xsl:when test="@permission='insert'">
+        GRANT INSERT ON "<xsl:value-of
+                select="$table"/>" TO "<xsl:value-of select="@group"/>"
+      </xsl:when>
+      <xsl:when test="@permission='noedit'">
+        GRANT SELECT, INSERT ON "<xsl:value-of
+                select="$table"/>" TO "<xsl:value-of select="@group"/>"
+      </xsl:when>
+      <xsl:when test="@permission='edit'">
+        GRANT SELECT, INSERT, UPDATE ON "<xsl:value-of
+                select="$table"/>" TO "<xsl:value-of select="@group"/>"
+      </xsl:when>
+      <xsl:when test="@permission='all'">
+        GRANT SELECT, INSERT, UPDATE, DELETE ON "<xsl:value-of
+                select="$table"/>" TO "<xsl:value-of select="@group"/>"
+      </xsl:when>
+      <xsl:otherwise>
+        REVOKE ALL ON "<xsl:value-of
+                select="$table"/>" FROM "<xsl:value-of select="@group"/>"
+      </xsl:otherwise>
+    </xsl:choose>
+    <xsl:text>
+        GO
+        
+    </xsl:text>
+  </xsl:template>
+
+  <!-- expects to be called in the context of an entity; probably should make this explicit. 
+    TODO: this is a mess; refactor. -->
+  <xsl:template name="linktable">
+        <xsl:param name="nearside"/>
+      <!-- This is tricky. For any many-to-many relationship between two 
+      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="farentityname" select="@entity"/>
+      <xsl:variable name="farentity" select="//adl:entity[@name=$farentityname]"/>
+	  <xsl:variable name="linksuffix">
+		  <xsl:choose>
+			  <xsl:when test="$linktable-field-name-convention = 'Name'"/>
+			  <xsl:when test="$linktable-field-name-convention = 'NameId'">
+				  <xsl:value-of select="'Id'"/>
+			  </xsl:when>
+			  <xsl:when test="$linktable-field-name-convention = 'Name_Id'">
+				  <xsl:value-of select="'_Id'"/>
+			  </xsl:when>
+			  <xsl:when test="$linktable-field-name-convention = 'NameLink'">
+				  <xsl:value-of select="'Link'"/>
+			  </xsl:when>
+			  <xsl:when test="$linktable-field-name-convention = 'Name_Link'">
+				  <xsl:value-of select="'_Link'"/>
+			  </xsl:when>
+		  </xsl:choose>
+	  </xsl:variable>
+
+	  <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/adl:property[@type='link' and @entity=$nearside]">false</xsl:when>
+              <xsl:otherwise>true</xsl:otherwise>
+            </xsl:choose>
+          </xsl:when>
+          <xsl:otherwise>false</xsl:otherwise>
+        </xsl:choose>
+      </xsl:variable>
+      <!-- Problems with responsibility for generating link tables: -->
+        -- Problems with responsibility for generating link tables:
+        -- @entity = <xsl:value-of select="@entity"/>
+        -- $nearside = <xsl:value-of select="$nearside"/>
+        -- $farside = <xsl:value-of select="$farside"/>
+        -- farlink = <xsl:value-of select="$farentity/adl:property[@type='link' and @entity=$nearside]/@name"/>
+        -- comparison = '<xsl:value-of select="$comparison"/>' 
+        -- my responsibility = <xsl:value-of select="$myresponsibility"/>
+      <xsl:variable name="linktablename">
+        <xsl:choose>
+          <xsl:when test="$comparison =-1">
+            <xsl:value-of select="concat( 'LN_', $nearside, '_', @entity)"/>
+          </xsl:when>
+          <xsl:otherwise>
+            <xsl:value-of select="concat( 'LN_', @entity, '_', $nearside)"/>
+          </xsl:otherwise>
+        </xsl:choose>
+      </xsl:variable>
+      <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="$linktablename"/>"
+        (
+          "<xsl:value-of select="concat( $nearside, $linksuffix)"/>" <xsl:call-template name="sql-type">
+            <xsl:with-param name="property" select="//adl:entity[@name=$nearside]/adl:key/adl:property[position()=1]"/>
+          </xsl:call-template> NOT NULL,
+          "<xsl:value-of select="concat( $farside, $linksuffix)"/>" <xsl:call-template name="sql-type">
+          <xsl:with-param name="property" select="$farentity/adl:key/adl:property[position()=1]"/>
+          </xsl:call-template> NOT NULL
+        )
+
+        GO
+          <xsl:text>
+            
+          </xsl:text>
+        ----  permissions  ------------------------------------------------------------------------------
+        <!-- only two levels of permission really matter for a link table. If you can read both of the 
+        parent tables, then you can read the link table. If you can edit either of the parent tables, 
+        then you need full CRUD permissions on the link table. Otherwise, you get nothing. -->
+        <xsl:for-each select="//adl:group">
+          <xsl:variable name="groupname" select="@name"/>
+            <xsl:choose>
+              <xsl:when test="//adl:entity[@name=$nearside]/adl:permission[@group=$groupname and @permission='all']">
+        GRANT SELECT,INSERT,UPDATE,DELETE ON "<xsl:value-of select="$linktablename"/>" TO "<xsl:value-of select="$groupname"/>" 
+              </xsl:when>
+              <xsl:when test="//adl:entity[@name=$nearside]/adl:permission[@group=$groupname and @permission='edit']">
+		GRANT SELECT,INSERT,UPDATE,DELETE ON "<xsl:value-of select="$linktablename"/>" TO "<xsl:value-of select="$groupname"/>"
+			  </xsl:when>
+              <xsl:when test="//adl:entity[@name=$farside]/adl:permission[@group=$groupname and @permission='all']">
+		GRANT SELECT,INSERT,UPDATE,DELETE ON "<xsl:value-of select="$linktablename"/>" TO "<xsl:value-of select="$groupname"/>"
+			  </xsl:when>
+              <xsl:when test="//adl:entity[@name=$farside]/adl:permission[@group=$groupname and @permission='edit']">
+		GRANT SELECT,INSERT,UPDATE,DELETE ON "<xsl:value-of select="$linktablename"/>" TO "<xsl:value-of select="$groupname"/>"
+			  </xsl:when>
+              <xsl:when test="//adl:entity[@name=$nearside]/adl:permission[@group=$groupname and @permission='none']">
+		REVOKE ALL ON "<xsl:value-of select="$linktablename"/>" FROM "<xsl:value-of select="$groupname"/>"
+			  </xsl:when>
+              <xsl:when test="//adl:entity[@name=$farside]/adl:permission[@group=$groupname and @permission='none']">
+		REVOKE ALL ON "<xsl:value-of select="$linktablename"/>" FROM "<xsl:value-of select="$groupname"/>"
+			  </xsl:when>
+              <xsl:otherwise>
+        GRANT SELECT ON <xsl:value-of select="$linktablename"/> TO <xsl:value-of select="$groupname"/>
+              </xsl:otherwise>
+            </xsl:choose>
+        GO
+          </xsl:for-each>
+          
+        ----  referential integrity  --------------------------------------------------------------------
+        
+          <xsl:variable name="neartable">
+            <xsl:call-template name="tablename">
+              <xsl:with-param name="entityname" select="$nearside"/>
+            </xsl:call-template>
+          </xsl:variable>
+          <xsl:variable name="fartable">
+            <xsl:call-template name="tablename">
+              <xsl:with-param name="entityname" select="$farentityname"/>
+            </xsl:call-template>
+          </xsl:variable>
+
+          <xsl:choose>
+            <xsl:when test="$nearside=@entity">
+              <xsl:call-template name="foreignkey">
+                <xsl:with-param name="nearside" select="$linktablename"/>
+                <xsl:with-param name="farside" select="$neartable"/>
+                <xsl:with-param name="linkfield" select="concat( $nearside, $linksuffix)"/>
+                <xsl:with-param name="ondelete" select="'NO ACTION'"/>
+              </xsl:call-template>
+              <xsl:call-template name="foreignkey">
+                <xsl:with-param name="nearside" select="$linktablename"/>
+                <xsl:with-param name="farside" select="$fartable"/>
+                <xsl:with-param name="linkfield" select="concat( $farside, $linksuffix)"/>
+                <xsl:with-param name="ondelete" select="'CASCADE'"/>
+              </xsl:call-template>
+            </xsl:when>
+            <xsl:otherwise>
+              <xsl:call-template name="foreignkey">
+                <xsl:with-param name="nearside" select="$linktablename"/>
+                <xsl:with-param name="farside" select="$neartable"/>
+                <xsl:with-param name="linkfield" select="concat( $nearside, $linksuffix)"/>
+                <xsl:with-param name="ondelete" select="'CASCADE'"/>
+              </xsl:call-template>
+              <xsl:call-template name="foreignkey">
+                <xsl:with-param name="nearside" select="$linktablename"/>
+                <xsl:with-param name="farside" select="$fartable"/>
+                <xsl:with-param name="linkfield" select="concat( @entity, $linksuffix)"/>
+                <xsl:with-param name="ondelete" select="'CASCADE'"/>
+              </xsl:call-template>
+            </xsl:otherwise>
+          </xsl:choose>
+        </xsl:when>
+        <xsl:otherwise>
+        -- Suppressing generation of <xsl:value-of select="$linktablename"/>, as it is not my responsibility
+        </xsl:otherwise>
+      </xsl:choose>
+      <xsl:if test="myresponsibility='true'">
+      </xsl:if>
+    </xsl:template>
+  
+  <xsl:template match="adl:property[@type='list']">
+        -- Suppressing output of property <xsl:value-of select="@name"/>,
+        -- as it is the 'one' end of a one-to-many relationship
+  </xsl:template>
+
+  <xsl:template match="adl:generator[@action='native']">
+    IDENTITY( 1, 1)
+  </xsl:template>
+  <xsl:template match="adl:generator"/>
+
+  <!-- the grand unified property handler, using the sql-type template to 
+  generate the correct types for each field -->
+  <xsl:template match="adl:property">
+    <xsl:variable name="column">
+      <xsl:call-template name="property-column-name">
+        <xsl:with-param name="property" select="."/>
+      </xsl:call-template>
+    </xsl:variable>
+    <xsl:variable name="type">
+      <xsl:call-template name="sql-type">
+        <xsl:with-param name="property" select="."/>
+      </xsl:call-template>
+    </xsl:variable>
+    <xsl:variable name="base-type">
+      <xsl:call-template name="base-type">
+        <xsl:with-param name="property" select="."/>
+      </xsl:call-template>
+    </xsl:variable>
+    <xsl:variable name="generator">
+      <xsl:apply-templates select="adl:generator"/>
+    </xsl:variable>
+          "<xsl:value-of select="$column"/>" <xsl:value-of 
+                select="concat( normalize-space( $type), ' ', normalize-space( $generator))"/><xsl:if
+                test="@required='true'"> NOT NULL</xsl:if><xsl:if
+            test="string(@default)"> DEFAULT <xsl:choose>
+              <xsl:when test="$base-type = 'integer' or $base-type = 'real' or $base-type = 'money'">
+                <xsl:value-of select="@default"/>
+              </xsl:when>
+				<xsl:when test="$base-type = 'boolean'">
+					<xsl:choose>
+						<xsl:when test="@default='true'">1</xsl:when>
+						<xsl:otherwise>0</xsl:otherwise>
+					</xsl:choose>
+				</xsl:when>
+              <xsl:otherwise>'<xsl:value-of select="@default"/>'</xsl:otherwise>
+            </xsl:choose>
+    </xsl:if>
+
+  </xsl:template>
+  
+  <!-- properties of type 'entity' are supposed to be being handled by the 
+  grand unified property handler. Unfortunately it gets them wrong and I'm not 
+  sure why. So temporarily this special case template fixes the problem. TODO: 
+  work out what's wrong with the grand unified version -->
+  <xsl:template match="adl:property[@type='entity']">
+    <xsl:variable name="column">
+      <xsl:call-template name="property-column-name">
+        <xsl:with-param name="property" select="."/>
+      </xsl:call-template>
+    </xsl:variable>
+    <xsl:variable name="type">
+      <xsl:call-template name="sql-type">
+        <xsl:with-param name="property" select="."/>
+      </xsl:call-template>
+    </xsl:variable>
+    <xsl:variable name="entity" select="@entity"/>
+    <xsl:variable name="defaulttype">
+      <xsl:call-template name="base-type">
+        <xsl:with-param name="property" 
+                        select="ancestor::adl:application/adl:entity[@name = $entity]/adl:key/adl:property[position() = 1]"/>
+      </xsl:call-template>
+    </xsl:variable>
+    <xsl:variable name="default">
+      <xsl:choose>
+        <xsl:when test="$defaulttype = 'string'">
+          '<xsl:value-of select="@default"/>'
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:value-of select="@default"/>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+          "<xsl:value-of select="$column"/>" <xsl:value-of select="$type"/><xsl:if 
+            test="string(@default)"> DEFAULT <xsl:value-of select="normalize-space($default)"/></xsl:if><xsl:if 
+                test="@required='true'"> NOT NULL</xsl:if>
+  </xsl:template>
+
+
+  <!-- consistent, repeatable way of getting the column name for a given property -->
+  <xsl:template name="property-column-name">
+    <!-- a property element -->
+    <xsl:param name="property"/>
+    <xsl:variable name="unescaped">
+    <xsl:choose>
+      <xsl:when test="$property/@column">
+        <xsl:value-of select="$property/@column"/>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:value-of select="$property/@name"/>
+      </xsl:otherwise>
+    </xsl:choose>
+    </xsl:variable>
+    <xsl:choose>
+      <xsl:when test="contains( $sqlkeywords, concat(' ', translate( $unescaped, $lcase, $ucase),' '))">
+		  <!--
+			names which are keywords need to be escaped /either/ with square
+			brackets /or/ with quotes, but currently we're using quotes for all names
+			so don't need square brackets.
+			xsl:value-of select="concat( '[', $unescaped, ']')"/ -->
+		  <xsl:value-of select="$unescaped"/>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:value-of select="$unescaped"/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template name="primary-key-name">
+    <xsl:param name="entityname"/>
+    <xsl:choose>
+      <xsl:when test="//adl:entity[@name=$entityname]/@natural-key">
+        <xsl:value-of select="//adl:entity[@name=$entityname]/@natural-key"/>
+      </xsl:when>
+      <xsl:when test="//adl:entity[@name=$entityname]/key">
+        <xsl:choose>
+          <xsl:when test="count(//adl:entity[@name=$entityname]/adl:key/adl:property) &gt; 1">
+            <xsl:message terminate="no">
+              ADL: WARNING: entity '<xsl:value-of select="$entityname"/>' has a compound primary key;
+              adl2mssql is not yet clever enough to generate appropriate code
+            </xsl:message>
+          </xsl:when>
+          <xsl:otherwise>
+            <xsl:value-of select="//adl:entity[@name=$entityname]/adl:key/adl:property[position()=1]"/>
+          </xsl:otherwise>
+        </xsl:choose>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:choose>
+          <xsl:when test="$abstract-key-name-convention='Name'">
+            <xsl:value-of select="@name"/>
+          </xsl:when>
+          <xsl:when test="$abstract-key-name-convention = 'NameId'">
+            <xsl:value-of select="concat( $entityname, 'Id')"/>
+          </xsl:when>
+          <xsl:when test="$abstract-key-name-convention = 'Name_Id'">
+            <xsl:value-of select="concat( $entityname, '_Id')"/>
+          </xsl:when>
+          <xsl:otherwise>
+            <xsl:value-of select="'Id'"/>
+          </xsl:otherwise>
+        </xsl:choose>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <!-- return the SQL type of the property which is passed as a parameter -->
+  <xsl:template name="sql-type">
+    <xsl:param name="property"/>
+    <xsl:variable name="base-type">
+      <xsl:call-template name="base-type">
+        <xsl:with-param name="property" select="$property"/>
+      </xsl:call-template>
+    </xsl:variable>
+    <xsl:variable name="base-size">
+      <xsl:call-template name="base-size">
+        <xsl:with-param name="property" select="$property"/>
+      </xsl:call-template>
+    </xsl:variable>
+    <xsl:choose>
+      <xsl:when test="$base-type = 'entity'">
+        <xsl:variable name="entity" select="$property/@entity"/>
+        <xsl:choose>
+          <xsl:when test="//adl:entity[@name=$entity]">
+            <xsl:choose>
+              <xsl:when test="//adl:entity[@name=$entity]/adl:key/adl:property">
+                <xsl:call-template name="sql-type">
+                  <xsl:with-param name="property"
+                                  select="//adl:entity[@name=$entity]/adl:key/adl:property[position()=1]"/>
+                </xsl:call-template>
+              </xsl:when>
+              <xsl:otherwise>
+                <xsl:message terminate="yes">
+                  ADL: ERROR: property '<xsl:value-of select="$property/@name"/>' refers to
+                  entity '<xsl:value-of select="$property/@entity"/>', but this entity has no key.
+                </xsl:message>
+              </xsl:otherwise>
+            </xsl:choose>
+          </xsl:when>
+          <xsl:otherwise>
+            <xsl:message terminate="yes">
+              ADL: ERROR: property '<xsl:value-of select="$property/@name"/>' refers to 
+              entity '<xsl:value-of select="$property/@entity"/>', but no such entity exists.
+            </xsl:message>
+          </xsl:otherwise>
+        </xsl:choose>
+      </xsl:when>
+      <xsl:when test="$base-type = 'date'">DATETIME</xsl:when>
+      <xsl:when test="$base-type = 'time'">DATETIME</xsl:when>
+      <!-- TODO: if the type was 'defined' then the size should probably come from the typedef -->
+      <xsl:when test="$base-type = 'string'">VARCHAR( <xsl:value-of select="$base-size"/>)</xsl:when>
+      <xsl:when test="$base-type = 'image'">VARCHAR( <xsl:value-of select="$base-size"/>)</xsl:when>
+      <xsl:when test="$base-type = 'text'">TEXT</xsl:when>
+      <xsl:when test="$base-type = 'boolean'">BIT</xsl:when>
+      <xsl:when test="$base-type = 'timestamp'">DATETIME</xsl:when>
+      <xsl:when test="$base-type = 'integer'">INT</xsl:when>
+      <xsl:when test="$base-type = 'real'">DOUBLE PRECISION</xsl:when>
+      <xsl:when test="$base-type = 'money'">DECIMAL( 16, 2)</xsl:when>
+      <xsl:otherwise>[sql:unknown? [<xsl:value-of select="$base-type"/>]]</xsl:otherwise>
+    </xsl:choose>
+
+  </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/transforms/adl2psql.xslt b/transforms/adl2psql.xslt
index 7044b31..7850ad9 100755
--- a/transforms/adl2psql.xslt
+++ b/transforms/adl2psql.xslt
@@ -1,5 +1,8 @@
 <?xml version="1.0"?>
-<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:stylesheet version="1.0" 
+  xmlns="http://bowyer.journeyman.cc/adl/1.4/" 
+  xmlns:adl="http://bowyer.journeyman.cc/adl/1.4/"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <!--  ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::  -->
     <!--						    											-->
     <!--	adl2psql.xsl			    										-->
@@ -18,7 +21,7 @@
     <!--
         JACQUARD 2 APPLICATION DESCRIPTION LANGUAGE FRAMEWORK
         
-        $Revision: 1.2 $
+        $Revision: 1.3 $
         
         NOTES:
         
@@ -35,41 +38,137 @@
         two removes (i.e. the 'distinguish' mechanism in ADL
     -->
     
-    <xsl:output indent="no" encoding="UTF-8" method="text"/>
-    
-    <xsl:template match="application"> 
+  <xsl:include href="base-type-include.xslt"/>
+
+  <!-- 
+      The convention to use for naming auto-generated abstract primary keys. Known values are
+      Id - the autogenerated primary key, if any, is called just 'Id'
+      Name - the autogenerated primary key has the same name as the entity
+      NameId - the name of the auto generated primary key is the name of the entity followed by 'Id'
+      Name_Id - the name of the auto generated primary key is the name of the entity followed by '_Id'  
+    -->
+  <xsl:param name="abstract-key-name-convention" select="Id"/>
+
+	<!-- the convention to use for fieldnames in link tables:
+		Name - the name of the foreign key is the same as the name of the table linked to
+		NameId - the name of the foreign key is the same as the name of the table linked to, followed by 'Id'
+		Name_Id - the name of the foreign key is the same as the name of the table linked to, followed by '_Id'
+		Name_Link  - the name of the foreign key is the same as the name of the table linked to, followed by '_Link'
+	-->
+	<xsl:param name="linktable-field-name-convention" select="Name"/>
+	
+  <xsl:param name="database"/>
+	<!-- the name and version of the product being built -->
+	<xsl:param name="product-version" select="'Application Description Language Framework'"/>
+
+	<!-- define upper and lower case letters to enable case conversion -->
+  <xsl:variable name="ucase">ABCDEFGHIJKLMNOPQRSTUVWXYZ</xsl:variable>
+  <xsl:variable name="lcase">abcdefghijklmnopqrstuvwxyz</xsl:variable>
+  <!-- define SQL keywords to police these out of field names -->
+  <xsl:variable name="sqlkeywords-multiline">
+	  ADD 				EXCEPT 				PERCENT
+	  ALL 				EXEC 				PLAN
+	  ALTER 				EXECUTE				PRECISION
+	  AND 				EXISTS 				PRIMARY
+	  ANY 				EXIT 				PRINT
+	  AS 					FETCH 				PROC
+	  ASC 				FILE 				PROCEDURE
+	  AUTHORIZATION 		FILLFACTOR 			PUBLIC
+	  BACKUP 				FOR 				RAISERROR
+	  BEGIN 				FOREIGN 			READ
+	  BETWEEN 			FREETEXT 			READTEXT
+	  BREAK 				FREETEXTTABLE 		RECONFIGURE
+	  BROWSE 				FROM 				REFERENCES
+	  BULK 				FULL 				REPLICATION
+	  BY 					FUNCTION 			RESTORE
+	  CASCADE 			GOTO 				RESTRICT
+	  CASE 				GRANT 				RETURN
+	  CHECK 				GROUP 				REVOKE
+	  CHECKPOINT 			HAVING 				RIGHT
+	  CLOSE 				HOLDLOCK		 	ROLLBACK
+	  CLUSTERED 			IDENTITY		 	ROWCOUNT
+	  COALESCE 			IDENTITY_INSERT 	ROWGUIDCOL
+	  COLLATE 			IDENTITYCOL		 	RULE
+	  COLUMN 				IF 					SAVE
+	  COMMIT 				IN 					SCHEMA
+	  COMPUTE 			INDEX			 	SELECT
+	  CONSTRAINT 			INNER 				SESSION_USER
+	  CONTAINS 			INSERT 				SET
+	  CONTAINSTABLE 		INTERSECT		 	SETUSER
+	  CONTINUE 			INTO 				SHUTDOWN
+	  CONVERT 			IS 					SOME
+	  CREATE 				JOIN			 	STATISTICS
+	  CROSS 				KEY					SYSTEM_USER
+	  CURRENT 			KILL			 	TABLE
+	  CURRENT_DATE 		LEFT			 	TEXTSIZE
+	  CURRENT_TIME 		LIKE			 	THEN
+	  CURRENT_TIMESTAMP 	LINENO				TO
+	  CURRENT_USER 		LOAD 				TOP
+	  CURSOR 				NATIONAL 			TRAN
+	  DATABASE 			NOCHECK 			TRANSACTION
+	  DBCC 				NONCLUSTERED 		TRIGGER
+	  DEALLOCATE 			NOT 				TRUNCATE
+	  DECLARE 			NULL 				TSEQUAL
+	  DEFAULT 			NULLIF 				UNION
+	  DELETE 				OF 					UNIQUE
+	  DENY 				OFF 				UPDATE
+	  DESC 				OFFSETS				UPDATETEXT
+	  DISK 				ON 					USE
+	  DISTINCT	 		OPEN 				USER
+	  DISTRIBUTED 		OPENDATASOURCE 		VALUES
+	  DOUBLE 				OPENQUERY 			VARYING
+	  DROP 				OPENROWSET 			VIEW
+	  DUMMY 				OPENXML 			WAITFOR
+	  DUMP 				OPTION 				WHEN
+	  ELSE 				OR 					WHERE
+	  END 				ORDER 				WHILE
+	  ERRLVL 				OUTER				WITH
+	  ESCAPE 				OVER				WRITETEXT
+  </xsl:variable>
+  <xsl:variable name="sqlkeywords" select="concat(' ', normalize-space($sqlkeywords-multiline), ' ')"/>
+
+
+  <xsl:template match="adl:application"> 
         -------------------------------------------------------------------------------------------------
         --
-        --    Database for application <xsl:value-of select="@name"/> version <xsl:value-of select="@version"/>
-        --    Generated for PostgreSQL [7|8] using adl2psql.xsl $Revision: 1.2 $
+        --    <xsl:value-of select="$product-version"/>
         --
+        --    Database for application <xsl:value-of select="@name"/> version <xsl:value-of select="@version"/>
+        --    Generated for PostgreSQL [7|8] using adl2psql.xsl $Revision: 1.3 $
+        --
+		--    <xsl:value-of select="@revision"/>
+ 		--
         --    Code generator (c) 2006 Simon Brooke [simon@weft.co.uk]
         --    http://www.weft.co.uk/library/jacquard/
         --
         -------------------------------------------------------------------------------------------------
 
+    <xsl:if test="string-length( $database) &gt; 0">
+        use "<xsl:value-of select="$database"/>";
+    </xsl:if>
+
         -------------------------------------------------------------------------------------------------
         --    authentication roles
         -------------------------------------------------------------------------------------------------
-        <xsl:apply-templates select="group"/>
+    <xsl:apply-templates select="adl:group"/>
 
         -------------------------------------------------------------------------------------------------
         --    tables, views and permissions
         -------------------------------------------------------------------------------------------------
-        <xsl:apply-templates select="entity"/>
+        <xsl:apply-templates select="adl:entity"/>
         
         -------------------------------------------------------------------------------------------------
         --    referential integrity constraints
         -------------------------------------------------------------------------------------------------
-        <xsl:for-each select="entity">
+        <xsl:for-each select="adl:entity">
             <xsl:variable name="nearside" select="@name"/>
-            <xsl:for-each select="property[@type='entity']">
+            <xsl:for-each select="adl: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:for-each select="adl:property[@type='link']">
                 <xsl:call-template name="linkintegrity">
                     <xsl:with-param name="nearside" select="$nearside"/>
                 </xsl:call-template>
@@ -81,7 +180,15 @@
         -------------------------------------------------------------------------------------------------
     </xsl:template>
     
-    <xsl:template match="group">
+    	<xsl:template match="adl:documentation">
+		/*    <xsl:apply-templates/> */
+	</xsl:template>
+	
+  	<xsl:template match="adl:group">
+		-------------------------------------------------------------------------------------------------
+		--    security group <xsl:value-of select="@name"/>
+		-------------------------------------------------------------------------------------------------
+	  	<xsl:apply-templates select="adl:documentation"/>
         CREATE GROUP <xsl:value-of select="@name"/>;
     </xsl:template>
     
@@ -108,7 +215,7 @@
     </xsl:template>
     
     
-    <xsl:template match="entity">
+    <xsl:template match="adl:entity">
          <xsl:variable name="table" select="@name"/>
          
         -------------------------------------------------------------------------------------------------
@@ -116,12 +223,17 @@
         -------------------------------------------------------------------------------------------------
         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
+        	<xsl:for-each select="descendant::adl:property[@type!='link']">
+        		<xsl:apply-templates select="."/><xsl:choose>
+        			<xsl:when test="position() = last()"/>
+        			<xsl:otherwise>,<xsl:text>
+        			</xsl:text></xsl:otherwise>
+        		</xsl:choose>
+        	</xsl:for-each>
         );
         
         ----  permissions  ------------------------------------------------------------------------------
-        <xsl:for-each select="permission">
+        <xsl:for-each select="adl:permission">
             <xsl:call-template name="permission">
                 <xsl:with-param name="table" select="$table"/>
             </xsl:call-template>
@@ -130,7 +242,7 @@
         --    convenience view lv<xsl:value-of select="concat( '_', @name)"/> for lists
         -------------------------------------------------------------------------------------------------
         CREATE VIEW lv<xsl:value-of select="concat( '_', @name)"/> AS
-        SELECT <xsl:for-each select="property[@type!='link']">
+        SELECT <xsl:for-each select="adl:property[@type!='link']">
             <xsl:choose>
                <xsl:when test="@type='entity'">
                    <xsl:call-template name="distinctfield">
@@ -147,10 +259,10 @@
             </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:for-each select="adl: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:for-each select="adl:property[@type='entity']">
             <xsl:choose>
             <xsl:when test="position() = 1">WHERE </xsl:when>
             <xsl:otherwise>AND   </xsl:otherwise>
@@ -159,14 +271,14 @@
         </xsl:for-each>;
 
         ----  permissions  ------------------------------------------------------------------------------
-        <xsl:for-each select="permission">
+        <xsl:for-each select="adl: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:for-each select="adl:property[@type='link']">
             <xsl:call-template name="linktable">
                 <xsl:with-param name="nearside" select="$table"/>
             </xsl:call-template>
@@ -273,14 +385,13 @@
         
     </xsl:template>
     
-    <xsl:template match="property[@type='entity']">
+    <xsl:template match="adl: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>
+                test="@required='true'"> NOT NULL</xsl:if>
     </xsl:template>
 
-    <xsl:template match="property[@type='defined']">
+    <xsl:template match="adl: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>
@@ -290,37 +401,40 @@
             <xsl:when test="$definitiontype='real'">DOUBLE PRECISION</xsl:when>
             <xsl:otherwise><xsl:value-of select="$definitiontype"/></xsl:otherwise>
         </xsl:choose><xsl:if 
-        test="string(@default)"> DEFAULT <xsl:value-of select="@default"/></xsl:if><xsl:if 
-            test="@required='true'"> NOT NULL</xsl:if>,<xsl:text>
-            </xsl:text>
+        test="string(@default)"> DEFAULT <xsl:value-of select="@default"/></xsl:if><xsl:choose>
+			<xsl:when test="parent::adl:key"> NOT NULL PRIMARY KEY</xsl:when>
+			<xsl:when test="@required='true'"> NOT NULL</xsl:when>
+		</xsl:choose>
     </xsl:template>
     
-    <xsl:template match="property[@type='string']">
+    <xsl:template match="adl: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>
+            test="string(@default)"> DEFAULT <xsl:value-of select="@default"/></xsl:if><xsl:choose>
+			<xsl:when test="parent::adl:key"> NOT NULL PRIMARY KEY</xsl:when>
+			<xsl:when test="@required='true'"> NOT NULL</xsl:when>
+		</xsl:choose>
     </xsl:template>
         
-    <xsl:template match="property[@type='integer']">
+    <xsl:template match="adl: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>
+            test="string(@default)"> DEFAULT <xsl:value-of select="@default"/></xsl:if><xsl:choose>
+			<xsl:when test="parent::adl:key"> NOT NULL PRIMARY KEY</xsl:when>
+			<xsl:when test="@required='true'"> NOT NULL</xsl:when>
+        </xsl:choose>
     </xsl:template>
     
-    <xsl:template match="property[@type='real']">
+    <xsl:template match="adl: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>
+                test="@required='true'"> NOT NULL</xsl:if>
     </xsl:template>
     
-    <xsl:template match="property">
+    <xsl:template match="adl: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>
+            test="string(@default)"> DEFAULT <xsl:value-of select="@default"/></xsl:if><xsl:choose>
+			<xsl:when test="parent::adl:key"> NOT NULL PRIMARY KEY</xsl:when>
+			<xsl:when test="@required='true'"> NOT NULL</xsl:when>
+		</xsl:choose>
     </xsl:template>
     
 </xsl:stylesheet>
diff --git a/transforms/adl2views.xslt b/transforms/adl2views.xslt
index ae0d729..53ace20 100755
--- a/transforms/adl2views.xslt
+++ b/transforms/adl2views.xslt
@@ -1,2059 +1,2068 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<xsl:stylesheet version="1.0"
-	xmlns="http://libs.cygnets.co.uk/adl/1.4/"
-	xmlns:adl="http://libs.cygnets.co.uk/adl/1.4/"
-	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
-	xmlns:msxsl="urn:schemas-microsoft-com:xslt"
-				xmlns:exsl="urn:schemas-microsoft-com:xslt"
-                extension-element-prefixes="exsl">
-	<!--
-    Application Description Language framework
-    adl2views.xsl
-    
-    (c) 2007 Cygnet Solutions Ltd
-    
-    Transform ADL into velocity view templates
-    
-    $Author: sb $
-    $Revision: 1.65 $
-    $Date: 2010-01-12 17:20:17 $
-	-->
-	<!-- WARNING WARNING WARNING: Do NOT reformat this file! 
-		Whitespace (or lack of it) is significant! -->
-
-	<xsl:include href="base-type-include.xslt"/>
-	<xsl:include href="permissions-include.xslt"/>
-  <!-- bug 1896 : boilerplate text in views should be tailored to the locale of
-		the expected user. Unfortunately I haven't yet worked out how to do
-		conditional includes in XSLT, so this is a step on the way to a solution,
-		not a solution in itself. -->
-  <xsl:include href="i18n-en-GB-include.xslt"/>
-
-  <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-GB"/>
-
-	<!-- whether or not to auto-generate site navigation - by default, don't -->
-	<xsl:param name="generate-site-navigation" select="'false'"/>
-
-	<!-- whether or not to layout errors - they may be in the default layout -->
-	<xsl:param name="show-errors" select="'false'"/>
-	<!-- whether or not to layout messages - they may be in the default layout -->
-	<xsl:param name="show-messages" select="'false'"/>
-
-	<!-- the maximum width, in characters, we're prepared to allocate to widgets -->
-	<xsl:param name="max-widget-width" select="40"/>
-
-	<!-- the name and version of the product being built -->
-	<xsl:param name="product-version" select="'Application Description Language Framework'"/>
-
-	<!-- bug 1800 : the name of the Velocity layout to use. If you are to 
-		be able to usefully define content in ADL, then the default ADL layout 
-		needs to be empty, but if ADL-generated pages are to 'play nice' in
-		largely non-ADL applications, they must be able to use standard layouts.
-		If you are going to use a non-default layout, however, you're responsible
-		for making sure it loads all the scripts, etc, that an ADL controller 
-		expects. -->
-	<xsl:param name="layout-name"/>
-	<!-- bug 1800 : the name of the area (i.e. URL path part) to use -->
-	<xsl:param name="area-name" select="auto"/>
-	<!-- the base url of the whole site -->
-	<xsl:param name="site-root" select="'..'"/>
-	<!-- Whether to authenticate at application or at database layer. 
-    If not 'Application', then 'Database'. -->
-	<xsl:param name="authentication-layer" select="'Application'"/>
-
-  <!-- bug 2847: how long to wait on a page before it auto-redirects to the default URL -->
-  <xsl:param name="page-timeout" select="300"/>
-  <!-- bug 2847: the default URL, probably a 'please login' screen -->
-  <xsl:param name="default-url" select="'../default.aspx'"/>
-
-	<xsl:template match="adl:application">
-		<output>
-			<!-- 'output' is a dummy wrapper root tag to make the entire output work as
-				an XML document; the actual output later gets cut into chunks and the
-				wrapper tag is discarded. -->
-			<xsl:apply-templates select="adl:entity"/>
-			<!-- make sure extraneous junk doesn't get into the last file generated,
-				by putting it into a separate file -->
-			<xsl:text>
-			  </xsl:text>
-			<xsl:comment> [ cut here: next file 'tail.txt' ] </xsl:comment>
-		</output>
-	</xsl:template>
-
-	<xsl:template match="adl:entity[@foreign='true']"/>
-	<!-- Don't bother generating anything for foreign entities -->
-
-	<xsl:template match="adl:entity">
-		<xsl:comment>Layout is <xsl:value-of select="$layout-name"/></xsl:comment>
-		<xsl:choose>
-			<xsl:when test="$layout-name">
-				<xsl:apply-templates select="." mode="non-empty-layout"/>
-			</xsl:when>
-			<xsl:otherwise>
-				<xsl:apply-templates select="." mode="empty-layout"/>
-			</xsl:otherwise>
-		</xsl:choose>
-	</xsl:template>
-
-	<!-- generate views for an entity, assuming a non-empty layout - i.e. 
-    I'm not responsible for the html, the head, or for the body tag -->
-	<xsl:template match="adl:entity" mode="non-empty-layout">
-		<xsl:variable name="keyfield">
-			<xsl:choose>
-				<xsl:when test="adl:key/adl:property">
-					<xsl:value-of select="adl:key/adl:property[position()=1]/@name"/>
-				</xsl:when>
-				<xsl:otherwise>[none]</xsl:otherwise>
-			</xsl:choose>
-		</xsl:variable>
-		<xsl:apply-templates select="adl:form" mode="non-empty-layout"/>
-		<xsl:apply-templates select="adl:list" mode="non-empty-layout"/>
-		<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>
-		<xsl:variable name="really-delete">
-			<xsl:call-template name="i18n-really-delete"/>
-		</xsl:variable>
-		#set( $title = "<xsl:value-of select="concat( $really-delete, ' ', @name)"/> $instance.UserIdentifier")
-    #capturefor( headextras)
-    <xsl:comment>
-			Auto generated Velocity maybe-delete form for <xsl:value-of select="@name"/>,
-		</xsl:comment>
-    <xsl:call-template name="head"/>
-    #end
-    <xsl:call-template name="maybe-delete">
-      <xsl:with-param name="entity" select="."/>
-    </xsl:call-template>
-  </xsl:template>
-
-	<!-- generate views for an entity, assuming an empty layout 
-			(i.e. I'm responsible for html, head and body tags) -->
-		<xsl:template match="adl:entity" mode="empty-layout">
-			<xsl:variable name="keyfield">
-				<xsl:choose>
-					<xsl:when test="adl:key/adl:property">
-						<xsl:value-of select="adl:key/adl:property[position()=1]/@name"/>
-					</xsl:when>
-					<xsl:otherwise>[none]</xsl:otherwise>
-				</xsl:choose>
-			</xsl:variable>
-
-			<xsl:apply-templates select="adl:form" mode="empty-layout"/>
-			<xsl:apply-templates select="adl:list" mode="empty-layout"/>
-			<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:variable name="really-delete">
-					<xsl:call-template name="i18n-really-delete"/>
-				</xsl:variable>
-				#set( $title = "<xsl:value-of select="concat( $really-delete, ' ', @name)"/> $instance.UserIdentifier")
-				<head>
-          <xsl:comment>
-            Auto generated Velocity maybe-delete form for <xsl:value-of select="@name"/>,
-          </xsl:comment>
-          <xsl:call-template name="head"/>
-					<xsl:call-template name="install-scripts"/>
-				</head>
-				<body>
-          <div id="page">
-            <xsl:call-template name="top"/>
-            <xsl:call-template name="maybe-delete">
-              <xsl:with-param name="entity" select="."/>
-            </xsl:call-template>
-            <xsl:call-template name="foot"/>
-          </div>
-        </body>
-			</html>
-		</xsl:template>
-
-		<!-- the guts of the maybe-delete form, whether or not we're using an empty layout -->
-  <xsl:template name="maybe-delete">
-    <xsl:param name="entity"/>
-    <div class="content">
-      <xsl:if test="$show-errors = 'true'">
-        #if ( $instance.NoDeleteReason)
-        <ul class="errors">
-          <li>$instance.NoDeleteReason</li>
-        </ul>
-        #end
-        #if ( $errors)
-        #if ( $errors.Count != 0)
-        <ul class="errors">
-          #foreach($e in $errors)
-          #if($e.Message)
-          <li>$t.Error($e)</li>
-          #else
-          <li>$t.Enc($e)</li>
-          #end
-          #end
-        </ul>
-        #end
-        #end
-      </xsl:if>
-      <xsl:if test="$show-messages = 'true'">
-        #if( $messages)
-        #if ( $messages.Count != 0)
-        <ul class="information">
-          #foreach ( $message in $messages)
-          <li>$message</li>
-          #end
-        </ul>
-        #end
-        #end
-      </xsl:if>
-      <form action="delete.rails" method="post">
-        <xsl:for-each select="$entity/adl:key/adl:property">
-          <xsl:choose>
-            <xsl:when test="@type='entity'">
-              <xsl:variable name="entityname" select="@entity"/>
-              <xsl:variable name="entitykeyname" select="//adl:entity[@name=$entityname]/adl:key/adl:property[position()=1]/@name"/>
-              <input type="hidden">
-                <xsl:attribute name="name">
-                  <xsl:value-of select="concat( 'instance.', @name)"/>
-                </xsl:attribute>
-                <xsl:attribute name="value">
-                  <xsl:value-of select="concat('$instance.', @name, '.', $entitykeyname)"/>
-                </xsl:attribute>
-              </input>
-            </xsl:when>
-            <xsl:otherwise>
-              <input type="hidden">
-                <xsl:attribute name="name">
-                  <xsl:value-of select="concat( 'instance.', @name)"/>
-                </xsl:attribute>
-                <xsl:attribute name="value">
-                  <xsl:value-of select="concat('$instance.', @name)"/>
-                </xsl:attribute>
-              </input>
-            </xsl:otherwise>
-          </xsl:choose>
-        </xsl:for-each>
-        <table>
-          <tr align="left" valign="top" class="actionDangerous">
-            <td class="actionDangerous">
-              <xsl:call-template name="i18n-really-delete"/>
-            </td>
-            <td class="widget">
-              <select name="reallydelete">
-                <option value="false">
-                  <xsl:call-template name="i18n-really-delete-no"/>
-                </option>
-                <option value="true">
-                  <xsl:call-template name="i18n-really-delete-yes"/>
-                </option>
-              </select>
-            </td>
-            <td class="actionDangerous" style="text-align:right">
-              <input type="submit" name="command" value="Go" />
-            </td>
-          </tr>
-        </table>
-      </form>
-    </div>
-  </xsl:template>
-
-  <!-- layout of forms -->
-	<xsl:template match="adl:form" mode="non-empty-layout">
-		<xsl:variable name="form" select="."/>
-		<xsl:text>
-		</xsl:text>
-		<xsl:comment>[ cut here: next file '<xsl:value-of select="concat( ancestor::adl:entity/@name, '/', @name)"/>.auto.vm' ]</xsl:comment>
-		<xsl:text>
-    </xsl:text>
-		#capturefor( title)
-    #if ( $instance)
-		#if ( ! $instance.IsNew)
-		<xsl:value-of select="concat( 'Edit ', ' ', ancestor::adl:entity/@name)"/> $instance.UserIdentifier
-		#else
-		<xsl:call-template name="i18n-add-a-new">
-			<xsl:with-param name="entity-name" select="ancestor::adl:entity/@name"/>
-		</xsl:call-template>
-    #end
-    #else
-    <xsl:call-template name="i18n-add-a-new">
-      <xsl:with-param name="entity-name" select="ancestor::adl:entity/@name"/>
-    </xsl:call-template>
-    #end
-    #end
-    #capturefor( headextras)
-    <xsl:comment>
-      Auto generated Velocity form for <xsl:value-of select="ancestor::adl:entity/@name"/>,
-    </xsl:comment>
-    <xsl:call-template name="head"/>
-		<xsl:call-template name="generate-head-javascript">
-			<xsl:with-param name="form" select="."/>
-      <xsl:with-param name="locale" select="$locale"/>
-		</xsl:call-template>
-
-		${StylesHelper.InstallStylesheet( "Epoch")}
-
-		<style type="text/css">
-			<xsl:for-each select="ancestor::adl:entity//adl: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>
-		#end
-		#capturefor(bodyattributes)
-		onload="performInitialisation()"
-		#end
-		<xsl:call-template name="top"/>
-		<xsl:call-template name="form-content">
-			<xsl:with-param name="form" select="."/>
-		</xsl:call-template>
-		<xsl:call-template name="foot"/>
-	</xsl:template>
-
-	<xsl:template match="adl:form" mode="empty-layout">
-		<xsl:variable name="form" select="."/>
-		<xsl:text>
-		</xsl:text>
-		<xsl:comment>[ cut here: next file '<xsl:value-of select="concat( ancestor::adl:entity/@name, '/', @name)"/>.auto.vm' ]</xsl:comment>
-		<xsl:text>
-		</xsl:text>
-		<html>
-			<xsl:comment>
-        #if ( $instance)
-				#if ( ! $instance.IsNew)
-				#set( $title = "<xsl:value-of select="concat( 'Edit ', ' ', ancestor::adl:entity/@name)"/> $instance.UserIdentifier")
-				#else
-				#set( $title = "<xsl:call-template name="i18n-add-a-new">
-					<xsl:with-param name="entity-name" select="ancestor::adl:entity/@name"/>
-				</xsl:call-template>")
-        #end
-        #else
-        #set( $title = "<xsl:call-template name="i18n-add-a-new">
-          <xsl:with-param name="entity-name" select="ancestor::adl:entity/@name"/>
-        </xsl:call-template>")
-        #end
-      </xsl:comment>
-			<head>
-        <xsl:comment>
-          Auto generated Velocity form for <xsl:value-of select="ancestor::adl:entity/@name"/>,
-        </xsl:comment>
-        <xsl:call-template name="head"/>
-        <xsl:if test="$page-timeout &gt; 0">
-          <meta http-equiv="refresh" content="5; URL=http://www.cryer.co.uk">
-            <xsl:attribute name="content">
-              <xsl:value-of select="concat($page-timeout, '; URL=', $default-url)"/>
-            </xsl:attribute>
-          </meta>
-        </xsl:if>
-        <xsl:call-template name="install-scripts"/>
-				<xsl:call-template name="generate-head-javascript">
-					<xsl:with-param name="form" select="."/>
-          <xsl:with-param name="locale" select="$locale"/>
-				</xsl:call-template>
-
-				${StylesHelper.InstallStylesheet( "Epoch")}
-
-				<style type="text/css">
-					<xsl:for-each select="ancestor::adl:entity//adl: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()">
-        <div id="page">
-          <xsl:call-template name="top"/>
-          <xsl:call-template name="form-content">
-            <xsl:with-param name="form" select="."/>
-          </xsl:call-template>
-          <xsl:call-template name="foot"/>
-        </div>
-      </body>
-		</html>
-	</xsl:template>
-
-	<!-- the content of a form, whether or not the layout is empty -->
-    <xsl:template name="form-content">
-		<!-- an entity of type form -->
-		<xsl:param name="form"/>
-		<div class="content">
-      #if ( $instance.NoDeleteReason)
-      <ul class="errors">
-        <li>$instance.NoDeleteReason</li>
-      </ul>
-      #end
-      <xsl:if test="$show-errors = 'true'">
-				#if ( $errors)
-					#if ( $errors.Count != 0)
-						<ul class="errors">
-							#foreach($e in $errors)
-								#if($e.Message)
-									<li>$t.Error($e)</li>
-								#else
-									<li>$t.Enc($e)</li>
-								#end
-							#end
-						</ul>
-					#end
-				#end
-			</xsl:if>
-			<xsl:if test="$show-messages = 'true'">
-				#if( $messages)
-					#if ( $messages.Count != 0)
-						<ul class="information">
-							#foreach ( $message in $messages)
-								<li>$message</li>
-							#end
-						</ul>
-					#end
-				#end
-			</xsl:if>
-			<form method="post" onsubmit="invokeSubmitHandlers(this);return trapEnterSubmissions(event, this);" onkeypress="trapKeyPress(event, this)" class="tabbed">
-				<xsl:attribute name="action">
-					<xsl:value-of select="concat( $form/@name, 'SubmitHandler.rails')"/>
-				</xsl:attribute>
-				<xsl:attribute name="name">
-					<xsl:value-of select="$form/@name"/>
-				</xsl:attribute>
-				<xsl:attribute name="id">
-					<xsl:value-of select="$form/@name"/>
-				</xsl:attribute>
-				<xsl:attribute name="enctype">
-					<xsl:choose>
-						<xsl:when test="$form/ancestor::adl:entity//adl:property[@type='uploadable']">
-							<xsl:value-of select="'multipart/form-data'"/>
-						</xsl:when>
-						<xsl:when test="$form/ancestor::adl:entity//adl:property[@type='image']">
-							<xsl:value-of select="'multipart/form-data'"/>
-						</xsl:when>
-						<xsl:otherwise>
-							<xsl:value-of select="'application/x-www-form-urlencoded'"/>
-						</xsl:otherwise>
-					</xsl:choose>
-				</xsl:attribute>
-				<input type="hidden" name="currentpane" value="$!currentpane" />
-				<xsl:for-each select="$form/ancestor::adl:entity/adl:key/adl:property">
-					<xsl:variable name="keyname" select="@name"/>
-					<xsl:choose>
-						<xsl:when test="$form//adl:field[@property=$keyname]">
-							<!-- it's already a field of the form - no need to add a hidden one -->
-						</xsl:when>
-						<xsl:otherwise>
-							<!-- create a hidden widget for the natural primary key -->
-							#if ( $instance)
-							#if ( ! ( $instance.IsNew))
-							${FormHelper.HiddenField( "instance.<xsl:value-of select="$keyname"/>")}
-							#end
-							#end
-						</xsl:otherwise>
-					</xsl:choose>
-				</xsl:for-each>
-				<xsl:apply-templates select="$form/adl:fieldgroup"/>
-				<div class="non-pane">
-					<table>
-						<xsl:choose>
-							<xsl:when test="@properties='listed'">
-								<xsl:apply-templates select="$form/adl:field|adl:auxlist"/>
-							</xsl:when>
-							<xsl:otherwise>
-								<xsl:apply-templates select="$form/ancestor::adl:entity/adl:property"/>
-							</xsl:otherwise>
-						</xsl:choose>
-          </table>
-          <ul class="verbs">
-            <xsl:apply-templates select="adl:verb"/>
-            <xsl:choose>
-              <xsl:when test="$authentication-layer='Database'">
-                <xsl:variable name="savegroups">
-                  <xsl:call-template name="entity-save-groups">
-                    <xsl:with-param name="entity" select="$form/ancestor::adl:entity"/>
-                  </xsl:call-template>
-                </xsl:variable>
-				  <xsl:variable name="updategroups">
-					  <xsl:call-template name="entity-update-groups">
-						  <xsl:with-param name="entity" select="$form/ancestor::adl:entity"/>
-					  </xsl:call-template>
-				  </xsl:variable>
-				  <!-- NOTE! NOTE! NOTE! Whitespace is significant - any linefeeds inside the #if ( ) clause
-								cause the Velocity parser to break! -->
-				#if ( $instance)
-				  #if ( $instance.IsNew)
-				    #if ( <xsl:for-each select="exsl:node-set( $savegroups)/*"> ${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} ||</xsl:for-each> false)
-                    <xsl:call-template name="save-widget-row"/>
-				    #end
-				  #else
-				    #if ( <xsl:for-each select="exsl:node-set( $updategroups)/*"> ${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} || </xsl:for-each> false)
-				    <xsl:call-template name="save-widget-row"/>
-				    #end
-				  #end
-				#else
-				<!-- for application-layer authentication, we may not actually have an instance at this stage -->
-				  #if ( <xsl:for-each select="exsl:node-set( $savegroups)/*"> ${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} || </xsl:for-each> false)
-				  <xsl:call-template name="save-widget-row"/>
-				  #end
-				#end
-				  <xsl:variable name="deletegroups">
-                  <xsl:call-template name="entity-delete-groups">
-                    <xsl:with-param name="entity" select="$form/ancestor::adl:entity"/>
-                  </xsl:call-template>
-                </xsl:variable>
-                <!-- NOTE! NOTE! NOTE! Whitespace is significant - any linefeeds inside the #if ( ) clause
-								cause the Velocity parser to break! -->
-                #if ( <xsl:for-each select="exsl:node-set( $deletegroups)/*"> ${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} || </xsl:for-each> false)
-                <xsl:call-template name="delete-widget-row"/>
-                #end
-              </xsl:when>
-              <xsl:when test="$authentication-layer='Application'">
-                <xsl:call-template name="save-widget-row"/>
-                <xsl:call-template name="delete-widget-row"/>
-              </xsl:when>
-            </xsl:choose>
-          </ul>
-        </div>
-      </form>
-		</div>
-	</xsl:template>
-
-	<!-- output a complete table row containing a save widget -->
-	<xsl:template name="save-widget-row">
-    <li class="standard-verb actionSafe">
-      <button type="submit" name="command" value="store">
-        <xsl:attribute name="title">
-          <xsl:call-template name='i18n-save-prompt'/>
-        </xsl:attribute>
-        Save
-      </button>
-    </li>
-  </xsl:template>
-
-	<!-- output a complete table row containing a delete widget -->
-  <xsl:template name="delete-widget-row">
-    <li class="standard-verb actionDangerous">
-      #if ( $instance)
-	  #if ( !$instance.IsNew)
-      #if ( $instance.NoDeleteReason)
-      <button type="submit" disabled="disabled" title="$instance.NoDeleteReason"  name="command" value="delete">Delete this</button>
-      #else
-      <button type="submit" name="command" value="delete">
-        <xsl:attribute name="title">
-          <xsl:call-template name="i18n-delete-prompt"/>
-        </xsl:attribute>
-        Delete this
-      </button>
-      #end
-      #end
-	  #end
-    </li>
-  </xsl:template>
-
-  <xsl:template match="adl:fieldgroup">
-    <xsl:if test="$authentication-layer = 'Database'">
-      <xsl:variable name="property" select="."/>
-      <xsl:variable name="readgroups">
-        <xsl:call-template name="fieldgroup-read-groups">
-          <xsl:with-param name="fieldgroup" select="."/>
-        </xsl:call-template>
-      </xsl:variable>
-      <!-- NOTE! NOTE! NOTE! Whitespace is significant - any linefeeds inside the #if ( ) clause cause the Velocity parser to break! -->
-      #if ( <xsl:for-each select="exsl:node-set( $readgroups)/*"> ${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} ||</xsl:for-each> false)
-    </xsl:if>
-
-    <div class="tab-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>
-			<h3 class="title">
-				<xsl:call-template name="showprompt">
-					<xsl:with-param name="node" select="."/>
-					<xsl:with-param name="fallback" select="@name"/>
-					<xsl:with-param name="entity" select="ancestor::adl:entity"/>
-					<xsl:with-param name="locale" select="$locale"/>
-				</xsl:call-template>
-			</h3>
-			<table>
-				<xsl:apply-templates select="adl:field|adl:auxlist"/>
-			</table>
-      <xsl:if test="adl:verb">
-        <ul class="verbs">
-          <xsl:apply-templates select="adl:verb"/>
-        </ul>
-      </xsl:if>
-		</div>
-    <xsl:if test="$authentication-layer = 'Database'">
-      #end
-    </xsl:if>
-	</xsl:template>
-
-	<xsl:template match="adl:auxlist">
-		<xsl:variable name="listprop" select="@property"/>
-		<xsl:variable name="farent" select="ancestor::adl:entity//adl:property[@name=$listprop]/@entity"/>
-		<xsl:variable name="nearent" select="ancestor::adl:entity/@name"/>
-		<xsl:variable name="farid">
-			<xsl:value-of select="//adl:entity[@name=$farent]/adl:key//adl:property[position()=1]/@name"/>
-		</xsl:variable>
-		<xsl:variable name="farkey">
-			<xsl:choose>
-				<xsl:when test="//adl:entity[@name=$farent]//adl:property[@entity=$nearent]/@farkey">
-					<xsl:value-of select="//adl:entity[@name=$farent]//adl:property[@entity=$nearent]/@farkey"/>
-				</xsl:when>
-				<xsl:otherwise>
-					<xsl:value-of select="//adl:entity[@name=$farent]//adl:property[@entity=$nearent]/@name"/>
-				</xsl:otherwise>
-			</xsl:choose>
-		</xsl:variable>
-		<xsl:variable name="nearkey">
-			<xsl:choose>
-				<xsl:when test="ancestor::adl:entity/adl:key/adl:property[position()=1 and @type='entity']">
-					<xsl:value-of select="concat( ancestor::adl:entity/adl:key/adl:property[position()=1]/@name, '_Value')"/>
-				</xsl:when>
-				<xsl:otherwise>
-					<xsl:value-of select="ancestor::adl:entity/adl:key/adl:property[position()=1]/@name"/>
-				</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, 'With', $farkey, '.rails?', $farkey, '=$instance.', $nearkey)"/>
-						</xsl:attribute>
-						<xsl:call-template name="i18n-add-a-new">
-							<xsl:with-param name="entity-name" select="$farent"/>
-						</xsl:call-template>
-					</a>
-				</td>
-			</tr>
-		</xsl:if>
-		<tr>
-			<td>
-				<xsl:attribute name="colspan">
-					<xsl:value-of select="count( field)"/>
-				</xsl:attribute>
-
-				<xsl:choose>
-					<xsl:when test="@properties='listed'">
-						<xsl:comment>auxlist with listed fields: <xsl:value-of select="$farent/@name"/></xsl:comment>
-						<xsl:call-template name="internal-with-fields-list">
-							<xsl:with-param name="entity" select="//adl:entity[@name=$farent]"/>
-							<xsl:with-param name="fields" select="adl:field"/>
-							<xsl:with-param name="instance-list" select="concat( 'instance.', $listprop)"/>
-						</xsl:call-template>
-					</xsl:when>
-					<xsl:otherwise>
-						<xsl:comment>auxlist with computed fields: <xsl:value-of select="$farent/@name"/></xsl:comment>
-						<xsl:call-template name="internal-with-properties-list">
-							<xsl:with-param name="entity" select="//adl:entity[@name=$farent]"/>
-							<xsl:with-param name="properties" select="//adl:entity[@name=$farent]//adl:property[(@distinct='user' or @distinct='all') and not( @type='link' or @type='list')]"/>
-							<xsl:with-param name="instance-list" select="concat( 'instance.', $listprop)"/>
-						</xsl:call-template>
-					</xsl:otherwise>
-				</xsl:choose>
-			</td>
-		</tr>
-	</xsl:template>
-
-	<xsl:template match="adl:verb">
-    <xsl:variable name="executegroups">
-      <xsl:call-template name="verb-execute-groups">
-        <xsl:with-param name="verb" select="."/>
-      </xsl:call-template>
-    </xsl:variable>
-    <!-- NOTE! NOTE! NOTE! Whitespace is significant - any linefeeds inside the #if ( ) clause
-								cause the Velocity parser to break! -->
-    #if ( <xsl:for-each select="exsl:node-set( $executegroups)/*"> ${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} ||</xsl:for-each> false)
-    <xsl:variable name="class">
-			<xsl:choose>
-				<xsl:when test="@dangerous='true'">actionDangerous</xsl:when>
-				<xsl:otherwise>actionSafe</xsl:otherwise>
-			</xsl:choose>
-		</xsl:variable>
-		<!-- don't emit a verb unless there is an instance for it to act on -->
-    #if( $instance)
-    #if( ! $instance.IsNew)
-    <li>
-      <xsl:attribute name="class">
-        <xsl:value-of select="concat( 'custom-verb ', $class)"/>
-      </xsl:attribute>
-      <button name="command">
-        <xsl:attribute name="value">
-          <xsl:value-of select="@verb"/>
-        </xsl:attribute>
-        <xsl:attribute name="title">
-          <xsl:apply-templates select="adl:help[@locale = $locale]"/>
-        </xsl:attribute>
-        <xsl:call-template name="showprompt">
-          <xsl:with-param name="node" select="."/>
-          <xsl:with-param name="fallback" select="@verb"/>
-        </xsl:call-template>
-      </button>
-    </li>
-    #end
-    #end
-    #end
-  </xsl:template>
-
-	<xsl:template match="adl:field">
-		<xsl:variable name="propname">
-			<xsl:value-of select="@property"/>
-		</xsl:variable>
-		<xsl:choose>
-			<xsl:when test="ancestor::adl:entity//adl:property[@name=$propname]">
-				<!-- there is a real property -->
-				<xsl:apply-templates select="ancestor::adl:entity//adl: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 -->
-				<xsl:comment>
-					Computed field (<xsl:value-of select="$propname"/>)? TODO: Not yet implememented
-				</xsl:comment>
-			</xsl:otherwise>
-		</xsl:choose>
-	</xsl:template>
-
-	<xsl:template match="adl:property[@type='message']">
-		<!-- HIHGLY experimental - an internationalised message -->
-		<xsl:param name="oddness" select="odd"/>
-		<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="node" select="."/>
-					<xsl:with-param name="fallback" select="@name"/>
-				</xsl:call-template>")}
-			</td>
-			<td class="widget" colspan="2">
-				#if( $instance)
-				#if( <xsl:value-of select="concat( '$instance.', @name)"/>)
-				<xsl:value-of select="concat( '$t.Msg( $instance.', @name, ')')"/>
-				#else
-				<input type="text">
-					<xsl:attribute name="name">
-						<xsl:value-of select="concat('i18n.instance.', @name)"/>
-					</xsl:attribute>
-				</input>
-				#end
-				#else
-				<input type="text">
-					<xsl:attribute name="name">
-						<xsl:value-of select="concat('i18n.instance.', @name)"/>
-					</xsl:attribute>
-				</input>
-				#end
-			</td>
-		</tr>
-	</xsl:template>
-
-	<xsl:template match="adl:property[@type='link'or @type='list']">
-		<!-- 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 and lists we implement a shuffle widget, which extends over both columns -->
-		<xsl:param name="oddness" select="odd"/>
-    <xsl:if test="$authentication-layer = 'Database'">
-      <xsl:variable name="property" select="."/>
-      <xsl:variable name="readgroups">
-        <xsl:call-template name="entity-read-groups">
-          <xsl:with-param name="entity" select="//adl:entity[@name=$property/@entity]"/>
-        </xsl:call-template>
-      </xsl:variable>
-      <!-- NOTE! NOTE! NOTE! Whitespace is significant - any linefeeds inside the #if ( ) clause cause the Velocity parser to break! -->
-      #if ( <xsl:for-each select="exsl:node-set( $readgroups)/*">${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} || </xsl:for-each> false)
-    </xsl:if>
-    <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="node" select="."/>
-					<xsl:with-param name="fallback" select="@name"/>
-				</xsl:call-template>")}
-			</td>
-      <td class="widget shuffle" colspan="2">
-        <xsl:call-template name="shuffle-widget">
-          <xsl:with-param name="property" select="."/>
-        </xsl:call-template>
-      </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="adl:help[@locale = $locale]"/>
-			</td>
-		</tr>
-    <xsl:if test="$authentication-layer = 'Database'">
-      #end
-    </xsl:if>
-	</xsl:template>
-
-	<xsl:template name="shuffle-widget">
-		<xsl:param name="property" select="."/>
-    #if ( $instance)
-    #if ( ! $instance.IsNew)
-		<table class="shuffle">
-			<tr>
-				<td class="widget shuffle-all" rowspan="2">
-					${ShuffleWidgetHelper.UnselectedOptions( "<xsl:value-of select="concat( $property/@name, '_unselected')"/>", <xsl:value-of select="concat( '$all_', $property/@name)"/>, $instance.<xsl:value-of select="$property/@name"/>)}
-				</td>
-				<td class="widget shuffle-action">
-					<input type="button" value="include &gt;&gt;">
-						<xsl:attribute name="onclick">
-							<xsl:value-of select="concat( 'shuffle(', $property/@name, '_unselected, ', $property/@name, ')')"/>
-						</xsl:attribute>
-					</input>
-				</td>
-				<td class="widget shuffle-selected" rowspan="2">
-					<xsl:variable name="entityname" select="$property/@entity"/>
-					<xsl:variable name="foreignkey" select="$property/@farkey"/>
-					<xsl:variable name="allow-shuffle-back">
-						<xsl:choose>
-							<xsl:when test="$property/@type='list' and //adl:entity[@name=$entityname]//adl:property[@name=$foreignkey and @required='true']">
-								<xsl:value-of select="'false'"/>
-							</xsl:when>
-							<xsl:otherwise>
-								<xsl:value-of select="'true'"/>
-							</xsl:otherwise>
-						</xsl:choose>
-					</xsl:variable>
-					${ShuffleWidgetHelper.SelectedOptions( "<xsl:value-of select="$property/@name"/>", $instance.<xsl:value-of select="$property/@name"/>, <xsl:value-of select="$allow-shuffle-back"/>)}
-				</td>
-			</tr>
-			<tr>
-				<td class="widget shuffle-action">
-					<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>
-    #else
-    <i>You must create your <xsl:value-of select="$property/ancestor::adl:entity/@name"/> record before you can add <xsl:value-of select="$property/@name"/> to it</i>
-    #end
-    #end
-	</xsl:template>
-
-	<xsl:template match="adl: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! -->
-		<xsl:variable name="property" select="."/>
-		<xsl:variable name="editgroups">
-			<xsl:call-template name="property-edit-groups">
-				<xsl:with-param name="property" select="$property"/>
-			</xsl:call-template>
-		</xsl:variable>
-		<xsl:variable name="insertgroups">
-			<xsl:call-template name="property-insert-groups">
-				<xsl:with-param name="property" select="$property"/>
-			</xsl:call-template>
-		</xsl:variable>
-		<xsl:variable name="readgroups">
-			<xsl:call-template name="property-read-groups">
-				<xsl:with-param name="property" select="$property"/>
-			</xsl:call-template>
-		</xsl:variable>
-    <xsl:if test="$authentication-layer = 'Database'">
-      <xsl:choose>
-        <xsl:when test="exsl:node-set( $readgroups)/*">
-          #if ( <xsl:for-each select="exsl:node-set( $readgroups)/*">${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} || </xsl:for-each> false)
-        </xsl:when>
-        <xsl:otherwise>
-          <xsl:comment>we haven't found any group of users who are entitled to see this field.</xsl:comment>
-          #if ( false)
-        </xsl:otherwise>
-      </xsl:choose>
-    </xsl:if>
-      <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="$authentication-layer = 'Application'">
-							<xsl:call-template name="property-widget">
-								<xsl:with-param name="property" select="."/>
-								<xsl:with-param name="mode" select="'Editable'"/>
-							</xsl:call-template>
-						</xsl:when>
-						<xsl:when test="$authentication-layer = 'Database'">
-							<xsl:if test="exsl:node-set( $editgroups)/*">
-								<!-- NOTE! NOTE! NOTE! Whitespace is significant - any linefeeds inside the #if ( ) clause
-								cause the Velocity parser to break! -->
-								#if ( <xsl:for-each select="exsl:node-set( $editgroups)/*">${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} ||</xsl:for-each> false)
-								<xsl:choose>
-									<xsl:when test="$property/@immutable='true'">
-										<xsl:call-template name="property-widget">
-											<xsl:with-param name="property" select="."/>
-											<xsl:with-param name="mode" select="'Immutable'"/>
-										</xsl:call-template>
-									</xsl:when>
-									<xsl:otherwise>
-										<xsl:call-template name="property-widget">
-											<xsl:with-param name="property" select="."/>
-											<xsl:with-param name="mode" select="'Editable'"/>
-										</xsl:call-template>
-									</xsl:otherwise>
-								</xsl:choose>
-								#else
-							</xsl:if>
-							<xsl:if test="exsl:node-set( $insertgroups)/*">
-								#if ( <xsl:for-each select="exsl:node-set( $insertgroups)/*">${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} ||</xsl:for-each> false)
-								<xsl:call-template name="property-widget">
-									<xsl:with-param name="property" select="."/>
-									<xsl:with-param name="mode" select="'Immutable'"/>
-								</xsl:call-template>
-								#else
-							</xsl:if>
-							<xsl:if test="exsl:node-set( $readgroups)/*">
-								#if ( <xsl:for-each select="exsl:node-set( $readgroups)/*">${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} ||</xsl:for-each> false)
-								<xsl:call-template name="property-widget">
-									<xsl:with-param name="property" select="."/>
-									<xsl:with-param name="mode" select="'DisplayAndHidden'"/>
-								</xsl:call-template>
-								#else
-							</xsl:if>
-								[Not authorised]
-							<xsl:if test="exsl:node-set( $readgroups)/*">
-								#end
-							</xsl:if>
-							<xsl:if test="exsl:node-set( $insertgroups)/*">
-								#end
-							</xsl:if>
-							<xsl:if test="exsl:node-set( $editgroups)/*">
-								#end
-							</xsl:if>
-						</xsl:when>
-					</xsl:choose>
-				</td>
-				<td class="help">
-					<xsl:apply-templates select="adl:help[@locale = $locale]"/>
-				</td>
-			</tr>
-    <xsl:if test="$authentication-layer = 'Database'">
-        #end
-    </xsl:if>
-
-  </xsl:template>
-
-
-	<!-- layout of lists -->
-	<!-- layout of a list assuming a non-empty layout -->
-	<xsl:template match="adl:list" mode="non-empty-layout">
-		<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">
-			<xsl:call-template name="i18n-plural">
-				<xsl:with-param name="noun" select="ancestor::adl:entity/@name"/>
-			</xsl:call-template>
-		</xsl:variable>
-
-    #capturefor( title)
-    <xsl:value-of select="normalize-space( concat( 'List ', $withpluralsuffix))"/>
-    #end
-    #capturefor( headextras)
-    <xsl:comment>
-      Auto generated Velocity list for <xsl:value-of select="ancestor::adl:entity/@name"/>,
-    </xsl:comment>
-    <xsl:call-template name="head"/>
-		#end
-		<xsl:call-template name="top"/>
-		<xsl:call-template name="list">
-			<xsl:with-param name="list" select="."/>
-		</xsl:call-template>
-		<xsl:call-template name="foot"/>
-	</xsl:template>
-
-
-	<xsl:template match="adl:option">
-		<option>
-			<xsl:attribute name="value">
-				<xsl:value-of select="@value"/>
-			</xsl:attribute>
-			<xsl:attribute name="id">
-				<xsl:value-of select="concat( ancestor::adl:property/@name, '-', @value)"/>
-			</xsl:attribute>
-			<xsl:call-template name="showprompt">
-				<xsl:with-param name="fallback" select="@value"/>
-			</xsl:call-template>
-		</option>
-	</xsl:template>
-	
-	
-	<!-- layout of a list assuming an empty layout -->
-		<xsl:template match="adl:list" mode="empty-layout">
-			<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">
-				<xsl:call-template name="i18n-plural">
-					<xsl:with-param name="noun" select="ancestor::adl:entity/@name"/>
-				</xsl:call-template>
-			</xsl:variable>
-			<html>
-			  <head>
-				  #set( $title = "<xsl:value-of select="normalize-space( concat( 'List ', $withpluralsuffix))"/>")
-          <xsl:comment>
-            Auto generated Velocity list for <xsl:value-of select="ancestor::adl:entity/@name"/>,
-          </xsl:comment>
-          <xsl:call-template name="head"/>
-				  <xsl:call-template name="install-scripts"/>
-			  </head>
-        <body>
-          <div id="page">
-            <xsl:call-template name="top"/>
-            <xsl:call-template name="list">
-              <xsl:with-param name="list" select="."/>
-            </xsl:call-template>
-            <xsl:call-template name="foot"/>
-          </div>
-        </body>
-      </html>
-	  </xsl:template>
-
-	  <!-- layout the content of a list, whether or not the layout is empty -->
-	  <xsl:template name="list">
-		  <!-- an entity of type adl:list -->
-		  <xsl:param name="list"/>
-		  <div class="content">
-			  <div class="controls">
-          <span class="pagination status">
-            Showing $instances.FirstItem - $instances.LastItem of $instances.TotalItems
-          </span>
-          #if (  <xsl:for-each select="adl:field">
-            <xsl:variable name="field" select="."/>
-            <xsl:variable name="search-name"
-                          select="concat('$search_', ancestor::adl:entity//adl:property[@name=$field/@property]/@name)"/>
-            <xsl:value-of select="$search-name"/>
-            <xsl:if test="not( position() = last())">||</xsl:if>
-          </xsl:for-each> )
-          <span class="pagination status">(Suppressing pagination in favour of search)</span>
-          #else
-				  <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>
-          #end
-				  <xsl:if test="$list/../adl:form">
-					  <span class="add">
-						  <a>
-							  <xsl:attribute name="href">
-								  <xsl:value-of select="concat( ancestor::adl:entity/adl:form[position()=1]/@name, '.rails')"/>
-							  </xsl:attribute>
-							  <xsl:call-template name="i18n-add-a-new">
-								  <xsl:with-param name="entity-name" select="ancestor::adl:entity/@name"/>
-							  </xsl:call-template>
-						  </a>
-					  </span>
-				  </xsl:if>
-			  </div>
-			  <form>
-				  <xsl:attribute name="action">
-					  <xsl:value-of select="concat( $list/@name, '.rails')"/>
-				  </xsl:attribute>
-				  <xsl:call-template name="internal-with-fields-list">
-					  <xsl:with-param name="entity" select="$list/ancestor::adl:entity"/>
-					  <xsl:with-param name="fields" select="$list/adl:field"/>
-					  <xsl:with-param name="can-search" select="'true'"/>
-				  </xsl:call-template>
-			  </form>
-		  </div>
-	  </xsl:template>
-
-	  <xsl:template name="internal-with-fields-list">
-		  <!-- a node-list of entities of type 'adl:field' or 'adl:field', each indicating a property 
-			of the same entity, to be shown in columns of this list -->
-		  <xsl:param name="fields"/>
-		  <!-- the entity of type 'adl:entity' on which the properties for all those fields can be found -->
-		  <xsl:param name="entity"/>
-		  <!-- the name of the list of instances of this entity, available to Velocity at runtime 
-				as an ICollection, which is to be layed out in this list -->
-		  <xsl:param name="instance-list" select="'instances'"/>
-		  <!-- NOTE NOTE NOTE: To be searchable, internal-with-fields-list must not only be called with can-search
-			equal to 'true', but also within a form! -->
-		  <!-- NOTE NOTE NOTE: It's obvious that internal-with-fields-list and internal-with-properties-list
-			ought to be replaced with a single template, but that template proves to be extremely hard to get 
-			right -->
-		  <xsl:param name="can-search"/>
-		  <table class="sortable" id="concat($entity/@name, '-list')">
-			  <tr>
-				  <xsl:for-each select="$fields">
-					  <xsl:variable name="field" select="."/>
-					  <th>
-						  <xsl:call-template name="showprompt">
-							<xsl:with-param name="node" select="."/>
-							<xsl:with-param name="fallback" select="@property"/>
-							<xsl:with-param name="entity" select="$entity"/>
-							<xsl:with-param name="locale" select="$locale"/>
-						  </xsl:call-template>
-					  </th>
-				  </xsl:for-each>
-				  <xsl:for-each select="$entity/adl:form">
-					  <th class="unsortable">-</th>
-				  </xsl:for-each>
-			  </tr>
-			  <xsl:if test="$can-search = 'true'">
-				  <tr class="search sorttop">
-					  <xsl:for-each select="$fields">
-						  <xsl:variable name="field" select="."/>
-						  <td class="search">
-							  <xsl:variable name="size">
-								  <xsl:choose>
-                    <!-- can't search non-concrete fields -->
-                    <xsl:when test="$entity//adl:property[@name=$field/@property]/@concrete='false'">0</xsl:when>
-									  <xsl:when test="$entity//adl:property[@name=$field/@property]/@type='string'">
-										  <xsl:choose>
-											  <xsl:when test="$entity//adl:property[@name=$field/@property]/@size &gt; 20">20</xsl:when>
-											  <xsl:otherwise>
-												  <xsl:value-of select="$entity//adl:property[@name=$field/@property]/@size"/>
-											  </xsl:otherwise>
-										  </xsl:choose>
-									  </xsl:when>
-									  <xsl:when test="$entity//adl:property[@name=$field/@property]/@type='integer'">8</xsl:when>
-									  <xsl:when test="$entity//adl:property[@name=$field/@property]/@type='real'">8</xsl:when>
-									  <xsl:when test="$entity//adl:property[@name=$field/@property]/@type='money'">8</xsl:when>
-									  <!-- xsl:when test="$entity//adl:property[@name=$field/@property]/@type='message'">20</xsl:when doesn't work yet -->
-									  <xsl:when test="$entity//adl:property[@name=$field/@property]/@type='text'">20</xsl:when>
-									  <!-- xsl:when test="$entity//adl:property[@name=$field/@property]/@type='enity'">20</xsl:when doesn't work yet -->
-									  <xsl:otherwise>0</xsl:otherwise>
-								  </xsl:choose>
-							  </xsl:variable>
-							  <xsl:if test="$size != 0">
-								  <input>
-                    <xsl:variable name="search-name" select="concat('search_',$entity//adl:property[@name=$field/@property]/@name)"/>
-									  <xsl:attribute name="name">
-										  <xsl:value-of select="$search-name"/>
-									  </xsl:attribute>
-									  <xsl:attribute name="size">
-                      <xsl:choose>
-                        <xsl:when test="$size &gt; 8">8</xsl:when>
-                        <xsl:otherwise>
-                          <xsl:value-of select="$size"/>
-                        </xsl:otherwise>
-                      </xsl:choose>	  
-									  </xsl:attribute>
-									  <xsl:attribute name="value">
-										  <xsl:value-of select="concat( '$!', $search-name)"/>
-									  </xsl:attribute>
-								  </input>
-							  </xsl:if>
-						  </td>
-					  </xsl:for-each>
-					  <td>
-						  <input type="submit" name="search-button" value="Search"/>
-					  </td>
-				  </tr>
-			  </xsl:if>
-			  <xsl:if test="not( $entity/@name)">
-				  <xsl:message terminate="yes">
-					  Unknown entity whilst trying to generate list
-				  </xsl:message>
-			  </xsl:if>
-			  <xsl:variable name="readgroups">
-				  <xsl:call-template name="entity-read-groups">
-					  <xsl:with-param name="entity" select="$entity"/>
-				  </xsl:call-template>
-			  </xsl:variable>
-			  <xsl:choose>
-				  <xsl:when test="$authentication-layer = 'Application'">
-					  <xsl:call-template name="internal-with-fields-rows">
-						  <xsl:with-param name="instance-list" select="$instance-list"/>
-						  <xsl:with-param name="entity" select="$entity"/>
-						  <xsl:with-param name="fields"	select="$fields"/>
-					  </xsl:call-template>
-				  </xsl:when>
-				  <xsl:when test="$authentication-layer = 'Database'">
-					<!-- NOTE NOTE NOTE: This is whitespace-sensitive! -->
-					#if ( <xsl:for-each select="exsl:node-set( $readgroups)/*">${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} ||</xsl:for-each> false)
-					<xsl:call-template name="internal-with-fields-rows">
-						<xsl:with-param name="instance-list" select="$instance-list"/>
-						<xsl:with-param name="entity" select="$entity"/>
-						<xsl:with-param name="fields" select="$fields"/>
-					</xsl:call-template>
-					#else
-					<tr>
-						<td colspan="5">[You are not authorised to view this data]</td>
-					</tr>
-					#end
-				  </xsl:when>
-			  </xsl:choose>
-		  </table>
-	  </xsl:template>
-
-	<xsl:template name="internal-with-fields-rows">
-		<xsl:param name="instance-list"/>
-		<xsl:param name="entity"/>
-		<xsl:param name="fields"/>
-		#foreach( <xsl:value-of select="concat( '$', $entity/@name)"/> in <xsl:value-of select="concat('$', $instance-list)"/>)
-		#if ( $velocityCount % 2 == 0)
-		#set( $oddity = "even")
-		#else
-		#set( $oddity = "odd")
-		#end
-		<tr class="$oddity">
-			<xsl:for-each select="$fields">
-				<xsl:variable name="field" select="."/>
-				<xsl:call-template name="list-field">
-					<xsl:with-param name="entity" select="$entity"/>
-					<xsl:with-param name="property" select="$entity//adl:property[@name=$field/@property]"/>
-					<xsl:with-param name="objectvar" select="$entity/@name"/>
-				</xsl:call-template>
-			</xsl:for-each>
-			<xsl:variable name="keys">
-				<xsl:call-template name="entity-keys-fragment">
-					<xsl:with-param name="entity" select="$entity"/>
-				</xsl:call-template>
-			</xsl:variable>
-			<xsl:for-each select="$entity/adl:form">
-				<!-- by default create a link to each form declared for the entity. 
-                    We probably need a means of overriding this -->
-				<td>
-					<a>
-						<xsl:attribute name="href">
-							<xsl:value-of select="concat( '../', $entity/@name, '/', @name, '.rails', $keys)"/>
-						</xsl:attribute>
-						<xsl:value-of select="@name"/>
-					</a>
-				</td>
-			</xsl:for-each>
-		</tr>
-		#end
-	</xsl:template>
-
-	<xsl:template name="internal-with-properties-list">
-		<!-- a node-list of entities of type 'adl:property', each a property of the same entity, to be shown
-			in columns of this list -->
-		<xsl:param name="properties"/>
-		<!-- the entity of type 'adl:entity' on which the properties for all those fields can be found -->
-		<xsl:param name="entity"/>
-		<!-- the name of the list of instances of this entity, available to Velocity at runtime 
-				as an ICollection, which is to be layed out in this list -->
-		<xsl:param name="instance-list" select="'instances'"/>
-		<!-- NOTE NOTE NOTE: To be searchable, internal-with-properties-list must not only be called with can-search
-			equal to 'true', but also within a form! -->
-		<!-- NOTE NOTE NOTE: It's obvious that internal-with-fields-list and internal-with-properties-list
-			ought to be replaced with a single template, but that template proves to be extremely hard to get 
-			right -->
-		<xsl:param name="can-search"/>
-		<table class="sortable">
-			<tr>
-				<xsl:for-each select="$properties">
-					<th>
-						<xsl:call-template name="showprompt">
-							<xsl:with-param name="node" select="."/>
-							<xsl:with-param name="fallback" select="@name"/>
-							<xsl:with-param name="entity" select="$entity"/>
-							<xsl:with-param name="locale" select="$locale"/>
-						</xsl:call-template>
-					</th>
-				</xsl:for-each>
-				<xsl:for-each select="$entity/adl:form">
-					<th>-</th>
-				</xsl:for-each>
-			</tr>
-			<xsl:if test="$can-search = 'true'">
-				<tr class="search">
-					<xsl:for-each select="$properties">
-						<td class="search">
-							<xsl:variable name="size">
-								<xsl:choose>
-									<xsl:when test="@type='string'">
-										<xsl:choose>
-											<xsl:when test="@size &gt; 8">8</xsl:when>
-											<xsl:otherwise>
-												<xsl:value-of select="@size"/>
-											</xsl:otherwise>
-										</xsl:choose>
-									</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:when test="@type='message'">20</xsl:when doesn't work yet -->
-									<xsl:when test="@type='text'">8</xsl:when>
-									<!-- xsl:when test="@type='enity'">20</xsl:when doesn't work yet -->
-									<xsl:otherwise>0</xsl:otherwise>
-								</xsl:choose>
-							</xsl:variable>
-							<xsl:if test="$size != 0">
-								<input>
-									<xsl:attribute name="name">
-										<xsl:value-of select="concat('search_', @name)"/>
-									</xsl:attribute>
-									<xsl:attribute name="size">
-										<xsl:value-of select="$size"/>
-									</xsl:attribute>
-									<xsl:attribute name="value">
-										<xsl:value-of select="concat( '$!search_', @name)"/>
-									</xsl:attribute>
-								</input>
-							</xsl:if>
-						</td>
-					</xsl:for-each>
-					<td>
-						<input type="submit" name="search-button" size="8" value="Search"/>
-					</td>
-				</tr>
-			</xsl:if>
-			#foreach( <xsl:value-of select="concat( '$', $entity/@name)"/> in <xsl:value-of select="concat('$', $instance-list)"/>)
-			#if ( $velocityCount % 2 == 0)
-			#set( $oddity = "even")
-			#else
-			#set( $oddity = "odd")
-			#end
-			<tr class="$oddity">
-				<xsl:for-each select="$properties">
-					<xsl:call-template name="list-field">
-						<xsl:with-param name="entity" select="$entity"/>
-						<xsl:with-param name="property" select="."/>
-						<xsl:with-param name="objectvar" select="$entity/@name"/>
-					</xsl:call-template>
-				</xsl:for-each>
-				<xsl:variable name="keys">
-					<!-- assemble keys in a Velocity-friendly format, then splice it into
-                    the HREF below -->
-					<xsl:for-each select="$entity/adl:key/adl:property">
-						<xsl:variable name="sep">
-							<xsl:choose>
-								<xsl:when test="position()=1">?</xsl:when>
-								<xsl:otherwise>&amp;</xsl:otherwise>
-							</xsl:choose>
-						</xsl:variable>
-						<xsl:choose>
-							<xsl:when test="@type='entity'">
-								<xsl:value-of select="concat( $sep, @name, '=$', $entity/@name, '.', @name, '_Value')"/>
-							</xsl:when>
-							<xsl:otherwise>
-								<xsl:value-of select="concat( $sep, @name, '=$', $entity/@name, '.', @name)"/>
-							</xsl:otherwise>
-						</xsl:choose>
-					</xsl:for-each>
-				</xsl:variable>
-				<xsl:for-each select="$entity/adl:form">
-					<!-- by default create a link to each form declared for the entity. 
-                    We probably need a means of overriding this -->
-					<td>
-						<a>
-							<xsl:attribute name="href">
-								<xsl:value-of select="concat( '../', $entity/@name, '/', @name, '.rails', $keys)"/>
-							</xsl:attribute>
-							<xsl:value-of select="@name"/>
-						</a>
-					</td>
-				</xsl:for-each>
-			</tr>
-			#end
-		</table>
-	</xsl:template>
-
-	<!-- output a list field -->
-	<xsl:template name="list-field">
-		<xsl:param name="entity"/>
-		<xsl:param name="property"/>
-		<xsl:param name="objectvar" select="instance"/>
-		<xsl:variable name="readgroups">
-			<xsl:call-template name="property-read-groups">
-				<xsl:with-param name="property" select="$property"/>
-			</xsl:call-template>
-		</xsl:variable>
-		<td>
-			<xsl:choose>
-				<xsl:when test="$authentication-layer = 'Application'">
-					<xsl:call-template name="list-field-inner">
-						<xsl:with-param name="entity" select="$entity"/>
-						<xsl:with-param name="property" select="$property"/>
-						<xsl:with-param name="objectvar" select="$objectvar"/>
-					</xsl:call-template>
-				</xsl:when>
-				<xsl:when test="$authentication-layer = 'Database'">
-					<!-- NOTE NOTE NOTE: This is whitespace-sensitive! -->
-					#if ( <xsl:for-each select="exsl:node-set( $readgroups)/*">${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} ||</xsl:for-each> false)
-					<xsl:if test="$property/@type='entity'">
-						<!-- right, this is horrible. You can't read the field unless you can read the property; 
-						but even if you can read the property, if its an entity property you still can't read it
-						unless you can also read the entity -->
-						<xsl:variable name="entityreadgroups">
-							<xsl:call-template name="entity-read-groups">
-								<xsl:with-param name="entity" select="//adl:entity[@name=$property/@entity]"/>
-							</xsl:call-template>
-						</xsl:variable>
-						#if ( <xsl:for-each select="exsl:node-set( $entityreadgroups)/*">${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} ||</xsl:for-each> false)
-					</xsl:if>
-					<xsl:call-template name="list-field-inner">
-						<xsl:with-param name="entity" select="$entity"/>
-						<xsl:with-param name="property" select="$property"/>
-						<xsl:with-param name="objectvar" select="$objectvar"/>
-					</xsl:call-template>
-					<xsl:if test="$property/@type='entity'">
-						#else
-						[Not authorised]
-						#end
-					</xsl:if>
-					#else
-					[Not authorised]
-					#end
-				</xsl:when>
-			</xsl:choose>
-		</td>
-	</xsl:template>
-
-	<xsl:template name="list-field-inner">
-		<xsl:param name="entity"/>
-		<xsl:param name="property"/>
-		<xsl:param name="objectvar" select="instance"/>
-		<xsl:choose>
-			<xsl:when test="$property/adl:option">
-				<xsl:for-each select="$property/adl:option">
-					<xsl:variable name="val">
-						<xsl:variable name="base-type">
-							<xsl:call-template name="base-type">
-								<xsl:with-param name="property" select="$property"/>
-							</xsl:call-template>
-						</xsl:variable>
-						<xsl:choose>
-							<xsl:when test="$base-type = 'string'">
-								<xsl:value-of select="concat( '&#34;', @value, '&#34;')"/>
-							</xsl:when>
-							<xsl:otherwise>
-								<xsl:value-of select="@value"/>
-							</xsl:otherwise>
-						</xsl:choose>
-					</xsl:variable>
-					#if( <xsl:value-of select="concat( '$', $entity/@name, '.', $property/@name)"/> == <xsl:value-of select="$val"/>)
-					<xsl:call-template name="showprompt">
-						<xsl:with-param name="node" select="."/>
-						<xsl:with-param name="fallback" select="@value"/>
-					</xsl:call-template>
-					#end
-				</xsl:for-each>
-			</xsl:when> 
-			<xsl:when test="$property/@type = 'date'">
-				#if ( <xsl:value-of select="concat( '$', $entity/@name, '.', $property/@name)"/>)
-				<xsl:value-of select="concat( '$', $entity/@name, '.', $property/@name)"/>.ToString( 'd')
-				#end
-			</xsl:when>
-			<xsl:when test="$property/@type='message'">
-				#if ( <xsl:value-of select="concat( '$', $entity/@name, '.', $property/@name)"/>)
-				$t.Msg( <xsl:value-of select="concat( '$', $entity/@name, '.', $property/@name)"/>)
-				#end
-			</xsl:when>
-			<xsl:when test="$property/@type='entity'">
-				#if( <xsl:value-of select="concat( '$', $entity/@name, '.', $property/@name)"/>)
-				<xsl:value-of select="concat( '$', $entity/@name, '.', $property/@name, '.UserIdentifier')"/>
-				#end
-			</xsl:when>
-			<xsl:otherwise>
-				<xsl:value-of select="concat( '$!', $entity/@name, '.', $property/@name)"/>
-			</xsl:otherwise>
-		</xsl:choose>
-	</xsl:template>
-
-	<!-- generate head javascript for a form -->
-	<xsl:template name="generate-head-javascript">
-		<xsl:param name="form">
-			<!-- assumed to be an instance of adl:form -->
-		</xsl:param>
-    <xsl:param name="locale"/>
-		<script type='text/javascript' language='JavaScript1.2'>
-			#if ( ${site-root})
-			var siteRoot = '$siteRoot';
-			#else
-			var siteRoot = '<xsl:value-of select='$site-root'/>';
-      #end
-
-      var enterPressed = false;
-
-      function trapKeyPress(event, form){
-        if(event.which == 13){
-          enterPressed = true;
-        } else {
-          enterPressed = false;
-        }
-      }
-
-      function trapEnterSubmissions(event, form){
-        if(enterPressed){
-          enterPressed = false; //we have trapped this, can stand down
-          return false;
-        }
-      }
-
-      function performInitialisation()
-      {
-      #if ( $instance)
-      #if ( ! $instance.IsNew)
-      <xsl:for-each select="$form/ancestor::adl:entity/adl:property[@type='link']">
-				<xsl:variable name="propname" select="@name"/>
-				<xsl:choose>
-					<xsl:when test="$form/@properties='all'">
-						<xsl:value-of select="concat( 'document.',$form/@name, '.', @name, '.submitHandler = shuffleSubmitHandler;')"/>
-					</xsl:when>
-					<xsl:when test="$form//adl:field[@property=$propname]">
-						<xsl:value-of select="concat( 'document.',$form/@name, '.', @name, '.submitHandler = shuffleSubmitHandler;')"/>
-					</xsl:when>
-					<!-- if we're not doing all properties, and if this property is not the property of a field,
-						we /don't/ set up a submit handler. -->
-				</xsl:choose>
-			</xsl:for-each>
-			#end
-			#end
-			var validator = new Validation('<xsl:value-of select="$form/@name"/>', {immediate : true, useTitles : true});
-      }
-
-      <xsl:for-each select="//adl:typedef">
-				<xsl:variable name="errormsg">
-					<xsl:choose>
-						<xsl:when test="adl:help[@locale=$locale]">
-							<xsl:apply-templates select="adl:help[@locale=$locale]"/>
-						</xsl:when>
-						<xsl:otherwise>
-							<xsl:call-template name="i18n-bad-format">
-								<xsl:with-param name="format-name" select="@name"/>
-							</xsl:call-template>
-						</xsl:otherwise>
-					</xsl:choose>
-				</xsl:variable>
-				Validation.add( '<xsl:value-of select="concat('validate-custom-', @name)"/>',
-				'<xsl:value-of select="normalize-space( $errormsg)"/>',
-				{
-				<xsl:choose>
-					<xsl:when test="@pattern">
-						pattern : new RegExp("<xsl:value-of select="@pattern"/>","gi")<xsl:if test="@size">
-							, maxLength : <xsl:value-of select="@size"/>
-						</xsl:if>
-					</xsl:when>
-					<xsl:when test="@minimum">
-						min : <xsl:value-of select="@minimum"/><xsl:if test="@maximum">
-							, max : <xsl:value-of select="@maximum"/>
-						</xsl:if>
-					</xsl:when>
-				</xsl:choose>
-				});
-			</xsl:for-each>
-		</script>
-	</xsl:template>
-
-	<!-- this template outputs MOST types of widget, but NOT shuffle widgets -->
-	<xsl:template name="property-widget">
-		<xsl:param name="property"/>
-		<xsl:param name="mode"/>
-		<xsl:variable name="base-type">
-			<xsl:call-template name="base-type">
-				<xsl:with-param name="property" select="$property"/>
-			</xsl:call-template>
-		</xsl:variable>
-		<xsl:variable name="href">
-			<xsl:choose>
-				<xsl:when test="$property/@type='entity' and //adl:entity[@name=$property/@entity]/adl:form[@name='edit']">
-					<!-- if this is an entity property, and the entity which it wraps has an edit form -->
-					<xsl:variable name="keys">
-						<xsl:call-template name="entity-keys-fragment">
-							<xsl:with-param name="entity" select="//adl:entity[@name=$property/@entity]"/>
-							<xsl:with-param name="instance" select="concat( 'instance.', $property/@name)"/>
-						</xsl:call-template>
-					</xsl:variable>
-					<xsl:value-of select="concat( '../', $property/@entity, '/edit.rails', $keys)"/>
-				</xsl:when>
-			</xsl:choose>
-		</xsl:variable>
-		<xsl:variable name="if-missing">
-			<xsl:choose>
-				<xsl:when test="$property/adl:if-missing[@locale = $locale]">
-					<xsl:value-of select="$property/adl:if-missing[@locale = $locale]"/>
-				</xsl:when>
-				<xsl:when test="$property/@required='true'">
-					<xsl:call-template name="i18n-value-required">
-						<xsl:with-param name="property-name" select="$property/@name"/>
-					</xsl:call-template>
-				</xsl:when>
-				<xsl:when test="$property/@type='defined'">
-					<xsl:call-template name="i18n-value-defined">
-						<xsl:with-param name="property-name" select="$property/@name"/>
-						<xsl:with-param name="definition-name" select="$property/@typedef"/>
-					</xsl:call-template>
-				</xsl:when>
-				<xsl:when test="$property/@type='entity'">
-					<xsl:call-template name="i18n-value-entity">
-						<xsl:with-param name="property-name" select="$property/@name"/>
-						<xsl:with-param name="entity-name" select="$property/@entity"/>
-					</xsl:call-template>
-				</xsl:when>
-				<xsl:otherwise>
-					<xsl:call-template name="i18n-value-type">
-						<xsl:with-param name="property-name" select="$property/@name"/>
-						<xsl:with-param name="type-name" select="$property/@type"/>
-					</xsl:call-template>
-				</xsl:otherwise>
-			</xsl:choose>
-		</xsl:variable>
-		<xsl:variable name="cssclass">
-			<xsl:if test="$property/@required='true'">required </xsl:if>
-			<xsl:choose>
-				<xsl:when test="$property/@type='defined'">
-					<xsl:choose>
-						<xsl:when test="//adl:typedef[@name=$property/@typedef]/@pattern">
-							<xsl:value-of select="concat( 'validate-custom-', $property/@typedef)"/>
-						</xsl:when>
-						<xsl:when test="//adl:typedef[@name=$property/@typedef]/@minimum">
-							<xsl:value-of select="concat( 'validate-custom-', $property/@typedef)"/>
-						</xsl:when>
-					</xsl:choose>
-				</xsl:when>
-				<xsl:when test="$base-type='integer'">validate-digits</xsl:when>
-				<xsl:when test="$base-type='real'">validate-number</xsl:when>
-				<xsl:when test="$base-type='money'">validate-number</xsl:when>
-				<xsl:when test="$base-type='date'">date-field validate-date</xsl:when>
-			</xsl:choose>
-		</xsl:variable>
-		<xsl:variable name="maxlength">
-			<xsl:call-template name="base-size">
-				<xsl:with-param name="property" select="$property"/>
-			</xsl:call-template>
-		</xsl:variable>
-		<xsl:variable name="size">
-			<xsl:choose>
-				<xsl:when test="$maxlength &gt; $max-widget-width">
-					<xsl:value-of select="$max-widget-width"/>
-				</xsl:when>
-				<xsl:otherwise>
-					<xsl:value-of select="$maxlength"/>
-				</xsl:otherwise>
-			</xsl:choose>
-		</xsl:variable>
-		<xsl:variable name="rows">
-			<!-- number of rows, if textarea emitted -->
-			<xsl:choose>
-				<xsl:when test="$base-type = 'text'">8</xsl:when>
-				<xsl:otherwise>1</xsl:otherwise>
-			</xsl:choose>
-		</xsl:variable>
-		<xsl:variable name="cols">
-			<!-- number of rows, if textarea emitted -->
-			<xsl:choose>
-				<xsl:when test="$base-type = 'text'">
-					<xsl:value-of select="$max-widget-width"/>
-				</xsl:when>
-				<xsl:otherwise>10</xsl:otherwise>
-			</xsl:choose>
-		</xsl:variable>
-		<xsl:variable name="required">
-			<xsl:choose>
-				<xsl:when test="$property/@required='true'">true</xsl:when>
-				<xsl:otherwise>false</xsl:otherwise>
-			</xsl:choose>
-		</xsl:variable>
-		<xsl:choose>
-			<xsl:when test="$property/adl:option">
-				<!-- emit a menu of options -->
-				<!-- it would be better to do this through a field helper but I haven't yet worked out how -->
-				<select>
-					<xsl:attribute name="name">
-						<xsl:value-of select="concat( 'instance.', $property/@name)"/>
-					</xsl:attribute>
-					<xsl:attribute name="id">
-						<xsl:value-of select="concat( 'instance_', $property/@name)"/>
-					</xsl:attribute>
-					<xsl:attribute name="class">
-						<xsl:value-of select="concat( 'instance.', $property/@name)"/>
-					</xsl:attribute>
-					<xsl:if test="not( $property/@required='true')">
-						<option value="'-1'">[unselected]</option>
-					</xsl:if>
-					<xsl:apply-templates select="$property/adl:option"/>
-				</select>
-				<script type="text/javascript" language="javascript">
-					// &lt;![CDATA[
-					#set ( <xsl:value-of select="concat( '$', $property/@name, '_sel_opt')"/>="<xsl:value-of select="concat( $property/@name, '-$instance.', $property/@name)"/>")
-					option = document.getElementById( "<xsl:value-of select="concat( '$', $property/@name, '_sel_opt')"/>");
-
-					if ( option != null)
-					{
-					option.selected = true;
-					}
-					// ]]&gt;
-				</script>
-
-			</xsl:when>
-			<xsl:when test="$property/@type = 'defined'">
-				<!-- it would be better to do this through a field helper but I haven't yet worked out how -->
-				<xsl:variable name="definition" select="//adl:typedef[@name=$property/@typedef]"/>
-				<xsl:variable name="minimum" select="$definition/@minimum"/>
-				<xsl:choose>
-					<xsl:when test="$base-type='string'">
-						${<xsl:value-of select="concat( $property/ancestor::adl:entity/@name, 'FieldHelper', '.', $mode, '(')"/> "<xsl:value-of select="concat( 'instance.', $property/@name)"/>", "%{class='<xsl:value-of select="normalize-space($cssclass)"/>',required='<xsl:value-of select="normalize-space( $required)"/>',title='<xsl:value-of select="normalize-space($if-missing)"/>',size='<xsl:value-of select="normalize-space($size)"/>',maxlength='<xsl:value-of select="normalize-space($maxlength)"/>',rows='<xsl:value-of select="normalize-space($rows)"/>',href='<xsl:value-of select="normalize-space($href)"/>'}")}
-					</xsl:when>
-					<xsl:when test="string-length($definition/@minimum) &gt; 0 and string-length( $definition/@maximum) &gt; 0">
-						<xsl:call-template name="slider-widget">
-							<xsl:with-param name="property" select="$property"/>
-							<xsl:with-param name="minimum" select="$definition/@minimum"/>
-							<xsl:with-param name="maximum" select="$definition/@maximum"/>
-						</xsl:call-template>
-						${<xsl:value-of select="concat( $property/ancestor::adl:entity/@name, 'FieldHelper', '.', $mode, '(')"/> "<xsl:value-of select="concat( 'instance.', $property/@name)"/>", "%{class='<xsl:value-of select="concat('slider, ', normalize-space($cssclass))"/>',title='<xsl:value-of select="normalize-space($if-missing)"/>',size='<xsl:value-of select="normalize-space($size)"/>',maxlength='<xsl:value-of select="normalize-space($maxlength)"/>',rows='<xsl:value-of select="normalize-space($rows)"/>',href='<xsl:value-of select="normalize-space($href)"/>'}")}
-					</xsl:when>
-					<xsl:otherwise>
-						${<xsl:value-of select="concat( $property/ancestor::adl:entity/@name, 'FieldHelper', '.', $mode, '(')"/> "<xsl:value-of select="concat( 'instance.', $property/@name)"/>", "%{class='<xsl:value-of select="normalize-space($cssclass)"/>',required='<xsl:value-of select="normalize-space( $required)"/>',title='<xsl:value-of select="normalize-space($if-missing)"/>',size='<xsl:value-of select="normalize-space($size)"/>',maxlength='<xsl:value-of select="normalize-space($maxlength)"/>',rows='<xsl:value-of select="normalize-space($rows)"/>',href='<xsl:value-of select="normalize-space($href)"/>'}")}
-					</xsl:otherwise>
-				</xsl:choose>
-			</xsl:when>
-			<xsl:when test="$property/@type = 'entity'">
-				<!-- once again, not only must you have access to the property but also to the entity -->
-				<xsl:variable name="readgroups">
-					<xsl:call-template name="entity-read-groups">
-						<xsl:with-param name="entity" select="//adl:entity[@name=$property/@entity]"/>
-					</xsl:call-template>
-				</xsl:variable>
-				<!-- NOTE! NOTE! NOTE! Whitespace is significant - any linefeeds inside the #if ( ) clause cause the Velocity parser to break! -->
-				#if ( <xsl:for-each select="exsl:node-set( $readgroups)/*">${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} ||</xsl:for-each> false)
-				${<xsl:value-of select="concat( $property/ancestor::adl:entity/@name, 'FieldHelper', '.', $mode, '(')"/> "<xsl:value-of select="concat( 'instance.', $property/@name)"/>", "%{class='<xsl:value-of select="normalize-space($cssclass)"/>',required='<xsl:value-of select="normalize-space( $required)"/>',title='<xsl:value-of select="normalize-space($if-missing)"/>',size='<xsl:value-of select="normalize-space($size)"/>',maxlength='<xsl:value-of select="normalize-space($maxlength)"/>',rows='<xsl:value-of select="normalize-space($rows)"/>',href='<xsl:value-of select="normalize-space($href)"/>'}")}
-				#else
-				[Not authorised]
-				#end
-			</xsl:when>
-			<xsl:otherwise>
-				${<xsl:value-of select="concat( $property/ancestor::adl:entity/@name, 'FieldHelper', '.', $mode, '(')"/> "<xsl:value-of select="concat( 'instance.', $property/@name)"/>", "%{class='<xsl:value-of select="normalize-space($cssclass)"/>',required='<xsl:value-of select="normalize-space( $required)"/>',title='<xsl:value-of select="normalize-space($if-missing)"/>',size='<xsl:value-of select="normalize-space($size)"/>',maxlength='<xsl:value-of select="normalize-space($maxlength)"/>',rows='<xsl:value-of select="normalize-space($rows)"/>',cols='<xsl:value-of select="normalize-space($cols)"/>',href='<xsl:value-of select="normalize-space($href)"/>'}")}
-      </xsl:otherwise>				
-		</xsl:choose>
-	</xsl:template>
-
-	<xsl:template name="slider-widget">
-		<xsl:param name="property"/>
-		<xsl:param name="minimum" select="0"/>
-		<xsl:param name="maximum" select="100"/>
-		<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( $property/@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( $property/@name, '-track-left')"/>
-					</xsl:attribute>
-				</div>
-				<div style="width:19px; height:20px;">
-					<xsl:attribute name="id">
-						<xsl:value-of select="concat( $property/@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="$property/@name"/>-slider','<xsl:value-of select="$property/@name"/>-track',{
-				onSlide:function(v){$('<xsl:value-of select="concat( 'instance_', $property/@name)"/>').value = <xsl:value-of select="$minimum"/>+ Math.floor(v*(<xsl:value-of select="$maximum - $minimum"/>))}
-        });
-        // ]]&gt;
-			</script>
-		</xsl:if>
-	</xsl:template>
-
-	<!-- assemble keys for this entity in a Velocity-friendly format, to splice into an HREF below -->
-	<xsl:template name="entity-keys-fragment">
-		<xsl:param name="entity"/>
-		<xsl:param name="instance" select="$entity/@name"/>
-		<xsl:for-each select="$entity/adl:key/adl:property">
-			<xsl:variable name="sep">
-				<xsl:choose>
-					<xsl:when test="position()=1">?</xsl:when>
-					<xsl:otherwise>&amp;</xsl:otherwise>
-				</xsl:choose>
-			</xsl:variable>
-			<xsl:choose>
-				<xsl:when test="@type='entity'">
-					<xsl:value-of select="concat( $sep, @name, '=$', $instance, '.', @name, '_Value')"/>
-				</xsl:when>
-				<xsl:otherwise>
-					<xsl:value-of select="concat( $sep, @name, '=$', $instance, '.', @name)"/>
-				</xsl:otherwise>
-			</xsl:choose>
-		</xsl:for-each>
-	</xsl:template>
-
-	<!-- overall page layout -->
-
-	<xsl:template match="adl:content"/>
-
-	<xsl:template match="adl:help">
-		<xsl:apply-templates/>
-	</xsl:template>
-
-	<!-- assuming an empty layout, install all the standard scripts 
-    which an ADL page may need -->
-	<xsl:template name="install-scripts">
-    ${ScriptsHelper.InstallScript( "ShuffleWidget")}
-
-    ${Ajax.InstallScripts()}
-    ${FormHelper.InstallScripts()}
-    ${Validation.InstallScripts()}
-    ${Scriptaculous.InstallScripts()}
-    ${DateTimeHelper.InstallScripts()}
-
-    ${ScriptsHelper.InstallScript( "Sitewide")}
-    ${ScriptsHelper.InstallScript( "Behaviour")}
-    ${ScriptsHelper.InstallScript( "Epoch")}
-    ${ScriptsHelper.InstallScript( "Panes")}
-    ${ScriptsHelper.InstallScript( "SortTable")}
-  </xsl:template>
-
-  <!-- standard header material - auto-timeout, etc -->
-	<xsl:template name="head">
-    <xsl:comment>
-      <xsl:value-of select="/adl:application/@name"/> <xsl:value-of select="$product-version"/> - <xsl:value-of select="/adl:application/@revision"/>
-      Auto generated Velocity macro for <xsl:value-of select="@name"/>,
-      generated from ADL.
-
-      Generated using adl2views.xslt <xsl:value-of select="substring( '$Revision: 1.65 $', 10)"/>
-      Generation parameters were:
-      area-name: <xsl:value-of select="$area-name"/>
-      default-url: <xsl:value-of select="$default-url"/>
-      generate-site-navigation: <xsl:value-of select="$generate-site-navigation"/>
-      layout-name: <xsl:value-of select="$layout-name"/>
-      locale: <xsl:value-of select="$locale"/>
-      max-widget-width: <xsl:value-of select="$max-widget-width"/>
-      product-version: <xsl:value-of select="$product-version"/>
-      page-timeout: <xsl:value-of select="$page-timeout"/>
-      show-errors: <xsl:value-of select="$show-errors"/>
-      show-messages: <xsl:value-of select="$show-messages"/>
-    </xsl:comment>
-    <xsl:if test="$page-timeout &gt; 0">
-      <meta http-equiv="refresh">
-        <xsl:attribute name="content">
-          <xsl:value-of select="concat($page-timeout, '; URL=', $default-url)"/>
-        </xsl:attribute>
-      </meta>
-    </xsl:if>
-    <xsl:choose>
-      <xsl:when test="adl:head">
-        <xsl:for-each select="adl:head/*">
-          <xsl:apply-templates select="."/>
-        </xsl:for-each>
-      </xsl:when>
-      <xsl:otherwise>
-        <xsl:for-each select="//adl:content/adl:head/*">
-					<xsl:apply-templates select="."/>
-        </xsl:for-each>
-      </xsl:otherwise>
-    </xsl:choose>
-  </xsl:template>
-  
-  <!-- standard top area content on all pages (navigation, etc) -->
-  <xsl:template name="top">
-    <xsl:choose>
-      <xsl:when test="adl:top">
-        <xsl:for-each select="adl:top/*">
-          <xsl:apply-templates select="."/>
-        </xsl:for-each>
-      </xsl:when>
-      <xsl:otherwise>
-        <xsl:for-each select="//adl:content/adl:top/*">
-          <xsl:apply-templates select="."/>
-        </xsl:for-each>
-      </xsl:otherwise>
-    </xsl:choose>
-    <xsl:if test="$authentication-layer = 'Database'">
-      #if ( ${SecurityHelper.GetUserName()})
-      <!-- the #else and #end of this #if is generated in the foot template -->
-    </xsl:if>
-    <xsl:variable name="current-entity" select="ancestor::adl:entity/@name"/>
-    <xsl:if test="$generate-site-navigation = 'true'">
-      <ul class="generatednav">
-        <xsl:for-each select="//adl:entity[adl:list[@name='list']]">
-          <xsl:variable name="readgroups">
-            <xsl:call-template name="page-read-groups">
-              <xsl:with-param name="page" select="."/>
-            </xsl:call-template>
-          </xsl:variable>
-          <xsl:if test="$authentication-layer = 'Database'">
-            #if ( <xsl:for-each select="exsl:node-set( $readgroups)/*"> ${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} ||</xsl:for-each> false)
-          </xsl:if>
-          <li>
-            <xsl:attribute name="class">
-              <xsl:choose>
-                <xsl:when test="@name = $current-entity">selected-nav</xsl:when>
-                <xsl:otherwise>navigation</xsl:otherwise>
-              </xsl:choose>
-            </xsl:attribute>
-            <a>
-              <xsl:attribute name="href">
-                <xsl:choose>
-                  <xsl:when test="string-length( $site-root) &gt; 0">
-                    <xsl:choose>
-                      <xsl:when test="string-length( $area-name) &gt; 0">
-                        <xsl:value-of select="concat( $site-root, '/', $area-name, '/', @name, '/', adl:list[position()=1]/@name, '.rails')"/>
-                      </xsl:when>
-                      <xsl:otherwise>
-                        <xsl:value-of select="concat( $site-root, '/', @name, '/', adl:list[position()=1]/@name, '.rails')"/>
-                      </xsl:otherwise>
-                    </xsl:choose>
-                  </xsl:when>
-                  <xsl:when test="string-length( $area-name) &gt; 0">
-                    <xsl:value-of select="concat( '/', $area-name, '/', @name, '/', adl:list[position()=1]/@name, '.rails')"/>
-                  </xsl:when>
-                  <xsl:otherwise>
-                    <xsl:value-of select="concat( '/', @name, '/', adl:list[position()=1]/@name, '.rails')"/>
-                  </xsl:otherwise>
-                </xsl:choose>
-              </xsl:attribute>
-              <xsl:call-template name="showprompt">
-                <xsl:with-param name="fallback" select="@name"/>
-                <xsl:with-param name="entity" select="."/>
-              </xsl:call-template>
-            </a>
-          </li>
-          <xsl:if test="$authentication-layer = 'Database'">
-            #end
-          </xsl:if>
-        </xsl:for-each>
-      </ul>
-    </xsl:if>
-  </xsl:template>
-
-  <!-- standard footer on all pages; product identifier and version -->
-  <xsl:template name="foot">
-    <xsl:if test="$authentication-layer = 'Database'">
-      <!-- the #if for this #else and #end is generated in the head template -->
-      #else
-      <div class="content">
-        <p>
-          To view this page you must first <a href="../dblogin/login.rails">Log in</a>
-        </p>
-      </div>
-      #end
-    </xsl:if>
-    <div class="pagefoot">
-      <xsl:choose>
-        <xsl:when test="adl:foot">
-          <xsl:for-each select="adl:foot/*">
-            <xsl:apply-templates select="."/>
-          </xsl:for-each>
-        </xsl:when>
-        <xsl:otherwise>
-          <xsl:for-each select="//adl:content/adl:foot/*">
-            <xsl:apply-templates select="."/>
-          </xsl:for-each>
-        </xsl:otherwise>
-      </xsl:choose>
-      <p class="product-version">
-        <xsl:value-of select="$product-version"/>; built with <xsl:value-of select="$authentication-layer"/>-layer authentication.
-      </p>
-    </div>
-  </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:param name="entity" select="$node/ancestor::adl:entity"/>
-		<xsl:param name="locale" select="'en-GB'"/>
-		<xsl:choose>
-			<xsl:when test="$node/adl:prompt[@locale=$locale]">
-				<xsl:value-of select="$node/adl:prompt[@locale=$locale][1]/@prompt"/>
-			</xsl:when>
-			<xsl:when test="$node/adl:prompt[@locale='default']">
-				<xsl:value-of select="$node/adl:prompt[@locale='default'][1]/@prompt"/>
-			</xsl:when>
-			<xsl:when test="$node/@property">
-				<!-- it's (probably) a field which doesn't have any prompt of its own - 
-					fetch from its property -->
-				<xsl:variable name="propname" select="@property"/>
-				<xsl:call-template name="showprompt">
-					<xsl:with-param name="fallback" select="$fallback"/>
-					<xsl:with-param name="node" select="$entity//adl:property[@name=$propname]"/>
-					<xsl:with-param name="entity" select="$entity"/>
-					<xsl:with-param name="locale" select="$locale"/>
-				</xsl:call-template>
-			</xsl:when>	  
-			<xsl:otherwise>
-				<xsl:value-of select="$fallback"/>
-			</xsl:otherwise>
-		</xsl:choose>
-	</xsl:template>
-
-  <!-- compose the list of search parameters to append to a pagination request; note that this does
-  not currently work but I have some hopes that in future it will and in the meantime it costs us
-  little -->
-  <xsl:template name="pagination-search-params">
-    <xsl:param name="form" select="."/>
-    "%{<xsl:for-each select="$form/adl:field">
-      <xsl:variable name="field" select="."/>
-      <xsl:variable name="search-name"
-                    select="concat('search_',$form/ancestor::adl:entity//adl:property[@name=$field/@property]/@name)"/>
-      <xsl:value-of select="concat( $search-name, '=$', $search-name)"/>
-      <xsl:if test="not( position() = last())">,</xsl:if>
-    </xsl:for-each>}"
-  </xsl:template>
-
-	<xsl:template match="groups">
-		<xsl:apply-templates/>
-	</xsl:template>
-
-    <!-- just copy anything we can't match -->
-  <xsl:template match="@* | node()">
-    <xsl:copy>
-      <xsl:apply-templates select="@* | node()"/>
-    </xsl:copy>
-  </xsl:template>
-
+<?xml version="1.0" encoding="UTF-8" ?>
+<xsl:stylesheet version="1.0"
+	xmlns="http://libs.cygnets.co.uk/adl/1.4/"
+	xmlns:adl="http://libs.cygnets.co.uk/adl/1.4/"
+	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+	xmlns:msxsl="urn:schemas-microsoft-com:xslt"
+				xmlns:exsl="urn:schemas-microsoft-com:xslt"
+                extension-element-prefixes="exsl">
+	<!--
+    Application Description Language framework
+    adl2views.xsl
+    
+    (c) 2007 Cygnet Solutions Ltd
+    
+    Transform ADL into velocity view templates
+    
+    $Author: simon $
+    $Revision: 1.66 $
+    $Date: 2010-07-20 19:53:40 $
+	-->
+	<!-- WARNING WARNING WARNING: Do NOT reformat this file! 
+		Whitespace (or lack of it) is significant! -->
+
+	<xsl:include href="base-type-include.xslt"/>
+	<xsl:include href="permissions-include.xslt"/>
+  <!-- bug 1896 : boilerplate text in views should be tailored to the locale of
+		the expected user. Unfortunately I haven't yet worked out how to do
+		conditional includes in XSLT, so this is a step on the way to a solution,
+		not a solution in itself. -->
+  <xsl:include href="i18n-en-GB-include.xslt"/>
+
+  <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-GB"/>
+
+	<!-- whether or not to auto-generate site navigation - by default, don't -->
+	<xsl:param name="generate-site-navigation" select="'false'"/>
+
+	<!-- whether or not to layout errors - they may be in the default layout -->
+	<xsl:param name="show-errors" select="'false'"/>
+	<!-- whether or not to layout messages - they may be in the default layout -->
+	<xsl:param name="show-messages" select="'false'"/>
+
+	<!-- the maximum width, in characters, we're prepared to allocate to widgets -->
+	<xsl:param name="max-widget-width" select="40"/>
+
+	<!-- the name and version of the product being built -->
+	<xsl:param name="product-version" select="'Application Description Language Framework'"/>
+
+	<!-- bug 1800 : the name of the Velocity layout to use. If you are to 
+		be able to usefully define content in ADL, then the default ADL layout 
+		needs to be empty, but if ADL-generated pages are to 'play nice' in
+		largely non-ADL applications, they must be able to use standard layouts.
+		If you are going to use a non-default layout, however, you're responsible
+		for making sure it loads all the scripts, etc, that an ADL controller 
+		expects. -->
+	<xsl:param name="layout-name"/>
+	<!-- bug 1800 : the name of the area (i.e. URL path part) to use -->
+	<xsl:param name="area-name" select="auto"/>
+	<!-- the base url of the whole site -->
+	<xsl:param name="site-root" select="'..'"/>
+	<!-- Whether to authenticate at application or at database layer. 
+    If not 'Application', then 'Database'. -->
+	<xsl:param name="authentication-layer" select="'Application'"/>
+
+  <!-- bug 2847: how long to wait on a page before it auto-redirects to the default URL -->
+  <xsl:param name="page-timeout" select="300"/>
+  <!-- bug 2847: the default URL, probably a 'please login' screen -->
+  <xsl:param name="default-url" select="'../default.aspx'"/>
+
+	<xsl:template match="adl:application">
+		<output>
+			<!-- 'output' is a dummy wrapper root tag to make the entire output work as
+				an XML document; the actual output later gets cut into chunks and the
+				wrapper tag is discarded. -->
+			<xsl:apply-templates select="adl:entity"/>
+			<!-- make sure extraneous junk doesn't get into the last file generated,
+				by putting it into a separate file -->
+			<xsl:text>
+			  </xsl:text>
+			<xsl:comment> [ cut here: next file 'tail.txt' ] </xsl:comment>
+		</output>
+	</xsl:template>
+
+	<xsl:template match="adl:entity[@foreign='true']"/>
+	<!-- Don't bother generating anything for foreign entities -->
+
+	<xsl:template match="adl:entity">
+		<xsl:comment>Layout is <xsl:value-of select="$layout-name"/></xsl:comment>
+		<xsl:choose>
+			<xsl:when test="$layout-name">
+				<xsl:apply-templates select="." mode="non-empty-layout"/>
+			</xsl:when>
+			<xsl:otherwise>
+				<xsl:apply-templates select="." mode="empty-layout"/>
+			</xsl:otherwise>
+		</xsl:choose>
+	</xsl:template>
+
+	<!-- generate views for an entity, assuming a non-empty layout - i.e. 
+    I'm not responsible for the html, the head, or for the body tag -->
+	<xsl:template match="adl:entity" mode="non-empty-layout">
+		<xsl:variable name="keyfield">
+			<xsl:choose>
+				<xsl:when test="adl:key/adl:property">
+					<xsl:value-of select="adl:key/adl:property[position()=1]/@name"/>
+				</xsl:when>
+				<xsl:otherwise>[none]</xsl:otherwise>
+			</xsl:choose>
+		</xsl:variable>
+		<xsl:apply-templates select="adl:form" mode="non-empty-layout"/>
+		<xsl:apply-templates select="adl:list" mode="non-empty-layout"/>
+		<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>
+		<xsl:variable name="really-delete">
+			<xsl:call-template name="i18n-really-delete"/>
+		</xsl:variable>
+		#set( $title = "<xsl:value-of select="concat( $really-delete, ' ', @name)"/> $instance.UserIdentifier")
+    #capturefor( headextras)
+    <xsl:comment>
+			Auto generated Velocity maybe-delete form for <xsl:value-of select="@name"/>,
+		</xsl:comment>
+    <xsl:call-template name="head"/>
+    #end
+    <xsl:call-template name="maybe-delete">
+      <xsl:with-param name="entity" select="."/>
+    </xsl:call-template>
+  </xsl:template>
+
+	<!-- generate views for an entity, assuming an empty layout 
+			(i.e. I'm responsible for html, head and body tags) -->
+		<xsl:template match="adl:entity" mode="empty-layout">
+			<xsl:variable name="keyfield">
+				<xsl:choose>
+					<xsl:when test="adl:key/adl:property">
+						<xsl:value-of select="adl:key/adl:property[position()=1]/@name"/>
+					</xsl:when>
+					<xsl:otherwise>[none]</xsl:otherwise>
+				</xsl:choose>
+			</xsl:variable>
+
+			<xsl:apply-templates select="adl:form" mode="empty-layout"/>
+			<xsl:apply-templates select="adl:list" mode="empty-layout"/>
+			<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:variable name="really-delete">
+					<xsl:call-template name="i18n-really-delete"/>
+				</xsl:variable>
+				#set( $title = "<xsl:value-of select="concat( $really-delete, ' ', @name)"/> $instance.UserIdentifier")
+				<head>
+          <xsl:comment>
+            Auto generated Velocity maybe-delete form for <xsl:value-of select="@name"/>,
+          </xsl:comment>
+          <xsl:call-template name="head"/>
+					<xsl:call-template name="install-scripts"/>
+				</head>
+				<body>
+          <div id="page">
+            <xsl:call-template name="top"/>
+            <xsl:call-template name="maybe-delete">
+              <xsl:with-param name="entity" select="."/>
+            </xsl:call-template>
+            <xsl:call-template name="foot"/>
+          </div>
+        </body>
+			</html>
+		</xsl:template>
+
+		<!-- the guts of the maybe-delete form, whether or not we're using an empty layout -->
+  <xsl:template name="maybe-delete">
+    <xsl:param name="entity"/>
+    <div class="content">
+      <xsl:if test="$show-errors = 'true'">
+        #if ( $instance.NoDeleteReason)
+        <ul class="errors">
+          <li>$instance.NoDeleteReason</li>
+        </ul>
+        #end
+        #if ( $errors)
+        #if ( $errors.Count != 0)
+        <ul class="errors">
+          #foreach($e in $errors)
+          #if($e.Message)
+          <li>$t.Error($e)</li>
+          #else
+          <li>$t.Enc($e)</li>
+          #end
+          #end
+        </ul>
+        #end
+        #end
+      </xsl:if>
+      <xsl:if test="$show-messages = 'true'">
+        #if( $messages)
+        #if ( $messages.Count != 0)
+        <ul class="information">
+          #foreach ( $message in $messages)
+          <li>$message</li>
+          #end
+        </ul>
+        #end
+        #end
+      </xsl:if>
+      <form action="delete.rails" method="post">
+        <xsl:for-each select="$entity/adl:key/adl:property">
+          <xsl:choose>
+            <xsl:when test="@type='entity'">
+              <xsl:variable name="entityname" select="@entity"/>
+              <xsl:variable name="entitykeyname" select="//adl:entity[@name=$entityname]/adl:key/adl:property[position()=1]/@name"/>
+              <input type="hidden">
+                <xsl:attribute name="name">
+                  <xsl:value-of select="concat( 'instance.', @name)"/>
+                </xsl:attribute>
+                <xsl:attribute name="value">
+                  <xsl:value-of select="concat('$instance.', @name, '.', $entitykeyname)"/>
+                </xsl:attribute>
+              </input>
+            </xsl:when>
+            <xsl:otherwise>
+              <input type="hidden">
+                <xsl:attribute name="name">
+                  <xsl:value-of select="concat( 'instance.', @name)"/>
+                </xsl:attribute>
+                <xsl:attribute name="value">
+                  <xsl:value-of select="concat('$instance.', @name)"/>
+                </xsl:attribute>
+              </input>
+            </xsl:otherwise>
+          </xsl:choose>
+        </xsl:for-each>
+        <table>
+          <tr align="left" valign="top" class="actionDangerous">
+            <td class="actionDangerous">
+              <xsl:call-template name="i18n-really-delete"/>
+            </td>
+            <td class="widget">
+              <select name="reallydelete">
+                <option value="false">
+                  <xsl:call-template name="i18n-really-delete-no"/>
+                </option>
+                <option value="true">
+                  <xsl:call-template name="i18n-really-delete-yes"/>
+                </option>
+              </select>
+            </td>
+            <td class="actionDangerous" style="text-align:right">
+              <input type="submit" name="command" value="Go" />
+            </td>
+          </tr>
+        </table>
+      </form>
+    </div>
+  </xsl:template>
+
+  <!-- layout of forms -->
+	<xsl:template match="adl:form" mode="non-empty-layout">
+		<xsl:variable name="form" select="."/>
+		<xsl:text>
+		</xsl:text>
+		<xsl:comment>[ cut here: next file '<xsl:value-of select="concat( ancestor::adl:entity/@name, '/', @name)"/>.auto.vm' ]</xsl:comment>
+		<xsl:text>
+    </xsl:text>
+		#capturefor( title)
+    #if ( $instance)
+		#if ( ! $instance.IsNew)
+		<xsl:value-of select="concat( 'Edit ', ' ', ancestor::adl:entity/@name)"/> $instance.UserIdentifier
+		#else
+		<xsl:call-template name="i18n-add-a-new">
+			<xsl:with-param name="entity-name" select="ancestor::adl:entity/@name"/>
+		</xsl:call-template>
+    #end
+    #else
+    <xsl:call-template name="i18n-add-a-new">
+      <xsl:with-param name="entity-name" select="ancestor::adl:entity/@name"/>
+    </xsl:call-template>
+    #end
+    #end
+    #capturefor( headextras)
+    <xsl:comment>
+      Auto generated Velocity form for <xsl:value-of select="ancestor::adl:entity/@name"/>,
+    </xsl:comment>
+    <xsl:call-template name="head"/>
+		<xsl:call-template name="generate-head-javascript">
+			<xsl:with-param name="form" select="."/>
+      <xsl:with-param name="locale" select="$locale"/>
+		</xsl:call-template>
+
+		${StylesHelper.InstallStylesheet( "Epoch")}
+
+		<style type="text/css">
+			<xsl:for-each select="ancestor::adl:entity//adl: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>
+		#end
+		#capturefor(bodyattributes)
+		onload="performInitialisation()"
+		#end
+		<xsl:call-template name="top"/>
+		<xsl:call-template name="form-content">
+			<xsl:with-param name="form" select="."/>
+		</xsl:call-template>
+		<xsl:call-template name="foot"/>
+	</xsl:template>
+
+	<xsl:template match="adl:form" mode="empty-layout">
+		<xsl:variable name="form" select="."/>
+		<xsl:text>
+		</xsl:text>
+		<xsl:comment>[ cut here: next file '<xsl:value-of select="concat( ancestor::adl:entity/@name, '/', @name)"/>.auto.vm' ]</xsl:comment>
+		<xsl:text>
+		</xsl:text>
+		<html>
+			<xsl:comment>
+        #if ( $instance)
+				#if ( ! $instance.IsNew)
+				#set( $title = "<xsl:value-of select="concat( 'Edit ', ' ', ancestor::adl:entity/@name)"/> $instance.UserIdentifier")
+				#else
+				#set( $title = "<xsl:call-template name="i18n-add-a-new">
+					<xsl:with-param name="entity-name" select="ancestor::adl:entity/@name"/>
+				</xsl:call-template>")
+        #end
+        #else
+        #set( $title = "<xsl:call-template name="i18n-add-a-new">
+          <xsl:with-param name="entity-name" select="ancestor::adl:entity/@name"/>
+        </xsl:call-template>")
+        #end
+      </xsl:comment>
+			<head>
+        <xsl:comment>
+          Auto generated Velocity form for <xsl:value-of select="ancestor::adl:entity/@name"/>,
+        </xsl:comment>
+        <xsl:call-template name="head"/>
+        <xsl:if test="$page-timeout &gt; 0">
+          <meta http-equiv="refresh" content="5; URL=http://www.cryer.co.uk">
+            <xsl:attribute name="content">
+              <xsl:value-of select="concat($page-timeout, '; URL=', $default-url)"/>
+            </xsl:attribute>
+          </meta>
+        </xsl:if>
+        <xsl:call-template name="install-scripts"/>
+				<xsl:call-template name="generate-head-javascript">
+					<xsl:with-param name="form" select="."/>
+          <xsl:with-param name="locale" select="$locale"/>
+				</xsl:call-template>
+
+				${StylesHelper.InstallStylesheet( "Epoch")}
+
+				<style type="text/css">
+					<xsl:for-each select="ancestor::adl:entity//adl: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()">
+        <div id="page">
+          <xsl:call-template name="top"/>
+          <xsl:call-template name="form-content">
+            <xsl:with-param name="form" select="."/>
+          </xsl:call-template>
+          <xsl:call-template name="foot"/>
+        </div>
+      </body>
+		</html>
+	</xsl:template>
+
+	<!-- the content of a form, whether or not the layout is empty -->
+    <xsl:template name="form-content">
+		<!-- an entity of type form -->
+		<xsl:param name="form"/>
+		<div class="content">
+      #if ( $instance.NoDeleteReason)
+      <ul class="errors">
+        <li>$instance.NoDeleteReason</li>
+      </ul>
+      #end
+      <xsl:if test="$show-errors = 'true'">
+				#if ( $errors)
+					#if ( $errors.Count != 0)
+						<ul class="errors">
+							#foreach($e in $errors)
+								#if($e.Message)
+									<li>$t.Error($e)</li>
+								#else
+									<li>$t.Enc($e)</li>
+								#end
+							#end
+						</ul>
+					#end
+				#end
+			</xsl:if>
+			<xsl:if test="$show-messages = 'true'">
+				#if( $messages)
+					#if ( $messages.Count != 0)
+						<ul class="information">
+							#foreach ( $message in $messages)
+								<li>$message</li>
+							#end
+						</ul>
+					#end
+				#end
+			</xsl:if>
+			<form method="post" onsubmit="invokeSubmitHandlers(this);return trapEnterSubmissions(event, this);" onkeypress="trapKeyPress(event, this)" class="tabbed">
+				<xsl:attribute name="action">
+					<xsl:value-of select="concat( $form/@name, 'SubmitHandler.rails')"/>
+				</xsl:attribute>
+				<xsl:attribute name="name">
+					<xsl:value-of select="$form/@name"/>
+				</xsl:attribute>
+				<xsl:attribute name="id">
+					<xsl:value-of select="$form/@name"/>
+				</xsl:attribute>
+				<xsl:attribute name="enctype">
+					<xsl:choose>
+						<xsl:when test="$form/ancestor::adl:entity//adl:property[@type='uploadable']">
+							<xsl:value-of select="'multipart/form-data'"/>
+						</xsl:when>
+						<xsl:when test="$form/ancestor::adl:entity//adl:property[@type='image']">
+							<xsl:value-of select="'multipart/form-data'"/>
+						</xsl:when>
+						<xsl:otherwise>
+							<xsl:value-of select="'application/x-www-form-urlencoded'"/>
+						</xsl:otherwise>
+					</xsl:choose>
+				</xsl:attribute>
+				<input type="hidden" name="currentpane" value="$!currentpane" />
+				<xsl:for-each select="$form/ancestor::adl:entity/adl:key/adl:property">
+					<xsl:variable name="keyname" select="@name"/>
+					<xsl:choose>
+						<xsl:when test="$form//adl:field[@property=$keyname]">
+							<!-- it's already a field of the form - no need to add a hidden one -->
+						</xsl:when>
+						<xsl:otherwise>
+							<!-- create a hidden widget for the natural primary key -->
+							#if ( $instance)
+							#if ( ! ( $instance.IsNew))
+							${FormHelper.HiddenField( "instance.<xsl:value-of select="$keyname"/>")}
+							#end
+							#end
+						</xsl:otherwise>
+					</xsl:choose>
+				</xsl:for-each>
+				<xsl:apply-templates select="$form/adl:fieldgroup"/>
+				<div class="non-pane">
+					<table>
+						<xsl:choose>
+							<xsl:when test="@properties='listed'">
+								<xsl:apply-templates select="$form/adl:field|adl:auxlist"/>
+							</xsl:when>
+							<xsl:otherwise>
+								<xsl:apply-templates select="$form/ancestor::adl:entity/adl:property"/>
+							</xsl:otherwise>
+						</xsl:choose>
+          </table>
+          <ul class="verbs">
+            <xsl:apply-templates select="adl:verb"/>
+            <xsl:choose>
+              <xsl:when test="$authentication-layer='Database'">
+                <xsl:variable name="savegroups">
+                  <xsl:call-template name="entity-save-groups">
+                    <xsl:with-param name="entity" select="$form/ancestor::adl:entity"/>
+                  </xsl:call-template>
+                </xsl:variable>
+				  <xsl:variable name="updategroups">
+					  <xsl:call-template name="entity-update-groups">
+						  <xsl:with-param name="entity" select="$form/ancestor::adl:entity"/>
+					  </xsl:call-template>
+				  </xsl:variable>
+				  <!-- NOTE! NOTE! NOTE! Whitespace is significant - any linefeeds inside the #if ( ) clause
+								cause the Velocity parser to break! -->
+				#if ( $instance)
+				  #if ( $instance.IsNew)
+				    #if ( <xsl:for-each select="exsl:node-set( $savegroups)/*"> ${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} ||</xsl:for-each> false)
+                    <xsl:call-template name="save-widget-row"/>
+				    #end
+				  #else
+				    #if ( <xsl:for-each select="exsl:node-set( $updategroups)/*"> ${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} || </xsl:for-each> false)
+				    <xsl:call-template name="save-widget-row"/>
+				    #end
+				  #end
+				#else
+				<!-- for application-layer authentication, we may not actually have an instance at this stage -->
+				  #if ( <xsl:for-each select="exsl:node-set( $savegroups)/*"> ${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} || </xsl:for-each> false)
+				  <xsl:call-template name="save-widget-row"/>
+				  #end
+				#end
+				  <xsl:variable name="deletegroups">
+                  <xsl:call-template name="entity-delete-groups">
+                    <xsl:with-param name="entity" select="$form/ancestor::adl:entity"/>
+                  </xsl:call-template>
+                </xsl:variable>
+                <!-- NOTE! NOTE! NOTE! Whitespace is significant - any linefeeds inside the #if ( ) clause
+								cause the Velocity parser to break! -->
+                #if ( <xsl:for-each select="exsl:node-set( $deletegroups)/*"> ${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} || </xsl:for-each> false)
+                <xsl:call-template name="delete-widget-row"/>
+                #end
+              </xsl:when>
+              <xsl:when test="$authentication-layer='Application'">
+                <xsl:call-template name="save-widget-row"/>
+                <xsl:call-template name="delete-widget-row"/>
+              </xsl:when>
+            </xsl:choose>
+          </ul>
+        </div>
+      </form>
+		</div>
+	</xsl:template>
+
+	<!-- output a complete table row containing a save widget -->
+	<xsl:template name="save-widget-row">
+    <li class="standard-verb actionSafe">
+      <button type="submit" name="command" value="store">
+        <xsl:attribute name="title">
+          <xsl:call-template name='i18n-save-prompt'/>
+        </xsl:attribute>
+        Save
+      </button>
+    </li>
+  </xsl:template>
+
+	<!-- output a complete table row containing a delete widget -->
+  <xsl:template name="delete-widget-row">
+    <li class="standard-verb actionDangerous">
+      #if ( $instance)
+	  #if ( !$instance.IsNew)
+      #if ( $instance.NoDeleteReason)
+      <button type="submit" disabled="disabled" title="$instance.NoDeleteReason"  name="command" value="delete">Delete this</button>
+      #else
+      <button type="submit" name="command" value="delete">
+        <xsl:attribute name="title">
+          <xsl:call-template name="i18n-delete-prompt"/>
+        </xsl:attribute>
+        Delete this
+      </button>
+      #end
+      #end
+	  #end
+    </li>
+  </xsl:template>
+
+  <xsl:template match="adl:fieldgroup">
+    <xsl:if test="$authentication-layer = 'Database'">
+      <xsl:variable name="property" select="."/>
+      <xsl:variable name="readgroups">
+        <xsl:call-template name="fieldgroup-read-groups">
+          <xsl:with-param name="fieldgroup" select="."/>
+        </xsl:call-template>
+      </xsl:variable>
+      <!-- NOTE! NOTE! NOTE! Whitespace is significant - any linefeeds inside the #if ( ) clause cause the Velocity parser to break! -->
+      #if ( <xsl:for-each select="exsl:node-set( $readgroups)/*"> ${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} ||</xsl:for-each> false)
+    </xsl:if>
+
+    <div class="tab-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>
+			<h3 class="title">
+				<xsl:call-template name="showprompt">
+					<xsl:with-param name="node" select="."/>
+					<xsl:with-param name="fallback" select="@name"/>
+					<xsl:with-param name="entity" select="ancestor::adl:entity"/>
+					<xsl:with-param name="locale" select="$locale"/>
+				</xsl:call-template>
+			</h3>
+			<table>
+				<xsl:apply-templates select="adl:field|adl:auxlist"/>
+			</table>
+      <xsl:if test="adl:verb">
+        <ul class="verbs">
+          <xsl:apply-templates select="adl:verb"/>
+        </ul>
+      </xsl:if>
+		</div>
+    <xsl:if test="$authentication-layer = 'Database'">
+      #end
+    </xsl:if>
+	</xsl:template>
+
+	<xsl:template match="adl:auxlist">
+		<xsl:variable name="listprop" select="@property"/>
+		<xsl:variable name="farent" select="ancestor::adl:entity//adl:property[@name=$listprop]/@entity"/>
+		<xsl:variable name="nearent" select="ancestor::adl:entity/@name"/>
+		<xsl:variable name="farid">
+			<xsl:value-of select="//adl:entity[@name=$farent]/adl:key//adl:property[position()=1]/@name"/>
+		</xsl:variable>
+		<xsl:variable name="farkey">
+			<xsl:choose>
+				<xsl:when test="//adl:entity[@name=$farent]//adl:property[@entity=$nearent]/@farkey">
+					<xsl:value-of select="//adl:entity[@name=$farent]//adl:property[@entity=$nearent]/@farkey"/>
+				</xsl:when>
+				<xsl:otherwise>
+					<xsl:value-of select="//adl:entity[@name=$farent]//adl:property[@entity=$nearent]/@name"/>
+				</xsl:otherwise>
+			</xsl:choose>
+		</xsl:variable>
+		<xsl:variable name="nearkey">
+			<xsl:choose>
+				<xsl:when test="ancestor::adl:entity/adl:key/adl:property[position()=1 and @type='entity']">
+					<xsl:value-of select="concat( ancestor::adl:entity/adl:key/adl:property[position()=1]/@name, '_Value')"/>
+				</xsl:when>
+				<xsl:otherwise>
+					<xsl:value-of select="ancestor::adl:entity/adl:key/adl:property[position()=1]/@name"/>
+				</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, 'With', $farkey, '.rails?', $farkey, '=$instance.', $nearkey)"/>
+						</xsl:attribute>
+						<xsl:call-template name="i18n-add-a-new">
+							<xsl:with-param name="entity-name" select="$farent"/>
+						</xsl:call-template>
+					</a>
+				</td>
+			</tr>
+		</xsl:if>
+		<tr>
+			<td>
+				<xsl:attribute name="colspan">
+					<xsl:value-of select="count( field)"/>
+				</xsl:attribute>
+
+				<xsl:choose>
+					<xsl:when test="@properties='listed'">
+						<xsl:comment>auxlist with listed fields: <xsl:value-of select="$farent/@name"/></xsl:comment>
+						<xsl:call-template name="internal-with-fields-list">
+							<xsl:with-param name="entity" select="//adl:entity[@name=$farent]"/>
+							<xsl:with-param name="fields" select="adl:field"/>
+							<xsl:with-param name="instance-list" select="concat( 'instance.', $listprop)"/>
+						</xsl:call-template>
+					</xsl:when>
+					<xsl:otherwise>
+						<xsl:comment>auxlist with computed fields: <xsl:value-of select="$farent/@name"/></xsl:comment>
+						<xsl:call-template name="internal-with-properties-list">
+							<xsl:with-param name="entity" select="//adl:entity[@name=$farent]"/>
+							<xsl:with-param name="properties" select="//adl:entity[@name=$farent]//adl:property[(@distinct='user' or @distinct='all') and not( @type='link' or @type='list')]"/>
+							<xsl:with-param name="instance-list" select="concat( 'instance.', $listprop)"/>
+						</xsl:call-template>
+					</xsl:otherwise>
+				</xsl:choose>
+			</td>
+		</tr>
+	</xsl:template>
+
+	<xsl:template match="adl:verb">
+    <xsl:variable name="executegroups">
+      <xsl:call-template name="verb-execute-groups">
+        <xsl:with-param name="verb" select="."/>
+      </xsl:call-template>
+    </xsl:variable>
+    <!-- NOTE! NOTE! NOTE! Whitespace is significant - any linefeeds inside the #if ( ) clause
+								cause the Velocity parser to break! -->
+    #if ( <xsl:for-each select="exsl:node-set( $executegroups)/*"> ${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} ||</xsl:for-each> false)
+    <xsl:variable name="class">
+			<xsl:choose>
+				<xsl:when test="@dangerous='true'">actionDangerous</xsl:when>
+				<xsl:otherwise>actionSafe</xsl:otherwise>
+			</xsl:choose>
+		</xsl:variable>
+		<!-- don't emit a verb unless there is an instance for it to act on -->
+    #if( $instance)
+    #if( ! $instance.IsNew)
+    <li>
+      <xsl:attribute name="class">
+        <xsl:value-of select="concat( 'custom-verb ', $class)"/>
+      </xsl:attribute>
+      <button name="command">
+        <xsl:attribute name="value">
+          <xsl:value-of select="@verb"/>
+        </xsl:attribute>
+        <xsl:attribute name="title">
+          <xsl:apply-templates select="adl:help[@locale = $locale]"/>
+        </xsl:attribute>
+        <xsl:call-template name="showprompt">
+          <xsl:with-param name="node" select="."/>
+          <xsl:with-param name="fallback" select="@verb"/>
+        </xsl:call-template>
+      </button>
+    </li>
+    #end
+    #end
+    #end
+  </xsl:template>
+
+	<xsl:template match="adl:field">
+		<xsl:variable name="propname">
+			<xsl:value-of select="@property"/>
+		</xsl:variable>
+		<xsl:choose>
+			<xsl:when test="ancestor::adl:entity//adl:property[@name=$propname]">
+				<!-- there is a real property -->
+				<xsl:apply-templates select="ancestor::adl:entity//adl: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 -->
+				<xsl:comment>
+					Computed field (<xsl:value-of select="$propname"/>)? TODO: Not yet implememented
+				</xsl:comment>
+			</xsl:otherwise>
+		</xsl:choose>
+	</xsl:template>
+
+	<xsl:template match="adl:property[@type='message']">
+		<!-- HIHGLY experimental - an internationalised message -->
+		<xsl:param name="oddness" select="odd"/>
+		<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="node" select="."/>
+					<xsl:with-param name="fallback" select="@name"/>
+				</xsl:call-template>")}
+			</td>
+			<td class="widget" colspan="2">
+				#if( $instance)
+				#if( <xsl:value-of select="concat( '$instance.', @name)"/>)
+				<xsl:value-of select="concat( '$t.Msg( $instance.', @name, ')')"/>
+				#else
+				<input type="text">
+					<xsl:attribute name="name">
+						<xsl:value-of select="concat('i18n.instance.', @name)"/>
+					</xsl:attribute>
+				</input>
+				#end
+				#else
+				<input type="text">
+					<xsl:attribute name="name">
+						<xsl:value-of select="concat('i18n.instance.', @name)"/>
+					</xsl:attribute>
+				</input>
+				#end
+			</td>
+		</tr>
+	</xsl:template>
+
+	<xsl:template match="adl:property[@type='link'or @type='list']">
+		<!-- 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 and lists we implement a shuffle widget, which extends over both columns -->
+		<xsl:param name="oddness" select="odd"/>
+    <xsl:if test="$authentication-layer = 'Database'">
+      <xsl:variable name="property" select="."/>
+      <xsl:variable name="readgroups">
+        <xsl:call-template name="entity-read-groups">
+          <xsl:with-param name="entity" select="//adl:entity[@name=$property/@entity]"/>
+        </xsl:call-template>
+      </xsl:variable>
+      <!-- NOTE! NOTE! NOTE! Whitespace is significant - any linefeeds inside the #if ( ) clause cause the Velocity parser to break! -->
+      #if ( <xsl:for-each select="exsl:node-set( $readgroups)/*">${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} || </xsl:for-each> false)
+    </xsl:if>
+    <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="node" select="."/>
+					<xsl:with-param name="fallback" select="@name"/>
+				</xsl:call-template>")}
+			</td>
+      <td class="widget shuffle" colspan="2">
+        <xsl:call-template name="shuffle-widget">
+          <xsl:with-param name="property" select="."/>
+        </xsl:call-template>
+      </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="adl:help[@locale = $locale]"/>
+			</td>
+		</tr>
+    <xsl:if test="$authentication-layer = 'Database'">
+      #end
+    </xsl:if>
+	</xsl:template>
+
+	<xsl:template name="shuffle-widget">
+		<xsl:param name="property" select="."/>
+    #if ( $instance)
+    #if ( ! $instance.IsNew)
+		<table class="shuffle">
+			<tr>
+				<td class="widget shuffle-all" rowspan="2">
+					${ShuffleWidgetHelper.UnselectedOptions( "<xsl:value-of select="concat( $property/@name, '_unselected')"/>", <xsl:value-of select="concat( '$all_', $property/@name)"/>, $instance.<xsl:value-of select="$property/@name"/>)}
+				</td>
+				<td class="widget shuffle-action">
+					<input type="button" value="include &gt;&gt;">
+						<xsl:attribute name="onclick">
+							<xsl:value-of select="concat( 'shuffle(', $property/@name, '_unselected, ', $property/@name, ')')"/>
+						</xsl:attribute>
+					</input>
+				</td>
+				<td class="widget shuffle-selected" rowspan="2">
+					<xsl:variable name="entityname" select="$property/@entity"/>
+					<xsl:variable name="foreignkey" select="$property/@farkey"/>
+					<xsl:variable name="allow-shuffle-back">
+						<xsl:choose>
+							<xsl:when test="$property/@type='list' and //adl:entity[@name=$entityname]//adl:property[@name=$foreignkey and @required='true']">
+								<xsl:value-of select="'false'"/>
+							</xsl:when>
+							<xsl:otherwise>
+								<xsl:value-of select="'true'"/>
+							</xsl:otherwise>
+						</xsl:choose>
+					</xsl:variable>
+					${ShuffleWidgetHelper.SelectedOptions( "<xsl:value-of select="$property/@name"/>", $instance.<xsl:value-of select="$property/@name"/>, <xsl:value-of select="$allow-shuffle-back"/>)}
+				</td>
+			</tr>
+			<tr>
+				<td class="widget shuffle-action">
+					<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>
+    #else
+    <i>You must create your <xsl:value-of select="$property/ancestor::adl:entity/@name"/> record before you can add <xsl:value-of select="$property/@name"/> to it</i>
+    #end
+    #end
+	</xsl:template>
+
+	<xsl:template match="adl: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! -->
+		<xsl:variable name="property" select="."/>
+		<xsl:variable name="editgroups">
+			<xsl:call-template name="property-edit-groups">
+				<xsl:with-param name="property" select="$property"/>
+			</xsl:call-template>
+		</xsl:variable>
+		<xsl:variable name="insertgroups">
+			<xsl:call-template name="property-insert-groups">
+				<xsl:with-param name="property" select="$property"/>
+			</xsl:call-template>
+		</xsl:variable>
+		<xsl:variable name="readgroups">
+			<xsl:call-template name="property-read-groups">
+				<xsl:with-param name="property" select="$property"/>
+			</xsl:call-template>
+		</xsl:variable>
+    <xsl:if test="$authentication-layer = 'Database'">
+      <xsl:choose>
+        <xsl:when test="exsl:node-set( $readgroups)/*">
+          #if ( <xsl:for-each select="exsl:node-set( $readgroups)/*">${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} || </xsl:for-each> false)
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:comment>we haven't found any group of users who are entitled to see this field.</xsl:comment>
+          #if ( false)
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:if>
+      <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="$authentication-layer = 'Application'">
+							<xsl:call-template name="property-widget">
+								<xsl:with-param name="property" select="."/>
+								<xsl:with-param name="mode" select="'Editable'"/>
+							</xsl:call-template>
+						</xsl:when>
+						<xsl:when test="$authentication-layer = 'Database'">
+							<xsl:if test="exsl:node-set( $editgroups)/*">
+								<!-- NOTE! NOTE! NOTE! Whitespace is significant - any linefeeds inside the #if ( ) clause
+								cause the Velocity parser to break! -->
+								#if ( <xsl:for-each select="exsl:node-set( $editgroups)/*">${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} ||</xsl:for-each> false)
+								<xsl:choose>
+									<xsl:when test="$property/@immutable='true'">
+										<xsl:call-template name="property-widget">
+											<xsl:with-param name="property" select="."/>
+											<xsl:with-param name="mode" select="'Immutable'"/>
+										</xsl:call-template>
+									</xsl:when>
+									<xsl:otherwise>
+										<xsl:call-template name="property-widget">
+											<xsl:with-param name="property" select="."/>
+											<xsl:with-param name="mode" select="'Editable'"/>
+										</xsl:call-template>
+									</xsl:otherwise>
+								</xsl:choose>
+								#else
+							</xsl:if>
+							<xsl:if test="exsl:node-set( $insertgroups)/*">
+								#if ( <xsl:for-each select="exsl:node-set( $insertgroups)/*">${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} ||</xsl:for-each> false)
+								<xsl:call-template name="property-widget">
+									<xsl:with-param name="property" select="."/>
+									<xsl:with-param name="mode" select="'Immutable'"/>
+								</xsl:call-template>
+								#else
+							</xsl:if>
+							<xsl:if test="exsl:node-set( $readgroups)/*">
+								#if ( <xsl:for-each select="exsl:node-set( $readgroups)/*">${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} ||</xsl:for-each> false)
+								<xsl:call-template name="property-widget">
+									<xsl:with-param name="property" select="."/>
+									<xsl:with-param name="mode" select="'DisplayAndHidden'"/>
+								</xsl:call-template>
+								#else
+							</xsl:if>
+								[Not authorised]
+							<xsl:if test="exsl:node-set( $readgroups)/*">
+								#end
+							</xsl:if>
+							<xsl:if test="exsl:node-set( $insertgroups)/*">
+								#end
+							</xsl:if>
+							<xsl:if test="exsl:node-set( $editgroups)/*">
+								#end
+							</xsl:if>
+						</xsl:when>
+					</xsl:choose>
+				</td>
+				<td class="help">
+					<xsl:apply-templates select="adl:help[@locale = $locale]"/>
+				</td>
+			</tr>
+    <xsl:if test="$authentication-layer = 'Database'">
+        #end
+    </xsl:if>
+
+  </xsl:template>
+
+
+	<!-- layout of lists -->
+	<!-- layout of a list assuming a non-empty layout -->
+	<xsl:template match="adl:list" mode="non-empty-layout">
+		<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">
+			<xsl:call-template name="i18n-plural">
+				<xsl:with-param name="noun" select="ancestor::adl:entity/@name"/>
+			</xsl:call-template>
+		</xsl:variable>
+
+    #capturefor( title)
+    <xsl:value-of select="normalize-space( concat( 'List ', $withpluralsuffix))"/>
+    #end
+    #capturefor( headextras)
+    <xsl:comment>
+      Auto generated Velocity list for <xsl:value-of select="ancestor::adl:entity/@name"/>,
+    </xsl:comment>
+    <xsl:call-template name="head"/>
+		#end
+		<xsl:call-template name="top"/>
+		<xsl:call-template name="list">
+			<xsl:with-param name="list" select="."/>
+		</xsl:call-template>
+		<xsl:call-template name="foot"/>
+	</xsl:template>
+
+
+	<xsl:template match="adl:option">
+		<option>
+			<xsl:attribute name="value">
+				<xsl:value-of select="@value"/>
+			</xsl:attribute>
+			<xsl:attribute name="id">
+				<xsl:value-of select="concat( ancestor::adl:property/@name, '-', @value)"/>
+			</xsl:attribute>
+			<xsl:call-template name="showprompt">
+				<xsl:with-param name="fallback" select="@value"/>
+			</xsl:call-template>
+		</option>
+	</xsl:template>
+	
+	
+	<!-- layout of a list assuming an empty layout -->
+		<xsl:template match="adl:list" mode="empty-layout">
+			<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">
+				<xsl:call-template name="i18n-plural">
+					<xsl:with-param name="noun" select="ancestor::adl:entity/@name"/>
+				</xsl:call-template>
+			</xsl:variable>
+			<html>
+			  <head>
+				  #set( $title = "<xsl:value-of select="normalize-space( concat( 'List ', $withpluralsuffix))"/>")
+          <xsl:comment>
+            Auto generated Velocity list for <xsl:value-of select="ancestor::adl:entity/@name"/>,
+          </xsl:comment>
+          <xsl:call-template name="head"/>
+				  <xsl:call-template name="install-scripts"/>
+			  </head>
+        <body>
+          <div id="page">
+            <xsl:call-template name="top"/>
+            <xsl:call-template name="list">
+              <xsl:with-param name="list" select="."/>
+            </xsl:call-template>
+            <xsl:call-template name="foot"/>
+          </div>
+        </body>
+      </html>
+	  </xsl:template>
+
+	  <!-- layout the content of a list, whether or not the layout is empty -->
+	  <xsl:template name="list">
+		  <!-- an entity of type adl:list -->
+		  <xsl:param name="list"/>
+		  <div class="content">
+			  <div class="controls">
+          <span class="pagination status">
+            Showing $instances.FirstItem - $instances.LastItem of $instances.TotalItems
+          </span>
+          #if (  <xsl:for-each select="adl:field">
+            <xsl:variable name="field" select="."/>
+            <xsl:variable name="search-name"
+                          select="concat('$search_', ancestor::adl:entity//adl:property[@name=$field/@property]/@name)"/>
+            <xsl:value-of select="$search-name"/>
+            <xsl:if test="not( position() = last())">||</xsl:if>
+          </xsl:for-each> )
+          <span class="pagination status">(Suppressing pagination in favour of search)</span>
+          #else
+				  <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>
+          #end
+				  <xsl:if test="$list/../adl:form">
+					  <span class="add">
+						  <a>
+							  <xsl:attribute name="href">
+								  <xsl:value-of select="concat( ancestor::adl:entity/adl:form[position()=1]/@name, '.rails')"/>
+							  </xsl:attribute>
+							  <xsl:call-template name="i18n-add-a-new">
+								  <xsl:with-param name="entity-name" select="ancestor::adl:entity/@name"/>
+							  </xsl:call-template>
+						  </a>
+					  </span>
+				  </xsl:if>
+			  </div>
+			  <form>
+				  <xsl:attribute name="action">
+					  <xsl:value-of select="concat( $list/@name, '.rails')"/>
+				  </xsl:attribute>
+				  <xsl:call-template name="internal-with-fields-list">
+					  <xsl:with-param name="entity" select="$list/ancestor::adl:entity"/>
+					  <xsl:with-param name="fields" select="$list/adl:field"/>
+					  <xsl:with-param name="can-search" select="'true'"/>
+				  </xsl:call-template>
+			  </form>
+		  </div>
+	  </xsl:template>
+
+	  <xsl:template name="internal-with-fields-list">
+		  <!-- a node-list of entities of type 'adl:field' or 'adl:field', each indicating a property 
+			of the same entity, to be shown in columns of this list -->
+		  <xsl:param name="fields"/>
+		  <!-- the entity of type 'adl:entity' on which the properties for all those fields can be found -->
+		  <xsl:param name="entity"/>
+		  <!-- the name of the list of instances of this entity, available to Velocity at runtime 
+				as an ICollection, which is to be layed out in this list -->
+		  <xsl:param name="instance-list" select="'instances'"/>
+		  <!-- NOTE NOTE NOTE: To be searchable, internal-with-fields-list must not only be called with can-search
+			equal to 'true', but also within a form! -->
+		  <!-- NOTE NOTE NOTE: It's obvious that internal-with-fields-list and internal-with-properties-list
+			ought to be replaced with a single template, but that template proves to be extremely hard to get 
+			right -->
+		  <xsl:param name="can-search"/>
+		  <table class="sortable" id="concat($entity/@name, '-list')">
+			  <tr>
+				  <xsl:for-each select="$fields">
+					  <xsl:variable name="field" select="."/>
+					  <th>
+						  <xsl:call-template name="showprompt">
+							<xsl:with-param name="node" select="."/>
+							<xsl:with-param name="fallback" select="@property"/>
+							<xsl:with-param name="entity" select="$entity"/>
+							<xsl:with-param name="locale" select="$locale"/>
+						  </xsl:call-template>
+					  </th>
+				  </xsl:for-each>
+				  <xsl:for-each select="$entity/adl:form">
+					  <th class="unsortable">-</th>
+				  </xsl:for-each>
+			  </tr>
+			  <xsl:if test="$can-search = 'true'">
+				  <tr class="search sorttop">
+					  <xsl:for-each select="$fields">
+						  <xsl:variable name="field" select="."/>
+						  <td class="search">
+							  <xsl:variable name="size">
+								  <xsl:choose>
+                    <!-- can't search non-concrete fields -->
+                    <xsl:when test="$entity//adl:property[@name=$field/@property]/@concrete='false'">0</xsl:when>
+									  <xsl:when test="$entity//adl:property[@name=$field/@property]/@type='string'">
+										  <xsl:choose>
+											  <xsl:when test="$entity//adl:property[@name=$field/@property]/@size &gt; 20">20</xsl:when>
+											  <xsl:otherwise>
+												  <xsl:value-of select="$entity//adl:property[@name=$field/@property]/@size"/>
+											  </xsl:otherwise>
+										  </xsl:choose>
+									  </xsl:when>
+									  <xsl:when test="$entity//adl:property[@name=$field/@property]/@type='integer'">8</xsl:when>
+									  <xsl:when test="$entity//adl:property[@name=$field/@property]/@type='real'">8</xsl:when>
+									  <xsl:when test="$entity//adl:property[@name=$field/@property]/@type='money'">8</xsl:when>
+									  <!-- xsl:when test="$entity//adl:property[@name=$field/@property]/@type='message'">20</xsl:when doesn't work yet -->
+									  <xsl:when test="$entity//adl:property[@name=$field/@property]/@type='text'">20</xsl:when>
+									  <!-- xsl:when test="$entity//adl:property[@name=$field/@property]/@type='enity'">20</xsl:when doesn't work yet -->
+									  <xsl:otherwise>0</xsl:otherwise>
+								  </xsl:choose>
+							  </xsl:variable>
+							  <xsl:if test="$size != 0">
+								  <input>
+                    <xsl:variable name="search-name" select="concat('search_',$entity//adl:property[@name=$field/@property]/@name)"/>
+									  <xsl:attribute name="name">
+										  <xsl:value-of select="$search-name"/>
+									  </xsl:attribute>
+									  <xsl:attribute name="size">
+                      <xsl:choose>
+                        <xsl:when test="$size &gt; 8">8</xsl:when>
+                        <xsl:otherwise>
+                          <xsl:value-of select="$size"/>
+                        </xsl:otherwise>
+                      </xsl:choose>	  
+									  </xsl:attribute>
+									  <xsl:attribute name="value">
+										  <xsl:value-of select="concat( '$!', $search-name)"/>
+									  </xsl:attribute>
+								  </input>
+							  </xsl:if>
+						  </td>
+					  </xsl:for-each>
+					  <td>
+						  <input type="submit" name="search-button" value="Search"/>
+					  </td>
+				  </tr>
+			  </xsl:if>
+			  <xsl:if test="not( $entity/@name)">
+				  <xsl:message terminate="yes">
+					  Unknown entity whilst trying to generate list
+				  </xsl:message>
+			  </xsl:if>
+			  <xsl:variable name="readgroups">
+				  <xsl:call-template name="entity-read-groups">
+					  <xsl:with-param name="entity" select="$entity"/>
+				  </xsl:call-template>
+			  </xsl:variable>
+			  <xsl:choose>
+				  <xsl:when test="$authentication-layer = 'Application'">
+					  <xsl:call-template name="internal-with-fields-rows">
+						  <xsl:with-param name="instance-list" select="$instance-list"/>
+						  <xsl:with-param name="entity" select="$entity"/>
+						  <xsl:with-param name="fields"	select="$fields"/>
+					  </xsl:call-template>
+				  </xsl:when>
+				  <xsl:when test="$authentication-layer = 'Database'">
+					<!-- NOTE NOTE NOTE: This is whitespace-sensitive! -->
+					#if ( <xsl:for-each select="exsl:node-set( $readgroups)/*">${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} ||</xsl:for-each> false)
+					<xsl:call-template name="internal-with-fields-rows">
+						<xsl:with-param name="instance-list" select="$instance-list"/>
+						<xsl:with-param name="entity" select="$entity"/>
+						<xsl:with-param name="fields" select="$fields"/>
+					</xsl:call-template>
+					#else
+					<tr>
+						<td colspan="5">[You are not authorised to view this data]</td>
+					</tr>
+					#end
+				  </xsl:when>
+			  </xsl:choose>
+		  </table>
+	  </xsl:template>
+
+	<xsl:template name="internal-with-fields-rows">
+		<xsl:param name="instance-list"/>
+		<xsl:param name="entity"/>
+		<xsl:param name="fields"/>
+		#foreach( <xsl:value-of select="concat( '$', $entity/@name)"/> in <xsl:value-of select="concat('$', $instance-list)"/>)
+		#if ( $velocityCount % 2 == 0)
+		#set( $oddity = "even")
+		#else
+		#set( $oddity = "odd")
+		#end
+		<tr class="$oddity">
+			<xsl:for-each select="$fields">
+				<xsl:variable name="field" select="."/>
+				<xsl:call-template name="list-field">
+					<xsl:with-param name="entity" select="$entity"/>
+					<xsl:with-param name="property" select="$entity//adl:property[@name=$field/@property]"/>
+					<xsl:with-param name="objectvar" select="$entity/@name"/>
+				</xsl:call-template>
+			</xsl:for-each>
+			<xsl:variable name="keys">
+				<xsl:call-template name="entity-keys-fragment">
+					<xsl:with-param name="entity" select="$entity"/>
+				</xsl:call-template>
+			</xsl:variable>
+			<xsl:for-each select="$entity/adl:form">
+				<!-- by default create a link to each form declared for the entity. 
+                    We probably need a means of overriding this -->
+				<td>
+					<a>
+						<xsl:attribute name="href">
+							<xsl:value-of select="concat( '../', $entity/@name, '/', @name, '.rails', $keys)"/>
+						</xsl:attribute>
+						<xsl:value-of select="@name"/>
+					</a>
+				</td>
+			</xsl:for-each>
+		</tr>
+		#end
+	</xsl:template>
+
+	<xsl:template name="internal-with-properties-list">
+		<!-- a node-list of entities of type 'adl:property', each a property of the same entity, to be shown
+			in columns of this list -->
+		<xsl:param name="properties"/>
+		<!-- the entity of type 'adl:entity' on which the properties for all those fields can be found -->
+		<xsl:param name="entity"/>
+		<!-- the name of the list of instances of this entity, available to Velocity at runtime 
+				as an ICollection, which is to be layed out in this list -->
+		<xsl:param name="instance-list" select="'instances'"/>
+		<!-- NOTE NOTE NOTE: To be searchable, internal-with-properties-list must not only be called with can-search
+			equal to 'true', but also within a form! -->
+		<!-- NOTE NOTE NOTE: It's obvious that internal-with-fields-list and internal-with-properties-list
+			ought to be replaced with a single template, but that template proves to be extremely hard to get 
+			right -->
+		<xsl:param name="can-search"/>
+		<table class="sortable">
+			<tr>
+				<xsl:for-each select="$properties">
+					<th>
+						<xsl:call-template name="showprompt">
+							<xsl:with-param name="node" select="."/>
+							<xsl:with-param name="fallback" select="@name"/>
+							<xsl:with-param name="entity" select="$entity"/>
+							<xsl:with-param name="locale" select="$locale"/>
+						</xsl:call-template>
+					</th>
+				</xsl:for-each>
+				<xsl:for-each select="$entity/adl:form">
+					<th>-</th>
+				</xsl:for-each>
+			</tr>
+			<xsl:if test="$can-search = 'true'">
+				<tr class="search">
+					<xsl:for-each select="$properties">
+						<td class="search">
+							<xsl:variable name="size">
+								<xsl:choose>
+									<xsl:when test="@type='string'">
+										<xsl:choose>
+											<xsl:when test="@size &gt; 8">8</xsl:when>
+											<xsl:otherwise>
+												<xsl:value-of select="@size"/>
+											</xsl:otherwise>
+										</xsl:choose>
+									</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:when test="@type='message'">20</xsl:when doesn't work yet -->
+									<xsl:when test="@type='text'">8</xsl:when>
+									<!-- xsl:when test="@type='enity'">20</xsl:when doesn't work yet -->
+									<xsl:otherwise>0</xsl:otherwise>
+								</xsl:choose>
+							</xsl:variable>
+							<xsl:if test="$size != 0">
+								<input>
+									<xsl:attribute name="name">
+										<xsl:value-of select="concat('search_', @name)"/>
+									</xsl:attribute>
+									<xsl:attribute name="size">
+										<xsl:value-of select="$size"/>
+									</xsl:attribute>
+									<xsl:attribute name="value">
+										<xsl:value-of select="concat( '$!search_', @name)"/>
+									</xsl:attribute>
+								</input>
+							</xsl:if>
+						</td>
+					</xsl:for-each>
+					<td>
+						<input type="submit" name="search-button" size="8" value="Search"/>
+					</td>
+				</tr>
+			</xsl:if>
+			#foreach( <xsl:value-of select="concat( '$', $entity/@name)"/> in <xsl:value-of select="concat('$', $instance-list)"/>)
+			#if ( $velocityCount % 2 == 0)
+			#set( $oddity = "even")
+			#else
+			#set( $oddity = "odd")
+			#end
+			<tr class="$oddity">
+				<xsl:for-each select="$properties">
+					<xsl:call-template name="list-field">
+						<xsl:with-param name="entity" select="$entity"/>
+						<xsl:with-param name="property" select="."/>
+						<xsl:with-param name="objectvar" select="$entity/@name"/>
+					</xsl:call-template>
+				</xsl:for-each>
+				<xsl:variable name="keys">
+					<!-- assemble keys in a Velocity-friendly format, then splice it into
+                    the HREF below -->
+					<xsl:for-each select="$entity/adl:key/adl:property">
+						<xsl:variable name="sep">
+							<xsl:choose>
+								<xsl:when test="position()=1">?</xsl:when>
+								<xsl:otherwise>&amp;</xsl:otherwise>
+							</xsl:choose>
+						</xsl:variable>
+						<xsl:choose>
+							<xsl:when test="@type='entity'">
+								<xsl:value-of select="concat( $sep, @name, '=$', $entity/@name, '.', @name, '_Value')"/>
+							</xsl:when>
+							<xsl:otherwise>
+								<xsl:value-of select="concat( $sep, @name, '=$', $entity/@name, '.', @name)"/>
+							</xsl:otherwise>
+						</xsl:choose>
+					</xsl:for-each>
+				</xsl:variable>
+				<xsl:for-each select="$entity/adl:form">
+					<!-- by default create a link to each form declared for the entity. 
+                    We probably need a means of overriding this -->
+					<td>
+						<a>
+							<xsl:attribute name="href">
+								<xsl:value-of select="concat( '../', $entity/@name, '/', @name, '.rails', $keys)"/>
+							</xsl:attribute>
+							<xsl:value-of select="@name"/>
+						</a>
+					</td>
+				</xsl:for-each>
+			</tr>
+			#end
+		</table>
+	</xsl:template>
+
+	<!-- output a list field -->
+	<xsl:template name="list-field">
+		<xsl:param name="entity"/>
+		<xsl:param name="property"/>
+		<xsl:param name="objectvar" select="instance"/>
+		<xsl:variable name="readgroups">
+			<xsl:call-template name="property-read-groups">
+				<xsl:with-param name="property" select="$property"/>
+			</xsl:call-template>
+		</xsl:variable>
+		<td>
+			<xsl:choose>
+				<xsl:when test="$authentication-layer = 'Application'">
+					<xsl:call-template name="list-field-inner">
+						<xsl:with-param name="entity" select="$entity"/>
+						<xsl:with-param name="property" select="$property"/>
+						<xsl:with-param name="objectvar" select="$objectvar"/>
+					</xsl:call-template>
+				</xsl:when>
+				<xsl:when test="$authentication-layer = 'Database'">
+					<!-- NOTE NOTE NOTE: This is whitespace-sensitive! -->
+					#if ( <xsl:for-each select="exsl:node-set( $readgroups)/*">${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} ||</xsl:for-each> false)
+					<xsl:if test="$property/@type='entity'">
+						<!-- right, this is horrible. You can't read the field unless you can read the property; 
+						but even if you can read the property, if its an entity property you still can't read it
+						unless you can also read the entity -->
+						<xsl:variable name="entityreadgroups">
+							<xsl:call-template name="entity-read-groups">
+								<xsl:with-param name="entity" select="//adl:entity[@name=$property/@entity]"/>
+							</xsl:call-template>
+						</xsl:variable>
+						#if ( <xsl:for-each select="exsl:node-set( $entityreadgroups)/*">${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} ||</xsl:for-each> false)
+					</xsl:if>
+					<xsl:call-template name="list-field-inner">
+						<xsl:with-param name="entity" select="$entity"/>
+						<xsl:with-param name="property" select="$property"/>
+						<xsl:with-param name="objectvar" select="$objectvar"/>
+					</xsl:call-template>
+					<xsl:if test="$property/@type='entity'">
+						#else
+						[Not authorised]
+						#end
+					</xsl:if>
+					#else
+					[Not authorised]
+					#end
+				</xsl:when>
+			</xsl:choose>
+		</td>
+	</xsl:template>
+
+	<xsl:template name="list-field-inner">
+		<xsl:param name="entity"/>
+		<xsl:param name="property"/>
+		<xsl:param name="objectvar" select="instance"/>
+		<xsl:choose>
+			<xsl:when test="$property/adl:option">
+				<xsl:for-each select="$property/adl:option">
+					<xsl:variable name="val">
+						<xsl:variable name="base-type">
+							<xsl:call-template name="base-type">
+								<xsl:with-param name="property" select="$property"/>
+							</xsl:call-template>
+						</xsl:variable>
+						<xsl:choose>
+							<xsl:when test="$base-type = 'string'">
+								<xsl:value-of select="concat( '&#34;', @value, '&#34;')"/>
+							</xsl:when>
+							<xsl:otherwise>
+								<xsl:value-of select="@value"/>
+							</xsl:otherwise>
+						</xsl:choose>
+					</xsl:variable>
+					#if( <xsl:value-of select="concat( '$', $entity/@name, '.', $property/@name)"/> == <xsl:value-of select="$val"/>)
+					<xsl:call-template name="showprompt">
+						<xsl:with-param name="node" select="."/>
+						<xsl:with-param name="fallback" select="@value"/>
+					</xsl:call-template>
+					#end
+				</xsl:for-each>
+			</xsl:when>
+      <xsl:when test="$property/@type = 'image'">
+        #if ( <xsl:value-of select="concat( '$', $entity/@name, '.', $property/@name)"/>)
+        <img class="thumbnail" alt="thumbnail">
+          <xsl:attribute name="src">
+            <xsl:value-of select="normalize-space(concat( '../Uploads/$', $entity/@name, '.', $property/@name))"/>
+          </xsl:attribute>
+        </img>
+        #end
+      </xsl:when>
+			<xsl:when test="$property/@type = 'date'">
+				#if ( <xsl:value-of select="concat( '$', $entity/@name, '.', $property/@name)"/>)
+				<xsl:value-of select="concat( '$', $entity/@name, '.', $property/@name)"/>.ToString( 'd')
+				#end
+			</xsl:when>
+			<xsl:when test="$property/@type='message'">
+				#if ( <xsl:value-of select="concat( '$', $entity/@name, '.', $property/@name)"/>)
+				$t.Msg( <xsl:value-of select="concat( '$', $entity/@name, '.', $property/@name)"/>)
+				#end
+			</xsl:when>
+			<xsl:when test="$property/@type='entity'">
+				#if( <xsl:value-of select="concat( '$', $entity/@name, '.', $property/@name)"/>)
+				<xsl:value-of select="concat( '$', $entity/@name, '.', $property/@name, '.UserIdentifier')"/>
+				#end
+			</xsl:when>
+			<xsl:otherwise>
+				<xsl:value-of select="concat( '$!', $entity/@name, '.', $property/@name)"/>
+			</xsl:otherwise>
+		</xsl:choose>
+	</xsl:template>
+
+	<!-- generate head javascript for a form -->
+	<xsl:template name="generate-head-javascript">
+		<xsl:param name="form">
+			<!-- assumed to be an instance of adl:form -->
+		</xsl:param>
+    <xsl:param name="locale"/>
+		<script type='text/javascript' language='JavaScript1.2'>
+			#if ( ${site-root})
+			var siteRoot = '$siteRoot';
+			#else
+			var siteRoot = '<xsl:value-of select='$site-root'/>';
+      #end
+
+      var enterPressed = false;
+
+      function trapKeyPress(event, form){
+        if(event.which == 13){
+          enterPressed = true;
+        } else {
+          enterPressed = false;
+        }
+      }
+
+      function trapEnterSubmissions(event, form){
+        if(enterPressed){
+          enterPressed = false; //we have trapped this, can stand down
+          return false;
+        }
+      }
+
+      function performInitialisation()
+      {
+      #if ( $instance)
+      #if ( ! $instance.IsNew)
+      <xsl:for-each select="$form/ancestor::adl:entity/adl:property[@type='link' or @type='list']">
+				<xsl:variable name="propname" select="@name"/>
+				<xsl:choose>
+					<xsl:when test="$form/@properties='all'">
+						<xsl:value-of select="concat( 'document.',$form/@name, '.', @name, '.submitHandler = shuffleSubmitHandler;')"/>
+					</xsl:when>
+					<xsl:when test="$form//adl:field[@property=$propname]">
+						<xsl:value-of select="concat( 'document.',$form/@name, '.', @name, '.submitHandler = shuffleSubmitHandler;')"/>
+					</xsl:when>
+					<!-- if we're not doing all properties, and if this property is not the property of a field,
+						we /don't/ set up a submit handler. -->
+				</xsl:choose>
+			</xsl:for-each>
+			#end
+			#end
+			var validator = new Validation('<xsl:value-of select="$form/@name"/>', {immediate : true, useTitles : true});
+      }
+
+      <xsl:for-each select="//adl:typedef">
+				<xsl:variable name="errormsg">
+					<xsl:choose>
+						<xsl:when test="adl:help[@locale=$locale]">
+							<xsl:apply-templates select="adl:help[@locale=$locale]"/>
+						</xsl:when>
+						<xsl:otherwise>
+							<xsl:call-template name="i18n-bad-format">
+								<xsl:with-param name="format-name" select="@name"/>
+							</xsl:call-template>
+						</xsl:otherwise>
+					</xsl:choose>
+				</xsl:variable>
+				Validation.add( '<xsl:value-of select="concat('validate-custom-', @name)"/>',
+				'<xsl:value-of select="normalize-space( $errormsg)"/>',
+				{
+				<xsl:choose>
+					<xsl:when test="@pattern">
+						pattern : new RegExp("<xsl:value-of select="@pattern"/>","gi")<xsl:if test="@size">
+							, maxLength : <xsl:value-of select="@size"/>
+						</xsl:if>
+					</xsl:when>
+					<xsl:when test="@minimum">
+						min : <xsl:value-of select="@minimum"/><xsl:if test="@maximum">
+							, max : <xsl:value-of select="@maximum"/>
+						</xsl:if>
+					</xsl:when>
+				</xsl:choose>
+				});
+			</xsl:for-each>
+		</script>
+	</xsl:template>
+
+	<!-- this template outputs MOST types of widget, but NOT shuffle widgets -->
+	<xsl:template name="property-widget">
+		<xsl:param name="property"/>
+		<xsl:param name="mode"/>
+		<xsl:variable name="base-type">
+			<xsl:call-template name="base-type">
+				<xsl:with-param name="property" select="$property"/>
+			</xsl:call-template>
+		</xsl:variable>
+		<xsl:variable name="href">
+			<xsl:choose>
+				<xsl:when test="$property/@type='entity' and //adl:entity[@name=$property/@entity]/adl:form[@name='edit']">
+					<!-- if this is an entity property, and the entity which it wraps has an edit form -->
+					<xsl:variable name="keys">
+						<xsl:call-template name="entity-keys-fragment">
+							<xsl:with-param name="entity" select="//adl:entity[@name=$property/@entity]"/>
+							<xsl:with-param name="instance" select="concat( 'instance.', $property/@name)"/>
+						</xsl:call-template>
+					</xsl:variable>
+					<xsl:value-of select="concat( '../', $property/@entity, '/edit.rails', $keys)"/>
+				</xsl:when>
+			</xsl:choose>
+		</xsl:variable>
+		<xsl:variable name="if-missing">
+			<xsl:choose>
+				<xsl:when test="$property/adl:if-missing[@locale = $locale]">
+					<xsl:value-of select="$property/adl:if-missing[@locale = $locale]"/>
+				</xsl:when>
+				<xsl:when test="$property/@required='true'">
+					<xsl:call-template name="i18n-value-required">
+						<xsl:with-param name="property-name" select="$property/@name"/>
+					</xsl:call-template>
+				</xsl:when>
+				<xsl:when test="$property/@type='defined'">
+					<xsl:call-template name="i18n-value-defined">
+						<xsl:with-param name="property-name" select="$property/@name"/>
+						<xsl:with-param name="definition-name" select="$property/@typedef"/>
+					</xsl:call-template>
+				</xsl:when>
+				<xsl:when test="$property/@type='entity'">
+					<xsl:call-template name="i18n-value-entity">
+						<xsl:with-param name="property-name" select="$property/@name"/>
+						<xsl:with-param name="entity-name" select="$property/@entity"/>
+					</xsl:call-template>
+				</xsl:when>
+				<xsl:otherwise>
+					<xsl:call-template name="i18n-value-type">
+						<xsl:with-param name="property-name" select="$property/@name"/>
+						<xsl:with-param name="type-name" select="$property/@type"/>
+					</xsl:call-template>
+				</xsl:otherwise>
+			</xsl:choose>
+		</xsl:variable>
+		<xsl:variable name="cssclass">
+			<xsl:if test="$property/@required='true'">required </xsl:if>
+			<xsl:choose>
+				<xsl:when test="$property/@type='defined'">
+					<xsl:choose>
+						<xsl:when test="//adl:typedef[@name=$property/@typedef]/@pattern">
+							<xsl:value-of select="concat( 'validate-custom-', $property/@typedef)"/>
+						</xsl:when>
+						<xsl:when test="//adl:typedef[@name=$property/@typedef]/@minimum">
+							<xsl:value-of select="concat( 'validate-custom-', $property/@typedef)"/>
+						</xsl:when>
+					</xsl:choose>
+				</xsl:when>
+				<xsl:when test="$base-type='integer'">validate-digits</xsl:when>
+				<xsl:when test="$base-type='real'">validate-number</xsl:when>
+				<xsl:when test="$base-type='money'">validate-number</xsl:when>
+				<xsl:when test="$base-type='date'">date-field validate-date</xsl:when>
+			</xsl:choose>
+		</xsl:variable>
+		<xsl:variable name="maxlength">
+			<xsl:call-template name="base-size">
+				<xsl:with-param name="property" select="$property"/>
+			</xsl:call-template>
+		</xsl:variable>
+		<xsl:variable name="size">
+			<xsl:choose>
+				<xsl:when test="$maxlength &gt; $max-widget-width">
+					<xsl:value-of select="$max-widget-width"/>
+				</xsl:when>
+				<xsl:otherwise>
+					<xsl:value-of select="$maxlength"/>
+				</xsl:otherwise>
+			</xsl:choose>
+		</xsl:variable>
+		<xsl:variable name="rows">
+			<!-- number of rows, if textarea emitted -->
+			<xsl:choose>
+				<xsl:when test="$base-type = 'text'">8</xsl:when>
+				<xsl:otherwise>1</xsl:otherwise>
+			</xsl:choose>
+		</xsl:variable>
+		<xsl:variable name="cols">
+			<!-- number of rows, if textarea emitted -->
+			<xsl:choose>
+				<xsl:when test="$base-type = 'text'">
+					<xsl:value-of select="$max-widget-width"/>
+				</xsl:when>
+				<xsl:otherwise>10</xsl:otherwise>
+			</xsl:choose>
+		</xsl:variable>
+		<xsl:variable name="required">
+			<xsl:choose>
+				<xsl:when test="$property/@required='true'">true</xsl:when>
+				<xsl:otherwise>false</xsl:otherwise>
+			</xsl:choose>
+		</xsl:variable>
+		<xsl:choose>
+			<xsl:when test="$property/adl:option">
+				<!-- emit a menu of options -->
+				<!-- it would be better to do this through a field helper but I haven't yet worked out how -->
+				<select>
+					<xsl:attribute name="name">
+						<xsl:value-of select="concat( 'instance.', $property/@name)"/>
+					</xsl:attribute>
+					<xsl:attribute name="id">
+						<xsl:value-of select="concat( 'instance_', $property/@name)"/>
+					</xsl:attribute>
+					<xsl:attribute name="class">
+						<xsl:value-of select="concat( 'instance.', $property/@name)"/>
+					</xsl:attribute>
+					<xsl:if test="not( $property/@required='true')">
+						<option value="'-1'">[unselected]</option>
+					</xsl:if>
+					<xsl:apply-templates select="$property/adl:option"/>
+				</select>
+				<script type="text/javascript" language="javascript">
+					// &lt;![CDATA[
+					#set ( <xsl:value-of select="concat( '$', $property/@name, '_sel_opt')"/>="<xsl:value-of select="concat( $property/@name, '-$instance.', $property/@name)"/>")
+					option = document.getElementById( "<xsl:value-of select="concat( '$', $property/@name, '_sel_opt')"/>");
+
+					if ( option != null)
+					{
+					option.selected = true;
+					}
+					// ]]&gt;
+				</script>
+
+			</xsl:when>
+			<xsl:when test="$property/@type = 'defined'">
+				<!-- it would be better to do this through a field helper but I haven't yet worked out how -->
+				<xsl:variable name="definition" select="//adl:typedef[@name=$property/@typedef]"/>
+				<xsl:variable name="minimum" select="$definition/@minimum"/>
+				<xsl:choose>
+					<xsl:when test="$base-type='string'">
+						${<xsl:value-of select="concat( $property/ancestor::adl:entity/@name, 'FieldHelper', '.', $mode, '(')"/> "<xsl:value-of select="concat( 'instance.', $property/@name)"/>", "%{class='<xsl:value-of select="normalize-space($cssclass)"/>',required='<xsl:value-of select="normalize-space( $required)"/>',title='<xsl:value-of select="normalize-space($if-missing)"/>',size='<xsl:value-of select="normalize-space($size)"/>',maxlength='<xsl:value-of select="normalize-space($maxlength)"/>',rows='<xsl:value-of select="normalize-space($rows)"/>',href='<xsl:value-of select="normalize-space($href)"/>'}")}
+					</xsl:when>
+					<xsl:when test="string-length($definition/@minimum) &gt; 0 and string-length( $definition/@maximum) &gt; 0">
+						<xsl:call-template name="slider-widget">
+							<xsl:with-param name="property" select="$property"/>
+							<xsl:with-param name="minimum" select="$definition/@minimum"/>
+							<xsl:with-param name="maximum" select="$definition/@maximum"/>
+						</xsl:call-template>
+						${<xsl:value-of select="concat( $property/ancestor::adl:entity/@name, 'FieldHelper', '.', $mode, '(')"/> "<xsl:value-of select="concat( 'instance.', $property/@name)"/>", "%{class='<xsl:value-of select="concat('slider, ', normalize-space($cssclass))"/>',title='<xsl:value-of select="normalize-space($if-missing)"/>',size='<xsl:value-of select="normalize-space($size)"/>',maxlength='<xsl:value-of select="normalize-space($maxlength)"/>',rows='<xsl:value-of select="normalize-space($rows)"/>',href='<xsl:value-of select="normalize-space($href)"/>'}")}
+					</xsl:when>
+					<xsl:otherwise>
+						${<xsl:value-of select="concat( $property/ancestor::adl:entity/@name, 'FieldHelper', '.', $mode, '(')"/> "<xsl:value-of select="concat( 'instance.', $property/@name)"/>", "%{class='<xsl:value-of select="normalize-space($cssclass)"/>',required='<xsl:value-of select="normalize-space( $required)"/>',title='<xsl:value-of select="normalize-space($if-missing)"/>',size='<xsl:value-of select="normalize-space($size)"/>',maxlength='<xsl:value-of select="normalize-space($maxlength)"/>',rows='<xsl:value-of select="normalize-space($rows)"/>',href='<xsl:value-of select="normalize-space($href)"/>'}")}
+					</xsl:otherwise>
+				</xsl:choose>
+			</xsl:when>
+			<xsl:when test="$property/@type = 'entity'">
+				<!-- once again, not only must you have access to the property but also to the entity -->
+				<xsl:variable name="readgroups">
+					<xsl:call-template name="entity-read-groups">
+						<xsl:with-param name="entity" select="//adl:entity[@name=$property/@entity]"/>
+					</xsl:call-template>
+				</xsl:variable>
+				<!-- NOTE! NOTE! NOTE! Whitespace is significant - any linefeeds inside the #if ( ) clause cause the Velocity parser to break! -->
+				#if ( <xsl:for-each select="exsl:node-set( $readgroups)/*">${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} ||</xsl:for-each> false)
+				${<xsl:value-of select="concat( $property/ancestor::adl:entity/@name, 'FieldHelper', '.', $mode, '(')"/> "<xsl:value-of select="concat( 'instance.', $property/@name)"/>", "%{class='<xsl:value-of select="normalize-space($cssclass)"/>',required='<xsl:value-of select="normalize-space( $required)"/>',title='<xsl:value-of select="normalize-space($if-missing)"/>',size='<xsl:value-of select="normalize-space($size)"/>',maxlength='<xsl:value-of select="normalize-space($maxlength)"/>',rows='<xsl:value-of select="normalize-space($rows)"/>',href='<xsl:value-of select="normalize-space($href)"/>'}")}
+				#else
+				[Not authorised]
+				#end
+			</xsl:when>
+			<xsl:otherwise>
+				${<xsl:value-of select="concat( $property/ancestor::adl:entity/@name, 'FieldHelper', '.', $mode, '(', '&quot;instance.', $property/@name, '&quot;')"/>, "%{class='<xsl:value-of select="normalize-space($cssclass)"/>',required='<xsl:value-of select="normalize-space( $required)"/>',title='<xsl:value-of select="normalize-space($if-missing)"/>',size='<xsl:value-of select="normalize-space($size)"/>',maxlength='<xsl:value-of select="normalize-space($maxlength)"/>',rows='<xsl:value-of select="normalize-space($rows)"/>',cols='<xsl:value-of select="normalize-space($cols)"/>',href='<xsl:value-of select="normalize-space($href)"/>',adltype='<xsl:value-of select="$property/@type"/>'}")}
+      </xsl:otherwise>				
+		</xsl:choose>
+	</xsl:template>
+
+	<xsl:template name="slider-widget">
+		<xsl:param name="property"/>
+		<xsl:param name="minimum" select="0"/>
+		<xsl:param name="maximum" select="100"/>
+		<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( $property/@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( $property/@name, '-track-left')"/>
+					</xsl:attribute>
+				</div>
+				<div style="width:19px; height:20px;">
+					<xsl:attribute name="id">
+						<xsl:value-of select="concat( $property/@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="$property/@name"/>-slider','<xsl:value-of select="$property/@name"/>-track',{
+				onSlide:function(v){$('<xsl:value-of select="concat( 'instance_', $property/@name)"/>').value = <xsl:value-of select="$minimum"/>+ Math.floor(v*(<xsl:value-of select="$maximum - $minimum"/>))}
+        });
+        // ]]&gt;
+			</script>
+		</xsl:if>
+	</xsl:template>
+
+	<!-- assemble keys for this entity in a Velocity-friendly format, to splice into an HREF below -->
+	<xsl:template name="entity-keys-fragment">
+		<xsl:param name="entity"/>
+		<xsl:param name="instance" select="$entity/@name"/>
+		<xsl:for-each select="$entity/adl:key/adl:property">
+			<xsl:variable name="sep">
+				<xsl:choose>
+					<xsl:when test="position()=1">?</xsl:when>
+					<xsl:otherwise>&amp;</xsl:otherwise>
+				</xsl:choose>
+			</xsl:variable>
+			<xsl:choose>
+				<xsl:when test="@type='entity'">
+					<xsl:value-of select="concat( $sep, @name, '=$', $instance, '.', @name, '_Value')"/>
+				</xsl:when>
+				<xsl:otherwise>
+					<xsl:value-of select="concat( $sep, @name, '=$', $instance, '.', @name)"/>
+				</xsl:otherwise>
+			</xsl:choose>
+		</xsl:for-each>
+	</xsl:template>
+
+	<!-- overall page layout -->
+
+	<xsl:template match="adl:content"/>
+
+	<xsl:template match="adl:help">
+		<xsl:apply-templates/>
+	</xsl:template>
+
+	<!-- assuming an empty layout, install all the standard scripts 
+    which an ADL page may need -->
+	<xsl:template name="install-scripts">
+    ${ScriptsHelper.InstallScript( "ShuffleWidget")}
+
+    ${Ajax.InstallScripts()}
+    ${FormHelper.InstallScripts()}
+    ${Validation.InstallScripts()}
+    ${Scriptaculous.InstallScripts()}
+    ${DateTimeHelper.InstallScripts()}
+
+    ${ScriptsHelper.InstallScript( "Sitewide")}
+    ${ScriptsHelper.InstallScript( "Behaviour")}
+    ${ScriptsHelper.InstallScript( "Epoch")}
+    ${ScriptsHelper.InstallScript( "Panes")}
+    ${ScriptsHelper.InstallScript( "SortTable")}
+  </xsl:template>
+
+  <!-- standard header material - auto-timeout, etc -->
+	<xsl:template name="head">
+    <xsl:comment>
+      <xsl:value-of select="/adl:application/@name"/> <xsl:value-of select="$product-version"/> - <xsl:value-of select="/adl:application/@revision"/>
+      Auto generated Velocity macro for <xsl:value-of select="@name"/>,
+      generated from ADL.
+
+      Generated using adl2views.xslt <xsl:value-of select="substring( '$Revision: 1.66 $', 10)"/>
+      Generation parameters were:
+      area-name: <xsl:value-of select="$area-name"/>
+      default-url: <xsl:value-of select="$default-url"/>
+      generate-site-navigation: <xsl:value-of select="$generate-site-navigation"/>
+      layout-name: <xsl:value-of select="$layout-name"/>
+      locale: <xsl:value-of select="$locale"/>
+      max-widget-width: <xsl:value-of select="$max-widget-width"/>
+      product-version: <xsl:value-of select="$product-version"/>
+      page-timeout: <xsl:value-of select="$page-timeout"/>
+      show-errors: <xsl:value-of select="$show-errors"/>
+      show-messages: <xsl:value-of select="$show-messages"/>
+    </xsl:comment>
+    <xsl:if test="$page-timeout &gt; 0">
+      <meta http-equiv="refresh">
+        <xsl:attribute name="content">
+          <xsl:value-of select="concat($page-timeout, '; URL=', $default-url)"/>
+        </xsl:attribute>
+      </meta>
+    </xsl:if>
+    <xsl:choose>
+      <xsl:when test="adl:head">
+        <xsl:for-each select="adl:head/*">
+          <xsl:apply-templates select="."/>
+        </xsl:for-each>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:for-each select="//adl:content/adl:head/*">
+					<xsl:apply-templates select="."/>
+        </xsl:for-each>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  
+  <!-- standard top area content on all pages (navigation, etc) -->
+  <xsl:template name="top">
+    <xsl:choose>
+      <xsl:when test="adl:top">
+        <xsl:for-each select="adl:top/*">
+          <xsl:apply-templates select="."/>
+        </xsl:for-each>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:for-each select="//adl:content/adl:top/*">
+          <xsl:apply-templates select="."/>
+        </xsl:for-each>
+      </xsl:otherwise>
+    </xsl:choose>
+    <xsl:if test="$authentication-layer = 'Database'">
+      #if ( ${SecurityHelper.GetUserName()})
+      <!-- the #else and #end of this #if is generated in the foot template -->
+    </xsl:if>
+    <xsl:variable name="current-entity" select="ancestor::adl:entity/@name"/>
+    <xsl:if test="$generate-site-navigation = 'true'">
+      <ul class="generatednav">
+        <xsl:for-each select="//adl:entity[adl:list[@name='list']]">
+          <xsl:variable name="readgroups">
+            <xsl:call-template name="page-read-groups">
+              <xsl:with-param name="page" select="."/>
+            </xsl:call-template>
+          </xsl:variable>
+          <xsl:if test="$authentication-layer = 'Database'">
+            #if ( <xsl:for-each select="exsl:node-set( $readgroups)/*"> ${SecurityHelper.InGroup( "<xsl:value-of select="./@name"/>")} ||</xsl:for-each> false)
+          </xsl:if>
+          <li>
+            <xsl:attribute name="class">
+              <xsl:choose>
+                <xsl:when test="@name = $current-entity">selected-nav</xsl:when>
+                <xsl:otherwise>navigation</xsl:otherwise>
+              </xsl:choose>
+            </xsl:attribute>
+            <a>
+              <xsl:attribute name="href">
+                <xsl:choose>
+                  <xsl:when test="string-length( $site-root) &gt; 0">
+                    <xsl:choose>
+                      <xsl:when test="string-length( $area-name) &gt; 0">
+                        <xsl:value-of select="concat( $site-root, '/', $area-name, '/', @name, '/', adl:list[position()=1]/@name, '.rails')"/>
+                      </xsl:when>
+                      <xsl:otherwise>
+                        <xsl:value-of select="concat( $site-root, '/', @name, '/', adl:list[position()=1]/@name, '.rails')"/>
+                      </xsl:otherwise>
+                    </xsl:choose>
+                  </xsl:when>
+                  <xsl:when test="string-length( $area-name) &gt; 0">
+                    <xsl:value-of select="concat( '/', $area-name, '/', @name, '/', adl:list[position()=1]/@name, '.rails')"/>
+                  </xsl:when>
+                  <xsl:otherwise>
+                    <xsl:value-of select="concat( '/', @name, '/', adl:list[position()=1]/@name, '.rails')"/>
+                  </xsl:otherwise>
+                </xsl:choose>
+              </xsl:attribute>
+              <xsl:call-template name="showprompt">
+                <xsl:with-param name="fallback" select="@name"/>
+                <xsl:with-param name="entity" select="."/>
+              </xsl:call-template>
+            </a>
+          </li>
+          <xsl:if test="$authentication-layer = 'Database'">
+            #end
+          </xsl:if>
+        </xsl:for-each>
+      </ul>
+    </xsl:if>
+  </xsl:template>
+
+  <!-- standard footer on all pages; product identifier and version -->
+  <xsl:template name="foot">
+    <xsl:if test="$authentication-layer = 'Database'">
+      <!-- the #if for this #else and #end is generated in the head template -->
+      #else
+      <div class="content">
+        <p>
+          To view this page you must first <a href="../dblogin/login.rails">Log in</a>
+        </p>
+      </div>
+      #end
+    </xsl:if>
+    <div class="pagefoot">
+      <xsl:choose>
+        <xsl:when test="adl:foot">
+          <xsl:for-each select="adl:foot/*">
+            <xsl:apply-templates select="."/>
+          </xsl:for-each>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:for-each select="//adl:content/adl:foot/*">
+            <xsl:apply-templates select="."/>
+          </xsl:for-each>
+        </xsl:otherwise>
+      </xsl:choose>
+      <p class="product-version">
+        <xsl:value-of select="$product-version"/>; built with <xsl:value-of select="$authentication-layer"/>-layer authentication.
+      </p>
+    </div>
+  </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:param name="entity" select="$node/ancestor::adl:entity"/>
+		<xsl:param name="locale" select="'en-GB'"/>
+		<xsl:choose>
+			<xsl:when test="$node/adl:prompt[@locale=$locale]">
+				<xsl:value-of select="$node/adl:prompt[@locale=$locale][1]/@prompt"/>
+			</xsl:when>
+			<xsl:when test="$node/adl:prompt[@locale='default']">
+				<xsl:value-of select="$node/adl:prompt[@locale='default'][1]/@prompt"/>
+			</xsl:when>
+			<xsl:when test="$node/@property">
+				<!-- it's (probably) a field which doesn't have any prompt of its own - 
+					fetch from its property -->
+				<xsl:variable name="propname" select="@property"/>
+				<xsl:call-template name="showprompt">
+					<xsl:with-param name="fallback" select="$fallback"/>
+					<xsl:with-param name="node" select="$entity//adl:property[@name=$propname]"/>
+					<xsl:with-param name="entity" select="$entity"/>
+					<xsl:with-param name="locale" select="$locale"/>
+				</xsl:call-template>
+			</xsl:when>	  
+			<xsl:otherwise>
+				<xsl:value-of select="$fallback"/>
+			</xsl:otherwise>
+		</xsl:choose>
+	</xsl:template>
+
+  <!-- compose the list of search parameters to append to a pagination request; note that this does
+  not currently work but I have some hopes that in future it will and in the meantime it costs us
+  little -->
+  <xsl:template name="pagination-search-params">
+    <xsl:param name="form" select="."/>
+    "%{<xsl:for-each select="$form/adl:field">
+      <xsl:variable name="field" select="."/>
+      <xsl:variable name="search-name"
+                    select="concat('search_',$form/ancestor::adl:entity//adl:property[@name=$field/@property]/@name)"/>
+      <xsl:value-of select="concat( $search-name, '=$', $search-name)"/>
+      <xsl:if test="not( position() = last())">,</xsl:if>
+    </xsl:for-each>}"
+  </xsl:template>
+
+	<xsl:template match="groups">
+		<xsl:apply-templates/>
+	</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/transforms/base-type-include.xslt b/transforms/base-type-include.xslt
index 4671480..4f43590 100755
--- a/transforms/base-type-include.xslt
+++ b/transforms/base-type-include.xslt
@@ -1,75 +1,75 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!--
-    Application Description Language framework
-    base-type-include.xslt
-    
-    (c) 2007 Cygnet Solutions Ltd
-    
-    An xsl transform intended to be included into other XSL stylesheets,
-    intended to keep lookup of the ADL base type from ADL properties in
-    one place for ease of maintenance
-    
-    $Author: sb $
-    $Revision: 1.4 $
-    $Date: 2010-01-12 17:20:17 $
-  -->
-
-<xsl:stylesheet version="1.0"
-  xmlns="http://libs.cygnets.co.uk/adl/1.4/"
-  xmlns:adl="http://libs.cygnets.co.uk/adl/1.4/"
-  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
-  exclude-result-prefixes="adl">
-
-
-	<!-- return the base ADL type of the property which is passed as a parameter -->
-	<xsl:template name="base-type">
-		<xsl:param name="property"/>
-		<xsl:choose>
-			<xsl:when test="$property/@type='defined'">
-				<xsl:variable name="definition">
-					<xsl:value-of select="$property/@typedef"/>
-				</xsl:variable>
-				<xsl:value-of select="/adl:application/adl:typedef[@name=$definition]/@type"/>
-			</xsl:when>
-			<xsl:when test="$property/@type='serial'">integer</xsl:when>
-			<xsl:when test="$property/@type='message'">integer</xsl:when>
-			<xsl:otherwise>
-				<xsl:value-of select="$property/@type"/>
-			</xsl:otherwise>
-		</xsl:choose>
-	</xsl:template>
-
-	<!-- return the size of the type of the property which is passed as a parameter -->
-	<xsl:template name="base-size">
-		<xsl:param name="property"/>
-		<xsl:variable name="base-type">
-			<xsl:call-template name="base-type">
-				<xsl:with-param name="property" select="$property"/>
-			</xsl:call-template>
-		</xsl:variable>
-		<xsl:choose>
-			<xsl:when test="$property/@type='defined'">
-				<xsl:variable name="definition">
-					<xsl:value-of select="$property/@typedef"/>
-				</xsl:variable>
-				<xsl:value-of select="/adl:application/adl:typedef[@name=$definition]/@size"/>
-			</xsl:when>
-			<!-- type='text' should really be unlimited, but in the real world it isn't. 
-			Furthermore, setting null values may currently break the smart form components 
-			parser -->
-			<xsl:when test="$base-type='text'">4294967296</xsl:when>
-			<xsl:when test="$base-type='integer'">8</xsl:when>
-			<xsl:when test="$base-type='real'">8</xsl:when>
-			<xsl:when test="$base-type='money'">10</xsl:when>
-			<xsl:when test="$base-type='date'">10</xsl:when>
-			<xsl:when test="$base-type='time'">8</xsl:when>
-			<xsl:when test="$property/@size &gt; 0">
-				<xsl:value-of select="$property/@size"/>
-			</xsl:when>
-			<xsl:otherwise>
-				<xsl:value-of select="$base-type"/>
-			</xsl:otherwise>
-		</xsl:choose>
-	</xsl:template>
-
-</xsl:stylesheet>
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+    Application Description Language framework
+    base-type-include.xslt
+    
+    (c) 2007 Cygnet Solutions Ltd
+    
+    An xsl transform intended to be included into other XSL stylesheets,
+    intended to keep lookup of the ADL base type from ADL properties in
+    one place for ease of maintenance
+    
+    $Author: simon $
+    $Revision: 1.5 $
+    $Date: 2010-07-20 19:53:40 $
+  -->
+
+<xsl:stylesheet version="1.0"
+  xmlns="http://libs.cygnets.co.uk/adl/1.4/"
+  xmlns:adl="http://libs.cygnets.co.uk/adl/1.4/"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  exclude-result-prefixes="adl">
+
+
+	<!-- return the base ADL type of the property which is passed as a parameter -->
+	<xsl:template name="base-type">
+		<xsl:param name="property"/>
+		<xsl:choose>
+			<xsl:when test="$property/@type='defined'">
+				<xsl:variable name="definition">
+					<xsl:value-of select="$property/@typedef"/>
+				</xsl:variable>
+				<xsl:value-of select="/adl:application/adl:typedef[@name=$definition]/@type"/>
+			</xsl:when>
+			<xsl:when test="$property/@type='serial'">integer</xsl:when>
+			<xsl:when test="$property/@type='message'">integer</xsl:when>
+			<xsl:otherwise>
+				<xsl:value-of select="$property/@type"/>
+			</xsl:otherwise>
+		</xsl:choose>
+	</xsl:template>
+
+	<!-- return the size of the type of the property which is passed as a parameter -->
+	<xsl:template name="base-size">
+		<xsl:param name="property"/>
+		<xsl:variable name="base-type">
+			<xsl:call-template name="base-type">
+				<xsl:with-param name="property" select="$property"/>
+			</xsl:call-template>
+		</xsl:variable>
+		<xsl:choose>
+			<xsl:when test="$property/@type='defined'">
+				<xsl:variable name="definition">
+					<xsl:value-of select="$property/@typedef"/>
+				</xsl:variable>
+				<xsl:value-of select="/adl:application/adl:typedef[@name=$definition]/@size"/>
+			</xsl:when>
+			<!-- type='text' should really be unlimited, but in the real world it isn't. 
+			Furthermore, setting null values may currently break the smart form components 
+			parser -->
+			<xsl:when test="$base-type='text'">4294967296</xsl:when>
+			<xsl:when test="$base-type='integer'">8</xsl:when>
+			<xsl:when test="$base-type='real'">8</xsl:when>
+			<xsl:when test="$base-type='money'">10</xsl:when>
+			<xsl:when test="$base-type='date'">10</xsl:when>
+			<xsl:when test="$base-type='time'">8</xsl:when>
+			<xsl:when test="$property/@size &gt; 0">
+				<xsl:value-of select="$property/@size"/>
+			</xsl:when>
+			<xsl:otherwise>
+				<xsl:value-of select="$base-type"/>
+			</xsl:otherwise>
+		</xsl:choose>
+	</xsl:template>
+
+</xsl:stylesheet>
diff --git a/transforms/csharp-type-include.xslt b/transforms/csharp-type-include.xslt
index 9582085..b51fba5 100755
--- a/transforms/csharp-type-include.xslt
+++ b/transforms/csharp-type-include.xslt
@@ -1,99 +1,100 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!--
-    Application Description Language framework
-    csharp-type-include.xslt
-    
-    (c) 2007 Cygnet Solutions Ltd
-    
-    An XSL transform intended to be included into other XSL stylesheets,
-    intended to keep lookup of the C# type from ADL properties in
-    one place for ease of maintenance
-    
-    $Author: sb $
-    $Revision: 1.4 $
-    $Date: 2010-01-12 17:20:17 $
-  -->
-
-<xsl:stylesheet version="1.0"
-  xmlns="http://libs.cygnets.co.uk/adl/1.4/"
-  xmlns:adl="http://libs.cygnets.co.uk/adl/1.4/"
-  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
-  exclude-result-prefixes="adl">
-
-  <xsl:include href="base-type-include.xslt"/>
-  
-  <!-- return the primitive C# type of the property which is passed as 
-  a parameter - i.e. if csharp-type is an entity, then the csharp-type 
-  of the keyfield of that entity, and so on. -->
-  <xsl:template name="csharp-base-type">
-    <xsl:param name="property"/>
-    <xsl:param name="entityns"/>
-    <xsl:choose>
-      <xsl:when test="$property/@type = 'entity'">
-        <xsl:variable name="entityname" select="$property/@entity"/>
-        <xsl:choose>
-          <xsl:when test="//adl:entity[@name=$entityname]/adl:key/adl:property">
-            <!-- recurse... -->
-            <xsl:call-template name="csharp-base-type">
-              <xsl:with-param name="property" 
-                              select="//adl:entity[@name=$entityname]/adl:key/adl:property[position()=1]"/>
-              <xsl:with-param name="entityns" select="$entityns"/>
-            </xsl:call-template>
-          </xsl:when>
-          <xsl:otherwise>
-            <xsl:message terminate="yes">
-              ADL: ERROR: could not find C# base type of property <xsl:value-of select="$property/@name"/>
-            </xsl:message>
-          </xsl:otherwise>
-        </xsl:choose>
-      </xsl:when>
-      <xsl:otherwise>
-        <xsl:call-template name="csharp-type">
-          <xsl:with-param name="property" select="$property"/>
-          <xsl:with-param name="entityns" select="$entityns"/>
-        </xsl:call-template>
-      </xsl:otherwise>
-    </xsl:choose>
-  </xsl:template>
-  
-  <!-- return the C# type of the property which is passed as a parameter -->
-  <xsl:template name="csharp-type">
-    <xsl:param name="property"/>
-    <xsl:param name="entityns"/>
-    <xsl:variable name="base-type">
-      <xsl:call-template name="base-type">
-        <xsl:with-param name="property" select="$property"/>
-      </xsl:call-template>
-    </xsl:variable>
-    <xsl:choose>
-      <xsl:when test="$property/@type = 'message'">Message</xsl:when>
-      <xsl:when test="$base-type = 'link'">
-        ICollection&lt;<xsl:value-of select="@entity"/>&gt;
-      </xsl:when>
-      <xsl:when test="$base-type = 'list'">
-        ICollection&lt;<xsl:value-of select="@entity"/>&gt;
-      </xsl:when>
-      <xsl:when test="$base-type = 'date'">DateTime</xsl:when>
-      <xsl:when test="$base-type = 'time'">DateTime</xsl:when>
-      <xsl:when test="$base-type = 'string'">String</xsl:when>
-      <xsl:when test="$base-type = 'text'">String</xsl:when>
-      <xsl:when test="$base-type = 'boolean'">Boolean</xsl:when>
-      <xsl:when test="$base-type = 'timestamp'">DateTime</xsl:when>
-      <xsl:when test="$base-type = 'integer'">int</xsl:when>
-      <xsl:when test="$base-type = 'real'">double</xsl:when>
-      <xsl:when test="$base-type = 'money'">Decimal</xsl:when>
-      <xsl:when test="$base-type = 'entity'">
-        <xsl:choose>
-          <xsl:when test="$entityns">
-            <xsl:value-of select="concat( $entityns, '.', $property/@entity)"/>
-          </xsl:when>
-          <xsl:otherwise>
-            <xsl:value-of select="$property/@entity"/>
-          </xsl:otherwise>
-        </xsl:choose>
-      </xsl:when>
-      <xsl:otherwise>[unknown?]</xsl:otherwise>
-    </xsl:choose>
-  </xsl:template>
-
-</xsl:stylesheet> 
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+    Application Description Language framework
+    csharp-type-include.xslt
+    
+    (c) 2007 Cygnet Solutions Ltd
+    
+    An XSL transform intended to be included into other XSL stylesheets,
+    intended to keep lookup of the C# type from ADL properties in
+    one place for ease of maintenance
+    
+    $Author: simon $
+    $Revision: 1.5 $
+    $Date: 2010-07-20 19:53:40 $
+  -->
+
+<xsl:stylesheet version="1.0"
+  xmlns="http://libs.cygnets.co.uk/adl/1.4/"
+  xmlns:adl="http://libs.cygnets.co.uk/adl/1.4/"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  exclude-result-prefixes="adl">
+
+  <xsl:include href="base-type-include.xslt"/>
+  
+  <!-- return the primitive C# type of the property which is passed as 
+  a parameter - i.e. if csharp-type is an entity, then the csharp-type 
+  of the keyfield of that entity, and so on. -->
+  <xsl:template name="csharp-base-type">
+    <xsl:param name="property"/>
+    <xsl:param name="entityns"/>
+    <xsl:choose>
+      <xsl:when test="$property/@type = 'entity'">
+        <xsl:variable name="entityname" select="$property/@entity"/>
+        <xsl:choose>
+          <xsl:when test="//adl:entity[@name=$entityname]/adl:key/adl:property">
+            <!-- recurse... -->
+            <xsl:call-template name="csharp-base-type">
+              <xsl:with-param name="property" 
+                              select="//adl:entity[@name=$entityname]/adl:key/adl:property[position()=1]"/>
+              <xsl:with-param name="entityns" select="$entityns"/>
+            </xsl:call-template>
+          </xsl:when>
+          <xsl:otherwise>
+            <xsl:message terminate="yes">
+              ADL: ERROR: could not find C# base type of property <xsl:value-of select="$property/@name"/>
+            </xsl:message>
+          </xsl:otherwise>
+        </xsl:choose>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:call-template name="csharp-type">
+          <xsl:with-param name="property" select="$property"/>
+          <xsl:with-param name="entityns" select="$entityns"/>
+        </xsl:call-template>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  
+  <!-- return the C# type of the property which is passed as a parameter -->
+  <xsl:template name="csharp-type">
+    <xsl:param name="property"/>
+    <xsl:param name="entityns"/>
+    <xsl:variable name="base-type">
+      <xsl:call-template name="base-type">
+        <xsl:with-param name="property" select="$property"/>
+      </xsl:call-template>
+    </xsl:variable>
+    <xsl:choose>
+      <xsl:when test="$property/@type = 'message'">Message</xsl:when>
+      <xsl:when test="$base-type = 'link'">
+        ICollection&lt;<xsl:value-of select="@entity"/>&gt;
+      </xsl:when>
+      <xsl:when test="$base-type = 'list'">
+        ICollection&lt;<xsl:value-of select="@entity"/>&gt;
+      </xsl:when>
+      <xsl:when test="$base-type = 'date'">DateTime</xsl:when>
+      <xsl:when test="$base-type = 'time'">DateTime</xsl:when>
+      <xsl:when test="$base-type = 'string'">String</xsl:when>
+      <xsl:when test="$base-type = 'text'">String</xsl:when>
+      <xsl:when test="$base-type = 'image'">String</xsl:when>
+      <xsl:when test="$base-type = 'boolean'">Boolean</xsl:when>
+      <xsl:when test="$base-type = 'timestamp'">DateTime</xsl:when>
+      <xsl:when test="$base-type = 'integer'">int</xsl:when>
+      <xsl:when test="$base-type = 'real'">double</xsl:when>
+      <xsl:when test="$base-type = 'money'">Decimal</xsl:when>
+      <xsl:when test="$base-type = 'entity'">
+        <xsl:choose>
+          <xsl:when test="$entityns">
+            <xsl:value-of select="concat( $entityns, '.', $property/@entity)"/>
+          </xsl:when>
+          <xsl:otherwise>
+            <xsl:value-of select="$property/@entity"/>
+          </xsl:otherwise>
+        </xsl:choose>
+      </xsl:when>
+      <xsl:otherwise>[unknown?]</xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+</xsl:stylesheet> 
diff --git a/transforms/i18n-en-GB-include.xslt b/transforms/i18n-en-GB-include.xslt
index 90a3559..7cb8362 100755
--- a/transforms/i18n-en-GB-include.xslt
+++ b/transforms/i18n-en-GB-include.xslt
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <xsl:stylesheet version="1.0"
-	xmlns="http://libs.cygnets.co.uk/adl/1.4/"
-	xmlns:adl="http://libs.cygnets.co.uk/adl/1.4/"
+	xmlns="http://bowyer.journeyman.cc/adl/1.4/"
+	xmlns:adl="http://bowyer.journeyman.cc/adl/1.4/"
 	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 	xmlns:msxsl="urn:schemas-microsoft-com:xslt">
 	
@@ -21,9 +21,9 @@
 	(iii) take arguments which are strings only, not nodesets.
 	Templates are listed in alphabetical order.
     
-    $Author: sb $
-    $Revision: 1.7 $
-    $Date: 2010-01-12 17:20:17 $
+    $Author: simon $
+    $Revision: 1.8 $
+    $Date: 2010-07-20 19:53:40 $
 	-->
 
 	<xsl:template name="i18n-add-a-new">
diff --git a/transforms/permissions-include.xslt b/transforms/permissions-include.xslt
index 1e20161..de441e7 100755
--- a/transforms/permissions-include.xslt
+++ b/transforms/permissions-include.xslt
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <xsl:stylesheet version="1.0"
-	xmlns="http://libs.cygnets.co.uk/adl/1.4/"
-	xmlns:adl="http://libs.cygnets.co.uk/adl/1.4/"
+	xmlns="http://bowyer.journeyman.cc/adl/1.4/"
+	xmlns:adl="http://bowyer.journeyman.cc/adl/1.4/"
 	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 	xmlns:msxsl="urn:schemas-microsoft-com:xslt"
 				xmlns:exsl="urn:schemas-microsoft-com:xslt"
@@ -14,9 +14,9 @@
     
     Utility templates to find permissions on various things
     
-    $Author: sb $
-    $Revision: 1.6 $
-    $Date: 2010-01-12 17:20:17 $
+    $Author: simon $
+    $Revision: 1.7 $
+    $Date: 2010-07-20 19:53:40 $
 	-->
 
 	<!-- collect all groups which can edit the specified property -->