<?xml version="1.0" encoding="UTF-8" ?> <xsl:stylesheet version="1.0" xmlns="urn:nhibernate-mapping-2.2" xmlns:adl="http://bowyer.journeyman.cc/adl/1.4/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- Application Description Framework adl2hibernate.xsl (c) 2007 Cygnet Solutions Ltd Transform ADL to Hibernate $Author: simon $ $Revision: 1.11 $ --> <xsl:param name="namespace"/> <xsl:param name="assembly"/> <xsl:param name="database"/> <!-- whether or not we want lazy initialisation of lists. Lazy initialisation is economic of memory and of startup time, and works well in things which are essentially atomic like Web transactions; but can lead to gnarly bugs. Values: 'true' (default) or 'false' - anything else will result in an error --> <xsl:param name="lazy" select="'true'"/> <!-- the name and version of the product being built --> <xsl:param name="product-version" select="'Application Description Language Framework'"/> <!-- the convention to use for fieldnames in link tables: Name - the name of the foreign key is the same as the name of the table linked to NameId - the name of the foreign key is the same as the name of the table linked to, followed by 'Id' Name_Id - the name of the foreign key is the same as the name of the table linked to, followed by '_Id' Name_Link - the name of the foreign key is the same as the name of the table linked to, followed by '_Link' --> <xsl:param name="linktable-field-name-convention" select="Name"/> <xsl: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:include href="csharp-type-include.xslt"/> <xsl:variable name="dbprefix"> <xsl:choose> <xsl:when test="string-length( $database) > 0"> <xsl:value-of select="concat( $database, '.dbo.')"/> </xsl:when> <xsl:otherwise/> </xsl:choose> </xsl:variable> <!-- define upper and lower case letters to enable case conversion --> <xsl:variable name="ucase">ABCDEFGHIJKLMNOPQRSTUVWXYZ</xsl:variable> <xsl:variable name="lcase">abcdefghijklmnopqrstuvwxyz</xsl:variable> <!-- define SQL keywords to police these out of field names --> <xsl:variable name="sqlkeywords-multiline"> ADD EXCEPT PERCENT ALL EXEC PLAN ALTER EXECUTE PRECISION AND EXISTS PRIMARY ANY EXIT PRINT AS FETCH PROC ASC FILE PROCEDURE AUTHORIZATION FILLFACTOR PUBLIC BACKUP FOR RAISERROR BEGIN FOREIGN READ BETWEEN FREETEXT READTEXT BREAK FREETEXTTABLE RECONFIGURE BROWSE FROM REFERENCES BULK FULL REPLICATION BY FUNCTION RESTORE CASCADE GOTO RESTRICT CASE GRANT RETURN CHECK GROUP REVOKE CHECKPOINT HAVING RIGHT CLOSE HOLDLOCK ROLLBACK CLUSTERED IDENTITY ROWCOUNT COALESCE IDENTITY_INSERT ROWGUIDCOL COLLATE IDENTITYCOL RULE COLUMN IF SAVE COMMIT IN SCHEMA COMPUTE INDEX SELECT CONSTRAINT INNER SESSION_USER CONTAINS INSERT SET CONTAINSTABLE INTERSECT SETUSER CONTINUE INTO SHUTDOWN CONVERT IS SOME CREATE JOIN STATISTICS CROSS KEY SYSTEM_USER CURRENT KILL TABLE CURRENT_DATE LEFT TEXTSIZE CURRENT_TIME LIKE THEN CURRENT_TIMESTAMP LINENO TO CURRENT_USER LOAD TOP CURSOR NATIONAL TRAN DATABASE NOCHECK TRANSACTION DBCC NONCLUSTERED TRIGGER DEALLOCATE NOT TRUNCATE DECLARE NULL TSEQUAL DEFAULT NULLIF UNION DELETE OF UNIQUE DENY OFF UPDATE DESC OFFSETS UPDATETEXT DISK ON USE DISTINCT OPEN USER DISTRIBUTED OPENDATASOURCE VALUES DOUBLE OPENQUERY VARYING DROP OPENROWSET VIEW DUMMY OPENXML WAITFOR DUMP OPTION WHEN ELSE OR WHERE END ORDER WHILE ERRLVL OUTER WITH ESCAPE OVER WRITETEXT </xsl:variable> <xsl:variable name="sqlkeywords" select="concat(' ', normalize-space($sqlkeywords-multiline), ' ')"/> <xsl:template match="adl:application"> <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> *************************************************************************** * * <xsl:value-of select="$product-version"/> * <xsl:value-of select="@name"/>.auto.hbm.xml * * ©2007 Cygnet Solutions Ltd * * THIS FILE IS AUTOMATICALLY GENERATED AND SHOULD NOT * BE MANUALLY EDITED. * * <xsl:value-of select="@revision"/> * * Generated using adl2hibernate.xslt revision <xsl:value-of select="substring('$Revision: 1.11 $', 12)"/> * *************************************************************************** </xsl:comment> <xsl:apply-templates select="adl:entity"/> </hibernate-mapping> </xsl:template> <xsl:template match="adl:group"> <xsl:comment> Authentication check table for security group <xsl:value-of select="@name"/> </xsl:comment> <xsl:apply-templates select="adl:documentation"/> <xsl:variable name="prefix"> <xsl:choose> <xsl:when test="string-length( $database) > 0"> <xsl:value-of select="concat( $database, '.dbo.')"/> </xsl:when> <xsl:otherwise/> </xsl:choose> </xsl:variable> <class> <xsl:attribute name="name"> <xsl:value-of select="concat( 'AuthCheck', @name)"/> </xsl:attribute> <xsl:attribute name="table"> <xsl:value-of select="concat( $prefix, '[', @table, ']')"/> </xsl:attribute> <id name="Check" column="Check" type="int"> <generator class="native"/> </id> </class> </xsl:template> <xsl:template match="adl:entity[@foreign='true']"/> <xsl:template match="adl:entity"> <xsl:apply-templates select="adl:documentation"/> <xsl:variable name="prefix"> <xsl:choose> <xsl:when test="string-length( $database) > 0"> <xsl:value-of select="concat( $database, '.dbo.')"/> </xsl:when> <xsl:otherwise/> </xsl:choose> </xsl:variable> <class> <xsl:attribute name="name"> <xsl:value-of select="@name"/> </xsl:attribute> <xsl:attribute name="table"> <xsl:choose> <xsl:when test="@table"> <xsl:value-of select="concat( $prefix, '[', @table, ']')"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="concat( $prefix, '[', @name, ']')"/> </xsl:otherwise> </xsl:choose> </xsl:attribute> <xsl:apply-templates select="adl:key"/> <xsl:apply-templates select="adl:property"/> </class> </xsl:template> <xsl:template match="adl:key"> <xsl:choose> <xsl:when test="count( adl:property) = 0"> </xsl:when> <xsl:when test="count( adl:property) = 1"> <id> <xsl:attribute name="name"> <xsl:value-of select="adl:property[position()=1]/@name"/> </xsl:attribute> <xsl:attribute name="column"> <xsl:call-template name="property-column-name"> <xsl:with-param name="property" select="adl:property[position()=1]"/> </xsl:call-template> </xsl:attribute> <xsl:attribute name="type"> <xsl:call-template name="csharp-base-type"> <xsl:with-param name="property" select="adl:property[position()=1]"/> </xsl:call-template> </xsl:attribute> <xsl:choose> <xsl:when test="adl:property[position()=1]/adl:generator"> <xsl:attribute name="name"> <xsl:value-of select="adl:property[position()=1]/@name"/> </xsl:attribute> <xsl:apply-templates select="adl:property[position()=1]/adl:generator"/> </xsl:when> <xsl:when test="adl:property[position()=1 and @type='entity']"> <xsl:attribute name="name"> <xsl:value-of select="concat( adl:property[position()=1]/@name, '_Value')"/> </xsl:attribute> <xsl:variable name="entityname" select="adl:property[position()=1]/@entity"/> <xsl:variable name="farkey"> <xsl:choose> <xsl:when test="adl:property[position()=1]/@farkey"> <xsl:value-of select="adl:property[position()=1]/@farkey"/> </xsl:when> <xsl:when test="//adl:entity[@name=$entityname]/adl:key/adl:property"> <xsl:value-of select="//adl:entity[@name=$entityname]/adl:key/adl:property[position()=1]/@name"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="'[unkown?]'"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <generator class="foreign"> <param name="property"> <xsl:value-of select="$farkey"/> </param> </generator> </xsl:when> <xsl:otherwise> <xsl:comment>TODO: remember you need to deal with this in manually maintained code</xsl:comment> <generator class="assigned"/> </xsl:otherwise> </xsl:choose> </id> <xsl:if test="adl:property[position()=1 and @type='entity']"> <xsl:apply-templates select="adl:property[position()=1]"/> </xsl:if> </xsl:when> <xsl:otherwise> <composite-id> <!-- xsl:attribute name="name"> <xsl:choose> <xsl:when test="$abstract-key-name-convention='Name'"> <xsl:value-of select="ancestor::adl:entity/@name"/> </xsl:when> <xsl:when test="$abstract-key-name-convention = 'NameId'"> <xsl:value-of select="concat( ancestor::adl:entity/@name, 'Id')"/> </xsl:when> <xsl:when test="$abstract-key-name-convention = 'Name_Id'"> <xsl:value-of select="concat( ancestor::adl:entity/@name, '_Id')"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="'Id'"/> </xsl:otherwise> </xsl:choose> </xsl:attribute --> <xsl:for-each select="adl:property[not(@type='entity')]"> <key-property> <xsl:attribute name="name"> <xsl:value-of select="@name"/> </xsl:attribute> <xsl:attribute name="column"> <xsl:call-template name="property-column-name"> <xsl:with-param name="property" select="."/> </xsl:call-template> </xsl:attribute> <xsl:attribute name="type"> <xsl:call-template name="csharp-type"> <xsl:with-param name="property" select="."/> </xsl:call-template> </xsl:attribute> <xsl:apply-templates select="adl:documentation"/> </key-property> </xsl:for-each> <xsl:for-each select="adl:property[@type='entity']"> <key-many-to-one> <xsl:attribute name="name"> <xsl:value-of select="@name"/> </xsl:attribute> <xsl:attribute name="column"> <xsl:call-template name="property-column-name"> <xsl:with-param name="property" select="."/> </xsl:call-template> </xsl:attribute> <xsl:attribute name="class"> <xsl:value-of select="@entity"/> </xsl:attribute> <xsl:choose> <xsl:when test="@cascade='manual'"/> <xsl:when test="@cascade"> <xsl:attribute name="cascade"> <xsl:value-of select="@cascade"/> </xsl:attribute> </xsl:when> </xsl:choose> <xsl:apply-templates select="adl:documentation"/> </key-many-to-one> </xsl:for-each> </composite-id> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="adl:generator"> <generator> <xsl:attribute name="class"> <xsl:choose> <xsl:when test="@action='manual'"> <xsl:value-of select="@class"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="@action"/> </xsl:otherwise> </xsl:choose> </xsl:attribute> </generator> </xsl:template> <xsl:template match="adl:property[@concrete='false']"> <!-- properties which are not concrete are by definition not stored in the database --> </xsl:template> <xsl:template match="adl:property[@type='message']"> <xsl:choose> <xsl:when test="@concrete='false'"/> <xsl:otherwise> <many-to-one class="Message"> <xsl:attribute name="name"> <xsl:value-of select="@name"/> </xsl:attribute> <xsl:if test="@column"> <xsl:attribute name="column"> <xsl:call-template name="property-column-name"> <xsl:with-param name="property" select="."/> </xsl:call-template> </xsl:attribute> </xsl:if> </many-to-one> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="adl:property[@type='entity']"> <!-- a property of type entity translates to a Hibernate many-to-one, unless it's part of the key, in which case it translates as one-to-one. TODO: Check this logic! --> <!-- xsl:choose> <xsl:when test="parent::adl:key"> <one-to-one> <xsl:attribute name="name"> <xsl:value-of select="@name"/> </xsl:attribute> <xsl:attribute name="class"> <xsl:value-of select="@entity"/> </xsl:attribute> <xsl:if test="@farkey"> <xsl:attribute name="property-ref"> <xsl:value-of select="@farkey"/> </xsl:attribute> </xsl:if> <xsl:choose> <xsl:when test="@cascade='manual'"/> <xsl:when test="@cascade"> <xsl:attribute name="cascade"> <xsl:value-of select="@cascade"/> </xsl:attribute> </xsl:when> </xsl:choose> <xsl:apply-templates select="adl:documentation"/> </one-to-one> </xsl:when> <xsl:otherwise --> <xsl:choose> <xsl:when test="@concrete='false'"/> <xsl:otherwise> <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> <xsl:attribute name="column"> <xsl:call-template name="property-column-name"> <xsl:with-param name="property" select="."/> </xsl:call-template> </xsl:attribute> <xsl:if test="@farkey"> <xsl:attribute name="property-ref"> <xsl:value-of select="@farkey"/> </xsl:attribute> </xsl:if> <xsl:choose> <xsl:when test="@cascade='manual'"/> <xsl:when test="@cascade"> <xsl:attribute name="cascade"> <xsl:value-of select="@cascade"/> </xsl:attribute> </xsl:when> </xsl:choose> <xsl:apply-templates select="adl:documentation"/> </many-to-one> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="adl:property[@type='list']"> <xsl:choose> <xsl:when test="@concrete='false'"/> <xsl:otherwise> <xsl:variable name="farent" select="@entity"/> <xsl:variable name="nearent" select="ancestor::adl: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::adl:entity/@name"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <set> <xsl:attribute name="name"> <xsl:value-of select="@name"/> </xsl:attribute> <xsl:attribute name="lazy"> <xsl:value-of select="$lazy"/> </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="//adl:entity[@name=$farent]/adl:property[@name=$farkey and @entity=$nearent]">true</xsl:when> <xsl:otherwise>false</xsl:otherwise> </xsl:choose> </xsl:attribute> <xsl:attribute name="cascade"> <xsl:choose> <xsl:when test="@cascade"> <xsl:value-of select="@cascade"/> </xsl:when> <xsl:otherwise>all</xsl:otherwise> </xsl:choose> </xsl:attribute> <xsl:choose> <xsl:when test="@cascade='manual'"/> <xsl:when test="@cascade"> <xsl:attribute name="cascade"> <xsl:value-of select="@cascade"/> </xsl:attribute> </xsl:when> </xsl:choose> <xsl:apply-templates select="adl:documentation"/> <!-- 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:call-template name="maybe-escape-keyword"> <xsl:with-param name="unescaped" select="$farkey"/> </xsl:call-template> </xsl:attribute> </key> <one-to-many> <xsl:attribute name="class"> <xsl:value-of select="@entity"/> </xsl:attribute> </one-to-many> </set> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="adl:property[@type='link']"> <!-- a property of type 'link' maps on to a Hibernate set --> <xsl:choose> <xsl:when test="@concrete='false'"/> <xsl:otherwise> <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( $dbprefix, 'ln_', ../@name, '_', @entity)"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="concat( $dbprefix, 'ln_', @entity, '_', ../@name)"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <set> <xsl:attribute name="name"> <xsl:value-of select="@name"/> </xsl:attribute> <xsl:attribute name="lazy"> <xsl:value-of select="$lazy"/> </xsl:attribute> <xsl:attribute name="table"> <xsl:value-of select="$tablename"/> </xsl:attribute> <xsl:attribute name="cascade"> <xsl:choose> <xsl:when test="@cascade"> <xsl:value-of select="@cascade"/> </xsl:when> <xsl:otherwise>all</xsl:otherwise> </xsl:choose> </xsl:attribute> <xsl:apply-templates select="adl:documentation"/> <xsl:variable name="linksuffix"> <xsl:choose> <xsl:when test="$linktable-field-name-convention = 'Name'"/> <xsl:when test="$linktable-field-name-convention = 'NameId'"> <xsl:value-of select="'Id'"/> </xsl:when> <xsl:when test="$linktable-field-name-convention = 'Name_Id'"> <xsl:value-of select="'_Id'"/> </xsl:when> <xsl:when test="$linktable-field-name-convention = 'NameLink'"> <xsl:value-of select="'Link'"/> </xsl:when> <xsl:when test="$linktable-field-name-convention = 'Name_Link'"> <xsl:value-of select="'_Link'"/> </xsl:when> </xsl:choose> </xsl:variable> <key> <xsl:attribute name="column"> <xsl:call-template name="maybe-escape-keyword"> <xsl:with-param name="unescaped" select="concat( ../@name, $linksuffix)"/> </xsl:call-template> </xsl:attribute> </key> <many-to-many> <xsl:attribute name="column"> <xsl:choose> <xsl:when test="../@name = @entity"> <xsl:value-of select="concat( @entity, '_1', $linksuffix)"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="concat( @entity, $linksuffix)"/> </xsl:otherwise> </xsl:choose> </xsl:attribute> <xsl:attribute name="class"> <xsl:value-of select="@entity"/> </xsl:attribute> </many-to-many> </set> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="adl: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:call-template name="csharp-type"> <xsl:with-param name="property" select="."/> </xsl:call-template> </xsl:attribute> <xsl:attribute name="column"> <xsl:call-template name="property-column-name"> <xsl:with-param name="property" select="."/> </xsl:call-template> </xsl:attribute> <xsl:apply-templates select="adl:documentation"/> </property> </xsl:template> <xsl:template match="adl:documentation"> <xsl:choose> <xsl:when test="ancestor::adl:documentation"/> <xsl:otherwise> <xsl:comment> <xsl:apply-templates/> </xsl:comment> </xsl:otherwise> </xsl:choose> </xsl:template> <!-- consistent, repeatable way of getting the column name for a given property --> <xsl:template name="property-column-name"> <!-- a property element --> <xsl:param name="property"/> <xsl:call-template name="maybe-escape-keyword"> <xsl:with-param name="unescaped"> <xsl:choose> <xsl:when test="$property/@column"> <xsl:value-of select="$property/@column"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$property/@name"/> </xsl:otherwise> </xsl:choose> </xsl:with-param> </xsl:call-template> </xsl:template> <!-- if the string passed as a parameter is an SQL keyword, escape it with square brackets; else return it as is.--> <xsl:template name="maybe-escape-keyword"> <xsl:param name="unescaped"/> <xsl:choose> <xsl:when test="contains( $sqlkeywords, concat(' ', translate( $unescaped, $lcase, $ucase),' '))"> <xsl:value-of select="concat( '[', $unescaped, ']')"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$unescaped"/> </xsl:otherwise> </xsl:choose> </xsl:template> <!-- horrible, horrible hackery. Compare two strings and return * 0 if they are identical, * -1 if the first is earlier in the default collating sequence, * 1 if the first is later. In XSL 2.0 this could be done using the compare(string, string) function. 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>