Mercurial > pub > ModelGenerator
view xslt/model.xsl @ 7:3fe157be5141
sync
author | cin |
---|---|
date | Tue, 06 Mar 2018 19:27:25 +0300 |
parents | 1f4009d4afb6 |
children | 5fe2e5724331 |
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 like properties of the entity which are members of this relation or key. @special - means that the member is a composite part and isn't accessible directly --> <!-- short form of primaryKey{@name, @type} --> <xsl:template match="m:primaryKey" mode="expand-member"> <xsl:copy> <xsl:copy-of select="@*"/> <m:property special="true"> <xsl:copy-of select="@*" /> <xsl:copy-of select="*" /> </m:property> </xsl:copy> </xsl:template> <!-- long form of primaryKey{ member{@name}+, property{@name, @type} } --> <xsl:template match="m:primaryKey[m:member | m:property]" mode="expand-member"> <xsl:copy> <xsl:copy-of select="@*"/> <xsl:apply-templates mode="expand-member"/> </xsl:copy> </xsl:template> <!-- stand alone properties --> <xsl:template match="m:property" mode="expand-member"> <xsl:copy-of select="."/> </xsl:template> <!-- properties declared inside relations, they are @special --> <xsl:template match="m:primaryKey/m:property | m:thisKey/m:property" mode="expand-member"> <xsl:copy> <xsl:attribute name="special">true</xsl:attribute> <xsl:copy-of select="@*"/> <xsl:copy-of select="*"/> </xsl:copy> </xsl:template> <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"/> </xsl:template> <xsl:template match="m:hasA" mode="expand-member"> <xsl:copy> <xsl:copy-of select="@*"/> <xsl:apply-templates mode="expand-member"/> </xsl:copy> </xsl:template> <xsl:template match="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>