0
|
1 <?xml version="1.0" encoding="UTF-8"?>
|
|
2 <xsl:stylesheet version="1.0"
|
4
|
3 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common"
|
|
4 extension-element-prefixes="exsl">
|
|
5 <xsl:output method="text" indent="yes" />
|
|
6
|
5
|
7 <!-- PARAMETERS -->
|
|
8
|
|
9 <!-- chargeset - название аккаунта, на который вести расходы -->
|
|
10 <xsl:param name="chargeset" />
|
|
11
|
|
12 <!-- root_task_id - id корневой задачи, в которую будут организованы все
|
|
13 задачи -->
|
|
14 <xsl:param name="root_task_id" />
|
|
15
|
|
16 <!-- root_task - описание корневой задачи -->
|
|
17 <xsl:param name="root_task" />
|
|
18
|
|
19 <!-- GLOBAL VARIABLES -->
|
4
|
20 <xsl:variable name="resources"
|
|
21 select="document('resources.xml')/resources/resource" />
|
|
22
|
3
|
23 <xsl:variable name="bugs" select="/bugzilla/bug" />
|
4
|
24
|
3
|
25 <xsl:key name="bugid" match="/bugzilla/bug" use="string(bug_id)" />
|
4
|
26
|
|
27 <xsl:variable name="roots" select="$bugs[not(blocked[key('bugid',.)])]" />
|
1
|
28
|
|
29 <!-- BUILD BUG TREE -->
|
|
30 <xsl:variable name="tree">
|
|
31 <xsl:apply-templates mode="tree" select="$roots" />
|
|
32 </xsl:variable>
|
|
33
|
|
34 <xsl:template match="bug" mode="tree">
|
|
35 <xsl:element name="bug">
|
|
36 <xsl:attribute name="id"><xsl:value-of select="bug_id" /></xsl:attribute>
|
3
|
37 <xsl:if test="component = 'product' or not(number(estimated_time))">
|
5
|
38 <xsl:attribute name="group"><xsl:value-of select="boolean(1)" /></xsl:attribute>
|
1
|
39 </xsl:if>
|
|
40 <xsl:for-each select="dependson">
|
|
41 <xsl:apply-templates mode="tree" select="key('bugid', .)" />
|
|
42 </xsl:for-each>
|
|
43 </xsl:element>
|
|
44 </xsl:template>
|
|
45
|
|
46 <!-- CALCULATE RELATIONS -->
|
|
47 <xsl:variable name="relations">
|
3
|
48 <xsl:apply-templates select="$bugs" mode="relations" />
|
1
|
49 </xsl:variable>
|
|
50
|
|
51 <xsl:template match="bug" mode="relations">
|
|
52 <xsl:variable name="bugid" select="string(bug_id)" />
|
|
53 <bug id="{$bugid}">
|
6
|
54 <!-- calculate all palaces where the same node appears -->
|
1
|
55 <xsl:apply-templates select="exsl:node-set($tree)//bug[@id = $bugid]"
|
|
56 mode="traverse-relations">
|
|
57 </xsl:apply-templates>
|
|
58 </bug>
|
|
59 </xsl:template>
|
|
60
|
|
61 <xsl:template match="bug" mode="traverse-relations">
|
|
62 <xsl:variable name="bugid" select="@id" />
|
3
|
63 <xsl:variable name="path" select="ancestor::bug" />
|
|
64 <xsl:variable name="level" select="count($path)" />
|
6
|
65 <!-- for the specified path calculate the distances to the preceding container -->
|
5
|
66 <xsl:for-each select="$path[@group]">
|
3
|
67 <xsl:variable name="pos" select="position()" />
|
4
|
68 <xsl:variable name="rank" select="$level - $pos" />
|
3
|
69 <rel container="{@id}" rank="{$rank}" level="{$level}">
|
6
|
70 <!-- record the full path -->
|
|
71 <xsl:for-each select="$path[@group]">
|
|
72 <parent id="{@id}" bugid="{$bugid}" />
|
3
|
73 </xsl:for-each>
|
|
74 </rel>
|
1
|
75 </xsl:for-each>
|
|
76 </xsl:template>
|
|
77
|
|
78 <!-- CALCULATE STRUCTURE -->
|
|
79
|
3
|
80 <xsl:variable name="parents">
|
1
|
81 <xsl:apply-templates select="exsl:node-set($relations)"
|
3
|
82 mode="parents" />
|
|
83 </xsl:variable>
|
|
84
|
|
85 <xsl:template match="bug" mode="parents">
|
|
86 <xsl:variable name="parent"
|
|
87 select="rel[ not(../rel/@rank < @rank) ][1]" />
|
|
88 <bug id="{@id}" parent="{$parent/@container}" rank="{$parent/@rank}"
|
6
|
89 level="{$parent/@level}">
|
|
90 <xsl:copy-of select="$parent/node()" />
|
|
91 </bug>
|
3
|
92 </xsl:template>
|
|
93
|
|
94 <xsl:variable name="structure">
|
5
|
95 <xsl:choose>
|
|
96 <xsl:when test="$root_task">
|
|
97 <bug id="_root" desc="{$root_task}" group="true">
|
6
|
98 <xsl:apply-templates select="$roots" mode="structure" />
|
5
|
99 </bug>
|
|
100 </xsl:when>
|
|
101 <xsl:otherwise>
|
6
|
102 <xsl:apply-templates select="$roots" mode="structure" />
|
5
|
103 </xsl:otherwise>
|
|
104 </xsl:choose>
|
1
|
105 </xsl:variable>
|
|
106
|
6
|
107 <!-- applied in context of the bugzilla document -->
|
1
|
108 <xsl:template match="bug" mode="structure">
|
3
|
109 <xsl:variable name="id" select="string(bug_id)" />
|
|
110 <xsl:variable name="self" select="." />
|
5
|
111 <xsl:variable name="children"
|
|
112 select="exsl:node-set($parents)/bug[@parent = $id]" />
|
|
113 <xsl:element name="bug">
|
|
114 <xsl:attribute name="id"><xsl:value-of select="$id" /></xsl:attribute>
|
|
115 <xsl:attribute name="desc"><xsl:value-of select="short_desc" /></xsl:attribute>
|
|
116
|
|
117 <xsl:if test="$children">
|
|
118 <xsl:attribute name="group"><xsl:value-of select="boolean($children)" /></xsl:attribute>
|
|
119
|
|
120 <xsl:for-each select="$children">
|
|
121 <xsl:variable name="child" select="@id" />
|
|
122 <xsl:apply-templates select="$bugs[bug_id = $child]"
|
|
123 mode="structure" />
|
|
124 </xsl:for-each>
|
|
125
|
|
126 </xsl:if>
|
|
127
|
|
128 <!-- filter out dependencies -->
|
6
|
129 <!-- exclude children, and missing bugs -->
|
3
|
130 <xsl:variable name="dependencies"
|
6
|
131 select="dependson[not(text() = exsl:node-set($parents)/bug/parent[@id=$id]/@bugid)][key('bugid', .)]" />
|
5
|
132 <xsl:for-each select="$dependencies">
|
|
133 <dependency id="{.}" />
|
|
134 </xsl:for-each>
|
|
135 </xsl:element>
|
1
|
136 </xsl:template>
|
|
137
|
4
|
138 <!-- output -->
|
0
|
139 <xsl:template match="/">
|
4
|
140 <xsl:apply-templates select="exsl:node-set($structure)/bug">
|
|
141 <xsl:with-param name="indent" select="0" />
|
6
|
142 <xsl:with-param name="chargeset" select="$chargeset" />
|
4
|
143 </xsl:apply-templates>
|
0
|
144 </xsl:template>
|
|
145
|
|
146 <xsl:template match="bug">
|
|
147 <xsl:param name="indent" select="0" />
|
5
|
148 <xsl:param name="chargeset" />
|
4
|
149 <xsl:variable name="id" select="@id" />
|
|
150 <xsl:variable name="details" select="$bugs[bug_id = $id]" />
|
6
|
151 <xsl:variable name="hasTime"
|
|
152 select="number($details/estimated_time) or number($details/actual_time) or number($details/remaining_time)" />
|
5
|
153
|
|
154 <!-- task header -->
|
0
|
155 <xsl:call-template name="start-task">
|
|
156 <xsl:with-param name="indent" select="$indent" />
|
5
|
157 <xsl:with-param name="id">
|
|
158 <xsl:call-template name="bug-local-name">
|
|
159 <xsl:with-param name="id" select="@id" />
|
|
160 </xsl:call-template>
|
|
161 </xsl:with-param>
|
|
162 <xsl:with-param name="desc" select="@desc" />
|
0
|
163 </xsl:call-template>
|
6
|
164
|
5
|
165 <xsl:if test="$chargeset">
|
|
166 <xsl:call-template name="println">
|
6
|
167 <xsl:with-param name="indent" select="$indent + 1" />
|
|
168 <xsl:with-param name="text"
|
|
169 select="concat('chargeset ', $chargeset)" />
|
5
|
170 </xsl:call-template>
|
|
171 </xsl:if>
|
|
172
|
|
173 <!-- task details -->
|
|
174 <xsl:choose>
|
|
175 <xsl:when test="@group">
|
|
176 <!-- DEBUG -->
|
|
177 <xsl:call-template name="comment">
|
|
178 <xsl:with-param name="indent" select="$indent + 1" />
|
|
179 <xsl:with-param name="comment" select="'group'" />
|
|
180 </xsl:call-template>
|
|
181
|
0
|
182
|
5
|
183 <xsl:apply-templates select="$details/node()"
|
|
184 mode="group-details">
|
4
|
185 <xsl:with-param name="indent" select="$indent + 1" />
|
5
|
186 </xsl:apply-templates>
|
0
|
187
|
6
|
188 <xsl:if test="$hasTime">
|
5
|
189 <xsl:call-template name="start-task">
|
|
190 <xsl:with-param name="indent" select="$indent + 1" />
|
|
191 <xsl:with-param name="id" select="'manage'" />
|
|
192 <xsl:with-param name="desc" select="@desc" />
|
|
193 </xsl:call-template>
|
|
194 <xsl:apply-templates
|
|
195 select="$details/estimated_time | $details/actual_time | $details/remaining_time | $details/assigned_to"
|
|
196 mode="task-details">
|
|
197 <xsl:with-param name="indent" select="$indent + 2" />
|
6
|
198 <xsl:with-param name="hasTime" select="$hasTime" />
|
5
|
199 </xsl:apply-templates>
|
|
200 <xsl:call-template name="end-task">
|
|
201 <xsl:with-param name="indent" select="$indent + 1" />
|
|
202 </xsl:call-template>
|
|
203 </xsl:if>
|
|
204 </xsl:when>
|
|
205 <xsl:otherwise>
|
|
206 <xsl:apply-templates select="$details/node()"
|
|
207 mode="task-details">
|
|
208 <xsl:with-param name="indent" select="$indent + 1" />
|
6
|
209 <xsl:with-param name="hasTime" select="$hasTime" />
|
5
|
210 </xsl:apply-templates>
|
|
211 </xsl:otherwise>
|
|
212 </xsl:choose>
|
|
213
|
|
214 <!-- subtasks and dependencies -->
|
4
|
215 <xsl:apply-templates>
|
|
216 <xsl:with-param name="indent" select="$indent + 1" />
|
5
|
217 <xsl:with-param name="referer" select="." />
|
4
|
218 </xsl:apply-templates>
|
0
|
219
|
|
220 <xsl:call-template name="end-task">
|
|
221 <xsl:with-param name="indent" select="$indent" />
|
|
222 </xsl:call-template>
|
|
223 </xsl:template>
|
|
224
|
5
|
225 <xsl:template match="dependency">
|
|
226 <xsl:param name="indent" />
|
|
227 <xsl:param name="referer" />
|
|
228 <xsl:call-template name="println">
|
|
229 <xsl:with-param name="indent" select="$indent" />
|
|
230 <xsl:with-param name="text">
|
|
231 <xsl:text>depends </xsl:text>
|
|
232 <xsl:call-template name="bug-reference">
|
|
233 <xsl:with-param name="id" select="@id" />
|
|
234 <xsl:with-param name="referer" select="$referer" />
|
|
235 </xsl:call-template>
|
|
236 </xsl:with-param>
|
|
237 </xsl:call-template>
|
|
238 </xsl:template>
|
|
239
|
|
240
|
|
241 <xsl:template match="text()" />
|
|
242
|
|
243 <!-- TASK ATTRIBUTES -->
|
|
244
|
4
|
245 <xsl:template match="estimated_time" mode="task-details">
|
5
|
246 <xsl:param name="indent" />
|
4
|
247 <xsl:if test="number(.)">
|
5
|
248 <xsl:call-template name="println">
|
|
249 <xsl:with-param name="indent" select="$indent" />
|
|
250 <xsl:with-param name="text" select="concat('effort ', .,'h')" />
|
|
251 </xsl:call-template>
|
4
|
252 </xsl:if>
|
|
253 </xsl:template>
|
|
254
|
|
255 <xsl:template match="assigned_to" mode="task-details">
|
5
|
256 <xsl:param name="indent" />
|
6
|
257 <xsl:param name="hasTime" />
|
|
258 <xsl:if test="$hasTime">
|
|
259 <xsl:variable name="email" select="string(.)" />
|
|
260 <xsl:variable name="resource" select="$resources[@email = $email]/@id" />
|
|
261 <xsl:if test="$resource">
|
|
262 <xsl:call-template name="println">
|
|
263 <xsl:with-param name="indent" select="$indent" />
|
|
264 <xsl:with-param name="text"
|
|
265 select="concat('allocate ', $resource)" />
|
|
266 </xsl:call-template>
|
|
267 </xsl:if>
|
4
|
268 </xsl:if>
|
|
269 </xsl:template>
|
|
270 <xsl:template match="text()" mode="task-details">
|
|
271 </xsl:template>
|
|
272
|
5
|
273 <xsl:template match="assigned_to" mode="group-details">
|
|
274 <xsl:param name="indent" />
|
|
275 <xsl:variable name="email" select="string(.)" />
|
|
276 <xsl:variable name="resource" select="$resources[@email = $email]/@id" />
|
|
277 <xsl:if test="$resource">
|
|
278 <xsl:call-template name="println">
|
|
279 <xsl:with-param name="indent" select="$indent" />
|
|
280 <xsl:with-param name="text"
|
|
281 select="concat('responsible ', $resource)" />
|
|
282 </xsl:call-template>
|
|
283 </xsl:if>
|
|
284 </xsl:template>
|
|
285 <xsl:template match="text()" mode="group-details">
|
4
|
286 </xsl:template>
|
|
287
|
5
|
288 <!-- PRIMITIVES -->
|
4
|
289
|
|
290
|
|
291
|
|
292 <xsl:template name="bug-local-name">
|
|
293 <xsl:param name="id" />
|
|
294 <xsl:value-of select="concat('bug',$id)" />
|
|
295 </xsl:template>
|
|
296
|
|
297
|
|
298 <xsl:template name="bug-reference">
|
|
299 <xsl:param name="id" />
|
|
300 <xsl:param name="referer" />
|
|
301
|
|
302 <xsl:variable name="refererPathFragment">
|
|
303 <bug id="#root" />
|
|
304 <xsl:for-each select="$referer/ancestor-or-self::bug">
|
|
305 <bug id="{@id}" />
|
|
306 </xsl:for-each>
|
|
307 </xsl:variable>
|
|
308 <xsl:variable name="targetPathFragment">
|
|
309 <bug id="#root" />
|
|
310 <xsl:for-each
|
5
|
311 select="exsl:node-set($structure)//bug[@id = $id]/ancestor-or-self::bug">
|
4
|
312 <bug id="{@id}" />
|
|
313 </xsl:for-each>
|
|
314 </xsl:variable>
|
|
315 <xsl:variable name="path"
|
|
316 select="exsl:node-set($refererPathFragment)/bug" />
|
|
317 <xsl:variable name="targetPath"
|
|
318 select="exsl:node-set($targetPathFragment)/bug" />
|
|
319
|
|
320 <!-- find closest shared container id -->
|
|
321 <xsl:variable name="join"
|
|
322 select="($path[@id = $targetPath/@id])[position() = last() ]/@id" />
|
|
323
|
|
324 <!-- how many levels we need to up -->
|
|
325 <xsl:variable name="depth"
|
|
326 select="count($path[@id = $join]/following-sibling::node())" />
|
|
327
|
|
328 <!-- DEBUG -->
|
|
329 <!-- <xsl:value-of select="concat('id=', $id, ',referer=', $referer/@id)"
|
|
330 /> <xsl:text>, path=</xsl:text> <xsl:for-each select="$targetPath"> <xsl:value-of
|
|
331 select="concat(name(),@id)" /> <xsl:if test="position() != last()"> <xsl:text>-</xsl:text>
|
|
332 </xsl:if> </xsl:for-each> -->
|
|
333 <!-- DEBUG -->
|
|
334 <!-- <xsl:value-of select="concat(', join=', $join,', depth=', $depth,'
|
|
335 ')" /> -->
|
|
336
|
|
337 <!-- PRINT REFERENCE -->
|
|
338 <xsl:call-template name="repeat">
|
|
339 <xsl:with-param name="value" select="'!'" />
|
|
340 <xsl:with-param name="count" select="$depth" />
|
|
341 </xsl:call-template>
|
|
342 <xsl:for-each select="$targetPath[@id = $join]/following-sibling::node()">
|
|
343 <xsl:call-template name="bug-local-name">
|
|
344 <xsl:with-param name="id" select="@id" />
|
|
345 </xsl:call-template>
|
|
346 <xsl:if test="position() != last()">
|
|
347 <xsl:text>.</xsl:text>
|
|
348 </xsl:if>
|
|
349 </xsl:for-each>
|
|
350
|
0
|
351 </xsl:template>
|
|
352
|
|
353 <xsl:template name="start-task">
|
|
354 <xsl:param name="indent" />
|
4
|
355 <xsl:param name="id" />
|
|
356 <xsl:param name="desc" />
|
0
|
357 <xsl:call-template name="begin-line">
|
|
358 <xsl:with-param name="indent" select="$indent" />
|
|
359 </xsl:call-template>
|
|
360 <xsl:text>task </xsl:text>
|
5
|
361 <xsl:value-of select="$id" />
|
4
|
362 <xsl:value-of select="concat(' "',$desc,'" {')" />
|
0
|
363 <xsl:call-template name="end-line" />
|
|
364 </xsl:template>
|
|
365
|
|
366 <xsl:template name="end-task">
|
|
367 <xsl:param name="indent" />
|
|
368 <xsl:call-template name="begin-line">
|
|
369 <xsl:with-param name="indent" select="$indent" />
|
|
370 </xsl:call-template>
|
|
371 <xsl:text>}</xsl:text>
|
|
372 <xsl:call-template name="end-line" />
|
|
373 </xsl:template>
|
|
374
|
|
375 <xsl:template name="begin-line">
|
|
376 <xsl:param name="indent" />
|
|
377 <xsl:if test="number($indent) > 0">
|
|
378 <xsl:text> </xsl:text>
|
|
379 <xsl:call-template name="begin-line">
|
|
380 <xsl:with-param name="indent" select="$indent - 1" />
|
|
381 </xsl:call-template>
|
|
382 </xsl:if>
|
|
383 </xsl:template>
|
5
|
384
|
0
|
385 <xsl:template name="end-line">
|
|
386 <xsl:text>
</xsl:text>
|
|
387 </xsl:template>
|
4
|
388
|
|
389 <xsl:template name="repeat">
|
|
390 <xsl:param name="value" />
|
|
391 <xsl:param name="count" select="0" />
|
|
392
|
|
393 <xsl:if test="number($count)">
|
6
|
394 <xsl:value-of select="$value" />
|
4
|
395 <xsl:call-template name="repeat">
|
|
396 <xsl:with-param name="value" select="$value" />
|
|
397 <xsl:with-param name="count" select="$count - 1" />
|
|
398 </xsl:call-template>
|
|
399 </xsl:if>
|
|
400 </xsl:template>
|
5
|
401
|
|
402 <xsl:template name="comment">
|
|
403 <xsl:param name="indent" />
|
|
404 <xsl:param name="comment" />
|
|
405 <xsl:call-template name="println">
|
|
406 <xsl:with-param name="indent" select="$indent" />
|
|
407 <xsl:with-param name="text">
|
|
408 <xsl:text># </xsl:text>
|
|
409 <xsl:value-of select="$comment" />
|
|
410 </xsl:with-param>
|
|
411 </xsl:call-template>
|
|
412 </xsl:template>
|
|
413
|
|
414 <xsl:template name="println">
|
|
415 <xsl:param name="indent" />
|
|
416 <xsl:param name="text" />
|
|
417 <xsl:call-template name="begin-line">
|
|
418 <xsl:with-param name="indent" select="$indent" />
|
|
419 </xsl:call-template>
|
|
420 <xsl:value-of select="$text" />
|
|
421 <xsl:call-template name="end-line" />
|
|
422 </xsl:template>
|
0
|
423 </xsl:stylesheet> |