adl/ADL.NET/Trans/adl2entityclass.xsl
af 9b6fd82110 Refinements of the ADL transforms to have them better work with more than just the
SRU codebase.

Note that synthetic primary key is now assumed to be 'Id'.... though actually most
 of the references to an entity's primary key should be looking it up rather than
 assuming its name.
2008-01-14 16:53:31 +00:00

462 lines
16 KiB
XML
Executable file

<?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.2 $
$Date: 2008-01-14 16:53:31 $
-->
<!-- WARNING WARNING WARNING: Do NOT reformat this file!
Whitespace (or lack of it) is significant! -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<xsl:output encoding="UTF-8" method="text"/>
<!-- The locale for which these entities are generated
TODO: Entities should NOT be locale specific. Instead, the
entity should generate messages based on the
client's locale. However, there may still need to be a concept of a
'default locale', for when we don't have messages which suit the
client's locale -->
<xsl:param name="locale" select="en-UK"/>
<!-- The C# namespace within which I shall generate controllers -->
<xsl:param name="controllerns" select="Unset"/>
<!-- The C# namespace within which I shall generate entities -->
<xsl:param name="entityns" select="Unset"/>
<xsl:template match="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.2 $', 11)"/>
<xsl:variable name="transform-revision"
select="substring( $transform-rev1, 0, string-length( $transform-rev1) - 1)"/>
<xsl:variable name="keynames" select="property[@distinct='system']" />
/* ---- [ 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.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using ADL.Entities;
using ADL.Exceptions;
using Iesi.Collections.Generic;
/// &lt;summary&gt;
/// Automatically generated from description of entity <xsl:value-of select="@name"/>
/// using adl2entityclass.xsl. Note that manually maintained parts of this
/// class may be defined in a separate file called <xsl:value-of select="@name"/>.cs, q.v.
///
/// DO NOT EDIT THIS FILE!
/// &lt;/summary&gt;
public partial class <xsl:value-of select="@name"/> : Entity
{
/// &lt;summary&gt;
/// Auto-generated no-args constructor; does nothing (but probably should
/// ensure ID slot is initialised correctly)
/// &lt;/summary&gt;
public <xsl:value-of select="@name"/>() : base(){
<xsl:call-template name="initialise-lists"/>
}
/*
/// &lt;summary&gt;
/// Auto-generated one-arg constructor; initialises Id slot and also all
/// one-to-many slots
/// &lt;/summary&gt;
public <xsl:value-of select="@name"/>( int key)
{
<xsl:call-template name="initialise-lists"/>
<!--xsl:choose>
<xsl:when test="@natural-key">
/* natural primary key exists - not initialising abstract key */
</xsl:when>
<xsl:otherwise>
_Id = key;
</xsl:otherwise>
</xsl:choose-->
}
*/
<!--xsl:choose>
<xsl:when test="@natural-key">
/* natural primary key exists - not generating abstract key */
</xsl:when>
<xsl:otherwise>
/// &lt;summary&gt;
/// Auto-generated iv/property for Id slot
/// &lt;/summary&gt;
private int _Id = -1;
public virtual int Id
{
get { return _Id; }
set { _Id = value; }
}
/// &lt;summary&gt;
/// Auto-generated overridden property for the Key slot, maps onto
/// _Id
/// &lt;/summary&gt;
public override int Key
{
get { return _Id; }
}
</xsl:otherwise>
</xsl:choose-->
/// &lt;summary&gt;
/// Auto-generated overridden property for the Key slot, maps onto
/// &lt;/summary&gt;
public override string KeyString {
get {
<xsl:choose>
<xsl:when test="count($keynames)=0">
return null; // No primary key; return null.
</xsl:when>
<xsl:when test="count($keynames)=1">
return <xsl:value-of select="$keynames[1]/@name"/>.ToString(); // Single key.
</xsl:when>
<xsl:otherwise>
StringBuilder result = new StringBuilder(<xsl:value-of select="$keynames[1]/@name"/>);
<xsl:for-each select="$keynames[position() != 1]">
result.Append('|');
result.Append(<xsl:value-of select="@name"/>);
</xsl:for-each>
return result.ToString();
</xsl:otherwise>
</xsl:choose>
}
}
/// &lt;summary&gt;
/// A user readable distinct identifying string
/// &lt;/summary&gt;
public override string UserIdentifier
{
get {
StringBuilder result = new StringBuilder();
<xsl:choose>
<xsl:when test="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:call-template name="list-properties"/>);
</xsl:otherwise>
</xsl:choose>
return result.ToString();
}
}
<xsl:apply-templates select="property"/>
}
}
</xsl:template>
<xsl:template name="list-properties">
<xsl:param name="props" select="property[@distinct='system']"/>
<xsl:if test="count($props)!=0">
<xsl:value-of select="$props[1]/@name"/>
<xsl:if test="count($props)!=1">, </xsl:if>
<xsl:call-template name="list-properties">
<xsl:with-param name="props" select="$props[position()!=1]"/>
</xsl:call-template>
</xsl:if>
</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-nullable">
<xsl:choose>
<xsl:when test="@type='defined'">
<xsl:call-template name="type-nullable">
<xsl:with-param name="typename" select="$defined-type"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="@type!='link' and @type!='list' and @type!='entity'">
<xsl:call-template name="type-nullable">
<xsl:with-param name="typename" select="@type"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>true</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="type">
<xsl:choose>
<xsl:when test="@type='defined'">
<!-- Find the right definition, then map its type onto a C# type -->
<xsl:call-template name="type-declarator">
<xsl:with-param name="typename" select="$defined-type"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="@type = 'link'">
ICollection&lt;<xsl:value-of select="@entity"/>&gt;
</xsl:when>
<xsl:when test="@type = 'list'">
ICollection&lt;<xsl:value-of select="@entity"/>&gt;
</xsl:when>
<xsl:when test="@type = 'entity'">
<xsl:value-of select="@entity"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="type-declarator">
<xsl:with-param name="typename" select="@type"/>
<xsl:with-param name="nullable" select="@required!='true'"/>
</xsl:call-template>
</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:choose>
</xsl:variable>
<xsl:variable name="validationpattern">
<xsl:choose>
<xsl:when test="@type='defined'">
<xsl:variable name="definition">
<xsl:value-of select="@definition"/>
</xsl:variable>
<xsl:value-of select="/application/definition[@name=$definition]/@pattern"/>
</xsl:when>
</xsl:choose>
</xsl:variable>
<xsl:if test="string-length( $validationpattern) &gt; 0">
private Regex <xsl:value-of select="@name"/>Validator = new Regex( "<xsl:value-of select="$validationpattern"/>");
</xsl:if>
private <xsl:value-of select="$type"/> _<xsl:value-of select="@name"/> <xsl:value-of select="$initialiser"/>;
public virtual <xsl:value-of select="$type"/><xsl:text> </xsl:text> <xsl:value-of select="@name"/>
{
get { return _<xsl:value-of select="@name"/>; }
set {
<xsl:if test="@required='true' and $type-nullable='true'">
if ( value == null)
{
throw new DataRequiredException( <xsl:choose>
<xsl:when test="ifmissing[@locale=$locale]">
<xsl:apply-templates select="ifmissing"/>
</xsl:when>
<xsl:otherwise>
"The value for <xsl:value-of select="@name"/> may not be set to null"
</xsl:otherwise>
</xsl:choose>
);
}
</xsl:if>
<xsl:if test="@type='defined'">
<xsl:variable name="definition">
<xsl:value-of select="@definition"/>
</xsl:variable>
<xsl:variable name="maximum">
<xsl:value-of select="/application/definition[@name=$definition]/@maximum"/>
</xsl:variable>
<xsl:variable name="minimum">
<xsl:value-of select="/application/definition[@name=$definition]/@minimum"/>
</xsl:variable>
<xsl:if test="string-length( $maximum) &gt; 0">
if ( value &gt; <xsl:value-of select="$maximum"/>)
{
throw new DataRangeException( "The maximum permitted value for <xsl:value-of select="@name"/> is <xsl:value-of select="$maximum"/>");
}
</xsl:if>
<xsl:if test="string-length( $minimum) &gt; 0">
if ( value &lt; <xsl:value-of select="$minimum"/>)
{
throw new DataRangeException( "The minimum permitted value for <xsl:value-of select="@name"/> is <xsl:value-of select="$minimum"/>");
}
</xsl:if>
<xsl:if test="string-length( $validationpattern) &gt; 0">
if ( value != null &amp;&amp; ! <xsl:value-of select="@name"/>Validator.IsMatch( value))
{
throw new DataFormatException( string.Format( "The value supplied ({0}) does not match the format required by <xsl:value-of select="@name"/>", value));
}
</xsl:if>
</xsl:if>
<xsl:if test="@size and $type='String'">
if ( value != null &amp;&amp; value.Length > <xsl:value-of select="@size"/>)
{
value = value.Substring( 0, <xsl:value-of select="@size"/>);
}
</xsl:if>
_<xsl:value-of select="@name"/> = value;
}
}
</xsl:template>
<xsl:template name="type-declarator">
<xsl:param name="typename"/>
<xsl:param name="nullable" select="false()"/>
<xsl:variable name="override-type" select="document('types.xml',/application)/types/type[@name=$typename]"/>
<xsl:variable name="type0">
<xsl:choose>
<xsl:when test="$override-type">
<xsl:copy-of select="$override-type"/>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="document('types.xml')/types/type[@name=$typename]"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="type" select="msxsl:node-set($type0)/type"/>
<xsl:choose>
<xsl:when test="$type">
<xsl:value-of select="$type/@dotnet" />
<xsl:if test="$nullable and $type/@dotnet-kind='value'">?</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:message terminate="yes">
Error! <xsl:value-of select="$typename"/> not found.
</xsl:message>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="type-nullable">
<xsl:param name="typename"/>
<xsl:variable name="override-type" select="document('types.xml',/application)/types/type[@name=$typename]"/>
<xsl:variable name="type0">
<xsl:choose>
<xsl:when test="$override-type">
<xsl:copy-of select="$override-type"/>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="document('types.xml')/types/type[@name=$typename]"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="type" select="msxsl:node-set($type0)/type"/>
<xsl:choose>
<xsl:when test="$type">
<xsl:if test="$type/@dotnet-kind!='value'">true</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:message terminate="yes">
Error! <xsl:value-of select="$typename"/> not found.
</xsl:message>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="help">
<xsl:if test="@locale=$locale">
<!-- might conceivably be more than one line -->
<xsl:text>
/* </xsl:text><xsl:apply-templates/> */
</xsl:if>
</xsl:template>
<xsl:template match="ifmissing">
<xsl:if test="@locale=$locale">
"<xsl:value-of select="normalize-space(.)"/>"
</xsl:if>
</xsl:template>
<xsl:template name="initialise-lists">
<!-- initialise all cocrete lists and links -->
<xsl:for-each select="property[@type='list']">
<xsl:choose>
<xsl:when test="@concrete='false'"/>
<xsl:otherwise>
_<xsl:value-of select="@name"/> = new HashedSet&lt;<xsl:value-of select="@entity"/>&gt;();
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<xsl:for-each select="property[@type='link']">
<xsl:choose>
<xsl:when test="@concrete='false'"/>
<xsl:otherwise>
_<xsl:value-of select="@name"/> = new HashedSet&lt;<xsl:value-of select="@entity"/>&gt;();
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>