diff --git a/ADL.NET/ADL.csproj b/ADL.NET/ADL.csproj new file mode 100755 index 0000000..b2b9933 --- /dev/null +++ b/ADL.NET/ADL.csproj @@ -0,0 +1,84 @@ +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion>8.0.50727</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{7D9E1F28-3F9C-4675-A02C-C9B2E98A839E}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>ADL</RootNamespace> + <AssemblyName>ADL</AssemblyName> + <StartupObject> + </StartupObject> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Data" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="Exceptions\DataSuitabilityException.cs" /> + <Compile Include="Exceptions\DataFormatException.cs" /> + <Compile Include="Exceptions\DataRangeException.cs" /> + <Compile Include="Exceptions\DataRequiredException.cs" /> + <Compile Include="Exceptions\DomainKnowledgeViolationException.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Properties\Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Resources.resx</DependentUpon> + </Compile> + </ItemGroup> + <ItemGroup> + <None Include="j2adl.dtd" /> + </ItemGroup> + <ItemGroup> + <Content Include="Trans\adl2controllerclasses.xsl" /> + <Content Include="Trans\adl2entityclass.xsl" /> + <Content Include="Trans\adl2hibernate.xsl" /> + <Content Include="Trans\adl2views.xsl" /> + <Content Include="Trans\adl2mssql.xsl" /> + <Content Include="Trans\adl2psql.xsl" /> + <Content Include="Trans\datadescriber.xsl" /> + <Content Include="Trans\hibernate2adl.xsl" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\CygnetToolkit\CygnetToolkit.csproj"> + <Project>{77FB7DE5-1F33-4DDC-8A2E-79EF4728705E}</Project> + <Name>CygnetToolkit</Name> + </ProjectReference> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="Properties\Resources.resx"> + <SubType>Designer</SubType> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + </EmbeddedResource> + </ItemGroup> + <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> +</Project> \ No newline at end of file diff --git a/ADL.NET/Exceptions/DataFormatException.cs b/ADL.NET/Exceptions/DataFormatException.cs new file mode 100755 index 0000000..cf93118 --- /dev/null +++ b/ADL.NET/Exceptions/DataFormatException.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Text; + +/* + * Application Description Framework + * DataRangeException.cs + * + * (c) 2007 Cygnet Solutions Ltd + * + * $Author: af $ + * $Revision: 1.1 $ + */ + +namespace ADL.Exceptions { + /// <summary> + /// An exception to be thrown if an attempt is made to set a property to a + /// value which is unsuitably formatted for the data type + /// </summary> + public class DataFormatException : DataSuitabilityException { + public DataFormatException(String message) : base(message) {} + } +} diff --git a/ADL.NET/Exceptions/DataRangeException.cs b/ADL.NET/Exceptions/DataRangeException.cs new file mode 100755 index 0000000..9906b6e --- /dev/null +++ b/ADL.NET/Exceptions/DataRangeException.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Text; + +/* + * Application Description Framework + * DataRangeException.cs + * + * (c) 2007 Cygnet Solutions Ltd + * + * $Author: af $ + * $Revision: 1.1 $ + */ + +namespace ADL.Exceptions { + /// <summary> + /// An exception to be thrown if an attempt is made to set a scalar property with a + /// defined range to a value which is outside that range + /// </summary> + public class DataRangeException : DataSuitabilityException { + public DataRangeException(String message) : base(message) {} + } +} diff --git a/ADL.NET/Exceptions/DataRequiredException.cs b/ADL.NET/Exceptions/DataRequiredException.cs new file mode 100755 index 0000000..1857b63 --- /dev/null +++ b/ADL.NET/Exceptions/DataRequiredException.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Text; + +/* + * Application Description Framework + * DataRequiredException.cs + * + * (c) 2007 Cygnet Solutions Ltd + * + * $Author: af $ + * $Revision: 1.1 $ + */ +namespace ADL.Exceptions { + /// <summary> + /// An exception to be thrown if an attempt is made to set a required property to null + /// </summary> + public class DataRequiredException : DataSuitabilityException { + public DataRequiredException(String message) : base(message){} + } +} diff --git a/ADL.NET/Exceptions/DataSuitabilityException.cs b/ADL.NET/Exceptions/DataSuitabilityException.cs new file mode 100755 index 0000000..377181c --- /dev/null +++ b/ADL.NET/Exceptions/DataSuitabilityException.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Text; + +/* + * Application Description Framework + * DataRangeException.cs + * + * (c) 2007 Cygnet Solutions Ltd + * + * $Author: af $ + * $Revision: 1.1 $ + */ + +namespace ADL.Exceptions { + /// <summary> + /// An exception to be thrown if an attempt is made to set a property + /// to a value which is unsuitable + /// </summary> + public abstract class DataSuitabilityException : Exception { + public DataSuitabilityException(String message) : base(message) {} + } +} diff --git a/ADL.NET/Exceptions/DomainKnowledgeViolationException.cs b/ADL.NET/Exceptions/DomainKnowledgeViolationException.cs new file mode 100755 index 0000000..67d0006 --- /dev/null +++ b/ADL.NET/Exceptions/DomainKnowledgeViolationException.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Text; + +/* + * Application Description Framework + * DomainKnowledgeViolationException.cs + * + * (c) 2007 Cygnet Solutions Ltd + * + * $Author: af $ + * $Revision: 1.1 $ + */ + +namespace ADL.Exceptions { + /// <summary> + /// An exception to be thrown if a state arises which violates + /// some specific knowledge about the application domain (i.e. + /// a 'business rule' violation) + /// </summary> + public class DomainKnowledgeViolationException : Exception { + public DomainKnowledgeViolationException(String message) : base(message) { } + } +} diff --git a/ADL.NET/Properties/AssemblyInfo.cs b/ADL.NET/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..2e82949 --- /dev/null +++ b/ADL.NET/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ADL")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ADL")] +[assembly: AssemblyCopyright("Copyright © 2007 Cygnet Solutions Ltd")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("6be1b0e7-f012-44ee-a35f-892f53b627ad")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/ADL.NET/Trans/adl2controllerclasses.xsl b/ADL.NET/Trans/adl2controllerclasses.xsl new file mode 100755 index 0000000..68bec4b --- /dev/null +++ b/ADL.NET/Trans/adl2controllerclasses.xsl @@ -0,0 +1,542 @@ +<?xml version="1.0" encoding="UTF-8"?> + + <!-- + C1873 SRU Hospitality + adl2controllerclasses.xsl + + (c) 2007 Cygnet Solutions Ltd + + Transform ADL into (partial) controller classes + + $Author: af $ + $Revision: 1.1 $ + $Date: 2008-01-09 15:01:45 $ + --> + + <!-- WARNING WARNING WARNING: Do NOT reformat this file! + Whitespace (or lack of it) is significant! --> + <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + <xsl:output encoding="UTF-8" method="text"/> + + <!-- The locale for which these controllers are generated + TODO: Controllers should NOT be locale specific. Instead, the + controller should render views and generate messages based on the + client's locale. However, there may still need to be a concept of a + 'default locale', for when we don't have messages which suit the + client's locale --> + <xsl:param name="locale" select="en-UK"/> + + <!-- The C# namespace within which I shall generate controllers --> + <xsl:param name="controllerns" select="Unset"/> + <!-- The C# namespace used by the entities for this project --> + <xsl:param name="entityns" select="Unset"/> + + <xsl:template match="application"> + <xsl:apply-templates select="entity"/> + </xsl:template> + + <xsl:template match="entity"> + <!-- what's all this about? the objective is to get the revision number of the + transform into the output, /without/ getting that revision number overwritten + with the revision number of the generated file if the generated file is + stored to CVS --> + <xsl:variable name="transform-rev1" + select="substring( '$Revision: 1.1 $', 11)"/> + <xsl:variable name="transform-revision" + select="substring( $transform-rev1, 0, string-length( $transform-rev1) - 1)"/> + + <xsl:variable name="key"> + <xsl:call-template name="primary-key"> + <xsl:with-param name="entityname" select="@name"/> + </xsl:call-template> + </xsl:variable> + +/* ---- [ cut here: next file '<xsl:value-of select="@name"/>Controller.auto.cs'] ---------------- */ + +//------------------------------------------------------------------ +// +// Application Description Framework +// <xsl:value-of select="@name"/>Controller.auto.cs +// +// (c) 2007 Cygnet Solutions Ltd +// +// Controller for auto-generated forms for editing <xsl:value-of select="@name"/>s +// Automatically generated from application description using +// adl2controllerclass.xsl version <xsl:value-of select="$transform-revision"/> +// +// This file is automatically generated; DO NOT EDIT IT. +// +//------------------------------------------------------------------ + +using System; +using System.Data; +using System.Collections.Generic; +using System.Configuration; +using System.Web; +using System.Web.Security; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.Web.UI.WebControls.WebParts; +using System.Web.UI.HtmlControls; +using Castle.MonoRail.Framework.Helpers; +using Cygnet.Web.Helpers; +using Cygnet.Web.Controllers; +using NHibernate; +using NHibernate.Expression; +using Castle.MonoRail.Framework; +using SRU.Hospitality.Entities; +using SRU.Hospitality.Helpers; +using ADL.Exceptions; +using Iesi.Collections.Generic; + +namespace <xsl:value-of select="$controllerns"/> { + + /// <summary> + /// Automatically generated partial controller class following 'thin controller' + /// strategy, for entity <xsl:value-of select="@name"/>. Note that part of this + /// class may be defined in a separate file called + /// <xsl:value-of select="@name"/>Controller.manual.cs, q.v. + /// + /// DO NOT EDIT THIS FILE! + /// </summary> + [ + Helper(typeof(ShuffleWidgetHelper), "ShuffleWidgetHelper"), + ] + public partial class <xsl:value-of select="@name"/>Controller : BaseController { + + /// <summary> + /// Store the record represented by the parameters passed in an HTTP service + /// Without Id -> it's new, I create a new persistent object; + /// With Id -> it's existing, I update the existing persistent object. + /// NOTE: Should only be called from a handler for method 'POST', never 'GET'. + /// </summary> + private void Store() + { + ISession hibernator = + NHibernateHelper.GetCurrentSession( Session[ NHibernateHelper.USERTOKEN], + Session[NHibernateHelper.PASSTOKEN]); + List<string> messages = new List<string>(); + + <xsl:value-of select="$entityns"/>.<xsl:value-of select="@name"/> record; + + <xsl:apply-templates select="property"/> + + string id = Form["<xsl:value-of select="concat( 'instance.', $key)"/>"]; + + if ( String.IsNullOrEmpty( id)) + { + /* it's new, create persistent object */ + record = new <xsl:value-of select="$entityns"/>.<xsl:value-of select="@name"/>(<xsl:for-each select="property[@distinct='system']">Form[<xsl:value-of select="concat( 'instance.', @name)"/>]<xsl:choose> + <xsl:when test="position() = last()"/> + <xsl:otherwise>, </xsl:otherwise> + </xsl:choose> + </xsl:for-each>); + + /* perform any domain knowledge behaviour on the new record + * after instantiation */ + record.AfterCreationHook( hibernator); + messages.Add( "New <xsl:value-of select="@name"/> record created"); + } + else + { + /* it's existing, retrieve it */ + record = + hibernator.CreateCriteria(typeof(<xsl:value-of select="@name"/>)) + .Add(Expression.Eq("<xsl:value-of select="$key"/>", Int32.Parse(id))) + .UniqueResult<<xsl:value-of select="$entityns"/>.<xsl:value-of select="@name"/>>(); + } + + if ( record != null) + { + try + { + /* actually update the record */ + BindObjectInstance( record, ParamStore.Form, "instance"); + + <xsl:for-each select="property[@type='entity']"> + /* for properties of type 'entity', it should not be necessary to do anything + * special - BindObjectInstance /should/ do it all. Unfortunately it sometimes + * doesn't, and I haven't yet characterised why not. TODO: Fix this! */ + record.<xsl:value-of select="@name"/> = + hibernator.CreateCriteria(typeof(<xsl:value-of select="@entity"/>)) + .Add(Expression.Eq("<xsl:call-template name="primary-key"> + <xsl:with-param name="entityname" select="@entity"/> + </xsl:call-template>", Int32.Parse(Form["<xsl:value-of select="concat( 'instance.', @name)"/>"]))) + .UniqueResult<<xsl:value-of select="$entityns"/>.<xsl:value-of select="@entity"/>>(); + </xsl:for-each> + + <xsl:for-each select="property[@type='link']"> + /* to update a link table which has no other data than the near and far keys, it is + * sufficient to smash the existing values and create new ones. It's also a lot easier! */ + + string[] <xsl:value-of select="concat(@name, 'Values')"/> = Form.GetValues( "<xsl:value-of select="concat( 'instance.', @name)"/>"); + + if ( <xsl:value-of select="concat(@name, 'Values')"/> != null) + { + /* update the linking table for my <xsl:value-of select="@name"/>; first smash the old values */ + if ( <xsl:value-of select="concat( 'record.', @name)"/> != null) + { + <xsl:value-of select="concat( 'record.', @name)"/>.Clear(); + } + else + { + <xsl:value-of select="concat( 'record.', @name)"/> = new HashedSet<<xsl:value-of select="@entity"/>>(); + } + + /* then reinstate the values from the indexes passed */ + foreach ( string index in <xsl:value-of select="concat(@name, 'Values')"/>) + { + <!-- todo: won't work for entities having natural keys --> + <xsl:value-of select="concat( 'record.', @name)"/>.Add( + hibernator.CreateCriteria(typeof(<xsl:value-of select="@entity"/>)) + .Add(Expression.Eq("<xsl:value-of select="@entity"/>Id", Int32.Parse(index))) + .UniqueResult<<xsl:value-of select="$entityns"/>.<xsl:value-of select="@entity"/>>()); + } + } + </xsl:for-each> + + <xsl:for-each select="property[@type='list']"> + /* with a list we cannot just smash the old values! Instead we need to check + * each one and exclude it if no longer required */ + if ( Form.GetValues( "<xsl:value-of select="concat( 'instance.', @name)"/>") != null) + { + string[] <xsl:value-of select="concat(@name, 'Values')"/> = Form.GetValues( "<xsl:value-of select="concat( 'instance.', @name)"/>"); + + /* updating <xsl:value-of select="@name"/> child records; first remove any not on the submitted list */ + foreach ( <xsl:value-of select="@entity"/> item in record.<xsl:value-of select="@name"/>) + { + String itemId = item.Key.ToString(); + bool found = false; + + foreach ( string index in <xsl:value-of select="concat(@name, 'Values')"/>) + { + <!-- TODO: this could definitely be made more efficient --> + if ( index.Equals( itemId)) + { + found = true; + } + } + + if ( ! found) + { + record.<xsl:value-of select="@name"/>.Remove( item); + } + } + + /* then add any on the included list which are not already members */ + foreach ( string index in <xsl:value-of select="concat(@name, 'Values')"/>) + { + <xsl:value-of select="@entity"/> item = + hibernator.CreateCriteria(typeof(<xsl:value-of select="@entity"/>)) + .Add(Expression.Eq("<xsl:value-of select="@entity"/>Id", Int32.Parse(index))) + .UniqueResult<<xsl:value-of select="$entityns"/>.<xsl:value-of select="@entity"/>>(); + + if ( ! record.<xsl:value-of select="@name"/>.Contains( item)) + { + record.<xsl:value-of select="@name"/>.Add( item); + } + } + } + </xsl:for-each> + + /* perform any domain knowledge behaviour on the record prior to updating */ + record.BeforeUpdateHook( hibernator); + + /* write the record to the database, in order to guarantee we have a valid key */ + hibernator.Save(record); + hibernator.Flush(); + + /* perform any domain knowledge behaviour on the record after updating */ + record.AfterUpdateHook( hibernator); + + messages.Add( "Record saved successfully"); + } + catch ( DataSuitabilityException dse) + { + AddError( dse.Message); + } + catch ( ApplicationException axe) + { + AddError( axe.Message); + } + + PropertyBag["messages"] = messages; + PropertyBag["username"] = Session[ NHibernateHelper.USERTOKEN]; + PropertyBag["instance"] = record; + + <xsl:call-template name="menus"> + <xsl:with-param name="entity" select="."/> + </xsl:call-template> + RenderViewWithFailover("<xsl:value-of select="concat( form[position()=1]/@name, '.vm')"/>", "<xsl:value-of select="concat( form[position()=1]/@name, '.auto.vm')"/>"); + } + else + { + throw new Exception( String.Format( "No record of type <xsl:value-of select="@name"/> with key value {0} found", id)); + } + } + + /// <summary> + /// Actually delete the selected record + /// </summary> + [AccessibleThrough(Verb.Get)] + public void Delete() + { + ISession hibernator = + NHibernateHelper.GetCurrentSession( Session[ NHibernateHelper.USERTOKEN], + Session[NHibernateHelper.PASSTOKEN]); + string id = Params["<xsl:value-of select="concat( 'instance.', $key)"/>"]; + string reallydelete = Params["reallydelete"]; + + if ( "true".Equals( reallydelete)) + { + <xsl:value-of select="@name"/> record = + hibernator.CreateCriteria(typeof(<xsl:value-of select="@name"/>)) + .Add(Expression.Eq("<xsl:value-of select="$key"/>", Int32.Parse(id))) + .UniqueResult<<xsl:value-of select="$entityns"/>.<xsl:value-of select="@name"/>>(); + + if ( record != null) + { + record.BeforeDeleteHook( hibernator); + + hibernator.Delete( + hibernator.CreateCriteria(typeof(<xsl:value-of select="@name"/>)) + .Add(Expression.Eq("<xsl:value-of select="$key"/>", Int32.Parse(id))) + .UniqueResult<<xsl:value-of select="$entityns"/>.<xsl:value-of select="@name"/>>()); + + hibernator.Flush(); + } + else + { + throw new ApplicationException( "No such record?"); + } + } + <xsl:choose> + <xsl:when test="list"> + InternalShowList(); + </xsl:when> + <xsl:otherwise> + Redirect( FormsAuthentication.DefaultUrl); + </xsl:otherwise> + </xsl:choose> + } + + <xsl:apply-templates select="form"/> + + <xsl:if test="list"> + <xsl:variable name="listname" select="list[position()=1]/@name"/> + <xsl:apply-templates select="list"/> + /// <summary> + /// list all instances of this entity to allow the user to select one for editing + /// this method invokes the default list view - which is probably what you want unless + /// you've a special reason for doing something different + /// </summary> + public void InternalShowList() + { + InternalShowList( "<xsl:value-of select="$listname"/>"); + } + + /// <summary> + /// list all instances of this entity to allow the user to select one for editing + /// </summary> + /// <param name="view">The name of the list view to show</param> + public void InternalShowList( String view) + { + ISession hibernator = + NHibernateHelper.GetCurrentSession( Session[ NHibernateHelper.USERTOKEN], + Session[NHibernateHelper.PASSTOKEN]); + IList<<xsl:value-of select="@name"/>> instances = + hibernator.CreateCriteria(typeof(<xsl:value-of select="@name"/>))<xsl:for-each select="property[@distinct='user']"> + <xsl:value-of select="concat( '.AddOrder( new Order( "', @name, '", true))')"/> + </xsl:for-each>.List<<xsl:value-of select="@name"/>>(); + + PropertyBag["username"] = Session[ NHibernateHelper.USERTOKEN]; + PropertyBag["instances"] = + PaginationHelper.CreatePagination( this, instances, 25); + + RenderViewWithFailover(view + ".vm", view + ".auto.vm"); + } + </xsl:if> + } +} + </xsl:template> + + <xsl:template match="property[@required='true']"> + if ( Form[ "<xsl:value-of select="concat( 'instance.', @name)"/>" ] == null) + { + AddError( <xsl:choose> + <xsl:when test="ifmissing[@locale=$locale]"> + <xsl:apply-templates select="ifmissing[@locale=$locale]"/> + </xsl:when> + <xsl:otherwise>"You must supply a value for <xsl:value-of select="@name"/>"</xsl:otherwise> + </xsl:choose>); + } + + </xsl:template> + + <!-- suppress properties otherwise --> + <xsl:template match="property"/> + + <xsl:template match="ifmissing"> + "<xsl:value-of select="normalize-space(.)"/>" + </xsl:template> + + <xsl:template match="form"> + <xsl:variable name="key"> + <xsl:choose> + <xsl:when test="../@natural-key"> + <xsl:value-of select="../@natural-key"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="concat( ../@name, 'Id')"/> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + /// <summary> + /// Handle the submission of the form named <xsl:value-of select="@name"/> + /// </summary> + [AccessibleThrough(Verb.Post)] + public void <xsl:value-of select="concat( @name, 'SubmitHandler')"/>( ) + { + string command = Form[ "command"]; + + if ( command == null) + { + throw new Exception( "No command?"); + } + else + <xsl:for-each select=".//verb"> + if ( command.Equals( "<xsl:value-of select="@verb"/>")) + { + /* NOTE: You must write an implementation of this verb in a + manually maintained partial class file for this class */ + <xsl:value-of select="@verb"/>(); + } + else + </xsl:for-each> + if ( command.Equals( "delete")) + { + ISession hibernator = + NHibernateHelper.GetCurrentSession( Session[ NHibernateHelper.USERTOKEN], + Session[NHibernateHelper.PASSTOKEN]); + string id = Form["<xsl:value-of select="concat( 'instance.', $key)"/>"]; + + PropertyBag["username"] = Session[ NHibernateHelper.USERTOKEN]; + PropertyBag["instance"] = + hibernator.CreateCriteria(typeof(<xsl:value-of select="../@name"/>)) + .Add(Expression.Eq("<xsl:value-of select="$key"/>", Int32.Parse(id))) + .UniqueResult<<xsl:value-of select="$entityns"/>.<xsl:value-of select="../@name"/>>(); + + RenderViewWithFailover( "maybedelete.vm", "maybedelete.auto.vm"); + } + else if ( command.Equals( "store")) + { + Store(); + } + else + { + throw new Exception( String.Format("Unrecognised command '{0}'", command)); + } + } + + /// <summary> + /// Show the form named <xsl:value-of select="@name"/>, with no content + /// </summary> + [AccessibleThrough(Verb.Get)] + public void <xsl:value-of select="@name"/>( ) + { + ISession hibernator = + NHibernateHelper.GetCurrentSession( Session[ NHibernateHelper.USERTOKEN], + Session[NHibernateHelper.PASSTOKEN]); + <xsl:call-template name="menus"> + <xsl:with-param name="entity" select=".."/> + </xsl:call-template> + + PropertyBag["username"] = Session[ NHibernateHelper.USERTOKEN]; + RenderViewWithFailover("<xsl:value-of select="concat( @name, '.vm')"/>", "<xsl:value-of select="concat( @name, '.auto.vm')"/>"); + } + + /// <summary> + /// Show the form named <xsl:value-of select="@name"/>, containing the indicated record + /// </summary> + /// <param name="<xsl:value-of select="concat( ../@name, 'Id')"/>">the key value of the record to show</param> + [AccessibleThrough(Verb.Get)] + public void <xsl:value-of select="@name"/>( Int32 <xsl:value-of select="concat( ../@name, 'Id')"/>) + { + ISession hibernator = + NHibernateHelper.GetCurrentSession( Session[ NHibernateHelper.USERTOKEN], + Session[NHibernateHelper.PASSTOKEN]); + <xsl:value-of select="$entityns"/>.<xsl:value-of select="../@name"/> record = + hibernator.CreateCriteria(typeof(<xsl:value-of select="../@name"/>)) + .Add(Expression.Eq("<xsl:value-of select="concat( ../@name, 'Id')"/>", <xsl:value-of select="../@name"/>Id)) + .UniqueResult<<xsl:value-of select="$entityns"/>.<xsl:value-of select="../@name"/>>(); + + PropertyBag["username"] = Session[ NHibernateHelper.USERTOKEN]; + PropertyBag["instance"] = record; + + <xsl:call-template name="menus"> + <xsl:with-param name="entity" select=".."/> + </xsl:call-template> + RenderViewWithFailover("<xsl:value-of select="concat( @name, '.vm')"/>", "<xsl:value-of select="concat( @name, '.auto.vm')"/>"); + } + + </xsl:template> + + <xsl:template match="list"> + /// <summary> + /// list all instances of this entity to allow the user to select one + /// this method invokes the named view. + /// </summary> + public void <xsl:value-of select="@name"/>() + { + InternalShowList( "<xsl:value-of select="@name"/>"); + } + + </xsl:template> + + <xsl:template name="menus"> + <xsl:param name="entity"/> + <xsl:for-each select="$entity/property[@type='entity']"> + /* produce a list of <xsl:value-of select="@entity"/> to populate the menu for <xsl:value-of select="@name"/> */ + <xsl:call-template name="menu"> + <xsl:with-param name="property" select="."/> + </xsl:call-template> + + </xsl:for-each> + <xsl:for-each select="$entity/property[@type='link']"> + /* produce a list of <xsl:value-of select="@entity"/> to populate the LHS of the shuffle for <xsl:value-of select="@name"/> */ + <xsl:call-template name="menu"> + <xsl:with-param name="property" select="."/> + </xsl:call-template> + </xsl:for-each> + <xsl:for-each select="$entity/property[@type='list']"> + /* produce a list of <xsl:value-of select="@entity"/> to populate the multi-select for <xsl:value-of select="@name"/> */ + <xsl:call-template name="menu"> + <xsl:with-param name="property" select="."/> + </xsl:call-template> + </xsl:for-each> + + </xsl:template> + + <xsl:template name="menu"> + <xsl:param name="property"/> + <xsl:variable name="ename" select="$property/@entity"/> + <xsl:variable name="entity" select="//entity[@name=$ename]"/> + PropertyBag["<xsl:value-of select="concat('all_', $property/@name)"/>"] = + hibernator.CreateCriteria(typeof(<xsl:value-of select="$property/@entity"/>))<xsl:for-each select="$entity/property[@distinct='user']"> + <xsl:value-of select="concat('.AddOrder( new Order( "', @name, '", true))')"/> + </xsl:for-each>.List<<xsl:value-of select="$property/@entity"/>>(); + </xsl:template> + + <xsl:template name="primary-key"> + <!-- return the name of the primary key of the entity with this name --> + <xsl:param name="entityname"/> + <xsl:choose> + <xsl:when test="//entity[@name=$entityname]/@natural-key"> + <xsl:value-of select="//entity[@name=$entityname]/@natural-key"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="concat( $entityname, 'Id')" /> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + </xsl:stylesheet> \ No newline at end of file diff --git a/ADL.NET/Trans/adl2entityclass.xsl b/ADL.NET/Trans/adl2entityclass.xsl new file mode 100755 index 0000000..cd09d89 --- /dev/null +++ b/ADL.NET/Trans/adl2entityclass.xsl @@ -0,0 +1,378 @@ +<?xml version="1.0" encoding="UTF-8" ?> + <!-- + C1873 SRU Hospitality + adl2entityclass.xsl + + (c) 2007 Cygnet Solutions Ltd + + Transform ADL into entity classes + + $Author: af $ + $Revision: 1.1 $ + $Date: 2008-01-09 15:01:45 $ + --> + + <!-- WARNING WARNING WARNING: Do NOT reformat this file! + Whitespace (or lack of it) is significant! --> +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + <xsl:output encoding="UTF-8" method="text"/> + + <!-- The locale for which these entities are generated + TODO: Entities should NOT be locale specific. Instead, the + entity should generate messages based on the + client's locale. However, there may still need to be a concept of a + 'default locale', for when we don't have messages which suit the + client's locale --> + <xsl:param name="locale" select="en-UK"/> + + <!-- The C# namespace within which I shall generate controllers --> + <xsl:param name="controllerns" select="Unset"/> + <!-- The C# namespace within which I shall generate entities --> + <xsl:param name="entityns" select="Unset"/> + + <xsl:template match="application"> + <xsl:apply-templates select="entity"/> + </xsl:template> + + <xsl:template match="application"> + <xsl:apply-templates select="entity"/> + </xsl:template> + + <xsl:template match="entity"> + <!-- what's all this about? the objective is to get the revision number of the + transform into the output, /without/ getting that revision number overwritten + with the revision number of the generated file if the generated file is + stored to CVS --> + + <xsl:variable name="transform-rev1" + select="substring( '$Revision: 1.1 $', 11)"/> + <xsl:variable name="transform-revision" + select="substring( $transform-rev1, 0, string-length( $transform-rev1) - 1)"/> + + /* ---- [ cut here: next file '<xsl:value-of select="@name"/>.auto.cs'] ---------------- */ + + //------------------------------------------------------------- + // + // Application Description Framework + // <xsl:value-of select="@name"/>.auto.cs + // + // (c)2007 Cygnet Solutions Ltd + // + // Automatically generated from application description using + // adl2entityclass.xsl version <xsl:value-of select="$transform-revision"/> + // + // This file is automatically generated; DO NOT EDIT IT. + // + //------------------------------------------------------------- + namespace <xsl:value-of select="$entityns"/> + { + using System; + using System.Configuration; + using System.Collections; + using System.Collections.Generic; + using System.Text; + using System.Text.RegularExpressions; + using ADL.Exceptions; + using Iesi.Collections.Generic; + + /// <summary> + /// Automatically generated from description of entity <xsl:value-of select="@name"/> + /// using adl2entityclass.xsl. Note that manually maintained parts of this + /// class may be defined in a separate file called <xsl:value-of select="@name"/>.cs, q.v. + /// + /// DO NOT EDIT THIS FILE! + /// </summary> + public partial class <xsl:value-of select="@name"/> : Entity + { + /// <summary> + /// Auto-generated no-args constructor; does nothing (but probably should + /// ensure ID slot is initialised correctly) + /// </summary> + public <xsl:value-of select="@name"/>() : base(){ + <xsl:call-template name="initialise-lists"/> + } + + /// <summary> + /// Auto-generated one-arg constructor; initialises Id slot and also all + /// one-to-many slots + /// </summary> + public <xsl:value-of select="@name"/>( int key) + { + <xsl:call-template name="initialise-lists"/> + + <xsl:choose> + <xsl:when test="@natural-key"> + /* natural primary key exists - not initialising abstract key */ + </xsl:when> + <xsl:otherwise> + _<xsl:value-of select="@name"/>Id = key; + </xsl:otherwise> + </xsl:choose> + } + + <xsl:choose> + <xsl:when test="@natural-key"> + /* natural primary key exists - not generating abstract key */ + </xsl:when> + <xsl:otherwise> + /// <summary> + /// Auto-generated iv/property for Id slot + /// </summary> + private int _<xsl:value-of select="@name"/>Id = -1; + + public virtual int <xsl:value-of select="@name"/>Id + { + get { return _<xsl:value-of select="@name"/>Id; } + set { _<xsl:value-of select="@name"/>Id = value; } + } + + /// <summary> + /// Auto-generated overridden property for the Key slot, maps onto + /// _<xsl:value-of select="@name"/>Id + /// </summary> + public override int Key + { + get { return _<xsl:value-of select="@name"/>Id; } + } + </xsl:otherwise> + </xsl:choose> + + /// <summary> + /// A user readable distinct identifying string + /// </summary> + public override string UserIdentifier + { + get { + StringBuilder result = new StringBuilder(); + <xsl:choose> + <xsl:when test="property[@distinct='user']"> + <xsl:for-each select="property[@distinct='user']"> + <xsl:choose> + <xsl:when test="@type='entity'"> + <!-- TODO: this is dangerous and could potentially give rise to + infinite loops; find a way of stopping it running away! --> + result.Append( <xsl:value-of select="concat( @name, '.UserIdentifier')"/>); + </xsl:when> + <xsl:otherwise> + result.Append(<xsl:value-of select="concat( '_', @name)"/>); + </xsl:otherwise> + </xsl:choose> + <xsl:choose> + <xsl:when test="position() = last()"/> + <xsl:otherwise> + result.Append( ", "); + </xsl:otherwise> + </xsl:choose> + </xsl:for-each> + </xsl:when> + <xsl:otherwise> + result.AppendFormat( "<xsl:value-of select="@name"/>#{0}[", _<xsl:value-of select="@name"/>Id); + </xsl:otherwise> + </xsl:choose> + + return result.ToString(); + } + } + + <xsl:apply-templates select="property"/> + } + } + + + </xsl:template> + + <xsl:template match="property[@concrete='false']"> + <!-- generate nothing for non-concrete properties --> + </xsl:template> + + <xsl:template match="property"> + // auto generating iv/property pair for slot with name <xsl:value-of select="@name"/> + <xsl:apply-templates select="help"/> + + <xsl:variable name="defined-type"> + <xsl:choose> + <xsl:when test="@type='defined'"> + <xsl:variable name="definition"> + <xsl:value-of select="@definition"/> + </xsl:variable> + <xsl:value-of select="/application/definition[@name=$definition]/@type"/> + </xsl:when> + </xsl:choose> + </xsl:variable> + + <xsl:variable name="type"> + <xsl:choose> + <xsl:when test="@type = 'link'"> + ICollection<<xsl:value-of select="@entity"/>> + </xsl:when> + <xsl:when test="@type = 'list'"> + ICollection<<xsl:value-of select="@entity"/>> + </xsl:when> + <xsl:when test="@type = 'date'">DateTime</xsl:when> + <xsl:when test="@type = 'time'">DateTime</xsl:when> + <xsl:when test="@type = 'string'">String</xsl:when> + <xsl:when test="@type = 'text'">String</xsl:when> + <xsl:when test="@type = 'boolean'">bool</xsl:when> + <xsl:when test="@type = 'timestamp'">TimeStamp</xsl:when> + <xsl:when test="@type = 'integer'">int</xsl:when> + <xsl:when test="@type = 'real'">double</xsl:when> + <xsl:when test="@type = 'money'">Decimal</xsl:when> + <xsl:when test="@type = 'entity'"> + <xsl:value-of select="@entity"/> + </xsl:when> + <xsl:when test="@type='defined'"> + <!-- MUCH more complicated... find the right definition, then map its type onto a C# type --> + <xsl:choose> + <!-- DefinableDataTypes are string|integer|real|money|date|time|timestamp --> + <xsl:when test="$defined-type = 'string'">String</xsl:when> + <xsl:when test="$defined-type = 'integer'">int</xsl:when> + <xsl:when test="$defined-type = 'real'">double</xsl:when> + <xsl:when test="$defined-type = 'money'">Decimal</xsl:when> + <xsl:when test="$defined-type = 'date'">DateTime</xsl:when> + <xsl:when test="$defined-type = 'time'">DateTime</xsl:when> + <xsl:when test="$defined-type = 'timestamp'">TimeStamp</xsl:when> + </xsl:choose> + </xsl:when> + <xsl:otherwise>[unknown?]</xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:variable name="nullable-decoration"> + <xsl:choose> + <xsl:when test="@required='true'"/> + <!-- when required is 'true' null is not permitted anyway; otherwise... --> + <xsl:when test="$type = 'int'">?</xsl:when> + <xsl:when test="@type = 'boolean'">?</xsl:when> + <xsl:when test="$type = 'double'">?</xsl:when> + <xsl:when test="$type = 'Double'">?</xsl:when> + <xsl:when test="$type = 'DateTime'">?</xsl:when> + <xsl:when test="$type = 'TimeStamp'">?</xsl:when> + <xsl:otherwise/> + </xsl:choose> + </xsl:variable> + <xsl:variable name="initialiser"> + <xsl:choose> + <xsl:when test="@default"> + <xsl:choose> + <xsl:when test="$type = 'String'"> = "<xsl:value-of select="@default"/>"</xsl:when> + <xsl:otherwise> = <xsl:value-of select="@default"/></xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:when test="$nullable-decoration = '?'"> = null</xsl:when> + <xsl:when test="@type = 'boolean'"> = false</xsl:when> + <xsl:when test="$type = 'int'"> = 0</xsl:when> + <xsl:when test="$type = 'double'"> = 0.0</xsl:when> + <xsl:when test="$type = 'Decimal'"> = 0.0M</xsl:when> + <xsl:when test="$type='String'"> = null</xsl:when> + </xsl:choose> + </xsl:variable> + + <xsl:variable name="validationpattern"> + <xsl:choose> + <xsl:when test="@type='defined'"> + <xsl:variable name="definition"> + <xsl:value-of select="@definition"/> + </xsl:variable> + <xsl:value-of select="/application/definition[@name=$definition]/@pattern"/> + </xsl:when> + </xsl:choose> + </xsl:variable> + <xsl:if test="string-length( $validationpattern) > 0"> + private Regex <xsl:value-of select="@name"/>Validator = new Regex( "<xsl:value-of select="$validationpattern"/>"); + </xsl:if> + + private <xsl:value-of select="$type"/><xsl:value-of select="$nullable-decoration"/> _<xsl:value-of select="@name"/> <xsl:value-of select="$initialiser"/>; + + public virtual <xsl:value-of select="$type"/><xsl:value-of select="$nullable-decoration"/><xsl:text> </xsl:text> <xsl:value-of select="@name"/> + { + get { return _<xsl:value-of select="@name"/>; } + set { + <xsl:if test="@required='true'"> + if ( value == null) + { + throw new DataRequiredException( <xsl:choose> + <xsl:when test="ifmissing[@locale=$locale]"> + <xsl:apply-templates select="ifmissing"/> + </xsl:when> + <xsl:otherwise> + "The value for <xsl:value-of select="@name"/> may not be set to null" + </xsl:otherwise> + </xsl:choose> + ); + } + </xsl:if> + <xsl:if test="@type='defined'"> + <xsl:variable name="definition"> + <xsl:value-of select="@definition"/> + </xsl:variable> + <xsl:variable name="maximum"> + <xsl:value-of select="/application/definition[@name=$definition]/@maximum"/> + </xsl:variable> + <xsl:variable name="minimum"> + <xsl:value-of select="/application/definition[@name=$definition]/@minimum"/> + </xsl:variable> + <xsl:if test="string-length( $maximum) > 0"> + if ( value > <xsl:value-of select="$maximum"/>) + { + throw new DataRangeException( "The maximum permitted value for <xsl:value-of select="@name"/> is <xsl:value-of select="$maximum"/>"); + } + </xsl:if> + <xsl:if test="string-length( $minimum) > 0"> + if ( value < <xsl:value-of select="$minimum"/>) + { + throw new DataRangeException( "The minimum permitted value for <xsl:value-of select="@name"/> is <xsl:value-of select="$minimum"/>"); + } + </xsl:if> + <xsl:if test="string-length( $validationpattern) > 0"> + if ( value != null && ! <xsl:value-of select="@name"/>Validator.IsMatch( value)) + { + throw new DataFormatException( string.Format( "The value supplied ({0}) does not match the format required by <xsl:value-of select="@name"/>", value)); + } + </xsl:if> + </xsl:if> + <xsl:if test="@size and $type='String'"> + if ( value != null && value.Length > <xsl:value-of select="@size"/>) + { + value = value.Substring( 0, <xsl:value-of select="@size"/>); + } + </xsl:if> + _<xsl:value-of select="@name"/> = value; + } + } + + </xsl:template> + + <xsl:template match="help"> + <xsl:if test="@locale=$locale"> + <!-- might conceivably be more than one line --> + <xsl:text> + /* </xsl:text><xsl:apply-templates/> */ + </xsl:if> + </xsl:template> + + <xsl:template match="ifmissing"> + <xsl:if test="@locale=$locale"> + "<xsl:value-of select="normalize-space(.)"/>" + </xsl:if> + </xsl:template> + + <xsl:template name="initialise-lists"> + <!-- initialise all cocrete lists and links --> + <xsl:for-each select="property[@type='list']"> + <xsl:choose> + <xsl:when test="@concrete='false'"/> + <xsl:otherwise> + _<xsl:value-of select="@name"/> = new HashedSet<<xsl:value-of select="@entity"/>>(); + </xsl:otherwise> + </xsl:choose> + </xsl:for-each> + <xsl:for-each select="property[@type='link']"> + <xsl:choose> + <xsl:when test="@concrete='false'"/> + <xsl:otherwise> + _<xsl:value-of select="@name"/> = new HashedSet<<xsl:value-of select="@entity"/>>(); + </xsl:otherwise> + </xsl:choose> + </xsl:for-each> + </xsl:template> + +</xsl:stylesheet> \ No newline at end of file diff --git a/ADL.NET/Trans/adl2hibernate.xsl b/ADL.NET/Trans/adl2hibernate.xsl new file mode 100755 index 0000000..18e2a57 --- /dev/null +++ b/ADL.NET/Trans/adl2hibernate.xsl @@ -0,0 +1,247 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns="urn:nhibernate-mapping-2.2"> + <!-- + Application Description Framework + adl2hibernate.xsl + + (c) 2007 Cygnet Solutions Ltd + + Transform ADL to Hibernate + + $Author: af $ + $Revision: 1.1 $ + --> + + <xsl:output indent="no" method="xml" encoding="utf-8"/> + <!-- NOTE! indent="no" because hibernate falls over if there is whitespace inside + a 'key' or 'one-to-many' element, and the printer used by the NAnt 'style' task + does not tag-minimize on output. If you change this the build will break, you + have been warned! --> + + <xsl:variable name="namespace">SRU.Hospitality.Entities</xsl:variable> + <xsl:variable name="assembly">SRU.Hospitality.DataModel</xsl:variable> + + <xsl:template match="application"> + <hibernate-mapping> + <xsl:attribute name="namespace"> + <xsl:value-of select="$namespace"/> + </xsl:attribute> + <xsl:attribute name="assembly"> + <xsl:value-of select="$assembly"/> + </xsl:attribute> + <xsl:comment> + *************************************************************************** + * + * C1873: C1873-SUS-Hospitality.auto.hbm.xml + * + * ©2007 Cygnet Solutions Ltd + * + * THIS FILE IS AUTOMATICALLY GENERATED AND SHOULD NOT + * BE MANUALLY EDITED. + * + * Generated using adl2hibernate-mapping.xsl revision <xsl:value-of select="substring('$Revision: 1.1 $', 12)"/> + * + *************************************************************************** + </xsl:comment> + <xsl:apply-templates select="entity"/> + </hibernate-mapping> + + </xsl:template> + + <xsl:template match="entity"> + <class> + <xsl:attribute name="name"> + <xsl:value-of select="@name"/> + </xsl:attribute> + <xsl:attribute name="table"> + <xsl:value-of select="@name"/> + </xsl:attribute> + <id type="Int32"> + <!-- ADL does not encode the primary key explicitly; instead it is + implicit and its name is always the name of the entity followed by + 'Id' --> + <xsl:attribute name="name"> + <xsl:value-of select="normalize-space( concat( @name, 'Id'))"/> + </xsl:attribute> + <generator class="native"/> + </id> + <xsl:apply-templates select="property"/> + </class> + </xsl:template> + + <xsl:template match="property[@concrete='false']"> + <!-- properties which are not concrete are by definition not + stored in the database --> + </xsl:template> + + <xsl:template match="property[@type='entity']"> + <!-- a property of type entity translates to a Hibernate many-to-one --> + <many-to-one> + <xsl:attribute name="name"> + <xsl:value-of select="@name"/> + </xsl:attribute> + <xsl:attribute name="class"> + <xsl:value-of select="@entity"/> + </xsl:attribute> + </many-to-one> + </xsl:template> + + <xsl:template match="property[@type='list']"> + <xsl:variable name="farent" select="@entity"/> + <xsl:variable name="nearent" select="ancestor::entity/@name"/> + <xsl:variable name="farkey"> + <xsl:choose> + <xsl:when test="@farkey"> + <xsl:value-of select="@farkey"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="ancestor::entity/@name"/> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + <set> + <xsl:attribute name="name"> + <xsl:value-of select="@name"/> + </xsl:attribute> + <xsl:attribute name="inverse"> + <!-- true if the other end of the link is described in the ADL (which it normally will be) --> + <xsl:choose> + <xsl:when test="//entity[@name=$farent]/property[@name=$farkey and @entity=$nearent]">true</xsl:when> + <xsl:otherwise>false</xsl:otherwise> + </xsl:choose> + </xsl:attribute> + <!-- careful with reformatting here: + 'The element cannot contain white space. Content model is empty.' --> + <key><xsl:attribute name="column"> + <!-- this is the name of the farside foreign key field which points to me --> + <xsl:value-of select="$farkey"/> + </xsl:attribute></key> + <one-to-many><xsl:attribute name="class"> + <xsl:value-of select="@entity"/> + </xsl:attribute></one-to-many> + </set> + </xsl:template> + + <xsl:template match="property[@type='link']"> + <!-- a property of type 'link' maps on to a Hibernate set --> + <xsl:variable name="comparison"> + <xsl:call-template name="stringcompare"> + <xsl:with-param name="node1" select="../@name"/> + <xsl:with-param name="node2" select="@entity"/> + </xsl:call-template> + </xsl:variable> + <xsl:variable name="tablename"> + <xsl:choose> + <xsl:when test="$comparison =-1"> + <xsl:value-of select="concat( 'ln_', ../@name, '_', @entity)"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="concat( 'ln_', @entity, '_', ../@name)"/> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + + <set> + <xsl:attribute name="name"> + <xsl:value-of select="@name"/> + </xsl:attribute> + <xsl:attribute name="table"> + <xsl:value-of select="$tablename"/> + </xsl:attribute> + <key> + <xsl:attribute name="column"> + <xsl:value-of select="concat( ../@name, 'Id')"/> + </xsl:attribute> + </key> + <many-to-many> + <xsl:attribute name="column"> + <xsl:choose> + <xsl:when test="../@name = @entity"> + <xsl:value-of select="concat( @entity, '_1Id')"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="concat( @entity, 'Id')"/> + </xsl:otherwise> + </xsl:choose> + </xsl:attribute> + <xsl:attribute name="class"> + <xsl:value-of select="@entity"/> + </xsl:attribute> + </many-to-many> + </set> + </xsl:template> + + <xsl:template match="property"> + <!-- tricky, this, because we're translating between ADL properties and + Hibernate properties, which are (slightly) different. There's potential + for confusion --> + <property> + <xsl:attribute name="name"> + <xsl:value-of select="@name"/> + </xsl:attribute> + <xsl:attribute name="type"> + <xsl:variable name="type"> + <xsl:choose> + <xsl:when test="@type = 'defined'"> + <xsl:variable name="definition"> + <xsl:value-of select="@definition"/> + </xsl:variable> + <xsl:value-of select="/application/definition[@name=$definition]/@type"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="@type"/> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:choose> + <xsl:when test="$type = 'date'">DateTime</xsl:when> + <xsl:when test="$type = 'time'">DateTime</xsl:when> + <xsl:when test="$type = 'string'">String</xsl:when> + <xsl:when test="$type = 'text'">String</xsl:when> + <xsl:when test="$type = 'boolean'">Boolean</xsl:when> + <xsl:when test="$type = 'timestamp'">TimeStamp</xsl:when> + <xsl:when test="$type = 'integer'">Int32</xsl:when> + <xsl:when test="$type = 'real'">Double</xsl:when> + <xsl:when test="$type = 'money'">Decimal</xsl:when> + <xsl:otherwise>[unknown?]</xsl:otherwise> + </xsl:choose> + </xsl:attribute> + </property> + </xsl:template> + + <!-- + horrible, horrible hackery. Compare two strings and return + * 0 if they are identical, + * -1 if the first is earlier in the default collating sequence, + * 1 if the first is later. + In XSL 2.0 this could be done using the compare(string, string) function. + TODO: probably should be an include file + --> + <xsl:template name="stringcompare"> + <xsl:param name="node1"/> + <xsl:param name="node2"/> + <xsl:choose> + <xsl:when test="string($node1)=string($node2)"> + <xsl:text>0</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:for-each select="$node1 | $node2"> + <xsl:sort select="."/> + <xsl:if test="position()=1"> + <xsl:choose> + <xsl:when test="string(.) = string($node1)"> + <xsl:text>-1</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>1</xsl:text> + </xsl:otherwise> + </xsl:choose> + </xsl:if> + </xsl:for-each> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + +</xsl:stylesheet> \ No newline at end of file diff --git a/ADL.NET/Trans/adl2mssql.xsl b/ADL.NET/Trans/adl2mssql.xsl new file mode 100755 index 0000000..ed6242c --- /dev/null +++ b/ADL.NET/Trans/adl2mssql.xsl @@ -0,0 +1,471 @@ +<?xml version="1.0"?> +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + <!-- + C1873 SRU Hospitality + adl2mssql.xsl + + (c) 2007 Cygnet Solutions Ltd + + Convert ADL to MS-SQL + + $Author: af $ + $Revision: 1.1 $ + --> + + <xsl:output indent="no" encoding="utf-8" method="text"/> + + <xsl:template match="application"> + ------------------------------------------------------------------------------------------------- + -- + -- Database for application <xsl:value-of select="@name"/> version <xsl:value-of select="@version"/> + -- Generated for MS-SQL 2000+ using adl2mssql.xsl $Revision: 1.1 $ + -- + -- Code generator (c) 2007 Cygnet Solutions Ltd + -- + ------------------------------------------------------------------------------------------------- + + ------------------------------------------------------------------------------------------------- + -- authentication roles + ------------------------------------------------------------------------------------------------- + <xsl:apply-templates select="group"/> + + ------------------------------------------------------------------------------------------------- + -- tables, views and permissions + ------------------------------------------------------------------------------------------------- + <xsl:apply-templates select="entity" mode="table"/> + + <xsl:apply-templates select="entity" mode="view"/> + + ------------------------------------------------------------------------------------------------- + -- referential integrity constraints + ------------------------------------------------------------------------------------------------- + <xsl:for-each select="entity"> + <xsl:variable name="nearside" select="@name"/> + <xsl:for-each select="property[@type='entity']"> + <xsl:call-template name="referentialintegrity"> + <xsl:with-param name="nearside" select="$nearside"/> + </xsl:call-template> + + </xsl:for-each> + </xsl:for-each> + + ------------------------------------------------------------------------------------------------- + -- end of file + ------------------------------------------------------------------------------------------------- + </xsl:template> + + <xsl:template match="group"> + execute sp_addrole @rolename = '<xsl:value-of select="@name"/>' + + GO + </xsl:template> + + + <xsl:template name="referentialintegrity"> + <xsl:param name="nearside"/> + <!-- set up referential integrity constraints for primary tables --> + ALTER TABLE "<xsl:value-of select="$nearside"/>" + ADD FOREIGN KEY ( "<xsl:value-of select="@name"/>") + REFERENCES "<xsl:value-of select="@entity"/>" ON DELETE NO ACTION + + GO + </xsl:template> + + + <xsl:template match="entity" mode="table"> + <xsl:variable name="table" select="@name"/> + + ------------------------------------------------------------------------------------------------- + -- primary table <xsl:value-of select="@name"/> + ------------------------------------------------------------------------------------------------- + CREATE TABLE "<xsl:value-of select="@name"/>" + ( + <xsl:apply-templates select="property[@type!='link']"/> + <xsl:value-of select="@name"/>Id INT IDENTITY( 1, 1) PRIMARY KEY + ) + + GO + + ---- permissions ------------------------------------------------------------------------------ + <xsl:for-each select="permission"> + <xsl:call-template name="permission"> + <xsl:with-param name="table" select="$table"/> + </xsl:call-template> + </xsl:for-each> + + </xsl:template> + + <xsl:template match="entity" mode="view"> + <xsl:variable name="table" select="@name"/> + ------------------------------------------------------------------------------------------------- + -- convenience view VW_DL_<xsl:value-of select="@name"/> for default list + ------------------------------------------------------------------------------------------------- + + CREATE VIEW "VW_DL_<xsl:value-of select="@name"/>" AS + SELECT "<xsl:value-of select="@name"/>"."<xsl:value-of select="@name"/>Id", + <xsl:for-each select="property[@type!='link']"> + <xsl:choose> + <xsl:when test="@type='entity'"> + <xsl:call-template name="distinctfield"> + <xsl:with-param name="table" select="@entity"/> + <xsl:with-param name="alias" select="@name"/> + </xsl:call-template> AS <xsl:value-of select="@name"/></xsl:when> + <xsl:otherwise>"<xsl:value-of select="$table"/>"."<xsl:value-of select="@name"/>"</xsl:otherwise> + </xsl:choose><xsl:choose> + <xsl:when test="position() = last()"></xsl:when> + <xsl:otherwise>, + </xsl:otherwise> + </xsl:choose> + </xsl:for-each> + FROM "<xsl:value-of select="@name"/>" <xsl:for-each + select="property[@type='entity']">, "<xsl:value-of select="@entity"/>" AS "<xsl:value-of select="@name"/>"</xsl:for-each> + <xsl:text> + </xsl:text> + <xsl:for-each select="property[@type='entity']"> + <xsl:choose> + <xsl:when test="position() = 1">WHERE </xsl:when> + <xsl:otherwise>AND </xsl:otherwise> + </xsl:choose>"<xsl:value-of select="$table"/>"."<xsl:value-of + select="@name"/>" = "<xsl:value-of select="@name"/>"."<xsl:value-of select="@entity"/>Id" + </xsl:for-each> + + GO + + ---- permissions ------------------------------------------------------------------------------ + <xsl:for-each select="permission"> + <xsl:call-template name="viewpermission"> + <xsl:with-param name="table" select="$table"/> + </xsl:call-template> + </xsl:for-each> + + <!-- link tables --> + <xsl:for-each select="property[@type='link']"> + <xsl:call-template name="linktable"> + <xsl:with-param name="nearside" select="$table"/> + </xsl:call-template> + </xsl:for-each> + + </xsl:template> + + <xsl:template name="distinctfield"> + <xsl:param name="table"/> + <xsl:param name="alias"/> + <!-- + print the names of the distinguishing fields in this table, + concatenating into a single string. + --> + <xsl:for-each select="/application/entity[@name=$table]"> + <xsl:for-each select="property[@distinct='user' or @distinct='all']"> + <xsl:choose> + <xsl:when test="@type='entity'"> + <xsl:call-template name="distinctfield"> + <xsl:with-param name="table" select="@entity"/> + <xsl:with-param name="alias" select="concat( $alias, '_', @name)"></xsl:with-param> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + "<xsl:value-of select="$alias"/>"."<xsl:value-of + select="@name"/>"<xsl:if test="position() != last()"> + ' ' + </xsl:if> + </xsl:otherwise> + </xsl:choose> + + </xsl:for-each> + </xsl:for-each> + </xsl:template> + + <xsl:template name="permission"> + <xsl:param name="table"/> + <!-- decode the permissions for a table --> + <xsl:choose> + <xsl:when test="@permission='read'">GRANT SELECT ON "<xsl:value-of + select="$table"/>" TO <xsl:value-of select="@group"/> + + GO</xsl:when> + <xsl:when test="@permission='insert'">GRANT INSERT ON "<xsl:value-of + select="$table"/>" TO <xsl:value-of select="@group"/> + + GO</xsl:when> + <xsl:when test="@permission='noedit'">GRANT SELECT, INSERT ON "<xsl:value-of + select="$table"/>" TO <xsl:value-of select="@group"/> + + GO</xsl:when> + <xsl:when test="@permission='edit'">GRANT SELECT, INSERT, UPDATE ON "<xsl:value-of + select="$table"/>" TO <xsl:value-of select="@group"/> + + GO</xsl:when> + <xsl:when test="@permission='all'">GRANT SELECT, INSERT, UPDATE, DELETE ON "<xsl:value-of + select="$table"/>" TO <xsl:value-of select="@group"/> + + GO</xsl:when> + <xsl:otherwise>REVOKE ALL ON "<xsl:value-of + select="$table"/>" FROM <xsl:value-of select="@group"/> + + GO</xsl:otherwise> + </xsl:choose> + <xsl:text> + + </xsl:text> + </xsl:template> + + <xsl:template name="viewpermission"> + <xsl:param name="table"/> + <!-- decode the permissions for a convenience view --> + <xsl:choose> + <xsl:when test="@permission='none'">REVOKE ALL ON "VW_DL_<xsl:value-of + select="$table"/>" FROM <xsl:value-of select="@group"/> + + GO</xsl:when> + <xsl:when test="@permission='insert'">REVOKE ALL ON "VW_DL_<xsl:value-of + select="$table"/>" FROM <xsl:value-of select="@group"/> + + GO</xsl:when> + <xsl:otherwise>GRANT SELECT ON "VW_DL_<xsl:value-of + select="$table"/>" TO <xsl:value-of select="@group"/> + + GO</xsl:otherwise> + </xsl:choose> + <xsl:text> + + </xsl:text> + </xsl:template> + + + <xsl:template name="linktable"> + <xsl:param name="nearside"/> + <!-- This is tricky. For any many-to-many relationship between two + entities, we only want to create one link table, even if (as should be) + a property of type 'link' has been declared at both ends --> + <xsl:variable name="farside"> + <xsl:choose> + <xsl:when test="@entity = $nearside"> + <xsl:value-of select="concat( @entity, '_1')"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="@entity"/> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:variable name="comparison"> + <xsl:call-template name="stringcompare"> + <xsl:with-param name="node1" select="$nearside"/> + <xsl:with-param name="node2" select="@entity"/> + </xsl:call-template> + </xsl:variable> + <xsl:variable name="farentity" select="/application/entity[@name=$farside]"/> + + -- Problems with responsibility for generating link tables: + -- @entity = <xsl:value-of select="@entity"/> + -- $nearside = <xsl:value-of select="$nearside"/> + -- $farside = <xsl:value-of select="$farside"/> + -- $farentity = <xsl:value-of select="count( $farentity/property)"/> + -- farlink = <xsl:value-of select="$farentity/property[@type='link' and @entity=$nearside]/@name"/> + -- comparison = '<xsl:value-of select="$comparison"/>' + + <xsl:variable name="myresponsibility"> + <xsl:choose> + <!-- if we could use the compare( string, string) function this would be a lot simpler, but + unfortunately that's in XSL 2.0, and neither NAnt nor Visual Studio can manage that --> + <!-- if the link is back to me, then obviously I'm responsible --> + <xsl:when test="$comparison = 0">true</xsl:when> + <!-- generally, the entity whose name is later in the default collating sequence + shall not be responsible. --> + <xsl:when test="$comparison = -1">true</xsl:when> + <!-- However if the one that is earlier doesn't have a 'link' + property for this join, however, then later end will have to do it --> + <xsl:when test="$comparison = 1"> + <xsl:choose> + <!-- the far side is doing it... --> + <xsl:when test="$farentity/property[@type='link' and @entity=$nearside]">false</xsl:when> + <xsl:otherwise>true</xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:otherwise>false</xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:variable name="tablename"> + <xsl:choose> + <xsl:when test="$comparison =-1"> + <xsl:value-of select="concat( 'ln_', $nearside, '_', @entity)"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="concat( 'ln_', @entity, '_', $nearside)"/> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + -- Responsibility = '<xsl:value-of select="$myresponsibility"/>' + <xsl:choose> + <xsl:when test="$myresponsibility='true'"> + <!-- create a linking table --> + + ------------------------------------------------------------------------------------------------- + -- link table joining <xsl:value-of select="$nearside"/> with <xsl:value-of select="@entity"/> + ------------------------------------------------------------------------------------------------- + CREATE TABLE "<xsl:value-of select="$tablename"/>" + ( + "<xsl:value-of select="$nearside"/>Id" INT NOT NULL, + "<xsl:value-of select="$farside"/>Id" INT NOT NULL, + ) + + GO + <xsl:text> + + </xsl:text> + ---- permissions ------------------------------------------------------------------------------ + <xsl:for-each select="../permission"> + <xsl:call-template name="permission"> + <xsl:with-param name="table" select="$tablename"/> + </xsl:call-template> + </xsl:for-each> + <xsl:text> + + </xsl:text> + ---- referential integrity -------------------------------------------------------------------- + <xsl:choose> + <xsl:when test="$nearside=@entity"> + ALTER TABLE "<xsl:value-of select="$tablename"/>" + ADD FOREIGN KEY ( "<xsl:value-of select="$nearside"/>Id") + REFERENCES "<xsl:value-of select="$nearside"/>" ON DELETE NO ACTION + + GO + + ALTER TABLE "<xsl:value-of select="$tablename"/>" + ADD FOREIGN KEY ( "<xsl:value-of select="$farside"/>Id") + REFERENCES "<xsl:value-of select="$nearside"/>" ON DELETE NO ACTION + + GO + + </xsl:when> + <xsl:otherwise> + ALTER TABLE "<xsl:value-of select="$tablename"/>" + ADD FOREIGN KEY ( "<xsl:value-of select="$nearside"/>Id") + REFERENCES "<xsl:value-of select="$nearside"/>" ON DELETE CASCADE + + GO + + ALTER TABLE "<xsl:value-of select="$tablename"/>" + ADD FOREIGN KEY ( "<xsl:value-of select="@entity"/>Id") + REFERENCES "<xsl:value-of select="@entity"/>" ON DELETE CASCADE + + GO + + + </xsl:otherwise> + </xsl:choose> + + + </xsl:when> + <xsl:otherwise> + -- Suppressing generation of <xsl:value-of select="$tablename"/>, as it is not my responsibility + </xsl:otherwise> + </xsl:choose> + <xsl:if test="myresponsibility='true'"> + </xsl:if> + </xsl:template> + + <xsl:template match="property[@type='list']"> + -- Suppressing output of property <xsl:value-of select="@name"/>, + -- as it is the 'one' end of a one-to-many relationship + </xsl:template> + + <xsl:template match="property[@type='entity']"> + "<xsl:value-of select="@name"/>" INT<xsl:if + test="string(@default)"> DEFAULT <xsl:value-of select="@default"/></xsl:if><xsl:if + test="@required='true'"> NOT NULL</xsl:if>,<xsl:text> + </xsl:text> + </xsl:template> + + <xsl:template match="property[@type='defined']"> + <xsl:variable name="name"><xsl:value-of select="@definition"/></xsl:variable> + <xsl:variable name="definitiontype"><xsl:value-of select="/application/definition[@name=$name]/@type"/></xsl:variable> + "<xsl:value-of select="@name"/>"<xsl:text> </xsl:text><xsl:choose> + <xsl:when test="$definitiontype='string'">VARCHAR( <xsl:value-of + select="/application/definition[@name=$name]/@size"/>)</xsl:when> + <xsl:when test="$definitiontype='integer'">INT</xsl:when> + <xsl:when test="$definitiontype='real'">DOUBLE PRECISION</xsl:when> + <xsl:otherwise><xsl:value-of select="$definitiontype"/></xsl:otherwise> + </xsl:choose><xsl:if + test="string(@default)"> DEFAULT <xsl:value-of select="@default"/></xsl:if><xsl:if + test="@required='true'"> NOT NULL</xsl:if>,<xsl:text> + </xsl:text> + </xsl:template> + + + <xsl:template match="property[@type='boolean']"> + -- SQL Server doesn't have proper booleans! + "<xsl:value-of select="@name"/>" BIT<xsl:choose> + <xsl:when test="@default='true'"> DEFAULT 1</xsl:when> + <xsl:when test="@default='false'"> DEFAULT 0</xsl:when> + </xsl:choose><xsl:if test="@required='true'"> NOT NULL</xsl:if>,<xsl:text> + </xsl:text> + </xsl:template> + + + <xsl:template match="property[@type='string']"> + "<xsl:value-of select="@name"/>" VARCHAR( <xsl:value-of select="@size"/>)<xsl:if + test="string(@default)"> DEFAULT '<xsl:value-of select="@default"/>'</xsl:if><xsl:if + test="@required='true'"> NOT NULL</xsl:if>,<xsl:text> + </xsl:text> + </xsl:template> + + <xsl:template match="property[@type='date' or @type = 'time']"> + "<xsl:value-of select="@name"/>" DATETIME<xsl:if + test="string(@default)"> DEFAULT <xsl:value-of select="@default"/> + </xsl:if><xsl:if + test="@required='true'"> NOT NULL</xsl:if>,<xsl:text> + </xsl:text> + </xsl:template> + + + <xsl:template match="property[@type='integer']"> + "<xsl:value-of select="@name"/>" INT<xsl:if + test="string(@default)"> DEFAULT <xsl:value-of select="@default"/></xsl:if><xsl:if + test="@required='true'"> NOT NULL</xsl:if>,<xsl:text> + </xsl:text> + </xsl:template> + + <xsl:template match="property[@type='real']"> + "<xsl:value-of select="@name"/>" DOUBLE PRECISION<xsl:if + test="string(@default)"> DEFAULT <xsl:value-of select="@default"/></xsl:if><xsl:if + test="@required='true'"> NOT NULL</xsl:if>,<xsl:text> + </xsl:text> + </xsl:template> + + <xsl:template match="property"> + "<xsl:value-of select="@name"/>" <xsl:text> </xsl:text><xsl:value-of select="@type"/><xsl:if + test="string(@default)"> DEFAULT <xsl:value-of select="@default"/></xsl:if><xsl:if + test="@required='true'"> NOT NULL</xsl:if>,<xsl:text> + </xsl:text> + </xsl:template> + + + <!-- horrible, horrible hackery. Compare two strings and return + * 0 if they are identical, + * -1 if the first is earlier in the default collating sequence, + * 1 if the first is later. + In XSL 2.0 this could be done using the compare(string, string) function. --> + <xsl:template name="stringcompare"> + <xsl:param name="node1"/> + <xsl:param name="node2"/> + <xsl:choose> + <xsl:when test="string($node1)=string($node2)"> + <xsl:text>0</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:for-each select="$node1 | $node2"> + <xsl:sort select="."/> + <xsl:if test="position()=1"> + <xsl:choose> + <xsl:when test="string(.) = string($node1)"> + <xsl:text>-1</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>1</xsl:text> + </xsl:otherwise> + </xsl:choose> + </xsl:if> + </xsl:for-each> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + +</xsl:stylesheet> diff --git a/ADL.NET/Trans/adl2psql.xsl b/ADL.NET/Trans/adl2psql.xsl new file mode 100755 index 0000000..fc2707b --- /dev/null +++ b/ADL.NET/Trans/adl2psql.xsl @@ -0,0 +1,321 @@ +<?xml version="1.0"?> +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + <!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: --> + <!-- --> + <!-- adl2psql.xsl --> + <!-- --> + <!-- Purpose: --> + <!-- XSL stylesheet to generate Postgresql [7|8] from ADL. --> + <!-- --> + <!-- Author: Simon Brooke <sb@cygnets.co.uk> --> + <!-- Created: 24th January 2006 --> + <!-- Copyright: (c) 2008 Cygnet Solutions --> + <!-- + JACQUARD 2 APPLICATION DESCRIPTION LANGUAGE FRAMEWORK + + $Revision: 1.1 $ + + NOTES: + + Needless to say this is all hugely experimental. + + Running the primary key field last is a hack which gets around the fact that + otherwise it's extremely complex to lose the comma after the last field. + Ideally where there is one 'distinct="system"' property of an entity that + should be the primary key and perhaps we'll achieve that in the long run... + + Still to do: + + References in convenience views for fields which have their reference value at + two removes (i.e. the 'distinguish' mechanism in ADL + --> + + <xsl:output indent="no" encoding="utf-8" method="text"/> + + <xsl:template match="application"> + ------------------------------------------------------------------------------------------------- + -- + -- Database for application <xsl:value-of select="@name"/> version <xsl:value-of select="@version"/> + -- Generated for PostgreSQL [7|8] using adl2psql.xsl $Revision: 1.1 $ + -- + -- Code generator (c) 2006 Simon Brooke [sb@cygnets.co.uk] + -- http://www.weft.co.uk/library/jacquard/ + -- + ------------------------------------------------------------------------------------------------- + + ------------------------------------------------------------------------------------------------- + -- authentication roles + ------------------------------------------------------------------------------------------------- + <xsl:apply-templates select="group"/> + + ------------------------------------------------------------------------------------------------- + -- tables, views and permissions + ------------------------------------------------------------------------------------------------- + <xsl:apply-templates select="entity"/> + + ------------------------------------------------------------------------------------------------- + -- referential integrity constraints + ------------------------------------------------------------------------------------------------- + <xsl:for-each select="entity"> + <xsl:variable name="nearside" select="@name"/> + <xsl:for-each select="property[@type='entity']"> + <xsl:call-template name="referentialintegrity"> + <xsl:with-param name="nearside" select="$nearside"/> + </xsl:call-template> + + </xsl:for-each> + <xsl:for-each select="property[@type='link']"> + <xsl:call-template name="linkintegrity"> + <xsl:with-param name="nearside" select="$nearside"/> + </xsl:call-template> + + </xsl:for-each> + </xsl:for-each> + ------------------------------------------------------------------------------------------------- + -- end of file + ------------------------------------------------------------------------------------------------- + </xsl:template> + + <xsl:template match="group"> + CREATE GROUP <xsl:value-of select="@name"/>; + </xsl:template> + + + <xsl:template name="referentialintegrity"> + <xsl:param name="nearside"/> + <!-- set up referential integrity constraints for primary tables --> + ALTER TABLE <xsl:value-of select="$nearside"/> ADD CONSTRAINT ri_<xsl:value-of select="$nearside"/>_<xsl:value-of select="@name"/> + FOREIGN KEY ( <xsl:value-of select="@name"/>) REFERENCES <xsl:value-of select="@entity"/> ON DELETE NO ACTION; + </xsl:template> + + + <xsl:template name="linkintegrity"> + <xsl:param name="nearside"/> + <!-- set up referential integrity constraints for link tables --> + ALTER TABLE ln_<xsl:value-of select="$nearside"/>_<xsl:value-of select="@entity"/> + ADD CONSTRAINT ri_<xsl:value-of select="$nearside"/>_<xsl:value-of select="@entity"/>_<xsl:value-of select="$nearside"/>_id + FOREIGN KEY ( <xsl:value-of select="$nearside"/>_id) REFERENCES <xsl:value-of select="$nearside"/> ON DELETE CASCADE; + + ALTER TABLE ln_<xsl:value-of select="$nearside"/>_<xsl:value-of select="@entity"/> + ADD CONSTRAINT ri_<xsl:value-of select="$nearside"/>_<xsl:value-of select="@entity"/>_<xsl:value-of select="@entity"/>_id + FOREIGN KEY ( <xsl:value-of select="@entity"/>_id) REFERENCES <xsl:value-of select="@entity"/> ON DELETE CASCADE; + + </xsl:template> + + + <xsl:template match="entity"> + <xsl:variable name="table" select="@name"/> + + ------------------------------------------------------------------------------------------------- + -- primary table <xsl:value-of select="@name"/> + ------------------------------------------------------------------------------------------------- + CREATE TABLE <xsl:value-of select="@name"/> + ( + <xsl:apply-templates select="property[@type!='link']"/> + <xsl:value-of select="@name"/>_id SERIAL NOT NULL PRIMARY KEY + ); + + ---- permissions ------------------------------------------------------------------------------ + <xsl:for-each select="permission"> + <xsl:call-template name="permission"> + <xsl:with-param name="table" select="$table"/> + </xsl:call-template> + </xsl:for-each> + ------------------------------------------------------------------------------------------------- + -- convenience view lv_<xsl:value-of select="@name"/> for lists + ------------------------------------------------------------------------------------------------- + CREATE VIEW lv_<xsl:value-of select="@name"/> AS + SELECT <xsl:for-each select="property[@type!='link']"> + <xsl:choose> + <xsl:when test="@type='entity'"> + <xsl:call-template name="distinctfield"> + <xsl:with-param name="table" select="@entity"/> + <xsl:with-param name="alias" select="@name"/> + </xsl:call-template> AS <xsl:value-of select="@name"/> + </xsl:when> + <xsl:otherwise><xsl:value-of select="$table"/>.<xsl:value-of select="@name"/> + </xsl:otherwise> + </xsl:choose><xsl:choose> + <xsl:when test="position() = last()"></xsl:when> + <xsl:otherwise>, + </xsl:otherwise> + </xsl:choose> + </xsl:for-each> + FROM <xsl:value-of select="@name"/> + <xsl:for-each select="property[@type='entity']">, <xsl:value-of select="@entity"/> AS <xsl:value-of select="@name"/></xsl:for-each> + <xsl:text> + </xsl:text> + <xsl:for-each select="property[@type='entity']"> + <xsl:choose> + <xsl:when test="position() = 1">WHERE </xsl:when> + <xsl:otherwise>AND </xsl:otherwise> + </xsl:choose><xsl:value-of select="$table"/>.<xsl:value-of + select="@name"/> = <xsl:value-of select="@name"/>.<xsl:value-of select="@entity"/>_id + </xsl:for-each>; + + ---- permissions ------------------------------------------------------------------------------ + <xsl:for-each select="permission"> + <xsl:call-template name="viewpermission"> + <xsl:with-param name="table" select="$table"/> + </xsl:call-template> + </xsl:for-each> + + <!-- link tables --> + <xsl:for-each select="property[@type='link']"> + <xsl:call-template name="linktable"> + <xsl:with-param name="nearside" select="$table"/> + </xsl:call-template> + ---- permissions ------------------------------------------------------------------------------ + <xsl:variable name="farside" select="@entity"/> + <xsl:for-each select="../permission"> + <xsl:call-template name="permission"> + <xsl:with-param name="table">ln_<xsl:value-of select="$table"/>_<xsl:value-of select="$farside"/></xsl:with-param> + </xsl:call-template> + </xsl:for-each> + </xsl:for-each> + + </xsl:template> + + <xsl:template name="distinctfield"> + <xsl:param name="table"/> + <xsl:param name="alias"/> + <!-- + print the names of the distinguishing fields in this table, + concatenating into a single string. + --> + <xsl:for-each select="/application/entity[@name=$table]"> + <xsl:for-each select="property[@distinct='user' or @distinct='all']"> + <xsl:choose> + <xsl:when test="@type='entity'"> + <xsl:call-template name="distinctfield"> + <xsl:with-param name="table" select="@entity"/> + <xsl:with-param name="alias" select="concat( $alias, '_', @name)"></xsl:with-param> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$alias"/>.<xsl:value-of + select="@name"/><xsl:if test="position() != last()"> | ' ' | </xsl:if> + </xsl:otherwise> + </xsl:choose> + + </xsl:for-each> + </xsl:for-each> + </xsl:template> + + <xsl:template name="permission"> + <xsl:param name="table"/> + <!-- decode the permissions for a table --> + <xsl:choose> + <xsl:when test="@permission='read'">GRANT SELECT ON <xsl:value-of + select="$table"/> TO GROUP <xsl:value-of select="@group"/>;</xsl:when> + <xsl:when test="@permission='insert'">GRANT INSERT ON <xsl:value-of + select="$table"/> TO GROUP <xsl:value-of select="@group"/>;</xsl:when> + <xsl:when test="@permission='noedit'">GRANT SELECT, INSERT ON <xsl:value-of + select="$table"/> TO GROUP <xsl:value-of select="@group"/>;</xsl:when> + <xsl:when test="@permission='edit'">GRANT SELECT, INSERT, UPDATE ON <xsl:value-of + select="$table"/> TO GROUP <xsl:value-of select="@group"/>;</xsl:when> + <xsl:when test="@permission='all'">GRANT SELECT, INSERT, UPDATE, DELETE ON <xsl:value-of + select="$table"/> TO GROUP <xsl:value-of select="@group"/>;</xsl:when> + <xsl:otherwise>REVOKE ALL ON <xsl:value-of + select="$table"/> FROM GROUP <xsl:value-of select="@group"/>;</xsl:otherwise> + </xsl:choose> + <xsl:text> + + </xsl:text> + </xsl:template> + + <xsl:template name="viewpermission"> + <xsl:param name="table"/> + <!-- decode the permissions for a convenience view --> + <xsl:choose> + <xsl:when test="@permission='none'">REVOKE ALL ON lv_<xsl:value-of + select="$table"/> FROM GROUP <xsl:value-of select="@group"/>;</xsl:when> + <xsl:when test="@permission='insert'">REVOKE ALL ON lv_<xsl:value-of + select="$table"/> FROM GROUP <xsl:value-of select="@group"/>;</xsl:when> + <xsl:otherwise>GRANT SELECT ON lv_<xsl:value-of + select="$table"/> TO GROUP <xsl:value-of select="@group"/>;</xsl:otherwise> + </xsl:choose> + <xsl:text> + + </xsl:text> + </xsl:template> + + + <xsl:template name="linktable"> + <xsl:param name="nearside"/> + <xsl:variable name="farside"> + <xsl:choose> + <xsl:when test="@entity = $nearside"><xsl:value-of select="@entity"/>_1</xsl:when> + <xsl:otherwise> + <xsl:value-of select="@entity"/> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + <!-- create a linking table --> + + ------------------------------------------------------------------------------------------------- + -- link table joining <xsl:value-of select="$nearside"/> with <xsl:value-of select="@entity"/> + ------------------------------------------------------------------------------------------------- + CREATE TABLE ln_<xsl:value-of select="$nearside"/>_<xsl:value-of select="@entity"/> + ( + <xsl:value-of select="$nearside"/>_id INT NOT NULL, + <xsl:value-of select="$farside"/>_id INT NOT NULL, + ); + <xsl:text> + + </xsl:text> + <!-- TODO: permissions for link tables! --> + + </xsl:template> + + <xsl:template match="property[@type='entity']"> + <xsl:value-of select="@name"/> INT<xsl:if + test="string(@default)"> DEFAULT <xsl:value-of select="@default"/></xsl:if><xsl:if + test="@required='true'"> NOT NULL</xsl:if>,<xsl:text> + </xsl:text> + </xsl:template> + + <xsl:template match="property[@type='defined']"> + <xsl:variable name="name"><xsl:value-of select="@definition"/></xsl:variable> + <xsl:variable name="definitiontype"><xsl:value-of select="/application/definition[@name=$name]/@type"/></xsl:variable> + <xsl:value-of select="@name"/><xsl:text> </xsl:text><xsl:choose> + <xsl:when test="$definitiontype='string'">VARCHAR( <xsl:value-of + select="/application/definition[@name=$name]/@size"/>)</xsl:when> + <xsl:when test="$definitiontype='integer'">INT</xsl:when> + <xsl:when test="$definitiontype='real'">DOUBLE PRECISION</xsl:when> + <xsl:otherwise><xsl:value-of select="$definitiontype"/></xsl:otherwise> + </xsl:choose><xsl:if + test="string(@default)"> DEFAULT <xsl:value-of select="@default"/></xsl:if><xsl:if + test="@required='true'"> NOT NULL</xsl:if>,<xsl:text> + </xsl:text> + </xsl:template> + + <xsl:template match="property[@type='string']"> + <xsl:value-of select="@name"/> VARCHAR( <xsl:value-of select="@size"/>)<xsl:if + test="string(@default)"> DEFAULT <xsl:value-of select="@default"/></xsl:if><xsl:if + test="@required='true'"> NOT NULL</xsl:if>,<xsl:text> + </xsl:text> + </xsl:template> + + <xsl:template match="property[@type='integer']"> + <xsl:value-of select="@name"/> INT<xsl:if + test="string(@default)"> DEFAULT <xsl:value-of select="@default"/></xsl:if><xsl:if + test="@required='true'"> NOT NULL</xsl:if>,<xsl:text> + </xsl:text> + </xsl:template> + + <xsl:template match="property[@type='real']"> + <xsl:value-of select="@name"/> DOUBLE PRECISION<xsl:if + test="string(@default)"> DEFAULT <xsl:value-of select="@default"/></xsl:if><xsl:if + test="@required='true'"> NOT NULL</xsl:if>,<xsl:text> + </xsl:text> + </xsl:template> + + <xsl:template match="property"> + <xsl:value-of select="@name"/> <xsl:text> </xsl:text><xsl:value-of select="@type"/><xsl:if + test="string(@default)"> DEFAULT <xsl:value-of select="@default"/></xsl:if><xsl:if + test="@required='true'"> NOT NULL</xsl:if>,<xsl:text> + </xsl:text> + </xsl:template> + +</xsl:stylesheet> diff --git a/ADL.NET/Trans/adl2views.xsl b/ADL.NET/Trans/adl2views.xsl new file mode 100755 index 0000000..e9caa45 --- /dev/null +++ b/ADL.NET/Trans/adl2views.xsl @@ -0,0 +1,1135 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + <!-- + C1873 SRU Hospitality + adl2views.xsl + + (c) 2007 Cygnet Solutions Ltd + + Transform ADL into velocity view templates + + $Author: af $ + $Revision: 1.1 $ + $Date: 2008-01-09 15:01:45 $ + --> + <!-- WARNING WARNING WARNING: Do NOT reformat this file! + Whitespace (or lack of it) is significant! --> + + <!-- + TODO: this transform BADLY needs to be refactored! It is /crap/! + --> + <xsl:output method="xml" indent="yes" encoding="UTF-8" omit-xml-declaration="yes"/> + + <!-- The locale for which these views are generated + TODO: we need to generate views for each available locale, but this is not + yet implemented. When it is we will almost certainly still need a 'default locale' --> + <xsl:param name="locale" select="en-UK"/> + + <!-- what's all this about? the objective is to get the revision number of the + transform into the output, /without/ getting that revision number overwritten + with the revision number of the generated file when the generated file is + stored to CVS --> + + <xsl:variable name="transform-rev1" + select="substring( '$Revision: 1.1 $', 11)"/> + <xsl:variable name="transform-revision" + select="substring( $transform-rev1, 0, string-length( $transform-rev1) - 1)"/> + + + <xsl:template match="application"> + <output> + <xsl:apply-templates select="entity"/> + <!-- make sure extraneous junk doesn't get into the last file generated, + by putting it into a separate file --> + <xsl:comment> [ cut here: next file 'tail.txt' ] </xsl:comment> + </output> + </xsl:template> + + <xsl:template match="entity"> + <xsl:apply-templates select="form"/> + <xsl:apply-templates select="list"/> + <xsl:text> + </xsl:text> + <xsl:comment> [ cut here: next file '<xsl:value-of select="concat( @name, '/maybedelete.auto.vm')"/>' ] </xsl:comment> + <xsl:text> + </xsl:text> + <html> + <xsl:comment> + #set( $title = "<xsl:value-of select="concat( 'Really delete ', @name)"/> $instance.UserIdentifier") + </xsl:comment> + <head> + <xsl:call-template name="head"/> + <xsl:comment> + Auto generated Velocity maybe-delete form for <xsl:value-of select="@name"/>, + generated from ADL. + + Generated using adl2views.xsl <xsl:value-of select="$transform-revision"/> + </xsl:comment> + ${Ajax.InstallScripts()} + ${FormHelper.InstallScripts()} + ${Validation.InstallScripts()} + ${Scriptaculous.InstallScripts()} + </head> + <body> + <xsl:call-template name="top"/> + <form action="delete.rails"> + <xsl:choose> + <xsl:when test="@natural-key"> + <!-- create a hidden widget for the natural primary key --> + ${FormHelper.HiddenField( "instance.<xsl:value-of select="@natural-key"/>")} + </xsl:when> + <xsl:otherwise> + <!-- there isn't a natural primary key; create a hidden widget + for the abstract primary key --> + ${FormHelper.HiddenField( "instance.<xsl:value-of select="@name"/>Id")} + </xsl:otherwise> + </xsl:choose> + <table> + <tr align="left" valign="top" class="actionDangerous"> + <td class="actionDangerous"> + Really delete? + </td> + <td class="widget"> + <select name="reallydelete"> + <option value="false">No, don't delete it</option> + <option value="true">Yes, do delete it</option> + </select> + </td> + <td class="actionDangerous" style="text-align:right"> + <input type="submit" name="command" value="Go!" /> + </td> + </tr> + </table> + </form> + <xsl:call-template name="foot"/> + </body> + </html> + </xsl:template> + + <!-- layout of forms --> + + <xsl:template match="form"> + <xsl:variable name="formname" select="@name"/> + <xsl:variable name="aoran"> + <xsl:variable name="initial" select="substring( ancestor::entity/@name, 1, 1)"/> + <xsl:choose> + <xsl:when test="$initial = 'A'">an</xsl:when> + <xsl:when test="$initial = 'E'">an</xsl:when> + <xsl:when test="$initial = 'I'">an</xsl:when> + <xsl:when test="$initial = 'O'">an</xsl:when> + <xsl:when test="$initial = 'U'">an</xsl:when> + <xsl:otherwise>a</xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:text> + </xsl:text> + <xsl:comment> [ cut here: next file '<xsl:value-of select="concat( ancestor::entity/@name, '/', @name)"/>.auto.vm' ] </xsl:comment> + <xsl:text> + </xsl:text> + <html> + <xsl:comment> + #if ( $instance) + #set( $title = "<xsl:value-of select="concat( 'Edit ', ' ', ancestor::entity/@name)"/> $instance.UserIdentifier") + #else + #set( $title = "Add a new <xsl:value-of select="ancestor::entity/@name"/>") + #end + </xsl:comment> + <head> + <xsl:call-template name="head"/> + <xsl:comment> + Auto generated Velocity form for <xsl:value-of select="@name"/>, + generated from ADL. + + Generated using adl2views.xsl <xsl:value-of select="$transform-revision"/> + </xsl:comment> + ${Ajax.InstallScripts()} + ${FormHelper.InstallScripts()} + ${Validation.InstallScripts()} + ${Scriptaculous.InstallScripts()} + ${DateTime.InstallScripts()} + ${ShuffleWidgetHelper.InstallScripts()} + <script type="text/javascript" language='JavaScript1.2' src="../script/panes.js"></script> + + <script type='text/javascript' language='JavaScript1.2'> + var panes = new Array( <xsl:for-each select='fieldgroup'> + "<xsl:value-of select='@name'/>"<xsl:choose> + <xsl:when test="position() = last()"/> + <xsl:otherwise>,</xsl:otherwise> + </xsl:choose></xsl:for-each> ); + + function performInitialisation() + { + <xsl:for-each select="../property[@type='link']"> + document.<xsl:value-of select="$formname"/>.<xsl:value-of select="@name"/>.submitHandler = shuffleSubmitHandler; + </xsl:for-each> + var validator = new Validation('<xsl:value-of select="$formname"/>', {immediate : true, useTitles : true}); + <xsl:if test="fieldgroup"> + switchtab( '<xsl:value-of select="fieldgroup[1]/@name"/>'); + </xsl:if> + } + + </script> + <style type="text/css"> + <xsl:for-each select="../property[@required='true']"> + #<xsl:value-of select="concat( 'advice-required-instance_', @name)"/> + { + color: white; + background-color: rgb( 198, 0, 57); + font-style: italic; + } + </xsl:for-each> + </style> + </head> + <body onload="performInitialisation()"> + <xsl:call-template name="top"/> + <div class="content"> + #if ( $Flash.errors) + <div class="warning"> + <h2>Errors were encountered</h2> + + <ul> + #foreach ($error in $Flash.errors) + <li> + $error + </li> + #end + </ul> + </div> + #end + #if ( $messages.Count == 0) + <!-- if I try to test for $messages.Count > 0, I get the > copied straight through to + the output instead of the entity value being substituted(?) --> + #else + <div class="information"> + #foreach ( $message in $messages) + <p> + $message + </p> + #end + </div> + #end + <form method="post" onsubmit="invokeSubmitHandlers( this)"> + <xsl:attribute name="action"> + <xsl:value-of select="concat( $formname, 'SubmitHandler.rails')"/> + </xsl:attribute> + <xsl:attribute name="name"> + <xsl:value-of select="$formname"/> + </xsl:attribute> + <xsl:attribute name="id"> + <xsl:value-of select="$formname"/> + </xsl:attribute> + <xsl:choose> + <xsl:when test="ancestor::entity/@natural-key"> + <xsl:variable name="keyfield" select="ancestor::entity/@natural-key"/> + <xsl:choose> + <xsl:when test="@properties='all'"> + <!-- no need to emit a hidden widget for the natural key, as there will be a + non-hidden one anyway --> + </xsl:when> + <xsl:when test="field[@name=$keyfield]"> + <!-- no need to emit a hidden widget for the natural key, as there will be a + non-hidden one anyway --> + </xsl:when> + <xsl:otherwise> + <!-- create a hidden widget for the natural primary key --> + ${FormHelper.HiddenField( "instance.<xsl:value-of select="$keyfield"/>")} + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:otherwise> + <!-- there isn't a natural primary key; create a hidden widget + for the abstract primary key --> + ${FormHelper.HiddenField( "instance.<xsl:value-of select="ancestor::entity/@name"/>Id")} + </xsl:otherwise> + </xsl:choose> + <xsl:if test="fieldgroup"> + <div id="tabbar"> + <xsl:for-each select="fieldgroup"> + <span class="tab"> + <xsl:attribute name="id"> + <xsl:value-of select="concat( @name, 'tab')"/> + </xsl:attribute> + <a> + <xsl:attribute name="href"> + <xsl:value-of select="concat( '#', @name, 'anchor')"/> + </xsl:attribute> + <xsl:attribute name="onclick">switchtab( '<xsl:value-of select="@name"/>'); return false;</xsl:attribute> + <xsl:call-template name="showprompt"> + <xsl:with-param name="fallback" select="@name"/> + </xsl:call-template> + </a> + </span> + </xsl:for-each> + </div> + </xsl:if> + <xsl:apply-templates select="fieldgroup"/> + <div class="pane"> + <table> + <xsl:choose> + <xsl:when test="@properties='listed'"> + <xsl:apply-templates select="field|auxlist|verb"/> + </xsl:when> + <xsl:otherwise> + <xsl:apply-templates select="ancestor::entity/property"/> + </xsl:otherwise> + </xsl:choose> + <tr class="actionSafe"> + <td class="actionSafe" colspan="2"> + To save this record + </td> + <td class="actionSafe" style="text-align:right"> + <button type="submit" name="command" value="store">Save this!</button> + </td> + </tr> + <tr align="left" valign="top" class="actionDangerous"> + + <td class="actionDangerous" colspan="2"> + To delete this record + </td> + <td class="actionDangerous" style="text-align:right"> + <button type="submit" name="command" value="delete">Delete this!</button> + </td> + </tr> + </table> + </div> + </form> + </div> + <xsl:call-template name="foot"/> + </body> + </html> + </xsl:template> + + <xsl:template match="fieldgroup"> + <div class="pane"> + <xsl:attribute name="id"> + <xsl:value-of select="concat( @name, 'pane')"/> + </xsl:attribute> + <xsl:attribute name="style"> + <xsl:choose> + <xsl:when test="position() = 1"/> + <xsl:otherwise>display: none</xsl:otherwise> + </xsl:choose> + </xsl:attribute> + <a> + <xsl:attribute name="name"> + <xsl:value-of select="concat( @name, 'anchor')"/> + </xsl:attribute> + <h3> + <xsl:call-template name="showprompt"> + <xsl:with-param name="fallback" select="@name"/> + </xsl:call-template> + </h3> + </a> + <table> + <xsl:apply-templates select="field|verb|auxlist"/> + </table> + </div> + </xsl:template> + + <xsl:template match="auxlist"> + <xsl:variable name="listprop" select="@property"/> + <xsl:variable name="farent" select="ancestor::entity/property[@name=$listprop]/@entity"/> + <xsl:variable name="nearent" select="ancestor::entity/@name"/> + <xsl:variable name="farid"> + <xsl:choose> + <xsl:when test="//entity[@name=$farent]/@natural-key"> + <xsl:value-of select="//entity[@name=$farent]/@natural-key"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="concat( $farent, 'Id')"/> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:variable name="farkey"> + <xsl:value-of select="//entity[@name=$farent]/property[@entity=$nearent]/@name"/> + </xsl:variable> + <xsl:variable name="nearkey"> + <xsl:choose> + <xsl:when test="ancestor::entity[@natural-key]"> + <xsl:value-of select="ancestor::entity[@natural-key]"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="concat( $nearent, 'Id')"/> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:variable name="action" select="concat( '../', $farent, '/', @onselect)"/> + <xsl:if test="@canadd='true'"> + <tr> + <td> + <xsl:attribute name="colspan"> + <xsl:value-of select="count( field)"/> + </xsl:attribute> + <a> + <xsl:attribute name="href"> + <xsl:value-of select="concat( $action, '.rails?', $farkey, '=$instance.', $nearkey)"/> + </xsl:attribute> + Add a new <xsl:value-of select="$farent"/> + </a> + </td> + </tr> + </xsl:if> + <xsl:choose> + <xsl:when test="@properties='listed'"> + <tr> + <xsl:for-each select="field"> + <xsl:variable name="fieldprop" select="@property"/> + <th> + <!-- Getting the prompt for the field from a property of another entity is a bit + complex... --> + <xsl:call-template name="showprompt"> + <xsl:with-param name="node" select="//entity[@name=$farent]/property[@name=$fieldprop]"/> + <xsl:with-param name="fallback" select="@property"/> + </xsl:call-template> + </th> + </xsl:for-each> + <th> + - + </th> + </tr> + #foreach( $item in $instance.<xsl:value-of select="@property"/>) + #if ( $velocityCount % 2 == 0) + #set( $oddity = "even") + #else + #set( $oddity = "odd") + #end + <tr class="$oddity"> + <xsl:for-each select="field"> + <xsl:variable name="fieldprop" select="@property"/> + <td> + <xsl:choose> + <xsl:when test="//entity[@name=$farent]/property[@name=$fieldprop]/@type='entity'"> + #if ( $item.<xsl:value-of select="@property"/>) + $item.<xsl:value-of select="@property"/>.UserIdentifier + #end + </xsl:when> + <xsl:when test="//entity[@name=$farent]/property[@name=$fieldprop]/option"> + <!-- if we can get a prompt value for the option, it would be better to + show it than the raw value--> + <xsl:for-each select="//entity[@name=$farent]/property[@name=$fieldprop]/option"> + #if ( $item.<xsl:value-of select="$fieldprop"/> == '<xsl:value-of select="@value"/>') + <xsl:call-template name="showprompt"> + <xsl:with-param name="fallback" select="@value"/> + </xsl:call-template> + #end + </xsl:for-each> + </xsl:when> + <xsl:otherwise> + $!item.<xsl:value-of select="@property"/> + </xsl:otherwise> + </xsl:choose> + </td> + </xsl:for-each> + <td> + <a> + <xsl:attribute name="href"> + <xsl:value-of select="concat( $action, '.rails?', $farid, '=$item.', $farid)"/> + </xsl:attribute> + Edit! + </a> + </td> + </tr> + #end + </xsl:when> + <xsl:otherwise> + <!-- properties not listed, so therefore presumably all. TODO: This won't work, rewrite. Need to + find the entity of the property this auxlist depends on, and then interrogate that --> + <tr> + <xsl:for-each select="ancestor::entity/property[@distinct='user']"> + <th> + <xsl:choose> + <xsl:when test="prompt[@locale=$locale]"> + <xsl:value-of select="prompt[@locale=$locale]/@prompt"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="@name"/> + </xsl:otherwise> + </xsl:choose> + </th> + </xsl:for-each> + <th>-</th> + </tr> + #foreach( $instance in $instances) + #if ( $velocityCount % 2 == 0) + #set( $oddity = "even") + #else + #set( $oddity = "odd") + #end + <tr class="$oddity"> + <xsl:for-each select="ancestor::entity/property[@distinct='user']"> + <td> + $!instance.<xsl:value-of select="@name"/> + </td> + </xsl:for-each> + <td> + <a> + <xsl:attribute name="href"> + <xsl:value-of select="concat( $action, '.rails?', ../@name, 'Id=$instance.', ../@name, 'Id')"/> + </xsl:attribute> + Edit! + </a> + </td> + </tr> + #end + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template match="verb"> + <xsl:variable name="class"> + <xsl:choose> + <xsl:when test="@dangerous='true'">actionDangerous</xsl:when> + <xsl:otherwise>actionSafe</xsl:otherwise> + </xsl:choose> + </xsl:variable> + <tr> + <xsl:attribute name="class"><xsl:value-of select="$class"/></xsl:attribute> + <td colspan="2"> + <xsl:attribute name="class"> + <xsl:value-of select="$class"/> + </xsl:attribute> + <xsl:apply-templates select="help[@locale = $locale]"/> + </td> + <td style="text-align:right"> + <xsl:attribute name="class"> + <xsl:value-of select="$class"/> + </xsl:attribute> + <button name="command"> + <xsl:attribute name="value"> + <xsl:value-of select="@verb"/> + </xsl:attribute> + <xsl:call-template name="showprompt"> + <xsl:with-param name="fallback" select="@verb"/> + </xsl:call-template> + </button> + </td> + </tr> + </xsl:template> + + <xsl:template match="field"> + <xsl:variable name="propname"> + <xsl:value-of select="@property"/> + </xsl:variable> + <xsl:choose> + <xsl:when test="ancestor::entity/property[@name=$propname]"> + <!-- there is a real property --> + <xsl:apply-templates select="ancestor::entity/property[@name=$propname]"> + <xsl:with-param name="oddness"> + <xsl:choose> + <xsl:when test="position() mod 2 = 0">even</xsl:when> + <xsl:otherwise>odd</xsl:otherwise> + </xsl:choose> + </xsl:with-param> + </xsl:apply-templates> + </xsl:when> + <xsl:otherwise> + <!-- it's presumably intended to be a computed field --> + Computed field? TODO: Not yet implememented + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template match="property[@type='link']"> + <!-- note! this template is only intended to match properties in the context of a form: + it may be we need to add a mode to indicate this! --> + <!-- for links we implement a shuffle widget, which extends over both columns --> + <!-- TODO: Permissions! --> + <xsl:param name="oddness" select="odd"/> + <tr> + <xsl:attribute name="class"> + <xsl:value-of select="$oddness"/> + </xsl:attribute> + <td class="label" rowspan="2"> + ${FormHelper.LabelFor( "instance.<xsl:value-of select="@name"/>", "<xsl:call-template name="showprompt"> + <xsl:with-param name="fallback" select="@name"/> + </xsl:call-template>")} + </td> + <td class="widget" colspan="2"> + <table> + <tr> + <td class="widget" rowspan="2"> + ${ShuffleWidgetHelper.UnselectedOptions( "<xsl:value-of select="concat( @name, '_unselected')"/>", <xsl:value-of select="concat( '$all_', @name)"/>, $instance.<xsl:value-of select="@name"/>)} + </td> + <td class="widget"> + <input type="button" value="include >>"> + <xsl:attribute name="onclick"> + <xsl:value-of select="concat( 'shuffle(', @name, '_unselected, ', @name, ')')"/> + </xsl:attribute> + </input> + </td> + <td class="widget" rowspan="2"> + ${ShuffleWidgetHelper.SelectedOptions( "<xsl:value-of select="@name"/>", $instance.<xsl:value-of select="@name"/>)} + </td> + </tr> + <tr> + <td class="widget"> + <input type="button" value="<< exclude"> + <xsl:attribute name="onclick"> + <xsl:value-of select="concat( 'shuffle(', @name, ', ', @name, '_unselected)')"/> + </xsl:attribute> + </input> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <xsl:attribute name="class"> + <xsl:choose> + <xsl:when test="position() mod 2 = 0">even</xsl:when> + <xsl:otherwise>odd</xsl:otherwise> + </xsl:choose> + </xsl:attribute> + <td class="help" colspan="2"> + <xsl:apply-templates select="help[@locale = $locale]"/> + </td> + </tr> + </xsl:template> + + + <xsl:template match="property[@type='text']"> + <!-- note! this template is only intended to match properties in the context of a form: + it may be we need to add a mode to indicate this! --> + <!-- text box widgets, like shuffle widgets, extend over both columns --> + <!-- TODO: Permissions! --> + <xsl:param name="oddness" select="odd"/> + <xsl:variable name="if-missing"> + <xsl:choose> + <xsl:when test="if-missing[@locale = $locale]"> + <xsl:value-of select="if-missing[@locale = $locale]"/> + </xsl:when> + <xsl:when test="required='true'">You must provide a value for <xsl:value-of select="@name"/></xsl:when> + <xsl:otherwise>Enter a value for <xsl:value-of select="@name"/></xsl:otherwise> + </xsl:choose> + </xsl:variable> + <tr> + <xsl:attribute name="class"> + <xsl:value-of select="$oddness"/> + </xsl:attribute> + <td class="label" rowspan="2"> + ${FormHelper.LabelFor( "instance.<xsl:value-of select="@name"/>", "<xsl:choose> + <xsl:when test="prompt[@locale = $locale]"> + <xsl:apply-templates select="prompt[@locale = $locale]"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="@name"/> + </xsl:otherwise> + </xsl:choose>")} + </td> + <td class="widget" colspan="2"> + ${FormHelper.TextArea( "instance.<xsl:value-of select="@name"/>", "%{rows='8' cols='60' title='<xsl:value-of select="$if-missing"/>'}")} + </td> + </tr> + <tr> + <xsl:attribute name="class"> + <xsl:choose> + <xsl:when test="position() mod 2 = 0">even</xsl:when> + <xsl:otherwise>odd</xsl:otherwise> + </xsl:choose> + </xsl:attribute> + <td class="help" colspan="2"> + <xsl:apply-templates select="help[@locale = $locale]"/> + </td> + </tr> + </xsl:template> + + <xsl:template match="property"> + <xsl:param name="oddness" select="odd"/> + <!-- note! this template is only intended to match properties in the context of a form: + it may be we need to add a mode to indicate this! --> + <!-- TODO: This really needs to be refactored --> + <!-- TODO: we really need to be able to handle different permissions for different + groups. If the current user is not a member of a group which has read access to + this widget, the widget shouldn't even appear (unless they have write but not read?); + if they are not a member of a group which has write access, the widget should be + disabled. I don't have time to implement this now as it is not trivial, but it is + important! --> + <xsl:variable name="if-missing"> + <xsl:choose> + <xsl:when test="if-missing[@locale = $locale]"> + <xsl:value-of select="if-missing[@locale = $locale]"/> + </xsl:when> + <xsl:when test="@required='true'"> + You must provide a value for <xsl:value-of select="@name"/> + </xsl:when> + <xsl:when test="@type='defined'"> + The value for <xsl:value-of select="@name"/> must be <xsl:value-of select="@definition"/> + </xsl:when> + <xsl:when test="@type='entity'"> + The value for <xsl:value-of select="@name"/> must be an instance of <xsl:value-of select="@entity"/> + </xsl:when> + <xsl:otherwise> + The value for <xsl:value-of select="@name"/> must be <xsl:value-of select="@type"/> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + <!-- TODO: this is a one-database-role permission model, because that's all SRU needs. + Different permissions for different database groups is much more complex! Also, this + handles permissions on only properties and entities, not on forms. Perhaps we need a + Helper class? --> + <xsl:variable name="permission"> + <xsl:choose> + <xsl:when test="permission"> + <xsl:value-of select="permission[position()=1]/@permission"/> + </xsl:when> + <xsl:when test="../permission"> + <xsl:value-of select="../permission[position()=1]/@permission"/> + </xsl:when> + <xsl:otherwise>none</xsl:otherwise> + </xsl:choose> + </xsl:variable> + <tr> + <xsl:attribute name="class"> + <xsl:value-of select="$oddness"/> + </xsl:attribute> + <td class="label"> + ${FormHelper.LabelFor( "instance.<xsl:value-of select="@name"/>", "<xsl:call-template name="showprompt"> + <xsl:with-param name="fallback" select="@name"/> + </xsl:call-template>")} + </td> + <td class="widget"> + <xsl:choose> + <xsl:when test="$permission='none'"> + [You are not authorised to see this data] + </xsl:when> + <xsl:when test="$permission='read'"> + <xsl:choose> + <xsl:when test="@type='entity'"> + <xsl:value-of select="concat('$instance.', @name, '.UserIdentifier')"/> + </xsl:when> + <!-- TODO: if @type='list' or 'link', should generate Velocity to generate ul list + of UserIdentifiers + --> + <xsl:otherwise> + <xsl:value-of select="concat('$instance.', @name)"/> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <!-- TODO: if $permission='insert', then you should get an editable widget if there + is no current value, else a 'not authorised' message --> + <!-- TODO: if $permission='noedit', then you should get an editable widget if there + is no current value, else just the value --> + <xsl:when test="@type='entity'"> + <!-- a menu of the appropriate entity --> + #if ( $instance) + ${FormHelper.Select( "instance.<xsl:value-of select="@name"/>", $instance.<xsl:value-of select="@name"/>, <xsl:value-of select="concat( '$all_', @name)"/>, "%{firstoption='[unset]' firstoptionvalue='-1' text='UserIdentifier' value='<xsl:value-of select="concat( @entity, 'Id')"/>' title='<xsl:value-of select="normalize-space( $if-missing)"/>'}" )} + #else + ${FormHelper.Select( "instance.<xsl:value-of select="@name"/>", $<xsl:value-of select="@name"/>, <xsl:value-of select="concat( '$all_', @name)"/>, "%{firstoption='[unset]' firstoptionvalue='-1' text='UserIdentifier' value='<xsl:value-of select="concat( @entity, 'Id')"/>' title='<xsl:value-of select="normalize-space( $if-missing)"/>'}" )} + #end + </xsl:when> + <xsl:when test="@type='list'"> + <!-- a multi-select menu of the appropriate entity --> + ${FormHelper.Select( "instance.<xsl:value-of select="@name"/>", $instance.<xsl:value-of select="@name"/>, <xsl:value-of select="concat( '$all_', @name)"/>, "%{multiple='multiple' size='8' text='UserIdentifier' value='<xsl:value-of select="concat( @entity, 'Id')"/>' title='<xsl:value-of select="normalize-space( $if-missing)"/>'}" )} + </xsl:when> + <xsl:when test="@type='defined'"> + <!-- likely to be hardest of all... --> + <xsl:variable name="definition"> + <xsl:value-of select="@definition"/> + </xsl:variable> + <xsl:variable name="maximum"> + <xsl:value-of select="/application/definition[@name=$definition]/@maximum"/> + </xsl:variable> + <xsl:variable name="minimum"> + <xsl:value-of select="/application/definition[@name=$definition]/@minimum"/> + </xsl:variable> + <xsl:variable name="validationpattern"> + <xsl:value-of select="/application/definition[@name=$definition]/@pattern"/> + </xsl:variable> + <xsl:variable name="definedtype"> + <xsl:value-of select="/application/definition[@name=$definition]/@type"/> + </xsl:variable> + <xsl:variable name="definedsize"> + <xsl:value-of select="/application/definition[@name=$definition]/@size"/> + </xsl:variable> + <input type="text"> + <xsl:attribute name="class"> + <xsl:if test="@required='true'">required </xsl:if> + <xsl:choose> + <xsl:when test="$definedtype='integer'">validate-digits</xsl:when> + <xsl:when test="$definedtype='real'">validate-number</xsl:when> + <xsl:when test="$definedtype='money'">validate-number</xsl:when> + <xsl:when test="$definedtype='date'">date-field validate-date</xsl:when> + </xsl:choose> + </xsl:attribute> + <xsl:attribute name="id"> + <xsl:value-of select="concat( 'instance_', @name)"/> + </xsl:attribute> + <xsl:attribute name="name"> + <xsl:value-of select="concat( 'instance.', @name)"/> + </xsl:attribute> + <xsl:choose> + <xsl:when test="$definedsize < 60"> + <xsl:attribute name="size"> + <xsl:value-of select="$definedsize"/> + </xsl:attribute> + <xsl:attribute name="maxlength"> + <xsl:value-of select="$definedsize"/> + </xsl:attribute> + </xsl:when> + <xsl:when test="$definedsize >= 60"> + <xsl:attribute name="size"> + <xsl:value-of select="60"/> + </xsl:attribute> + <xsl:attribute name="maxlength"> + <xsl:value-of select="$definedsize"/> + </xsl:attribute> + </xsl:when> + </xsl:choose> + <xsl:attribute name="value">$!instance.<xsl:value-of select="@name"/></xsl:attribute> + <xsl:attribute name="title"> + <xsl:value-of select="normalize-space( $if-missing)"/> + </xsl:attribute> + </input> + <xsl:if test="string-length( $minimum) > 0 and string-length( $maximum) > 0"> + <div style="width:200px; height:20px; background: transparent url(../images/slider-images-track-right.png) no-repeat top right;"> + <xsl:attribute name="id"> + <xsl:value-of select="concat( @name, '-track')"/> + </xsl:attribute> + <div style="position: absolute; width: 5px; height: 20px; background: transparent url(../images/slider-images-track-left.png) no-repeat top left"> + <xsl:attribute name="id"> + <xsl:value-of select="concat( @name, '-track-left')"/> + </xsl:attribute> + </div> + <div style="width:19px; height:20px;"> + <xsl:attribute name="id"> + <xsl:value-of select="concat( @name, '-slider')"/> + </xsl:attribute> + <img src="../images/slider-images-handle.png" alt="" style="float: left;" /> + </div> + </div> + <script type="text/javascript" language="javascript"> + // <![CDATA[ + new Control.Slider('<xsl:value-of select="@name"/>-slider','<xsl:value-of select="@name"/>-track',{ + onSlide:function(v){$('<xsl:value-of select="concat( 'instance_', @name)"/>').value = <xsl:value-of select="$minimum"/>+ Math.floor(v*(<xsl:value-of select="$maximum - $minimum"/>))} + }) + // ]]> + </script> + </xsl:if> + <!-- TODO: generate javascript to do client-side validation --> + </xsl:when> + <xsl:when test="option"> + <!-- if a property has options, we definitely want a select widget--> + <select> + <xsl:attribute name="id"> + <xsl:value-of select="concat( 'instance_', @name)"/> + </xsl:attribute> + <xsl:attribute name="name"> + <xsl:value-of select="concat( 'instance.', @name)"/> + </xsl:attribute> + <xsl:attribute name="title"> + <xsl:value-of select="normalize-space( $if-missing)"/> + </xsl:attribute> + <xsl:apply-templates select="option"/> + </select> + <script type="text/javascript" language="javascript"> + #set ( <xsl:value-of select="concat( '$', @name, '_sel_opt')"/>="<xsl:value-of select="concat( @name, '-$instance.', @name)"/>") + option = document.getElementById( "<xsl:value-of select="concat( '$', @name, '_sel_opt')"/>"); + + if ( option != null) + { + option.selected = true; + } + </script> + </xsl:when> + <xsl:when test="@type='boolean'"> + ${FormHelper.CheckboxField( "instance.<xsl:value-of select="@name"/>")} + </xsl:when> + <xsl:when test="@type='date'"> + <xsl:variable name="class"><xsl:if test="@required='true'">required </xsl:if>date-field validate-date</xsl:variable> + ${FormHelper.TextField( "instance.<xsl:value-of select="@name"/>", "%{class='<xsl:value-of select="$class"/>' size='10' maxlength='10'}")} + </xsl:when> + <xsl:otherwise> + <xsl:variable name="class"> + <xsl:if test="@required='true'">required </xsl:if><xsl:choose> + <xsl:when test="@type='integer'">validate-digits</xsl:when> + <xsl:when test="@type='real'">validate-number</xsl:when> + <xsl:when test="@type='money'">validate-number</xsl:when> + </xsl:choose> + </xsl:variable> + <xsl:variable name="size"> + <xsl:choose> + <xsl:when test="@size < 60"> + <xsl:value-of select="@size"/> + </xsl:when> + <xsl:when test="@type='integer'">8</xsl:when> + <xsl:when test="@type='real'">8</xsl:when> + <xsl:when test="@type='money'">8</xsl:when> + <xsl:otherwise>60</xsl:otherwise> + </xsl:choose> + </xsl:variable> + ${FormHelper.TextField( "instance.<xsl:value-of select="@name"/>", "%{class='<xsl:value-of select="$class"/>' title='<xsl:value-of select="normalize-space( $if-missing)"/>' size='<xsl:value-of select="$size"/>' maxlength='<xsl:value-of select="@size"/>'}")} + </xsl:otherwise> + </xsl:choose> + </td> + <td class="help"> + <xsl:apply-templates select="help[@locale = $locale]"/> + </td> + </tr> + </xsl:template> + + <xsl:template match="prompt"> + <xsl:value-of select="@prompt"/> + </xsl:template> + + <xsl:template match="help"> + <xsl:apply-templates/> + </xsl:template> + + <xsl:template match="option"> + <option> + <xsl:attribute name="id"><xsl:value-of select="../@name"/>-<xsl:value-of select="@value"/></xsl:attribute> + <xsl:attribute name="value"> + <xsl:value-of select="@value"/> + </xsl:attribute> + <xsl:choose> + <xsl:when test="prompt[@locale=$locale]"> + <xsl:value-of select="prompt[@locale=$locale]/@prompt"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="@value"/> + </xsl:otherwise> + </xsl:choose> + </option> + </xsl:template> + + <!-- layout of lists --> + + <xsl:template match="list"> + <xsl:variable name="action" select="@onselect"/> + <xsl:text> + </xsl:text> + <xsl:comment> [ cut here: next file '<xsl:value-of select="concat( ../@name, '/', @name)"/>.auto.vm' ] </xsl:comment> + <xsl:text> + </xsl:text> + <xsl:variable name="withpluralsuffix"> + <!-- English-laguage syntactic sugar of entity name --> + <xsl:choose> + <xsl:when test="../@name='Person'">People</xsl:when> + <xsl:when test="starts-with( substring(../@name, string-length(../@name) ), 's')"> + <xsl:value-of select="../@name"/>es + </xsl:when> + <xsl:when test="starts-with( substring(../@name, string-length(../@name) ), 'y')"> + <xsl:value-of select="substring( ../@name, 0, string-length(../@name) )"/>ies + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="../@name"/>s + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + <html> + <head> + #set( $title = "<xsl:value-of select="normalize-space( concat( 'List ', $withpluralsuffix))"/>") + <xsl:call-template name="head"/> + <xsl:comment> + Auto generated Velocity list for <xsl:value-of select="@name"/>, + generated from ADL. + + Generated using adl2listview.xsl <xsl:value-of select="$transform-revision"/> + </xsl:comment> + ${Ajax.InstallScripts()} + ${FormHelper.InstallScripts()} + ${Validation.InstallScripts()} + ${Scriptaculous.InstallScripts()} + ${DateTime.InstallScripts()} + </head> + <body> + + <xsl:call-template name="top"/> + <div class="content"> + <xsl:if test="@name='list'"> + <!-- this is a hack. There shouldn't be anything magic about a list named 'list'. + We need lists (and forms) to have some sort of pragma to guide the transformation + process --> + <div class="controls"> + <span class="pagination status"> + Showing $instances.FirstItem - $instances.LastItem of $instances.TotalItems + </span> + <span class="pagination control"> + #if($instances.HasFirst) $PaginationHelper.CreatePageLink( 1, "<<" ) #end + #if(!$instances.HasFirst) << #end + </span> + <span class="pagination control"> + #if($instances.HasPrevious) $PaginationHelper.CreatePageLink( $instances.PreviousIndex, "<" ) #end + #if(!$instances.HasPrevious) < #end + </span> + <span class="pagination control"> + #if($instances.HasNext) $PaginationHelper.CreatePageLink( $instances.NextIndex, ">" ) #end + #if(!$instances.HasNext) > #end + </span> + <span class="pagination control"> + #if($instances.HasLast) $PaginationHelper.CreatePageLink( $instances.LastIndex, ">>" ) #end + #if(!$instances.HasLast) >> #end + </span> + <xsl:if test="../form"> + <span class="add"> + <a> + <xsl:attribute name="href"> + <xsl:value-of select="concat( ../form[position() = 1]/@name, '.rails')"/> + </xsl:attribute> + Add a new <xsl:value-of select="../@name"/> + </a> + </span> + </xsl:if> + <div class="search"> + <form method="get"> + <xsl:attribute name="action"> + <xsl:value-of select="@name"/>.rails + </xsl:attribute> + <label for="searchexpr">Search:</label> + <input type="text" id="searchexpr" name="searchexpr" size="12"/> + </form> + </div> + </div> + </xsl:if> + <table> + <xsl:choose> + <xsl:when test="@properties='listed'"> + <tr> + <xsl:for-each select="field"> + <th> + <xsl:variable name="pname" select="@property"/> + <xsl:variable name="property" select="ancestor::entity/property[@name=$pname]"/> + <xsl:choose> + <xsl:when test="$property/prompt[@locale=$locale]"> + <xsl:value-of select="$property/prompt[@locale=$locale]/@prompt"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="@property"/> + </xsl:otherwise> + </xsl:choose> + </th> + </xsl:for-each> + <th>-</th> + </tr> + #foreach( $instance in $instances) + #if ( $velocityCount % 2 == 0) + #set( $oddity = "even") + #else + #set( $oddity = "odd") + #end + <tr class="$oddity"> + <xsl:for-each select="field"> + <td> + $!instance.<xsl:value-of select="@property"/> + </td> + </xsl:for-each> + <td> + <a> + <xsl:attribute name="href"> + <xsl:value-of select="concat( $action, '.rails?', ../@name, 'Id=$instance.', ../@name, 'Id')"/> + </xsl:attribute> + Edit! + </a> + </td> + </tr> + #end + </xsl:when> + <xsl:otherwise> + <tr> + <xsl:for-each select="ancestor::entity/property[@distinct='user']"> + <th> + <xsl:choose> + <xsl:when test="prompt[@locale=$locale]"> + <xsl:value-of select="prompt[@locale=$locale]/@prompt"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="@name"/> + </xsl:otherwise> + </xsl:choose> + </th> + </xsl:for-each> + <th>-</th> + </tr> + #foreach( $instance in $instances) + #if ( $velocityCount % 2 == 0) + #set( $oddity = "even") + #else + #set( $oddity = "odd") + #end + <tr class="$oddity"> + <xsl:for-each select="ancestor::entity/property[@distinct='user']"> + <td> + $!instance.<xsl:value-of select="@name"/> + </td> + </xsl:for-each> + <td> + <a> + <xsl:attribute name="href"> + <xsl:value-of select="concat( $action, '.rails?', ../@name, 'Id=$instance.', ../@name, 'Id')"/> + </xsl:attribute> + Edit! + </a> + </td> + </tr> + #end + </xsl:otherwise> + </xsl:choose> + </table> + </div> + <xsl:call-template name="foot"/> + </body> + </html> + </xsl:template> + + <!-- overall page layout --> + + <xsl:template name="head"> + <xsl:choose> + <xsl:when test="head"> + <xsl:apply-templates select="head/*"/> + </xsl:when> + <xsl:otherwise> + <xsl:apply-templates select="/application/content/head/*"/> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="top"> + <xsl:choose> + <xsl:when test="top"> + <xsl:apply-templates select="top/*"/> + </xsl:when> + <xsl:otherwise> + <xsl:apply-templates select="/application/content/top/*"/> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="foot"> + <xsl:choose> + <xsl:when test="foot"> + <xsl:apply-templates select="foot/*"/> + </xsl:when> + <xsl:otherwise> + <xsl:apply-templates select="/application/content/foot/*"/> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- if this node (default to current node) has a child of type prompt for the current locale, + show that prompt; else show the first prompt child with locale='default' if any; + else show the value of the fallback param --> + <xsl:template name="showprompt"> + <xsl:param name="fallback" select="Unknown"/> + <xsl:param name="node" select="."/> + <xsl:choose> + <xsl:when test="$node/prompt[@locale=$locale]"> + <xsl:value-of select="$node/prompt[@locale=$locale][1]/@prompt"/> + </xsl:when> + <xsl:when test="$node/prompt[@locale='default']"> + <xsl:value-of select="$node/prompt[@locale='default'][1]/@prompt"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$fallback"/> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- just copy anything we can't match --> + <xsl:template match="@* | node()"> + <xsl:copy> + <xsl:apply-templates select="@* | node()"/> + </xsl:copy> + </xsl:template> + +</xsl:stylesheet> \ No newline at end of file diff --git a/ADL.NET/Trans/datadescriber.xsl b/ADL.NET/Trans/datadescriber.xsl new file mode 100755 index 0000000..8b1d8dd --- /dev/null +++ b/ADL.NET/Trans/datadescriber.xsl @@ -0,0 +1,426 @@ +<?xml version="1.0" encoding="utf-8" ?> + +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + <xsl:output encoding="utf-8" method="html" indent="yes" /> + + <xsl:param name="locale" select="en-UK"/> + + <xsl:template match="application"> + <html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <title> + Data definition for the <xsl:value-of select="@name"/> application + version <xsl:value-of select="@version"/> + </title> + <link href="styles/default.css" rel="stylesheet" type="text/css" /> + </head> + <body> + <h1> + Data definition for the <xsl:value-of select="@name"/> application version <xsl:value-of select="@version"/> + </h1> + <xsl:apply-templates select="documentation"/> + + <xsl:for-each select="entity"> + <h2> + <xsl:value-of select="@name" /> + </h2> + <xsl:apply-templates select="documentation"/> + <dl> + <xsl:for-each select="permission"> + <dt> + Group: + <xsl:value-of select="@group"/> + </dt> + <dd> + Permissions: + <xsl:value-of select="@permission"/> + </dd> + </xsl:for-each> + </dl> + <table> + <tr class="header"> + <th class="white">Property</th> + <th class="white">Type</th> + <th class="white">Req'd</th> + <th class="white">Def'lt</th> + <th class="white">Size</th> + <th class="white">Distinct</th> + <th class="white">Prompt</th> + </tr> + <xsl:for-each select="property" > + <tr> + <xsl:attribute name="class"> + <xsl:choose> + <xsl:when test="position() mod 2 = 0">even</xsl:when> + <xsl:otherwise>odd</xsl:otherwise> + </xsl:choose> + </xsl:attribute> + <td> + <xsl:value-of select="@name"/>  + </td> + <td> + <xsl:value-of select="@type"/> + <xsl:if test="@type='entity'"> + of type <xsl:value-of select="@entity"/> + </xsl:if> + <xsl:if test="@definition"> + : + <xsl:variable name="definition"> + <xsl:value-of select="@definition"/> + </xsl:variable> + <xsl:variable name="defined-type"> + <xsl:value-of select="/application/definition[@name=$definition]/@type"/> + </xsl:variable> + <xsl:choose> + <xsl:when test="$defined-type = 'string'"> + String matching + "<xsl:value-of select="/application/definition[@name=$definition]/@pattern"/>" + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="/application/definition[@name=$definition]/@minimum"/> < + <xsl:value-of select="@definition"/> < + <xsl:value-of select="/application/definition[@name=$definition]/@maximum"/> + </xsl:otherwise> + </xsl:choose> + </xsl:if> +   + </td> + <td> + <xsl:value-of select="@required"/>  + </td> + <td> + <xsl:value-of select="@default"/>  + </td> + <td> + <xsl:value-of select="@size"/>  + </td> + <td> + <xsl:value-of select="@distinct"/>  + </td> + <td> + <xsl:for-each select="prompt"> + <xsl:apply-templates select="@prompt"/>  + </xsl:for-each> + </td> + </tr> + <xsl:if test="help"> + <tr> + <td> + <xsl:apply-templates select="help"/>  + </td> + </tr> + </xsl:if> + <xsl:if test="documentation"> + <tr> + <td> + <xsl:apply-templates select="help"/>  + </td> + </tr> + </xsl:if> + </xsl:for-each> + </table> + </xsl:for-each> + <xsl:apply-templates select="form"/> + <xsl:apply-templates select="list"/> + <xsl:apply-templates select="page"/> + </body> + </html> + </xsl:template> + + <xsl:template match="prompt"> + <!-- If I'm the prompt for the current locale, show me; + if I'm the default prompt, show me only if there isn't + one for the default locale --> + <xsl:choose> + <xsl:when test="@locale=$locale"> + <xsl:value-of select="@prompt"/> + </xsl:when> + <xsl:when test="@locale='default'"> + <xsl:choose> + <xsl:when test="../prompt[@locale=$locale]"/> + <xsl:otherwise> + <xsl:value-of select="@prompt"/> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + </xsl:choose> + </xsl:template> + + <xsl:template match="help"> + <!-- If I'm the helptext for the current locale, show me; + if I'm the default helptext, show me only if there isn't + one for the default locale --> + <xsl:choose> + <xsl:when test="@locale=$locale"> + <xsl:apply-templates/> + </xsl:when> + <xsl:when test="@locale='default'"> + <xsl:choose> + <xsl:when test="../help[@locale=$locale]"/> + <xsl:otherwise> + <xsl:apply-templates/> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + </xsl:choose> + </xsl:template> + + <xsl:template match="documentation"> + <div xmlns="http://www.w3.org/1999/xhtml" class="documentation"> + <xsl:apply-templates /> + </div> + </xsl:template> + + <xsl:template match="form"> + <div xmlns="http://www.w3.org/1999/xhtml"> + <h3 xmlns="http://www.w3.org/1999/xhtml"> + Form <xsl:value-of select="@name"/> + </h3> + <xsl:if test="permission"> + <h4 xmlns="http://www.w3.org/1999/xhtml">Permissions</h4> + <ul xmlns="http://www.w3.org/1999/xhtml"> + <xsl:apply-templates select="permission"/> + </ul> + </xsl:if> + <xsl:choose> + <xsl:when test="@properties='listed'"> + <p>Showing the following properties</p> + <table xmlns="http://www.w3.org/1999/xhtml"> + <tr> + <th> </th> + <th>Property</th> + <th>Prompt</th> + <th>Documentation</th> + </tr> + <xsl:apply-templates select="field|fieldgroup|auxlist|verb"/> + </table> + </xsl:when> + <xsl:otherwise> + <p>Showing all properties</p> + </xsl:otherwise> + </xsl:choose> + </div> + </xsl:template> + + <xsl:template match="page"> + <div xmlns="http://www.w3.org/1999/xhtml"> + <h3 xmlns="http://www.w3.org/1999/xhtml"> + Page <xsl:value-of select="@name"/> + </h3> + <xsl:if test="permission"> + <ul xmlns="http://www.w3.org/1999/xhtml"> + <xsl:apply-templates select="permission"/> + </ul> + </xsl:if> + <xsl:choose> + <xsl:when test="@properties='listed'"> + <p>Showing the following properties</p> + <table xmlns="http://www.w3.org/1999/xhtml"> + <tr> + <th> </th> + <th>Property</th> + <th>Prompt</th> + <th>Documentation</th> + </tr> + <xsl:apply-templates select="field|fieldgroup|auxlist|verb"/> + </table> + </xsl:when> + <xsl:otherwise> + <p>Showing all properties</p> + </xsl:otherwise> + </xsl:choose> + </div> + </xsl:template> + + <xsl:template match="list"> + <div xmlns="http://www.w3.org/1999/xhtml"> + <h3 xmlns="http://www.w3.org/1999/xhtml"> + List <xsl:value-of select="@name"/>, on select <xsl:value-of select="onselect"/> + </h3> + <xsl:if test="permission"> + <ul xmlns="http://www.w3.org/1999/xhtml"> + <xsl:apply-templates select="permission"/> + </ul> + </xsl:if> + <xsl:choose> + <xsl:when test="@properties='listed'"> + <p>Showing the following properties</p> + <table xmlns="http://www.w3.org/1999/xhtml"> + <tr> + <th> </th> + <th>Property</th> + <th>Prompt</th> + <th>Documentation</th> + </tr> + <xsl:apply-templates select="field|fieldgroup|auxlist|verb"/> + </table> + </xsl:when> + <xsl:otherwise> + <p>Showing all properties</p> + </xsl:otherwise> + </xsl:choose> + </div> + </xsl:template> + + <xsl:template match="field"> + <tr xmlns="http://www.w3.org/1999/xhtml"> + <xsl:attribute name="class"> + <xsl:choose> + <xsl:when test="parent::fieldgroup"> + <xsl:choose> + <xsl:when test="position() = last()">fieldgroup-end</xsl:when> + <xsl:otherwise>fieldgroup</xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:when test="parent::auxlist"> + <xsl:choose> + <xsl:when test="position() = last()">auxlist-end</xsl:when> + <xsl:otherwise>auxlist</xsl:otherwise> + </xsl:choose> + </xsl:when> + </xsl:choose> + </xsl:attribute> + <td>Field</td> + <td> + <xsl:value-of select="@property"/> + </td> + <td> + <xsl:apply-templates select="prompt"/> + </td> + <td> + <xsl:apply-templates select="help"/> + </td> + <td> + <xsl:apply-templates select="documentation"/> + </td> + </tr> + <xsl:if test="permission"> + <tr xmlns="http://www.w3.org/1999/xhtml"> + <td></td> + <td colspan="3"> + <xsl:apply-templates select="permission"/> + </td> + </tr> + </xsl:if> + </xsl:template> + + + <xsl:template match="verb"> + <tr xmlns="http://www.w3.org/1999/xhtml"> + <xsl:attribute name="class"> + <xsl:choose> + <xsl:when test="parent::fieldgroup"> + <xsl:choose> + <xsl:when test="position() = last()">fieldgroup-end</xsl:when> + <xsl:otherwise>fieldgroup</xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:when test="parent::auxlist"> + <xsl:choose> + <xsl:when test="position() = last()">auxlist-end</xsl:when> + <xsl:otherwise>auxlist</xsl:otherwise> + </xsl:choose> + </xsl:when> + </xsl:choose> + </xsl:attribute> + <td>Verb</td> + <td> + <xsl:value-of select="@verb"/> + <xsl:if test="@dangerous='true'">[dangerous]</xsl:if> + </td> + <td> + <xsl:apply-templates select="prompt"/> + </td> + <td> + <xsl:apply-templates select="help"/> + </td> + <td> + <xsl:apply-templates select="documentation"/> + </td> + </tr> + <xsl:if test="permission"> + <tr xmlns="http://www.w3.org/1999/xhtml"> + <td></td> + <td colspan="3"> + <xsl:apply-templates select="permission"/> + </td> + </tr> + </xsl:if> + </xsl:template> + + + + <xsl:template match="auxlist"> + <tr xmlns="http://www.w3.org/1999/xhtml" class="auxlist-start"> + <th>Auxlist</th> + <th> + <xsl:value-of select="@property"/> + </th> + <th> + <xsl:apply-templates select="prompt"/> + </th> + <th> + <xsl:apply-templates select="help"/> + </th> + <th> + <xsl:apply-templates select="documentation"/> + </th> + </tr> + <tr xmlns="http://www.w3.org/1999/xhtml" class="auxlist"> + <th>On select:</th> + <td> + <xsl:value-of select="@onselect"/> + </td> + <td colspan="2"> + <xsl:choose> + <xsl:when test="@properties='listed'"> + Showing the following properties + </xsl:when> + <xsl:otherwise> + Showing all properties + </xsl:otherwise> + </xsl:choose> + </td> + </tr> + <xsl:apply-templates select="field|fieldgroup|auxlist|verb"/> + </xsl:template> + + <xsl:template match="fieldgroup"> + <tr xmlns="http://www.w3.org/1999/xhtml" class="fieldgroup-start"> + <th>Auxlist</th> + <th> + <xsl:value-of select="@name"/> + </th> + <th> + <xsl:apply-templates select="prompt"/> + </th> + <th> + <xsl:apply-templates select="help"/> + </th> + <th> + <xsl:apply-templates select="documentation"/> + </th> + </tr> + <tr xmlns="http://www.w3.org/1999/xhtml" class="auxlist"> + <th>On select:</th> + <td> + <xsl:value-of select="@onselect"/> + </td> + <td colspan="2"> + <xsl:choose> + <xsl:when test="@properties='listed'"> + Showing the following properties + </xsl:when> + <xsl:otherwise> + Showing all properties + </xsl:otherwise> + </xsl:choose> + </td> + </tr> + <xsl:apply-templates select="field|fieldgroup|auxlist|verb"/> + </xsl:template> + + + + +</xsl:stylesheet> diff --git a/ADL.NET/Trans/hibernate2adl.xsl b/ADL.NET/Trans/hibernate2adl.xsl new file mode 100755 index 0000000..90f1b7d --- /dev/null +++ b/ADL.NET/Trans/hibernate2adl.xsl @@ -0,0 +1,100 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="urn:nhibernate-mapping-2.2"> + <!-- + Application Description Framework + hibernate2adl.xsl + + (c) 2007 Cygnet Solutions Ltd + + Transforms hibernate mapping file into partial ADL file. Not complete, + because the whole point of having an ADL is that the hibernate mapping + is not sufficiently rich. + + $Author: af $ + $Revision: 1.1 $ + --> + + <xsl:output indent="yes" method="xml" encoding="utf-8" doctype-system="file:../j2adl.dtd"/> + + <xsl:template match="hibernate-mapping"> + <application name="unset" version="unset"> + <xsl:apply-templates select="class"/> + </application> + </xsl:template> + + <xsl:template match="class"> + <entity> + <xsl:attribute name="name"> + <xsl:value-of select="@name"/> + </xsl:attribute> + <xsl:apply-templates/> + </entity> + </xsl:template> + + <xsl:template match="property"> + <property> + <xsl:attribute name="name"> + <xsl:value-of select="@name"/> + </xsl:attribute> + <xsl:attribute name="type"> + <xsl:choose> + <xsl:when test="@type = 'DateTime'">date</xsl:when> + <xsl:when test="@type = 'String'">string</xsl:when> + <xsl:when test="@type = 'bool'">boolean</xsl:when> + <xsl:when test="@type = 'TimeStamp'">timestamp</xsl:when> + <xsl:when test="@type = 'int'">integer</xsl:when> + <xsl:otherwise>[unknown?]</xsl:otherwise> + </xsl:choose> + </xsl:attribute> + <xsl:attribute name="required"> + <xsl:choose> + <xsl:when test="@not-null = 'true'">true</xsl:when> + <xsl:otherwise>false</xsl:otherwise> + </xsl:choose> + </xsl:attribute> + <xsl:attribute name="size"> + <xsl:value-of select="@length"/> + </xsl:attribute> + </property> + + </xsl:template> + + <xsl:template match="id"> + <property distinct="system" required="true"> + <xsl:attribute name="name"> + <xsl:value-of select="@name"/> + </xsl:attribute> + <xsl:attribute name="type"> + <xsl:choose> + <xsl:when test="@type = 'DateTime'">date</xsl:when> + <xsl:when test="@type = 'String'">string</xsl:when> + <xsl:when test="@type = 'bool'">boolean</xsl:when> + <xsl:when test="@type = 'TimeStamp'">timestamp</xsl:when> + <xsl:when test="@type = 'int'">integer</xsl:when> + <xsl:otherwise>[unknown?]</xsl:otherwise> + </xsl:choose> + </xsl:attribute> + <xsl:attribute name="size"> + <xsl:value-of select="@length"/> + </xsl:attribute> + </property> + </xsl:template> + + <xsl:template match="many-to-one"> + <property type="entity"> + <xsl:attribute name="name"> + <xsl:value-of select="@name"/> + </xsl:attribute> + <xsl:attribute name="entity"> + <xsl:value-of select="@class"/> + </xsl:attribute> + </property> + </xsl:template> + + <xsl:template match="@* | node()"> + <xsl:copy> + <xsl:apply-templates select="@* | node()"/> + </xsl:copy> + + </xsl:template> +</xsl:stylesheet> \ No newline at end of file