diff options
Diffstat (limited to 'src')
69 files changed, 25210 insertions, 0 deletions
diff --git a/src/current/.gitignore b/src/current/.gitignore new file mode 100644 index 0000000..2460008 --- /dev/null +++ b/src/current/.gitignore @@ -0,0 +1 @@ +!Makefile diff --git a/src/current/Makefile b/src/current/Makefile new file mode 100644 index 0000000..dc6eb54 --- /dev/null +++ b/src/current/Makefile @@ -0,0 +1,8 @@ + +.PHONY: dslc clean + +dslc: + $(MAKE) -C src/ dslc + +clean: + $(MAKE) -C src/ clean diff --git a/src/current/c1map.xsl b/src/current/c1map.xsl new file mode 100644 index 0000000..660fdf7 --- /dev/null +++ b/src/current/c1map.xsl @@ -0,0 +1,383 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> +<!-- + Generates PHP code that works with the LoVullo ConceptOne import system + + This map expects that the data are available in the bucket provided by the + quote and therefore validates against a provided Program UI source file. Data + external to the bucket may be provided if it is indicated as such. + + Each map source file is independent; variables and values do not bleed into + one-another, unless explicitly passed. +--> +<xsl:stylesheet version="2.0" + xmlns:c1="http://www.epic-premier.com/XMLSchema" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:lvm="http://www.lovullo.com/rater/map/c1" + xmlns:lvmp="http://www.lovullo.com/rater/map/c1/pp"> + +<xsl:output + indent="yes" + omit-xml-declaration="yes" + /> + +<!-- newline --> +<xsl:variable name="lvmp:nl" select="' '" /> + +<xsl:include href="c1map/c1nodes.xsl" /> +<xsl:include href="c1map/valparse.xsl" /> +<xsl:include href="c1map/render.xsl" /> + +<!-- + Represents the root of the source document that processing was initiated upon +--> +<xsl:variable name="orig-root" select="/" /> + + +<!-- + The root node +--> +<xsl:template match="lvm:c1-map" priority="5"> + <!-- populated by includes, if any --> + <xsl:param name="args" /> + + <xsl:message select="$args" /> + + <!-- get the name from the first C1 node --> + <xsl:variable name="name" select=" + if ( @id ) then + @id + else + concat( translate( c1:*[1]/name(), '_', '' ), 'Composer' ) + " /> + + <!-- preprocessed result --> + <xsl:variable name="pp-result"> + <lvmp:root program="{@program}" name="{$name}"> + <!-- introduce outer scope for variables --> + <lvmp:scope id=""> + <xsl:apply-templates /> + </lvmp:scope> + </lvmp:root> + </xsl:variable> + + <!-- final processing --> + <xsl:variable name="result"> + <xsl:apply-templates select="$pp-result/lvmp:root" mode="lvmp:render" /> + </xsl:variable> + + <!-- remove escapes --> + <xsl:value-of disable-output-escaping="yes" select="$result" /> +</xsl:template> + + +<!-- + Include another source map file relative to the path of the original source + file + + The attributes @name and @for-each are special and cannot be used as + arguments to the template. The special @for-each attribute will be copied + into each of the children of the root node in the template as @lvm:for-each. + For example, if the template consists of + + <c1-map> + <Product> + </Product> + </c1-map> + + then <lvm:include for-each="foo" /> would produce + + <c1-map> + <Product lvm:for-each="foo"> + </Product> + </c1-map> +--> +<xsl:template match="lvm:include" priority="5"> + <xsl:message>[c1map] +<xsl:value-of select="@name" /></xsl:message> + + <xsl:variable name="src" select=" + document( concat( @name, '.xml' ), $orig-root )/lvm:c1-map + " /> + + <xsl:if test="not( $src )"> + <xsl:message terminate="yes">fatal: c1-map node not found</xsl:message> + </xsl:if> + + <!-- process the body of the c1-map; we don't want to process the root node, + as that would start processing from scratch, prematurely rendering the result --> + <lvmp:scope id="/{@name}"> + <!-- arguments are included as attributes --> + <xsl:variable name="args" select=" + @*[ not( local-name()='name' or local-name()='for-each' ) ] + " /> + <xsl:variable name="for-each" select="@for-each" /> + + <!-- augment the XML with our own mappings --> + <xsl:variable name="augmented"> + <lvm:c1-map> + <xsl:copy-of select="$src/@*" /> + + <xsl:for-each select="$src/lvm:param"> + <xsl:call-template name="lvmp:param-to-map"> + <xsl:with-param name="args" select="$args" /> + <xsl:with-param name="param" select="." /> + <xsl:with-param name="context" select="/lvm:c1-map" /> + </xsl:call-template> + </xsl:for-each> + + + <xsl:choose> + <!-- if @for-each was provided, then apply to all first-level + children of the included template --> + <xsl:when test="$for-each"> + <!-- we will need to expose the mapping --> + <!-- TODO: need to validate that it actually exists --> + <lvm:external name="{$for-each}" /> + + <xsl:for-each select="$src/*"> + <xsl:copy> + <xsl:copy-of select="@*" /> + <xsl:attribute name="lvm:for-each" select="$for-each" /> + <xsl:copy-of select="*|text()" /> + </xsl:copy> + </xsl:for-each> + </xsl:when> + + <!-- no @for-each; just do a quick copy of all the nodes --> + <xsl:otherwise> + <xsl:copy-of select="$src/*" /> + </xsl:otherwise> + </xsl:choose> + </lvm:c1-map> + </xsl:variable> + + <xsl:apply-templates select="$augmented/lvm:c1-map/*" /> + </lvmp:scope> + + <xsl:message>[c1map] -<xsl:value-of select="@name" /></xsl:message> +</xsl:template> + + +<!-- + Processes a template param into mappings + + This will generate the mappings necessary to process the template as though + it was hard-coded with the imported mappings. + + The {} brace syntax denotes a variable, but mixing values and inline + variables are not supported. +--> +<xsl:template name="lvmp:param-to-map"> + <xsl:param name="args" /> + <xsl:param name="param" /> + <xsl:param name="context" /> + + <xsl:variable name="name" select="$param/@name" /> + <xsl:variable name="arg" select="$args[ local-name()=$name ]" /> + <xsl:variable name="argvar" select="substring-after( $arg, '{' )" /> + + <xsl:if test="$argvar and not( $argvar='' )"> + <xsl:variable name="varname" select="substring-before( $argvar, '}' )" /> + + <lvmp:translate name="{$name}" to="{$varname}" /> + + <xsl:variable name="predot" select="substring-before( $varname, '.' )" /> + + <xsl:choose> + <!-- no dot; output the entire thing --> + <xsl:when test="$predot = ''"> + <lvm:external name="{$varname}" /> + </xsl:when> + + <!-- multi-level var --> + <xsl:otherwise> + <lvm:external name="{$predot}" dict="true" lvmp:no-validate="true" /> + </xsl:otherwise> + </xsl:choose> + </xsl:if> + + <!-- TODO: no need to do this if the above conditional matches --> + <lvm:map to="{$name}" lvmp:allow-default="true"> + <xsl:copy-of select="$param/@dict" /> + <xsl:copy-of select="$param/@default" /> + + <xsl:choose> + <xsl:when test="$arg"> + <!-- determines if we have a variable --> + + <xsl:choose> + <xsl:when test="$argvar and not( $argvar='' )"> + <xsl:attribute name="from" + select="substring-before( $argvar, '}' )" /> + </xsl:when> + + <!-- static value --> + <xsl:otherwise> + <xsl:attribute name="value" select="$arg" /> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + + <!-- required param --> + <xsl:when test="$param/@required"> + <xsl:message terminate="yes"> + <xsl:text>error: missing required template argument `</xsl:text> + <xsl:value-of select="$name" /> + <xsl:text>'</xsl:text> + </xsl:message> + </xsl:when> + + <!-- otherwise, we have no value --> + <xsl:otherwise> + <xsl:attribute name="value" select="''" /> + </xsl:otherwise> + </xsl:choose> + </lvm:map> +</xsl:template> + + +<!-- + Common actions performed by nearly every mapping +--> +<xsl:template name="lvmp:map-common"> + <!-- may or may not be set --> + <xsl:copy-of select="@dict" /> + <xsl:copy-of select="@link" /> + <xsl:copy-of select="@transform" /> + + <xsl:apply-templates select="@default" /> +</xsl:template> + + +<xsl:template match="lvm:param" priority="4"> + <!-- processed above on import; no longer needed --> +</xsl:template> + +<xsl:template match="lvm:map[@from]" priority="4"> + <lvmp:var name="{@to}" from="{@from}" src="map"> + <xsl:call-template name="lvmp:map-common" /> + </lvmp:var> +</xsl:template> + +<xsl:template match="lvm:map[lvm:from]" priority="4"> + <lvmp:var name="{@to}" from="{lvm:from/@name}"> + <xsl:call-template name="lvmp:map-common" /> + </lvmp:var> +</xsl:template> + +<xsl:template match="lvm:map[@value]" priority="4"> + <!-- it does not make sense to have a string value be a dictionary --> + <xsl:if test="@dict"> + <xsl:message terminate="yes"> + <xsl:text>error: cannot have @dict on static mapping `</xsl:text> + <xsl:value-of select="@to" /> + <xsl:text>'</xsl:text> + </xsl:message> + </xsl:if> + + <!-- nor does a default make sense --> + <xsl:if test="@default and not( @lvmp:allow-default='true' )"> + <xsl:message terminate="yes"> + <xsl:text>error: cannot have @default on static mapping `</xsl:text> + <xsl:value-of select="@to" /> + <xsl:text>'</xsl:text> + </xsl:message> + </xsl:if> + + <lvmp:var name="{@to}" value="{@value}"> + <!-- we may use defaults internally --> + <xsl:call-template name="lvmp:map-common" /> + </lvmp:var> +</xsl:template> + +<xsl:template match="lvm:pass" priority="4"> + <lvmp:var name="{@name}" from="{@name}" src="map"> + <xsl:call-template name="lvmp:map-common" /> + </lvmp:var> +</xsl:template> + +<xsl:template match="lvm:external" priority="4"> + <lvmp:var name="{@name}" from="{@name}" src="external"> + <xsl:call-template name="lvmp:map-common" /> + </lvmp:var> +</xsl:template> + +<xsl:template match="lvm:*/@default"> + <lvmp:default> + <xsl:apply-templates select="." mode="lvm:valparse" /> + </lvmp:default> +</xsl:template> + + +<xsl:template match="lvmp:translate" priority="4"> + <!-- added by pre-processor during include; ignore --> +</xsl:template> + + +<!-- + Override default behavior of c1 nodes when iteration is requested +--> +<xsl:template match="c1:*[ @lvm:for-each ]" + mode="lvmp:c1-node-result" priority="5"> + + <lvmp:for-each name="{@lvm:for-each}"> + <!-- proceed with processing as normal --> + <xsl:apply-templates select="@*|*" /> + </lvmp:for-each> +</xsl:template> + + +<xsl:template match="lvm:if" priority="4"> + <lvmp:condition> + <lvmp:when> + <xsl:call-template name="lvmp:gen-val"> + <xsl:with-param name="name" select="@name" /> + </xsl:call-template> + </lvmp:when> + + <xsl:apply-templates /> + </lvmp:condition> +</xsl:template> + + +<!-- + Unhandled node character data + + Note that, if a node contains newlines, then there will be text preceding and + following its children. For example: + + <foo> + <bar> + </foo> + + In the above, the `foo' node has the text "\n ", followed by the node `bar', + followed by the text "\n" (assuming that `foo' starts in column 1). +--> +<xsl:template match="text()" priority="1"> + <!-- do not output whitespace from source files --> +</xsl:template> + + +<!-- + Bail out on unhandled nodes. +--> +<xsl:template match="*" priority="1"> + <xsl:message> + <xsl:text>[c1map] fatal: unexpected node </xsl:text> + <xsl:apply-templates select="." mode="lvmp:node-out" /> + <xsl:text>:</xsl:text> + </xsl:message> + + <xsl:message terminate="yes" select="." /> +</xsl:template> + +<xsl:template match="*" mode="lvmp:node-out"> + <xsl:variable name="parent" select="parent::*" /> + <xsl:if test="$parent"> + <xsl:apply-templates select="$parent" mode="lvmp:node-out" /> + </xsl:if> + + <xsl:text>/</xsl:text> + <xsl:value-of select="name()" /> +</xsl:template> + +</xsl:stylesheet> diff --git a/src/current/c1map/c1nodes.xsl b/src/current/c1map/c1nodes.xsl new file mode 100644 index 0000000..da4470f --- /dev/null +++ b/src/current/c1map/c1nodes.xsl @@ -0,0 +1,95 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> +<!-- + Describes how ConceptOne nodes are handled in the output. + + Only nodes in the C1 XML namespace will be included in the output; all other + nodes will be in error, except for nodes as part of the c1 map namespace, + which are processed and will not be included in the output. + + The output is an array format used to generate the final XML at runtime; this + format was not developed in conjunction with this project and is separate, so + be sure that this compiler is updated if the format changes. +--> +<xsl:stylesheet version="2.0" + xmlns:c1="http://www.epic-premier.com/XMLSchema" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:lvm="http://www.lovullo.com/rater/map/c1" + xmlns:lvmp="http://www.lovullo.com/rater/map/c1/pp"> + +<!-- + Nodes with attributes or children are recursively processed and have the + form: + '>Name' => array( <recurse> ) +--> +<xsl:template match="c1:*[*|@*]" priority="5"> + <!-- make the output a little bit sane --> + <xsl:value-of select="$lvmp:nl" /> + + <!-- defer node rendering; allows us to easily determine if there are + siblings of the same name within a node boundary --> + <lvmp:node name="{name()}" /> + <xsl:text> => </xsl:text> + + <lvmp:node-boundary> + <xsl:apply-templates select="." mode="lvmp:c1-node-result" /> + </lvmp:node-boundary> +</xsl:template> + + +<!-- + The default behavior of c1 nodes is to simply output the nodes as-is, with + variable substitutions. +--> +<xsl:template match="c1:*" mode="lvmp:c1-node-result" priority="1"> + <xsl:text>array( </xsl:text> + <xsl:apply-templates select="@*|*" /> + <xsl:text>) </xsl:text> +</xsl:template> + + +<!-- + Text-only nodes are of the form: + '>Name' => 'value' +--> +<xsl:template match="c1:*[text()]" priority="4"> + <!-- defer node rendering; allows us to easily determine if there are + siblings of the same name within a node boundary --> + <lvmp:node name="{name()}" /> + <xsl:text> => </xsl:text> + + <xsl:text></xsl:text> + <!-- TODO: escape single quotes --> + <xsl:apply-templates select="text()" mode="lvm:valparse" /> + <xsl:text>, </xsl:text> +</xsl:template> + + +<!-- + Attributes are of the format: + '[Name]' => 'value' +--> +<xsl:template match="c1:*/@*" priority="5"> + <xsl:text>'[</xsl:text> + <xsl:value-of select="name()" /> + <xsl:text>]' => </xsl:text> + <xsl:apply-templates select="." mode="lvm:valparse" /> + <xsl:text>, </xsl:text> +</xsl:template> + + +<!-- alternative attribute format for special situations --> +<xsl:template match="lvm:attribute" priority="5"> + <xsl:text>'[</xsl:text> + <xsl:value-of select="@name" /> + <xsl:text>]' => </xsl:text> + <xsl:apply-templates select="@value" mode="lvm:valparse" /> + <xsl:text>, </xsl:text> +</xsl:template> + + +<xsl:template match="c1:*/@lvm:*" priority="6"> + <!-- discard all system attributes --> + <!-- TODO: error once everything is properly implemented --> +</xsl:template> + +</xsl:stylesheet> diff --git a/src/current/c1map/render.xsl b/src/current/c1map/render.xsl new file mode 100644 index 0000000..c782a35 --- /dev/null +++ b/src/current/c1map/render.xsl @@ -0,0 +1,339 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> +<!-- + Renders the final PHP code +--> +<xsl:stylesheet version="2.0" + xmlns:c1="http://www.epic-premier.com/XMLSchema" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:lvm="http://www.lovullo.com/rater/map/c1" + xmlns:lvmp="http://www.lovullo.com/rater/map/c1/pp"> + + +<xsl:import href="transform.xsl" /> + + +<xsl:template match="lvmp:root" mode="lvmp:render" priority="5"> + <xsl:text><?php |