Mercurial > pub > ModelGenerator
changeset 1:7f803979305f
improved cs-dom generation, added getMember, getKeyMember templates
author | cin |
---|---|
date | Thu, 22 Feb 2018 19:14:00 +0300 |
parents | cbdada054b4a |
children | 035de8b7b18e |
files | .project data/model.xml xslt/model.xslt xslt/text-tools.xsl |
diffstat | 4 files changed, 176 insertions(+), 36 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.project Thu Feb 22 19:14:00 2018 +0300 @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>ModelGenerator</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + </buildSpec> + <natures> + </natures> +</projectDescription>
--- a/data/model.xml Wed Feb 21 03:01:53 2018 +0300 +++ b/data/model.xml Thu Feb 22 19:14:00 2018 +0300 @@ -33,7 +33,7 @@ <description>Район проведения операции, в котором будет работать данная единица. </description> - <thisKey name="RegionId" matches="Id" /> + <thisKey name="RegionId"/> </hasA> <hasA name="Operation" type="Operation" optional="true"> <description>Идентификатор операции, используется для фильтрации @@ -79,8 +79,8 @@ </property> <hasMany name="Regions" type="Region"> <description>Список районов поиска</description> - <otherKey name="OperationId" /> - <clr:association> + <otherKey name="Operation" /> + <clr:association otherKey="OperationId"> <!-- explicit otherKey for code generation --> <clr:type ref="listOf"> <clr:type ref="Region" /> </clr:type>
--- a/xslt/model.xslt Wed Feb 21 03:01:53 2018 +0300 +++ b/xslt/model.xslt Thu Feb 22 19:14:00 2018 +0300 @@ -5,6 +5,8 @@ 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:include href="text-tools.xsl"/> + <xsl:output method="xml" indent="yes" /> <xsl:key name="type" match="m:package/m:*" use="@name" /> @@ -257,30 +259,51 @@ <xsl:template match="m:hasA/clr:association" mode="property-attributes"> <cs:attribute> <cs:type name="Association" namespace="Linq2Db"/> - <cs:parameter name="thisKey">nameof(<xsl:apply-templates select="../m:thisKey" mode="property-name"/>)</cs:parameter> - <cs:parameter name="otherKey">nameof(<cs:typeName> - <xsl:apply-templates select="." mode="property-type"/> - </cs:typeName>.<xsl:call-template name="getKeyName"> - <xsl:with-param name="type" select="../@type"/> - </xsl:call-template>)</cs:parameter> + <cs:parameter name="thisKey"> + <cs:nameOf> + <xsl:call-template name="getMember"> + <xsl:with-param name="memberName" select="../@name"/> + <xsl:with-param name="explicitMemberName" select="@thisKey"/> + <xsl:with-param name="type" select="../../@name"/> + <xsl:with-param name="short" select="true()"/> + </xsl:call-template> + </cs:nameOf> + </cs:parameter> + <cs:parameter name="otherKey"> + <cs:nameOf> + <xsl:call-template name="getKeyMember"> + <xsl:with-param name="explicitMemberName" select="@thisKey"/> + <xsl:with-param name="type" select="../@type"/> + </xsl:call-template> + </cs:nameOf> + </cs:parameter> </cs:attribute> </xsl:template> + + <xsl:template match="m:hasMany/clr:association" mode="property-attributes"> <cs:attribute> <cs:type name="Association" namespace="Linq2Db"/> <!-- thisKey points to own primaryKey which may be inherited, using getKeyName to address such cases --> - <cs:parameter name="thisKey">nameof(<xsl:call-template name="getKeyName"> - <xsl:with-param name="type" select="../../@name"/> - </xsl:call-template>)</cs:parameter> - <cs:parameter name="otherKey">nameof(<cs:typeName> - <xsl:call-template name="getClrType"> + <cs:parameter name="thisKey"> + <cs:nameOf> + <xsl:call-template name="getKeyMember"> + <xsl:with-param name="type" select="../../@name"/> + <xsl:with-param name="explicitMemberName" select="@thisKey"/> + <xsl:with-param name="short" select="true()"/> + </xsl:call-template> + </cs:nameOf> + </cs:parameter> + <cs:parameter name="otherKey"> + <cs:nameOf> + <xsl:call-template name="getMember"> <xsl:with-param name="type" select="../@type"/> + <xsl:with-param name="memberName" select="../m:otherKey/@name"/> + <xsl:with-param name="explicitMemberName" select="@otherKey"/> </xsl:call-template> - </cs:typeName>.<xsl:call-template name="getClrPropertyName"> - <xsl:with-param name="member" select="../m:otherKey/@name"/> - <xsl:with-param name="type" select="../@type"/> - </xsl:call-template>)</cs:parameter> + </cs:nameOf> + </cs:parameter> </cs:attribute> </xsl:template> @@ -520,11 +543,13 @@ <xsl:template name="getClrPropertyName"> <xsl:param name="type"/> <xsl:param name="member"/> - <trace msg="getClrPropertyName {$type}.{$member}"/> + <!-- prevents cyclic references --> + <xsl:param name="seen" select="/.."/> <xsl:for-each select="exsl:node-set($fragment)"> <xsl:apply-templates select="key('type', $type)" mode="member-lookup"> <xsl:with-param name="member" select="$member"/> + <xsl:with-param name="seen" select="$seen"/> </xsl:apply-templates> </xsl:for-each> </xsl:template> @@ -533,18 +558,36 @@ <xsl:template match="m:entity" mode="member-lookup"> <xsl:param name="member"/> - <xsl:variable name="match" select="*[@name=$member]"/> - <xsl:choose> - <xsl:when test="$match"> - <xsl:apply-templates select="$match" mode="member-lookup"/> - </xsl:when> - <xsl:when test="m:extends"> - <xsl:call-template name="getClrPropertyName"> - <xsl:with-param name="type" select="m:extends/@type"/> - <xsl:with-param name="member" select="$member"/> - </xsl:call-template> - </xsl:when> - </xsl:choose> + <xsl:param name="seen"/> + <xsl:variable name="self" select="."/> + + <xsl:if test="not($seen[generate-id() = generate-id($self)])"> + <xsl:variable name="match" select="*[@name=$member]"/> + <xsl:choose> + <xsl:when test="$match"> + <xsl:apply-templates select="$match" mode="member-lookup"/> + </xsl:when> + <xsl:when test="m:extends"> + <xsl:call-template name="getClrPropertyName"> + <xsl:with-param name="type" select="m:extends/@type"/> + <xsl:with-param name="member" select="$member"/> + <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 {$member}"/> + <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> <xsl:template match="m:property | m:primaryKey" mode="member-lookup"> @@ -554,5 +597,63 @@ <xsl:template match="m:hasA" mode="member-lookup"> <xsl:apply-templates select="m:thisKey" mode="property-name"/> </xsl:template> - + + <xsl:template name="getKeyMember"> + <xsl:param name="explicitMemberName" select="''"/> + <xsl:param name="type"/> + <xsl:param name="short" select="false()"/> + <cs:member> + <xsl:choose> + <xsl:when test="$explicitMemberName"> + <xsl:attribute name="name"> + <xsl:value-of select="$explicitMemberName"/> + </xsl:attribute> + </xsl:when> + <xsl:otherwise> + <xsl:attribute name="name"> + <xsl:call-template name="getKeyName"> + <xsl:with-param name="type" select="$type"/> + </xsl:call-template> + </xsl:attribute> + </xsl:otherwise> + </xsl:choose> + <xsl:if test="not($short)"> + <xsl:call-template name="getClrType"> + <xsl:with-param name="type" select="$type"/> + </xsl:call-template> + </xsl:if> + </cs:member> + </xsl:template> + + <xsl:template name="getMember"> + <xsl:param name="memberName"/> + <xsl:param name="type"/> + <xsl:param name="explicitMemberName" select="''"/> + <xsl:param name="short" select="false()"/> + <cs:member> + <xsl:choose> + <xsl:when test="$explicitMemberName"> + <xsl:attribute name="name"> + <xsl:value-of select="$explicitMemberName"/> + </xsl:attribute> + </xsl:when> + <xsl:otherwise> + <xsl:attribute name="name"> + <xsl:call-template name="getClrPropertyName"> + <xsl:with-param name="member" select="$memberName"/> + <xsl:with-param name="type" select="$type"/> + </xsl:call-template> + </xsl:attribute> + </xsl:otherwise> + </xsl:choose> + <xsl:if test="not($short)"> + <xsl:call-template name="getClrType"> + <xsl:with-param name="type" select="$type"/> + </xsl:call-template> + </xsl:if> + </cs:member> + </xsl:template> + + + </xsl:stylesheet>
--- a/xslt/text-tools.xsl Wed Feb 21 03:01:53 2018 +0300 +++ b/xslt/text-tools.xsl Thu Feb 22 19:14:00 2018 +0300 @@ -1,8 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" - xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:t="http://implab.org/schemas/temp" + xmlns:exsl="http://exslt.org/common" extension-element-prefixes="exsl"> <!-- TEXT ROUTINES --> - <xsl:template name="write-line"> + <xsl:template name="writeLine"> <xsl:param name="level" select="0" /> <xsl:param name="text" /> <xsl:call-template name="indent"> @@ -22,7 +23,7 @@ </xsl:if> </xsl:template> - <xsl:template name="to-lower-first"> + <xsl:template name="toLowerFirst"> <xsl:param name="value" /> <xsl:variable name="smallcase" select="'abcdefghijklmnopqrstuvwxyz'" /> <xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" /> @@ -32,10 +33,37 @@ select="concat(translate($before,$uppercase,$smallcase), $after)" /> </xsl:template> - <xsl:template name="to-lower"> + <xsl:template name="toLower"> <xsl:param name="value" /> <xsl:variable name="smallcase" select="'abcdefghijklmnopqrstuvwxyz'" /> <xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" /> <xsl:value-of select="translate($value,$uppercase,$smallcase)" /> </xsl:template> + + <xsl:template name="warn"> + <xsl:param name="msg" /> + <xsl:message terminate="no"> + <xsl:apply-templates select="exsl:node-set($msg)" + mode="trace" /> + </xsl:message> + </xsl:template> + + <xsl:template name="error"> + <xsl:param name="msg" /> + <xsl:message terminate="no"> + <xsl:apply-templates select="exsl:node-set($msg)" + mode="trace" /> + </xsl:message> + </xsl:template> + + <xsl:template match="t:trace" mode="trace"> + <xsl:param name="level" select="0" /> + <xsl:call-template name="writeLine"> + <xsl:with-param name="text" select="@msg" /> + <xsl:with-param name="level" select="$level" /> + </xsl:call-template> + <xsl:apply-templates mode="trace"> + <xsl:with-param name="level" select="$level + 1" /> + </xsl:apply-templates> + </xsl:template> </xsl:stylesheet> \ No newline at end of file