[Cluster-devel] [PATCH 2/2] rgmanager: ra2rng.xsl et al.: enforce "forbid child" from RA metadata
Jan Pokorný
jpokorny at redhat.com
Mon Dec 16 12:38:22 UTC 2013
As with previous change, the reflection of this change is yet to come
to cluster.git (ccs_update_schema script) via a separate patch.
Note that this effectively adds requirement for xmllint/libxml2, but
it is required by xsltproc/libxslt already anyway.
Also note that this provision to schema generation will not work
properly until libxslt bugfix [1] is propagated to the target
deployment.
[1] https://mail.gnome.org/archives/xslt/2013-December/msg00001.html
Signed-off-by: Jan Pokorný <jpokorny at redhat.com>
---
rgmanager/src/resources/Makefile.am | 15 +-
rgmanager/src/resources/ra2rng-postprocess.xsl | 265 +++++++++++++++++++++++++
rgmanager/src/resources/ra2rng.xsl | 12 ++
3 files changed, 287 insertions(+), 5 deletions(-)
create mode 100644 rgmanager/src/resources/ra2rng-postprocess.xsl
diff --git a/rgmanager/src/resources/Makefile.am b/rgmanager/src/resources/Makefile.am
index caeb947..00435f7 100644
--- a/rgmanager/src/resources/Makefile.am
+++ b/rgmanager/src/resources/Makefile.am
@@ -105,12 +105,17 @@ ras-validation: $(RESOURCES) $(TARGET) $(DTD)
resources.rng: $(RESOURCES) $(TARGET) utils/config-utils.sh
resources.rng: $(XSL) $(RESRNG)
rm -f resources.rng
- cat resources.rng.head >> resources.rng
@echo Generating per-resource RelaxNG information...
- @for f in $(RESOURCES) $(TARGET); do \
- echo " ./$$f"; \
- bash ./$$f meta-data | xsltproc ra2rng.xsl - >> resources.rng; \
- done
+ cat resources.rng.head >> resources.rng
+ @{ echo '<rha:wrap xmlns:rha="http://redhat.com/~pkennedy/annotation_namespace/cluster_conf_annot_namespace">'; \
+ for f in $(RESOURCES) $(TARGET); do \
+ echo " ./$$f" >&2; \
+ bash ./$$f meta-data | xsltproc ra2rng.xsl -; \
+ done; \
+ echo '</rha:wrap>'; } \
+ | xsltproc ra2rng-postprocess.xsl - \
+ | xmllint --xpath '/*[local-name() = "wrap"]/node()' - \
+ >> resources.rng
cat resources.rng.mid >> resources.rng
cat resources.rng.tail >> resources.rng
diff --git a/rgmanager/src/resources/ra2rng-postprocess.xsl b/rgmanager/src/resources/ra2rng-postprocess.xsl
new file mode 100644
index 0000000..066efb3
--- /dev/null
+++ b/rgmanager/src/resources/ra2rng-postprocess.xsl
@@ -0,0 +1,265 @@
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:int="__internal__"
+ xmlns:rha="http://redhat.com/~pkennedy/annotation_namespace/cluster_conf_annot_namespace"
+ exclude-result-prefixes="int">
+
+<xsl:param name="global-init-indent" select="' '"/>
+<xsl:param name="global-indent" select="' '"/>
+<xsl:param name="global-radefine-all" select="'CHILDREN'"/>
+<xsl:param name="global-radefine-except"
+ select="concat($global-radefine-all, '-EXCEPT-')"/>
+
+
+<!--
+ helper definitions
+ -->
+
+<xsl:variable name="SP" select="' '"/>
+<xsl:variable name="NL" select="'
'"/>
+<xsl:variable name="NLNL" select="'

'"/>
+
+<!-- NOTES:
+ - radefine
+ := define[element]
+ - restrictingradefine
+ := define[element and rha:restriction]
+ and in this context also: ^- and @rha:type = 'forbid-childelem'
+ NOTE: element is currently insignificant, as currently
+ it is implied by the other constraints
+ - forbidchildradefine
+ := radefines forbidden to be referred to from restrictingradefines
+ (as per particular RAs metadada and in turn intermediate
+ rha:restriction annotation)
+ - forbidstring
+ := for restrictingradefine denotes concatenation of respective
+ forbidchildradefines' (ordered!) names (see limitation below
+ and also refer to get-forbidstring named template)
+ - revmap
+ := map using 'key' xslt facility defined reversely, but
+ serving for lookups as implied by the particular name
+ (i.e., not viceversa, "rev" part is already applied)
+ - limitation: 5+ forbidchildradefines per restrictingradefine
+ (currently 5 atmost, and can be scaled further
+ by brainless extension of concat's if needed)
+ -->
+<xsl:key name="revmap-forbidstring-to-restrictingradefines"
+ match="define[rha:restriction[
+ @rha:type = 'forbid-childelem'
+ ]]"
+ use="concat(
+ rha:restriction[
+ @rha:type = 'forbid-childelem'
+ ][1]/@rha:value,
+ rha:restriction[
+ @rha:type = 'forbid-childelem'
+ ][2]/@rha:value,
+ rha:restriction[
+ @rha:type = 'forbid-childelem'
+ ][3]/@rha:value,
+ rha:restriction[
+ @rha:type = 'forbid-childelem'
+ ][4]/@rha:value
+ )"/>
+
+<!-- xsl:key name="revmap-forbidchildradefine-to-restrictingradefines"
+ match="define[rha:restriction[
+ @rha:type = 'forbid-childelem'
+ ]]"
+ use="//define[
+ /element/@name = current()/rha:restriction[
+ @rha:type = 'forbid-childelem'
+ ]@rha:value
+ ]"/-->
+
+<xsl:key name="revmap-radefine-to-forbidchildradefines"
+ match="define[
+ element/@name
+ ]"
+ use="//define[rha:restriction[
+ @rha:type = 'forbid-childelem'
+ and
+ @rha:value = current()/element/@name
+ ]]"/>
+
+<xsl:template name="get-forbidstring">
+ <xsl:param name="radefine"/>
+ <xsl:value-of select="concat(
+ $radefine/rha:restriction[
+ @rha:type = 'forbid-childelem'
+ ][1]/@rha:value,
+ $radefine/rha:restriction[
+ @rha:type = 'forbid-childelem'
+ ][2]/@rha:value,
+ $radefine/rha:restriction[
+ @rha:type = 'forbid-childelem'
+ ][3]/@rha:value,
+ $radefine/rha:restriction[
+ @rha:type = 'forbid-childelem'
+ ][4]/@rha:value
+ )"/>
+</xsl:template>
+
+<xsl:variable name="all-radefines"
+ select="//define[
+ element/@name
+ ]"/>
+
+<xsl:variable name="all-restrictingradefines"
+ select="$all-radefines[rha:restriction[
+ @rha:type = 'forbid-childelem'
+ ]]"/>
+
+
+<!--
+ proceed
+ -->
+
+<!-- start with and use identity by default... -->
+
+<xsl:template match="@*|node()">
+ <xsl:copy>
+ <xsl:apply-templates select="@*|node()"/>
+ </xsl:copy>
+</xsl:template>
+
+<!-- ...unless a special case of restrictingradefine, which needs
+ $global-radefine-all reference rewritten to custom
+ $global-radefine-except$forbidstring... -->
+
+<xsl:template match="@*|node()" mode="rewrite">
+ <xsl:copy>
+ <xsl:apply-templates select="@*|node()" mode="rewrite"/>
+ </xsl:copy>
+</xsl:template>
+
+<xsl:template match="ref/@name[. = 'CHILDREN']"
+ mode="rewrite">
+ <!-- NOTE: forbidstring evaluated anew as we do a traversal-based
+ template application rather than procedural one
+ (as there is generally not a direct link parent-child) -->
+ <xsl:variable name="forbidstring">
+ <xsl:call-template name="get-forbidstring">
+ <xsl:with-param name="radefine"
+ select="ancestor::define[last()]"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="{name()}">
+ <xsl:value-of select="concat($global-radefine-except,
+ $forbidstring)"/>
+ </xsl:attribute>
+</xsl:template>
+
+<!-- ... which is triggered amongst others in the following core logic
+ matching any radefine -->
+
+<xsl:template match="define[
+ element/@name
+ ]">
+ <xsl:variable name="forbidstring">
+ <xsl:call-template name="get-forbidstring">
+ <xsl:with-param name="radefine"
+ select="."/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="self" select="."/>
+
+ <!-- identity modulo rha:restriction + rewrite or not as per above -->
+ <xsl:copy>
+ <xsl:choose>
+ <xsl:when test="$forbidstring != ''">
+ <xsl:apply-templates select="@*|*[
+ name() != 'rha:restriction'
+ ]|processing-instruction()|comment()"
+ mode="rewrite"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="@*|*[
+ name() != 'rha:restriction'
+ ]|processing-instruction()|comment()"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:copy>
+
+ <!-- if we know that $global-radefine-except$forbidstring is not
+ defined by us (set of all radefines is set of all
+ restrictingradefines for this very $forbidstring) AND it is
+ the first restrictingradefine for particular forbidchildradefines
+ (virtually an ordered set, as concatenation keeps ordering),
+ define empty $global-radefine-except$forbidstring symbol, just
+ for the sake of being defined at all (otherwise it couldn't be
+ resolved when no such forbidchildradefine existed) -->
+ <xsl:if test="$forbidstring != ''
+ and
+ count(
+ key(
+ 'revmap-radefine-to-forbidchildradefines',
+ key(
+ 'revmap-forbidstring-to-restrictingradefines',
+ $forbidstring
+ )[1]
+ )
+ ) = count($all-radefines)
+ and
+ generate-id(
+ key(
+ 'revmap-forbidstring-to-restrictingradefines',
+ $forbidstring
+ )
+ ) = generate-id()">
+ <xsl:value-of select="concat($NL, $global-init-indent)"/>
+ <xsl:element name="define">
+ <xsl:attribute name="name">
+ <xsl:value-of select="concat($global-radefine-except,
+ $forbidstring)"/>
+ </xsl:attribute>
+ <xsl:attribute name="combine">
+ <xsl:value-of select="'choice'"/>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+
+ <!-- state the membership of the current radefine in all various
+ $global-radefine-except$forbidstring'ish sets by the means of
+ "combining definition" feature of Relax NG (similar to what is
+ already done with $global-radefine-all themselves) -->
+ <xsl:for-each select="$all-restrictingradefines">
+ <!-- $forbidstring use here always a bug, but cannot be redefined -->
+ <xsl:variable name="forbidstring-other">
+ <xsl:call-template name="get-forbidstring">
+ <xsl:with-param name="radefine"
+ select="."/>
+ </xsl:call-template>
+ </xsl:variable>
+ <!-- access via the first item below is because this is the only
+ guaranteed to exist -->
+ <xsl:if test="not(
+ key(
+ 'revmap-radefine-to-forbidchildradefines',
+ key(
+ 'revmap-forbidstring-to-restrictingradefines',
+ $forbidstring-other
+ )[1]
+ )[generate-id() = generate-id($self)]
+ )">
+ <xsl:value-of select="concat($NL, $global-init-indent)"/>
+ <xsl:element name="define">
+ <xsl:attribute name="name">
+ <xsl:value-of select="concat($global-radefine-except,
+ $forbidstring-other)"/>
+ </xsl:attribute>
+ <xsl:attribute name="combine">
+ <xsl:value-of select="'choice'"/>
+ </xsl:attribute>
+ <xsl:element name="ref">
+ <xsl:attribute name="name">
+ <xsl:value-of select="$self/@name"/>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:element>
+ </xsl:if>
+ </xsl:for-each>
+
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/rgmanager/src/resources/ra2rng.xsl b/rgmanager/src/resources/ra2rng.xsl
index 5b9a307..71df682 100644
--- a/rgmanager/src/resources/ra2rng.xsl
+++ b/rgmanager/src/resources/ra2rng.xsl
@@ -489,6 +489,18 @@
</xsl:call-template>
<xsl:value-of select="$NL"/>
+ <xsl:for-each select="special[@tag='rgmanager']/child[@forbid='1']">
+ <xsl:call-template name="tag">
+ <xsl:with-param name="name" select="'rha:restriction'"/>
+ <xsl:with-param name="attrs" select="concat(
+ 'rha:type=', $Q, 'forbid-childelem', $Q, $SP,
+ 'rha:value=', $Q, @type, $Q)"/>
+ <xsl:with-param name="indented"
+ select="$global-init-indent"/>
+ </xsl:call-template>
+ <xsl:value-of select="$NL"/>
+ </xsl:for-each>
+
<!-- element name=... rha:description=... (start) -->
<xsl:call-template name="tag-start">
<xsl:with-param name="name" select="'element'"/>
--
1.8.1.4
More information about the Cluster-devel
mailing list