Mercurial > pub > ModelGenerator
view xslt/model.xsl @ 9:d3542662cf70
working on members preprocessing
author | cin |
---|---|
date | Sun, 11 Mar 2018 10:27:32 +0300 |
parents | 5fe2e5724331 |
children | 19a8a71eaa54 |
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 useful 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:copy> <xsl:copy-of select="@*"/> <xsl:apply-templates mode="expand-member"/> </xsl:copy> </xsl:template> <!-- short form of primaryKey{@name, @type} --> <xsl:template match="m:primaryKey" mode="expand-member"> <xsl:variable name="pkName" select="concat(@declaringType, 'Pk')"/> <xsl:variable name="propName" select="@name" /> <xsl:variable name="specialProperty"> <m:property name="{$propName}" special="true"> <xsl:copy-of select="@*[not(self::name)]" /> <m:hiddenBy name="{$pkName}" type="{@declaringType}"/> <xsl:copy-of select="*" /> </m:property> </xsl:variable> <xsl:apply-templates select="exsl:node-set($specialProperty)" mode="expand-member"/> <xsl:copy> <xsl:attribute name="name"><xsl:value-of select="$pkName"/></xsl:attribute> <m:member name="{@name}" type="{@declaringType}"/> </xsl:copy> </xsl:template> <!-- long form of primaryKey{ member{@name}+ } --> <xsl:template match="m:primaryKey[m:member]" mode="expand-member"> <xsl:apply-templates mode="expand-member"/> </xsl:template> <!-- short form of hasA --> <xsl:template match="m:hasA" mode="expand-member"> <xsl:variable name="foreignPk"> <xsl:call-template name="getPrimaryKey"> <xsl:with-param name="type" select="@type"/> </xsl:call-template> </xsl:variable> <xsl:variable name="expandedPk"> <xsl:apply-templates select="exsl:node-set($foreignPk)" mode="expand-member"/> </xsl:variable> <xsl:variable name="resolvedPk"> <xsl:apply-templates select="exsl:node-set($expandedPk)/m:primaryKey" mode="resolve-members"/> </xsl:variable> </xsl:template> <!-- short form of hasA with matched keys specified --> <xsl:template match="m:hasA[m:thisKey]"> <xsl:apply-templates select="m:thisKey" mode="generate-fk-properties"/> <xsl:copy> <xsl:copy-of select="@*"/> <xsl:apply-templates mode="expand-member"/> </xsl:copy> </xsl:template> <xsl:template match="m:hasA/m:thisKey" mode="expand-member"> <m:member name="{@name}" matches="{@matches}"/> </xsl:template> <!-- long form of hasA --> <xsl:template match="m:hasA[m:member]" mode="expand-member"> <xsl:apply-templates mode="expand-member"/> </xsl:template> <!-- resolve expands --> <xsl:template match="m:member" mode="resolve-members"> <xsl:variable name="$name" select="@name"/> <xsl:variable name="$declaringType" select="@declaringType" /> <xsl:choose> <xsl:when test="/*[@name=$name and @declaringType=$declaringType]"> <xsl:apply-templates select="/*[@name=$name and @declaringType=$declaringType]" mode="resolve-members"/> </xsl:when> <xsl:otherwise> <xsl:variable name="fragment"> <xsl:call-template name="getMembers"> <xsl:with-param name="memberName" select="$name"/> <xsl:with-param name="type" select="$declaringType"/> </xsl:call-template> </xsl:variable> <xsl:apply-templates select="exsl:node-set($fragment)/*[not(@special)]" mode="resolve-members"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="m:property" mode="resolve-members"> <xsl:copy-of select="."/> </xsl:template> </xsl:stylesheet>