Mercurial > pub > ModelGenerator
view xslt/model.xsl @ 8:5fe2e5724331
sync
author | cin |
---|---|
date | Wed, 07 Mar 2018 15:54:22 +0300 |
parents | 3fe157be5141 |
children | d3542662cf70 |
line wrap: on
line source
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:m="http://implab.org/schemas/data-model.v1.xsd" xmlns:clr="http://implab.org/schemas/data-model/dotnet.v1.xsd" xmlns:cs="http://implab.org/schemas/code-dom/csharp.v1.xsd" xmlns:sql="http://implab.org/schemas/data-model/sql.v1.xsd" xmlns:t="http://implab.org/schemas/temp" xmlns:exsl="http://exslt.org/common" exclude-result-prefixes="clr m xsl exsl sql"> <xsl:import href="preprocess.xsl" /> <xsl:include href="text-tools.xsl"/> <xsl:output method="xml" indent="yes" /> <xsl:key name="type" match="m:package/m:*" use="@name" /> <xsl:template match="/"> <cs:document> <xsl:apply-templates select="$module" mode="document" /> </cs:document> </xsl:template> <!-- code generation --> <!-- disable default template --> <xsl:template match="*|text()" mode="document" /> <xsl:template match="t:module" mode="document"> <xsl:apply-templates mode="document" /> </xsl:template> <!-- member resolution traits --> <!-- Resolves members using given criteria @param type the name of the type whose members are inspected @param memberName the name of the member to lookup @param scope the scope where to look (members, properties, keys, relations) This template recursively inspects the given type down to it's inheritance hierarchy and outputs members matching criteria. --> <xsl:template name="getMembers"> <xsl:param name="type"/> <xsl:param name="memberName" select="''"/> <xsl:param name="scope" select="'members'"/> <!-- prevents cyclic references --> <xsl:param name="seen" select="/.."/> <xsl:for-each select="$module"> <xsl:apply-templates select="key('type', $type)" mode="lookup-members"> <xsl:with-param name="memberName" select="$memberName"/> <xsl:with-param name="scope" select="$scope"/> <xsl:with-param name="seen" select="$seen"/> </xsl:apply-templates> </xsl:for-each> </xsl:template> <xsl:template match="*" mode="lookup-members"/> <xsl:template match="m:entity" mode="lookup-members"> <xsl:param name="memberName" select="''"/> <xsl:param name="scope" select="'members'"/> <xsl:param name="seen"/> <xsl:variable name="self" select="."/> <xsl:if test="not($seen[generate-id() = generate-id($self)])"> <xsl:variable name="scopeMembers"> <xsl:call-template name="selectScopeMembers"> <xsl:with-param name="scope" select="$scope"/> </xsl:call-template> </xsl:variable> <xsl:variable name="members" select="exsl:node-set($scopeMembers)/*[not($memberName) or @name=$memberName]"/> <xsl:choose> <xsl:when test="$members"> <xsl:copy-of select="$members"/> </xsl:when> <xsl:when test="m:extends"> <xsl:call-template name="getMembers"> <xsl:with-param name="type" select="m:extends/@type"/> <xsl:with-param name="memberName" select="$memberName"/> <xsl:with-param name="scope" select="$scope"/> <xsl:with-param name="seen" select="$seen | $self"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:call-template name="warn"> <xsl:with-param name="msg"> <t:trace msg="failed to resolve {$memberName}, scope={$scope}"/> <t:trace msg="inspected classes"> <xsl:for-each select="$seen | $self"> <t:trace msg="{name()} {@name}"/> </xsl:for-each> </t:trace> </xsl:with-param> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:if> </xsl:template> <!-- this template implements scope filtering --> <xsl:template name="selectScopeMembers"> <xsl:param name="scope" select="'members'"/> <xsl:choose> <xsl:when test="$scope='members'"> <xsl:apply-templates mode="filter-members"/> </xsl:when> <xsl:when test="$scope='keys'"> <xsl:apply-templates mode="filter-keys"/> </xsl:when> <xsl:when test="$scope='properties'"> <xsl:apply-templates mode="fiflter-properties"/> </xsl:when> <xsl:when test="$scope='relations'"> <xsl:apply-templates mode="fiflter-relations"/> </xsl:when> </xsl:choose> </xsl:template> <!-- filter-members --> <xsl:template match="*|text()" mode="filter-members"/> <xsl:template match="*[@name]" mode="filter-members"> <xsl:copy> <xsl:copy-of select="@*" /> <xsl:attribute name="declaringType"><xsl:value-of select="../@name" /></xsl:attribute> <xsl:copy-of select="*" /> </xsl:copy> </xsl:template> <!-- filter-keys --> <xsl:template match="*|text()" mode="filter-keys"/> <xsl:template match="m:primaryKey" mode="filter-keys"> <xsl:apply-templates select="." mode="filter-members"/> </xsl:template> <!-- filter-properties --> <xsl:template match="*|text()" mode="filter-properties"/> <xsl:template match="m:property" mode="filter-properties"> <xsl:apply-templates select="." mode="filter-members"/> </xsl:template> <!-- filter-relations --> <xsl:template match="*|text()" mode="filter-relations"/> <xsl:template match="m:hasA | m:hasMany" mode="filter-relations"> <xsl:apply-templates select="." mode="filter-members"/> </xsl:template> <!-- Resolves primaryKey information for the given type name. @returns m:primaryKey node copy with additional attribute @declaringType which points to the type where this primaryKey was defined. --> <xsl:template name="getPrimaryKey"> <xsl:param name="type" /> <xsl:call-template name="getMembers"> <xsl:with-param name="type" select="$type"/> <xsl:with-param name="scope" select="'keys'"/> </xsl:call-template> </xsl:template> <!-- expand-member templates are used to process relations and keys and provide usefull information. This mode is designed to recursively traverse members expanding details like special properties generated by relations. expand-member-reference is special mode used to traverse inside members which are referenced from relations. By default this mode does nothing. Use this templates to produce intermediate model for further processing by specific code-generators. @special - means that the member is a composite part and isn't accessible directly --> <xsl:template match="*" mode="expand-member"> <xsl:apply-templates mode="expand-member"/> </xsl:template> <xsl:template match="text()" mode="expand-member"/> <xsl:template match="*|text()" mode="expand-member-reference"/> <!-- short form of primaryKey{@name, @type} --> <xsl:template match="m:primaryKey" mode="expand-member"> <xsl:variable name="specialProperty"> <m:property special="true"> <xsl:copy-of select="@*" /> <m:hiddenBy name="{@name}" type="{@declaringType}"/> <xsl:copy-of select="*" /> </m:property> </xsl:variable> <xsl:apply-templates select="exsl:node-set($specialProperty)" mode="expand-member"/> <xsl:apply-templates mode="expand-member"/> </xsl:template> <!-- long form of primaryKey{ member{@name}+, property{@name, @type} } --> <xsl:template match="m:primaryKey[m:member | m:property]" mode="expand-member"> <xsl:apply-templates mode="expand-member"/> </xsl:template> <!-- properties declared inside relations, they are @special --> <xsl:template match="m:primaryKey/m:property | m:thisKey/m:property" mode="expand-member"> <xsl:variable name="specialProperty"> <xsl:copy> <xsl:attribute name="special">true</xsl:attribute> <xsl:copy-of select="@*"/> <m:hiddenBy name="{@name}" type="{@declaringType}"/> <xsl:copy-of select="*"/> </xsl:copy> </xsl:variable> <xsl:apply-templates select="exsl:node-set($specialProperty)" mode="expand-member"/> </xsl:template> <!-- traverse inside referenced members --> <xsl:template match="m:member" mode="expand-member"> <xsl:param name="declaringType"/> <xsl:variable name="expanded"> <xsl:call-template name="getMembers"> <xsl:with-param name="memberName" select="@name"/> <xsl:with-param name="type" select="$declaringType"/> </xsl:call-template> </xsl:variable> <!-- recusive expand --> <xsl:apply-templates select="exsl:node-set($expanded)" mode="expand-member-reference"/> </xsl:template> <xsl:template match="m:hasA/m:thisKey" mode="expand-member"> <xsl:variable name="otherKey"> <xsl:call-template name="getPrimaryKey"> <xsl:with-param name="type" select="../@type"/> </xsl:call-template> </xsl:variable> <xsl:variable name="otherKeyExpanded"> <xsl:apply-templates select="exsl:node-set($otherKey)" mode="expand-member"/> </xsl:variable> <xsl:variable name="pk" select="exsl:node-set($otherKeyExpanded)[1]"/> <m:property name="{@name}" type="{$pk/@type}" hidden="true"> <m:related name="{$pk/@name}" type="{../@type}"/> </m:property> </xsl:template> <xsl:template match="m:thisKey[m:member | property]"> <xsl:apply-templates mode="expand-member"/> </xsl:template> </xsl:stylesheet>