sysmodelgen/core/mergesysdef-module.xsl
branchHighFidelityModel
changeset 432 0f44a943faf9
parent 165 ba562c1e2717
equal deleted inserted replaced
429:cb270197b394 432:0f44a943faf9
     8 
     8 
     9 	Initial Contributors:
     9 	Initial Contributors:
    10 	Nokia Corporation - initial contribution.
    10 	Nokia Corporation - initial contribution.
    11 	Contributors:
    11 	Contributors:
    12 	Description:
    12 	Description:
    13 	XSLT module for merging only two sysdef files according to the 3.0.0 rules. Old syntax not supported and must be converetd before calling.
    13 	XSLT module for merging only two sysdef files according to the 3.0.1 rules. 
       
    14 		2.x and older syntax not supported and must be converted before calling.
       
    15 
       
    16 		Requires the including XSLT to also include path-module.xsl
    14 -->
    17 -->
    15 	
    18 	
    16 <xsl:variable name="defaultnamespace">http://www.symbian.org/system-definition</xsl:variable>
    19 <xsl:variable name="defaultnamespace">http://www.symbian.org/system-definition</xsl:variable>
    17 
    20 
    18 <xsl:template match="/SystemDefinition[starts-with(@schema,'2.') or starts-with(@schema,'1.')]" priority="2" mode="merge-models">
    21 <xsl:template match="/SystemDefinition[starts-with(@schema,'2.') or starts-with(@schema,'1.')]" priority="2" mode="merge-models">
    40 </xsl:apply-templates>
    43 </xsl:apply-templates>
    41 </xsl:element>
    44 </xsl:element>
    42 </xsl:template>
    45 </xsl:template>
    43 
    46 
    44 
    47 
    45 <xsl:template match="@id|@before" mode="translate-namespaces"><xsl:param name="nsdoc"/>
    48 <xsl:template match="@id|@before|@replace" mode="translate-namespaces"><xsl:param name="nsdoc"/>
    46 	<xsl:attribute name="{name()}">
    49 	<xsl:attribute name="{name()}">
    47 		<xsl:variable name="id">
    50 		<xsl:variable name="id">
    48 			<xsl:choose>
    51 			<xsl:choose>
    49 				<xsl:when test="contains(.,':')">
    52 				<xsl:when test="contains(.,':')">
    50 					<xsl:value-of select="substring-after(.,':')"/>
    53 					<xsl:value-of select="substring-after(.,':')"/>
   133 	<xsl:if test="name(*) != name($other/*)">
   136 	<xsl:if test="name(*) != name($other/*)">
   134 		<xsl:message terminate="yes">ERROR: Can only merge system models of the same rank</xsl:message>
   137 		<xsl:message terminate="yes">ERROR: Can only merge system models of the same rank</xsl:message>
   135 	</xsl:if>
   138 	</xsl:if>
   136 	 
   139 	 
   137 	<xsl:copy>
   140 	<xsl:copy>
   138 		<xsl:copy-of  select="@*"/> <!--  use attributes from origin model -->
   141 		<xsl:attribute name="schema">
       
   142 			<xsl:call-template name="compare-versions">
       
   143 				<xsl:with-param name="v1" select="@schema"/>
       
   144 				<xsl:with-param name="v2" select="$other/@schema"/>
       
   145 			</xsl:call-template>
       
   146 		</xsl:attribute>
       
   147 		<xsl:copy-of  select="@*[name()!='schema']"/> <!--  use attributes from origin model -->
   139 		<xsl:variable name="namespaces">
   148 		<xsl:variable name="namespaces">
   140 			<xsl:copy> <!-- needs <copy> so the processor doesn't lose the namespaces -->
   149 			<xsl:copy> <!-- needs <copy> so the processor doesn't lose the namespaces -->
   141 				<!--copy namespaces as needed -->
   150 				<!--copy namespaces as needed -->
   142 				
   151 				
   143 				<xsl:copy-of select="namespace::*[name()!='xml']"/> <!-- all upstream namespaces -->
   152 				<xsl:copy-of select="namespace::*[name()!='xml']"/> <!-- all upstream namespaces -->
   181 	</xsl:variable>
   190 	</xsl:variable>
   182 		<xsl:apply-templates mode="merge-models">
   191 		<xsl:apply-templates mode="merge-models">
   183 			<xsl:with-param name="other" select="exslt:node-set($otherdoc)/*"/>
   192 			<xsl:with-param name="other" select="exslt:node-set($otherdoc)/*"/>
   184 			<xsl:with-param name="up" select="$up"/>
   193 			<xsl:with-param name="up" select="$up"/>
   185 			<xsl:with-param name="down" select="$down"/>
   194 			<xsl:with-param name="down" select="$down"/>
       
   195 			<xsl:with-param name="replaces" select="exslt:node-set($otherdoc)//*[self::component or self::collection or self::package or self::layer]/@replace"/>
   186 		</xsl:apply-templates>
   196 		</xsl:apply-templates>
   187 	
   197 	
   188 	</xsl:copy>
   198 	</xsl:copy>
   189 </xsl:template>
   199 </xsl:template>
   190 
   200 
   191 <xsl:template match="systemModel" mode="merge-models">
   201 <xsl:template match="systemModel" mode="merge-models">
   192 	<xsl:param name="other"/>	<!-- the parent of the downstream systemModel this is merged with -->
   202 	<xsl:param name="other"/>	<!-- the parent of the downstream systemModel this is merged with -->
   193 	<xsl:param name="up"/>
   203 	<xsl:param name="up"/>
   194 	<xsl:param name="down"/>
   204 	<xsl:param name="down"/>
       
   205 	<xsl:param name="replaces"/>
   195 	<xsl:copy><xsl:copy-of  select="@*"/>
   206 	<xsl:copy><xsl:copy-of  select="@*"/>
   196 		<!--  copy metas and comments in between meta. Do not try to merge metadata between models -->
   207 		<!--  copy metas and comments in between meta. Do not try to merge metadata between models -->
   197 			<xsl:copy-of select="meta | $other/systemModel/meta | comment()[following-sibling::meta]"/>	
   208 			<xsl:copy-of select="meta | $other/systemModel/meta | comment()[following-sibling::meta]"/>	
   198 		<xsl:apply-templates mode="merge-models">
   209 		<xsl:apply-templates mode="merge-models">
   199 			<xsl:with-param name="other" select="$other/systemModel"/>
   210 			<xsl:with-param name="other" select="$other/systemModel"/>
   200 			<xsl:with-param name="up" select="$up"/>
   211 			<xsl:with-param name="up" select="$up"/>
   201 			<xsl:with-param name="down" select="$down"/>
   212 			<xsl:with-param name="down" select="$down"/>
       
   213 			<xsl:with-param name="replaces" select="$replaces"/>
   202 		</xsl:apply-templates>
   214 		</xsl:apply-templates>
       
   215 
       
   216 		<!-- tack on any remaining layers -->
       
   217 		<xsl:apply-templates mode="merge-copy-of" select="$other/systemModel/layer[not(@before) and not(following-sibling::*[@id=current()/layer/@id]) and not(@id=current()/layer/@id)]">
       
   218 			<xsl:with-param name="origin" select="$down"/>
       
   219 			<xsl:with-param name="root" select="current()/.."/>
       
   220 			<xsl:with-param name="replaces" select="$replaces"/>
       
   221 		</xsl:apply-templates>		
       
   222 
   203 	</xsl:copy>
   223 	</xsl:copy>
   204 </xsl:template>
   224 </xsl:template>
   205 
   225 
   206 <xsl:template match="@*|*|comment()" mode="merge-models"><xsl:copy-of select="."/></xsl:template>
   226 <xsl:template match="@*|*|comment()" mode="merge-models"><xsl:copy-of select="."/></xsl:template>
   207 
   227 
   233 				<xsl:value-of select="substring-after(concat(' ',normalize-space($other/@levels),' '),' - ')"/>
   253 				<xsl:value-of select="substring-after(concat(' ',normalize-space($other/@levels),' '),' - ')"/>
   234 			</xsl:variable>
   254 			</xsl:variable>
   235 			<xsl:attribute name="levels"><xsl:value-of select="normalize-space($lev)"/></xsl:attribute>
   255 			<xsl:attribute name="levels"><xsl:value-of select="normalize-space($lev)"/></xsl:attribute>
   236 		</xsl:when>
   256 		</xsl:when>
   237 		<xsl:otherwise> <!--  if they differ, use the origin's levels -->
   257 		<xsl:otherwise> <!--  if they differ, use the origin's levels -->
   238 			<xsl:message>Note: levels differ "<xsl:value-of select="."/>" vs "<xsl:value-of select="$other/@levels"/>"</xsl:message>
   258 			<xsl:message>Note: levels differ "<xsl:value-of select="."/>" vs "<xsl:value-of select="$other/@levels"/>" on <xsl:value-of select="../@id"/></xsl:message>
   239 			<xsl:copy-of select="."/>
   259 			<xsl:copy-of select="."/>
   240 		</xsl:otherwise>
   260 		</xsl:otherwise>
   241 	</xsl:choose>
   261 	</xsl:choose>
   242 </xsl:template>
   262 </xsl:template>
   243 
   263 
   250 	<xsl:param name="remainder" select="/.."/>
   270 	<xsl:param name="remainder" select="/.."/>
   251 
   271 
   252 	<xsl:choose>
   272 	<xsl:choose>
   253 		<xsl:when test="not($to-sort)"/>  <!-- nothing left to copy. stop -->
   273 		<xsl:when test="not($to-sort)"/>  <!-- nothing left to copy. stop -->
   254 		<xsl:when test="not($base)"/>  <!-- reached end. stop -->
   274 		<xsl:when test="not($base)"/>  <!-- reached end. stop -->
   255 		<xsl:when test="$base[1]/@id=$end/following-sibling::*[1]/@id"/> <!-- passed $end. Stop -->
   275 		<xsl:otherwise>
   256 		<xsl:when test="$base[1]/@id = $to-sort[1]/@id">  <!-- both lists start with same item -->
   276 			<xsl:for-each select="$to-sort">
   257 			<xsl:if test="$base[1]/@id!=$end/@id"> <!-- not at end, so keep going -->
   277 				<xsl:if test="((@before=$end/@id) or not(@before) or not($base/ancestor::SystemDefinition//*[@id=current()/@before])) and not($base[@id=current()/@id])">
   258 				<xsl:call-template name="copy-sorted-content">
   278 					<xsl:apply-templates mode="merge-copy-of" select=".">
   259 					<xsl:with-param name="base" select="$base[position() != 1]"/>
   279 						<xsl:with-param name="origin" select="$down"/>
   260 					<xsl:with-param name="to-sort" select="$to-sort[position() != 1]"/>
   280 						<xsl:with-param name="root" select="$end/ancestor::SystemDefinition"/>
   261 					<xsl:with-param name="remainder" select="$remainder"/>
   281 					</xsl:apply-templates>
   262 					<xsl:with-param name="start" select="$start"/>
   282 				</xsl:if>
   263 					<xsl:with-param name="end" select="$end"/>
   283 			</xsl:for-each>
   264 					<xsl:with-param name="down" select="$down"/>
   284 		</xsl:otherwise>	
   265 				</xsl:call-template>		
       
   266 			</xsl:if>
       
   267 		</xsl:when>	
       
   268 		<xsl:when test="$remainder[@id = $base[1]/@id]"> <!-- left over item is in $base -->
       
   269 			<xsl:call-template name="copy-sorted-content">
       
   270 				<xsl:with-param name="base" select="$base[position() != 1]"/>
       
   271 				<xsl:with-param name="to-sort" select="$to-sort"/>
       
   272 				<xsl:with-param name="remainder" select="$remainder[@id != $base[1]/@id]"/>
       
   273 				<xsl:with-param name="start" select="$start"/>
       
   274 				<xsl:with-param name="end" select="$end"/>
       
   275 				<xsl:with-param name="down" select="$down"/>
       
   276 			</xsl:call-template>		
       
   277 		</xsl:when>
       
   278 		<xsl:when test="not($base[@id = $to-sort[1]/@id])"> <!-- in to-sort, but not base -->		
       
   279 			<xsl:if test="$base[1]/@id=$end/@id  and not($base[@id=$to-sort[1]/@before])">
       
   280 			 	<!-- if at end, then this needs to be copied
       
   281 					don't copy if the before ID is found in $base	-->
       
   282 				<xsl:apply-templates mode="merge-copy-of" select="$to-sort[1]">
       
   283 					<xsl:with-param name="origin" select="$down"/>
       
   284 					<xsl:with-param name="root" select="$end/ancestor::systemModel"/>
       
   285 				</xsl:apply-templates>
       
   286 			</xsl:if>			
       
   287 		<xsl:call-template name="copy-sorted-content">
       
   288 			<xsl:with-param name="base" select="$base"/>
       
   289 			<xsl:with-param name="to-sort" select="$to-sort[position() != 1]"/>
       
   290 			<xsl:with-param name="remainder" select="$remainder"/>
       
   291 			<xsl:with-param name="start" select="$start"/>
       
   292 			<xsl:with-param name="end" select="$end"/>
       
   293 			<xsl:with-param name="down" select="$down"/>
       
   294 		</xsl:call-template>		
       
   295 		</xsl:when>	
       
   296 		<xsl:when test="not($to-sort[@id = $base[1]/@id])"> <!-- in base, but not to-sort -->		
       
   297 		<xsl:call-template name="copy-sorted-content">
       
   298 			<xsl:with-param name="base" select="$base[position() != 1]"/>
       
   299 			<xsl:with-param name="to-sort" select="$to-sort"/>
       
   300 			<xsl:with-param name="remainder" select="$remainder"/>
       
   301 			<xsl:with-param name="start" select="$start"/>
       
   302 			<xsl:with-param name="end" select="$end"/>
       
   303 			<xsl:with-param name="down" select="$down"/>
       
   304 		</xsl:call-template>		
       
   305 		</xsl:when>	
       
   306 		<xsl:when test="$base[@id = $to-sort[1]/@id]"> <!-- is in base, but not 1st one-->
       
   307 			<xsl:call-template name="copy-sorted-content">
       
   308 				<xsl:with-param name="base" select="$base"/>
       
   309 				<xsl:with-param name="to-sort" select="$to-sort[position() != 1] "/>
       
   310 				<xsl:with-param name="remainder" select="$remainder | $to-sort[1]"/>
       
   311 				<xsl:with-param name="start" select="$start"/>
       
   312 				<xsl:with-param name="end" select="$end"/>
       
   313 				<xsl:with-param name="down" select="$down"/>
       
   314 			</xsl:call-template>
       
   315 		</xsl:when>	
       
   316 	</xsl:choose>
   285 	</xsl:choose>
   317 </xsl:template>
   286 </xsl:template>
   318 
   287 
   319 <xsl:template match="node()" mode="merge-data">
   288 <xsl:template match="node()" mode="merge-data">
   320 	<xsl:copy-of select="." />
   289 	<xsl:copy-of select="." />
   351 	<xsl:apply-templates select="node()" mode="as-xml-text"/>
   320 	<xsl:apply-templates select="node()" mode="as-xml-text"/>
   352 	<xsl:value-of select="concat('&lt;/',name(),'&gt;')"/>
   321 	<xsl:value-of select="concat('&lt;/',name(),'&gt;')"/>
   353 </xsl:template>
   322 </xsl:template>
   354 
   323 
   355 
   324 
       
   325 <xsl:template name="best-prev"><xsl:param name="cur" select="."/><xsl:param name="alt"/>
       
   326 <xsl:if test="$alt">
       
   327 <xsl:variable name="prev" select="$cur/preceding-sibling::*[@id][1]"/> 
       
   328 <xsl:choose>
       
   329 	<xsl:when test="not($prev)"/>
       
   330 	<xsl:when test="$alt/preceding-sibling::*[@id=$prev/@id]"><xsl:value-of select="$prev/@id"/></xsl:when>
       
   331 	<xsl:otherwise>
       
   332 		<xsl:call-template name="best-prev">
       
   333 			<xsl:with-param name="cur" select="$prev"/>
       
   334 			<xsl:with-param name="alt" select="$alt"/>
       
   335 		</xsl:call-template>
       
   336 	</xsl:otherwise>
       
   337 </xsl:choose>
       
   338 </xsl:if>
       
   339 </xsl:template>
       
   340 
   356 <xsl:template match="layer | package | collection | component" mode="merge-models">
   341 <xsl:template match="layer | package | collection | component" mode="merge-models">
   357 	<xsl:param name="other"/>	<!-- the downstream item of the parent's rank that contains a potential items this is merged with -->
   342 	<xsl:param name="other"/>	<!-- the downstream item of the parent's rank that contains a potential items this is merged with -->
   358 	<xsl:param name="up"/>
   343 	<xsl:param name="up"/>
   359 	<xsl:param name="down"/>
   344 	<xsl:param name="down"/>
       
   345 	<xsl:param name="replaces"/>
   360 	<xsl:variable name="this" select="."/>	<!-- current item -->
   346 	<xsl:variable name="this" select="."/>	<!-- current item -->
   361 	
       
   362 	<!-- match = this item in the downstream model -->	
   347 	<!-- match = this item in the downstream model -->	
   363 	<xsl:variable name="match" select="$other/*[@id=current()/@id]"/>
   348 	<xsl:variable name="match" select="$other/*[@id=current()/@id]"/>
   364 	
   349 
   365 	
   350 	<xsl:choose>
       
   351 		<xsl:when test="$replaces[.=$this/@id] or (self::component and $match)">  <!-- replace the item instead of merge -->
       
   352 			<xsl:message>Note: <xsl:value-of select="name()"/> "<xsl:value-of select="@id"/>" in "<xsl:value-of select="../@id"/>" <xsl:choose>
       
   353 					<xsl:when test="self::component and $match">overridden in downstream sysdef</xsl:when>
       
   354 					<xsl:otherwise><xsl:for-each select="$replaces[.=$this/@id]/..">replaced by <xsl:value-of select="name()"/> "<xsl:value-of select="@id"/>" in "<xsl:value-of select="../@id"/>"</xsl:for-each></xsl:otherwise>
       
   355 				</xsl:choose>
       
   356 			</xsl:message>
       
   357 			<!-- if the removed item is in the downstream doc, just copy that and ignore the upstream contents -->
       
   358 			<xsl:apply-templates mode="merge-copy-of" select="$match">
       
   359 				<xsl:with-param name="origin" select="$down"/>
       
   360 				<xsl:with-param name="root" select="$this/ancestor::SystemDefinition"/>			
       
   361 				<xsl:with-param name="replaces" select="$replaces"/>
       
   362 			</xsl:apply-templates>		
       
   363 		</xsl:when>
       
   364 		<xsl:otherwise>
       
   365 			<!-- remove this if it's in the list of stuff to be replaced-->
       
   366 
       
   367 <xsl:variable name="prev-id">
       
   368 	<xsl:call-template name="best-prev">
       
   369 		<xsl:with-param name="alt" select="$match"/>
       
   370 	</xsl:call-template>
       
   371 </xsl:variable>
       
   372 
   366 	<!-- prev = the previous item before the current one (no metas, only named items)-->
   373 	<!-- prev = the previous item before the current one (no metas, only named items)-->
   367 	<xsl:variable name="prev" select="preceding-sibling::*[@id][1]"/> 
   374 	<xsl:variable name="prev" select="preceding-sibling::*[@id=$prev-id]"/> 
   368 
   375 
   369 	<!-- copy all items between this and prev  that are solely in the downstream model -->	 		
   376 
   370 
   377 	<!-- copy all items between this and prev that are solely in the downstream model -->	 		
   371 	<xsl:choose>
   378 
   372 		<xsl:when test="$match and (not($prev) or $other/*[@id= $prev/@id] )">
   379 	<!-- <xsl:variable name="upstream-ids" select="ancestor::SystemDefinition//@id[parent::component or parent::collection or parent::package or parent::layer]"/> -->
       
   380 	<xsl:variable name="upstream-ids" select="../*/@id"/> <!-- this is much faster than using all IDs. before only currently works in the same parent anyway -->
       
   381 
       
   382 	<!-- $upstream-ids is used to avoid inserting an item that's being moved -->
       
   383 
       
   384 	<xsl:choose>
       
   385 		<xsl:when test="$match and $prev">
   373 			<xsl:call-template name="copy-sorted-content">
   386 			<xsl:call-template name="copy-sorted-content">
   374 				<xsl:with-param name="base" select="../*[@id]"/>
   387 				<xsl:with-param name="base" select="../*[@id]"/>
   375 				<xsl:with-param name="to-sort" select="$other/*[@id]"/>
   388 				<xsl:with-param name="to-sort" select="$other/*[@id and not(@before=$upstream-ids)][following-sibling::*[@id=$match/@id]][preceding-sibling::*[@id=$prev/@id]]"/>
   376 				<xsl:with-param name="start" select="$prev"/>
   389 				<xsl:with-param name="start" select="$prev"/>
   377 				<xsl:with-param name="end" select="."/>
   390 				<xsl:with-param name="end" select="."/>
   378 				<xsl:with-param name="down" select="$down"/>
   391 				<xsl:with-param name="down" select="$down"/>
   379 			</xsl:call-template>
   392 			</xsl:call-template>
   380 		</xsl:when>
   393 		</xsl:when>
   381 	<xsl:when test="not($match/preceding-sibling::*[@id=$this/../*/@id]) and $other/*[@id= current()/@id]/preceding-sibling::*[@id and not(@before)]">
   394 		<xsl:when test="$match and not($prev)">
   382 		<!-- if this is the first item in other that's also in this, then put all new items from other here -->
   395 			<xsl:call-template name="copy-sorted-content">
   383 		<xsl:apply-templates mode="merge-copy-of" select="$match/preceding-sibling::*[@id and not(@before)]">
   396 				<xsl:with-param name="base" select="../*[@id]"/>
   384 			<xsl:with-param name="origin" select="$down"/>
   397 				<xsl:with-param name="to-sort" select="$other/*[@id and not(@before=$upstream-ids)][following-sibling::*[@id=$match/@id]]"/>
   385 			<xsl:with-param name="root" select="$this/ancestor::systemModel"/>	
   398 				<xsl:with-param name="start" select="$prev"/>
   386 		</xsl:apply-templates>
   399 				<xsl:with-param name="end" select="."/>
   387 	</xsl:when>
   400 				<xsl:with-param name="down" select="$down"/>
       
   401 			</xsl:call-template>
       
   402 		</xsl:when>
   388 	</xsl:choose>
   403 	</xsl:choose>
   389 
   404 
   390  	<!-- just copy anything identified as being before this, assume they're all ok -->
   405  	<!-- just copy anything identified as being before this, assume they're all ok -->
       
   406 
   391 	<xsl:apply-templates mode="merge-copy-of" select="$other/*[@before=current()/@id]">
   407 	<xsl:apply-templates mode="merge-copy-of" select="$other/*[@before=current()/@id]">
   392 		<xsl:with-param name="remove-before" select="1"/>
   408 		<xsl:with-param name="remove-before" select="1"/>
   393 		<xsl:with-param name="origin" select="$down"/>
   409 		<xsl:with-param name="origin" select="$down"/>
   394 		<xsl:with-param name="root" select="$this/ancestor::systemModel"/>	
   410 		<xsl:with-param name="root" select="$this/ancestor::SystemDefinition"/>	
       
   411 		<xsl:with-param name="replaces" select="$replaces"/>
   395 	</xsl:apply-templates>
   412 	</xsl:apply-templates>
   396 
       
   397 	
   413 	
   398 	<xsl:copy>
   414 	<xsl:copy>
   399 		<xsl:apply-templates select="@*" mode="merge-models"> <!-- copy upstream attributes -->
   415 		<xsl:apply-templates select="@*" mode="merge-models"> <!-- copy upstream attributes -->
   400 			<xsl:with-param name="other" select="$match"/>
   416 			<xsl:with-param name="other" select="$match"/>
   401 		</xsl:apply-templates>
   417 		</xsl:apply-templates>
   408 			<xsl:if test="not(@root)">
   424 			<xsl:if test="not(@root)">
   409 				<xsl:copy-of select="$up/@root"/>
   425 				<xsl:copy-of select="$up/@root"/>
   410 			</xsl:if>
   426 			</xsl:if>
   411 		</xsl:if>
   427 		</xsl:if>
   412 		
   428 		
   413 		<xsl:for-each select="$match/@*">  <!-- copy downstream attributes, only if not set on upstream -->
   429 		<xsl:for-each select="$match/@*[name()!='replace']">  <!-- copy downstream attributes, only if not set on upstream -->
   414 			<xsl:if test="not($this/@*[name()=name(current())])"><xsl:copy-of select="."/></xsl:if>
   430 			<xsl:if test="not($this/@*[name()=name(current())])"><xsl:copy-of select="."/></xsl:if>
   415 		</xsl:for-each>
   431 		</xsl:for-each>
       
   432 
       
   433 		<xsl:if test="$match/@replace"> <!-- check replace separately -->
       
   434 			<xsl:if test="not($this/ancestor::SystemDefinition//*[(self::component or self::collection or self::package or self::layer) and $match/@replace=@id])">
       
   435 				<!-- only remove replace if it's been used -->
       
   436 				<xsl:copy-of select="$match/@replace"/>
       
   437 			</xsl:if>
       
   438 		</xsl:if>
   416 		
   439 		
   417 		<xsl:choose>
   440 		<xsl:choose>
   418 			<xsl:when test="self::component">
   441 			<xsl:when test="self::component">
   419 				<!-- copy all units, metas and comments from this
   442 				<!-- copy all units, metas and comments from this
   420 					copy all metas in the merged component
   443 					copy all metas in the merged component
   433 				
   456 				
   434 				<xsl:apply-templates mode="merge-models">
   457 				<xsl:apply-templates mode="merge-models">
   435 					<xsl:with-param name="other" select="$match"/>
   458 					<xsl:with-param name="other" select="$match"/>
   436 					<xsl:with-param name="up" select="$up"/>
   459 					<xsl:with-param name="up" select="$up"/>
   437 					<xsl:with-param name="down" select="$down"/>
   460 					<xsl:with-param name="down" select="$down"/>
       
   461 					<xsl:with-param name="replaces" select="$replaces"/>
   438 				</xsl:apply-templates>
   462 				</xsl:apply-templates>
   439 				<!--  don't copy if explicitly or implicitly placed already-->
   463 				<!--  don't copy if explicitly or implicitly placed already-->
   440 				<xsl:for-each select="$match/*[not(@before) and not(following-sibling::*[@id=$this/*/@id])]">
   464 				<xsl:for-each select="$match/*[not(@before) and not(following-sibling::*[@id=$this/*/@id])]">
   441 					<xsl:if test="not($this/*[@id=current()/@id])">
   465 					<xsl:if test="not($this/*[@id=current()/@id])">
   442 						<xsl:apply-templates mode="merge-copy-of" select=".">
   466 						<xsl:apply-templates mode="merge-copy-of" select=".">
   443 							<xsl:with-param name="origin" select="$down"/>
   467 							<xsl:with-param name="origin" select="$down"/>
   444 							<xsl:with-param name="root" select="$this/ancestor::systemModel"/>			
   468 							<xsl:with-param name="root" select="$this/ancestor::SystemDefinition"/>			
       
   469 							<xsl:with-param name="replaces" select="$replaces"/>
   445 						</xsl:apply-templates>
   470 						</xsl:apply-templates>
   446 					</xsl:if>
   471 					</xsl:if>
   447 				</xsl:for-each>
   472 				</xsl:for-each>
   448 			</xsl:otherwise>
   473 			</xsl:otherwise>
   449 		</xsl:choose>
   474 		</xsl:choose>
   450 	</xsl:copy>
   475 	</xsl:copy>
   451 	
   476 
   452 	<xsl:if test="self::layer and not(following-sibling::layer)">	
   477 		</xsl:otherwise>
   453 		<!-- for the last layer, tack on any remaining layers -->
   478 	</xsl:choose>
   454 		<xsl:apply-templates mode="merge-copy-of" select="$other/layer[not(@before) and not(following-sibling::*[@id=$this/../layer/@id]) and not(@id=$this/../layer/@id)]">
       
   455 			<xsl:with-param name="origin" select="$down"/>
       
   456 			<xsl:with-param name="root" select="$this/ancestor::systemModel"/>			
       
   457 		</xsl:apply-templates>		
       
   458 	</xsl:if>
       
   459 </xsl:template>
   479 </xsl:template>
   460 
   480 
   461 
   481 
   462 
   482 
   463 <xsl:template match="*" mode="merge-copy-of">
   483 <xsl:template match="*" mode="merge-copy-of">
   464 	<xsl:param name="remove-before" select="0"/> <!-- set to true if any before attribute is to be removed -->
   484 	<xsl:param name="remove-before" select="0"/> <!-- set to true if any before attribute is to be removed -->
   465 	<xsl:param name="origin"/>	<!--the element containing the @name to use the origin-model attribute  -->
   485 	<xsl:param name="origin"/>	<!--the element containing the @name to use the origin-model attribute  -->
   466 	<xsl:param name="root"/> 	<!--the systemModel element in the upstream doc  -->
   486 	<xsl:param name="root"/> 	<!--the systemModel element in the upstream doc  -->
   467 
   487 	<xsl:param name="replaces" select="ancestor::SystemDefinition/descendant::*[(self::component or self::collection or self::package or self::layer) and not(ancestor::meta)]/@replace"/> <!-- recalculate this is necessarfy, but should just pass down as a param -->
       
   488 	<xsl:variable name="moved" select="$root/descendant::*[name()=name(current()/..) and @id!=current()/../@id]/*[@id=current()/@id]"/>
   468 	<xsl:choose>
   489 	<xsl:choose>
   469 		<!-- this might slow things down, consider making optional -->
   490 		<!-- this might slow things down, consider making optional -->
   470 		<xsl:when test="not(self::layer) and count($root/descendant::*[name()=name(current()/..) and @id!=current()/../@id]/*[@id=current()/@id])">
   491 		<xsl:when test="not(self::layer) and (count($moved) and not($moved[ancestor-or-self::*/@id=$replaces]) )">
   471 			<xsl:message>Warning: <xsl:value-of select="name()"/> "<xsl:value-of select="@id"/>" moved in downstream model. Ignoring moved <xsl:value-of select="name()"/>
   492 			<xsl:message>Warning: <xsl:value-of select="name()"/> "<xsl:value-of select="@id"/>" moved in downstream model. Ignoring moved <xsl:value-of select="name()"/>
   472 				<xsl:text>&#xa;</xsl:text>
   493 				<xsl:text>&#xa;</xsl:text>
   473 			</xsl:message>
   494 			</xsl:message>
   474 		</xsl:when>
   495 		</xsl:when>
   475 		<xsl:otherwise>
   496 		<xsl:otherwise>
   476 			<!-- save all content in a variable to test to see if it's got any problems (ie been removed due to errors)-->
   497 			<!-- save all content in a variable to test to see if it's got any problems (ie been removed due to errors)-->
   477 			<xsl:variable name="content">
   498 			<xsl:variable name="content">
   478 				<xsl:apply-templates select="*|comment()" mode="merge-copy-of">
   499 				<xsl:apply-templates select="*|comment()" mode="merge-copy-of">
   479 					<xsl:with-param name="origin" select="$origin"/>
   500 					<xsl:with-param name="origin" select="$origin"/>
   480 					<xsl:with-param name="root" select="$root"/>
   501 					<xsl:with-param name="root" select="$root"/>
       
   502 					<xsl:with-param name="replaces" select="$replaces"/>
   481 				</xsl:apply-templates>
   503 				</xsl:apply-templates>
   482 			</xsl:variable>
   504 			</xsl:variable>
   483 			<xsl:choose>
   505 			<xsl:choose>
   484 				<!-- if all elements in this have been deleted, throw out this element -->
   506 				<!-- if all elements in this have been deleted, throw out this element -->
   485 				<xsl:when test="not(exslt:node-set($content)/*) and *">
   507 				<xsl:when test="not(exslt:node-set($content)/*) and *">
   487 						<xsl:text>&#xa;</xsl:text>
   509 						<xsl:text>&#xa;</xsl:text>
   488 					</xsl:message>
   510 					</xsl:message>
   489 				</xsl:when>
   511 				</xsl:when>
   490 				<xsl:otherwise>
   512 				<xsl:otherwise>
   491 					<xsl:copy>
   513 					<xsl:copy>
   492 						<xsl:choose>
   514 						<xsl:call-template name="merge-copy-of-atts">
   493 							<xsl:when test="$remove-before">
   515 							<xsl:with-param name="remove-before" select="$remove-before"/>
   494 								<xsl:copy-of select="@*[name()!='before']"/>
   516 							<xsl:with-param name="root" select="$root"/>
   495 							</xsl:when>
   517 						</xsl:call-template>
   496 							<xsl:otherwise><xsl:copy-of select="@*"/></xsl:otherwise>
       
   497 						</xsl:choose>
       
   498 						<xsl:copy-of select="exslt:node-set($content)"/>
   518 						<xsl:copy-of select="exslt:node-set($content)"/>
   499 					</xsl:copy>
   519 					</xsl:copy>
   500 				</xsl:otherwise>
   520 				</xsl:otherwise>
   501 			</xsl:choose>					
   521 			</xsl:choose>					
   502 		</xsl:otherwise>
   522 		</xsl:otherwise>
   503 	</xsl:choose>
   523 	</xsl:choose>
   504 </xsl:template>
   524 </xsl:template>
   505 
       
   506 
       
   507 <xsl:template match="comment()|@*" mode="merge-copy-of">
   525 <xsl:template match="comment()|@*" mode="merge-copy-of">
   508 	<xsl:copy-of select="."/>
   526 	<xsl:copy-of select="."/>
       
   527 </xsl:template>
       
   528 
       
   529 
       
   530 <xsl:template name="merge-copy-of-atts">
       
   531 	<xsl:param name="remove-before" select="0"/> <!-- set to true if any before attribute is to be removed -->
       
   532 	<xsl:param name="root"/> 	<!--the systemModel element in the upstream doc  -->
       
   533 	
       
   534 	<xsl:choose>
       
   535 		<xsl:when test="$remove-before">
       
   536 			<xsl:copy-of select="@*[name()!='before' and name()!='replace']"/>
       
   537 		</xsl:when>
       
   538 		<xsl:otherwise><xsl:copy-of select="@*[name()!='replace']"/></xsl:otherwise>
       
   539 	</xsl:choose>
       
   540 	<xsl:if test="@replace and not($root/descendant::*[(self::component or self::collection or self::package or self::layer) and @id=current()/@replace])">
       
   541 		<!-- only include replace if it's not been used -->
       
   542 		<xsl:copy-of select="@replace"/>
       
   543 	</xsl:if>
   509 </xsl:template>
   544 </xsl:template>
   510 
   545 
   511 <xsl:template match="component" mode="merge-copy-of">
   546 <xsl:template match="component" mode="merge-copy-of">
   512 	<xsl:param name="remove-before" select="0"/> <!-- set to true if any before attribute is to be removed -->
   547 	<xsl:param name="remove-before" select="0"/> <!-- set to true if any before attribute is to be removed -->
   513 	<xsl:param name="origin"/>	<!--the element containing the @name to use the origin-model attribute  -->
   548 	<xsl:param name="origin"/>	<!--the element containing the @name to use the origin-model attribute  -->
   514 	<xsl:param name="root"/> 	<!--the systemModel element in the upstream doc  -->
   549 	<xsl:param name="root"/> 	<!--the systemModel element in the upstream doc  -->
   515 	
       
   516 	<xsl:choose>
   550 	<xsl:choose>
   517 		<!-- this might slow things down, consider making optional -->
   551 		<!-- this might slow things down, consider making optional -->
   518 		<xsl:when test="$root/descendant::collection[@id!=current()/../@id]/component[@id=current()/@id]">
   552 		<xsl:when test="$root/descendant::collection[@id!=current()/../@id]/component[@id=current()/@id]">
   519 			<xsl:message>Warning: <xsl:value-of select="name()"/> "<xsl:value-of select="@id"/>" moved in downstream model. Ignoring moved <xsl:value-of select="name()"/>
   553 			<xsl:message>Warning: <xsl:value-of select="name()"/> "<xsl:value-of select="@id"/>" moved in downstream model. Ignoring moved <xsl:value-of select="name()"/>
   520 				<xsl:text>&#xa;</xsl:text>
   554 				<xsl:text>&#xa;</xsl:text>
   521 			</xsl:message>
   555 			</xsl:message>
   522 		</xsl:when>
   556 		</xsl:when>
   523 		<xsl:otherwise>
   557 		<xsl:otherwise>
   524 			<xsl:copy>
   558 			<xsl:copy>
   525 				<xsl:choose>
   559 				<xsl:call-template name="merge-copy-of-atts">
   526 					<xsl:when test="$remove-before">
   560 					<xsl:with-param name="remove-before" select="$remove-before"/>
   527 						<xsl:copy-of select="@*[name()!='before']"/>
   561 					<xsl:with-param name="root" select="$root"/>
   528 					</xsl:when>
   562 				</xsl:call-template>
   529 					<xsl:otherwise><xsl:copy-of select="@*"/></xsl:otherwise>
       
   530 				</xsl:choose>
       
   531 				<xsl:if test="not(@origin-model) and $origin/@name">
   563 				<xsl:if test="not(@origin-model) and $origin/@name">
   532 					<xsl:attribute name="origin-model">
   564 					<xsl:attribute name="origin-model">
   533 						<xsl:value-of select="$origin/@name"/>
   565 						<xsl:value-of select="$origin/@name"/>
   534 					</xsl:attribute>
   566 					</xsl:attribute>
   535 					<xsl:if test="not(@root)">
   567 					<xsl:if test="not(@root)">
   536 						<xsl:copy-of select="$origin/@root"/>
   568 						<xsl:copy-of select="$origin/@root"/>
   537 					</xsl:if>
   569 					</xsl:if>
   538 				</xsl:if>
   570 				</xsl:if>
   539 				<xsl:copy-of select="*|comment()"/>
   571 				<xsl:apply-templates select="*|comment()" mode="merge-copy-of">
       
   572 					<xsl:with-param name="origin" select="$origin"/>
       
   573 					<xsl:with-param name="root" select="$root"/>
       
   574 				</xsl:apply-templates>
   540 			</xsl:copy>
   575 			</xsl:copy>
   541 		</xsl:otherwise>
   576 		</xsl:otherwise>
   542 	</xsl:choose>
   577 	</xsl:choose>
   543 </xsl:template>
   578 </xsl:template>
   544 
   579 
       
   580 
       
   581 <xsl:template match="unit" mode="merge-copy-of">
       
   582 	<xsl:param name="origin"/>	<!--the element containing the @name to use the origin-model attribute  -->
       
   583 	<xsl:param name="root"/> 	<!--the systemModel element in the upstream doc  -->
       
   584 	<xsl:copy>
       
   585 				<xsl:apply-templates select="@*" mode="merge-copy-of">
       
   586 					<xsl:with-param name="origin" select="$origin"/>
       
   587 					<xsl:with-param name="root" select="$root"/>
       
   588 				</xsl:apply-templates>
       
   589 	</xsl:copy>
       
   590 </xsl:template>
       
   591 
       
   592 
       
   593 
       
   594 
       
   595 <xsl:template match="meta" mode="merge-copy-of">
       
   596 	<xsl:param name="origin"/>	<!--the element containing the @name to use the origin-model attribute  -->
       
   597 	<xsl:param name="root"/> 	<!--the systemModel element in the upstream doc  -->
       
   598 	<xsl:copy>
       
   599 		<xsl:apply-templates select="@*" mode="merge-copy-of">
       
   600 			<xsl:with-param name="origin" select="$origin"/>
       
   601 			<xsl:with-param name="root" select="$root"/>
       
   602 		</xsl:apply-templates>
       
   603 		<xsl:copy-of select="node()"/>
       
   604 	</xsl:copy>
       
   605 </xsl:template>
       
   606 
       
   607 
       
   608 <xsl:template match="unit/@bldFile | unit/@mrp | unit/@base | meta/@href" mode="merge-copy-of">
       
   609 	<xsl:param name="origin" select="/.."/>	<!--the element containing the @name to use the origin-model attribute  -->
       
   610 
       
   611 	<xsl:attribute name="{name()}">
       
   612 		<xsl:choose>
       
   613 			<xsl:when test="not($origin/@pathto)"><xsl:value-of select="."/></xsl:when>
       
   614 			<xsl:when test="(contains(.,'://') and not(contains(substring-before(.,'://'),'/'))) or starts-with(.,'/')"> <!-- absolute URI or absolute path-->
       
   615 				<xsl:value-of select="."/>
       
   616 			</xsl:when>
       
   617 			<xsl:when test="contains($origin/@pathto,'://') and not(contains(substring-before($origin/@pathto,'://'),'/'))"> <!-- absolute URI for downstream sysdef not valif for unit paths, just copy and raise warning-->
       
   618 				<xsl:message>ERROR: Could not resolve relative path in downstream file: <xsl:value-of select="."/> relative to absolute URI <xsl:value-of select="$origin/@pathto"/></xsl:message>
       
   619 				<xsl:value-of select="."/>
       
   620 			</xsl:when>
       
   621 		<xsl:otherwise> <!-- relative link -->
       
   622 			<xsl:call-template name="joinpath">
       
   623 				<xsl:with-param name="file" select="$origin/@pathto"/>
       
   624 				<xsl:with-param name="rel" select="."/>
       
   625 			</xsl:call-template>
       
   626 		</xsl:otherwise>
       
   627 		</xsl:choose>
       
   628 	</xsl:attribute>
       
   629 </xsl:template>
   545 </xsl:stylesheet>
   630 </xsl:stylesheet>