(1) when generating constructors, generate a reverence for the StylesHelper, as it is used in views we generate. (2) when generating lists, don't layout columns whose contents are themselves lists.
1232 lines
49 KiB
HTML
Executable file
1232 lines
49 KiB
HTML
Executable file
<?xml version="1.0" encoding="UTF-8"?>
|
|
|
|
<!--
|
|
Application Description Language framework
|
|
adl2controllerclasses.xsl
|
|
|
|
(c) 2007 Cygnet Solutions Ltd
|
|
|
|
Transform ADL into (partial) controller classes
|
|
|
|
$Author: sb $
|
|
$Revision: 1.23 $
|
|
$Date: 2009-01-28 12:10:02 $
|
|
-->
|
|
|
|
<!-- WARNING WARNING WARNING: Do NOT reformat this file!
|
|
Whitespace (or lack of it) is significant! -->
|
|
<xsl:stylesheet version="1.0"
|
|
xmlns="http://libs.cygnets.co.uk/adl/1.1/"
|
|
xmlns:adl="http://libs.cygnets.co.uk/adl/1.1/"
|
|
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
|
|
<xsl:include href="csharp-type-include.xslt"/>
|
|
|
|
<xsl:output encoding="UTF-8" method="text"/>
|
|
|
|
<!-- The locale for which these controllers are generated
|
|
TODO: Controllers should NOT be locale specific. Instead, the
|
|
controller should render views and generate messages based on the
|
|
client's locale. However, there may still need to be a concept of a
|
|
'default locale', for when we don't have messages which suit the
|
|
client's locale -->
|
|
<xsl:param name="locale" select="en-UK"/>
|
|
|
|
<!-- bug 1896 : boilerplate text in views should be tailored to the locale of
|
|
the expected user. Unfortunately I haven't yet worked out how to do
|
|
conditional includes in XSLT, so this is a step on the way to a solution,
|
|
not a solution in itself. -->
|
|
<xsl:include href="i18n-en-GB-include.xslt"/>
|
|
|
|
<!-- The C# namespace within which I shall generate controllers -->
|
|
<xsl:param name="controllerns" select="Unset"/>
|
|
<!-- The C# namespace used by the entities for this project -->
|
|
<xsl:param name="entityns" select="Unset"/>
|
|
<!-- Whether to authenticate at application or at database layer.
|
|
If not 'Application', then 'Database'. -->
|
|
<xsl:param name="authentication-layer" select="Application"/>
|
|
|
|
<!-- the name and version of the product being built -->
|
|
<xsl:param name="product-version" select="'Application Description Language Framework'"/>
|
|
|
|
<!-- bug 1800 : the name of the Velocity layout to use -->
|
|
<xsl:param name="layout-name" select="adl-default-layout"/>
|
|
<!-- bug 1800 : the name of the Velocity rescue view to use -->
|
|
<xsl:param name="rescue-name"/>
|
|
<!-- bug 1800 : the name of the area (i.e. URL path part) to use -->
|
|
<xsl:param name="area-name"/>
|
|
|
|
<xsl:template match="adl:application">
|
|
/* ---- [ cut here: next file '<xsl:value-of select="concat( 'Abstract', /adl:application/@name, 'Controller')"/>.auto.cs'] ---------------- */
|
|
//------------------------------------------------------------------
|
|
//
|
|
// <xsl:value-of select="$product-version"/>
|
|
// <xsl:value-of select="concat( 'Abstract', /adl:application/@name, 'Controller.auto.cs')"/>
|
|
//
|
|
// (c) 2007 Cygnet Solutions Ltd
|
|
//
|
|
// Automatically generated abstract super class for controllers for the
|
|
// <xsl:value-of select="/adl:application/@name"/> application; generated using
|
|
// adl2controllerclasses.xslt version <xsl:value-of select="substring( '$Revision: 1.23 $', 10)"/>
|
|
//
|
|
// <xsl:value-of select="/adl:application/@revision"/>
|
|
//
|
|
// This file is automatically generated; DO NOT EDIT IT.
|
|
//
|
|
//------------------------------------------------------------------
|
|
|
|
using System;
|
|
using System.Data;
|
|
using System.Collections.Generic;
|
|
using NHibernate;
|
|
using NHibernate.Expression;
|
|
using Cygnet.Web.Controllers;
|
|
using <xsl:value-of select="$entityns"/>;
|
|
|
|
namespace <xsl:value-of select="$controllerns"/> {
|
|
|
|
/// <summary>
|
|
/// Automatically generated abstract super class for controllers for the
|
|
/// <xsl:value-of select="/adl:application/@name"/> application
|
|
///
|
|
/// DO NOT EDIT THIS FILE!
|
|
/// </summary>
|
|
public abstract partial class <xsl:value-of select="concat( 'Abstract', /adl:application/@name, 'Controller')"/> : BaseController {
|
|
<xsl:for-each select="//adl:entity">
|
|
/// <summary>
|
|
/// Return a list of all instances of <xsl:value-of select="@name"/> for use in menus, etc;
|
|
/// </summary>
|
|
protected IList<<xsl:value-of select="concat( $entityns, '.', @name)"/>> <xsl:value-of select="concat( 'FetchAll', @name)"/>( ISession hibernator) {
|
|
return hibernator.CreateCriteria(typeof(<xsl:value-of select="concat( $entityns, '.', @name)"/>))
|
|
<xsl:for-each select="descendant::adl:property[@distinct='user']">
|
|
.AddOrder( <xsl:value-of select="concat('new Order( "', @name, '", true)')"/>)
|
|
</xsl:for-each>
|
|
.SetCacheable( true)
|
|
.SetCacheRegion( "<xsl:value-of select="/adl:application/@name"/>")
|
|
.List<<xsl:value-of select="concat( $entityns, '.', @name)"/>>();
|
|
}
|
|
|
|
</xsl:for-each>
|
|
}
|
|
}
|
|
<xsl:apply-templates select="adl:entity"/>
|
|
</xsl:template>
|
|
|
|
|
|
<!-- Don't bother generating anything for foreign entities -->
|
|
<xsl:template match="adl:entity[@foreign='true']"/>
|
|
|
|
<xsl:template match="adl:entity">
|
|
/*
|
|
* Not generating controller for entity <xsl:value-of select="@name"/>,
|
|
* as it has no forms, pages or lists.
|
|
*/
|
|
</xsl:template>
|
|
<xsl:template match="adl:entity[adl:form|adl:page|adl:list]">
|
|
|
|
/* ---- [ cut here: next file '<xsl:value-of select="@name"/>Controller.auto.cs'] ---------------- */
|
|
|
|
//------------------------------------------------------------------
|
|
//
|
|
// <xsl:value-of select="$product-version"/>
|
|
// <xsl:value-of select="@name"/>Controller.auto.cs
|
|
//
|
|
// (c) 2007 Cygnet Solutions Ltd
|
|
//
|
|
// Controller for auto-generated forms for editing <xsl:value-of select="@name"/>s
|
|
// Automatically generated from application description using
|
|
// adl2controllerclasses.xslt version <xsl:value-of select="substring( '$Revision: 1.23 $', 10)"/>
|
|
//
|
|
// 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.Exceptions;
|
|
using Cygnet.Web.Helpers;
|
|
using Cygnet.Web.Controllers;
|
|
using Cygnet.Web.SmartControls;
|
|
using NHibernate;
|
|
using NHibernate.Expression;
|
|
using Castle.MonoRail.Framework;
|
|
using Iesi.Collections.Generic;
|
|
using <xsl:value-of select="$entityns"/>;
|
|
|
|
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>
|
|
[
|
|
<xsl:if test="$layout-name">
|
|
Layout("<xsl:value-of select="$layout-name"/>"),
|
|
</xsl:if>
|
|
<xsl:if test="$rescue-name">
|
|
Rescue("<xsl:value-of select="$rescue-name"/>"),
|
|
</xsl:if>
|
|
ControllerDetails("<xsl:value-of select="@name"/>", Area = "<xsl:value-of select="$area-name"/>"),
|
|
Helper(typeof(StylesHelper), "StylesHelper"),
|
|
Helper(typeof(<xsl:value-of select="concat( @name, 'FieldHelper')"/>), "<xsl:value-of select="concat( @name, 'FieldHelper')"/>")
|
|
]
|
|
public partial class <xsl:value-of select="concat( @name, 'Controller')"/> : <xsl:value-of select="concat( 'Abstract', /adl:application/@name, 'Controller')"/> {
|
|
|
|
/* The SmartFormHelper stuff in generated controller classes does not yet work. There is some
|
|
* hope that in future it will offer definite benefits and in the mean time it is doing no harm.
|
|
* However if you are looking for bugs look elsewhere - this is not currently used */
|
|
protected class <xsl:value-of select="concat( @name, 'FieldHelper')"/> : SmartFormHelper {
|
|
public <xsl:value-of select="concat( @name, 'FieldHelper')"/>() {
|
|
<xsl:for-each select="descendant::adl:property[@type='entity']">
|
|
<xsl:variable name="entityname" select="@entity"/>
|
|
<xsl:variable name="entity" select="//adl:entity[@name=$entityname]"/>
|
|
<xsl:choose>
|
|
<xsl:when test="$entity/@foreign='true'">
|
|
/* Entity <xsl:value-of select="$entityname"/> is foreign..? */
|
|
<xsl:variable name="foreignkey" select="$entity/adl:key/adl:property[position()=1]/@name"/>
|
|
<xsl:variable name="userident">
|
|
<xsl:choose>
|
|
<xsl:when test="$entity//adl:property[@distinct='user' or @distinct='all']">
|
|
<xsl:value-of select="$entity//adl:property[@distinct='user' or @distinct='all'][position()=1]/@name"/>
|
|
</xsl:when>
|
|
<xsl:otherwise>
|
|
<xsl:value-of select="$foreignkey"/>
|
|
</xsl:otherwise>
|
|
</xsl:choose>
|
|
</xsl:variable>
|
|
Register<<xsl:value-of select="concat( $entityns, '.', $entityname)"/>>( "",
|
|
new TypeMenuControl<<xsl:value-of select="concat( $entityns, '.', $entityname)"/>>( "<xsl:value-of select="$foreignkey"/>","<xsl:value-of select="$userident"/>"));
|
|
</xsl:when>
|
|
<xsl:otherwise>
|
|
Register<<xsl:value-of select="concat( $entityns, '.', $entityname)"/>>( "", EntityMenuControl<<xsl:value-of select="concat( $entityns, '.', $entityname)"/>>.Instance);
|
|
</xsl:otherwise>
|
|
</xsl:choose>
|
|
</xsl:for-each>
|
|
<xsl:for-each select="descendant::adl:property[@type='list']">
|
|
<xsl:variable name="entityname" select="@entity"/>
|
|
Register<<xsl:value-of select="concat( $entityns, '.', $entityname)"/>>( "", EntityShuffleControl<<xsl:value-of select="concat( $entityns, '.', $entityname)"/>>.Instance);
|
|
</xsl:for-each>
|
|
|
|
}
|
|
}
|
|
|
|
<xsl:if test="adl:property[@type='message']">
|
|
/// <summary>
|
|
/// Temporary hack to sort a problem with uninitialised messages
|
|
/// </summary>
|
|
public void fixupMessages() {
|
|
ISession hibernator =
|
|
NHibernateHelper.GetCurrentSession( <xsl:if test="$authentication-layer = 'Database'">
|
|
Session[ NHibernateHelper.USERTOKEN],
|
|
Session[NHibernateHelper.PASSTOKEN]
|
|
</xsl:if>);
|
|
ICollection<<xsl:value-of select="concat($entityns, '.', @name)"/>> instances =
|
|
hibernator.CreateCriteria( typeof( <xsl:value-of select="concat($entityns, '.', @name)"/>))
|
|
.List<<xsl:value-of select="concat($entityns, '.', @name)"/>>();
|
|
|
|
foreach ( <xsl:value-of select="concat($entityns, '.', @name)"/> instance in instances) {
|
|
<xsl:for-each select="adl:property[@type='message']">
|
|
if ( <xsl:value-of select="concat( 'instance.', @name)"/> == null || <xsl:value-of select="concat( 'instance.', @name, '.MessageId')"/> == 0 ){
|
|
<xsl:value-of select="concat( 'instance.', @name)"/> = new Message();
|
|
hibernator.Save( <xsl:value-of select="concat( 'instance.', @name)"/>);
|
|
}
|
|
</xsl:for-each>
|
|
hibernator.Save( instance);
|
|
}
|
|
hibernator.Flush();
|
|
<xsl:if test="adl:list[@name='list']">
|
|
list();
|
|
</xsl:if>
|
|
}
|
|
</xsl:if>
|
|
|
|
<xsl:if test="adl:form">
|
|
<!-- unless there's at least one form, we won't generate a 'store' method -->
|
|
/// <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( <xsl:if test="$authentication-layer = 'Database'">
|
|
Session[ NHibernateHelper.USERTOKEN],
|
|
Session[NHibernateHelper.PASSTOKEN]
|
|
</xsl:if>);
|
|
List<string> messages = new List<string>();
|
|
/* A 'newborn' instance can be updated even if the current user doesn't have
|
|
* update permissions, seeing that we use an update operation to set the
|
|
* field values and save the entity. */
|
|
Boolean isnewborn = false;
|
|
|
|
/* the instance (record) of type <xsl:value-of select="@name"/> we're dealing with */
|
|
<xsl:value-of select="concat($entityns, '.', @name)"/> record = null;
|
|
|
|
try {
|
|
<xsl:if test="adl:property[@distinct='system' or @distinct='all']">
|
|
/* a criteria object to use in distinctness checks */
|
|
ICriteria matchCriteria = null;
|
|
</xsl:if>
|
|
|
|
record = FetchRecord( hibernator);
|
|
|
|
<xsl:apply-templates select="adl:property"/>
|
|
|
|
if ( HasNoErrors()) {
|
|
if ( record == null) {
|
|
/* it seems to be new, create persistent object - if the user is permitted to */
|
|
AssertUserCanCreate();
|
|
|
|
try {
|
|
if ( AllKeys()) {
|
|
record = new <xsl:value-of select="concat($entityns, '.', @name)"/>(<xsl:for-each select="adl:key/adl:property">
|
|
<xsl:variable name="basetype">
|
|
<xsl:call-template name="base-type">
|
|
<xsl:with-param name="property" select="."/>
|
|
</xsl:call-template>
|
|
</xsl:variable>
|
|
<xsl:choose>
|
|
<xsl:when test="$basetype='integer'">
|
|
Int32.Parse( Form["<xsl:value-of select="concat( 'instance.', @name)"/>"])
|
|
</xsl:when>
|
|
<xsl:when test="$basetype='entity'">
|
|
<!-- Maybe TODO: this doesn't work recursively - if an entity has a key which is an entity
|
|
and the key of that entity is an entity, you're on your own, mate! -->
|
|
<xsl:variable name="keyentity" select="@entity"/>
|
|
<xsl:variable name="keyenttype">
|
|
<xsl:call-template name="primary-key-csharp-type">
|
|
<xsl:with-param name="entity" select="//adl:entity[@name=$keyentity]"/>
|
|
</xsl:call-template>
|
|
</xsl:variable>
|
|
hibernator.CreateCriteria( typeof( <xsl:value-of select="concat( $entityns, '.', $keyentity)"/>))
|
|
<xsl:call-template name="add-hibernate-expression-eq">
|
|
<xsl:with-param name="property" select="//adl:entity[@name=$keyentity]/adl:key/adl:property[position()=1]"/>
|
|
<xsl:with-param name="value">
|
|
Form[ "<xsl:value-of select="concat( 'instance.', @name)"/>"]
|
|
</xsl:with-param>
|
|
</xsl:call-template>
|
|
.UniqueResult<<xsl:value-of select="concat( $entityns, '.', $keyentity)"/>>()
|
|
</xsl:when>
|
|
<xsl:otherwise>
|
|
Form["<xsl:value-of select="concat( 'instance.', @name)"/>"]
|
|
</xsl:otherwise>
|
|
</xsl:choose>
|
|
<xsl:choose>
|
|
<xsl:when test="position() = last()"/>
|
|
<xsl:otherwise>, </xsl:otherwise>
|
|
</xsl:choose>
|
|
</xsl:for-each>);
|
|
}
|
|
else
|
|
{
|
|
record = new <xsl:value-of select="concat($entityns, '.', @name)"/>();
|
|
}
|
|
}
|
|
catch ( FormatException) {
|
|
/* failed to parse a number - not wholly unexpected, since it's most likely
|
|
* that an empty string was passed in */
|
|
record = new <xsl:value-of select="concat($entityns, '.', @name)"/>();
|
|
}
|
|
catch ( NullReferenceException) {
|
|
/* again, probably more normal than otherwise */
|
|
record = new <xsl:value-of select="concat($entityns, '.', @name)"/>();
|
|
}
|
|
messages.Add( "New <xsl:value-of select="@name"/> record created");
|
|
isnewborn = true;
|
|
}
|
|
|
|
if ( record != null) {
|
|
/* a transaction to ensure our database operations are atomic */
|
|
ITransaction tx = null;
|
|
|
|
if ( ! isnewborn) {
|
|
/* isnewborn cannot be true unless we've already checked user can create
|
|
* so no need to do it again here */
|
|
AssertUserCanUpdate();
|
|
}
|
|
|
|
try {
|
|
/* begin our atomic transaction */
|
|
tx = hibernator.BeginTransaction();
|
|
|
|
/* actually update the record */
|
|
BindObjectInstance( record, ParamStore.Form, "instance");
|
|
|
|
<xsl:if test="descendant::adl:property[@type='message']">
|
|
/* there is at least one slot whose value is an internationalised message;
|
|
* if these have yet to be initialised they must be handled specially */
|
|
Locale locale = GetBestLocaleForUser();
|
|
<xsl:for-each select="descendant::adl:property[@type='message']">
|
|
if ( ! String.IsNullOrEmpty( Form["<xsl:value-of select="concat( 'instance.', @name)"/>"])){
|
|
/* there's an uninitialised message for this slot */
|
|
Message mess = record.<xsl:value-of select="@name"/>;
|
|
if ( mess == null) {
|
|
mess = new Message();
|
|
}
|
|
hibernator.Save( mess);
|
|
|
|
Translation trans = mess.GetTranslationObject( locale, hibernator);
|
|
if ( trans == null) {
|
|
trans = new Translation( mess, locale);
|
|
}
|
|
trans.MessageText = Form["<xsl:value-of select="concat( 'instance.', @name)"/>"];
|
|
record.<xsl:value-of select="@name"/> = mess;
|
|
hibernator.Save( trans);
|
|
}
|
|
</xsl:for-each>
|
|
</xsl:if>
|
|
<xsl:for-each select="descendant::adl:property[@type='entity']">
|
|
/* for properties of type 'entity', it should not be necessary to do anything
|
|
* special - BindObjectInstance /should/ do it all. Unfortunately it sometimes
|
|
* doesn't, and I haven't yet characterised why not. */
|
|
<xsl:variable name="entityname" select="@entity"/>
|
|
<xsl:choose>
|
|
<xsl:when test="//adl:entity[@name=$entityname]">
|
|
if ( ! String.IsNullOrEmpty( Form["<xsl:value-of select="concat( 'instance.', @name)"/>"]))
|
|
{
|
|
record.<xsl:value-of select="@name"/> = <xsl:call-template name="fetch-property-instance">
|
|
<xsl:with-param name="property" select="."/>
|
|
<xsl:with-param name="value">Form[ "<xsl:value-of select="concat( 'instance.', @name)"/>"]</xsl:with-param>
|
|
</xsl:call-template>;
|
|
}
|
|
</xsl:when>
|
|
<xsl:otherwise>
|
|
<xsl:message terminate="yes">
|
|
ADL: ERROR: Could not fix up value of <xsl:value-of select="@name "/>, because no
|
|
entity was found called <xsl:value-of select="$entityname"/>
|
|
</xsl:message>
|
|
</xsl:otherwise>
|
|
</xsl:choose>
|
|
</xsl:for-each>
|
|
|
|
<xsl:for-each select="descendant::adl:property[@type='link']">
|
|
<xsl:variable name="farentityname" select="@entity"/>
|
|
<xsl:variable name="farkey" select="//adl:entity[@name=$farentityname]/adl:key/adl:property[position()=1]/@name"/>
|
|
<xsl:variable name="farkeybasetype">
|
|
<xsl:call-template name="base-type">
|
|
<xsl:with-param name="property" select="//adl:entity[@name=$farentityname]/adl:key/adl:property[position()=1]"/>
|
|
</xsl:call-template>
|
|
</xsl:variable>
|
|
/* 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)"/>");
|
|
|
|
/* 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="concat( $entityns, '.', @entity)"/>>();
|
|
}
|
|
|
|
if ( <xsl:value-of select="concat(@name, 'Values')"/> != null)
|
|
{
|
|
/* then reinstate the values from the indexes passed */
|
|
foreach ( string index in <xsl:value-of select="concat(@name, 'Values')"/>)
|
|
{
|
|
<xsl:value-of select="concat( 'record.', @name)"/>.Add(
|
|
hibernator.CreateCriteria(typeof(<xsl:value-of select="concat( $entityns, '.', @entity)"/>))
|
|
<xsl:call-template name="add-hibernate-expression-eq">
|
|
<xsl:with-param name="property" select="//adl:entity[@name=$farentityname]/adl:key/adl:property[position()=1]"/>
|
|
<xsl:with-param name="value" select="'index'"/>
|
|
</xsl:call-template>
|
|
.UniqueResult<<xsl:value-of select="concat( $entityns, '.', @entity)"/>>());
|
|
}
|
|
}
|
|
</xsl:for-each>
|
|
|
|
<xsl:for-each select="descendant::adl:property[@type='list']">
|
|
<xsl:variable name="farentityname" select="@entity"/>
|
|
<xsl:variable name="farkey" select="//adl:entity[@name=$farentityname]/adl:key/adl:property[position()=1]/@name"/>
|
|
<xsl:variable name="farkeybasetype">
|
|
<xsl:call-template name="base-type">
|
|
<xsl:with-param name="property" select="//adl:entity[@name=$farentityname]/adl:key/adl:property[position()=1]"/>
|
|
</xsl:call-template>
|
|
</xsl:variable>
|
|
<xsl:variable name="foreignkey">
|
|
<xsl:choose>
|
|
<xsl:when test="@farkey">
|
|
<xsl:value-of select="@farkey"/>
|
|
</xsl:when>
|
|
<xsl:otherwise>
|
|
<!-- If I haven't been told what the far side foreign key is, assume it has the
|
|
name of my entity -->
|
|
<xsl:value-of select="ancestor::adl:entity/@name"/>
|
|
</xsl:otherwise>
|
|
</xsl:choose>
|
|
</xsl:variable>
|
|
/* 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.KeyString;
|
|
bool found = false;
|
|
|
|
foreach ( string index in <xsl:value-of select="concat(@name, 'Values')"/>)
|
|
{
|
|
if ( index.Equals( itemId))
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
} /* foreach ( string index... */
|
|
|
|
if ( ! found)
|
|
{
|
|
record.<xsl:value-of select="@name"/>.Remove( item);
|
|
break;
|
|
}
|
|
} /* foreach ( <xsl:value-of select="@entity"/> item ... */
|
|
|
|
/* then add any on the included list which are not already members */
|
|
foreach ( string index in <xsl:value-of select="concat(@name, 'Values')"/>)
|
|
{
|
|
<xsl:value-of select="concat( $entityns, '.', @entity)"/> item =
|
|
hibernator.CreateCriteria(typeof(<xsl:value-of select="@entity"/>))
|
|
<xsl:call-template name="add-hibernate-expression-eq">
|
|
<xsl:with-param name="property" select="//adl:entity[@name=$farentityname]/adl:key/adl:property[position()=1]"/>
|
|
<xsl:with-param name="value" select="'index'"/>
|
|
</xsl:call-template>
|
|
.UniqueResult<<xsl:value-of select="concat( $entityns, '.', @entity)"/>>();
|
|
|
|
if ( ! record.<xsl:value-of select="@name"/>.Contains( item))
|
|
{
|
|
/* check whether it's already a child of another <xsl:value-of select="ancestor::adl:entity/@name"/>
|
|
* and, if it is, remove it */
|
|
<xsl:value-of select="concat( $entityns, '.', ancestor::adl:entity/@name)"/> oldparent =
|
|
<xsl:value-of select="concat( 'item.', $foreignkey)"/>;
|
|
if ( oldparent != null) {
|
|
oldparent.<xsl:value-of select="@name"/>.Remove( item);
|
|
hibernator.Save( oldparent);
|
|
}
|
|
|
|
/* then add it to my <xsl:value-of select="@name"/> */
|
|
record.<xsl:value-of select="@name"/>.Add( item);
|
|
<xsl:value-of select="concat( 'item.', $foreignkey)"/> = record;
|
|
hibernator.Save( item);
|
|
}
|
|
} /* foreach ( string index... */
|
|
} /* if ( Form.GetValues( "<xsl:value-of select="concat( 'instance.', @name)"/>") != null) */
|
|
</xsl:for-each>
|
|
|
|
/* write the record to the database, in order to guarantee we have a valid key */
|
|
hibernator.Save(record);
|
|
hibernator.Flush();
|
|
tx.Commit();
|
|
|
|
messages.Add( "<xsl:call-template name="i18n-record-saved"/>");
|
|
} /* try actually commit */
|
|
catch ( Exception any) {
|
|
tx.Rollback();
|
|
messages.Add( "<xsl:call-template name="i18n-record-not-saved"/>");
|
|
throw any;
|
|
}
|
|
} /* if ( record != null) */
|
|
else {
|
|
throw new ApplicationException( String.Format( "<xsl:call-template name="i18n-record-not-found">
|
|
<xsl:with-param name="entity-name" select="@name"/>
|
|
</xsl:call-template>"));
|
|
}
|
|
} /* if ( HasNoErrors()) */
|
|
} /* try */
|
|
catch ( DataSuitabilityException dse)
|
|
{
|
|
AddError( dse);
|
|
}
|
|
catch ( ApplicationException axe)
|
|
{
|
|
AddError( axe.Message);
|
|
}
|
|
|
|
if ( ! HasNoErrors())
|
|
{
|
|
/* the session may be polluted; create a new session */
|
|
NHibernateHelper.CloseSession();
|
|
hibernator = NHibernateHelper.GetCurrentSession(<xsl:if test="$authentication-layer = 'Database'">
|
|
Session[ NHibernateHelper.USERTOKEN],
|
|
Session[NHibernateHelper.PASSTOKEN]
|
|
</xsl:if>);
|
|
|
|
record = FetchRecord( hibernator);
|
|
} /* if ( ! HasNoErrors()) */
|
|
<xsl:value-of select="concat( 'this.',adl:form[position()=1]/@name)"/>( record);
|
|
}
|
|
</xsl:if>
|
|
|
|
<xsl:if test="adl:form">
|
|
<!-- unless there's at least one form, we won't generate a 'delete' method -->
|
|
/// <summary>
|
|
/// Actually delete the selected record
|
|
/// </summary>
|
|
[AccessibleThrough(Verb.Post)]
|
|
public void Delete()
|
|
{
|
|
AssertUserCanDelete();
|
|
ISession hibernator =
|
|
NHibernateHelper.GetCurrentSession( <xsl:if test="$authentication-layer = 'Database'">
|
|
Session[ NHibernateHelper.USERTOKEN],
|
|
Session[NHibernateHelper.PASSTOKEN]
|
|
</xsl:if>);
|
|
|
|
if ( "true".Equals( Params["reallydelete"]))
|
|
{
|
|
<xsl:value-of select="concat($entityns, '.', @name)"/> record = FetchRecord( hibernator);
|
|
|
|
if ( record != null)
|
|
{
|
|
hibernator.Delete( record);
|
|
hibernator.Flush();
|
|
}
|
|
else
|
|
{
|
|
throw new ApplicationException( "No such record?");
|
|
}
|
|
}
|
|
<xsl:choose>
|
|
<xsl:when test="adl:list">
|
|
Redirect( "<xsl:value-of select="concat(adl:list[position()=1]/@name, '.rails')"/>");
|
|
</xsl:when>
|
|
<xsl:otherwise>
|
|
Redirect( FormsAuthentication.DefaultUrl);
|
|
</xsl:otherwise>
|
|
</xsl:choose>
|
|
}
|
|
</xsl:if>
|
|
<xsl:apply-templates select="adl:form"/>
|
|
|
|
<xsl:if test="adl:list">
|
|
<xsl:variable name="listname" select="adl:list[position()=1]/@name"/>
|
|
<xsl:apply-templates select="adl: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)
|
|
{
|
|
AssertUserCanRead();
|
|
ISession hibernator =
|
|
NHibernateHelper.GetCurrentSession( <xsl:if test="$authentication-layer = 'Database'">
|
|
Session[ NHibernateHelper.USERTOKEN],
|
|
Session[NHibernateHelper.PASSTOKEN]
|
|
</xsl:if>);
|
|
|
|
ICriteria search =
|
|
hibernator.CreateCriteria(typeof(<xsl:value-of select="concat( $entityns, '.', @name)"/>));
|
|
|
|
<xsl:for-each select="adl:property">
|
|
<xsl:variable name="base-type">
|
|
<xsl:call-template name="base-type">
|
|
<xsl:with-param name="property" select="."/>
|
|
</xsl:call-template>
|
|
</xsl:variable>
|
|
<xsl:choose>
|
|
<xsl:when test="$base-type='boolean'"/>
|
|
<xsl:when test="$base-type='link'"/>
|
|
<xsl:when test="$base-type='list'"/>
|
|
<xsl:otherwise>
|
|
if ( ! String.IsNullOrEmpty( Params[ "<xsl:value-of select="concat( 'search_', @name)"/>"])) {
|
|
search<xsl:call-template name="add-hibernate-expression-like">
|
|
<xsl:with-param name="property" select="."/>
|
|
<xsl:with-param name="value">Params["<xsl:value-of select="concat( 'search_', @name)"/>"]</xsl:with-param>
|
|
</xsl:call-template>;
|
|
}
|
|
</xsl:otherwise>
|
|
</xsl:choose>
|
|
</xsl:for-each>
|
|
<xsl:for-each select="adl:property[@distinct='user' or @distinct='all']">
|
|
search.AddOrder(<xsl:value-of select="concat( ' new Order( "', @name, '", true)')"/>);
|
|
</xsl:for-each>
|
|
|
|
IList<<xsl:value-of select="concat( $entityns, '.', @name)"/>> instances = search.List<<xsl:value-of select="concat( $entityns, '.', @name)"/>>();
|
|
|
|
<xsl:if test="$authentication-layer = 'Database'">
|
|
PropertyBag["username"] = Session[ NHibernateHelper.USERTOKEN];
|
|
</xsl:if>
|
|
PropertyBag["instances"] =
|
|
PaginationHelper.CreatePagination( this, instances, 25);
|
|
|
|
RenderViewWithFailover(view + ".vm", view + ".auto.vm");
|
|
}
|
|
</xsl:if>
|
|
|
|
/// <summary>
|
|
/// Check whether values for all my keys are available in the form fields
|
|
/// </summary>
|
|
protected bool AllKeys() {
|
|
/* whether we have valid values for all the key fields */
|
|
bool result = true;
|
|
|
|
<xsl:for-each select="adl:key/adl:property">
|
|
if ( String.IsNullOrEmpty( Form["<xsl:value-of select="concat( 'instance.', @name)"/>"])) {
|
|
result = false;
|
|
} else if ( "<xsl:value-of select="concat('$instance.', @name)"/>".Equals( Form["<xsl:value-of select="concat( 'instance.', @name)"/>"])) {
|
|
/* nasty artefact of NVelocity forms - default 'null value' is dollar followed by fieldname */
|
|
result = false;
|
|
}
|
|
</xsl:for-each>
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Fetch the record represented by the values in the current Form
|
|
/// </summary>
|
|
protected <xsl:value-of select="concat($entityns, '.', @name)"/> FetchRecord(ISession hibernator) {
|
|
/* the instance (record) of type <xsl:value-of select="@name"/> we're dealing with */
|
|
<xsl:value-of select="concat($entityns, '.', @name)"/> record = null;
|
|
|
|
if ( AllKeys()){
|
|
/* it's (probably) existing, retrieve it */
|
|
record = hibernator.CreateCriteria(typeof(<xsl:value-of select="concat( $entityns, '.', @name)"/>))
|
|
<xsl:for-each select="adl:key/adl:property">
|
|
<xsl:call-template name="add-hibernate-expression-eq">
|
|
<xsl:with-param name="property" select="."/>
|
|
<xsl:with-param name="value">Form["<xsl:value-of select="concat( 'instance.', @name)"/>"]</xsl:with-param>
|
|
</xsl:call-template>
|
|
</xsl:for-each>
|
|
.UniqueResult<<xsl:value-of select="concat( $entityns, '.', @name)"/>>();
|
|
}
|
|
|
|
return record;
|
|
}
|
|
}
|
|
}
|
|
/* ---- [ cut here: next file 'junk'] ------------------------- */
|
|
</xsl:template>
|
|
|
|
<xsl:template match="adl:property">
|
|
<xsl:if test="@required='true'">
|
|
if ( String.IsNullOrEmpty( Form[ "<xsl:value-of select="concat( 'instance.', @name)"/>" ]))
|
|
{
|
|
AddError( <xsl:choose>
|
|
<xsl:when test="adl:ifmissing[@locale=$locale]">
|
|
<xsl:apply-templates select="adl:ifmissing[@locale=$locale]"/>
|
|
</xsl:when>
|
|
<xsl:otherwise>
|
|
"<xsl:call-template name="i18n-value-required">
|
|
<xsl:with-param name="property-name" select="@name"/>
|
|
</xsl:call-template>"
|
|
</xsl:otherwise>
|
|
</xsl:choose>);
|
|
}
|
|
</xsl:if>
|
|
<xsl:if test="@distinct='system' or @distinct='all'">
|
|
<xsl:call-template name="check-property-value-distinct">
|
|
<xsl:with-param name="property" select="."/>
|
|
</xsl:call-template>
|
|
</xsl:if>
|
|
</xsl:template>
|
|
|
|
<xsl:template match="adl:ifmissing">
|
|
"<xsl:value-of select="normalize-space(.)"/>"
|
|
</xsl:template>
|
|
|
|
<xsl:template match="adl:form">
|
|
/// <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( "<xsl:call-template name="i18n-command-not-found"/>");
|
|
}
|
|
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( <xsl:if test="$authentication-layer = 'Database'">
|
|
Session[ NHibernateHelper.USERTOKEN],
|
|
Session[NHibernateHelper.PASSTOKEN]
|
|
</xsl:if>);
|
|
|
|
<xsl:value-of select="concat($entityns, '.', ancestor::adl:entity/@name)"/> record = FetchRecord( hibernator);
|
|
|
|
TypedPropertyBag = new {
|
|
<xsl:if test="$authentication-layer = 'Database'">
|
|
username = Session[ NHibernateHelper.USERTOKEN],
|
|
</xsl:if>
|
|
instance = record };
|
|
|
|
RenderViewWithFailover( "maybedelete.vm", "maybedelete.auto.vm");
|
|
}
|
|
else if ( command.Equals( "store"))
|
|
{
|
|
Store();
|
|
}
|
|
else
|
|
{
|
|
throw new Exception( String.Format("<xsl:call-template name="i18n-command-not-found">
|
|
<xsl:with-param name="command" select="'{0}'"/>
|
|
</xsl:call-template>", command));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Show the form named <xsl:value-of select="@name"/>, with no content
|
|
/// </summary>
|
|
[AccessibleThrough(Verb.Get)]
|
|
public void <xsl:value-of select="@name"/>( )
|
|
{
|
|
AssertUserCanRead();
|
|
|
|
<xsl:value-of select="concat( 'this.', @name)"/>( (<xsl:value-of select="concat($entityns, '.', ancestor::adl:entity/@name)"/>)null);
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Show the form named <xsl:value-of select="@name"/>, containing the indicated record. As
|
|
/// the primary key of the record is itself an entity, we need to first fetch that entity
|
|
/// </summary>
|
|
<xsl:for-each select="ancestor::adl:entity/adl:key/adl:property">
|
|
<xsl:choose>
|
|
<xsl:when test="@type='entity'">
|
|
/// <param name="<xsl:value-of select="@name"/>">the key value of the key value of the record to show</param>
|
|
</xsl:when>
|
|
<xsl:otherwise>
|
|
/// <param name="<xsl:value-of select="@name"/>">the key value of the record to show</param>
|
|
</xsl:otherwise>
|
|
</xsl:choose>
|
|
</xsl:for-each>
|
|
[AccessibleThrough(Verb.Get)]
|
|
public void <xsl:value-of select="@name"/>( <xsl:for-each select="ancestor::adl:entity/adl:key/adl:property">
|
|
<!-- all args are passed as string because that's what hibernate-expression-eq expects -->
|
|
string <xsl:value-of select="concat( ' ', @name)"/>
|
|
<xsl:if test="not( position() = last())">,</xsl:if>
|
|
</xsl:for-each>) {
|
|
ISession hibernator =
|
|
NHibernateHelper.GetCurrentSession( <xsl:if test="$authentication-layer = 'Database'">
|
|
Session[ NHibernateHelper.USERTOKEN],
|
|
Session[NHibernateHelper.PASSTOKEN]
|
|
</xsl:if>);
|
|
<xsl:value-of select="concat( 'this.', @name)"/>(
|
|
hibernator.CreateCriteria( typeof(<xsl:value-of select="concat($entityns, '.', ancestor::adl:entity/@name)"/>))
|
|
<xsl:for-each select="ancestor::adl:entity/adl:key/adl:property">
|
|
<xsl:call-template name="add-hibernate-expression-eq">
|
|
<xsl:with-param name="property" select="."/>
|
|
<xsl:with-param name="value" select="@name"/>
|
|
</xsl:call-template>
|
|
</xsl:for-each>
|
|
.UniqueResult<<xsl:value-of select="concat($entityns, '.', ancestor::adl:entity/@name)"/>>());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Show the form named <xsl:value-of select="@name"/>, containing the indicated record
|
|
/// </summary>
|
|
/// <param name="record">the record to show</param>
|
|
protected void <xsl:value-of select="@name"/>( <xsl:value-of select="concat($entityns, '.', ancestor::adl:entity/@name)"/> record)
|
|
{
|
|
ISession hibernator =
|
|
NHibernateHelper.GetCurrentSession( <xsl:if test="$authentication-layer = 'Database'">
|
|
Session[ NHibernateHelper.USERTOKEN],
|
|
Session[NHibernateHelper.PASSTOKEN]
|
|
</xsl:if>);
|
|
|
|
TypedPropertyBag = new {
|
|
<xsl:if test="$authentication-layer = 'Database'">
|
|
username = Session[ NHibernateHelper.USERTOKEN],
|
|
</xsl:if>
|
|
<xsl:call-template name="formmenus">
|
|
<xsl:with-param name="form" select="."/>
|
|
</xsl:call-template>
|
|
instance = record };
|
|
|
|
RenderViewWithFailover("<xsl:value-of select="concat( @name, '.vm')"/>", "<xsl:value-of select="concat( @name, '.auto.vm')"/>");
|
|
}
|
|
</xsl:template>
|
|
|
|
<xsl:template match="adl:list">
|
|
/// <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 match="adl:documentation">
|
|
/* <xsl:apply-templates/> */
|
|
</xsl:template>
|
|
|
|
|
|
<xsl:template match="adl:key">
|
|
<!-- the key shouldn't be matched directly - at least, not in this implementation -->
|
|
</xsl:template>
|
|
|
|
<!-- for properties with @distinct='all' or @distinct='system',
|
|
check that values are indeed distinct -->
|
|
<xsl:template name="check-property-value-distinct">
|
|
<xsl:param name="property"/>
|
|
|
|
<xsl:variable name="basetype">
|
|
<xsl:call-template name="base-type">
|
|
<xsl:with-param name="property" select="."/>
|
|
</xsl:call-template>
|
|
</xsl:variable>
|
|
|
|
<xsl:choose>
|
|
<xsl:when test="$property/ancestor::adl:key and not( $property/ancestor::adl:entity/adl:key[position()=2])">
|
|
<!-- if I'm the property of a key field and it is the only key field of my entity then
|
|
it is pointless trying to establish my distinctness -->
|
|
</xsl:when>
|
|
<xsl:when test="$property/@distinct = 'system' or $property/@distinct='all'">
|
|
/* <xsl:value-of select="$property/@name"/> should be distinct: check that it is */
|
|
matchCriteria =
|
|
hibernator.CreateCriteria(typeof(<xsl:value-of select="$property/ancestor::adl:entity/@name"/>));
|
|
|
|
matchCriteria<xsl:call-template name="add-hibernate-expression-eq">
|
|
<xsl:with-param name="property" select="$property"/>
|
|
<xsl:with-param name="value">
|
|
Form["<xsl:value-of select="concat( 'instance.', @name)"/>"]
|
|
</xsl:with-param>
|
|
</xsl:call-template>;
|
|
|
|
if ( record != null) {
|
|
/* i.e. we do have values for each of our key fields... */
|
|
<xsl:for-each select="$property/ancestor::adl:entity/adl:key/adl:property[position()=1]">
|
|
<xsl:variable name="keybasetype">
|
|
<xsl:call-template name="base-type">
|
|
<xsl:with-param name="property" select="."/>
|
|
</xsl:call-template>
|
|
</xsl:variable>
|
|
matchCriteria.Add(Expression.Not(<xsl:call-template name="hibernate-expression-eq">
|
|
<xsl:with-param name="property" select="."/>
|
|
<xsl:with-param name="value">
|
|
Form["<xsl:value-of select="concat( 'instance.', @name)"/>"]
|
|
</xsl:with-param>
|
|
</xsl:call-template>));
|
|
</xsl:for-each>
|
|
}
|
|
|
|
if ( matchCriteria.List<<xsl:value-of select="$property/ancestor::adl:entity/@name"/>>().Count > 0)
|
|
{
|
|
AddError(
|
|
String.Format("There is already a {0} with the {1} '{2}'",
|
|
"<xsl:value-of select="$property/ancestor::adl:entity/@name"/>", "<xsl:value-of select="$property/@name"/>", Form["<xsl:value-of select="concat('instance.', $property/@name)"/>"]));
|
|
}
|
|
</xsl:when>
|
|
</xsl:choose>
|
|
</xsl:template>
|
|
|
|
|
|
<!-- produce all menus for a given form: harder, but more efficient -->
|
|
<xsl:template name="formmenus">
|
|
<!-- an entity assumed to be of type adl:form -->
|
|
<xsl:param name="form"/>
|
|
<xsl:choose>
|
|
<xsl:when test="$form/@properties = 'all'">
|
|
<xsl:call-template name="entitymenus">
|
|
<xsl:with-param name="entity" select="$form/ancestor::adl:entity"/>
|
|
</xsl:call-template>
|
|
</xsl:when>
|
|
<xsl:otherwise>
|
|
/* form menus */
|
|
<xsl:for-each select="$form//adl:field">
|
|
<xsl:variable name="propname" select="@property"/>
|
|
<xsl:choose>
|
|
<xsl:when test="parent::adl:auxlist"/>
|
|
<xsl:when test="$form/ancestor::adl:entity/adl:property[@name=$propname and @type='entity']">
|
|
/* produce a list of <xsl:value-of select="$form/ancestor::adl:entity/adl:property[@name=$propname]/@entity"/> to populate the select for <xsl:value-of select="$propname"/> */
|
|
<xsl:call-template name="menu">
|
|
<xsl:with-param name="property" select="$form/ancestor::adl:entity/adl:property[@name=$propname]"/>
|
|
</xsl:call-template>
|
|
</xsl:when>
|
|
<xsl:when test="$form/ancestor::adl:entity/adl:property[@name=$propname and @type='link']">
|
|
/* produce a list of <xsl:value-of select="$form/ancestor::adl:entity/adl:property[@name=$propname]/@entity"/> to populate the LHS of the shuffle for <xsl:value-of select="$propname"/> */
|
|
<xsl:call-template name="menu">
|
|
<xsl:with-param name="property" select="$form/ancestor::adl:entity/adl:property[@name=$propname]"/>
|
|
</xsl:call-template>
|
|
</xsl:when>
|
|
<xsl:when test="$form/ancestor::adl:entity/adl:property[@name=$propname and @type='list']">
|
|
/* produce a list of <xsl:value-of select="$form/ancestor::adl:entity/adl:property[@name=$propname]/@entity"/> to populate the multi-select for <xsl:value-of select="@name"/> */
|
|
<xsl:call-template name="menu">
|
|
<xsl:with-param name="property" select="$form/ancestor::adl:entity/adl:property[@name=$propname]"/>
|
|
</xsl:call-template>
|
|
</xsl:when>
|
|
</xsl:choose>
|
|
</xsl:for-each>
|
|
</xsl:otherwise>
|
|
</xsl:choose>
|
|
</xsl:template>
|
|
|
|
|
|
<!-- produce all menus for a given entity: easier, but less efficient -->
|
|
<xsl:template name="entitymenus">
|
|
<xsl:param name="entity"/>
|
|
/* there's no way I can find of producing a set of just those entities
|
|
* we'll need menus for. So we set up variables for all the menus we might
|
|
* need, and then only instantiate those we do need. */
|
|
<!-- xsl:for-each select="//adl:entity">
|
|
IList<<xsl:value-of select="concat( $entityns, '.', @name)"/>> <xsl:value-of select="concat( 'all', @name)"/> = null;
|
|
</xsl:for-each -->
|
|
<xsl:for-each select="$entity//adl:property[@type='entity']">
|
|
<!-- $entity//adl:property because it is possible to have type='entity' in the key -->
|
|
<xsl:call-template name="menu">
|
|
<xsl:with-param name="property" select="."/>
|
|
</xsl:call-template>
|
|
</xsl:for-each>
|
|
<xsl:for-each select="$entity/adl:property[@type='link']">
|
|
<!-- $entity/adl:property because it is not possible to have type='link' in the key -->
|
|
/* produce a list of <xsl:value-of select="@entity"/> to populate the LHS of the shuffle for <xsl:value-of select="@name"/> */
|
|
<xsl:call-template name="menu">
|
|
<xsl:with-param name="property" select="."/>
|
|
</xsl:call-template>
|
|
</xsl:for-each>
|
|
<xsl:for-each select="$entity/adl:property[@type='list']">
|
|
/* produce a list of <xsl:value-of select="@entity"/> to populate the multi-select for <xsl:value-of select="@name"/> */
|
|
<xsl:call-template name="menu">
|
|
<xsl:with-param name="property" select="."/>
|
|
</xsl:call-template>
|
|
</xsl:for-each>
|
|
|
|
</xsl:template>
|
|
|
|
<xsl:template name="menu">
|
|
<xsl:param name="property"/>
|
|
<xsl:variable name="entity" select="//adl:entity[@name=$property/@entity]"/>
|
|
<xsl:value-of select="concat('all_', $property/@name)"/> =
|
|
<xsl:value-of select="concat( 'FetchAll', $entity/@name)"/>( NHibernateHelper.GetCurrentSession()),
|
|
</xsl:template>
|
|
|
|
<xsl:template name="primary-key-csharp-type">
|
|
<xsl:param name="entity"/>
|
|
<xsl:if test="not( $entity)">
|
|
<xsl:message terminate="yes">
|
|
ADL: ERROR: No entity passed to template primary-key-csharp-type
|
|
</xsl:message>
|
|
</xsl:if>
|
|
<xsl:if test="not($entity/adl:key/adl:property)">
|
|
<xsl:message terminate="no">
|
|
ADL: WARNING: entity '<xsl:value-of select="$entity/@name"/>' has no primary key.
|
|
You will have to manually edit <xsl:value-of select="concat( $entity/@name, 'Controller.auto.cs')"/>
|
|
</xsl:message>
|
|
</xsl:if>
|
|
<xsl:call-template name="csharp-type">
|
|
<xsl:with-param name="property" select="$entity/adl:key/adl:property[ position() = 1]"/>
|
|
<xsl:with-param name="entityns" select="$entityns"/>
|
|
</xsl:call-template>
|
|
</xsl:template>
|
|
|
|
<xsl:template name="primary-key-name">
|
|
<!-- return the name of the primary key of the entity with this name -->
|
|
<xsl:param name="entity"/>
|
|
<xsl:if test="not($entity/adl:key)">
|
|
<xsl:message terminate="yes">
|
|
ADL: ERROR: No key for entity: <xsl:value-of select="$entity/@name"/>
|
|
</xsl:message>
|
|
</xsl:if>
|
|
<xsl:choose>
|
|
<xsl:when test="$entity/adl:key/adl:property[position()=2]">
|
|
<xsl:message terminate="no">
|
|
ADL: WARNING: Entity <xsl:value-of select="$entity/@name"/> has a composite primary key.
|
|
You will need to manually edit <xsl:value-of select="concat( $entity/@name, 'Controller.auto.cs')"/>
|
|
</xsl:message>
|
|
<xsl:value-of select="$entity/adl:key/adl:property[position()=1]/@name"/>
|
|
</xsl:when>
|
|
<xsl:when test="$entity/adl:key/adl:property">
|
|
<xsl:value-of select="$entity/adl:key/adl:property[position()=1]/@name"/>
|
|
</xsl:when>
|
|
<xsl:otherwise>
|
|
<xsl:message terminate="no">
|
|
ADL: WARNING: Entity <xsl:value-of select="$entity/@name"/> has no primary key.
|
|
You will need to manually edit <xsl:value-of select="concat( $entity/@name, 'Controller.auto.cs')"/>
|
|
</xsl:message>
|
|
</xsl:otherwise>
|
|
</xsl:choose>
|
|
</xsl:template>
|
|
|
|
<!-- it's often convenient to wrap an expression in an Add() -->
|
|
<xsl:template name="add-hibernate-expression-eq">
|
|
<xsl:param name="property"/>
|
|
<xsl:param name="value"/>
|
|
<xsl:variable name="basetype">
|
|
<xsl:call-template name="base-type">
|
|
<xsl:with-param name="property" select="$property"/>
|
|
</xsl:call-template>
|
|
</xsl:variable>
|
|
.Add(<xsl:call-template name="hibernate-expression-eq">
|
|
<xsl:with-param name="property" select="$property"/>
|
|
<xsl:with-param name="value" select="$value"/>
|
|
</xsl:call-template>)
|
|
</xsl:template>
|
|
|
|
<!-- it's often convenient to wrap an expression in an Add() -->
|
|
<xsl:template name="add-hibernate-expression-like">
|
|
<xsl:param name="property"/>
|
|
<xsl:param name="value"/>
|
|
<xsl:variable name="basetype">
|
|
<xsl:call-template name="base-type">
|
|
<xsl:with-param name="property" select="$property"/>
|
|
</xsl:call-template>
|
|
</xsl:variable>
|
|
.Add(<xsl:call-template name="hibernate-expression-like">
|
|
<xsl:with-param name="property" select="$property"/>
|
|
<xsl:with-param name="value" select="$value"/>
|
|
</xsl:call-template>)
|
|
</xsl:template>
|
|
|
|
<!-- generate a hibernate equality expression based on this property,
|
|
comparing it to this value -->
|
|
<xsl:template name="hibernate-expression-eq">
|
|
<!-- an entity of type property -->
|
|
<xsl:param name="property"/>
|
|
<!-- an expression which, at run time, will evaluate to a string -->
|
|
<xsl:param name="value"/>
|
|
<xsl:variable name="basetype">
|
|
<xsl:call-template name="base-type">
|
|
<xsl:with-param name="property" select="$property"/>
|
|
</xsl:call-template>
|
|
</xsl:variable>
|
|
Expression.Eq("<xsl:value-of select="$property/@name"/>", <xsl:choose>
|
|
<xsl:when test="$basetype = 'string'">
|
|
<xsl:value-of select="$value"/>
|
|
</xsl:when>
|
|
<xsl:when test="$basetype = 'integer'">
|
|
Int32.Parse( <xsl:value-of select="$value"/>)
|
|
</xsl:when>
|
|
<xsl:when test="$basetype = 'money'">
|
|
Decimal.Parse( <xsl:value-of select="$value"/>)
|
|
</xsl:when>
|
|
<xsl:when test="$basetype = 'date'">
|
|
DateTime.Parse( <xsl:value-of select="$value"/>)
|
|
</xsl:when>
|
|
<xsl:when test="$basetype='entity'">
|
|
<xsl:call-template name="fetch-property-instance">
|
|
<xsl:with-param name="property" select="$property"/>
|
|
<xsl:with-param name="value" select="$value"/>
|
|
</xsl:call-template>
|
|
</xsl:when>
|
|
<xsl:otherwise>
|
|
<xsl:message terminate="yes">
|
|
ADL: Error: properties of type <xsl:value-of select="$basetype"/> cannot yet be used
|
|
in equality tests
|
|
</xsl:message>
|
|
</xsl:otherwise>
|
|
</xsl:choose>)
|
|
</xsl:template>
|
|
|
|
<!-- generate a hibernate like expression based on this property,
|
|
comparing it to this value -->
|
|
<xsl:template name="hibernate-expression-like">
|
|
<xsl:param name="property"/>
|
|
<xsl:param name="value"/>
|
|
<xsl:variable name="basetype">
|
|
<xsl:call-template name="base-type">
|
|
<xsl:with-param name="property" select="$property"/>
|
|
</xsl:call-template>
|
|
</xsl:variable>
|
|
<xsl:choose>
|
|
<xsl:when test="$basetype='string' or $basetype='text'">
|
|
Expression.Like( "<xsl:value-of select="@name"/>", "%"+<xsl:value-of select="$value"/>+"%")
|
|
</xsl:when>
|
|
<xsl:when test="$basetype='real'">
|
|
/* match to four significant places */
|
|
Expression.Between( "<xsl:value-of select="@name"/>",
|
|
Double.Parse( <xsl:value-of select="$value"/>) * 1.0001,
|
|
Double.Parse( <xsl:value-of select="$value"/>) * 0.9999)
|
|
</xsl:when>
|
|
<xsl:otherwise>
|
|
<xsl:call-template name="hibernate-expression-eq">
|
|
<xsl:with-param name="property" select="$property"/>
|
|
<xsl:with-param name="value" select="$value"/>
|
|
</xsl:call-template>
|
|
</xsl:otherwise>
|
|
</xsl:choose>
|
|
</xsl:template>
|
|
|
|
<!-- argument: a property
|
|
returns 'true' if that property is of a type which makes it searchable,
|
|
else 'false'. See also how search fields are generated in adl2views.xsl -->
|
|
<xsl:template name="is-searchable">
|
|
<xsl:param name="property"/>
|
|
<xsl:variable name="base-type">
|
|
<xsl:call-template name="base-type">
|
|
<xsl:with-param name="property" select="$property"/>
|
|
</xsl:call-template>
|
|
</xsl:variable>
|
|
<xsl:choose>
|
|
<xsl:when test="$base-type='string'">true</xsl:when>
|
|
<xsl:when test="$base-type='integer'">true</xsl:when>
|
|
<xsl:when test="$base-type='real'">true</xsl:when>
|
|
<xsl:when test="$base-type='money'">true</xsl:when>
|
|
<xsl:when test="$base-type='text'">true</xsl:when>
|
|
<xsl:when test="$base-type='entity'">true</xsl:when>
|
|
<xsl:otherwise>false</xsl:otherwise>
|
|
</xsl:choose>
|
|
|
|
</xsl:template>
|
|
|
|
<xsl:template name="fetch-property-instance">
|
|
<!-- the property for which the instance is sought; it is assumed that
|
|
the property passed has type 'entity' -->
|
|
<xsl:param name="property"/>
|
|
<!-- the name of the value in the returned values from which the instance
|
|
must be resolved -->
|
|
<xsl:param name="value"/>
|
|
<xsl:variable name="basetype">
|
|
<xsl:call-template name="base-type">
|
|
<xsl:with-param name="property" select="$property"/>
|
|
</xsl:call-template>
|
|
</xsl:variable>
|
|
<xsl:if test="not( $basetype='entity')">
|
|
<xsl:message terminate="yes">
|
|
ADL: ERROR: property passed to fetch-property-instance whose type is not 'entity'
|
|
</xsl:message>
|
|
</xsl:if>
|
|
hibernator.CreateCriteria(typeof(<xsl:value-of select="concat( $entityns, '.', $property/@entity)"/>))
|
|
<xsl:for-each select="//adl:entity[@name=$property/@entity]/adl:key/adl:property">
|
|
<xsl:call-template name="add-hibernate-expression-eq">
|
|
<xsl:with-param name="property" select="."/>
|
|
<xsl:with-param name="value" select="$value"/>
|
|
</xsl:call-template>
|
|
</xsl:for-each>
|
|
.UniqueResult<<xsl:value-of select="concat( $entityns, '.', $property/@entity)"/>>()
|
|
</xsl:template>
|
|
|
|
</xsl:stylesheet> |