view bug-list.xsl @ 12:52b34ea50eff default tip

sync: work time projection doesn't seem to be working anyway
author cin
date Sun, 13 Sep 2015 19:37:16 +0300
parents 4eb9fdf4efa9
children
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:exsl="http://exslt.org/common"
	xmlns:date="http://exslt.org/dates-and-times"
	extension-element-prefixes="exsl date">
	<xsl:output method="text" indent="yes" />

	<!-- PARAMETERS -->

	<!-- chargeset - название аккаунта, на который вести расходы -->
	<xsl:param name="chargeset" />

	<!-- root_task_id - id корневой задачи, в которую будут организованы все 
		задачи -->
	<xsl:param name="root_task_id" />

	<!-- root_task - описание корневой задачи -->
	<xsl:param name="root_task" />

	<!-- GLOBAL VARIABLES -->
	<xsl:variable name="resources"
		select="document('resources.xml')/resources/resource" />

	<xsl:variable name="bugs" select="/bugzilla/bug" />

	<xsl:key name="bugid" match="/bugzilla/bug" use="string(id)" />

	<xsl:variable name="roots" select="$bugs[not(blocks[key('bugid',.)])]" />

	<!-- BUILD BUG TREE -->
	<xsl:variable name="tree">
		<xsl:apply-templates mode="tree" select="$roots" />
	</xsl:variable>

	<xsl:template match="bug" mode="tree">
		<xsl:element name="bug">
			<xsl:attribute name="id"><xsl:value-of select="id" /></xsl:attribute>
			<xsl:if test="component = 'product' or not(number(estimated_time))">
				<xsl:attribute name="group"><xsl:value-of select="boolean(1)" /></xsl:attribute>
			</xsl:if>
			<xsl:for-each select="depends_on">
				<xsl:apply-templates mode="tree" select="key('bugid', .)" />
			</xsl:for-each>
		</xsl:element>
	</xsl:template>

	<!-- CALCULATE RELATIONS -->
	<xsl:variable name="relations">
		<xsl:apply-templates select="$bugs" mode="relations" />
	</xsl:variable>

	<xsl:template match="bug" mode="relations">
		<xsl:variable name="bugid" select="string(id)" />
		<bug id="{$bugid}">
			<!-- calculate all palaces where the same node appears -->
			<xsl:apply-templates select="exsl:node-set($tree)//bug[@id = $bugid]"
				mode="traverse-relations">
			</xsl:apply-templates>
		</bug>
	</xsl:template>

	<xsl:template match="bug" mode="traverse-relations">
		<xsl:variable name="bugid" select="@id" />
		<xsl:variable name="path" select="ancestor::bug" />
		<xsl:variable name="level" select="count($path)" />
		<!-- for the specified path calculate the distances to the preceding container -->
		<xsl:for-each select="$path[@group]">
			<xsl:variable name="pos" select="position()" />
			<xsl:variable name="rank" select="$level - $pos" />
			<rel container="{@id}" rank="{$rank}" level="{$level}">
				<!-- record the full path -->
				<xsl:for-each select="$path[@group]">
					<parent id="{@id}" bugid="{$bugid}" />
				</xsl:for-each>
			</rel>
		</xsl:for-each>
	</xsl:template>

	<!-- CALCULATE STRUCTURE -->

	<xsl:variable name="parents">
		<xsl:apply-templates select="exsl:node-set($relations)"
			mode="parents" />
	</xsl:variable>

	<xsl:template match="bug" mode="parents">
		<xsl:variable name="parent"
			select="rel[ not(../rel/@rank &lt; @rank) ][1]" />
		<bug id="{@id}" parent="{$parent/@container}" rank="{$parent/@rank}"
			level="{$parent/@level}">
			<xsl:copy-of select="$parent/node()" />
		</bug>
	</xsl:template>

	<xsl:variable name="structure">
		<xsl:choose>
			<xsl:when test="$root_task">
				<bug id="_root" desc="{$root_task}" group="true">
					<xsl:apply-templates select="$roots" mode="structure" />
				</bug>
			</xsl:when>
			<xsl:otherwise>
				<xsl:apply-templates select="$roots" mode="structure" />
			</xsl:otherwise>
		</xsl:choose>
	</xsl:variable>

	<!-- applied in context of the bugzilla document -->
	<xsl:template match="bug" mode="structure">
		<xsl:variable name="id" select="string(id)" />
		<xsl:variable name="self" select="." />
		<xsl:variable name="children"
			select="exsl:node-set($parents)/bug[@parent = $id]" />
		<xsl:element name="bug">
			<xsl:attribute name="id"><xsl:value-of select="$id" /></xsl:attribute>
			<xsl:attribute name="desc"><xsl:value-of select="summary" /></xsl:attribute>
			<xsl:attribute name="estimated"><xsl:value-of
				select="number((time/estimated | estimated_time)[1])" /></xsl:attribute>
            <xsl:attribute name="complete"><xsl:value-of select="status = 'RESOLVED' or status = 'VERIFIED'"/></xsl:attribute>

			<xsl:if test="$children">
				<xsl:attribute name="group"><xsl:value-of select="boolean($children)" /></xsl:attribute>

				<xsl:for-each select="$children">
					<xsl:variable name="child" select="@id" />
					<xsl:apply-templates select="$bugs[id = $child]"
						mode="structure" />
				</xsl:for-each>

			</xsl:if>

			<!-- filter out dependencies -->
			<!-- exclude children, and missing bugs -->
			<xsl:variable name="dependencies"
				select="depends_on[not(text() = exsl:node-set($parents)/bug/parent[@id=$id]/@bugid)][key('bugid', .)]" />
			<xsl:for-each select="$dependencies">
				<dependency id="{.}" />
			</xsl:for-each>
		</xsl:element>
	</xsl:template>

	<!-- output -->
	<xsl:template match="/">
		<xsl:apply-templates select="exsl:node-set($structure)/node()">
			<xsl:with-param name="indent" select="0" />
			<xsl:with-param name="chargeset" select="$chargeset" />
		</xsl:apply-templates>
		<!-- 
		<xsl:apply-templates select="bugzilla/timesheet">
			<xsl:with-param name="indent" select="0" />
		</xsl:apply-templates>
		 -->
	</xsl:template>

	<!-- task -->
	<xsl:template match="bug">
		<xsl:param name="indent" select="0" />
		<xsl:param name="chargeset" />

		<!-- format the task header -->
		<xsl:call-template name="start-task">
			<xsl:with-param name="indent" select="$indent" />
			<xsl:with-param name="id">
				<xsl:call-template name="bug-local-name">
					<xsl:with-param name="id" select="@id" />
				</xsl:call-template>
			</xsl:with-param>
			<xsl:with-param name="desc" select="@desc" />
		</xsl:call-template>

		<!-- specify chargeset if present -->
		<xsl:if test="$chargeset">
			<xsl:call-template name="println">
				<xsl:with-param name="indent" select="$indent + 1" />
				<xsl:with-param name="text"
					select="concat('chargeset ', $chargeset)" />
			</xsl:call-template>
		</xsl:if>

		<!-- print task contents -->
		<xsl:apply-templates select="." mode="task-content">
			<xsl:with-param name="indent" select="$indent + 1" />
		</xsl:apply-templates>

		<!-- prints subtasks and dependencies -->
		<xsl:apply-templates>
			<xsl:with-param name="indent" select="$indent + 1" />
			<xsl:with-param name="referer" select="." />
		</xsl:apply-templates>

		<xsl:call-template name="end-task">
			<xsl:with-param name="indent" select="$indent" />
		</xsl:call-template>
	</xsl:template>

	<!-- dependency -->
	<xsl:template match="dependency">
		<xsl:param name="indent" select="0" />
		<xsl:param name="referer" />

		<xsl:call-template name="println">
			<xsl:with-param name="indent" select="$indent" />
			<xsl:with-param name="text">
				<xsl:text>depends </xsl:text>
				<xsl:call-template name="bug-reference">
					<xsl:with-param name="id" select="@id" />
					<xsl:with-param name="referer" select="$referer" />
				</xsl:call-template>
			</xsl:with-param>
		</xsl:call-template>
	</xsl:template>

	<!-- an organizational task with spent/estimated time will contain a generated 
		task which will contain the information about resource allocation and bookings -->
	<xsl:template match="bug[@group][@estimated > 0]" mode="task-content"
		priority="3">
		<xsl:param name="indent" select="0" />
		<xsl:variable name="id" select="@id" />

		<!-- DEBUG -->
		<xsl:call-template name="comment">
			<xsl:with-param name="indent" select="$indent" />
			<xsl:with-param name="comment" select="'group'" />
		</xsl:call-template>

		<!-- print group details -->
		<xsl:apply-templates select="$bugs[id = $id]/node()"
			mode="group-task">
			<xsl:with-param name="indent" select="$indent" />
		</xsl:apply-templates>

		<xsl:variable name="metabug">
			<bug id="{@id}" estimated="{@estimated}" desc="{@desc}" />
		</xsl:variable>

		<!-- write an administrative bug for this group-task -->
		<xsl:apply-templates select="exsl:node-set($metabug)/bug[1]">
			<xsl:with-param name="indent" select="$indent" />
		</xsl:apply-templates>
	</xsl:template>

	<!-- an organizational task without resource allocations -->
	<xsl:template match="bug[@group]" mode="task-content">
		<xsl:param name="indent" select="0" />
		<xsl:variable name="id" select="@id" />
		<xsl:apply-templates select="$bugs[id = $id]/node()"
			mode="group-task">
			<xsl:with-param name="indent" select="$indent" />
		</xsl:apply-templates>
	</xsl:template>

	<!-- a work task -->
	<xsl:template match="bug[@estimated > 0]" mode="task-content">
		<xsl:param name="indent" select="0" />
		<xsl:variable name="id" select="@id" />

		<!-- DEBUG -->
		<xsl:call-template name="comment">
			<xsl:with-param name="indent" select="$indent" />
			<xsl:with-param name="comment" select="'work'" />
		</xsl:call-template>

		<xsl:apply-templates select="$bugs[id = $id]/node()"
			mode="work-task">
			<xsl:with-param name="indent" select="$indent" />
		</xsl:apply-templates>
	</xsl:template>
	
	<xsl:template match="bug[@estimated > 0 and @complete]" mode="task-content">
        <xsl:param name="indent" select="0" />
        <xsl:variable name="id" select="@id" />

        <!-- DEBUG -->
        <xsl:call-template name="comment">
            <xsl:with-param name="indent" select="$indent" />
            <xsl:with-param name="comment" select="'work'" />
        </xsl:call-template>

        <xsl:apply-templates select="$bugs[id = $id]/node()"
            mode="done-work-task">
            <xsl:with-param name="indent" select="$indent" />
        </xsl:apply-templates>
    </xsl:template>

	<!-- a milestone task -->
	<xsl:template match="bug" mode="task-content">
		<xsl:param name="indent" select="0" />
		<xsl:variable name="id" select="@id" />

		<!-- DEBUG -->
		<xsl:call-template name="comment">
			<xsl:with-param name="indent" select="$indent" />
			<xsl:with-param name="comment" select="'milestone'" />
		</xsl:call-template>

		<xsl:apply-templates select="$bugs[id = $id]/node()"
			mode="milestone-task">
			<xsl:with-param name="indent" select="$indent" />
		</xsl:apply-templates>
	</xsl:template>

	<!-- each type of task processed in the corresponding mode MODES: * group-task 
		* work-task * milestone-task -->

	<!-- group-task -->
	<xsl:template match="assigned_to" mode="group-task">
		<xsl:param name="indent" />
		<xsl:variable name="email" select="string(.)" />
		<xsl:variable name="resource" select="$resources[@email = $email]/@id" />
		<xsl:if test="$resource">
			<xsl:call-template name="println">
				<xsl:with-param name="indent" select="$indent" />
				<xsl:with-param name="text"
					select="concat('responsible ', $resource)" />
			</xsl:call-template>
		</xsl:if>
	</xsl:template>

	<xsl:template match="*" mode="group-task">
		<xsl:param name="indent" select="0" />
		<xsl:apply-templates mode="group-task">
			<xsl:with-param name="indent" select="$indent" />
		</xsl:apply-templates>
	</xsl:template>

	<xsl:template match="text()" mode="group-task">
	</xsl:template>


	<!-- work-task -->
	<xsl:template match="assigned_to" mode="work-task">
		<xsl:param name="indent" />
		<xsl:variable name="email" select="string(.)" />
		<xsl:variable name="resource" select="$resources[@email = $email]/@id" />
		<xsl:if test="$resource">
			<xsl:call-template name="println">
				<xsl:with-param name="indent" select="$indent" />
				<xsl:with-param name="text" select="concat('allocate ', $resource)" />
			</xsl:call-template>
		</xsl:if>
	</xsl:template>

	<!-- if we have a timereports -->
	<xsl:template match="time/estimated[. > 0]" mode="work-task">
		<xsl:param name="indent" />
		<xsl:call-template name="println">
			<xsl:with-param name="indent" select="$indent" />
			<xsl:with-param name="text" select="concat('effort ', .,'h')" />
		</xsl:call-template>
	</xsl:template>

	<!-- if we have an estimated_time -->
	<xsl:template match="estimated_time[../time/estimated = 0]"
		mode="work-task">
		<xsl:param name="indent" />
		<xsl:call-template name="comment">
			<xsl:with-param name="indent" select="$indent" />
			<xsl:with-param name="comment" select="'original estimated'" />
		</xsl:call-template>
		<xsl:call-template name="println">
			<xsl:with-param name="indent" select="$indent" />
			<xsl:with-param name="text" select="concat('effort ', .,'h')" />
		</xsl:call-template>
	</xsl:template>

	<xsl:template match="*" mode="work-task">
		<xsl:param name="indent" select="0" />
		<xsl:apply-templates mode="work-task">
			<xsl:with-param name="indent" select="$indent" />
		</xsl:apply-templates>
	</xsl:template>

	<xsl:template match="text()" mode="work-task">
	</xsl:template>
	
	<!-- done-work-task -->
	
	<xsl:template match="assigned_to" mode="done-work-task">
        <xsl:param name="indent" />
        <xsl:variable name="email" select="string(.)" />
        <xsl:variable name="resource" select="$resources[@email = $email]/@id" />
        <xsl:if test="$resource">
            <xsl:call-template name="println">
                <xsl:with-param name="indent" select="$indent" />
                <xsl:with-param name="text" select="concat('allocate ', $resource)" />
            </xsl:call-template>
        </xsl:if>
    </xsl:template>

    <!-- if we have a timereports -->
    <xsl:template match="time/estimated[. > 0]" mode="done-work-task">
        <xsl:param name="indent" />
        <xsl:call-template name="println">
            <xsl:with-param name="indent" select="$indent" />
            <xsl:with-param name="text" select="concat('effort ', .,'h')" />
        </xsl:call-template>
    </xsl:template>
    
    <xsl:template match="last_change_time" mode="done-work-task">
        <xsl:param name="indent" />
        <xsl:call-template name="println">
            <xsl:with-param name="indent" select="$indent" />
            <xsl:with-param name="text" select="concat('end ', .)" />
        </xsl:call-template>
    </xsl:template>

    <xsl:template match="*" mode="done-work-task">
        <xsl:param name="indent" select="0" />
        <xsl:apply-templates mode="work-task">
            <xsl:with-param name="indent" select="$indent" />
        </xsl:apply-templates>
    </xsl:template>

    <xsl:template match="text()" mode="done-work-task">
    </xsl:template>

	<!-- milestone-task -->
	<xsl:template match="assigned_to" mode="milestone-task">
		<xsl:param name="indent" />
		<xsl:variable name="email" select="string(.)" />
		<xsl:variable name="resource" select="$resources[@email = $email]/@id" />
		<xsl:if test="$resource">
			<xsl:call-template name="println">
				<xsl:with-param name="indent" select="$indent" />
				<xsl:with-param name="text"
					select="concat('responsible ', $resource)" />
			</xsl:call-template>
		</xsl:if>
	</xsl:template>

	<xsl:template match="*" mode="milestone-task">
		<xsl:param name="indent" select="0" />
		<xsl:apply-templates mode="milestone-task">
			<xsl:with-param name="indent" select="$indent" />
		</xsl:apply-templates>
	</xsl:template>

	<xsl:template match="text()" mode="milestone-task">
	</xsl:template>

	<!-- TIMESHEETS -->

	<xsl:template match="timesheet">
		<xsl:param name="indent" select="0" />
		<xsl:variable name="email" select="string(@resource)" />
		<xsl:variable name="resource" select="$resources[@email = $email]/@id" />

		<xsl:call-template name="println">
			<xsl:with-param name="indent" select="$indent" />
			<xsl:with-param name="text"
				select="concat('timesheet ', $resource, ' ', @start, ' - ', @end, ' {')" />
		</xsl:call-template>

		<xsl:apply-templates mode="timesheet">
			<xsl:with-param name="indent" select="$indent + 1" />
		</xsl:apply-templates>

		<xsl:call-template name="println">
			<xsl:with-param name="indent" select="$indent" />
			<xsl:with-param name="text" select="'}'" />
		</xsl:call-template>
	</xsl:template>

	<xsl:template match="bug" mode="timesheet">
		<xsl:param name="indent" select="0" />
		<xsl:variable name="id" select="@id" />

		<xsl:call-template name="begin-line">
			<xsl:with-param name="indent" select="$indent" />
		</xsl:call-template>
		<xsl:text>task </xsl:text>
		<xsl:for-each
			select="exsl:node-set( $parents)/bug[@id = $id]/parent/@id | @id">
			<xsl:call-template name="bug-local-name">
				<xsl:with-param name="id" select="." />
			</xsl:call-template>
			<xsl:if test="position() != last()">
				<xsl:text>.</xsl:text>
			</xsl:if>
		</xsl:for-each>
		<xsl:text> {</xsl:text>
		<xsl:call-template name="end-line" />

		<xsl:apply-templates mode="timesheet">
			<xsl:with-param name="indent" select="$indent + 1" />
		</xsl:apply-templates>

		<xsl:call-template name="println">
			<xsl:with-param name="indent" select="$indent" />
			<xsl:with-param name="text" select="'}'" />
		</xsl:call-template>

	</xsl:template>

	<xsl:template match="work" mode="timesheet">
		<xsl:param name="indent" select="0" />

		<xsl:call-template name="println">
			<xsl:with-param name="indent" select="$indent" />
			<xsl:with-param name="text" select="concat('work ', ., 'h')" />
		</xsl:call-template>
	</xsl:template>

	<xsl:template match="remaining" mode="timesheet">
		<xsl:param name="indent" select="0" />

		<xsl:call-template name="println">
			<xsl:with-param name="indent" select="$indent" />
			<xsl:with-param name="text" select="concat('remaining ', ., 'h')" />
		</xsl:call-template>
	</xsl:template>

	<xsl:template match="*" mode="timesheet">
		<xsl:param name="indent" select="0" />
		<xsl:apply-templates mode="milestone-task">
			<xsl:with-param name="indent" select="$indent" />
		</xsl:apply-templates>
	</xsl:template>

	<xsl:template match="text()" mode="timesheet">
	</xsl:template>

	<!-- PRIMITIVES -->

	<xsl:template name="bug-local-name">
		<xsl:param name="id" />
		<xsl:value-of select="concat('bug',$id)" />
	</xsl:template>


	<xsl:template name="bug-reference">
		<xsl:param name="id" />
		<xsl:param name="referer" />

		<xsl:variable name="refererPathFragment">
			<bug id="#root" />
			<xsl:for-each select="$referer/ancestor-or-self::bug">
				<bug id="{@id}" />
			</xsl:for-each>
		</xsl:variable>
		<xsl:variable name="targetPathFragment">
			<bug id="#root" />
			<xsl:for-each
				select="exsl:node-set($structure)//bug[@id = $id]/ancestor-or-self::bug">
				<bug id="{@id}" />
			</xsl:for-each>
		</xsl:variable>
		<xsl:variable name="path"
			select="exsl:node-set($refererPathFragment)/bug" />
		<xsl:variable name="targetPath"
			select="exsl:node-set($targetPathFragment)/bug" />

		<!-- find closest shared container id -->
		<xsl:variable name="join"
			select="($path[@id = $targetPath/@id])[position() = last() ]/@id" />

		<!-- how many levels we need to up -->
		<xsl:variable name="depth"
			select="count($path[@id = $join]/following-sibling::node())" />

		<!-- DEBUG -->
		<!-- <xsl:value-of select="concat('id=', $id, ',referer=', $referer/@id)" 
			/> <xsl:text>, path=</xsl:text> <xsl:for-each select="$targetPath"> <xsl:value-of 
			select="concat(name(),@id)" /> <xsl:if test="position() != last()"> <xsl:text>-</xsl:text> 
			</xsl:if> </xsl:for-each> -->
		<!-- DEBUG -->
		<!-- <xsl:value-of select="concat(', join=', $join,', depth=', $depth,' 
			')" /> -->

		<!-- PRINT REFERENCE -->
		<xsl:call-template name="repeat">
			<xsl:with-param name="value" select="'!'" />
			<xsl:with-param name="count" select="$depth" />
		</xsl:call-template>
		<xsl:for-each select="$targetPath[@id = $join]/following-sibling::node()">
			<xsl:call-template name="bug-local-name">
				<xsl:with-param name="id" select="@id" />
			</xsl:call-template>
			<xsl:if test="position() != last()">
				<xsl:text>.</xsl:text>
			</xsl:if>
		</xsl:for-each>

	</xsl:template>

	<xsl:template name="start-task">
		<xsl:param name="indent" />
		<xsl:param name="id" />
		<xsl:param name="desc" />
		<xsl:call-template name="begin-line">
			<xsl:with-param name="indent" select="$indent" />
		</xsl:call-template>
		<xsl:text>task </xsl:text>
		<xsl:value-of select="$id" />
		<xsl:value-of select="concat(' &quot;',$desc,'&quot; {')" />
		<xsl:call-template name="end-line" />
	</xsl:template>

	<xsl:template name="end-task">
		<xsl:param name="indent" />
		<xsl:call-template name="begin-line">
			<xsl:with-param name="indent" select="$indent" />
		</xsl:call-template>
		<xsl:text>}</xsl:text>
		<xsl:call-template name="end-line" />
	</xsl:template>

	<xsl:template name="begin-line">
		<xsl:param name="indent" />
		<xsl:if test="number($indent) > 0">
			<xsl:text>    </xsl:text>
			<xsl:call-template name="begin-line">
				<xsl:with-param name="indent" select="$indent - 1" />
			</xsl:call-template>
		</xsl:if>
	</xsl:template>

	<xsl:template name="end-line">
		<xsl:text>&#xa;</xsl:text>
	</xsl:template>

	<xsl:template name="repeat">
		<xsl:param name="value" />
		<xsl:param name="count" select="0" />

		<xsl:if test="number($count)">
			<xsl:value-of select="$value" />
			<xsl:call-template name="repeat">
				<xsl:with-param name="value" select="$value" />
				<xsl:with-param name="count" select="$count - 1" />
			</xsl:call-template>
		</xsl:if>
	</xsl:template>

	<xsl:template name="comment">
		<xsl:param name="indent" />
		<xsl:param name="comment" />
		<xsl:call-template name="println">
			<xsl:with-param name="indent" select="$indent" />
			<xsl:with-param name="text">
				<xsl:text># </xsl:text>
				<xsl:value-of select="$comment" />
			</xsl:with-param>
		</xsl:call-template>
	</xsl:template>

	<xsl:template name="println">
		<xsl:param name="indent" />
		<xsl:param name="text" />
		<xsl:call-template name="begin-line">
			<xsl:with-param name="indent" select="$indent" />
		</xsl:call-template>
		<xsl:value-of select="$text" />
		<xsl:call-template name="end-line" />
	</xsl:template>
</xsl:stylesheet>