<?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-31 12:34:21 $
  -->

  <!-- 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:a="http://cygnets.co.uk/schemas/adl-1.2"
  xmlns:msxsl="urn:schemas-microsoft-com:xslt">

  <xsl:import href="types.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="lang" 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="a:application">
    <xsl:apply-templates select="a:entity"/>
  </xsl:template>

  <xsl:template match="a: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="a:key/a:property" />

/* ---- [ 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 Cygnet.Entities;
    using Cygnet.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 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:for-each select="$keynames">
              result.Append(<xsl:value-of select="@name"/><xsl:if test="@type='entity'">.KeyString</xsl:if>);
              <xsl:if test="position()!=last()">
                result.Append('|');
              </xsl:if>
            </xsl:for-each>
            return result.ToString();
          </xsl: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="a:key/a:property">
            <xsl:for-each select="a:key/a:property">
              result.Append(<xsl:value-of select="@name"/><xsl:if test="@type='entity'">.UserIdentifier</xsl:if>);
              <xsl:if test="position() != last()">
                result.Append( ", ");
              </xsl:if>
            </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="a:key/a:property|a:property|a:set"/>
    }
    }


  </xsl:template>

  <!-- Creates a comma-separated list of all the properties passed in, or all the key properties by default. -->
  <xsl:template name="list-properties">
    <xsl:param name="props" select="a:key/a:property"/>
    <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="a:property[@concrete='false']">
    <!-- generate nothing for non-concrete properties -->
  </xsl:template>

  <xsl:template match="a:property">
    // auto generating iv/property pair for slot with name <xsl:value-of select="@name"/>
    <xsl:apply-templates select="a:help"/>

    <xsl:variable name="type-nullable">
      <xsl:choose>
        <xsl:when test="@type='link' or @type='list' or @type='entity'">true</xsl:when>
        <xsl:otherwise>
          <xsl:call-template name="type-nullable">
          </xsl:call-template>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <xsl:variable name="type">
      <xsl:choose>
        <xsl:when test="@type = 'link'">
          ICollection&lt;<xsl:value-of select="@entity"/>&gt;
        </xsl:when>
        <xsl:when test="@type = 'list'">
          ICollection&lt;<xsl:value-of select="@entity"/>&gt;
        </xsl:when>
        <xsl:when test="@type = 'entity'">
          <xsl:value-of select="@entity"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:call-template name="type-declarator">
            <xsl:with-param name="nullable" select="@not-null!='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:if test="not(@type='link' or @type='list' or @type='entity')">
        <xsl:call-template name="type-attr">
          <xsl:with-param name="attr" select="'pattern'" />
        </xsl:call-template>
      </xsl:if>
    </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="@not-null='true' and $type-nullable='true'">
      if ( value == null)
      {
      throw new DataRequiredException( <xsl:choose>
        <xsl:when test="ifmissing[@locale=$lang]">
          <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="not(@type='link' or @type='list' or @type='entity')">
      <xsl:variable name="maximum">
        <xsl:call-template name="type-attr">
          <xsl:with-param name="attr" select="'maximum'" />
        </xsl:call-template>
      </xsl:variable>
      <xsl:variable name="minimum">
        <xsl:call-template name="type-attr">
          <xsl:with-param name="attr" select="'minimum'" />
        </xsl:call-template>
      </xsl:variable>
      <xsl:if test="string-length( $maximum) &gt; 0">
        if ( value &gt; <xsl:value-of select="$maximum"/>)
        {
        throw new DataRangeException( "The maximum permitted value for <xsl:value-of select="@name"/> is <xsl:value-of select="$maximum"/>");
        }
      </xsl:if>
      <xsl:if test="string-length( $minimum) &gt; 0">
        if ( value &lt; <xsl:value-of select="$minimum"/>)
        {
        throw new DataRangeException( "The minimum permitted value for <xsl:value-of select="@name"/> is <xsl:value-of select="$minimum"/>");
        }
      </xsl:if>
      <xsl:if  test="string-length( $validationpattern) &gt; 0">
        if ( value != null &amp;&amp; ! <xsl:value-of select="@name"/>Validator.IsMatch( value))
        {
        throw new DataFormatException( string.Format( "The value supplied ({0}) does not match the format required by <xsl:value-of select="@name"/>", value));
        }
      </xsl:if>
    </xsl:if>
    <xsl:if test="@size and $type='String'">
      if ( value != null &amp;&amp; value.Length > <xsl:value-of select="@size"/>)
      {
      value = value.Substring( 0, <xsl:value-of select="@size"/>);
      }
    </xsl:if>
    _<xsl:value-of select="@name"/> = value;
    }
    }

  </xsl:template>

  <xsl:template match="a:set[a:many-to-many]">
    // auto generating for set with name <xsl:value-of select="@name"/>, having many-to-many child
    private ICollection&lt;<xsl:value-of 
            select="a:many-to-many/@entity"/>&gt;<xsl:text> </xsl:text>_<xsl:value-of select="@name"/>;

    public virtual ICollection&lt;<xsl:value-of select="a:many-to-many/@entity"/>&gt; <xsl:value-of select="@name"/>
    {
    get { return _<xsl:value-of select="@name"/>; }
    set { _<xsl:value-of select="@name"/> = value; }
    }

  </xsl:template>

  <xsl:template match="a:set[a:one-to-many]">
    // auto generating for set with name <xsl:value-of select="@name"/>, having one-to-many child
    private ICollection&lt;<xsl:value-of 
            select="a:one-to-many/@entity"/>&gt;<xsl:text> </xsl:text>_<xsl:value-of select="@name"/>;

    public virtual ICollection&lt;<xsl:value-of select="a:one-to-many/@entity"/>&gt; <xsl:value-of select="@name"/>
    {
    get { return _<xsl:value-of select="@name"/>; }
    set { _<xsl:value-of select="@name"/> = value; }
    }

  </xsl:template>




  <xsl:template name="type-declarator">
    <xsl:param name="nullable" select="false()"/>
    <xsl:call-template name="type-attr">
      <xsl:with-param name="attr" select="'dotnet'"/>
    </xsl:call-template>
    <xsl:variable name="kind">
      <xsl:call-template name="type-attr">
        <xsl:with-param name="attr" select="'dotnet-kind'"/>
      </xsl:call-template>
    </xsl:variable>
    <xsl:if test="$nullable and $kind='value'">?</xsl:if>
  </xsl:template>

  <xsl:template name="type-nullable">
    <xsl:variable name="kind">
      <xsl:call-template name="type-attr">
        <xsl:with-param name="attr" select="'dotnet-kind'"/>
      </xsl:call-template>
    </xsl:variable>
    <xsl:if test="$kind!='value'">true</xsl:if>
  </xsl:template>
  

  <xsl:template match="help">
    <xsl:if test="@lang=$lang">
      <!-- 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="@lang=$lang">
                  "<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>