Move sysdeftools from buildtools package into build package
authorBob Rosenberg <bob.rosenberg@nokia.com>
Wed, 28 Jul 2010 13:20:46 +0100
changeset 624 f70b728ea30c
parent 621 96fee2635b19
child 625 a1925fb7753a
child 634 f7179968fc36
Move sysdeftools from buildtools package into build package
metatools/sysdeftools/checklinks.bat
metatools/sysdeftools/checklinks.pl
metatools/sysdeftools/docs/readme.txt
metatools/sysdeftools/filtering.bat
metatools/sysdeftools/filtering.xsl
metatools/sysdeftools/group/bld.inf
metatools/sysdeftools/group/unixxslcmd
metatools/sysdeftools/group/unixxsltccmd
metatools/sysdeftools/joinandparesysdef.bat
metatools/sysdeftools/joinandparesysdef.xsl
metatools/sysdeftools/joinsysdef.bat
metatools/sysdeftools/joinsysdef.pl
metatools/sysdeftools/joinsysdef.xsl
metatools/sysdeftools/lib/filter-module.xsl
metatools/sysdeftools/lib/joinsysdef-module.xsl
metatools/sysdeftools/lib/mergesysdef-module.xsl
metatools/sysdeftools/lib/modelcheck.xsl
metatools/sysdeftools/lib/path-module.xsl
metatools/sysdeftools/lib/test-model.xsl
metatools/sysdeftools/lib/usage.xsl
metatools/sysdeftools/mergesysdef.bat
metatools/sysdeftools/mergesysdef.xsl
metatools/sysdeftools/rootsysdef.bat
metatools/sysdeftools/rootsysdef.pl
metatools/sysdeftools/sysdefdowngrade.bat
metatools/sysdeftools/sysdefdowngrade.xsl
metatools/sysdeftools/validate-sysdef.bat
metatools/sysdeftools/validate-sysdef.xsl
metatools/sysdeftools/xalanj/LICENSE.xalan
metatools/sysdeftools/xalanj/serializer.jar
metatools/sysdeftools/xalanj/xalan.jar
metatools/sysdeftools/xalanj/xercesImpl.jar
metatools/sysdeftools/xalanj/xml-apis.jar
package_definition.xml
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metatools/sysdeftools/checklinks.bat	Wed Jul 28 13:20:46 2010 +0100
@@ -0,0 +1,17 @@
+@rem Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+@rem All rights reserved.
+@rem This component and the accompanying materials are made available
+@rem under the terms of the License "Eclipse Public License v1.0"
+@rem which accompanies this distribution, and is available
+@rem at the URL "http://www.eclipse.org/legal/epl-v10.html".
+@rem
+@rem Initial Contributors:
+@rem Nokia Corporation - initial contribution.
+@rem
+@rem Contributors:
+@rem
+@rem Description: 
+@rem
+@setlocal
+@perl %~dpn0.pl %*
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metatools/sysdeftools/checklinks.pl	Wed Jul 28 13:20:46 2010 +0100
@@ -0,0 +1,525 @@
+# Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "Eclipse Public License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+#
+# Initial Contributors:
+# Nokia Corporation - initial contribution.
+#
+# Contributors:
+#
+# Description:
+# Script to validate the unit links in a system definition or package definition XML file
+#!/usr/bin/perl
+
+use strict;
+
+
+use FindBin;		# for FindBin::Bin
+use lib $FindBin::Bin;
+use lib "$FindBin::Bin/lib";
+
+use Cwd;
+use Cwd 'abs_path';
+use Getopt::Long;
+use File::Basename;
+use File::Spec;
+use XML::DOM;
+
+my $output;
+my $path;
+my %defineParams;
+my %defines;
+my $defaultns = 'http://www.symbian.org/system-definition';	# needed if no DTD
+my $realloc;
+
+# need to add options for controlling which metas are filtered out and which are included inline
+GetOptions
+	(
+	'path=s' => $path,
+	 'effective-sysdef=s' => \$realloc
+	);
+
+# -path specifies the full system-model path to the file which is being processed. 
+#	This must be an absolute path if you're processing a root sysdef.
+#	If processing a pkgdef file, you can use "./package_definition.xml" to leave all links relative. Though I can't really see the use case for this.
+
+
+# if config is not set, no confguration will be done.
+# If it is set, all configuration metadata will be processed and stripped from the output, even if the confguration data is empty
+
+ if($path eq '') {$path = '/os/deviceplatformrelease/foundation_system/system_model/system_definition.xml'}
+
+($#ARGV == -1 ) && &help();
+my $sysdef = &abspath(shift);	# resolve the location of the root sysdef
+
+$realloc = $realloc || $sysdef;
+
+my %unitmap;
+my @p1=reverse(split(/[\\\/]/,$path));
+my @p2=reverse(split(/[\\\/]/,$realloc));
+
+shift(@p1);shift(@p2); # don't care abt file name
+while(lc($p1[0]) eq lc($p2[0])) {shift(@p1);shift(@p2)}
+
+$unitmap{join('/',reverse(@p1))} = join("/",reverse(@p2));
+
+my @p1=reverse(split(/[\\\/]/,$sysdef));
+my @p2=reverse(split(/[\\\/]/,$realloc));
+
+shift(@p1);shift(@p2); # don't care abt file name
+while(lc($p1[0]) eq lc($p2[0]) && scalar(@p1)) {shift(@p1);shift(@p2)}
+
+$unitmap{join('/',reverse(@p1))} = join("/",reverse(@p2));
+
+
+# rootmap is a mapping from the filesystem to the paths in the doc
+my %rootmap = &rootMap($path,$sysdef);	
+my %nsmap;
+my %urimap;
+
+my $parser = new XML::DOM::Parser;
+my   $sysdefdoc;
+eval {
+	$sysdefdoc = $parser->parsefile ($sysdef);
+};
+if(!$sysdefdoc) {
+	die "ERROR: could not open $sysdef\n";
+}
+
+
+
+my $maxschema = $sysdefdoc->getDocumentElement()->getAttribute('schema');	# don't check value, just store it.
+
+my $docroot =  $sysdefdoc->getDocumentElement;
+
+my $ns = $docroot->getAttribute('id-namespace');
+if(!$ns && $nsmap{''})
+	{
+	$docroot->setAttribute('id-namespace',$nsmap{''});
+	}
+
+$docroot->setAttribute('schema',$maxschema);	# output has the largest syntax version of all includes
+
+
+while(my($pre,$uri) = each(%nsmap))
+	{
+	$pre ne '' || next ;
+	$docroot->setAttribute("xmlns:$pre",$uri);
+	}
+
+&walk($sysdef,$docroot);	# process the XML
+
+ 
+sub abspath
+	{ 	# normalize the path into an absolute one
+	my  ($name,$path) = fileparse($_[0]);
+	$path=~tr,\\,/,;
+	if( -e $path)
+		{
+		return abs_path($path)."/$name";
+		}
+	my @dir = split('/',$_[0]);
+	my @new;
+	foreach my $d (@dir)
+		{
+		if($d eq '.') {next}
+		if($d eq '..')
+			{
+			pop(@new);
+			next;
+			}
+		push(@new,$d)
+		}
+	return join('/',@new);
+	}
+
+sub rootMap {
+	my @pathdirs = split(/\//,$_[0]);
+	my @rootdirs = split(/\//,$_[1]);
+
+	while(lc($rootdirs[$#rootdirs])  eq lc($pathdirs[$#pathdirs])  )
+		{
+		pop(@rootdirs);
+		pop(@pathdirs);
+		}
+	return (join('/',@rootdirs)  => join('/',@pathdirs) );
+	}
+
+sub rootMapMeta {
+	# find all the explict path mapping from the link-mapping metadata
+	my $node = shift;
+	foreach my $child (@{$node->getChildNodes})
+			{
+			if ($child->getNodeType==1 && $child->getTagName eq 'map-prefix')
+				{
+				my $from = $child->getAttribute('link');
+				my $to = $child->getAttribute('to');		# optional, but blank if not set
+				$rootmap{$from} = $to;
+				}
+			}
+	# once this is processed we have no more need for it. Remove from output
+	$node->getParentNode->removeChild($node);
+	}
+
+
+sub walk
+	{ 	# walk through the doc, resolving all links
+	my $file = shift;
+	my $node = shift;
+	my $type = $node->getNodeType;
+	if($type!=1) {return}
+	my $tag = $node->getTagName;
+	if($tag=~/^(layer|package|collection|component)$/ )
+		{
+		my $link= $node->getAttribute('href');
+		if($link)
+			{
+			my $file = &resolvePath($file,$link); 
+			if(-e $file)
+				{
+				&combineLink($node,$file);
+				}
+			else
+				{
+				print  "Note: $file not found\n";
+				$node->removeAttribute('href');
+				}
+			return;
+			}
+		}
+	elsif($tag=~/^(SystemDefinition|systemModel)$/ )
+		{
+		}
+	elsif($tag eq 'unit')
+		{
+		my %at = &atts($node);
+		my $pro;
+		foreach my $o (keys(%at)) 
+			{
+			if($o eq 'proFile' || $o=~/:proFile$/)
+				{
+				$pro = $at{$o};
+				last;
+				}
+			}
+		my $filter=$node->getParentNode()->getAttribute('filter');
+		if($filter ne '' && $at{'filter'}) {$filter.=','.$at{'filter'}}
+		elsif($at{'filter'}) {$filter=$at{'filter'}}
+		if($filter ne '') {$filter="\t($filter)"}
+		foreach my $atr ('bldFile','mrp','base')
+			{
+			my $ext;
+			my $link= $at{$atr};
+			if($atr eq 'bldFile') {
+				$ext = ($pro ne '') ? "/$pro" : '/bld.inf'
+			}
+			if($link ne '')
+				{
+				my $ok = 0;
+				my $trylink;
+				if($link && !($link=~/^\//))
+					{
+					$link= &abspath(File::Basename::dirname($file)."/$link");
+					$ok = (-e "$link$ext");
+					if(!$ok)	
+						{
+						foreach my $a (keys %rootmap)
+							{
+							$link=~s,^$a,$rootmap{$a},ie;
+							# remove leading ./  which is used to indicate that paths should remain relative
+							$link=~s,^\./([^/]),$1,; 
+							}
+
+						}
+					}
+				if(!$ok)
+					{
+					foreach my $a (keys %unitmap) {
+						if($a eq substr($link,0,length($a))) {
+							$trylink = $unitmap{$a}.substr($link,length($a));
+							if(-e "$trylink$ext") {
+								$ok=1;
+								$link = $trylink;
+								last;
+							}
+						}
+					}
+					}
+				if(!$ok)
+					{
+					print "Error: $atr not found in ",($trylink ne '') ? $trylink : $link,"$filter\n";
+					}				
+				}
+			}
+		}
+	elsif($tag eq 'meta')
+		{
+		my $rel= $node->getAttribute('rel') || 'Generic';
+		my $link= $node->getAttribute('href');
+		$link=~s,^file://(/([a-z]:/))?,$2,; # convert file URI to absolute path
+		if ($link ne '' ) 
+			{ 
+			if($link=~/^[\/]+:/)
+				{
+				print  "Note: Remote URL $link not validated\n";
+				next; # do not alter children
+				}
+			if(! ($link=~/^\//))
+				{
+				$link= &abspath(File::Basename::dirname($file)."/$link");
+				}
+			if(! -e $link) 
+				{
+				if(! -e &realPath($link)) {
+					print  "Warning: Local metadata file not found: $link\n";
+				}
+				next; # do not alter children
+				}
+			}
+		if($node->getAttribute('rel') eq 'link-mapping')
+			{# need to process this now
+			&rootMapMeta($node);
+			}
+		return;
+		}
+	else {return}
+	my $checkversion=0;
+	foreach my $item (@{$node->getChildNodes})
+		{
+		#print $item->getNodeType,"\n";
+		&walk($file,$item);
+		}
+
+
+
+	}
+
+
+sub realPath
+	{
+	my $link = shift;
+	foreach my $a (keys %unitmap)
+		{
+		if($a eq substr($link,0,length($a))) 
+			{
+			my $trylink = $unitmap{$a}.substr($link,length($a));
+			if(-e $trylink) {return $trylink}
+			}
+		}
+	}
+
+sub combineLink
+	{
+	# combine data from linked sysdef fragment w/ equivalent element in parent document
+	my $node = shift;
+	my $file = shift;
+	my $getfromfile = &localfile($file);
+	$getfromfile eq '' && return;  # already raised warning, no need to repeat
+	my $doc;
+	eval {
+		$doc = $parser->parsefile ($getfromfile);
+	};
+	if(!$doc) {
+		print "ERROR: could not open $getfromfile\n";
+		return;
+	}
+	my $item =&firstElement($doc->getDocumentElement);
+	$item || die "badly formatted $file";	
+	my @upid = &getNamespaceAndValue($node,'id');
+	my @downid = &getNamespaceAndValue($item,'id');
+	(($upid[0] eq $downid[0]) && ($upid[1] eq $downid[1]))  || die "$upid[1] ($upid[0]) differs from $downid[1] ($downid[0]) ";	# make sure the link is valid
+	&walk($getfromfile,$item);
+	}
+
+
+sub copyInto
+	{
+	# make a deep copy the node (2nd arg) into the element (1st arg)
+	my $parent=shift;
+	my $item = shift;
+	my $doc = $parent->getOwnerDocument;
+	my $type = $item->getNodeType;
+	my $new;
+	if($type==1) 
+		{
+		$new = $doc->createElement($item->getTagName);
+		my %down = &atts($item);
+		foreach my $ordered ('id','name','bldFile','mrp','level','levels','introduced','deprecated','filter')
+			{
+			if($down{$ordered})
+				{
+				$new->setAttribute($ordered,$down{$ordered});
+				delete $down{$ordered}
+				}
+			}
+		while(my($a,$b) = each(%down))
+			{
+			$new->setAttribute($a,$b);
+			}
+		foreach my $child (@{$item->getChildNodes})
+			{
+			&copyInto($new,$child);
+			}
+		}
+	elsif($type==3) 
+		{
+		$new = $doc->createTextNode ($item->getData);
+		}
+	elsif($type==8) 
+		{
+		$new = $doc->createComment  ($item->getData);
+		}
+	if($new)
+		{
+		$parent->appendChild($new);
+		}
+	}
+
+
+sub getNamespaceAndValue
+	{
+	my $node = shift;
+	my $attr = shift || 'id';
+	my $id = $node->getAttribute($attr);
+	if($id eq '') {return}
+	my $ns;
+	if($id=~s/^(.*)://)
+		{ # it's got a ns, find out what it is
+		$ns=&getNs($node,$1);
+		}
+	else
+		{
+		$ns = $node->getOwnerDocument->getDocumentElement->getAttribute("id-namespace") ||
+			$defaultns;
+		}
+	return ($ns,$id);;
+	}
+
+sub getNs
+	{
+	# find the namespace URI that applies to the specified prefix.
+	my $node = shift;
+	my $pre = shift;
+	my $uri = $node->getAttribute("xmlns:$pre");
+	if($uri) {return $uri}
+	my $parent = $node->getParentNode;
+	if($parent && $parent->getNodeType==1)
+		{
+		return getNs($parent,$pre);
+		}
+	}
+
+
+
+sub firstElement {
+	# return the first element in this node
+	my $node = shift;
+	foreach my $item (@{$node->getChildNodes}) {
+		if($item->getNodeType==1) {return $item}
+	}
+}
+
+
+sub atts {
+	# return a hash of all attribtues defined for this element
+	my $node = shift;
+	my %at = $node->getAttributes;
+	my %list;
+	foreach my $a (keys %{$node->getAttributes}) 
+		{
+		if($a ne '')
+			{
+			$list{$a} = $node->getAttribute ($a);
+			}
+		}
+	return %list;
+}
+
+
+sub ns 
+	{
+	# return a hash of ns prefix and uri -- the xmlns: part is stripped off
+	my $node = shift;
+	my %list;
+	foreach my $a (keys %{$node->getAttributes}) 
+		{
+		my $pre = $a;
+		if($pre=~s/^xmlns://)
+			{
+			$list{$pre} = $node->getAttribute ($a);
+			}
+		}
+	return %list;
+	}
+
+
+sub resolvePath
+	{
+	# return full path to 2nd arg relative to first (path or absolute URI)
+	my $base = shift;
+	my $path = shift;
+	if($path=~m,^/,) {return $path } # path is absolute, but has no drive. Let OS deal with it.
+	if($path=~s,^file:///([a-zA-Z]:/),$1,) {return $path } # file URI with drive letter
+	if($path=~m,^file://,) {return $path } # file URI with no drive letter (unit-style). Just pass on as is with leading / and let OS deal with it
+	if($path=~m,^[a-z0-9][a-z0-9]+:,i) {return $path } # absolute URI -- no idea how to handle, so just return
+	return &abspath(File::Basename::dirname($base)."/$path");
+	}
+
+
+sub resolveURI
+	{
+	# return full path to 2nd arg relative to first (path or absolute URI)
+	my $base = shift;
+	my $path = shift;
+	if($path=~m,[a-z0-9][a-z0-9]+:,i) {return $path } # absolute URI -- just return
+	if($path=~m,^/,) {return $path } # path is absolute, but has no drive. Let OS deal with it.
+	return &abspath(File::Basename::dirname($base)."/$path");
+	}
+
+sub localfile
+	{
+	my $file = shift;
+	if($file=~s,file:///([a-zA-Z]:/),$1,) {return $file } # file URI with drive letter
+	if($file=~m,file://,) {return $file } # file URI with no drive letter (unit-style). Just pass on as is with leading / and let OS deal with it
+	if($file=~m,^([a-z0-9][a-z0-9]+):,i)
+		{
+		print  "ERROR: $1 scheme not supported\n";
+		return;  # return empty string if not supported.
+		} 
+	return $file
+	}
+
+
+
+	
+
+sub help
+	{
+	my $name= $0; $name=~s,^.*[\\/],,;
+my $text;
+format STDERR =
+ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+  $text,
+     ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<~~
+    $text
+.
+print STDERR "usage: $name  [options...] sysdef\n  valid options are:\n\n";
+	foreach (
+		"-path [sm-path]\tspecifies the full system-model path to the file which is being processed. By default this is  \"/os/deviceplatformrelease/foundation_system/system_model/system_definition.xml\"",
+			"   This must be an absolute path if you're processing a root sysdef.",
+			"   If processing a pkgdef file, you can use \"./package_definition.xml\" to leave all links relative.",
+		"effective-sysdef [local-file]\tspecifies another local filesystem location the sysdef should be considered when resolving linked metas and unit paths, but not system model item hrefs. This is mainly used for testing system-wide changes to pkgdefs since it allows the pkgdefs to exist in a separate location to the rest of the codeline"
+		) {
+		$text = $_;
+		write STDERR;
+		print STDERR "\n";
+	}
+
+	exit(1);
+	}
+
+
+	
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metatools/sysdeftools/docs/readme.txt	Wed Jul 28 13:20:46 2010 +0100
@@ -0,0 +1,64 @@
+# Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "Eclipse Public License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+#
+# Initial Contributors:
+# Nokia Corporation - initial contribution.
+# Contributors:
+# Description:
+
+Run any .bat or .pl file with no arguments to get syntax and command line options.
+
+*Directory structure*
+
+Main directory contains XLST and Perl scripts and the .bat files that call them
+docs contains this file
+lib contains common XSLT modules
+xalanj contains an implementation of Xalan-J, an XSLT processor implemented in Java
+
+
+*The tools*
+
+Filtering tools: 
+filtering.xsl - Filter a sysdef in the 2.0 or 3.0 syntax
+filtering.bat - Call filtering.xsl using xalan-j
+
+Joining tools: 
+joinsysdef.pl - Create a stand-alone sysdef from a linked set of fragments. Supports confguring via an .hrh file. By default this also embeds any linked metadata.
+joinsysdef.bat - Call joinsysdef.pl
+joinsysdef.xsl - Create a stand-alone sysdef from a linked set of fragments
+joinandparesysdef.xsl - Create a stand-alone sysdef from a linked set of fragments, paring down to just a set of items of the desired rank.
+
+Merging tools: 
+mergesysdef.xsl - Merge two 3.x syntax stand-alone system definitions. It can process two standalone sysdefs or two sysdef fragments which describe the same system model item.
+mergesysdef.bat - Call mergesysdef.xsl using xalan-j
+
+Other tools:
+sysdefdowngrade.xsl - Convert a 3.0.x sysdef to 2.0.1 sytnax
+sysdefdowngrade.bat - Call sysdefdowngrade.xsl using xalan-j
+rootsysdef.pl - Generate a root system definition from a template root sysdef and a set of wildcard paths to look for pkgdef files
+rootsysdef.bat - Call rootsysdef.pl
+
+Validation tools:
+checklinks.pl - Checks that all referenced files in a system definition exist at the specified locations. If there are any linked system definition fragments, it will recursively check them as well.
+checklinks.bat - call checklinks.pl
+validate-sysdef.xsl - Validate a sysdef file, reporting any errors as plain text
+validate-sysdef.bat - Call validate-sysdef.xsl using xalan-j
+
+Modules (in lib):
+filter-module.xsl - XSLT module which contains the logic to process the filter attribute in the system definition
+joinsysdef-module.xsl - XSLT module which contains the logic to join a system definition file
+mergesysdef-module.xsl - XSLT module for merging only two sysdef files according to the 3.0.0 rules
+test-model.xsl - XSLT module for validating sysdef files
+modelcheck.xsl - Validates a sysdef file, reporting any errors in HTM format. Can validate a sysdef in a web browser by using <?xml-stylesheet type="text/xsl" href="modelcheck.xsl"?>
+
+
+XSLT Processing (in xalanj):
+xalan.jar
+xercesImpl.jar
+xml-apis.jar
+serializer.jar
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metatools/sysdeftools/filtering.bat	Wed Jul 28 13:20:46 2010 +0100
@@ -0,0 +1,21 @@
+@rem Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+@rem All rights reserved.
+@rem This component and the accompanying materials are made available
+@rem under the terms of the License "Eclipse Public License v1.0"
+@rem which accompanies this distribution, and is available
+@rem at the URL "http://www.eclipse.org/legal/epl-v10.html".
+@rem
+@rem Initial Contributors:
+@rem Nokia Corporation - initial contribution.
+@rem
+@rem Contributors:
+@rem
+@rem Description: 
+@rem
+@setlocal
+@if .%1==. goto use
+@ java -jar %~dp0xalanj\xalan.jar -xsl %~dpn0.xsl %* 
+@goto end
+:use
+@ java -jar %~dp0xalanj\xalan.jar -in %~dpn0.xsl -xsl %~dp0lib\usage.xsl -param usage "%~n0"
+:end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metatools/sysdeftools/filtering.xsl	Wed Jul 28 13:20:46 2010 +0100
@@ -0,0 +1,293 @@
+<?xml version="1.0"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common"  exclude-result-prefixes="exslt">
+<!--Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+	All rights reserved.
+	This component and the accompanying materials are made available
+	under the terms of the License "Eclipse Public License v1.0"
+	which accompanies this distribution, and is available
+	at the URL "http://www.eclipse.org/legal/epl-v10.html".
+
+	Initial Contributors:
+	Nokia Corporation - initial contribution.
+	Contributors:
+	Description:
+	Filter a sysdef in the 2.0 or 3.0 syntax
+	The functionality of these filters is not supported outside of this tool. 
+	The filtering concepts here may not be carried forward in future system definition processing tools
+-->
+<!--Description:This filters a sysdef in either the 2.0 or 3.0 syntax
+-->
+
+<!--Input:<sysdef> - (required) The system definition XML file to process. Can be in the 2.0 or 3.0 format, and can be a fragment or stand-alone.-->
+<!--Output:<sysdef> - (optional) The system definition XML file to save the output as. If not present it will write to stdout.-->
+
+
+
+<xsl:output method="xml" indent="yes"/>
+
+<xsl:param name="filter-type">only</xsl:param>
+<!-- <type> - The method of filtering. Legal values are:
+		"only" = every component/unit can only have zero or more of these specified filters. ie, it can only have filters from this list, no other filters are allowed. This covers the common use case of "I want anything with gt and or techview, but no other filters" that was the first step in all old symbian.com builds. 
+
+		"has" =  every component/unit must have all of these filters. ie it can have any other filters, but all specified filters must all be present. This covers the case where filter="test" identifies tests and there is no special filter to identify things that are not tests. So a filter for "!test" will strip out anything with filter="test" (plus any other filters) for a production build, and a filter of "test" will strip out everything that does not have filter="test" (plus any other filters) for a test build. Opposite filters will generate sets that are exactly opposite to each other.
+
+		"with" =  components/units that have the opposite filter are removed. This covers the old symbian.com case of java, !java and "don't care" components. In other words we have a global feature that every item can be built only when the feature is set, only when the feature is not set, or it does not care and will always be built. So for a !java build only items containing filter="java" are stripped out. For a java build, only items with filter="!java" are stripped out. Anything which does not explicitly mention java are always unaffected. Opposite filters will generate sets which overlap.
+-->
+
+
+<xsl:param name="filter"/> <!-- <list> - (required) A comma-separated list of filters used to process the sysdef.-->
+
+<xsl:param name="addbuild" select="0"/> <!--1 - (optional) If present, it will add a system build section that accepts everything. This is needed for genxml processing -->
+
+<xsl:template match="node()|@*"><xsl:copy-of select="."/></xsl:template>
+<xsl:template match="*"><xsl:param name="data"/>
+	<xsl:copy>
+		<xsl:copy-of select="@*"/>
+		<xsl:apply-templates select="node()">
+			<xsl:with-param name="data" select="$data"/>
+		</xsl:apply-templates>
+	</xsl:copy>
+</xsl:template>
+
+<xsl:template match="component|unit"><xsl:param name="data"/> <!-- filterable items -->
+	 <xsl:variable name="display">
+	 	<xsl:apply-templates select="$data" mode="filter">
+			<xsl:with-param name="item" select="current()"/>
+		</xsl:apply-templates>
+	 </xsl:variable>
+	 
+	 <xsl:if test="$display != 'hide' "> <!-- if hide, remove completely from the output-->
+		<xsl:copy>
+			<xsl:copy-of select="@*"/>
+			<xsl:apply-templates select="node()">
+				<xsl:with-param name="data" select="$data"/>
+			</xsl:apply-templates>
+		</xsl:copy>
+	</xsl:if>
+</xsl:template>
+
+<xsl:template match="/SystemDefinition">
+	<xsl:variable name="f">
+		<xsl:element name="filter-{$filter-type}">
+			<xsl:call-template name="filter-list">
+				<xsl:with-param name="f" select="$filter"/>
+			</xsl:call-template>
+		</xsl:element>
+	</xsl:variable>
+	<xsl:choose>
+		<xsl:when test="starts-with(@schema,'3.0')"/> <!-- no DTD needed for 3.0 sysdef -->
+		<xsl:when test="$addbuild">
+			<xsl:call-template name="DTD-bld"/> <!-- insert 2.0.1 DTD w/sysbuild parts-->
+		</xsl:when>
+		<xsl:otherwise>
+			<xsl:call-template name="DTD"/> <!-- insert 2.0.1 DTD -->
+		</xsl:otherwise>
+	</xsl:choose>
+	<xsl:copy>
+		<xsl:copy-of select="@*"/>
+		<xsl:variable name="content"> <!-- save content for potential further processing -->
+			<xsl:apply-templates select="node()">
+				<xsl:with-param name="data" select="exslt:node-set($f)/*"/>
+			</xsl:apply-templates>
+		</xsl:variable>
+		<!-- just output content as is. We could create a template to remove any filtered out items, but so far there's no compelling need -->
+		<xsl:copy-of select="$content"/>  
+
+		<xsl:if test="$addbuild">
+			<SystemBuild schema="1.0.0">
+				<configuration name="any" description="text">
+					<xsl:attribute name="filter">
+						<xsl:for-each select="//@filter[not(.=following::*/@filter)]">
+							<xsl:value-of select="."/><xsl:if test="position()!=last()">,</xsl:if>
+						</xsl:for-each>
+					</xsl:attribute>
+					<xsl:for-each select="exslt:node-set($content)/systemModel/layer[descendant::unit]">
+						<!-- only include layers we know have units -->
+						<ref item="{@name}"/>
+					</xsl:for-each>
+				</configuration>
+			</SystemBuild>
+		</xsl:if>
+	</xsl:copy>
+</xsl:template>
+
+
+<xsl:include href="lib/filter-module.xsl"/>
+
+<xsl:template name="DTD-bld">
+<xsl:text disable-output-escaping="yes"><![CDATA[<!DOCTYPE SystemDefinition [
+ <!ELEMENT SystemDefinition ( systemModel?, SystemBuild? )>
+ <!ATTLIST SystemDefinition
+  name CDATA #REQUIRED
+  schema CDATA #REQUIRED>
+ <!ELEMENT systemModel (layer+)>
+ <!ELEMENT layer (block* | collection*)*>
+ <!ATTLIST layer
+  name CDATA #REQUIRED
+  long-name CDATA #IMPLIED
+  levels NMTOKENS #IMPLIED
+  span CDATA #IMPLIED>
+ <!ELEMENT block (subblock* | collection*)*>
+ <!ATTLIST block
+  levels NMTOKENS #IMPLIED
+  span CDATA #IMPLIED
+  level NMTOKEN #IMPLIED
+  name CDATA #REQUIRED
+  long-name CDATA #IMPLIED>
+ <!ELEMENT subblock (collection)*>
+ <!ATTLIST subblock
+  name CDATA #REQUIRED
+  long-name CDATA #IMPLIED>
+ <!ELEMENT collection (component)*>
+ <!ATTLIST collection
+  name CDATA #REQUIRED
+  long-name CDATA #IMPLIED
+  level NMTOKEN #IMPLIED>
+ <!ELEMENT component (unit)*>
+ <!ATTLIST component
+  name CDATA #REQUIRED
+  long-name CDATA #IMPLIED
+  deprecated CDATA #IMPLIED
+  introduced CDATA #IMPLIED
+  contract CDATA #IMPLIED
+  plugin (Y|N) "N"
+  filter CDATA #IMPLIED
+  class NMTOKENS #IMPLIED
+  supports CDATA #IMPLIED
+  purpose ( optional | mandatory | development ) "optional">
+ <!ELEMENT unit EMPTY>
+ <!ATTLIST unit
+  mrp CDATA #IMPLIED
+  filter CDATA #IMPLIED
+  bldFile CDATA #IMPLIED
+  root CDATA #IMPLIED
+  version NMTOKEN #IMPLIED
+  prebuilt NMTOKEN #IMPLIED
+  late (Y|N) #IMPLIED
+  priority CDATA #IMPLIED>
+ <!ELEMENT SystemBuild (option* | target+ | targetList+ | list+ | configuration+)*>
+ <!ATTLIST SystemBuild schema CDATA #REQUIRED>
+ <!ELEMENT list (ref+)>
+ <!ATTLIST list
+  name ID #REQUIRED
+  description CDATA #REQUIRED>
+ <!ELEMENT ref EMPTY>
+ <!ATTLIST ref item CDATA #REQUIRED>
+ <!ELEMENT targetList EMPTY>
+ <!ATTLIST targetList
+  name ID #REQUIRED
+  description CDATA #REQUIRED
+  target IDREFS #REQUIRED>
+ <!ELEMENT target EMPTY>
+ <!ATTLIST target
+  name ID #REQUIRED
+  abldTarget CDATA #REQUIRED
+  description CDATA #REQUIRED>
+ <!ELEMENT option EMPTY>
+ <!ATTLIST option
+  name ID #REQUIRED
+  abldOption CDATA #REQUIRED
+  description CDATA #REQUIRED
+  enable (Y | N ) #REQUIRED>
+ <!ELEMENT configuration (listRef+ | ref+ | task+)*>
+ <!ATTLIST configuration
+  name ID #REQUIRED
+  description CDATA #REQUIRED
+  filter CDATA #REQUIRED>
+ <!ELEMENT task (listRef* , (buildLayer | specialInstructions))>
+ <!ELEMENT listRef EMPTY>
+ <!ATTLIST listRef list CDATA #REQUIRED>
+ <!ELEMENT buildLayer EMPTY>
+ <!ATTLIST buildLayer
+  command CDATA #REQUIRED
+  targetList IDREFS #IMPLIED
+  unitParallel (Y | N ) #REQUIRED
+  targetParallel (Y | N ) "N">
+ <!ELEMENT specialInstructions EMPTY>
+ <!ATTLIST specialInstructions
+  name CDATA #REQUIRED
+  cwd CDATA #REQUIRED
+  root CDATA #IMPLIED
+  command CDATA #REQUIRED>
+]>
+]]></xsl:text>
+</xsl:template>
+
+<xsl:template name="DTD">
+<xsl:text disable-output-escaping="yes"><![CDATA[<!DOCTYPE SystemDefinition [
+<!ELEMENT SystemDefinition ( systemModel )>
+<!ATTLIST SystemDefinition
+  name CDATA #REQUIRED
+  schema CDATA #REQUIRED
+>
+<!-- all paths are relative to the environment variable specified by the root attribute, or SOURCEROOT if not.  -->
+
+<!-- System Model Section of DTD -->
+<!ELEMENT systemModel (layer+)>
+
+<!ELEMENT layer (block* | collection*)*>
+<!-- Kernel Services, Base Services, OS Services, Etc -->
+<!ATTLIST layer
+  name CDATA #REQUIRED
+  long-name CDATA #IMPLIED
+  levels NMTOKENS #IMPLIED
+  span CDATA #IMPLIED
+>
+
+<!ELEMENT block (subblock* | collection*)*>
+ <!-- Generic OS services, Comms Services, etc -->
+<!ATTLIST block
+  levels NMTOKENS #IMPLIED
+  span CDATA #IMPLIED
+  level NMTOKEN #IMPLIED
+  name CDATA #REQUIRED
+  long-name CDATA #IMPLIED
+>
+
+<!ELEMENT subblock (collection)*>
+<!-- Cellular Baseband Services, Networking Services, etc -->
+<!ATTLIST subblock
+  name CDATA #REQUIRED
+  long-name CDATA #IMPLIED
+>
+
+<!ELEMENT collection (component)*>
+<!-- Screen Driver, Content Handling, etc -->
+<!ATTLIST collection
+  name CDATA #REQUIRED
+  long-name CDATA #IMPLIED
+  level NMTOKEN #IMPLIED
+>
+
+<!ELEMENT component (unit)*>
+<!-- contains units or is a  package or prebuilt -->
+<!ATTLIST component
+  name CDATA #REQUIRED
+  long-name CDATA #IMPLIED
+  deprecated CDATA #IMPLIED
+  introduced CDATA #IMPLIED
+  contract CDATA #IMPLIED
+  plugin (Y|N) "N"
+  filter CDATA #IMPLIED
+  class NMTOKENS #IMPLIED
+  supports CDATA #IMPLIED
+  purpose ( optional | mandatory | development ) "optional"
+>
+
+<!ELEMENT unit EMPTY >
+<!-- must be buildable (bld.inf) -->
+<!-- bldFile  may someday be removed in favour of mrp -->
+<!ATTLIST unit
+  mrp CDATA #IMPLIED
+  filter CDATA #IMPLIED
+  bldFile CDATA #IMPLIED
+  root CDATA #IMPLIED
+  version NMTOKEN #IMPLIED
+  prebuilt NMTOKEN #IMPLIED
+  late (Y|N) #IMPLIED
+  priority CDATA #IMPLIED
+>
+]>
+]]></xsl:text>
+</xsl:template>
+</xsl:stylesheet>	
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metatools/sysdeftools/group/bld.inf	Wed Jul 28 13:20:46 2010 +0100
@@ -0,0 +1,79 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+PRJ_PLATFORMS
+TOOLS2
+
+/**
+@file
+
+@SYMPurpose Tool for manipulating and verifying system definition files
+*/
+
+PRJ_EXPORTS
+
+//  raw scripts 
+
+../checklinks.pl		/epoc32/tools/build/checklinks.pl
+../filtering.xsl		/epoc32/tools/build/filtering.xsl
+../joinandparesysdef.xsl		/epoc32/tools/build/joinandparesysdef.xsl
+../joinsysdef.pl		/epoc32/tools/build/joinsysdef.pl
+../joinsysdef.xsl		/epoc32/tools/build/joinsysdef.xsl
+../mergesysdef.xsl		/epoc32/tools/build/mergesysdef.xsl
+../rootsysdef.pl		/epoc32/tools/build/rootsysdef.pl
+../sysdefdowngrade.xsl		/epoc32/tools/build/sysdefdowngrade.xsl
+../validate-sysdef.xsl		/epoc32/tools/build/validate-sysdef.xsl
+
+
+//  reusable modules and internal utilities 
+
+../lib/filter-module.xsl		/epoc32/tools/build/lib/filter-module.xsl
+../lib/joinsysdef-module.xsl		/epoc32/tools/build/lib/joinsysdef-module.xsl
+../lib/mergesysdef-module.xsl		/epoc32/tools/build/lib/mergesysdef-module.xsl
+../lib/modelcheck.xsl		/epoc32/tools/build/lib/modelcheck.xsl
+../lib/path-module.xsl		/epoc32/tools/build/lib/path-module.xsl
+../lib/test-model.xsl		/epoc32/tools/build/lib/test-model.xsl
+../lib/usage.xsl		/epoc32/tools/build/lib/usage.xsl
+
+//  Xalan jar files 
+../xalanj/serializer.jar		/epoc32/tools/build/xalanj/serializer.jar
+../xalanj/xalan.jar		/epoc32/tools/build/xalanj/xalan.jar
+../xalanj/xercesImpl.jar		/epoc32/tools/build/xalanj/xercesImpl.jar
+../xalanj/xml-apis.jar		/epoc32/tools/build/xalanj/xml-apis.jar
+
+
+
+
+// Perl-calling .bat files (identical, can export from any single one of these).
+../checklinks.bat		/epoc32/tools/build/checklinks.bat
+../joinsysdef.bat		/epoc32/tools/build/joinsysdef.bat
+../rootsysdef.bat		/epoc32/tools/build/rootsysdef.bat
+
+// Xalan-calling .bat/unix files (identical, can export from single file)
+../joinandparesysdef.bat		/epoc32/tools/build/joinandparesysdef.bat
+../filtering.bat		/epoc32/tools/build/filtering.bat
+../validate-sysdef.bat		/epoc32/tools/build/validate-sysdef.bat
+unixxslcmd 		/epoc32/tools/build/joinandparesysdef
+unixxslcmd 		/epoc32/tools/build/filtering
+unixxslcmd 		/epoc32/tools/build/validate-sysdef
+
+// Xalan-calling .bat/unix files that use XSLTC (identical, can export from single file)
+../mergesysdef.bat		/epoc32/tools/build/mergesysdef.bat
+../sysdefdowngrade.bat		/epoc32/tools/build/sysdefdowngrade.bat
+unixxsltccmd		/epoc32/tools/build/mergesysdef
+unixxsltccmd		/epoc32/tools/build/sysdefdowngrade
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metatools/sysdeftools/group/unixxslcmd	Wed Jul 28 13:20:46 2010 +0100
@@ -0,0 +1,24 @@
+#!/bin/bash
+#
+# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "Eclipse Public License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+#
+# Contributors:
+# Nokia Corporation - initial contribution.
+#
+# Description:
+#  XSLT wrapper for Unix
+
+BASEDIR=`dirname $0`
+
+if [ $# != 0 ]
+then
+    exec java -jar $BASEDIR/xalanj/xalan.jar -xsl $0.xsl $@
+fi
+
+java -jar $BASEDIR/xalanj/xalan.jar -xsl $BASEDIR/lib/usage.xsl -in $0.xsl -param usage $0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metatools/sysdeftools/group/unixxsltccmd	Wed Jul 28 13:20:46 2010 +0100
@@ -0,0 +1,24 @@
+#!/bin/bash
+#
+# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "Eclipse Public License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+#
+# Contributors:
+# Nokia Corporation - initial contribution.
+#
+# Description:
+#  XSLT wrapper for Unix
+
+BASEDIR=`dirname $0`
+
+if [ $# != 0 ]
+then
+    exec java -jar $BASEDIR/xalanj/xalan.jar -xsl $0.xsl -XSLTC $@
+fi
+
+java -jar $BASEDIR/xalanj/xalan.jar -xsl $BASEDIR/lib/usage.xsl -in $0.xsl -param usage $0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metatools/sysdeftools/joinandparesysdef.bat	Wed Jul 28 13:20:46 2010 +0100
@@ -0,0 +1,21 @@
+@rem Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+@rem All rights reserved.
+@rem This component and the accompanying materials are made available
+@rem under the terms of the License "Eclipse Public License v1.0"
+@rem which accompanies this distribution, and is available
+@rem at the URL "http://www.eclipse.org/legal/epl-v10.html".
+@rem
+@rem Initial Contributors:
+@rem Nokia Corporation - initial contribution.
+@rem
+@rem Contributors:
+@rem
+@rem Description: 
+@rem
+@setlocal
+@if .%1==. goto use
+@ java -jar %~dp0xalanj\xalan.jar -xsl %~dpn0.xsl %* 
+@goto end
+:use
+@ java -jar %~dp0xalanj\xalan.jar -in %~dpn0.xsl -xsl %~dp0lib\usage.xsl -param usage "%~n0"
+:end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metatools/sysdeftools/joinandparesysdef.xsl	Wed Jul 28 13:20:46 2010 +0100
@@ -0,0 +1,49 @@
+<?xml version="1.0"?>
+ <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<!--Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+	All rights reserved.
+	This component and the accompanying materials are made available
+	under the terms of the License "Eclipse Public License v1.0"
+	which accompanies this distribution, and is available
+	at the URL "http://www.eclipse.org/legal/epl-v10.html".
+
+	Initial Contributors:
+	Nokia Corporation - initial contribution.
+	Contributors:
+	Description:
+	Create a stand-alone sysdef from a linked set of fragments, paring down to just a set of items of the desired rank.
+-->
+ 	<xsl:output method="xml" indent="yes"/>
+
+<!--Description:This pares the generated sysdef down to just a set of items of the desired
+rank. In other words, you provide a list of IDs to keep and a system model
+rank (layer, package, collection, component). 
+Every item of that rank in the sysdef will be removed except those in the list
+of IDs.
+Primary use cases of this would be to extract a single layer, or to select a
+specific set of packages.
+
+-->
+<xsl:param name="pare"/>		
+	<!--<list> - (required) A comma-separated list of IDs in the literal from as the document they appear in (ie same namespace prefix) -->
+
+<xsl:param name="rank">package</xsl:param>
+	<!--<rank> = the rank item to pare down. This will remove any item of that rank EXCEPT those in $pare -->
+
+<xsl:variable name="pare-list" select="concat(',',translate(normalize-space($pare),' ',','),',')"/> <!-- accept spaces in pare. Pad with commas to make computing easier -->
+
+<xsl:include href="joinsysdef.xsl"/>  
+
+<xsl:template match="/SystemDefinition[systemModel]">
+	<xsl:apply-templates select="." mode="join">
+		<xsl:with-param name="filename" select="$path"/>
+		<xsl:with-param name="data" select="current()"/> <!-- just has to be non-empty -->
+	</xsl:apply-templates>
+</xsl:template>
+
+<xsl:template match="*" mode="filter"> <!-- use this to strip out the unwanted items -->
+	<xsl:param name="item" />
+	<xsl:if test="$rank=name($item) and not(contains($pare-list,concat(',',$item/@id,',')))">hide</xsl:if>
+</xsl:template>
+
+</xsl:stylesheet>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metatools/sysdeftools/joinsysdef.bat	Wed Jul 28 13:20:46 2010 +0100
@@ -0,0 +1,17 @@
+@rem Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+@rem All rights reserved.
+@rem This component and the accompanying materials are made available
+@rem under the terms of the License "Eclipse Public License v1.0"
+@rem which accompanies this distribution, and is available
+@rem at the URL "http://www.eclipse.org/legal/epl-v10.html".
+@rem
+@rem Initial Contributors:
+@rem Nokia Corporation - initial contribution.
+@rem
+@rem Contributors:
+@rem
+@rem Description: 
+@rem
+@setlocal
+@perl %~dpn0.pl %*
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metatools/sysdeftools/joinsysdef.pl	Wed Jul 28 13:20:46 2010 +0100
@@ -0,0 +1,850 @@
+# Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "Eclipse Public License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+#
+# Initial Contributors:
+# Nokia Corporation - initial contribution.
+#
+# Contributors:
+#
+# Description:
+#
+#!/usr/bin/perl
+
+use strict;
+
+
+use FindBin;		# for FindBin::Bin
+use lib $FindBin::Bin;
+use lib "$FindBin::Bin/lib";
+
+use Cwd;
+use Cwd 'abs_path';
+use Getopt::Long;
+use File::Basename;
+use File::Spec;
+use XML::DOM;
+
+my $output;
+my $path;
+my @config;
+my @includes;
+my %defineParams;
+my %defines;
+my $defaultns = 'http://www.symbian.org/system-definition';	# needed if no DTD
+my @excludeMetaList;
+my @cannotExclude= ('link-mapping', 'config');
+my %ID;	# list of all IDs
+
+my @newarg;
+foreach my $a (@ARGV)
+	{ #extract all -I parameters from the parameter list 
+	if($a=~s/^-I//)
+		{
+		push(@includes,$a);
+		}
+	else
+		{
+		push(@newarg,$a);
+		}
+	}
+@ARGV=@newarg;
+
+# need to add options for controlling which metas are filtered out and which are included inline
+GetOptions
+	(
+	 'path=s' => \$path,
+	'output=s' => \$output,
+	'config=s' => \@config,
+	'exclude-meta=s' => \@excludeMetaList
+	);
+
+# -path specifies the full system-model path to the file which is being processed. 
+#	This must be an absolute path if you're processing a root sysdef.
+#	If processing a pkgdef file, you can use "./package_definition.xml" to leave all links relative. Though I can't really see the use case for this.
+
+# -output specifies the file to save the output to. If not specified this will write to stdout
+
+# -config specifies the name of an .hrh file in which the configuration data is acquired from. If not set, no confguration will be done.
+
+# -I[path] specifies the include paths to use when resolving #includes in the .hrh file. Same syntax as cpp command uses. Any number of these can be provided.
+
+
+# if config is not set, no confguration will be done.
+# If it is set, all configuration metadata will be processed and stripped from the output, even if the confguration data is empty
+
+ if($path eq '') {$path = '/os/deviceplatformrelease/foundation_system/system_model/system_definition.xml'}
+
+($#ARGV == -1 ) && &help();
+my $sysdef = &abspath(shift);	# resolve the location of the root sysdef
+
+
+my %excludeMeta;
+foreach (@excludeMetaList) {$excludeMeta{$_}=1}	# make list a hash table
+foreach (@cannotExclude)
+	{
+	$excludeMeta{$_} && print STDERR "Error: Cannot exclude meta rel=\"$_\"\n";
+	$excludeMeta{$_}=0
+	}	# cannot exclude any of these rel types
+
+
+# rootmap is a mapping from the filesystem to the paths in the doc
+my %rootmap = &rootMap($path,$sysdef);	
+my %nsmap;
+my %urimap;
+
+foreach my $conf (@config) 
+	{ # run cpp to get all #defines
+	&getDefines($conf);
+	}
+
+my $parser = new XML::DOM::Parser;
+my   $sysdefdoc = $parser->parsefile ($sysdef);
+
+
+my $maxschema = $sysdefdoc->getDocumentElement()->getAttribute('schema');	# don't check value, just store it.
+
+
+# find all the namespaces used in all trhe fragments and use that 
+# to set the namespaces ni the root element of the created doc
+#   should be able to optimise by only parsing each doc once and 
+#	maybe skipping the contends of <meta>
+my @nslist = &namespaces($sysdef,$sysdefdoc->getDocumentElement());
+
+
+while(@nslist)
+	{
+	my $uri = shift(@nslist);
+	my $prefix =shift(@nslist);
+	if($prefix eq 'id namespace'){$prefix=''}
+	if(defined $urimap{$uri}) {next} # already done this uri
+	$urimap{$uri} = $prefix;
+	if($nsmap{$prefix})
+		{ # need a new prefix for this, guess from the URI (for readability)
+		if($uri=~/http:\/\/(www\.)?([^.\/]+)\./) {$prefix = $2}
+		my $i=0;
+		while($nsmap{$prefix})
+			{ # still no prefix, just make up 
+			$prefix="ns$i";
+			$i++;
+			# next line not really necessary, but it's a good safety to stop infinite loops
+			$i eq 1000 && die "cannot create namespace prefix for $uri";
+			}
+		}
+	$nsmap{$prefix}=$uri;
+	}
+
+my $docroot =  $sysdefdoc->getDocumentElement;
+
+my $ns = $docroot->getAttribute('id-namespace');
+if(!$ns && $nsmap{''})
+	{
+	$docroot->setAttribute('id-namespace',$nsmap{''});
+	}
+
+$docroot->setAttribute('schema',$maxschema);	# output has the largest syntax version of all includes
+
+
+while(my($pre,$uri) = each(%nsmap))
+	{
+	$pre ne '' || next ;
+	$docroot->setAttribute("xmlns:$pre",$uri);
+	}
+
+&walk($sysdef,$docroot);	# process the XML
+
+
+# print to file or stdout
+if($output eq '') 
+	{
+	print $sysdefdoc->toString;
+	}
+else
+	{
+	$sysdefdoc->printToFile($output);
+	}
+
+ 
+sub abspath
+	{ 	# normalize the path into an absolute one
+	my  ($name,$path) = fileparse($_[0]);
+	$path=~tr,\\,/,;
+	if( -e $path)
+		{
+		return abs_path($path)."/$name";
+		}
+	my @dir = split('/',$_[0]);
+	my @new;
+	foreach my $d (@dir)
+		{
+		if($d eq '.') {next}
+		if($d eq '..')
+			{
+			pop(@new);
+			next;
+			}
+		push(@new,$d)
+		}
+	return join('/',@new);
+	}
+
+sub rootMap {
+	my @pathdirs = split(/\//,$_[0]);
+	my @rootdirs = split(/\//,$_[1]);
+
+	while(lc($rootdirs[$#rootdirs])  eq lc($pathdirs[$#pathdirs])  )
+		{
+		pop(@rootdirs);
+		pop(@pathdirs);
+		}
+	return (join('/',@rootdirs)  => join('/',@pathdirs) );
+	}
+
+sub rootMapMeta {
+	# find all the explict path mapping from the link-mapping metadata
+	my $node = shift;
+	foreach my $child (@{$node->getChildNodes})
+			{
+			if ($child->getNodeType==1 && $child->getTagName eq 'map-prefix')
+				{
+				my $from = $child->getAttribute('link');
+				my $to = $child->getAttribute('to');		# optional, but blank if not set
+				$rootmap{$from} = $to;
+				}
+			}
+	# once this is processed we have no more need for it. Remove from output
+	$node->getParentNode->removeChild($node);
+	}
+
+
+sub walk
+	{ 	# walk through the doc, resolving all links
+	my $file = shift;
+	my $node = shift;
+	my $type = $node->getNodeType;
+	if($type!=1) {return}
+	my $tag = $node->getTagName;
+	if($tag=~/^(layer|package|collection|component)$/ )
+		{
+		if($file eq $sysdef)
+			{
+			&fixIDs($node);	# normalise all IDs in the root doc. Child docs are handled elsewhere.
+			}
+		my $link= $node->getAttribute('href');
+		if($link)
+			{
+			my $file = &resolvePath($file,$link); 
+			if(-e $file)
+				{
+				&combineLink($node,$file);
+				}
+			else
+				{
+				print STDERR "Note: $file not found\n";
+				$node->removeAttribute('href');
+				}
+			return;
+			}
+		else 
+			{ # only check for duplicate IDs on the implementation
+			my $id= $node->getAttribute('id');
+			my $p = $node->getParentNode();
+			my $ptext = $p->getTagName()." \"".$p->getAttribute('id')."\"";
+			if(defined $ID{$id})
+				{
+				print STDERR "Error: duplicate ID: $tag \"$id\" in $ptext matches $ID{$id}\n";
+				}
+			else 
+				{
+				my $p = $node->getParentNode();
+				$ID{$id}="$tag in $ptext";
+				}
+			}
+		}
+	elsif($tag=~/^(SystemDefinition|systemModel)$/ )
+		{
+		}
+	elsif($tag eq 'unit')
+		{
+		foreach my $atr ('bldFile','mrp','base','proFile')
+			{
+			my $link= $node->getAttribute($atr);
+			if($link && !($link=~/^\//))
+				{
+				$link= &abspath(File::Basename::dirname($file)."/$link");
+				foreach my $a (keys %rootmap) {
+					$link=~s,^$a,$rootmap{$a},ie;
+				}
+				# remove leading ./  which is used to indicate that paths should remain relative
+				$link=~s,^\./([^/]),$1,; 
+				$node->setAttribute($atr,$link);
+				}
+			}
+		}
+	elsif($tag eq 'meta')
+		{
+		my $rel= $node->getAttribute('rel') || 'Generic';
+		if($excludeMeta{$rel})
+			{
+			$node->getParentNode->removeChild($node);
+			return;
+			}
+		my $link= $node->getAttribute('href');
+		$link=~s,^file://(/([a-z]:/))?,$2,; # convert file URI to absolute path
+		if ($link ne '' ) 
+			{ 
+			if($link=~/^[\/]+:/)
+				{
+				print STDERR "Note: Remote URL $link not embedded\n";
+				next; # do not alter children
+				}
+			if(! ($link=~/^\//))
+				{
+				$link= &abspath(File::Basename::dirname($file)."/$link");
+				}
+			if(! -e $link) 
+				{
+				print STDERR "Warning: Local metadata file not found: $link\n";
+				next; # do not alter children
+				}
+			# if we're here we can just embed the file
+			# no processing logic is done! It's just embedded blindly
+			my $item;
+			eval {
+				my  $metadoc = $parser->parsefile ($link);
+				$item = $metadoc->getDocumentElement;
+			};
+			if(!$item)
+				{
+				print STDERR "Error: Could not process metadata file: $link\n";
+				next; # do not alter children
+				}
+			$node->removeAttribute('href');
+			&blindCopyInto($node,$item);
+			}
+		if($node->getAttribute('rel') eq 'link-mapping')
+			{# need to process this now
+			&rootMapMeta($node);
+			}
+		return;
+		}
+	else {return}
+	my $checkversion=0;
+	foreach my $item (@{$node->getChildNodes})
+		{
+		#print $item->getNodeType,"\n";
+		&walk($file,$item);
+		$checkversion = $checkversion  || ($tag eq 'component' &&  $item->getNodeType==1 && $item->getAttribute('version') ne '');
+		}
+
+	if($checkversion && scalar(@config))
+		{ # need to check the conf metadata on the units in this component
+		&doCmpConfig($node);
+		}
+	foreach my $item (@{$node->getChildNodes})
+		{
+		if ($item->getNodeType==1 && $item->getTagName eq 'meta')
+			{
+			&processMeta($item);
+			}
+		}
+	}
+
+
+sub combineLink
+	{
+	# combine data from linked sysdef fragment w/ equivalent element in parent document
+	my $node = shift;
+	my $file = shift;
+	my $getfromfile = &localfile($file);
+	$getfromfile eq '' && return;  # already raised warning, no need to repeat
+	my  $doc = $parser->parsefile ($getfromfile);
+	my $item =&firstElement($doc->getDocumentElement);
+	$item || die "badly formatted $file";	
+	&fixIDs($item);
+	my %up = &atts($node);
+	my %down = &atts($item);
+	$up{'id'} eq $down{'id'}  || die "$up{id} differs from $down{id}";
+	$node->removeAttribute('href');
+	foreach my $v (keys %up) {delete $down{$v}}
+	foreach my $v (keys %down)
+		{
+		$node->setAttribute($v,$down{$v})
+		}
+	foreach my $child (@{$item->getChildNodes})
+		{
+		&copyInto($node,$child);
+		}
+	&walk($file,$node);
+	}
+
+
+sub blindCopyInto
+	{
+	# make a deep copy the node (2nd arg) into the element (1st arg)
+	my $parent=shift;
+	my $item = shift;
+	my $doc = $parent->getOwnerDocument;
+	my $type = $item->getNodeType;
+	my $new;
+	if($type==1) 
+		{
+		$new = $doc->createElement($item->getTagName);
+		my %down = &atts($item);
+		while(my($a,$b) = each(%down))
+			{
+			$new->setAttribute($a,$b);
+			}
+		foreach my $child (@{$item->getChildNodes})
+			{
+			&blindCopyInto($new,$child);
+			}
+		}
+	elsif($type==3) 
+		{
+		$new = $doc->createTextNode ($item->getData);
+		}
+	elsif($type==8) 
+		{
+		$new = $doc->createComment  ($item->getData);
+		}
+	if($new)
+		{
+		$parent->appendChild($new);
+		}
+	}
+
+sub copyInto
+	{
+	# make a deep copy the node (2nd arg) into the element (1st arg)
+	my $parent=shift;
+	my $item = shift;
+	my $doc = $parent->getOwnerDocument;
+	my $type = $item->getNodeType;
+	my $new;
+	if($type==1) 
+		{
+		&fixIDs($item);
+		$new = $doc->createElement($item->getTagName);
+		my %down = &atts($item);
+		foreach my $ordered ('id','name','bldFile','mrp','level','levels','introduced','deprecated','filter')
+			{
+			if($down{$ordered})
+				{
+				$new->setAttribute($ordered,$down{$ordered});
+				delete $down{$ordered}
+				}
+			}
+		while(my($a,$b) = each(%down))
+			{
+			$new->setAttribute($a,$b);
+			}
+		foreach my $child (@{$item->getChildNodes})
+			{
+			&copyInto($new,$child);
+			}
+		}
+	elsif($type==3) 
+		{
+		$new = $doc->createTextNode ($item->getData);
+		}
+	elsif($type==8) 
+		{
+		$new = $doc->createComment  ($item->getData);
+		}
+	if($new)
+		{
+		$parent->appendChild($new);
+		}
+	}
+
+sub getNs
+	{
+	# find the namespace URI that applies to the specified prefix.
+	my $node = shift;
+	my $pre = shift;
+	my $uri = $node->getAttribute("xmlns:$pre");
+	if($uri) {return $uri}
+	my $parent = $node->getParentNode;
+	if($parent && $parent->getNodeType==1)
+		{
+		return getNs($parent,$pre);
+		}
+	}
+
+
+sub fixIDs
+	{
+	# translate the ID to use the root doc's namespaces 
+	my $node = shift;
+	foreach my $id ('id','before')
+		{
+		&fixID($node,$id);
+		}
+}
+
+sub fixID
+	{
+	# translate the ID to use the root doc's namespaces 
+	my $node = shift;
+	my $attr = shift || 'id';
+	my $id = $node->getAttribute($attr);
+	if($id eq '') {return}
+	my $ns;
+	if($id=~s/^(.*)://)
+		{ # it's got a ns, find out what it is
+		my $pre = $1;
+		$ns=&getNs($node,$pre);
+		}
+	else
+		{
+		$ns = $node->getOwnerDocument->getDocumentElement->getAttribute("id-namespace") ||
+			$defaultns;
+		}
+	$ns = $urimap{$ns};
+	$id = ($ns eq '') ? $id : "$ns:$id";
+	return $node->setAttribute($attr,$id);
+}
+
+sub firstElement {
+	# return the first element in this node
+	my $node = shift;
+	foreach my $item (@{$node->getChildNodes}) {
+		if($item->getNodeType==1) {return $item}
+	}
+}
+
+
+sub atts {
+	# return a hash of all attribtues defined for this element
+	my $node = shift;
+	my %at = $node->getAttributes;
+	my %list;
+	foreach my $a (keys %{$node->getAttributes}) 
+		{
+		if($a ne '')
+			{
+			$list{$a} = $node->getAttribute ($a);
+			}
+		}
+	return %list;
+}
+
+
+sub ns 
+	{
+	# return a hash of ns prefix and uri -- the xmlns: part is stripped off
+	my $node = shift;
+	my %list;
+	foreach my $a (keys %{$node->getAttributes}) 
+		{
+		my $pre = $a;
+		if($pre=~s/^xmlns://)
+			{
+			$list{$pre} = $node->getAttribute ($a);
+			}
+		}
+	return %list;
+	}
+
+
+sub resolvePath
+	{
+	# return full path to 2nd arg relative to first (path or absolute URI)
+	my $base = shift;
+	my $path = shift;
+	if($path=~m,^/,) {return $path } # path is absolute, but has no drive. Let OS deal with it.
+	if($path=~s,^file:///([a-zA-Z]:/),$1,) {return $path } # file URI with drive letter
+	if($path=~m,^file://,) {return $path } # file URI with no drive letter (unit-style). Just pass on as is with leading / and let OS deal with it
+	if($path=~m,^[a-z0-9][a-z0-9]+:,i) {return $path } # absolute URI -- no idea how to handle, so just return
+	return &abspath(File::Basename::dirname($base)."/$path");
+	}
+
+
+sub resolveURI
+	{
+	# return full path to 2nd arg relative to first (path or absolute URI)
+	my $base = shift;
+	my $path = shift;
+	if($path=~m,[a-z0-9][a-z0-9]+:,i) {return $path } # absolute URI -- just return
+	if($path=~m,^/,) {return $path } # path is absolute, but has no drive. Let OS deal with it.
+	return &abspath(File::Basename::dirname($base)."/$path");
+	}
+
+sub localfile
+	{
+	my $file = shift;
+	if($file=~s,file:///([a-zA-Z]:/),$1,) {return $file } # file URI with drive letter
+	if($file=~m,file://,) {return $file } # file URI with no drive letter (unit-style). Just pass on as is with leading / and let OS deal with it
+	if($file=~m,^([a-z0-9][a-z0-9]+):,i)
+		{
+		print STDERR "ERROR: $1 scheme not supported\n";
+		return;  # return empty string if not supported.
+		} 
+	return $file
+	}
+
+sub namespaces
+	{
+	# return a list of namespace URI / prefix pairs, in the order they're defined
+	# these need to be used to define namespaces in the root element
+	my $file = shift;
+	my $node = shift;
+	my $type = $node->getNodeType;
+	if($type!=1) {return}
+	my $tag = $node->getTagName;
+	my @res;
+	my %nslist = &ns($node);
+	while(my($pre,$uri)=each(%nslist))
+		{ # push all namespaces defined here onto the list
+		push(@res,$uri,$pre);
+		}
+	if($tag=~/^(layer|package|collection|component)$/ )
+		{ # these have the potential of linking, so check for that
+		my $link= $node->getAttribute('href');
+		if($link)
+			{
+			$link=&resolvePath($file,$link);
+			if(-e $link)
+				{
+				my  $doc;
+				eval {
+					$doc = $parser->parsefile ($link);
+				};
+				if($doc)
+					{
+					&checkSyntaxVersion($doc->getDocumentElement->getAttribute('schema'));	# ensure we track we highest syntax number
+					my @docns = &namespaces($link,$doc->getDocumentElement);
+					undef $doc;
+					return (@res,@docns);
+					#ignore any children nodes if this is a link
+					}
+				print STDERR "Error: Malformed XML. Could not process $link\n";
+				}
+			# print STDERR "Note: $link not found\n";  -- no need to warm now. Do so later when trying to join
+			}
+		}
+	elsif($tag eq 'SystemDefinition' )
+		{
+		my $default = $node->getAttribute('id-namespace');
+		if($default)
+			{# mangle with a space so it's clear it's not a qname
+			push(@res,$default,'id namespace');
+			}
+		}
+	foreach my $item (@{$node->getChildNodes})
+		{
+		push(@res,&namespaces($file,$item));
+		}
+	return @res;
+	}
+
+sub processMeta
+	{ # acts upon any known <meta> and strips it from the output if it's used
+	my $metanode = shift;
+
+	my $rel = $metanode->getAttribute('rel') || 'Generic';
+	if($rel eq 'config' && scalar(@config))
+		{ # only process if there is something to configure
+		&doconfig($metanode);
+		}
+	else 
+		{
+		# do nothing. Not supported yet
+		}
+	}
+
+sub doCmpConfig
+	{ # configure in or out the units in a component
+	my $cmp = shift;	# the component node
+	my @unversioned;	# list of all units with no version attribute (if more than one, they should all have filters defined)
+	my %versioned;		# hash table of all units with a specified version, it's a fatal error to hav the same verison twice in one component
+	foreach my $item (@{$cmp->getChildNodes})
+		{ # populate %versioned and @unversioned to save processsing later
+		if($item->getNodeType==1 && $item->getTagName eq 'unit')
+			{
+			my $ver = $item->getAttribute('version');
+			if($ver eq '') {push(@unversioned,$item)}
+			else
+				{
+				defined $versioned{$ver}  && die "Cannot have more than one unit with version $ver in the same component ".$cmp->getAttribute('id');
+				$versioned{$ver}=$item;
+				}
+			}
+		}
+	my @picks = &getMetaConfigPick($cmp); # the list, in order, of all <pick> elements that affect this component
+	foreach my $pick (@picks)
+		{
+		my $ver = $pick->getAttribute('version');
+		if(!$versioned{$ver})
+			{
+			print STDERR "ERROR: Reference to invalid unit version $ver in component ",$cmp->getAttribute('id'),". Ignoring.\n";
+			return;
+			}
+		if(&definedMatches($pick))
+			{ # remove all other units;
+			delete $versioned{$ver}; # to avoid removing in loop
+			foreach my $unit (@unversioned, values(%versioned))
+				{
+				$cmp->removeChild($unit);
+				print STDERR "Note: unit ",$unit->getAttribute('version')," in component " ,$cmp->getAttribute('id')," configured out\n";
+				}
+			last; # done. No more processing after first match
+			}
+		else
+			{ # remove this unit and continue
+			$cmp->removeChild($versioned{$ver});
+			print STDERR "Note: unit $ver in component " ,$cmp->getAttribute('id')," configured out\n";
+			delete $versioned{$ver}; # gone, don't process anymore;
+			}
+		}
+	if (scalar(@unversioned, values(%versioned)) > 1)
+		{
+		print STDERR "Warning: component ",$cmp->getAttribute('id')," has more than one unit after configuration\n";
+		}
+	}
+
+	
+sub getMetaConfigPick
+	{	# return an array of all <pick> elements that affect the specified element
+	my $node = shift;
+	my @pick;
+	while($node->getParentNode->getNodeType==1)
+		{
+		foreach my $item (@{$node->getChildNodes})
+			{
+			my @picks;
+			if($item->getNodeType==1 &&  $item->getAttribute('rel') eq 'config') 
+				{ # it's conf metadata
+				foreach my $p (@{$item->getChildNodes})
+					{
+					if($p->getNodeType==1 &&  $p->getTagName eq 'pick') {push(@picks,$p)}
+					}
+				}
+			@pick=(@picks,@pick); # prepend this to the start;
+			}
+		$node=$node->getParentNode;
+		}
+	return @pick;
+	}
+
+sub definedMatches
+	{ # process all <defined> and <not-defined> the specified element and return true or false if the combination matches
+	my $node  = shift;
+	my $match = 1;
+	foreach my $def (@{$node->getChildNodes})
+		{
+		if($def->getNodeType == 1) 
+			{
+			my $tag = $def->getTagName;
+			if($tag eq 'defined' or $tag eq 'not-defined')
+				{
+				my $var = $def->getAttribute('condition') || die "Must have condition set on all $tag elements";
+				$defineParams{$var} && die "Cannot use a macro with parameters as a feature flag: $var(".$defineParams{$var}->[0].")"; 
+				$match = $match &&  (($tag eq 'defined') ? defined($defines{$var}) : ! defined($defines{$var}));
+				}
+			}
+		}
+		return $match;
+	}
+
+sub doconfig
+	{ # confgure in or out a system model item that owns the specified <meta>, remove the <meta> when done.
+	my $meta  = shift;
+	my $keep = definedMatches($meta);
+	my $parent = $meta->getParentNode;
+	if(!$keep)
+		{
+		print STDERR "Note: ",$parent->getTagName," " ,$parent->getAttribute('id')," configured out\n";
+		$parent->getParentNode->removeChild($parent);
+		return; # it's removed, so there's nothing else we can possibly do
+		}
+
+	$parent->removeChild($meta);
+	}
+
+sub getDefines
+	{ # populate the list of #defines from a specified .hrh file.
+	my $file = shift;
+	my $inc;
+	foreach my $i (@includes)
+		{
+		$inc.=" -I$i";
+		}
+	open(CPP,"cpp -dD$inc \"$file\"|");
+	while(<CPP>)
+		{
+		if(!/\S/){next} # skip blank lines
+		if(/^# [0-9]+ /) {next} # don't care about these
+		s/\s+$//;
+		if(s/^#define\s+(\S+)\((.*?)\)\s+//)
+			{ #parametered define
+			push(@{$defineParams{$1}},@2,$_);
+			}
+		elsif(s/^#define\s+(\S+)//)
+			{ # normal define
+			my $def = $1;
+			s/^\s+//;
+			$defines{$1}=$_;
+			}
+		else {die "cannot process $_";}
+		}
+	close CPP;
+	$? && die "Call to cpp produced an error";
+	}
+
+sub  checkSyntaxVersion
+	{ # check if supplied version number is greater than $maxschema
+	my $schema = shift;
+	my @max=split(/\./,$maxschema);
+	my @cur=split(/\./,$schema);
+	while(@max) 
+		{
+		($max[0] > $cur[0])  && return;		# max is bigger, do nothing
+		if($cur[0] > $max[0])
+			{
+			$maxschema=$schema;
+			return;
+			}
+		shift @max;
+		shift @cur;
+		}
+	# they are equal - do nothing
+	}
+
+sub help
+	{
+	my $name= $0; $name=~s,^.*[\\/],,;
+my $text;
+format STDERR =
+ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+  $text,
+     ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<~~
+    $text
+.
+print STDERR "usage: $name  [options...] sysdef\n  valid options are:\n\n";
+	foreach (
+		"-path\tspecifies the full system-model path to the file which is being processed. By default this is  \"/os/deviceplatformrelease/foundation_system/system_model/system_definition.xml\"",
+			"   This must be an absolute path if you're processing a root sysdef.",
+			"   If processing a pkgdef file, you can use \"./package_definition.xml\" to leave all links relative.",
+
+		"-output\tspecifies the file to save the output to. If not specified this will write to stdout",
+
+		"-config\tspecifies the name of an .hrh file in which the configuration data is acquired from. If not set, no confguration will be done.",
+			"   If it is set, all configuration metadata will be processed and stripped from the output, even if the confguration data is empty",
+		"-I[path]\tspecifies the include paths to use when resolving #includes in the .hrh file. This uses the same syntax as cpp command uses: a captial \"I\" followed by the path with no space in between. Any number of these can be provided.",
+		"-exclude-meta [rel]\tspecifies the 'rel' value of <meta> elements to exclude from the output. Any number of these can be provided. The following meta rel values affect the processing of the system definition and cannot be excluded: ".join(', ',@cannotExclude)
+		) {
+		$text = $_;
+		write STDERR;
+		print STDERR "\n";
+	}
+
+	exit(1);
+	}
+
+
+	
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metatools/sysdeftools/joinsysdef.xsl	Wed Jul 28 13:20:46 2010 +0100
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+ <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<!--Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+	All rights reserved.
+	This component and the accompanying materials are made available
+	under the terms of the License "Eclipse Public License v1.0"
+	which accompanies this distribution, and is available
+	at the URL "http://www.eclipse.org/legal/epl-v10.html".
+
+	Initial Contributors:
+	Nokia Corporation - initial contribution.
+	Contributors:
+	Description:
+	Create a stand-alone sysdef from a linked set of fragments
+-->
+ 	<xsl:output method="xml" indent="yes"/>
+<!--Description:This creates a stand-alone sysdef from a linked set of fragments.
+All API metadata will be removed
+-->
+<!--Input:<sysdef> - (required) The 3.0 formatsystem definition XML file to
+		process. This can be a fragment or stand-alone. 
+		If there are no linked fragments, this will just convert all
+		relative unit paths into absolute paths and embed any linked
+		metadata-->
+
+<xsl:param name="path">/os/deviceplatformrelease/foundation_system/system_model/system_definition.xml</xsl:param>
+<!-- <path> - The full system model path for this file. Use forward slashes.-->
+
+<xsl:template match="/*">
+	<xsl:apply-templates select="." mode="join"/>
+</xsl:template>
+
+
+<xsl:template match="/SystemDefinition[systemModel]">
+<xsl:apply-templates select="." mode="join">
+	<xsl:with-param name="filename" select="$path"/>
+</xsl:apply-templates>
+</xsl:template>
+
+
+<xsl:template match="meta[@rel='Api']" priority="2" mode="meta"/> <!-- ignore these, not needed in system build -->
+
+
+<xsl:include href="lib/joinsysdef-module.xsl"/>
+
+</xsl:stylesheet>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metatools/sysdeftools/lib/filter-module.xsl	Wed Jul 28 13:20:46 2010 +0100
@@ -0,0 +1,123 @@
+<?xml version="1.0"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common"  exclude-result-prefixes="exslt">
+<!--Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+	All rights reserved.
+	This component and the accompanying materials are made available
+	under the terms of the License "Eclipse Public License v1.0"
+	which accompanies this distribution, and is available
+	at the URL "http://www.eclipse.org/legal/epl-v10.html".
+
+	Initial Contributors:
+	Nokia Corporation - initial contribution.
+	Contributors:
+	Description:
+	XSLT module which contains the logic to process the filter attribute in the system definition
+-->
+	<xsl:output method="xml" indent="yes"/>
+
+
+<!-- filters can only return hide or show -->
+
+<!-- filter-only =  item's @filter can only have items from the list
+	anything with no filters passes
+-->
+<xsl:template match="filter-only" mode="filter"><xsl:param name="item"/>
+	<xsl:if test="$item[@filter]">
+		<xsl:variable name="this" select="."/>
+		<xsl:variable name="my-filters">
+			<xsl:call-template name="filter-list">
+				<xsl:with-param name="f" select="$item/parent::component/@filter"/>
+			</xsl:call-template>
+			<xsl:call-template name="filter-list">
+				<xsl:with-param name="f" select="$item/@filter"/>
+			</xsl:call-template>
+		</xsl:variable>
+		<xsl:variable name="match">
+			<xsl:for-each select="exslt:node-set($my-filters)/*">
+				<xsl:if test="not($this/*[name()=name(current())  and @v=current()/@v])">x</xsl:if>
+			</xsl:for-each>
+		</xsl:variable>
+		<xsl:if test="$match!=''">hide</xsl:if>
+	</xsl:if>
+</xsl:template>
+
+
+
+<!-- filter-has =  item's @filter must have all filters in the list. ie it can have any other filters, but these must all be present	
+-->
+<xsl:template match="filter-has" mode="filter"><xsl:param name="item"/>
+	<xsl:if test="$item[self::component and not(unit/@filter)] or $item[self::unit and ../unit/@filter]">
+		<xsl:variable name="my-filters">
+			<xsl:call-template name="filter-list">
+				<xsl:with-param name="f" select="$item/parent::component/@filter"/>
+			</xsl:call-template>
+			<xsl:call-template name="filter-list">
+				<xsl:with-param name="f" select="$item/@filter"/>
+			</xsl:call-template>
+		</xsl:variable>
+		<xsl:variable name="match">
+			<xsl:for-each select="*">
+				<!-- 	if(f in this) {return true}  else if(!f in this) {return false} else {return !(f is positive)} -->
+				<xsl:choose>
+					<xsl:when test="exslt:node-set($my-filters)/*[name()=name(current()) and @v=current()/@v]"/> <!-- filter in item -->
+					<xsl:when test="exslt:node-set($my-filters)/*[name()!=name(current()) and @v=current()/@v]">x</xsl:when> <!-- !filter in item -->
+					<xsl:when test="self::filter">x</xsl:when> <!-- !(filter is positive) -->
+				</xsl:choose>
+			</xsl:for-each>
+		</xsl:variable>
+		<xsl:if test="$match!=''">hide</xsl:if>
+	</xsl:if>
+</xsl:template>
+
+<xsl:template match="filter-with" mode="filter"><xsl:param name="item"/>
+	<xsl:if test="$item[(self::component or self::unit)  and not(unit/@filter or self::unit[not(../unit[@filter])])]">
+		<xsl:variable name="my-filters">
+			<xsl:call-template name="filter-list">
+				<xsl:with-param name="f" select="$item/parent::component/@filter"/>
+			</xsl:call-template>
+			<xsl:call-template name="filter-list">
+				<xsl:with-param name="f" select="$item/@filter"/>
+			</xsl:call-template>
+		</xsl:variable>
+		<xsl:variable name="match">
+			<xsl:for-each select="*">
+				<xsl:if test="exslt:node-set($my-filters)/*[name()!=name(current()) and @v=current()/@v]">x</xsl:if> <!-- !filter in item -->
+			</xsl:for-each>
+		</xsl:variable>
+		<xsl:if test="$match!=''">hide</xsl:if>
+	</xsl:if>
+</xsl:template>
+
+
+
+<xsl:template name="filter-item"> <xsl:param name="f"/>
+	<!-- create an element for a given filter. If the filter's empty make nothing -->
+	<xsl:choose>
+		<xsl:when test="$f=''"/>
+		<xsl:when test="starts-with($f,'!')">
+				<not v="{substring($f,2)}"/>
+		</xsl:when>
+		<xsl:otherwise>
+				<filter v="{$f}"/>
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+<xsl:template name="filter-list"><xsl:param name="f"/>
+	<!-- turn a filter list into a set of elements (<filter> or <not>) with the attribute "v" containing the "absolute value" of the filter
+		filter="A,B,!C" becomes  <filter v="A"/><filter v="B"/><not v="C"/> 
+	  -->
+	<xsl:choose>
+		<xsl:when test="contains($f,',')">
+			<xsl:call-template name="filter-item"><xsl:with-param name="f" select="normalize-space(substring-before($f,','))"/></xsl:call-template>
+			<xsl:call-template name="filter-list">
+				<xsl:with-param name="f" select="substring-after($f,',')"/>
+			</xsl:call-template>
+		</xsl:when>
+		<xsl:otherwise>
+			<xsl:call-template name="filter-item"><xsl:with-param name="f" select="normalize-space($f)"/></xsl:call-template>
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+</xsl:stylesheet> 
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metatools/sysdeftools/lib/joinsysdef-module.xsl	Wed Jul 28 13:20:46 2010 +0100
@@ -0,0 +1,525 @@
+<?xml version="1.0"?>
+ <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
+ 	xmlns:exslt="http://exslt.org/common" exclude-result-prefixes="exslt">
+<!--Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+	All rights reserved.
+	This component and the accompanying materials are made available
+	under the terms of the License "Eclipse Public License v1.0"
+	which accompanies this distribution, and is available
+	at the URL "http://www.eclipse.org/legal/epl-v10.html".
+
+	Initial Contributors:
+	Nokia Corporation - initial contribution.
+	Contributors:
+	Description:
+	XSLT module which contains the logic to join a system definition file
+-->
+	<!-- save SF namespace as a constant to avoid the risk of typos-->
+ <xsl:variable name="defaultns">http://www.symbian.org/system-definition</xsl:variable>
+ 
+<!-- create a stand-alone sysdef from a linked set of fragments -->
+
+<xsl:template match="/*" mode="join">
+	<xsl:param name="filename"/>
+	<xsl:message terminate="yes">ERROR: Cannot process this document<xsl:if test="$filename !=''"> (<xsl:value-of select="$filename"/>)</xsl:if>
+		<xsl:choose>
+			<xsl:when test="self::SystemDefinition/@schema">. Unrecognised syntax schema="<xsl:value-of select="@schema"/>"</xsl:when>
+			<xsl:when test="self::SystemDefinition">. Missing schema</xsl:when>
+			<xsl:otherwise>. Invalid file type: <xsl:value-of select="name()"/></xsl:otherwise>
+		</xsl:choose>
+	</xsl:message>
+</xsl:template>
+
+<!-- anything in schemas 3.0.x won't add new functional attributes that need processing here, just blindly copy them-->
+
+<xsl:template match="/SystemDefinition[starts-with(@schema,'3.0.') and count(*)=1]" mode="join">
+	<xsl:param name="origin" select="/.."/>
+	<xsl:param name="root"/>
+	<xsl:param name="filename"/>
+	<xsl:param name="namespaces"/>
+	<xsl:param name="data" select="/.."/>
+	<xsl:choose>
+		<xsl:when test="$origin">	<!-- this sysdef fragment was linked from a parent sysdef -->
+			<xsl:for-each select="*"> <!-- can be only one -->
+				<xsl:variable name="upid"><xsl:apply-templates select="$origin/@id" mode="my-id"/></xsl:variable>		<!-- namespaceless ID of this in parent doc -->
+				<xsl:variable name="id"><xsl:apply-templates select="@id" mode="my-id"/></xsl:variable>						<!-- namespaceless ID of this here -->
+				<xsl:variable name="upns"><xsl:apply-templates select="$origin/@id" mode="my-namespace"/></xsl:variable>	<!-- ID's namespace in parent doc -->
+				<xsl:variable name="ns"><xsl:apply-templates select="@id" mode="my-namespace"/></xsl:variable>	<!-- ID's namespace -->
+				<xsl:if test="$id!=$upid or $ns!=$upns">
+					<xsl:message terminate="yes">ERROR: Linked ID "<xsl:value-of select="$id"/>" (<xsl:value-of select="$ns"/>) must match linking document "<xsl:value-of select="$upid"/>" (<xsl:value-of select="$upns"/>)</xsl:message>
+				</xsl:if>
+				<!-- copy any attributes not already defined (parent doc overrides child doc)-->
+				<xsl:for-each select="@*">
+					<xsl:variable name="n" select="name()"/>
+					<xsl:choose>
+						<xsl:when test="$n='id'"/> <!-- never copy this, always set -->
+						<xsl:when test="$origin/@*[name()=$n]"> <!-- don't copy if already set -->
+							<xsl:message>Note: Cannot set "<xsl:value-of select="$n"/>", already set on <xsl:value-of select="$origin/@id"/>. Ignoring linked value</xsl:message>
+						</xsl:when>
+						<xsl:when test="$n='before' or $n='replace'">
+							<!-- ensure ns is correct (if any future attribtues will ever use an ID, process it here too)-->
+							<xsl:apply-templates select="." mode="join">
+								<xsl:with-param name="namespaces" select="$namespaces"/>
+							</xsl:apply-templates>
+						</xsl:when> 
+						<xsl:otherwise><xsl:copy-of select="."/></xsl:otherwise> <!-- just copy anything else -->
+					</xsl:choose>
+				</xsl:for-each>
+				<xsl:copy-of select="../namespace::*[not(.=$namespaces)]"/> <!-- set any namespaces not already set (they should all alreayd be, but some XSLT processors are quirky) -->
+			 	<xsl:apply-templates select="$data" mode="overlay-attributes">
+					<xsl:with-param name="item" select="current()"/>
+				</xsl:apply-templates>
+				<xsl:variable name="content">									
+					<xsl:apply-templates select="*|comment()" mode="join">
+						<xsl:with-param name="root" select="$root"/>
+						<xsl:with-param name="filename" select="$filename"/>
+						<xsl:with-param name="data" select="$data"/>
+						<xsl:with-param name="namespaces" select="$namespaces | ../namespace::*[not(.=$namespaces)]"/>
+					</xsl:apply-templates>
+				</xsl:variable>
+				<xsl:apply-templates select="." mode="is-content-filtered"> <!-- optionally add filtered="yes" if some content has been removed -->
+					<xsl:with-param name="content" select="$content"/>
+				</xsl:apply-templates>
+			 	<xsl:apply-templates select="$data" mode="overlay-meta">
+					<xsl:with-param name="item" select="current()"/>
+				</xsl:apply-templates>
+				<xsl:copy-of select="$content"/>
+			</xsl:for-each>
+		</xsl:when>
+		<xsl:when test="function-available('exslt:node-set')"> <!-- this is the root element of a root sysdef -->
+			<!--try to put all namespaces in root element -->
+			<xsl:variable name="nss">
+				<!-- contains node set of namespaces to add to root element.
+					May panic if there are too many single-letter namespaces and this can't create a new one -->
+				<xsl:call-template name="needed-namespaces">
+					<xsl:with-param name="foundns">
+						<xsl:apply-templates select="//*[(self::component or self::collection or self::package or self::layer) and @href]" mode="scan-for-namespaces"/>
+					</xsl:with-param>
+				</xsl:call-template>
+			</xsl:variable>
+			<xsl:variable name="ns" select="@id-namespace | namespace::* | exslt:node-set($nss)/*"/>
+			<xsl:copy><xsl:copy-of select="@*[name()!='schema']"/><xsl:call-template name="set-schema"/>
+				<xsl:apply-templates select="self::*[not(@id-namespace)]" mode="add-id-ns"/>
+				<xsl:for-each select="exslt:node-set($nss)/*"> <!-- add namespace definitions -->
+					<xsl:attribute name="xmlns:{name()}">
+						<xsl:value-of select="."/>
+					</xsl:attribute>
+				</xsl:for-each>
+				<!-- no need to call is-content-filtered, it never will be from this element --> 
+				<xsl:apply-templates select="*|comment()" mode="join">
+					<xsl:with-param name="namespaces" select="$ns"/>
+					<xsl:with-param name="root" select="$root"/>
+					<xsl:with-param name="data" select="$data"/>
+					<xsl:with-param name="filename" select="$filename"/>
+				</xsl:apply-templates>
+			</xsl:copy>
+		</xsl:when>
+		<xsl:otherwise> <!-- can't handle node-set() so put the namespaces in the document instead of the root element-->
+			<xsl:variable name="ns" select="@id-namespace | namespace::*"/>
+			<xsl:copy><xsl:copy-of select="@*[name()!='schema']"/><xsl:call-template name="set-schema"/>
+				<!-- no need to call is-content-filtered, it never will be from this element -->
+				<xsl:apply-templates select="*|comment()" mode="join">
+					<xsl:with-param name="namespaces" select="$ns"/>
+					<xsl:with-param name="root" select="$root"/>
+					<xsl:with-param name="data" select="$data"/>
+					<xsl:with-param name="filename" select="$filename"/>
+				</xsl:apply-templates>
+			</xsl:copy>
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+<xsl:template match="*" mode="scan-for-namespaces"/> <!-- just in case of errors, consider replacing by terminate -->
+<xsl:template match="*[@href and not(self::meta)]" mode="scan-for-namespaces">
+	<!-- produce a list of namespace-prefix namespace pairs separated by newlines, in reverse order found in documents 
+		reverse order so we can try to use the first namespace prefix defined if it's available-->
+	<xsl:variable name="linked" select="document(@href,.)/*"/>
+	<xsl:for-each select="$linked">
+		<xsl:apply-templates select="//*[(self::component or self::collection or self::package or self::layer) and @href]" mode="scan-for-namespaces"/>
+		<xsl:for-each select="//namespace::* | @id-namespace">
+			<xsl:value-of select="concat(name(),' ',.,'&#xa;')"/>
+		</xsl:for-each>
+	</xsl:for-each>
+	<xsl:if test="not($linked)">
+	<xsl:message>Note: The link to <xsl:value-of select="@href"/> from <xsl:value-of select="concat(name(),' ',@id)"/> could not be resolved. Perhaps there's an error in the XML?</xsl:message>
+	</xsl:if>
+</xsl:template>
+
+<xsl:template name="needed-namespaces">
+	<xsl:param name="foundns"/>
+	<xsl:param name="usedpre"/>
+
+	<xsl:if test="$foundns!=''">
+		<xsl:variable name="line" select="substring-before($foundns,'&#xa;')"/> <!-- always has trailing newline -->
+		<xsl:variable name="name" select="substring-after($line,' ')"/> <!-- namespace prefix -->
+		<xsl:variable name="remainder" select="substring-after($foundns,'&#xa;')"/>
+		<xsl:variable name="newprefix">
+			<xsl:if test="not(contains(concat('&#xa;',$remainder),concat('&#xa;',$line,'&#xa;'))) and
+				not(//namespace::*[.=$name] or @id-namespace[.=$name] or (not(@id-namespace) and $defaultns=$name))">
+						<xsl:apply-templates select="." mode="ns-prefix">
+							<xsl:with-param name="ns" select="$name"/>
+							<xsl:with-param name="pre" select="substring-before($line,' ')"/>
+							<xsl:with-param name="dontuse" select="$usedpre"/>
+						</xsl:apply-templates>
+			</xsl:if>
+		</xsl:variable>
+		<xsl:if test="$newprefix!=''">
+			<!-- can treat this as if it were a namespace node -->
+			<xsl:element name="{$newprefix}">
+				<xsl:value-of select="$name"/>
+			</xsl:element>
+		</xsl:if>
+		<xsl:if test="$remainder!=''">
+			<xsl:call-template name="needed-namespaces">
+				<xsl:with-param name="foundns" select="$remainder"/>
+				<xsl:with-param name="usedpre" select="concat($usedpre,' ',$newprefix,' ')"/>
+			</xsl:call-template>
+		</xsl:if>
+	</xsl:if>
+</xsl:template>
+
+<xsl:template match="/SystemDefinition" mode="ns-prefix">
+	<!-- should be able to replace this with mechanism that uses the XSLT processor's own ability to generate namespaces -->
+	<xsl:param name="ns"/>
+	<xsl:param name="pre"/>
+	<xsl:param name="dontuse"/>
+	<xsl:param name="chars">ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz</xsl:param>
+	<xsl:variable name="name" select="substring(substring-after($ns,'http://www.'),1,1)"/>
+	<xsl:choose>
+		<xsl:when test="$pre!='' and $pre!='id-namespace' and not(//namespace::*[name()=$pre]) and not(contains($dontuse,concat(' ',$pre,' ')))">
+			<xsl:value-of select="$pre"/>
+		</xsl:when>
+		<xsl:when test="$ns='' and $chars=''">
+			<xsl:message terminate="yes">ERROR: Cannot create namespace prefix for downstream default namespace in <xsl:value-of select="*/@id"/></xsl:message>
+		</xsl:when>
+		<xsl:when test="$name!='' and not(contains($dontuse,concat(' ',$name,' ')))"><xsl:value-of select="$name"/></xsl:when>
+		<xsl:when test="namespace::*[name()=substring($chars,1,1)] or contains($dontuse,concat(' ',substring($chars,1,1),' '))">
+			<xsl:apply-templates mode="ns-prefix">
+				<xsl:with-param name="chars" select="substring($chars,2)"/>
+			</xsl:apply-templates>
+		</xsl:when>
+		<xsl:otherwise>
+			<xsl:value-of select="substring($chars,1,1)"/>
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+
+<!-- schema handling -->
+
+<xsl:template name="set-schema">
+<xsl:attribute name="schema">
+	<xsl:apply-templates mode="my-schema" select="/SystemDefinition"/>
+</xsl:attribute>
+</xsl:template>
+
+<xsl:template name="compare-versions"><xsl:param name="v1"/><xsl:param name="v2"/>
+			<xsl:choose>
+				<xsl:when test="$v1=$v2"><xsl:value-of select="$v1"/></xsl:when>
+				<xsl:when test="substring-before($v1,'.') &gt; substring-before($v2,'.')"><xsl:value-of select="$v1"/></xsl:when>
+				<xsl:when test="substring-before($v1,'.') &lt; substring-before($v2,'.')"><xsl:value-of select="$v2"/></xsl:when>
+				<xsl:when test="substring-before(substring-after($v1,'.'),'.') &gt; substring-before(substring-after($v2,'.'),'.')"><xsl:value-of select="$v1"/></xsl:when>
+				<xsl:when test="substring-before(substring-after($v1,'.'),'.') &lt; substring-before(substring-after($v2,'.'),'.')"><xsl:value-of select="$v2"/></xsl:when>
+				<xsl:when test="substring-after(substring-after($v1,'.'),'.') &gt; substring-after(substring-after($v2,'.'),'.')"><xsl:value-of select="$v1"/></xsl:when>
+				<xsl:when test="substring-after(substring-after($v1,'.'),'.') &lt; substring-after(substring-after($v2,'.'),'.')"><xsl:value-of select="$v2"/></xsl:when>
+				<xsl:otherwise><xsl:value-of select="$v1"/></xsl:otherwise>
+			</xsl:choose>
+</xsl:template>
+
+<xsl:template name="compare-version-list"><xsl:param name="list"/>
+	<xsl:variable name="cur" select="substring-before($list,' ')"/>
+	<xsl:variable name="remaining" select="substring-after($list,' ')"/>
+	<xsl:choose>
+		<xsl:when test="$remaining=''"><xsl:value-of select="$cur"/></xsl:when>
+		<xsl:otherwise>
+			<xsl:variable name="nextbig">
+				<xsl:call-template name="compare-version-list">
+					<xsl:with-param name="list" select="$remaining"/>
+				</xsl:call-template>
+			</xsl:variable>
+			<xsl:call-template name="compare-versions">
+				<xsl:with-param name="v1" select="$cur"/>
+				<xsl:with-param name="v2" select="$nextbig"/>
+			</xsl:call-template>
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+<xsl:template match="/SystemDefinition" mode="my-schema"><xsl:param name="biggest" select="@schema"/>
+	<xsl:variable name="linked" select="//*[(self::component or self::collection or self::package or self::layer) and @href]"/>
+	<xsl:choose>
+		<xsl:when test="not($linked)"> <!-- no need to go further -->
+			<xsl:call-template name="compare-versions">
+				<xsl:with-param name="v1" select="@schema"/>
+				<xsl:with-param name="v2" select="$biggest"/>
+			</xsl:call-template>
+		</xsl:when>
+		<xsl:otherwise>
+				<xsl:call-template name="compare-version-list">
+					<xsl:with-param name="list">
+						<xsl:for-each select="$linked">
+						<xsl:call-template name="compare-versions">
+							<xsl:with-param name="v1">
+								<xsl:apply-templates mode="my-schema" select="document(@href,.)/*"/>
+							</xsl:with-param>
+							<xsl:with-param name="v2" select="$biggest"/>
+						</xsl:call-template>
+						<xsl:text> </xsl:text>
+					</xsl:for-each>
+				</xsl:with-param>
+				</xsl:call-template>
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+
+<xsl:template match="unit" mode="join">	<xsl:param name="root"/><xsl:param name="filename"/><xsl:param name="data"/>
+	 <xsl:variable name="display">
+	 	<xsl:apply-templates select="$data" mode="filter">
+			<xsl:with-param name="item" select="current()"/>
+		</xsl:apply-templates>
+	 </xsl:variable>
+	 
+	 <xsl:if test="$display != 'hide' "> <!-- if hide, remove completely from the output-->	 
+		<xsl:element name="{name()}">
+			<xsl:apply-templates select="@*" mode="join">
+				<xsl:with-param name="root" select="$root"/>
+				<xsl:with-param name="filename" select="$filename"/>
+			</xsl:apply-templates>
+		</xsl:element>
+	</xsl:if>
+</xsl:template>
+
+<!-- override mode="meta" to translate metadata sections. By default, include -->
+<xsl:template match="meta" priority="2" mode="join"><xsl:param name="data"/>
+	 <xsl:variable name="display">
+	 	<xsl:apply-templates select="$data" mode="filter">
+			<xsl:with-param name="item" select="current()"/>
+		</xsl:apply-templates>
+	 </xsl:variable>
+	 
+	<xsl:if test="$display != 'hide' "> <!-- if hide, remove completely from the output-->	
+		<xsl:apply-templates select="." mode="meta"> 
+			<xsl:with-param name="display" select="$display"/>
+			<xsl:with-param name="data" select="$data"/>
+		</xsl:apply-templates>
+	</xsl:if>
+</xsl:template>
+
+<xsl:template match="meta[@rel='link-mapping']" priority="3" mode="join"/> <!--these are only used in the joining process, so remove from output -->
+
+
+<xsl:template match="*" mode="join">
+	<xsl:param name="root"/><xsl:param name="filename"/><xsl:param name="namespaces"/><xsl:param name="data"/>
+	<!-- get attribtues from overlay -->
+	<!-- test for presence, if filtered out, just return -->
+	<!-- test for children, if it has some, but they're filtered out, either return or leave as empty, dependening on filter rule
+		if had items and now has none, options:
+			still has meta: keep / delete
+			still has comments: keep / delete 
+	 -->
+	 <xsl:variable name="display">
+	 	<xsl:apply-templates select="$data" mode="filter">
+			<xsl:with-param name="item" select="current()"/>
+		</xsl:apply-templates>
+	 </xsl:variable>
+	 
+	 <xsl:if test="$display != 'hide' "> <!-- if hide, remove completely from the output-->
+		 <xsl:variable name="href">
+		 	<xsl:apply-templates select="." mode="link">
+				<xsl:with-param name="data" select="$data"/>
+			</xsl:apply-templates>
+		 </xsl:variable>
+	 		 
+		<xsl:element name="{name()}"> <!-- use this instead of <copy> so xalan doesn't add extra wrong namespaces -->
+			<xsl:apply-templates select="@*" mode="join">
+				<xsl:with-param name="namespaces" select="$namespaces"/>
+			</xsl:apply-templates>
+			<xsl:if test="$display != '' ">
+				<!-- custom attribute to indicate how this is to be represented. Blank indicates normal, hide removes from the output (see above), anything else is put in the attribute --> 
+				<xsl:attribute name="display"><xsl:value-of select="$display"/></xsl:attribute>
+			</xsl:if>
+		 	<xsl:apply-templates select="$data" mode="overlay-attributes">
+				<xsl:with-param name="item" select="current()"/>
+			</xsl:apply-templates>			
+			<xsl:choose>
+				<xsl:when test="$href !='' ">
+					<xsl:variable name="prefixmap" select="ancestor::SystemDefinition/*/meta[@rel='link-mapping']/map-prefix[starts-with($href,@link)]"/>
+					<xsl:variable name="origin" select="."/>
+					<xsl:apply-templates select="document($href,.)/*" mode="join">
+						<xsl:with-param name="origin" select="$origin"/>
+						<xsl:with-param name="data" select="$data"/>
+						<xsl:with-param name="namespaces" select="$namespaces"/>
+						<xsl:with-param name="filename">
+							<xsl:call-template name="joinpath">
+								<xsl:with-param name="file" select="$filename"/>
+								<xsl:with-param name="rel">
+									<xsl:choose>
+										<xsl:when test="$prefixmap">
+											<xsl:value-of select="$prefixmap/@to"/>
+											<xsl:value-of select="substring-after($href,$prefixmap/@link)"/>
+										</xsl:when>
+										<xsl:otherwise>
+											<xsl:value-of select="$href"/>
+										</xsl:otherwise>
+									</xsl:choose>								
+								 </xsl:with-param>
+							</xsl:call-template>					
+						</xsl:with-param>
+						<xsl:with-param name="root">
+							<xsl:value-of select="$root"/>/<xsl:call-template name="lastbefore">
+								<xsl:with-param name="string" select="$href"/>
+							</xsl:call-template>
+						</xsl:with-param>
+					</xsl:apply-templates> 
+				</xsl:when>
+				<xsl:otherwise>
+					<xsl:variable name="content">
+						<xsl:apply-templates select="*|comment()" mode="join">
+							<xsl:with-param name="root" select="$root"/>
+							<xsl:with-param name="filename" select="$filename"/>
+							<xsl:with-param name="namespaces" select="$namespaces"/>
+							<xsl:with-param name="data" select="$data"/>
+						</xsl:apply-templates>
+					</xsl:variable>
+					<xsl:apply-templates select="." mode="is-content-filtered"> <!-- add filtered="yes" if some content has been removed -->
+						<xsl:with-param name="content" select="$content"/>
+					</xsl:apply-templates>
+				 	<xsl:apply-templates select="$data" mode="overlay-meta">
+						<xsl:with-param name="item" select="current()"/>
+					</xsl:apply-templates>
+					<xsl:copy-of select="$content"/>
+				</xsl:otherwise>
+			</xsl:choose>
+		</xsl:element>
+	</xsl:if>
+</xsl:template>
+
+<!-- By default, do nothing. Can override template to add filtered="yes" if need to track what's a placeholder and what's been filtered 
+	implement with param name="content"
+-->
+<xsl:template mode="is-content-filtered" match="*" priority="-2"/>
+
+
+<xsl:template match="@mrp[starts-with(.,'/')] | @bldFile[starts-with(.,'/')] | @base[starts-with(.,'/')]" mode="join">
+	<xsl:copy-of select="."/>
+</xsl:template>
+
+
+<xsl:template match="@mrp|@bldFile|@base" mode="join">	<xsl:param name="root"/><xsl:param name="filename"/>
+	<xsl:attribute name="{name()}">
+		<xsl:call-template name="joinpath">
+			<xsl:with-param name="file" select="$filename"/>
+			<xsl:with-param name="rel" select="."/>
+		</xsl:call-template>	
+	</xsl:attribute>	
+</xsl:template>
+
+
+<xsl:template match="@href" mode="join"/> <!--never copy this into the generated doc, that's the whole point of this module -->
+
+<xsl:template match="@*" mode="my-namespace"> <!-- the namespace of an ID -->
+	<xsl:choose>
+		<xsl:when test="contains(.,':')">
+			<xsl:value-of select="ancestor::*/namespace::*[name()=substring-before(current(),':')]"/>
+		</xsl:when>
+		<xsl:when test="/SystemDefinition/@id-namespace">
+			<xsl:value-of select="/SystemDefinition/@id-namespace"/>
+		</xsl:when>
+		<xsl:otherwise>
+			<xsl:value-of select="$defaultns"/>
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+
+<xsl:template match="@*" mode="my-id"> <!-- the ID with namespace prefix removed -->
+	<xsl:choose>
+		<xsl:when test="contains(.,':')">
+			<xsl:value-of select="substring-after(.,':')"/>
+		</xsl:when>
+		<xsl:otherwise>
+			<xsl:value-of select="."/>
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+<xsl:template match="*" mode="err-path">
+<xsl:if test="../@id">
+	<xsl:apply-templates select=".." mode="err-path"/>/</xsl:if>
+<xsl:value-of select="@id"/>
+</xsl:template>
+
+
+<xsl:template match="@id|@before|@replace" mode="join">
+	<xsl:param name="namespaces"/>
+	<!-- this will change the namespace prefixes for all IDs to match the root document -->
+	<xsl:variable name="ns">
+		<xsl:apply-templates select="." mode="my-namespace"/>
+	</xsl:variable>
+	<xsl:if test="$ns=''">
+		<xsl:message terminate="yes">ERROR: Could not find namespace for <xsl:value-of select="name()"/> "<xsl:value-of select="."/>" in <xsl:apply-templates select="../.." mode="err-path"/>
+		<xsl:text>&#xa;</xsl:text>
+		</xsl:message>
+	</xsl:if>
+	<xsl:variable name="prefix" select="name($namespaces[.=$ns])"/>
+	<xsl:attribute name="{name()}">
+	<xsl:choose>
+		<xsl:when test="$prefix = 'id-namespace' or  (not($namespaces[name()='id-namespace']) and $ns=$defaultns)"/> <!-- it's the default namespace, no prefix -->
+		<xsl:when test="$prefix='' and contains(.,':')">
+			<!-- complex: copy id and copy namespace (namespace should be copied already)-->
+			<xsl:value-of select="."/>
+		</xsl:when>
+		<xsl:when test="$prefix='' and $ns=$defaultns"/> <!-- no prefix and it's the default --> 
+		<xsl:when test="$prefix!=''">			<!-- just change the prefix -->
+			<xsl:value-of select="concat($prefix,':')"/>
+		</xsl:when>
+		<xsl:otherwise>
+		<xsl:message terminate="yes">ERROR: Joining error in resolving namespace for <xsl:value-of select="name()"/> "<xsl:value-of select="."/>" in <xsl:apply-templates select="../.." mode="err-path"/>
+		<xsl:text>&#xa;</xsl:text></xsl:message>
+		</xsl:otherwise>
+	</xsl:choose>
+		<xsl:apply-templates select="." mode="my-id"/>
+	</xsl:attribute>
+</xsl:template>
+
+
+
+<xsl:template match="@*|comment()" mode="join"><xsl:copy-of select="."/></xsl:template>
+
+
+<xsl:include href="path-module.xsl"/>
+
+<!-- overridable templates follow -->
+
+
+<xsl:template match="*" mode="filter" priority="-9"/> <!-- by default show --> 
+<xsl:template match="*" mode="overlay-attributes" priority="-9"/> <!-- by default do nothing --> 
+<xsl:template match="*" mode="overlay-meta" priority="-9"/> <!-- by default do nothing --> 
+<xsl:template match="/SystemDefinition" mode="add-id-ns" priority="-9"/> <!-- some tools may have an easier job if this were always present, but, by default, assume it can just stay implied -->
+
+<xsl:template match="*" mode="link" priority="-1"> <!-- can be overriden to allow custom changes to href values --> 
+<xsl:value-of select="@href"/>
+</xsl:template>
+
+
+<xsl:template match="*" mode="meta" priority="-9"><xsl:param name="data"/><xsl:param name="display"/>
+	<xsl:element name="{name()}">
+		<xsl:copy-of select="@*[name()!='href']"/> <!-- copy all attributes as is, always drop href -->
+		<xsl:choose>
+			<xsl:when test="$display='local' and @href and contains(@href,':') and not(starts-with(@href,'file:'))">
+				<!-- non-local URL: only want local URLs, so keep href as is-->
+				<xsl:copy-of select="@href"/> 
+			</xsl:when>
+			<xsl:when test="@href">
+				<xsl:copy-of select="document(@href,.)/*"/> 
+			</xsl:when>
+			<xsl:otherwise>
+				<xsl:copy-of select="*|comment()"/>
+			</xsl:otherwise>
+		</xsl:choose>
+	</xsl:element>
+</xsl:template>
+
+
+</xsl:stylesheet>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metatools/sysdeftools/lib/mergesysdef-module.xsl	Wed Jul 28 13:20:46 2010 +0100
@@ -0,0 +1,653 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common"  exclude-result-prefixes="exslt">
+<!--Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+	All rights reserved.
+	This component and the accompanying materials are made available
+	under the terms of the License "Eclipse Public License v1.0"
+	which accompanies this distribution, and is available
+	at the URL "http://www.eclipse.org/legal/epl-v10.html".
+
+	Initial Contributors:
+	Nokia Corporation - initial contribution.
+	Contributors:
+	Description:
+	XSLT module for merging only two sysdef files according to the 3.0.1 rules. 
+		2.x and older syntax not supported and must be converetd before calling.
+
+		Requires the including XSLT to also include path-module.xsl
+-->
+	
+<xsl:variable name="defaultnamespace">http://www.symbian.org/system-definition</xsl:variable>
+
+<xsl:template match="/SystemDefinition[starts-with(@schema,'2.') or starts-with(@schema,'1.')]" priority="2" mode="merge-models">
+	<xsl:message terminate="yes">ERROR: Syntax <xsl:value-of select="@schema"/> not supported</xsl:message>
+</xsl:template>
+<!--<xsl:template match="/SystemDefinition[not(systemModel)]" priority="2" mode="merge-models">
+	<xsl:message terminate="yes">ERROR: Can only merge stand-alone system models</xsl:message>
+</xsl:template>-->
+
+<!-- stuff for dealing with namespaces -->
+
+
+<xsl:template match="node()|@*" mode="translate-namespaces"><xsl:copy-of select="."/></xsl:template>
+<!-- don't translate meta or unit tags, just copy verbatim -->
+<xsl:template match="meta|unit" mode="translate-namespaces" priority="2">
+<xsl:element name="{name()}">
+<xsl:copy-of select="@*|*|comment()"/>
+</xsl:element>
+</xsl:template>
+
+<xsl:template match="*" mode="translate-namespaces"><xsl:param name="nsdoc"/>
+<xsl:element name="{name()}">
+<xsl:apply-templates select="@*|node()" mode="translate-namespaces">
+	<xsl:with-param name="nsdoc" select="$nsdoc"/>
+</xsl:apply-templates>
+</xsl:element>
+</xsl:template>
+
+
+<xsl:template match="@id|@before|@replace" mode="translate-namespaces"><xsl:param name="nsdoc"/>
+	<xsl:attribute name="{name()}">
+		<xsl:variable name="id">
+			<xsl:choose>
+				<xsl:when test="contains(.,':')">
+					<xsl:value-of select="substring-after(.,':')"/>
+				</xsl:when>
+				<xsl:otherwise>
+					<xsl:value-of select="."/>
+				</xsl:otherwise>
+			</xsl:choose>
+		</xsl:variable>
+		<xsl:variable name="ns">
+			<xsl:choose>
+				<xsl:when test="contains(.,':')">
+					<xsl:value-of select="ancestor-or-self::*/namespace::*[name()=substring-before(current()/.,':')]"/>
+				</xsl:when>
+				<xsl:when test="ancestor::SystemDefinition/@id-namespace">
+					<xsl:value-of select="ancestor::SystemDefinition/@id-namespace"/>
+				</xsl:when>
+				<xsl:otherwise>
+					<xsl:value-of select="$defaultnamespace"/>
+				</xsl:otherwise>
+			</xsl:choose>
+		</xsl:variable>
+		<xsl:choose>
+			<xsl:when test="not($nsdoc/@id-namespace) and $defaultnamespace=$ns">
+				<xsl:value-of select="$id"/>
+			</xsl:when>
+			<xsl:when test="$nsdoc/@id-namespace=$ns">
+				<xsl:value-of select="$id"/>
+			</xsl:when>
+			<xsl:when test="$nsdoc/namespace::*[.=$ns]">
+				<xsl:value-of select="concat(name($nsdoc/namespace::*[.=$ns]),':',$id)"/>
+			</xsl:when>
+			<xsl:when test="ancestor::SystemDefinition/@id-namespace=$ns">
+				<xsl:variable name="myns">
+					<xsl:apply-templates mode="ns-prefix" select="$nsdoc">
+						<xsl:with-param name="ns" select="$ns"/>
+					</xsl:apply-templates>
+				</xsl:variable>			
+				<xsl:value-of select="concat($myns,':',$id)"/>
+			</xsl:when>
+			<xsl:otherwise> <!-- some namespace that needed to be defined --> 
+			<xsl:message>Warning: need definition for namespace "<xsl:value-of select="$ns"/>" for <xsl:value-of select="$id"/></xsl:message>
+				<xsl:value-of select="."/>					
+			</xsl:otherwise>
+		</xsl:choose>		
+	</xsl:attribute>
+</xsl:template>
+
+<xsl:template match="SystemDefinition" mode="ns-prefix">
+	<xsl:param name="ns"/> <!-- the namespace URI -->
+	<xsl:param name="pre"/> <!-- the preferred prefix to use if possbile -->
+	<xsl:param name="dontuse"/> <!-- space prefixed, separated and terminated list of namespace prefixes to not use -->
+	<xsl:param name="chars">ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz</xsl:param> <!-- single letter namespace prefixes to try -->
+	<xsl:variable name="name" select="substring(substring-after($ns,'http://www.'),1,1)"/>
+	<xsl:choose>
+		<xsl:when test="$pre!='' and $pre!='id-namespace' and not(//namespace::*[name()=$pre]) and not(contains($dontuse,concat(' ',$pre,' ')))">
+			<xsl:value-of select="$pre"/>
+		</xsl:when>
+		<xsl:when test="$ns='' and $chars=''">
+			<xsl:message terminate="yes">ERROR: Cannot create namespace prefix for downstream default namespace in <xsl:value-of select="*/@id"/></xsl:message>
+		</xsl:when>
+		<xsl:when test="$name!='' and not(contains($dontuse,concat(' ',$name,' ')))"><xsl:value-of select="$name"/></xsl:when>
+		<xsl:when test="namespace::*[name()=substring($chars,1,1)] or contains($dontuse,concat(' ',substring($chars,1,1),' '))">
+			<xsl:apply-templates mode="ns-prefix">
+				<xsl:with-param name="chars" select="substring($chars,2)"/>
+			</xsl:apply-templates>
+		</xsl:when>
+		<xsl:otherwise>
+			<xsl:value-of select="substring($chars,1,1)"/>
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+
+<!--  need to make sure this handles <meta> correctly -->
+
+<xsl:template match="SystemDefinition" mode="merge-models">
+	<xsl:param name="other"/>	<!-- the downstream SystemDefinition this is merged with -->
+	<xsl:param name="up" select="systemModel"/>	<!-- the element containing the origin @name used for any component from "this" model. -->
+	<xsl:param name="down" select="$other/systemModel"/> <!-- the element containing origin @name used for any component from $other model. -->
+	
+	<!-- do some testing -->
+ 	<xsl:if test="$other[starts-with(@schema,'2.') or starts-with(@schema,'1.')]">
+		<xsl:message terminate="yes">ERROR: Syntax <xsl:value-of select="$other/@schema"/> not supported</xsl:message>
+	</xsl:if>
+	<xsl:if test="name(*) != name($other/*)">
+		<xsl:message terminate="yes">ERROR: Can only merge system models of the same rank</xsl:message>
+	</xsl:if>
+	 
+	<xsl:copy>
+		<xsl:attribute name="schema">
+			<xsl:call-template name="compare-versions">
+				<xsl:with-param name="v1" select="@schema"/>
+				<xsl:with-param name="v2" select="$other/@schema"/>
+			</xsl:call-template>
+		</xsl:attribute>
+		<xsl:copy-of  select="@*[name()!='schema']"/> <!--  use attributes from origin model -->
+		<xsl:variable name="namespaces">
+			<xsl:copy> <!-- needs <copy> so the processor doesn't lose the namespaces -->
+				<!--copy namespaces as needed -->
+				
+				<xsl:copy-of select="namespace::*[name()!='xml']"/> <!-- all upstream namespaces -->
+
+				<xsl:variable name="cur" select="."/>
+				<xsl:for-each select="$other/namespace::*"> <!-- all namespaces in downstream not already in upstream -->
+					<xsl:if test="not((. = $cur/@id-namespace) or (not($cur/@id-namespace) and .= $defaultnamespace) or  $cur/namespace::*[.=current()])">
+							<!-- namespace in downstream not in upstream doc -->
+							<xsl:variable name="newprefix">
+								 <!-- test to see if the ns prefix already exists -->
+								<xsl:apply-templates select="$cur" mode="ns-prefix">
+									<xsl:with-param name="ns" select="."/>
+									<xsl:with-param name="pre" select="name()"/>
+								</xsl:apply-templates>
+							</xsl:variable>
+							<xsl:copy/>
+					</xsl:if>   
+				</xsl:for-each>
+				
+					<xsl:if test="not(($other/@id-namespace = @id-namespace) or (not($other/@id-namespace) and not(@id-namespace)) or (not(@id-namespace) and $other/@id-namespace = $defaultnamespace) or namespace::*[.=$other/@id-namespace])">  
+						<!-- default namespace in downstream not in upstream doc -->
+						<!-- need to make created ns a bit more intelligent -->
+						<xsl:attribute name="bar" namespace="{$other/@id-namespace}">
+							<xsl:value-of select="$other/@id-namespace"/>
+						</xsl:attribute>
+				</xsl:if>
+			</xsl:copy>
+		</xsl:variable>
+
+		
+		<!-- copy the namespaces to currently open element (the root one) -->
+		<xsl:copy-of select="namespace::*"/>
+		<xsl:for-each select="$other/namespace::*[.!=current()/namespace::*]"><xsl:copy/></xsl:for-each>
+		<xsl:for-each select="exslt:node-set($namespaces)/*/namespace::*"><xsl:copy/></xsl:for-each>
+	<!-- translate all IDs in downstream doc to use namespaces from upstream doc  
+		This is so much easier than having to propigate this info around while creating the doc-->
+	<xsl:variable name="otherdoc">
+		<xsl:apply-templates mode="translate-namespaces" select="$other">
+			<xsl:with-param name="nsdoc" select="exslt:node-set($namespaces)/* | ."/>
+		</xsl:apply-templates>
+	</xsl:variable>
+		<xsl:apply-templates mode="merge-models">
+			<xsl:with-param name="other" select="exslt:node-set($otherdoc)/*"/>
+			<xsl:with-param name="up" select="$up"/>
+			<xsl:with-param name="down" select="$down"/>
+			<xsl:with-param name="replaces" select="exslt:node-set($otherdoc)//*[self::component or self::collection or self::package or self::layer]/@replace"/>
+		</xsl:apply-templates>
+	
+	</xsl:copy>
+</xsl:template>
+
+<xsl:template match="systemModel" mode="merge-models">
+	<xsl:param name="other"/>	<!-- the parent of the downstream systemModel this is merged with -->
+	<xsl:param name="up"/>
+	<xsl:param name="down"/>
+	<xsl:param name="replaces"/>
+	<xsl:copy><xsl:copy-of  select="@*"/>
+		<!--  copy metas and comments in between meta. Do not try to merge metadata between models -->
+			<xsl:copy-of select="meta | $other/systemModel/meta | comment()[following-sibling::meta]"/>	
+		<xsl:apply-templates mode="merge-models">
+			<xsl:with-param name="other" select="$other/systemModel"/>
+			<xsl:with-param name="up" select="$up"/>
+			<xsl:with-param name="down" select="$down"/>
+			<xsl:with-param name="replaces" select="$replaces"/>
+		</xsl:apply-templates>
+	</xsl:copy>
+</xsl:template>
+
+<xsl:template match="@*|*|comment()" mode="merge-models"><xsl:copy-of select="."/></xsl:template>
+
+
+<xsl:template match="meta|comment()[following-sibling::meta]" mode="merge-models"/>
+	<!-- copy elesewhere, not here so that metas always appear first-->
+
+
+
+<!-- merge levels attribute via std rules -->
+<xsl:template match="layer/@levels|package/@levels" mode="merge-models">
+	<xsl:param name="other"/><!-- the element contains the other @levels -->
+	<xsl:choose>
+		<!--  if they are the same, or not specified in the other,  just copy -->
+		<xsl:when test=".=$other/@levels or not($other/@levels)"><xsl:copy-of select="."/></xsl:when>
+		<xsl:when test="contains(concat(' ',normalize-space(.),' '),concat(' ',normalize-space($other/@levels),' '))">
+			<!--upstream completely contains downstream, just copy --> 
+			<xsl:copy-of select="."/>
+		</xsl:when>
+		<xsl:when test="contains(concat(' ',normalize-space($other/@levels),' '),concat(' ',normalize-space(.),' '))">
+			<!--  If this is contained is other, then use other-->
+			<xsl:copy-of select="$other/@levels"/>
+		</xsl:when>
+		<xsl:when test="contains(concat(' ',normalize-space($other/@levels),' '),' - ')">
+			<!-- if other uses - syntax, then pre/append -->
+			<xsl:variable name="lev">
+				<xsl:value-of select="substring-before(concat(' ',normalize-space($other/@levels),' '),' - ')"/>
+				<xsl:value-of select="concat(' ',.,' ')"/>
+				<xsl:value-of select="substring-after(concat(' ',normalize-space($other/@levels),' '),' - ')"/>
+			</xsl:variable>
+			<xsl:attribute name="levels"><xsl:value-of select="normalize-space($lev)"/></xsl:attribute>
+		</xsl:when>
+		<xsl:otherwise> <!--  if they differ, use the origin's levels -->
+			<xsl:message>Note: levels differ "<xsl:value-of select="."/>" vs "<xsl:value-of select="$other/@levels"/>" on <xsl:value-of select="../@id"/></xsl:message>
+			<xsl:copy-of select="."/>
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+<xsl:template name="copy-sorted-content">
+	<xsl:param name="base"/>
+	<xsl:param name="to-sort"/>
+	<xsl:param name="start"/>
+	<xsl:param name="end"/>
+	<xsl:param name="down"/>
+	<xsl:param name="remainder" select="/.."/>
+
+	<xsl:choose>
+		<xsl:when test="not($to-sort)"/>  <!-- nothing left to copy. stop -->
+		<xsl:when test="not($base)"/>  <!-- reached end. stop -->
+		<xsl:when test="$base[1]/@id=$end/following-sibling::*[1]/@id"/> <!-- passed $end. Stop -->
+		<xsl:when test="$base[1]/@id = $to-sort[1]/@id">  <!-- both lists start with same item -->
+			<xsl:if test="$base[1]/@id!=$end/@id"> <!-- not at end, so keep going -->
+				<xsl:call-template name="copy-sorted-content">
+					<xsl:with-param name="base" select="$base[position() != 1]"/>
+					<xsl:with-param name="to-sort" select="$to-sort[position() != 1]"/>
+					<xsl:with-param name="remainder" select="$remainder"/>
+					<xsl:with-param name="start" select="$start"/>
+					<xsl:with-param name="end" select="$end"/>
+					<xsl:with-param name="down" select="$down"/>
+				</xsl:call-template>		
+			</xsl:if>
+		</xsl:when>	
+		<xsl:when test="$remainder[@id = $base[1]/@id]"> <!-- left over item is in $base -->
+			<xsl:call-template name="copy-sorted-content">
+				<xsl:with-param name="base" select="$base[position() != 1]"/>
+				<xsl:with-param name="to-sort" select="$to-sort"/>
+				<xsl:with-param name="remainder" select="$remainder[@id != $base[1]/@id]"/>
+				<xsl:with-param name="start" select="$start"/>
+				<xsl:with-param name="end" select="$end"/>
+				<xsl:with-param name="down" select="$down"/>
+			</xsl:call-template>		
+		</xsl:when>
+		<xsl:when test="not($base[@id = $to-sort[1]/@id])"> <!-- in to-sort, but not base -->		
+			<xsl:if test="$base[1]/@id=$end/@id  and not($base[@id=$to-sort[1]/@before])">
+			 	<!-- if at end, then this needs to be copied
+					don't copy if the before ID is found in $base	-->
+				<xsl:apply-templates mode="merge-copy-of" select="$to-sort[1]">
+					<xsl:with-param name="origin" select="$down"/>
+					<xsl:with-param name="root" select="$end/ancestor::SystemDefinition"/>
+				</xsl:apply-templates>
+			</xsl:if>			
+		<xsl:call-template name="copy-sorted-content">
+			<xsl:with-param name="base" select="$base"/>
+			<xsl:with-param name="to-sort" select="$to-sort[position() != 1]"/>
+			<xsl:with-param name="remainder" select="$remainder"/>
+			<xsl:with-param name="start" select="$start"/>
+			<xsl:with-param name="end" select="$end"/>
+			<xsl:with-param name="down" select="$down"/>
+		</xsl:call-template>		
+		</xsl:when>	
+		<xsl:when test="not($to-sort[@id = $base[1]/@id])"> <!-- in base, but not to-sort -->		
+		<xsl:call-template name="copy-sorted-content">
+			<xsl:with-param name="base" select="$base[position() != 1]"/>
+			<xsl:with-param name="to-sort" select="$to-sort"/>
+			<xsl:with-param name="remainder" select="$remainder"/>
+			<xsl:with-param name="start" select="$start"/>
+			<xsl:with-param name="end" select="$end"/>
+			<xsl:with-param name="down" select="$down"/>
+		</xsl:call-template>		
+		</xsl:when>	
+		<xsl:when test="$base[@id = $to-sort[1]/@id]"> <!-- is in base, but not 1st one-->
+			<xsl:call-template name="copy-sorted-content">
+				<xsl:with-param name="base" select="$base"/>
+				<xsl:with-param name="to-sort" select="$to-sort[position() != 1] "/>
+				<xsl:with-param name="remainder" select="$remainder | $to-sort[1]"/>
+				<xsl:with-param name="start" select="$start"/>
+				<xsl:with-param name="end" select="$end"/>
+				<xsl:with-param name="down" select="$down"/>
+			</xsl:call-template>
+		</xsl:when>	
+	</xsl:choose>
+</xsl:template>
+
+<xsl:template match="node()" mode="merge-data">
+	<xsl:copy-of select="." />
+</xsl:template>
+
+<xsl:template match="meta" mode="merge-data">
+	<xsl:param name="metas" />
+	<!-- compare this meta against all metas in the  merged doc
+		if they are identical, then ignore this one.
+		identical is computed by translating to a string, normalising some known parts. This might be slow in some cases-->
+	<xsl:variable name="val"><xsl:apply-templates select="." mode="as-xml-text" /></xsl:variable>
+	<xsl:variable name="match">
+		<xsl:for-each select="$metas">
+			<xsl:variable name="cur"><xsl:apply-templates select="." mode="as-xml-text" /></xsl:variable>
+			<xsl:if test="$cur=$val">*</xsl:if>
+		</xsl:for-each>
+	</xsl:variable>
+	<xsl:if test="$match='' ">
+		<xsl:copy-of select="." />
+	</xsl:if>
+</xsl:template>
+
+<xsl:template match="text()[normalize-space(.)='']" mode="as-xml-text"/>
+<xsl:template match="node()" mode="as-xml-text"><xsl:value-of select="."/></xsl:template>
+<xsl:template match="comment()" mode="as-xml-text">&lt;--<xsl:value-of select="."/>--&gt;</xsl:template>
+<xsl:template match="@*" mode="as-xml-text">
+	<xsl:value-of select="concat(' ',name())"/>="<xsl:value-of select="."/>"</xsl:template>
+<xsl:template match="*" mode="as-xml-text">
+	<xsl:value-of select="concat('&lt;',name())"/>
+	<xsl:apply-templates select="@*" mode="as-xml-text"/>
+	<xsl:if test="self::meta and not(@rel)"> rel="Generic"</xsl:if>
+	<xsl:if test="self::meta and not(@type)"> type="auto"</xsl:if>
+	<xsl:text>&gt;</xsl:text>
+	<xsl:apply-templates select="node()" mode="as-xml-text"/>
+	<xsl:value-of select="concat('&lt;/',name(),'&gt;')"/>
+</xsl:template>
+
+
+<xsl:template match="layer | package | collection | component" mode="merge-models">
+	<xsl:param name="other"/>	<!-- the downstream item of the parent's rank that contains a potential items this is merged with -->
+	<xsl:param name="up"/>
+	<xsl:param name="down"/>
+	<xsl:param name="replaces"/>
+	<xsl:variable name="this" select="."/>	<!-- current item -->
+	<!-- match = this item in the downstream model -->	
+	<xsl:variable name="match" select="$other/*[@id=current()/@id]"/>
+
+	<xsl:choose>
+		<xsl:when test="$replaces[.=$this/@id] or (self::component and $match)">  <!-- replace the item instead of merge -->
+			<xsl:message>Note: <xsl:value-of select="name()"/> "<xsl:value-of select="@id"/>" in "<xsl:value-of select="../@id"/>" <xsl:choose>
+				<xsl:when test="self::component and $match">overridden in downstream sysdef</xsl:when>
+				<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>
+			</xsl:choose>
+			</xsl:message>
+			<!-- if the removed item is in the downstream doc, just copy that and ignore the upstream contents -->
+			<xsl:apply-templates mode="merge-copy-of" select="$match">
+				<xsl:with-param name="origin" select="$down"/>
+				<xsl:with-param name="root" select="$this/ancestor::SystemDefinition"/>			
+				<xsl:with-param name="replaces" select="$replaces"/>
+			</xsl:apply-templates>		
+		</xsl:when>
+		<xsl:otherwise>
+			<!-- remove this if it's in the list of stuff to be replaced-->
+
+	<!-- prev = the previous item before the current one (no metas, only named items)-->
+	<xsl:variable name="prev" select="preceding-sibling::*[@id][1]"/> 
+
+	<!-- copy all items between this and prev  that are solely in the downstream model -->	 		
+
+	<xsl:choose>
+		<xsl:when test="$match and (not($prev) or $other/*[@id= $prev/@id] )">
+			<xsl:call-template name="copy-sorted-content">
+				<xsl:with-param name="base" select="../*[@id]"/>
+				<xsl:with-param name="to-sort" select="$other/*[@id]"/>
+				<xsl:with-param name="start" select="$prev"/>
+				<xsl:with-param name="end" select="."/>
+				<xsl:with-param name="down" select="$down"/>
+			</xsl:call-template>
+		</xsl:when>
+	<xsl:when test="not($match/preceding-sibling::*[@id=$this/../*/@id]) and $other/*[@id= current()/@id]/preceding-sibling::*[@id and not(@before)]">
+		<!-- if this is the first item in other that's also in this, then put all new items from other here -->
+		<xsl:apply-templates mode="merge-copy-of" select="$match/preceding-sibling::*[@id and not(@before)]">
+			<xsl:with-param name="origin" select="$down"/>
+			<xsl:with-param name="root" select="$this/ancestor::SystemDefinition"/>	
+			<xsl:with-param name="replaces" select="$replaces"/>
+		</xsl:apply-templates>
+	</xsl:when>
+	</xsl:choose>
+
+ 	<!-- just copy anything identified as being before this, assume they're all ok -->
+	<xsl:apply-templates mode="merge-copy-of" select="$other/*[@before=current()/@id]">
+		<xsl:with-param name="remove-before" select="1"/>
+		<xsl:with-param name="origin" select="$down"/>
+		<xsl:with-param name="root" select="$this/ancestor::SystemDefinition"/>	
+		<xsl:with-param name="replaces" select="$replaces"/>
+	</xsl:apply-templates>
+
+	
+	<xsl:copy>
+		<xsl:apply-templates select="@*" mode="merge-models"> <!-- copy upstream attributes -->
+			<xsl:with-param name="other" select="$match"/>
+		</xsl:apply-templates>
+		
+		<xsl:if test="self::component and not(@origin-model) and $up/@name">
+			<!-- insert origin-model and optional root for components only -->
+			<xsl:attribute name="origin-model">
+				<xsl:value-of select="$up/@name"/>
+			</xsl:attribute>
+			<xsl:if test="not(@root)">
+				<xsl:copy-of select="$up/@root"/>
+			</xsl:if>
+		</xsl:if>
+		
+		<xsl:for-each select="$match/@*[name()!='replace']">  <!-- copy downstream attributes, only if not set on upstream -->
+			<xsl:if test="not($this/@*[name()=name(current())])"><xsl:copy-of select="."/></xsl:if>
+		</xsl:for-each>
+
+		<xsl:if test="$match/@replace"> <!-- check replace separately -->
+			<xsl:if test="not($this/ancestor::SystemDefinition//*[(self::component or self::collection or self::package or self::layer) and $match/@replace=@id])">
+				<!-- only remove replace if it's been used -->
+				<xsl:copy-of select="$match/@replace"/>
+			</xsl:if>
+		</xsl:if>
+		
+		<xsl:choose>
+			<xsl:when test="self::component">
+				<!-- copy all units, metas and comments from this
+					copy all metas in the merged component
+					copy any new comments in the merged component (not duplicates)
+					if there are no units in the this, copy all units in the merged component
+					if there are units in this, copy only the versioned units in the merged component (only those versions not already specified) -->
+				<xsl:copy-of select="*|comment() | $match/meta |$match/unit[not($this/unit)] | $match/unit[$this/unit and @version[.!=$this/unit/@version]] | $match/comment()[.!=$this/comment()]"/>				
+			</xsl:when>
+			<xsl:otherwise>
+
+				<!--  copy metas and comments in between meta. Do not try to merge metadata between models -->
+				<xsl:apply-templates select="meta | $match/meta | comment()[following-sibling::meta]" mode="merge-data">
+					<xsl:with-param name="metas" select="$match/meta"/>
+				</xsl:apply-templates>
+				<xsl:copy-of select=" $match/meta | $match/comment()[following-sibling::meta]"/>
+				
+				<xsl:apply-templates mode="merge-models">
+					<xsl:with-param name="other" select="$match"/>
+					<xsl:with-param name="up" select="$up"/>
+					<xsl:with-param name="down" select="$down"/>
+					<xsl:with-param name="replaces" select="$replaces"/>
+				</xsl:apply-templates>
+				<!--  don't copy if explicitly or implicitly placed already-->
+				<xsl:for-each select="$match/*[not(@before) and not(following-sibling::*[@id=$this/*/@id])]">
+					<xsl:if test="not($this/*[@id=current()/@id])">
+						<xsl:apply-templates mode="merge-copy-of" select=".">
+							<xsl:with-param name="origin" select="$down"/>
+							<xsl:with-param name="root" select="$this/ancestor::SystemDefinition"/>			
+							<xsl:with-param name="replaces" select="$replaces"/>
+						</xsl:apply-templates>
+					</xsl:if>
+				</xsl:for-each>
+			</xsl:otherwise>
+		</xsl:choose>
+	</xsl:copy>
+
+		</xsl:otherwise>
+	</xsl:choose>
+	
+	<xsl:if test="self::layer and not(following-sibling::layer)">	
+		<!-- for the last layer, tack on any remaining layers -->
+		<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)]">
+			<xsl:with-param name="origin" select="$down"/>
+			<xsl:with-param name="root" select="$this/ancestor::SystemDefinition"/>			
+			<xsl:with-param name="replaces" select="$replaces"/>
+		</xsl:apply-templates>		
+	</xsl:if>
+</xsl:template>
+
+
+
+<xsl:template match="*" mode="merge-copy-of">
+	<xsl:param name="remove-before" select="0"/> <!-- set to true if any before attribute is to be removed -->
+	<xsl:param name="origin"/>	<!--the element containing the @name to use the origin-model attribute  -->
+	<xsl:param name="root"/> 	<!--the systemModel element in the upstream doc  -->
+	<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 -->
+	<xsl:variable name="moved" select="$root/descendant::*[name()=name(current()/..) and @id!=current()/../@id]/*[@id=current()/@id]"/>
+	<xsl:choose>
+		<!-- this might slow things down, consider making optional -->
+		<xsl:when test="not(self::layer) and (count($moved) and not($moved[ancestor-or-self::*/@id=$replaces]) )">
+			<xsl:message>Warning: <xsl:value-of select="name()"/> "<xsl:value-of select="@id"/>" moved in downstream model. Ignoring moved <xsl:value-of select="name()"/>
+				<xsl:text>&#xa;</xsl:text>
+			</xsl:message>
+		</xsl:when>
+		<xsl:otherwise>
+			<!-- save all content in a variable to test to see if it's got any problems (ie been removed due to errors)-->
+			<xsl:variable name="content">
+				<xsl:apply-templates select="*|comment()" mode="merge-copy-of">
+					<xsl:with-param name="origin" select="$origin"/>
+					<xsl:with-param name="root" select="$root"/>
+					<xsl:with-param name="replaces" select="$replaces"/>
+				</xsl:apply-templates>
+			</xsl:variable>
+			<xsl:choose>
+				<!-- if all elements in this have been deleted, throw out this element -->
+				<xsl:when test="not(exslt:node-set($content)/*) and *">
+					<xsl:message>Warning: All content in downstream <xsl:value-of select="name()"/> "<xsl:value-of select="@id"/>" is invalid. Ignoring <xsl:value-of select="name()"/>
+						<xsl:text>&#xa;</xsl:text>
+					</xsl:message>
+				</xsl:when>
+				<xsl:otherwise>
+					<xsl:copy>
+						<xsl:call-template name="merge-copy-of-atts">
+							<xsl:with-param name="remove-before" select="$remove-before"/>
+							<xsl:with-param name="root" select="$root"/>
+						</xsl:call-template>
+						<xsl:copy-of select="exslt:node-set($content)"/>
+					</xsl:copy>
+				</xsl:otherwise>
+			</xsl:choose>					
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+<xsl:template match="comment()|@*" mode="merge-copy-of">
+	<xsl:copy-of select="."/>
+</xsl:template>
+
+
+<xsl:template name="merge-copy-of-atts">
+	<xsl:param name="remove-before" select="0"/> <!-- set to true if any before attribute is to be removed -->
+	<xsl:param name="root"/> 	<!--the systemModel element in the upstream doc  -->
+	
+	<xsl:choose>
+		<xsl:when test="$remove-before">
+			<xsl:copy-of select="@*[name()!='before' and name()!='replace']"/>
+		</xsl:when>
+		<xsl:otherwise><xsl:copy-of select="@*[name()!='replace']"/></xsl:otherwise>
+	</xsl:choose>
+	<xsl:if test="@replace and not($root/descendant::*[(self::component or self::collection or self::package or self::layer) and @id=current()/@replace])">
+		<!-- only include replace if it's not been used -->
+		<xsl:copy-of select="@replace"/>
+	</xsl:if>
+</xsl:template>
+
+<xsl:template match="component" mode="merge-copy-of">
+	<xsl:param name="remove-before" select="0"/> <!-- set to true if any before attribute is to be removed -->
+	<xsl:param name="origin"/>	<!--the element containing the @name to use the origin-model attribute  -->
+	<xsl:param name="root"/> 	<!--the systemModel element in the upstream doc  -->
+	<xsl:choose>
+		<!-- this might slow things down, consider making optional -->
+		<xsl:when test="$root/descendant::collection[@id!=current()/../@id]/component[@id=current()/@id]">
+			<xsl:message>Warning: <xsl:value-of select="name()"/> "<xsl:value-of select="@id"/>" moved in downstream model. Ignoring moved <xsl:value-of select="name()"/>
+				<xsl:text>&#xa;</xsl:text>
+			</xsl:message>
+		</xsl:when>
+		<xsl:otherwise>
+			<xsl:copy>
+				<xsl:call-template name="merge-copy-of-atts">
+					<xsl:with-param name="remove-before" select="$remove-before"/>
+					<xsl:with-param name="root" select="$root"/>
+				</xsl:call-template>
+				<xsl:if test="not(@origin-model) and $origin/@name">
+					<xsl:attribute name="origin-model">
+						<xsl:value-of select="$origin/@name"/>
+					</xsl:attribute>
+					<xsl:if test="not(@root)">
+						<xsl:copy-of select="$origin/@root"/>
+					</xsl:if>
+				</xsl:if>
+				<xsl:apply-templates select="*|comment()" mode="merge-copy-of">
+					<xsl:with-param name="origin" select="$origin"/>
+					<xsl:with-param name="root" select="$root"/>
+				</xsl:apply-templates>
+			</xsl:copy>
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+
+<xsl:template match="unit" mode="merge-copy-of">
+	<xsl:param name="origin"/>	<!--the element containing the @name to use the origin-model attribute  -->
+	<xsl:param name="root"/> 	<!--the systemModel element in the upstream doc  -->
+	<xsl:copy>
+				<xsl:apply-templates select="@*" mode="merge-copy-of">
+					<xsl:with-param name="origin" select="$origin"/>
+					<xsl:with-param name="root" select="$root"/>
+				</xsl:apply-templates>
+	</xsl:copy>
+</xsl:template>
+
+
+
+
+<xsl:template match="meta" mode="merge-copy-of">
+	<xsl:param name="origin"/>	<!--the element containing the @name to use the origin-model attribute  -->
+	<xsl:param name="root"/> 	<!--the systemModel element in the upstream doc  -->
+	<xsl:copy>
+		<xsl:apply-templates select="@*" mode="merge-copy-of">
+			<xsl:with-param name="origin" select="$origin"/>
+			<xsl:with-param name="root" select="$root"/>
+		</xsl:apply-templates>
+		<xsl:copy-of select="node()"/>
+	</xsl:copy>
+</xsl:template>
+
+
+<xsl:template match="unit/@bldFile | unit/@mrp | unit/@base | meta/@href" mode="merge-copy-of">
+	<xsl:param name="origin" select="/.."/>	<!--the element containing the @name to use the origin-model attribute  -->
+
+	<xsl:attribute name="{name()}">
+		<xsl:choose>
+			<xsl:when test="not($origin/@pathto)"><xsl:value-of select="."/></xsl:when>
+			<xsl:when test="(contains(.,'://') and not(contains(substring-before(.,'://'),'/'))) or starts-with(.,'/')"> <!-- absolute URI or absolute path-->
+				<xsl:value-of select="."/>
+			</xsl:when>
+			<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-->
+				<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>
+				<xsl:value-of select="."/>
+			</xsl:when>
+		<xsl:otherwise> <!-- relative link -->
+			<xsl:call-template name="joinpath">
+				<xsl:with-param name="file" select="$origin/@pathto"/>
+				<xsl:with-param name="rel" select="."/>
+			</xsl:call-template>
+		</xsl:otherwise>
+		</xsl:choose>
+	</xsl:attribute>
+</xsl:template>
+</xsl:stylesheet>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metatools/sysdeftools/lib/modelcheck.xsl	Wed Jul 28 13:20:46 2010 +0100
@@ -0,0 +1,74 @@
+<xsl:stylesheet  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+<!--Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+	All rights reserved.
+	This component and the accompanying materials are made available
+	under the terms of the License "Eclipse Public License v1.0"
+	which accompanies this distribution, and is available
+	at the URL "http://www.eclipse.org/legal/epl-v10.html".
+
+	Initial Contributors:
+	Nokia Corporation - initial contribution.
+	Contributors:
+	Description:
+	Validate a system definition file or files and output results in HTML
+-->
+	<xsl:output method="html"/>
+	<xsl:include href="test-model.xsl"/>
+	<xsl:param name="path-errors" select="/model/@path-errors='yes' "/>
+	 <!--1 - (optional) If present, it will check to see if unit paths follow the coding standards-->
+
+<xsl:template match="/model">
+	<html><head>
+		<title>Cross-Checking System Model</title>
+		<style>p {margin: 0px; padding: 0px} 
+			p.warn span {color: blue}
+			p.note span {color: green}
+			p.err span {font-weight: bold}
+			p.err {color: red; background: yellow}
+			p.note {font-size: 90%}
+			<xsl:if test="contains(concat(' ',normalize-space(/model/@supress-errors),' '),' note ')">
+				p.note {display: none}
+			</xsl:if>
+			<xsl:if test="contains(concat(' ',normalize-space(/model/@supress-errors),' '),' err ')">
+				p.err {display: none}
+			</xsl:if>
+			<xsl:if test="contains(concat(' ',normalize-space(/model/@supress-errors),' '),' warn ')">
+				p.warn {display: none}
+			</xsl:if>
+		</style>
+	</head><body>
+	<xsl:apply-templates select="." mode="check"/>
+	</body></html>
+</xsl:template>
+
+
+<xsl:template name="Section"><xsl:param name="text"/><xsl:param name="sub"/>
+<h2><xsl:value-of select="$text"/>
+<xsl:if test="$sub!=''"><xsl:text> </xsl:text> <small>(<xsl:value-of select="$sub"/>)</small></xsl:if></h2>
+</xsl:template>
+
+<xsl:template name="Note"><xsl:param name="text"/><xsl:param name="sub"/>
+<p class="note">
+	<span>Note:</span>
+	<xsl:text> </xsl:text>
+	<xsl:copy-of select="$text"/>
+<xsl:if test="$sub!=''"><xsl:text> </xsl:text> <small>(<xsl:value-of select="$sub"/>)</small></xsl:if></p>
+</xsl:template>
+
+<xsl:template name="Warning"><xsl:param name="text"/><xsl:param name="sub"/>
+<p class="warn">
+	<span>Warning:</span>
+	<xsl:text> </xsl:text>
+	<xsl:value-of select="$text"/>
+<xsl:if test="$sub!=''"><xsl:text> </xsl:text> <small>(<xsl:value-of select="$sub"/>)</small></xsl:if></p>
+</xsl:template>
+
+<xsl:template name="Error"><xsl:param name="text"/><xsl:param name="sub"/>
+<p class="err">
+	<span>Error:</span>
+	<xsl:text> </xsl:text>
+	<xsl:value-of select="$text"/>
+<xsl:if test="$sub!=''"><xsl:text> </xsl:text> <small>(<xsl:value-of select="$sub"/>)</small></xsl:if></p>
+</xsl:template>
+
+</xsl:stylesheet>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metatools/sysdeftools/lib/path-module.xsl	Wed Jul 28 13:20:46 2010 +0100
@@ -0,0 +1,110 @@
+<?xml version="1.0"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<!--Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+	All rights reserved.
+	This component and the accompanying materials are made available
+	under the terms of the License "Eclipse Public License v1.0"
+	which accompanies this distribution, and is available
+	at the URL "http://www.eclipse.org/legal/epl-v10.html".
+
+	Initial Contributors:
+	Nokia Corporation - initial contribution.
+	Contributors:
+	Description:
+	XSLT module which contains named templates which process file paths
+-->
+
+ <xsl:template name="lastbefore"><xsl:param name="string"/><xsl:param name="substr" select="'/'"/>
+        <xsl:if test="contains($string,$substr)">
+                <xsl:value-of select="substring-before($string,$substr)"/>
+                <xsl:if test="contains(substring-after($string,$substr),$substr)">
+	                <xsl:value-of select="$substr"/>
+	              </xsl:if>
+        <xsl:call-template name="lastbefore">
+                <xsl:with-param name="string" select="substring-after($string,$substr)"/>
+                <xsl:with-param name="substr" select="$substr"/>
+        </xsl:call-template>
+        </xsl:if>
+</xsl:template>
+
+ <xsl:template name="joinpath"><xsl:param name="file"/><xsl:param name="rel"/>
+	<xsl:choose>
+		<xsl:when test="(contains($rel,'://') and not(contains(substring-before($rel,'://'),'/'))) or starts-with($rel,'/')"> <!-- absolute URI or absolute path-->
+			<xsl:value-of select="$rel"/>
+		</xsl:when>
+		<xsl:otherwise> <!-- relative link -->
+			<xsl:call-template name="reducepath">
+				<xsl:with-param name="file">
+					<xsl:call-template name="lastbefore">
+						<xsl:with-param name="string" select="$file"/>
+					</xsl:call-template>
+					<xsl:text>/</xsl:text>
+					<xsl:value-of select="$rel"/>
+				</xsl:with-param>
+			</xsl:call-template>
+		</xsl:otherwise>
+	</xsl:choose>
+ </xsl:template>
+
+<xsl:template name="reducepath"><xsl:param name="file"/>
+	<xsl:call-template name="reducedotdotpath">
+    	<xsl:with-param name="file">
+			<xsl:call-template name="reducedotpath">
+		    	<xsl:with-param name="file" select="$file"/>
+		    </xsl:call-template>
+		</xsl:with-param>
+	</xsl:call-template>
+</xsl:template>
+
+<xsl:template name="reducedotdotpath"><xsl:param name="file"/>
+	<xsl:variable name="pre">
+		<xsl:call-template name="lastbefore">
+			    <xsl:with-param name="string" select="substring-before($file,'/../')"/>
+		</xsl:call-template>
+	</xsl:variable>
+	<xsl:choose>
+		<xsl:when test="starts-with($file,'../')">
+			<xsl:text>../</xsl:text>
+			<xsl:call-template name="reducedotdotpath">
+        		<xsl:with-param name="file" select="substring($file,4)"/>
+			</xsl:call-template>
+		</xsl:when>
+		<xsl:when test="contains($file,'/../') and $pre='' and not(starts-with($file,'/'))"> <!-- if file is a relative path and the dotdots go up to the top dir, don't start with a slash -->
+			<xsl:call-template name="reducepath">
+        		<xsl:with-param name="file" select="substring-after($file,'/../')"/>
+			</xsl:call-template>
+		</xsl:when>
+		<xsl:when test="contains($file,'/../')">
+			<xsl:call-template name="reducepath">
+        		<xsl:with-param name="file" select="concat($pre,'/',substring-after($file,'/../'))"/>
+			</xsl:call-template>
+		</xsl:when>
+		<xsl:otherwise><xsl:value-of select="$file"/></xsl:otherwise>
+	</xsl:choose>
+ </xsl:template>
+
+<xsl:template name="reducedotpath"><xsl:param name="file"/>
+	<xsl:choose>	
+		<xsl:when test="starts-with($file,'./')">
+			<xsl:call-template name="reducedotpath">
+        		<xsl:with-param name="file" select="substring($file,3)"/>
+			</xsl:call-template>
+		</xsl:when>
+
+		<xsl:when test="contains($file,'/./')">
+			<xsl:call-template name="reducepath">
+        		<xsl:with-param name="file">
+	                <xsl:value-of select="substring-before($file,'/./')"/>
+			        <xsl:text>/</xsl:text>
+					<xsl:value-of select="substring-after($file,'/./')"/>
+				</xsl:with-param>
+			</xsl:call-template>
+		</xsl:when>
+		<xsl:when test="substring($file,string-length($file) - 1) = '/.'">
+           <xsl:value-of select="substring($file,1,string-length($file) - 2)"/>
+		</xsl:when>
+		<xsl:otherwise><xsl:value-of select="$file"/></xsl:otherwise>
+	</xsl:choose>
+ </xsl:template>
+
+</xsl:stylesheet>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metatools/sysdeftools/lib/test-model.xsl	Wed Jul 28 13:20:46 2010 +0100
@@ -0,0 +1,578 @@
+<xsl:stylesheet  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+<!--Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+	All rights reserved.
+	This component and the accompanying materials are made available
+	under the terms of the License "Eclipse Public License v1.0"
+	which accompanies this distribution, and is available
+	at the URL "http://www.eclipse.org/legal/epl-v10.html".
+
+	Initial Contributors:
+	Nokia Corporation - initial contribution.
+	Contributors:
+	Description:
+	Module containing the validation logic for system definition 3.0.0 syntax
+-->
+	<xsl:key name="named" match="*[ancestor::systemModel]" use="@name"/>
+	<xsl:param name="Filename"/> <!--<Filename> - (optional) the full system model path to the current sysdef file. This is needed to determine non-standard path errors -->
+	<xsl:variable name="info" select="document(/model//info[@type='extra']/@href,/model)//c"/>
+
+	<xsl:variable name="all-ids">
+		<xsl:apply-templates select="document(/model/sysdef/@href)| SystemDefinition" mode="ids"/>
+	</xsl:variable>
+
+ 
+<xsl:template match="/model" priority="-1">
+	<xsl:apply-templates select="." mode="check"/>
+</xsl:template>
+
+<xsl:template match="/model" mode="check">
+	<xsl:for-each select="sysdef">
+		<xsl:apply-templates select="document (@href,. )/*">
+			<xsl:with-param name="filename">
+				<xsl:choose>
+					<xsl:when test="starts-with(current()/@href,current()/@rootpath)">
+						<xsl:value-of select="substring-after(current()/@href,current()/@rootpath)"/>
+					</xsl:when>
+					<xsl:otherwise>
+						<xsl:value-of select="@href"/>
+					</xsl:otherwise>
+				</xsl:choose>
+			 </xsl:with-param>
+		</xsl:apply-templates>
+	</xsl:for-each>
+
+
+
+<xsl:apply-templates mode="x-check" select="document (//info[@type='vp']/@href)/*">
+	<xsl:with-param name="sysdef" select="document (sysdef/@href)/*"/>
+</xsl:apply-templates>
+
+<xsl:apply-templates mode="x-check" select="document (//info[@type='build']/@href)/*">
+	<xsl:with-param name="sysdef" select="document (sysdef/@href)/*"/>
+</xsl:apply-templates>
+</xsl:template>
+
+<xsl:template match="/SystemDefinition[starts-with(@schema,'3.0.')]" mode="ids">
+	<xsl:for-each select="//*[@id and not(@href)]"><xsl:value-of select="concat(' ',@id,' ')"/></xsl:for-each>
+	<xsl:apply-templates select="document(//layer/@href | //package/@href | //collection/@href | //component/@href,.)/*" mode="ids"/>
+</xsl:template>
+
+<xsl:template match="/SystemDefinition[starts-with(@schema,'3.0.')and systemModel]" priority="2">
+	<xsl:param name="filename" select="$Filename"/>
+<xsl:call-template name="Section">
+	<xsl:with-param name="text">System Definition: <xsl:value-of select="*/@name"/></xsl:with-param>
+	<xsl:with-param name="sub"><xsl:value-of select="(string-length($all-ids) - string-length(translate($all-ids,' ',''))) div 2 "/> items</xsl:with-param>
+</xsl:call-template>
+	<xsl:apply-templates select="*">
+		<xsl:with-param name="filename" select="$filename"/>
+	</xsl:apply-templates>
+</xsl:template>
+
+<xsl:template match="/SystemDefinition[starts-with(@schema,'3.0.')] | systemModel">
+	<xsl:param name="filename"  select="$Filename"/>
+		
+<xsl:if test="//unit">
+<xsl:call-template name="Section">
+	<xsl:with-param name="text"><xsl:value-of select="translate(substring(name(*),1,1),'clp','CLP')"/><xsl:value-of select="substring(name(*),2)"/> Definition: <xsl:value-of select="*/@name"/></xsl:with-param>
+	<xsl:with-param name="sub"><xsl:value-of select="count(//unit)"/> unit<xsl:if test="count(//unit)!=1">s</xsl:if></xsl:with-param>
+</xsl:call-template>
+</xsl:if>
+<xsl:if test="self::systemModel and not(@name)">
+	<xsl:call-template name="Error"><xsl:with-param name="text">systemModel element should have a name</xsl:with-param></xsl:call-template>
+</xsl:if>
+	<xsl:apply-templates select="*">
+		<xsl:with-param name="filename" select="$filename"/>
+	</xsl:apply-templates>
+</xsl:template>
+
+
+<xsl:template match="@*" mode="valid">
+	<xsl:call-template name="Error"><xsl:with-param name="text">Attribute <xsl:value-of select="name()"/>="<xsl:value-of select="."/>" is not valid for <xsl:value-of select="name(..)"/></xsl:with-param></xsl:call-template>
+</xsl:template>
+
+<xsl:template match="@before|@id|package/@span|layer/@span|collection/@level|package/@level|package/@levels|layer/@levels" mode="valid"/> <!-- really should check syntax -->
+
+<xsl:template match="@name|@href|@filter|package/@version|unit/@version|unit/@prebuilt" mode="valid"/> 
+
+<xsl:template match="component/@introduced|component/@deprecated" mode="valid"/> 
+
+<xsl:template match="component/@origin-model" mode="valid"/>
+
+<xsl:template match="unit/@priority" mode="valid">
+	<xsl:call-template name="Note"><xsl:with-param name="text">Attribute <xsl:value-of select="name()"/> is deprecated</xsl:with-param></xsl:call-template>
+</xsl:template>
+
+
+<xsl:template match="@*[namespace-uri()!='']" mode="valid"> 
+	<xsl:call-template name="Note"><xsl:with-param name="text">Extension attribute <xsl:value-of select="local-name()"/>="<xsl:value-of select="."/>" in namespace <xsl:value-of select="namespace-uri()"/></xsl:with-param></xsl:call-template>
+</xsl:template>
+
+<xsl:template match="@*[namespace-uri()='http://www.nokia.com/qt' and local-name()='proFile']" mode="valid"/> 
+	
+
+<xsl:template match="@*[namespace-uri()='http://www.nokia.com/qt' and local-name()='qmakeArgs']" mode="valid"> 
+	<xsl:call-template name="Note"><xsl:with-param name="text">Should avoid using extension attribute <xsl:value-of select="local-name()"/>="<xsl:value-of select="."/>" in namespace <xsl:value-of select="namespace-uri()"/></xsl:with-param></xsl:call-template>
+</xsl:template>
+
+
+<xsl:template match="@replace" mode="valid">
+	<xsl:if test="/SystemDefinition[@schema='3.0.0']">
+		<xsl:call-template name="Error"><xsl:with-param name="text">Attribute <b><xsl:value-of select="name()"/></b>="<xsl:value-of select="."/>" not valid in schema <xsl:value-of select="/SystemDefinition/@schema"/>. Must use schema 3.0.1 or higher</xsl:with-param></xsl:call-template>
+	</xsl:if>
+</xsl:template>
+
+
+
+<xsl:template name="validate-class">
+	<ok>plugin</ok>
+	<ok>doc</ok>
+	<ok>tool</ok>
+	<ok>config</ok>
+	<ok>api</ok>
+	<w d="deprecated">test</w>
+</xsl:template>
+
+<xsl:template name="validate-purpose">
+	<ok>mandatory</ok>
+	<ok>optional</ok>
+	<ok>development</ok>
+</xsl:template>
+<xsl:template name="validate-target">
+	<ok>other</ok>
+	<ok>desktop</ok>
+	<ok>device</ok>
+</xsl:template>
+
+
+<xsl:template name="validate-tech-domain">
+	<ok>lo</ok>
+	<ok>hb</ok>
+	<ok>mm</ok>
+	<ok>ma</ok>
+	<ok>pr</ok>
+	<ok>vc</ok>
+	<ok>se</ok>
+	<ok>ui</ok>
+	<ok>dc</ok>
+	<ok>de</ok>
+	<ok>dm</ok>
+	<ok>rt</ok>
+	<ok>to</ok>
+	<w d="Non-standard">ocp</w>
+</xsl:template>
+
+<xsl:template match="component/@class" mode="valid">
+	<xsl:call-template name="checklist">
+		<xsl:with-param name="list" select="normalize-space(.)"/>
+		<xsl:with-param name="values" select="document('')/*/xsl:template[@name=concat('validate-',name(current()))]/*"/>
+	</xsl:call-template>
+</xsl:template> 
+
+<xsl:template name="checklist">
+	<xsl:param name="list" select="."/><xsl:param name="values"/><xsl:param name="sep" select="' '"/>
+	<xsl:variable name="item">
+		<xsl:choose>
+			<xsl:when test="contains($list,$sep)"><xsl:value-of select="substring-before($list,$sep)"/></xsl:when>
+			<xsl:otherwise><xsl:value-of select="$list"/></xsl:otherwise>
+		</xsl:choose>
+	</xsl:variable>
+	<xsl:variable name="v" select="$values[.=$item]"/>
+	<xsl:choose>
+		<xsl:when test="not($v)">
+			<xsl:call-template name="Error"><xsl:with-param name="text">Illegal <xsl:value-of select="name()"/> value <xsl:value-of select="name()"/>="<xsl:value-of select="."/>"</xsl:with-param></xsl:call-template>
+		</xsl:when> 
+		<xsl:when test="name($v)='ok'"/> 
+		<xsl:when test="name($v)='w'">
+			<xsl:call-template name="Warning"><xsl:with-param name="text"><xsl:value-of select="$v/@d"/> value in <xsl:value-of select="name()"/>="<xsl:value-of select="."/>"</xsl:with-param></xsl:call-template>
+		</xsl:when> 
+	</xsl:choose>	
+	<xsl:if test="contains($list,$sep)">
+		<xsl:call-template name="checklist">
+			<xsl:with-param name="list" select="substring-after($list,$sep)"/>
+			<xsl:with-param name="values" select="$values"/>
+			<xsl:with-param name="sep" select="$sep"/>			
+		</xsl:call-template>
+	</xsl:if>
+</xsl:template> 
+
+
+<xsl:template match="package/@tech-domain|component/@purpose|component/@target" mode="valid">
+	<xsl:variable name="v" select="document('')/*/xsl:template[@name=concat('validate-',name(current()))]/*[.=current()]"/>
+	<xsl:choose>
+		<xsl:when test="not($v)">
+			<xsl:call-template name="Error"><xsl:with-param name="text">Illegal <xsl:value-of select="name()"/> value <xsl:value-of select="name()"/>="<xsl:value-of select="."/>"</xsl:with-param></xsl:call-template>
+		</xsl:when> 
+		<xsl:when test="name($v)='ok'"/> 
+		<xsl:when test="name($v)='w'">
+			<xsl:call-template name="Warning"><xsl:with-param name="text"><xsl:value-of select="$v/@d"/> value in <xsl:value-of select="name()"/>="<xsl:value-of select="."/>"</xsl:with-param></xsl:call-template>
+		</xsl:when> 
+	</xsl:choose>
+</xsl:template> 
+
+
+
+
+
+<xsl:template match="*" priority="-2">
+	<xsl:call-template name="Error"><xsl:with-param name="text">Element "<xsl:value-of select="name()"/>" is not valid in the context of "<xsl:value-of select="name(..)"/>"</xsl:with-param></xsl:call-template>
+</xsl:template>
+
+<xsl:template match="component[not(parent::collection)] | collection[not(parent::package)] | package[not(parent::package or parent::layer or (parent::SystemDefinition and count(../*)=1))] | layer[not(parent::systemModel)] " priority="3">
+	<xsl:call-template name="Error"><xsl:with-param name="text"><xsl:value-of select="name()"/> "<xsl:value-of select="@id"/>" has invalid parent <xsl:value-of select="name(..)"/> "<xsl:value-of select="../@id"/>"</xsl:with-param></xsl:call-template>
+</xsl:template>
+
+<xsl:template match="layer | package | collection | component">
+	<xsl:param name="filename"/>
+
+<xsl:apply-templates select="@*" mode="valid"/>
+<xsl:apply-templates select="@id"/>
+<xsl:if test="self::component">
+	<xsl:choose>
+		<xsl:when test="count(unit[not(@filter | @version)]) = 0 "/>
+		<xsl:when test="count(unit[not(@version)]) &gt; 1 and @filter='s60'">
+			<xsl:call-template name="Warning"><xsl:with-param name="text">S60 Component "<xsl:value-of select="@id"/>" has <xsl:value-of select="count(unit)"/> units.</xsl:with-param></xsl:call-template>
+		</xsl:when>
+		<xsl:when test="count(unit[not(@version)]) &gt; 1">
+			<xsl:call-template name="Error"><xsl:with-param name="text">Component "<xsl:value-of select="@id"/>" has <xsl:value-of select="count(unit)"/> units.</xsl:with-param></xsl:call-template>
+		</xsl:when>
+	</xsl:choose>
+	<xsl:choose>
+		<xsl:when test="unit"/>
+		<xsl:when test="contains(comment(),'PLACEHOLDER=')"/>
+		<xsl:when test="comment()">
+			<xsl:call-template name="Note"><xsl:with-param name="text">Component "<xsl:value-of select="@name"/>" is empty.</xsl:with-param></xsl:call-template>
+		</xsl:when>
+		<xsl:when test="not(comment())">
+			<xsl:call-template name="Warning"><xsl:with-param name="text">Component "<xsl:value-of select="@name"/>" is empty and has no comment</xsl:with-param></xsl:call-template>
+		</xsl:when>
+	</xsl:choose>
+</xsl:if>
+<xsl:if test="@href">
+	<xsl:variable name="child" select="document(@href,.)/SystemDefinition"/>
+	<xsl:if test="@id!=$child/@id">
+		<xsl:call-template name="Error"><xsl:with-param name="text"><xsl:value-of select="name()"/> "<xsl:value-of select="@id"/>" must match ID in linked file "<xsl:value-of select="@href"/>"</xsl:with-param></xsl:call-template>
+	</xsl:if>
+	<xsl:if test="$child/@href">
+		<xsl:call-template name="Error"><xsl:with-param name="text">linked <xsl:value-of select="name()"/> "<xsl:value-of select="@id"/>" cannot be a link</xsl:with-param></xsl:call-template>
+	</xsl:if>
+	<xsl:for-each select="@*[name()!='id']">
+		<xsl:if test="$child/@*[name()=name(current())]">
+			<xsl:call-template name="Warning"><xsl:with-param name="text">linked <xsl:value-of select="name()"/> "<xsl:value-of select="@id"/>" has duplicate attribute to linking document. Duplicate ignored.</xsl:with-param></xsl:call-template>
+		</xsl:if>
+	</xsl:for-each>
+	<xsl:if test="*">
+		<xsl:call-template name="Error"><xsl:with-param name="text"><xsl:value-of select="name()"/> "<xsl:value-of select="@id"/>" cannot have both link and content. Content ignored.</xsl:with-param></xsl:call-template>
+	</xsl:if>
+</xsl:if>
+<xsl:if test="@href and name()!=name(document(@href,.)/SystemDefinition/*)">
+		<xsl:call-template name="Error"><xsl:with-param name="text"><xsl:value-of select="name()"/> "<xsl:value-of select="@id"/>" must match item in linked file "<xsl:value-of select="@href"/>"</xsl:with-param></xsl:call-template>
+</xsl:if>
+<xsl:if test="not(@href)">
+	<xsl:apply-templates select="*">
+		<xsl:with-param name="filename" select="$filename"/>
+	</xsl:apply-templates>
+</xsl:if>
+<xsl:if test="@href">
+	<xsl:apply-templates select="document(@href,.)/*">
+		<xsl:with-param name="filename">
+			<xsl:call-template name="normpath">
+				<xsl:with-param name="path">
+					<xsl:if test="not(starts-with(current()/@href,'/'))">
+						<xsl:call-template name="before">
+							<xsl:with-param name="text" select="$filename"/>
+						</xsl:call-template>
+					</xsl:if>
+					<xsl:value-of select="current()/@href"/>
+				 </xsl:with-param>
+			</xsl:call-template>
+		 </xsl:with-param>
+	</xsl:apply-templates>
+</xsl:if>
+</xsl:template>
+
+
+
+<xsl:template match="meta">	<xsl:param name="filename"/>
+	<xsl:apply-templates select="@*"/>
+</xsl:template>
+
+<xsl:template match="meta/@rel | meta/@type | meta/@href"/> <!-- anything is valid -->
+
+<xsl:template match="unit">	<xsl:param name="filename"/>
+	<xsl:apply-templates select="@*">
+		<xsl:with-param name="filename" select="$filename"/>
+	</xsl:apply-templates>
+</xsl:template>
+
+
+<xsl:template match="unit/@* | meta/@*" priority="-1">	
+	<xsl:apply-templates select="." mode="valid"/>
+</xsl:template>
+
+
+<xsl:template match="@id" mode="path">
+	<xsl:choose>
+		<xsl:when test="contains(.,':')"><xsl:value-of  select="substring-after(.,':')"/></xsl:when>
+		<xsl:otherwise><xsl:value-of  select="."/></xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+
+<xsl:template match="@id">
+<xsl:if test="contains(concat(' ',substring-after($all-ids,concat(' ',.,' '))),concat(' ',.,' '))">
+	<xsl:call-template name="Warning"><xsl:with-param name="text">Duplicate ID: <xsl:value-of select="name(..)"/> "<xsl:value-of select="."/>"</xsl:with-param></xsl:call-template>
+</xsl:if>
+
+<xsl:if test="contains(.,':') and not(ancestor::*/namespace::*[name()=substring-before(current(),':')])">
+	<xsl:call-template name="Error"><xsl:with-param name="text">Undefined namespace for ID "<xsl:value-of select="."/>"</xsl:with-param></xsl:call-template>
+</xsl:if>
+
+</xsl:template>
+
+
+<xsl:template mode="localid" match="*">
+	<xsl:choose>
+		<xsl:when test="contains(@id,':')">/<xsl:value-of select="substring-after(@id,':')"/></xsl:when>
+		<xsl:otherwise><xsl:value-of select="@id"/></xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+<xsl:template match="@bldFile|@mrp|@base"><xsl:param name="filename"/>
+<xsl:if test="substring(.,string-length(.))='/'">
+		<xsl:call-template name="Warning"><xsl:with-param name="text"><code><xsl:value-of select="name()"/></code> path "<xsl:value-of select="."/>" should not end in /</xsl:with-param></xsl:call-template>
+</xsl:if>
+<xsl:if test="contains(.,'\')">
+		<xsl:call-template name="Error"><xsl:with-param name="text"><code><xsl:value-of select="name()"/></code> path "<xsl:value-of select="."/>" must use only forward slashes</xsl:with-param></xsl:call-template>
+</xsl:if>
+
+<!-- this is a realtive path, so just check that it's the expected number of dirs down -->
+	<xsl:variable name="fullpath"><xsl:call-template name="normpath">
+				<xsl:with-param name="path">
+					<xsl:if test="not(starts-with(.,'/'))">
+						<xsl:call-template name="before">
+							<xsl:with-param name="text" select="$filename"/>
+						</xsl:call-template>
+					</xsl:if>
+					<xsl:value-of select="."/>
+				 </xsl:with-param>
+			</xsl:call-template>
+		</xsl:variable>
+		<xsl:variable name="path">
+			<xsl:choose>
+				<xsl:when test="not(contains($filename,':'))">/<xsl:for-each select="ancestor::*/@id"><xsl:apply-templates mode="path" select="."/>/</xsl:for-each></xsl:when>
+				<xsl:otherwise><xsl:for-each select="../../../@id|../../@id"><xsl:apply-templates mode="path" select="."/>/</xsl:for-each></xsl:otherwise>
+			</xsl:choose>
+		</xsl:variable>
+		<xsl:variable name="segment"> <!-- the part relative to the fragment directory -->
+			<xsl:choose>
+				<xsl:when test="ancestor::layer">
+					<xsl:apply-templates select="ancestor::package" mode="localid"/>/<xsl:apply-templates select="ancestor::collection" mode="localid"/>
+				</xsl:when>
+				<xsl:when test="ancestor::package">
+				<xsl:apply-templates select="ancestor::collection" mode="localid"/>
+				</xsl:when>
+				<xsl:when test="ancestor::collection"/>
+			</xsl:choose>/<xsl:apply-templates select="ancestor::component" mode="localid"/>/</xsl:variable>
+		<xsl:choose>
+			<xsl:when test="not(starts-with(concat(.,'/'),$segment) or starts-with(concat('/',.,'/'),$segment)) and $path-errors">
+				<xsl:call-template name="Note"><xsl:with-param name="text">Unexpected <code><xsl:value-of select="name()"/></code> path for <xsl:apply-templates mode="path" select="../../../@id"/> -&gt; <strong><xsl:apply-templates mode="path" select="../../@id"/></strong>: "<xsl:value-of select="$fullpath"/>"</xsl:with-param></xsl:call-template>
+			</xsl:when>
+		</xsl:choose>
+</xsl:template>
+
+
+<xsl:template match="@bldFile[starts-with(.,'/') or contains(.,'../') or contains(.,':')] | @mrp[starts-with(.,'/') or contains(.,'../') or contains(.,':')] |@base[starts-with(.,'/') or contains(.,'../') or contains(.,':')]"><xsl:param name="filename"/>
+<xsl:if test="substring(.,string-length(.))='/'">
+		<xsl:call-template name="Warning"><xsl:with-param name="text"><code><xsl:value-of select="name()"/></code> path "<xsl:value-of select="."/>" should not end in /</xsl:with-param></xsl:call-template>
+</xsl:if>
+<xsl:if test="contains(.,'\')">
+		<xsl:call-template name="Error"><xsl:with-param name="text"><code><xsl:value-of select="name()"/></code> path "<xsl:value-of select="."/>" must use only forward slashes</xsl:with-param></xsl:call-template>
+</xsl:if>
+	<xsl:variable name="fullpath"><xsl:call-template name="normpath">
+				<xsl:with-param name="path">
+					<xsl:if test="not(starts-with(.,'/'))">
+						<xsl:call-template name="before">
+							<xsl:with-param name="text" select="$filename"/>
+						</xsl:call-template>
+					</xsl:if>
+					<xsl:value-of select="."/>
+				 </xsl:with-param>
+			</xsl:call-template>
+		</xsl:variable>
+		<xsl:variable name="path">
+			<xsl:choose>
+				<xsl:when test="not(contains($filename,':'))">/<xsl:for-each select="ancestor::*/@id"><xsl:apply-templates mode="path" select="."/>/</xsl:for-each></xsl:when>
+				<xsl:otherwise><xsl:for-each select="../../../@id|../../@id"><xsl:apply-templates mode="path" select="."/>/</xsl:for-each></xsl:otherwise>
+			</xsl:choose>
+		</xsl:variable>
+		<xsl:variable name="segment">
+			<xsl:choose>
+				<xsl:when test="ancestor::layer">
+					<xsl:value-of select="concat($fullpath,'/')"/>
+				</xsl:when>
+				<xsl:when test="ancestor::package">
+					<xsl:value-of select="concat('/',substring-after(substring-after($fullpath,'/'),'/'),'/')"/>
+				</xsl:when>
+				<xsl:when test="ancestor::collection">
+					<xsl:value-of select="concat('/',substring-after(substring-after(substring-after($fullpath,'/'),'/'),'/'),'/')"/>
+				</xsl:when>
+				<xsl:otherwise>
+					<xsl:value-of select="concat('/',substring-after(substring-after(substring-after(substring-after($fullpath,'/'),'/'),'/'),'/'),'/')"/>
+				</xsl:otherwise>
+			</xsl:choose>
+		</xsl:variable>
+<xsl:choose>
+	<xsl:when test="contains($filename,':')">
+		<xsl:choose>
+			<xsl:when test="not(starts-with(.,$path) or concat(.,'/')=$path) and $path-errors">
+				<xsl:call-template name="Note"><xsl:with-param name="text">Unexpected <code><xsl:value-of select="name()"/></code> path for <xsl:apply-templates mode="path" select="../../../@id"/> -&gt; <strong><xsl:apply-templates mode="path" select="../../@id"/></strong>: "<xsl:value-of select="."/>"</xsl:with-param></xsl:call-template>
+			</xsl:when>
+		</xsl:choose>
+	</xsl:when>
+	<xsl:otherwise>
+		<xsl:choose>
+			<xsl:when test="not($path-errors)"/>
+			<xsl:when test="substring-before(substring($segment,2),'/') != substring-before(substring($path,2),'/') and (ancestor::SystemDefinition/@id-namespace!='http://www.symbian.org/system-definition' and not(contains(../../@id,':')))">
+				<xsl:call-template name="Warning"><xsl:with-param name="text">Unexpected <code><xsl:value-of select="name()"/></code> path for <xsl:apply-templates mode="path" select="../../../@id"/> -&gt; <strong><xsl:apply-templates mode="path" select="../../@id"/></strong>: "<xsl:value-of select="$fullpath"/>"</xsl:with-param></xsl:call-template>
+			</xsl:when>
+			<xsl:when test="substring-before(substring($segment,2),'/') != substring-before(substring($path,2),'/')">
+				<xsl:call-template name="Error"><xsl:with-param name="text">Unexpected <code><xsl:value-of select="name()"/></code> path for <xsl:apply-templates mode="path" select="../../../@id"/> -&gt; <strong><xsl:apply-templates mode="path" select="../../@id"/></strong>: "<xsl:value-of select="$fullpath"/>"</xsl:with-param></xsl:call-template>
+			</xsl:when>
+			<xsl:when test="not(starts-with($segment,$path))">
+				<xsl:call-template name="Note"><xsl:with-param name="text">Unexpected <code><xsl:value-of select="name()"/></code> path for <xsl:apply-templates mode="path" select="../../../@id"/> -&gt; <strong><xsl:apply-templates mode="path" select="../../@id"/></strong>: "<xsl:value-of select="$fullpath"/>"</xsl:with-param></xsl:call-template>
+			</xsl:when>
+		</xsl:choose>
+	</xsl:otherwise>
+</xsl:choose>
+</xsl:template>
+
+<xsl:template match="SystemDefinition" mode="check-matches">
+	<xsl:param name="which"/>
+	<xsl:param name="other"/>
+	<xsl:for-each select="//*[@mrp]">
+		<xsl:variable name="mrp" select="@mrp"/>
+		<xsl:if test="not($other//*[@mrp=$mrp])">
+			<xsl:call-template name="Error"><xsl:with-param name="text"><xsl:value-of select="$mrp"/> has no match in <xsl:value-of select="$which"/>.</xsl:with-param></xsl:call-template>
+		</xsl:if>
+	</xsl:for-each>
+</xsl:template>
+
+<xsl:template match="*" mode="value">
+	<xsl:call-template name="Error"><xsl:with-param name="text">
+		<xsl:value-of select="name()"/>:<xsl:for-each select="@*"><xsl:value-of select="concat(name(),'=',.)"/></xsl:for-each>
+	</xsl:with-param></xsl:call-template>
+</xsl:template>
+
+<xsl:template match="*" mode="compare"><xsl:param name="base"/>
+<xsl:variable name="n" select="@id"/>
+<xsl:variable name="tag" select="name()"/>
+<xsl:variable name="v"><xsl:apply-templates select="." mode="value"/></xsl:variable>
+<xsl:variable name="v2"><xsl:apply-templates mode="value" select="$base//*[name()=$tag and @id=$n]"/></xsl:variable>
+<xsl:if  test="$v != $v2">
+	<xsl:call-template name="Error"><xsl:with-param name="text">
+		<xsl:value-of select="concat(name(),' ',@name)"/> not identical. [<xsl:value-of select="$v"/>|<xsl:value-of select="$v2"/>]</xsl:with-param></xsl:call-template>
+</xsl:if>	
+</xsl:template>
+
+
+
+<xsl:template match="unit" mode="compare" priority="1"><xsl:param name="base"/>
+<xsl:variable name="n" select="concat(@version,':',@mrp,'.',@prebuilt)"/>
+<xsl:variable name="v"><xsl:apply-templates select="." mode="value"/></xsl:variable>
+<xsl:variable name="v2"><xsl:apply-templates mode="value" select="$base//unit[concat(@version,':',@mrp,'.',@prebuilt)=$n]"/></xsl:variable>
+<xsl:if  test="$v != $v2">
+	<xsl:call-template name="Error"><xsl:with-param name="text">
+		<xsl:value-of select="concat('&#xa;',name(),' ',../@name,' v',@version)"/> not identical. [<xsl:value-of select="$v"/>|<xsl:value-of select="$v2"/>]</xsl:with-param></xsl:call-template>
+</xsl:if>
+</xsl:template>
+
+<xsl:template match="/variations/@module"> (<xsl:value-of select="."/>)</xsl:template>
+
+<xsl:template match="/variations" mode="x-check"><xsl:param name="sysdef"/>
+<xsl:call-template name="Section"><xsl:with-param name="text">vp cross-check <xsl:apply-templates select="@module"/></xsl:with-param></xsl:call-template>
+<xsl:for-each select="//component">
+	<xsl:variable name="found">
+		<xsl:apply-templates select="$sysdef" mode="lookfor">
+			<xsl:with-param name="id" select="@name"/>
+			<xsl:with-param name="version" select="@version"/>
+		</xsl:apply-templates>
+	</xsl:variable>
+	<xsl:if test="$found=''">
+		<xsl:call-template name="Error"><xsl:with-param name="text">VP component "<xsl:value-of select="@name"/>"<xsl:if test="@version"> v<xsl:value-of select="@version"/></xsl:if> not in SysDef</xsl:with-param></xsl:call-template>
+	</xsl:if>
+</xsl:for-each>
+</xsl:template>
+
+<xsl:template match="*" mode="lookfor"><xsl:param name="id"/><xsl:param name="version"/>
+	<xsl:choose>
+		<xsl:when test="string-length($version) and //component[@id=$id and unit[@version=$version]]">Found</xsl:when>
+		<xsl:when test="string-length($version)=0 and //*[@id=$id]">Found</xsl:when>
+		<xsl:otherwise>
+			<xsl:apply-templates select="document(//layer/@href | //package/@href | //collection/@href | //component/@href,.)/*/*" mode="lookfor">
+				<xsl:with-param name="version" select="$version"/>
+				<xsl:with-param name="id" select="$id"/>
+			</xsl:apply-templates>
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+
+
+<xsl:template match="SystemBuild" mode="x-check"><xsl:param name="sysdef"/>
+
+<xsl:call-template name="Section"><xsl:with-param name="text">System Build cross-check</xsl:with-param></xsl:call-template>
+<xsl:for-each select="//ref">
+	<xsl:variable name="found">
+		<xsl:apply-templates select="$sysdef" mode="lookfor">
+		<xsl:with-param name="id" select="current()/@item"/>
+	</xsl:apply-templates>
+</xsl:variable>
+	<xsl:if test="$found=''">
+		<xsl:call-template name="Error"><xsl:with-param name="text">Build item "<xsl:value-of select="@item"/>" not in SysDef</xsl:with-param></xsl:call-template>
+</xsl:if>
+</xsl:for-each>
+
+<xsl:for-each select="//listRef">
+	<xsl:if test="not(//list[@name=current()/@list])">
+		<xsl:call-template name="Error"><xsl:with-param name="text">Build list "<xsl:value-of select="@name"/>" not defined</xsl:with-param></xsl:call-template>
+</xsl:if>	
+</xsl:for-each>
+</xsl:template>
+
+
+<xsl:template name="my-release">
+	<xsl:variable name="n" select="@name"/>
+	<xsl:variable name="new" select="@introduced"/>
+	<xsl:variable name="end" select="@deprecated"/>
+	<xsl:choose>
+		<xsl:when test="$new!='' and $end!=''">(<xsl:value-of select="concat($new,' - ',$end)"/>)</xsl:when>
+		<xsl:when test="$new!='' ">(<xsl:value-of select="$new"/>)</xsl:when>
+		<xsl:when test="$end!=''">(? - <xsl:value-of select="$end"/>)</xsl:when>
+	</xsl:choose>
+</xsl:template>
+
+<xsl:template name="normpath"><xsl:param name="path"/>
+<!-- normalize out any ".." in the path in $path  -->
+<xsl:choose>
+	<xsl:when test="contains($path,'/../')">
+	<xsl:call-template name="normpath">
+		<xsl:with-param name="path">
+		<xsl:call-template name="before">
+			<xsl:with-param name="text" select="substring-before($path,'/../')"/>
+		</xsl:call-template>
+		<xsl:value-of select="substring-after($path,'/../')"/>
+		</xsl:with-param>
+		</xsl:call-template>
+	</xsl:when>
+	<xsl:otherwise><xsl:value-of select="$path"/></xsl:otherwise>
+</xsl:choose>
+</xsl:template>
+
+<!-- return all text before the last / -->
+<xsl:template name="before"><xsl:param name="text"/>
+<xsl:if test="contains($text,'/')">
+	<xsl:value-of select="substring-before($text,'/')"/>/<xsl:call-template name="before"><xsl:with-param name="text" select="substring-after($text,'/')"/></xsl:call-template>
+	</xsl:if>
+</xsl:template>
+
+
+</xsl:stylesheet>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metatools/sysdeftools/lib/usage.xsl	Wed Jul 28 13:20:46 2010 +0100
@@ -0,0 +1,135 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output method="text"/>
+<xsl:param name="usage"/>
+
+<xsl:template match="node()|@*"><xsl:copy-of select="."/></xsl:template>
+<xsl:template match="/*">
+	<xsl:apply-templates select="." mode="desc"/>
+
+	<xsl:variable name="in">
+		<xsl:call-template name="input"/>
+	</xsl:variable>
+	<xsl:variable name="out">
+		<xsl:call-template name="output"/>
+	</xsl:variable>
+
+	<xsl:if test="$usage != ''">
+		<xsl:text>&#xa;usage: </xsl:text><xsl:value-of select="$usage"/>
+	</xsl:if>
+	<xsl:if test="$usage != '' and contains($out,'&gt;')"> [<xsl:value-of select="substring-before($out,'&gt;')"/>&gt;]  [params ...] <xsl:value-of select="substring-before($in,'&gt;')"/>&gt;</xsl:if>
+		<xsl:choose>
+			<xsl:when test="system-property('xsl:vendor-url') = 'http://xml.apache.org/xalan-c' ">
+The input file must be last. Other arguments can be in any order. 
+Parameters are case-sensitive. Text parameter values must be in single quotes.
+</xsl:when>
+			<xsl:when test="system-property('xsl:vendor-url') = 'http://xml.apache.org/xalan-j' ">
+Arguments can be in any order. 
+Parameters are case-sensitive.
+</xsl:when>
+			<xsl:when test="system-property('xsl:vendor-url') = 'http://xmlsoft.org/XSLT/' ">
+The input file must be last. Other arguments can be in any order. 
+Parameters are case-sensitive.
+</xsl:when>
+		</xsl:choose>
+
+	<xsl:text>&#xa;&#9;</xsl:text>
+		<xsl:call-template name="input"/>
+	<xsl:text>&#xa;&#9;</xsl:text>
+		<xsl:call-template name="output"/>
+	<xsl:apply-templates select="." mode="params"/>
+</xsl:template>
+
+
+<xsl:template match="/*" mode="desc">
+	<xsl:value-of select="substring-after(comment()[starts-with(.,'Description:')],':')"/>
+	<xsl:apply-templates select="document(xsl:import/@href | xsl:include/@href,.)/*" mode="desc"/>
+</xsl:template>
+
+<xsl:template match="/*" mode="params">
+	<xsl:for-each select="xsl:param">
+		<xsl:text>&#xa;&#9;</xsl:text>
+		<xsl:choose>
+			<xsl:when test="system-property('xsl:vendor-url') = 'http://xml.apache.org/xalan-c' ">
+				<xsl:text>-p </xsl:text>			
+			</xsl:when>
+			<xsl:when test="system-property('xsl:vendor-url') = 'http://xml.apache.org/xalan-j' ">
+				<xsl:text>-param </xsl:text>			
+			</xsl:when>
+			<xsl:when test="system-property('xsl:vendor-url') = 'http://xmlsoft.org/XSLT/' ">
+				<xsl:text>--string-param </xsl:text>			
+			</xsl:when>
+		</xsl:choose>
+		<xsl:value-of select="concat(@name,' ')"/>
+		<xsl:for-each select="following-sibling::node()[self::* or self::comment()][1]">
+			<xsl:if test="self::comment()">
+			<xsl:value-of select="."/>
+			</xsl:if>
+		</xsl:for-each>
+		<xsl:text>&#xa;</xsl:text>
+		<xsl:if test="not(*) and normalize-space(.)!='' ">&#9;&#9;Defaults to <xsl:choose>
+			<xsl:when test="system-property('xsl:vendor-url') = 'http://xml.apache.org/xalan-c' ">'<xsl:value-of select="."/>'</xsl:when>
+			<xsl:when test="system-property('xsl:vendor-url') = 'http://xml.apache.org/xalan-j' ">"<xsl:value-of select="."/>"</xsl:when>
+			<xsl:when test="system-property('xsl:vendor-url') = 'http://xmlsoft.org/XSLT/' ">"<xsl:value-of select="."/>"</xsl:when>
+		</xsl:choose></xsl:if>
+	</xsl:for-each>
+	<xsl:apply-templates select="document(xsl:import/@href | xsl:include/@href,.)/*" mode="params"/>
+</xsl:template>
+
+
+<xsl:template name="string"><xsl:param name="look">Description</xsl:param>
+	<xsl:variable name="s">
+		<xsl:value-of select="substring-after(comment()[starts-with(.,concat($look,':'))],':')"/>
+	</xsl:variable>
+	<xsl:choose>
+		<xsl:when test="$s != ''"><xsl:value-of select="$s"/></xsl:when>
+		<xsl:otherwise>
+			<xsl:for-each select="document(xsl:import/@href | xsl:include/@href,.)/*">
+				<xsl:call-template name="string">
+					<xsl:with-param name="look" select="$look"/>
+				</xsl:call-template>
+			</xsl:for-each>
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+<xsl:template name="input">
+	<xsl:variable name="p">
+		<xsl:call-template name="string">
+			<xsl:with-param name="look" select="'Input'"/>
+		</xsl:call-template>
+	</xsl:variable>
+		<xsl:choose>
+			<xsl:when test="system-property('xsl:vendor-url') = 'http://xml.apache.org/xalan-c' "/>
+			<xsl:when test="system-property('xsl:vendor-url') = 'http://xmlsoft.org/XSLT/' "/>
+			<xsl:when test="system-property('xsl:vendor-url') = 'http://xml.apache.org/xalan-j' ">
+				<xsl:text>-in </xsl:text>			
+			</xsl:when>
+		</xsl:choose>
+	<xsl:if test="$p =''  ">&lt;xml&gt; - (required) The input XML file</xsl:if>
+	<xsl:if test="$p !=''  "><xsl:value-of select="$p"/></xsl:if>
+	<xsl:text>&#xa;</xsl:text>
+</xsl:template>
+
+<xsl:template name="output">
+	<xsl:variable name="p">
+		<xsl:call-template name="string">
+			<xsl:with-param name="look" select="'Output'"/>
+		</xsl:call-template>
+	</xsl:variable>
+	<xsl:choose>
+		<xsl:when test="system-property('xsl:vendor-url') = 'http://xml.apache.org/xalan-c' ">
+			<xsl:text>-o </xsl:text>			
+		</xsl:when>
+		<xsl:when test="system-property('xsl:vendor-url') = 'http://xml.apache.org/xalan-j' ">
+			<xsl:text>-out </xsl:text>			
+		</xsl:when>
+		<xsl:when test="system-property('xsl:vendor-url') = 'http://xmlsoft.org/XSLT/' ">
+			<xsl:text>-o </xsl:text>			
+		</xsl:when>
+	</xsl:choose>
+	<xsl:if test="$p =''  ">&lt;file&gt; - (optional) The <xsl:value-of select="xsl:output/@method"/> file to save the output as. If not present it will write to stdout.</xsl:if>
+	<xsl:if test="$p !=''  "><xsl:value-of select="$p"/></xsl:if>
+	<xsl:text>&#xa;</xsl:text>
+</xsl:template>
+
+</xsl:stylesheet>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metatools/sysdeftools/mergesysdef.bat	Wed Jul 28 13:20:46 2010 +0100
@@ -0,0 +1,21 @@
+@rem Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+@rem All rights reserved.
+@rem This component and the accompanying materials are made available
+@rem under the terms of the License "Eclipse Public License v1.0"
+@rem which accompanies this distribution, and is available
+@rem at the URL "http://www.eclipse.org/legal/epl-v10.html".
+@rem
+@rem Initial Contributors:
+@rem Nokia Corporation - initial contribution.
+@rem
+@rem Contributors:
+@rem
+@rem Description: 
+@rem
+@setlocal
+@if .%1==. goto use
+@ java -jar %~dp0xalanj\xalan.jar -xsl %~dpn0.xsl %*  -XSLTC
+@goto end
+:use
+@ java -jar %~dp0xalanj\xalan.jar -in %~dpn0.xsl -xsl %~dp0lib\usage.xsl -param usage "%~n0"
+:end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metatools/sysdeftools/mergesysdef.xsl	Wed Jul 28 13:20:46 2010 +0100
@@ -0,0 +1,142 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common" exclude-result-prefixes="exslt">
+<!--Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+	All rights reserved.
+	This component and the accompanying materials are made available
+	under the terms of the License "Eclipse Public License v1.0"
+	which accompanies this distribution, and is available
+	at the URL "http://www.eclipse.org/legal/epl-v10.html".
+
+	Initial Contributors:
+	Nokia Corporation - initial contribution.
+	Contributors:
+	Description:
+	Merge two 3.x syntax system definitions
+-->
+
+<!--Description:This merges two 3.x syntax system definitions.
+It can process two standalone sysdefs or two sysdef fragments which describe
+the same system model item.
+If the sysdefs are not the same schema, the output will use the highest schema
+value of the two.
+-->
+<!--Input:<sysdef> - (required) The system definition XML file to process in the 3.0 format, and can be a fragment or stand-alone.
+	If a fragment, this must be the same rank as the Downstream sysdef-->
+<!--Output:<sysdef> - (optional) The system definition XML file to save the output as. If not present it will write to stdout.-->
+
+	<xsl:output method="xml" indent="yes"/>
+	<xsl:param name="Downstream">mcl/System_Definition_Template.xml</xsl:param> <!-- <sysdef> - (required) The path to the downstream systef relative to the upstream one (ie the -in sysdef). -->
+	<xsl:key name="origin" match="component" use="@origin-model"/>
+
+<xsl:variable name="downstream" select="document($Downstream,.)/SystemDefinition"/>
+<xsl:param name="upname">
+	<xsl:choose>
+		<xsl:when test="$downstream[starts-with(@schema,'2.') or starts-with(@schema,'1.')]">
+			<xsl:message terminate="yes">Syntax <xsl:value-of select="@schema"/> not supported</xsl:message>
+		</xsl:when>
+		<xsl:when test="name($downstream/*)!=name(/SystemDefinition/*)">
+			<xsl:message terminate="yes">Can only merge fragments of the same rank</xsl:message>
+		</xsl:when>
+<!--		<xsl:when test="$downstream[not(systemModel)]">
+			<xsl:message terminate="yes">Needs to be a standalone system definition</xsl:message>
+		</xsl:when>-->
+		<xsl:when test="/SystemDefinition/systemModel/@name=$downstream/systemModel/@name or not(/SystemDefinition/systemModel/@name)">
+			<xsl:apply-templates mode="origin-term" select="/*">
+				<xsl:with-param name="root">Upstream</xsl:with-param>
+			</xsl:apply-templates>
+			</xsl:when>
+		<xsl:otherwise><xsl:value-of select="/SystemDefinition/systemModel/@name"/></xsl:otherwise>
+	</xsl:choose>
+</xsl:param>
+<!-- [name] - (optional) The name used in the origin-model attribute of any component that comes from the upstream sysdef. Defaults to the name attribute on the systemModel element, or "Upstream"-->
+
+<xsl:param name="downname">
+	<xsl:choose>
+		<xsl:when test="/SystemDefinition/systemModel/@name=$downstream/systemModel/@name or not($downstream/systemModel/@name)">
+			<xsl:apply-templates mode="origin-term" select="$downstream">	
+				<xsl:with-param name="root">Downstream</xsl:with-param>
+			</xsl:apply-templates>
+			</xsl:when>
+		<xsl:when test="name($downstream/*)!=name(/SystemDefinition/*)">
+			<xsl:message terminate="yes">Can only merge fragments of the same rank</xsl:message>
+		</xsl:when>
+		<xsl:otherwise><xsl:value-of select="$downstream/systemModel/@name"/></xsl:otherwise>
+	</xsl:choose>
+</xsl:param>
+<!-- [name] - (optional) The name used in the origin-model attribute of any component that comes from the downstream sysdef. Defaults to the name attribute on the systemModel element, or "Downstream"-->
+
+<xsl:template mode="origin-term" match="*">
+	<xsl:param name="root"/>
+	<xsl:param name="index"/>
+	<xsl:choose>
+		<xsl:when test="not(key('origin',concat($root,$index)))">
+			<xsl:value-of select="concat($root,$index)"/>
+		</xsl:when>
+		<xsl:when test="$index=''">
+			<xsl:apply-templates mode="origin-term" select=".">	
+				<xsl:with-param name="root" select="$root"/>
+				<xsl:with-param name="index" select="1"/>
+			</xsl:apply-templates>
+		</xsl:when>
+		<xsl:otherwise>
+			<xsl:apply-templates mode="origin-term" select=".">	
+				<xsl:with-param name="root" select="$root"/>
+				<xsl:with-param name="index" select="$index + 1"/>
+			</xsl:apply-templates>		
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+
+<!-- choose the greater of the two versions -->
+<xsl:template name="compare-versions"><xsl:param name="v1"/><xsl:param name="v2"/>
+			<xsl:choose>
+				<xsl:when test="$v1=$v2"><xsl:value-of select="$v1"/></xsl:when>
+				<xsl:when test="substring-before($v1,'.') &gt; substring-before($v2,'.')"><xsl:value-of select="$v1"/></xsl:when>
+				<xsl:when test="substring-before($v1,'.') &lt; substring-before($v2,'.')"><xsl:value-of select="$v2"/></xsl:when>
+				<xsl:when test="substring-before(substring-after($v1,'.'),'.') &gt; substring-before(substring-after($v2,'.'),'.')"><xsl:value-of select="$v1"/></xsl:when>
+				<xsl:when test="substring-before(substring-after($v1,'.'),'.') &lt; substring-before(substring-after($v2,'.'),'.')"><xsl:value-of select="$v2"/></xsl:when>
+				<xsl:when test="substring-after(substring-after($v1,'.'),'.') &gt; substring-after(substring-after($v2,'.'),'.')"><xsl:value-of select="$v1"/></xsl:when>
+				<xsl:when test="substring-after(substring-after($v1,'.'),'.') &lt; substring-after(substring-after($v2,'.'),'.')"><xsl:value-of select="$v2"/></xsl:when>
+				<xsl:otherwise><xsl:value-of select="$v1"/></xsl:otherwise>
+			</xsl:choose>
+</xsl:template>
+
+<!--  this merge only two files according to the 3.0.x rules. Old syntax not supported. Must be converetd before calling -->
+
+
+
+<xsl:template match="/*">
+	<xsl:variable name="upmodel">
+		<sysdef name="{$upname}"/>
+	</xsl:variable>
+	<xsl:variable name="downmodel">
+		<sysdef name="{$downname}" pathto="{$Downstream}"/>
+	</xsl:variable>
+	
+	<xsl:choose>
+		<xsl:when test="function-available('exslt:node-set')">
+			<xsl:apply-templates mode="merge-models" select=".">
+				<xsl:with-param name="other" select="$downstream"/>
+				<xsl:with-param name="up" select="exslt:node-set($upmodel)/sysdef"/>
+				<xsl:with-param name="down" select="exslt:node-set($downmodel)/sysdef"/>
+			</xsl:apply-templates>
+		</xsl:when>
+		<xsl:otherwise> <!-- no node set funcion, so don't bother setting the names -->
+			<xsl:apply-templates mode="merge-models" select=".">
+				<xsl:with-param name="other" select="$downstream"/>
+			</xsl:apply-templates> 		
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+<xsl:include href="lib/path-module.xsl"/>
+<xsl:include href="lib/mergesysdef-module.xsl"/>
+
+<xsl:template match="@*[local-name()='proFile' or local-name()='qmakeArgs'  or namespace-uri()='qt']" mode="merge-copy-of">
+	<!-- this fixes a xalan-j bug where it changes the namespace in the merged model to just "qt"-->
+	<xsl:attribute name="{local-name()}" namespace="http://www.nokia.com/qt">
+		<xsl:value-of select="."/>
+	</xsl:attribute>
+</xsl:template>
+
+</xsl:stylesheet>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metatools/sysdeftools/rootsysdef.bat	Wed Jul 28 13:20:46 2010 +0100
@@ -0,0 +1,17 @@
+@rem Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+@rem All rights reserved.
+@rem This component and the accompanying materials are made available
+@rem under the terms of the License "Eclipse Public License v1.0"
+@rem which accompanies this distribution, and is available
+@rem at the URL "http://www.eclipse.org/legal/epl-v10.html".
+@rem
+@rem Initial Contributors:
+@rem Nokia Corporation - initial contribution.
+@rem
+@rem Contributors:
+@rem
+@rem Description: 
+@rem
+@setlocal
+@perl %~dpn0.pl %*
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metatools/sysdeftools/rootsysdef.pl	Wed Jul 28 13:20:46 2010 +0100
@@ -0,0 +1,809 @@
+# Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "Eclipse Public License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+#
+# Initial Contributors:
+# Nokia Corporation - initial contribution.
+#
+# Contributors:
+#
+# Description:
+#  This will create a new root system definition file based on the provided template
+#!/usr/bin/perl
+
+use strict;
+
+
+use FindBin;		# for FindBin::Bin
+use lib $FindBin::Bin;
+use lib "$FindBin::Bin/lib";
+
+use Cwd;
+use Cwd 'abs_path';
+use Getopt::Long;
+use File::Basename;
+use File::Spec;
+use XML::DOM;
+
+my $output;
+my $path;
+my $defaultns = 'http://www.symbian.org/system-definition';	# needed if no DTD
+my @searchpaths;
+my @searchroots;
+my %additional;
+my %add;
+my %newNs;
+my $warning = "Error";
+my $placeholders=0;
+my $sysmodelname;
+
+my @tdOrder =("hb","se", "lo","dc", "vc" , "pr", "dm", "de", "mm", "ma" , "ui",  "rt", "to" );
+
+sub help
+	{
+	my $name= $0; $name=~s,^.*[\\/],,;
+	print STDERR "usage: $name  [options...] template\n\nThis will create a new root system definition file based on the provided template by globbing for pkgdefs in the filesystem. Any found pkgdef files are added to the end of their layer or at the end of their tech domain section, if one is defined",
+	"\nvalid options are:\n",
+		"  -path [dir]\tspecifies the full system-model path to the file which is being processed. By default this is  \"/os/deviceplatformrelease/foundation_system/system_model/system_definition.xml\"\n",
+		"\t\tThis is only needed when creating a stand-alone sysdef as the output",
+
+		"  -output [file]\tspecifies the file to save the output to. If set, all hrefs will set to be relative to this location. If not specified all href will be absolute file URIs and this will write to stdout\n\n",
+
+		"  -w [Note|Warning|Error]\tspecifies prefix text for any notifications. Defautls to Error\n\n",
+		"  -root [dir]\tspecifies the root directory of the filesystem. All globbing will be done relative to this path\n\n",
+
+		"  -glob [wildcard path]\tThe wildcard search to look for pkgdef files. eg  \"\\*\\*\package_definition.xml\". Can specify any number of these.\n",
+		"  -placeholders [bool]\tif set, all packages not found in the template will be left in as empty placeholders\n";
+		"  -name [text]\tthe name in <systemModel> to use for the generated root sysdef. If not present, this will use the name from the templat\n";
+	exit(1);
+	}
+
+GetOptions
+	(
+	 'path=s' => \$path,
+	 'name=s' => \$sysmodelname,
+	'output=s' => \$output,
+	'w=s' => \$warning,
+	'root=s' => \@searchroots,
+	'glob=s' => \@searchpaths,
+	'placeholders=s' => \$placeholders
+	);
+
+
+ if($path eq '') {$path = '/os/deviceplatformrelease/foundation_system/system_model/system_definition.xml'}
+
+if(!($warning =~/^(Note|Warning|Error)$/)) {$warning="Error"}
+
+# path is the system model path of the processed sysdef file. This is only used when creating a stand-alone sysdef as the output
+# output specifies the file this is saved in. If specified, all (relative) paths will be modified to be relative to it. If not, all paths will be absolute
+# w is the warning level: Note, Warning or Error.
+# root = -root g:\sf
+# glob = -glob "\*\*\package_definition.xml"
+
+#Example command lines:
+#rootsysdef.pl -root F:\sftest\mcl\sf  -glob "\*\*\package_definition.xml"  -output  F:\sftest\mcl\build\system_definition.sf.xml   F:\sftest\mcl\sf\os\deviceplatformrelease\foundation_system\system_model\system_definition.xml
+#rootsysdef.pl -root F:\sftest\mcl\sf  -glob "\*\*\*\*\package_definition.xml"  -output  F:\sftest\mcl\build\system_definition.mine.xml   F:\sftest\mcl\sf\os\deviceplatformrelease\foundation_system\system_model\system_definition.xml
+if(!scalar @ARGV && !scalar @searchpaths) {&help()};
+
+
+my %replacefile;
+my $dir;
+foreach(@searchpaths)
+	{
+	my $ndir = shift(@searchroots);
+	if($ndir ne '') {$dir=$ndir}
+	foreach my $file (glob "$dir$_")
+		{
+		my $map =substr($file,length($dir));
+		$map=~tr/\\/\//;
+		$additional{$map}=$file;
+		$replacefile{&abspath($file)}=$map;
+		$add{&abspath($file)}=1;
+		}
+	}
+
+my $parser = new XML::DOM::Parser;
+my $sysdef;
+my %rootmap;
+my  $sysdefdoc;
+if(scalar @ARGV)
+	{
+	$sysdef = &abspath(shift);	# resolve the location of the root sysdef
+
+	# rootmap is a mapping from the filesystem to the paths in the doc
+	%rootmap = &rootMap($path,$sysdef);	
+
+	$sysdefdoc = $parser->parsefile ($sysdef);
+	}
+else 
+	{
+	$sysdefdoc = $parser->parse('<SystemDefinition schema="3.0.1"><systemModel name="System Model"/></SystemDefinition>');
+	}
+
+my %nsmap;
+my %urimap;
+
+my $mapmeta;
+my $modpath;
+if($output eq '')
+	{ #figure out mapping path
+	my @fspath = split(/[\\\/]/,$sysdef);
+	my @smpath = split(/[\\\/]/,$path);
+	while(lc($smpath[$#smpath]) eq lc($fspath[$#fspath] )) {
+		pop(@smpath);
+		pop(@fspath);
+	}
+	my $mappath = join('/',@fspath);
+	my $topath = join('/',@smpath);
+	$mappath=~s,^/?,file:///,;
+	$mapmeta = $sysdefdoc->createElement('meta');
+	$mapmeta->setAttribute('rel','link-mapping');
+	my $node = $sysdefdoc->createElement('map-prefix');
+	$node->setAttribute('link',$mappath);
+	$topath ne '' && $node->setAttribute('to',$topath);
+	$mapmeta->appendChild($node);
+	}
+else
+	{
+	$modpath = &relativeTo(&abspath($output), $sysdef);
+	}
+
+
+# find all the namespaces used in all the fragments and use that 
+# to set the namespaces in the root element of the created doc
+#   should be able to optimise by only parsing each doc once and 
+#	maybe skipping the contends of <meta>
+my @nslist = &namespaces($sysdef,$sysdefdoc->getDocumentElement());
+
+my %replacing;
+my %newContainer;
+my %foundDescendants;
+
+foreach(keys %add)
+	{
+	my   $fragment = $parser->parsefile ($_);
+	my $fdoc = $fragment->getDocumentElement();
+	my $topmost =&firstElement($fdoc);
+	if(!$topmost) {
+		print STDERR "$warning: $_ has no content. Skipping\n";
+		next;
+	}
+	my $type = $topmost->getTagName;
+	my $id = $topmost->getAttribute('id');
+	my ($localid,$ns) = &idns($topmost,$id);	
+	my @path = &guessIdInPath($localid,$_);
+	if($type eq 'layer') {@path=@path[0]}
+	elsif($type eq 'package')  {@path=@path[0..1]}
+	elsif($type eq 'collection')  {@path=@path[0..2]}
+	elsif($type eq 'component')  {@path=@path[0..3]}
+	@path = reverse(@path);
+	$add{$_}=join('/',@path)." $localid $ns";
+	$replacing{$type}->{"$localid $ns"} = $_;
+	# keys with a space are namespaced and fully identified, and contain the filename as the content.
+	# keys with no space have unknown namespace and contain a hash of the content
+	$newContainer{join('/',@path[0..$#path-1])}->{"$localid $ns"} = $_;
+	for(my $i=-1;$i<$#path-1;$i++)
+		{
+		$foundDescendants{$path[$i+1]}=1;
+		$newContainer{join('/',@path[0..$i])}->{$path[$i+1]}=1;
+		}
+	}
+
+
+while(@nslist)
+	{
+	my $uri = shift(@nslist);
+	my $prefix =shift(@nslist);
+	if($prefix eq 'id namespace'){$prefix=''}
+	if(defined $urimap{$uri}) {next} # already done this uri
+	$urimap{$uri} = $prefix;
+	if($nsmap{$prefix})
+		{ # need a new prefix for this, guess from the URI (for readability)
+		if($uri=~/http:\/\/(www\.)?([^.\/]+)\./) {$prefix = $2}
+		my $i=0;
+		while($nsmap{$prefix})
+			{ # still no prefix, just make up 
+			$prefix="ns$i";
+			$i++;
+			# next line not really necessary, but it's a good safety to stop infinite loops
+			$i eq 1000 && die "ERROR: cannot create namespace prefix for $uri";
+			}
+		}
+	$nsmap{$prefix}=$uri;
+	}
+
+my $docroot =  $sysdefdoc->getDocumentElement;
+
+my $ns = $docroot->getAttribute('id-namespace');
+if(!$ns && $nsmap{''})
+	{
+	$docroot->setAttribute('id-namespace',$nsmap{''});
+	}
+while(my($pre,$uri) = each(%nsmap))
+	{
+	$pre ne '' || next ;
+	$docroot->setAttribute("xmlns:$pre",$uri);
+	}
+
+&walk($sysdef,$docroot);
+
+if($output eq '') 
+	{
+	print $sysdefdoc->toString;
+	}
+else
+	{
+	$sysdefdoc->printToFile($output);
+	}
+
+ 
+sub abspath
+	{
+	# normalize the path into an absolute one
+	my  ($name,$path) = fileparse($_[0]);
+	if($path eq '' && $name eq '') {return};
+	$path=~tr,\\,/,;
+	if( -e $path)
+		{
+		return abs_path($path)."/$name";
+		}
+	my @dir = split('/',$_[0]);
+	my @new;
+	foreach my $d (@dir)
+		{
+		if($d eq '.') {next}
+		if($d eq '..')
+			{
+			pop(@new);
+			next;
+			}
+		push(@new,$d)
+		}
+	return join('/',@new);
+	}
+
+
+ 
+sub normpath
+	{
+	# normalize the path 
+	my @norm;
+	foreach my $dir(split(/[\\\/]/,shift)) {
+		if($dir eq '.') {next}
+		if($dir eq '..')
+			{
+			if($#norm == -1 || $norm[$#norm] eq '..')
+				{ # keep  as is
+				push(@norm,$dir);
+				}
+			elsif($#norm == 0 && $norm[0] eq '')
+				{  # path begins with /, interpret /.. as just / -- ie toss out
+				next
+				}
+			else
+				{
+				pop(@norm);
+				}
+			}
+		else
+			{
+			push(@norm,$dir);
+			}
+	}
+
+	return join('/',@norm)
+	}
+
+
+sub rootMap {
+	my @pathdirs = split(/\//,$_[0]);
+	my @rootdirs = split(/\//,$_[1]);
+
+	while(lc($rootdirs[$#rootdirs])  eq lc($pathdirs[$#pathdirs])  )
+		{
+		pop(@rootdirs);
+		pop(@pathdirs);
+		}
+	return (join('/',@rootdirs)  => join('/',@pathdirs) );
+	}
+
+sub replacedBy
+	{ # can only check once. Destroys data
+	my $node = shift;
+	my $fullid= join(' ',&idns($node));
+	my $type =  $node->getTagName;
+	my $repl = $replacing{$type}->{$fullid};
+	delete $replacing{$type}->{$fullid};
+	return $repl;
+	}
+
+sub walk
+	{
+	#' walk through the doc, resolving all links
+	my $file = shift;
+	my $node = shift;
+	my $type = $node->getNodeType;
+	if($type!=1) {return}
+	my $tag = $node->getTagName;
+	if($tag=~/^(layer|package|collection|component)$/ )
+		{
+		if($file eq $sysdef)
+			{
+			&fixIDs($node);	# normalise all IDs in the root doc.
+			}
+		my $override = &replacedBy($node);
+		my $link= $node->getAttribute('href');
+		if($override eq '' )
+			{
+			my ($id,$ns)=&idns($node);
+			if($foundDescendants{$id})
+				{ # keep this node, it'll be populated by what we found
+				if($link)
+					{
+					$node->removeAttribute('href');
+					}
+				}
+			elsif($link || !$placeholders)
+				{ # not going to be used, remove
+				$node->getParentNode->removeChild($node) ; # not present, remove
+				return;
+				}
+			}
+		else
+			{	
+			my $href = $node->getAttribute('href');	
+			my $ppath =  join('/',&parentPath($node->getParentNode));
+			delete $newContainer{$ppath}->{join(' ',&idns($node))};		# remove this from list of things which need to be added
+			if(&resolvePath($file,$href) ne $override)
+				{ # file has changed, update
+				print STDERR "$warning: Replacing $tag ",$node->getAttribute('id')," with $override\n";
+				&setHref($node,$override);
+				return;
+				}
+			}
+		my @curpath = &parentPath($node);
+		my $curitem = $curpath[$#curpath];
+		my $curp = join('/',@curpath[0..$#curpath-1]);
+		delete $newContainer{$curp}->{$curitem};
+
+		if($link)
+			{
+			foreach my $child (@{$node->getChildNodes}) {$node->removeChild($child)} # can't have children
+			&fixHref($node,$file);
+			return;
+			}
+		}
+	elsif($tag eq 'systemModel' && $mapmeta)
+		{ # need absolute paths for all links
+		$node->insertBefore ($mapmeta,$node->getFirstChild);
+		$sysmodelname eq '' || $node->setAttribute('name',$sysmodelname);
+		}
+	elsif($tag=~/^(SystemDefinition|systemModel)$/ )
+		{
+		($sysmodelname ne '' && $tag eq 'systemModel') && $node->setAttribute('name',$sysmodelname);
+		}
+	elsif($tag eq 'unit')
+		{
+		foreach my $atr ('bldFile','mrp','base','proFile')
+			{
+			my $link= $node->getAttribute($atr);
+			if($link && !($link=~/^\//))
+				{
+				if($mapmeta)
+					{ # use absolute paths
+					$link= &abspath(File::Basename::dirname($file)."/$link");
+					foreach my $a (keys %rootmap)
+						{
+						$link=~s,^$a,$rootmap{$a},ie;
+						}
+					}
+				else
+					{ # modified relative path 
+					$link = &normpath($modpath.$link);
+					}
+				$node->setAttribute($atr,$link);
+				}
+			}
+		}
+	elsif($tag eq 'meta')
+		{
+		&fixHref($node,$file);
+		foreach my $child (@{$node->getChildNodes}) {$node->removeChild($child)} # can't have children
+		&processMeta($node);
+		next;
+		}
+	else {return}
+	foreach my $item (@{$node->getChildNodes})
+		{
+		#print $item->getNodeType,"\n";
+		&walk($file,$item);
+		}
+	if($tag=~/^(systemModel|layer|package|collection|component)$/ )
+		{ # check for appending
+		my $ppath =  join('/',&parentPath($node));
+		if($newContainer{$ppath}) {
+			foreach my $item (sort keys %{$newContainer{$ppath}})
+				{
+				&appendNewItem($node,$item,$newContainer{$ppath}->{$item});
+				}
+			}
+		}
+	}
+
+
+sub getNs
+	{
+	# find the ns URI that applies to the specified prefix.
+	my $node = shift;
+	my $pre = shift;
+	my $uri = $node->getAttribute("xmlns:$pre");
+	if($uri) {return $uri}
+	my $parent = $node->getParentNode;
+	if($parent && $parent->getNodeType==1)
+		{
+		return getNs($parent,$pre);
+		}
+	}
+
+
+sub fixIDs
+	{
+	# translate the ID to use the root doc's namespaces 
+	my $node = shift;
+	foreach my $id ('id','before')
+		{
+		&fixID($node,$id);
+		}
+}
+
+sub idns
+	{ # return the namespace of an ID
+	my $node = shift;
+	my $id = shift;
+	if($id eq '' ) {$id = $node->getAttribute('id'); }
+	if($id=~s/^(.*)://)
+		{ # it's got a ns, find out what it is
+		my $pre = $1;
+		return ($id,&getNs($node,$pre));
+		}
+		return ($id,$node->getOwnerDocument->getDocumentElement->getAttribute("id-namespace") ||	$defaultns);
+	}
+
+sub fixID
+	{
+	# translate the ID to use the root doc's namespaces 
+	my $node = shift;
+	my $attr = shift || 'id';
+	my $id = $node->getAttribute($attr);
+	if($id eq '') {return}
+	my $ns;
+	if($id=~s/^(.*)://)
+		{ # it's got a ns, find out what it is
+		my $pre = $1;
+		$ns=&getNs($node,$pre);
+		}
+	else
+		{
+		$ns = $node->getOwnerDocument->getDocumentElement->getAttribute("id-namespace") ||
+			$defaultns;
+		}
+	$ns = $urimap{$ns};
+	$id = ($ns eq '') ? $id : "$ns:$id";
+	return $node->setAttribute($attr,$id);
+}
+
+sub firstElement {
+	# return the first element in this node
+	my $node = shift;
+	foreach my $item (@{$node->getChildNodes}) {
+		if($item->getNodeType==1) {return $item}
+	}
+}
+
+
+sub atts {
+	# return a hash of all attribtues defined for this element
+	my $node = shift;
+	my %at = $node->getAttributes;
+	my %list;
+	foreach my $a (keys %{$node->getAttributes}) 
+		{
+		if($a ne '')
+			{
+			$list{$a} = $node->getAttribute ($a);
+			}
+		}
+	return %list;
+}
+
+
+sub ns 
+	{
+	# return a hash of ns prefix and uri -- the xmlns: part is stripped off
+	my $node = shift;
+	my %list;
+	foreach my $a (keys %{$node->getAttributes}) 
+		{
+		my $pre = $a;
+		if($pre=~s/^xmlns://)
+			{
+			$list{$pre} = $node->getAttribute ($a);
+			}
+		}
+	return %list;
+	}
+
+
+
+sub namespaces
+	{
+	# return a list of namespace URI / prefix pairs, in the order they're defined
+	# these need to be used to define namespaces in the root element
+	my $file = shift;
+	my $node = shift;
+	my $type = $node->getNodeType;
+	if($type!=1) {return}
+	my $tag = $node->getTagName;
+	my @res;
+	my %nslist = &ns($node);
+	while(my($pre,$uri)=each(%nslist))
+		{ # push all namespaces defined here onto the list
+		push(@res,$uri,$pre);
+		}
+	if($tag=~/^(layer|package|collection|component)$/ )
+		{ # these have the potential of linking, so check for that
+		}
+	elsif($tag eq 'SystemDefinition' )
+		{
+		my $default = $node->getAttribute('id-namespace');
+		if($default)
+			{# mangle with a space so it's clear it's not a qname
+			push(@res,$default,'id namespace');
+			}
+		}
+	foreach my $item (@{$node->getChildNodes})
+		{
+		push(@res,&namespaces($file,$item));
+		}
+	return @res;
+	}
+
+sub  processMeta
+	{
+	my $metanode = shift;
+	# do nothing. Not supported yet
+	}
+
+sub guessIdInPath
+	{
+	my $id = shift;
+	my @path = reverse(split(/\//,$_[0]));
+	while(@path)
+		{
+		my $dir = shift(@path);
+		if($dir eq $id)
+			{
+			return ($id,@path);
+			}
+		}
+	print STDERR "$warning: Non-standard ID $id in $_[0]\n";
+	@path = reverse(split(/\//,$_[0]));
+	if($path[0] eq 'package_definition.xml')
+		{
+		return @path[1..$#path];
+		}
+	}
+
+
+sub parentPath
+	{
+	my $node=shift;
+	my @path;
+	while($node)
+		{
+		if(!$node) {return @path}
+		my $id=$node->getAttribute('id');
+		if($id eq '') {return @path}
+		$id=~s/^.*://;
+		@path = ($id,@path);
+		$node = $node->getParentNode();
+		}
+	return @path;
+	}
+
+sub childTag
+	{
+	my $tag = shift;
+	if($tag eq 'systemModel') {return 'layer'}
+	if($tag eq 'layer') {return 'package'}
+	if($tag eq 'package') {return 'collection'}
+	if($tag eq 'collection') {return 'component'}
+	die "ERROR: no child for $tag";
+	}
+
+sub appendNewItem
+	{
+	my $node = shift;
+	my $doc = $node->getOwnerDocument;
+	my $id = shift;
+	if($id eq '') {return}
+	my $fullid=$id;
+	my $contents = shift;
+	my $tag = &childTag($node->getTagName());
+	my $new = $doc->createElement($tag);
+	if($id=~/^(.*) (.*)/)
+		{
+		$id=$1;
+		$ns = getNamespacePrefix($node,$2);
+		if($ns ne '') {$id="$ns:$id"}
+		}
+	else
+		{
+		$contents = '';
+		}
+	$new->setAttribute('id',$id);		# default namespace
+	$node->appendChild($new);
+	my $ppath =  join('/',&parentPath($new));
+	if($contents eq '')
+		{ # look for additions
+		print STDERR "$warning: Adding new $tag: $id\n";
+		if($newContainer{$ppath}) {
+			foreach my $item (sort keys %{$newContainer{$ppath}})
+				{
+				&appendNewItem($new,$item,$newContainer{$ppath}->{$item});
+				}
+			}
+		}
+	else
+		{ # this one item is defined in the specified file
+		if($tag eq 'package') 
+			{ #include some package data in root
+			my $fragment = $parser->parsefile ($contents);
+			my $fdoc = $fragment->getDocumentElement();
+			my $topmost =&firstElement($fdoc);
+			my %at = &atts($topmost);
+			foreach my $arg ('tech-domain','level','span')
+				{
+				if($at{$arg}) {	$new->setAttribute($arg,$at{$arg})}
+				}
+			if($at{'tech-domain'}) {&positionByTechDomain($new)}
+			}
+		&setHref($new,$contents);
+		print STDERR "$warning: Adding found $tag $id from $contents\n";
+		delete $replacing{$tag}->{$fullid};
+		}
+	# newline after each new tag so output's not ugly
+	if($new->getNextSibling)
+		{
+		$node->insertBefore($doc->createTextNode ("\n"),$new->getNextSibling);
+		}
+	else
+		{
+		$node->appendChild($doc->createTextNode ("\n"));
+		}
+	delete $newContainer{$ppath};
+	}
+
+
+sub getNamespacePrefix
+	{
+	my $node = shift;
+	my $ns = shift;
+	my $root = $node->getOwnerDocument->getDocumentElement;
+	my $idns = $root->getAttribute("id-namespace");
+	if($idns && $idns eq $ns) {return}
+	if(!$idns && $defaultns eq $ns) {return}
+	foreach my $a (keys %{$root->getAttributes}) 
+		{
+		my $pre = $a;
+		if($pre=~s/^xmlns://)
+			{
+			if($root->getAttribute ($a) eq $ns)  {return $pre}
+			}
+		}
+	die "ERROR: no namespace prefix defined for $ns";
+	}
+
+
+sub resolvePath
+	{
+	# return full path to 2nd arg relative to first (path or absolute URI)
+	my $base = shift;
+	my $path = shift;
+	if($path=~m,^/,) {return $path } # path is absolute, but has no drive. Let OS deal with it.
+	if($path=~s,^file:///([a-zA-Z]:/),$1,) {return $path } # file URI with drive letter
+	if($path=~m,^file://,) {return $path } # file URI with no drive letter (unit-style). Just pass on as is with leading / and let OS deal with it
+	if($path=~m,^[a-z0-9][a-z0-9]+:,i) {return $path } # absolute URI -- no idea how to handle, so just return
+	return &abspath(File::Basename::dirname($base)."/$path");
+	}
+
+
+sub fixHref {
+	my $node = shift;
+	my $base = shift;
+	my $link= $node->getAttribute('href');
+	if($link=~/^(ftp|http)s:\/\//) {return} # remote link, do nothing
+	my $path = &resolvePath($base,$link);
+	if(!-e $path) 
+		{ # no such file, delete
+		my $tag  =$node->getTagName;
+		my $id = $node->getAttribute('id');
+		print STDERR "$warning: $tag $id not found at $link\n";	
+		$node->getParentNode->removeChild($node);
+		return;
+		}
+	foreach my $child (@{$node->getChildNodes}) {$node->removeChild($child)} # can't have children
+	if($output eq '')
+		{
+		$path=~s,^/?,file:///,;
+		$node->setAttribute('href',$path);	# replace with absolute URI
+		return;
+		}
+	$node->setAttribute('href',&normpath($modpath.$link));	# make relative path to output file
+	}
+
+
+sub setHref {
+	my $node = shift;
+	my $file = shift;
+	if($output eq '') 
+		{
+		$path = &abspath($file);
+		$path=~s,^/?,file:///,;
+		$node->setAttribute('href',$path);	# replace with absolute URI
+		}
+	else 
+		{
+		$node->setAttribute('href',&relativeTo(&abspath($output),$file,'file'));
+		}
+	while(my $child =  $node->getFirstChild ) {$node->removeChild($child)}
+}
+
+
+sub relativeTo {
+	if($_[0] eq '') {return &abspath($_[1])}
+	my @outfile = split(/[\\\/]/,lc(shift));
+	my @infile  = split(/[\\\/]/,lc(shift));
+	my $asdir = shift ne 'file';
+	while($outfile[0] eq $infile[0])
+		{
+		shift(@outfile);
+		shift(@infile);
+		}
+	$modpath = '../' x (scalar(@outfile) - 1);
+	if($asdir) {
+		if(scalar @infile > 1)  {$modpath .=  join('/',@infile[0..$#infile - 1]).'/'}
+	} else   {$modpath .=  join('/',@infile)}
+	return $modpath;
+}
+
+sub positionByTechDomain 
+	{
+	my $node=shift;
+	my $td = $node->getAttribute('tech-domain');
+	my %before;
+	foreach my $t (@tdOrder)
+		{
+		$before{$t}=1;
+		if($t eq $td) {last}
+		}
+	my $prev = $node->getPreviousSibling;
+	foreach my $child (reverse @{$node->getParentNode->getChildNodes})
+		{
+		if($child->getNodeType==1 && $child->getTagName eq 'package' && $child!=$node)
+			{
+			if($before{$child->getAttribute('tech-domain')})
+				{
+				my $next = $child->getNextSibling;
+				while($next &&  $next->getNodeType!=1) {$next = $next->getNextSibling}
+				if($next) {
+					$node->getParentNode->insertBefore ($node,$next);
+				}
+				last;
+				}
+			}
+		}
+	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metatools/sysdeftools/sysdefdowngrade.bat	Wed Jul 28 13:20:46 2010 +0100
@@ -0,0 +1,21 @@
+@rem Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+@rem All rights reserved.
+@rem This component and the accompanying materials are made available
+@rem under the terms of the License "Eclipse Public License v1.0"
+@rem which accompanies this distribution, and is available
+@rem at the URL "http://www.eclipse.org/legal/epl-v10.html".
+@rem
+@rem Initial Contributors:
+@rem Nokia Corporation - initial contribution.
+@rem
+@rem Contributors:
+@rem
+@rem Description: 
+@rem
+@setlocal
+@if .%1==. goto use
+@ java -jar %~dp0xalanj\xalan.jar -xsl %~dpn0.xsl %*  -XSLTC
+@goto end
+:use
+@ java -jar %~dp0xalanj\xalan.jar -in %~dpn0.xsl -xsl %~dp0lib\usage.xsl -param usage "%~n0"
+:end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metatools/sysdeftools/sysdefdowngrade.xsl	Wed Jul 28 13:20:46 2010 +0100
@@ -0,0 +1,438 @@
+<?xml version="1.0"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<!--Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+	All rights reserved.
+	This component and the accompanying materials are made available
+	under the terms of the License "Eclipse Public License v1.0"
+	which accompanies this distribution, and is available
+	at the URL "http://www.eclipse.org/legal/epl-v10.html".
+
+	Initial Contributors:
+	Nokia Corporation - initial contribution.
+	Contributors:
+	Description:
+	Downgrade a 3.x system definition into the 2.0.1 syntax
+-->
+	<xsl:output method="xml" indent="yes"/>
+
+
+<!--Description:Downgrades a 3.x system definition into the 2.0.1 syntax
+ -->
+
+<!--Input:<sysdef> - (required) The system definition XML file to process, in the 3.0 format, and can be a pkgdef or stand-alone sysdef.-->
+<!--Output:<sysdef> - (optional) The system definition XML file to save the output as. If not present it will write to stdout.-->
+
+	<xsl:param name="Path">os/deviceplatformrelease/foundation_system/system_model</xsl:param>
+	<!-- <oldpath> - The directory containing the root system definition XML file in the 2.0 sysdef style. This must not end in /
+		This is used to compute the absolute paths the 2.0 syntax needs. -->
+	<xsl:param name="Root"/> <!--<list> - (optional) A space separated list of root variables in the form "VAR1=value1 VAR=value2" --> 
+	<xsl:param name="Strict" select="0"/> <!--1 - (optional) If present, namespaced extensions are stripped out --> 
+	<xsl:variable name="root" select="concat(' ',$Root,' ')"/> <!-- sort of hack to allow absolute paths in downgraded output -->
+	<xsl:variable name="srcroot" select="substring-before(substring-after($root,' SRCROOT='),' ')"/> <!-- the default path prefix -->
+
+<xsl:template match="/*">
+	<xsl:message terminate="yes">ERROR: Cannot process this document</xsl:message>
+</xsl:template>
+
+<!-- can only handle 3.0.x to 2.0.1 transforms
+	Assumes only packages are using href
+ -->
+<xsl:template match="/SystemDefinition[starts-with(@schema,'3.0.')]"> 
+	<!-- process root system definition or package definition-->
+	<xsl:call-template name="DTD"/> <!-- insert 2.0.01 DTD -->
+  <SystemDefinition name="{*/@name}" schema="2.0.1">
+  	<xsl:apply-templates select="*|comment()"/>
+  </SystemDefinition>
+</xsl:template>
+
+<xsl:template match="/SystemDefinition[starts-with(@schema,'3.0.') and systemModel]"> 
+	<xsl:call-template name="DTD"/> <!-- insert 2.0.01 DTD -->
+  <SystemDefinition name="{systemModel/@name}" schema="2.0.1">
+  	<xsl:apply-templates select="*|comment()"/>
+  </SystemDefinition>
+</xsl:template>
+
+<xsl:template match="/SystemDefinition/package[@href]" priority="2">
+	<xsl:message terminate="yes">ERROR: Package definition (<xsl:value-of select="@id"/>) cannot link another package</xsl:message>
+</xsl:template>
+
+<xsl:template match="/SystemDefinition/package" priority="1">
+	<!-- process package definition file--> 
+  <systemModel>
+  	<layer name="anonymous"> <!-- fake layer -->
+		<block>
+			<xsl:apply-templates mode="copy" select="@id|@name|@span|@level|@levels"/><!--  valid attribuites for 2.0 -->
+		  	<xsl:apply-templates select="*|comment()">
+		  		<xsl:with-param name="path" select="concat($Path,'/')"/> <!-- need to keep tack of where the current document is -->
+		  	</xsl:apply-templates>			
+		</block>  
+   	</layer>
+  </systemModel>
+</xsl:template>
+
+
+
+<xsl:template match="/"><xsl:apply-templates select="*"/></xsl:template>
+<xsl:template match="@*|comment()"><xsl:copy-of select="."/></xsl:template> 
+	<!-- comments are copied verbatim. Attribtues are copied by default -->
+
+<xsl:template match="systemModel">
+	<systemModel>
+  	<xsl:apply-templates select="*|comment()"> <!-- no attributes -->
+  		<xsl:with-param name="path" select="$Path"/> <!-- need to keep tack of where the current document is -->
+  	</xsl:apply-templates>
+	</systemModel>
+</xsl:template>
+
+<xsl:template mode="copy" match="@*">
+	<xsl:copy-of select="."/>
+</xsl:template>
+
+<xsl:template mode="copy" match="@id"> <!-- id in 3.0 is name in 2.0 -->
+	<xsl:attribute name="name"><xsl:value-of select="."/></xsl:attribute>
+</xsl:template>
+
+<xsl:template mode="copy" match="@name">  <!-- name in 3.0 is long-name in 2.0.1 -->
+	<xsl:if test=".!=../@id"> <!-- don't bother if it will be the same as name -->
+		<xsl:attribute name="long-name"><xsl:value-of select="."/></xsl:attribute>
+	</xsl:if>
+</xsl:template>
+	
+<xsl:template match="layer"><xsl:param name="path"/>
+	<layer>
+		<xsl:apply-templates mode="copy" select="@id|@name|@span|@levels"/> <!--  valid attribuites for 2.0 -->
+		<xsl:apply-templates select="*|comment()"> 
+			<xsl:with-param name="path" select="$path"/> 
+		</xsl:apply-templates>
+	</layer>
+</xsl:template>
+
+<xsl:template match="layer/package"><!-- translates to block -->
+	<xsl:param name="path"/>
+	<block>
+		<xsl:apply-templates mode="copy" select="@id|@name|@span|@level|@levels"/><!--  valid attribuites for 2.0 -->
+		<xsl:choose>
+			<xsl:when test="@href">
+				<xsl:variable name="this" select="."/>
+				<xsl:variable name="prefixmap" select="ancestor::SystemDefinition/*/meta[@rel='link-mapping']/map-prefix[starts-with(current()/@href,@link)]"/>
+				<xsl:for-each select="document(@href,.)/SystemDefinition/*">
+					<xsl:variable name="my-id"><xsl:apply-templates mode="normalize-id" select="@id"/></xsl:variable>
+					<xsl:variable name="other-id"><xsl:apply-templates mode="normalize-id" select="$this/@id"/></xsl:variable>
+					<xsl:if test="$my-id != $other-id">
+						<xsl:message terminate="yes">ERROR: Package IDs do not match: <xsl:value-of select="$my-id"/> vs <xsl:value-of select="$other-id"/></xsl:message>
+					</xsl:if>
+					<xsl:if test="@name and @name!=@id and not($this/@name and $this/@name=$this/@id)">
+						<!-- set long-name only if name is different from the id and not set in child doc -->
+						<xsl:attribute name="long-name"><xsl:value-of select="@name"/></xsl:attribute>
+					</xsl:if>						
+					<xsl:for-each select="@span|@levels|@level">
+						<!-- copy only if not set in child doc -->
+						<xsl:if test="not(this/@*[name()=name(current())])">
+							<xsl:copy-of select="."/>
+						</xsl:if>
+					</xsl:for-each>
+					<xsl:apply-templates select="*|comment()">
+	  					<xsl:with-param name="path">
+							<xsl:choose>
+								<xsl:when test="$prefixmap">
+	  								<xsl:call-template name="normpath">
+	  									<xsl:with-param name="path">
+										<xsl:apply-templates select="$prefixmap/@to"/>
+										<xsl:value-of select="substring-after($this/@href,$prefixmap/@link)"/>
+									 </xsl:with-param>
+	  								</xsl:call-template>
+								</xsl:when>
+								<xsl:when test="starts-with($this/@href,'/')">  <!-- absolute path -->
+	  								<xsl:call-template name="normpath">
+	  									<xsl:with-param name="path" select="$this/@href"/>
+	  								</xsl:call-template>
+								</xsl:when>
+								<xsl:when test="contains($this/@href,'://')">  <!-- generic URI -->
+	  								<xsl:call-template name="normpath">
+	  									<xsl:with-param name="path" select="substring-after($this/@href,'://')"/>
+	  								</xsl:call-template>
+								</xsl:when>
+								<xsl:otherwise>
+	  								<xsl:call-template name="normpath">
+	  									<xsl:with-param name="path" select="concat($path,'/',$this/@href)"/>
+	  								</xsl:call-template>
+								</xsl:otherwise>
+							</xsl:choose>
+	  					</xsl:with-param> 
+	  				</xsl:apply-templates>
+				</xsl:for-each>
+			</xsl:when>
+			<xsl:otherwise>
+				<xsl:apply-templates select="*|comment()">
+  					<xsl:with-param name="path" select="$path"/> 
+  				</xsl:apply-templates>
+			</xsl:otherwise>
+		</xsl:choose>
+	</block>
+</xsl:template>
+
+<xsl:template match="package/package">	<!-- translates to subblock --><xsl:param name="path"/>
+	<subblock>
+		<xsl:apply-templates mode="copy" select="@id|@name"/>
+		<xsl:apply-templates select="*|comment()">
+			<xsl:with-param name="path" select="$path"/> 
+		</xsl:apply-templates>
+	</subblock>
+</xsl:template>
+
+<xsl:template match="package/package/pacakge"> <!-- cannot nest this deep --><xsl:param name="path"/>
+	<xsl:message>WARNING: Excessive nesting of packages: Ignoring <xsl:value-of select="@id"/></xsl:message>
+	<xsl:apply-templates select="*|comment()">
+		<xsl:with-param name="path" select="$path"/> 
+	</xsl:apply-templates>
+</xsl:template>
+
+
+<xsl:template match="collection"><xsl:param name="path"/>
+	<collection>
+		<xsl:apply-templates mode="copy" select="@id|@name|@level"/>
+		<xsl:apply-templates select="*|comment()">
+			<xsl:with-param name="path" select="$path"/> 
+		</xsl:apply-templates>
+	</collection>
+</xsl:template>
+
+
+<xsl:template match="component"><xsl:param name="path"/>
+	<component>
+		<xsl:apply-templates mode="copy" select="@id|@name|@deprecated|@introduced|@filter|@purpose"/>
+		<xsl:if test="contains(concat(' ',@class,' '),' plugin ')">
+			<xsl:attribute name="plugin">Y</xsl:attribute>
+		</xsl:if>
+		<xsl:call-template name="class">
+			<xsl:with-param name="remove">plugin</xsl:with-param>
+			<xsl:with-param name="add">
+				<xsl:if test="not(*) and comment()">placeholder</xsl:if>
+				<xsl:if test="@target='desktop'"> PC</xsl:if>
+			</xsl:with-param>
+		</xsl:call-template>
+	  	<xsl:apply-templates select="*|comment()">
+			<xsl:with-param name="path" select="$path"/> 
+		</xsl:apply-templates>
+	</component>
+</xsl:template>
+
+<xsl:template match="unit[@base and not(@mrp or @bldFile)]"/>
+
+<xsl:template match="unit"><xsl:param name="path"/>
+	<unit>
+		<xsl:apply-templates select="@mrp|@bldFile|@late">
+			<xsl:with-param name="path" select="$path"/> 
+		</xsl:apply-templates>
+		<xsl:copy-of select="@filter|@root[not(contains($root,concat(' ',.,'=')))]|@version|@prebuilt|@priority"/>
+		<xsl:for-each select="@*[contains(name(),':') and not($Strict)]">
+			<xsl:attribute name="{local-name()}">
+				<xsl:value-of select="."/>
+			</xsl:attribute>
+		</xsl:for-each>
+	</unit>
+</xsl:template>
+
+<xsl:template match="unit/@late"> <!-- 2.0 uses Y/N, 3.0 uses yes/no -->
+	<xsl:attribute name="{name()}">
+		<xsl:choose>
+			<xsl:when test=".='yes'">Y</xsl:when>
+			<xsl:when test=".='no'">N</xsl:when>
+		</xsl:choose>
+	</xsl:attribute>
+</xsl:template>
+
+<xsl:template match="@mrp|@bldFile"><xsl:param name="path"/>
+	<xsl:attribute name="{name()}">
+		<xsl:choose>
+			<xsl:when test="../@root">
+				<xsl:variable name="pre" select="substring-before(substring-after($root,concat(' ',../@root,'=')),' ')"/>
+				<xsl:value-of select="$pre"/>
+				<xsl:if test="$pre!='' and $pre!='/'">/</xsl:if>
+			</xsl:when>
+			<xsl:when test="$srcroot='/'"> <!-- treat all paths as absolute -->
+				<xsl:value-of select="$srcroot"/>
+			</xsl:when>
+			<xsl:when test="$srcroot!=''">
+				<xsl:value-of select="concat($srcroot,'/')"/>
+			</xsl:when>
+		</xsl:choose>
+		<xsl:choose>
+		<xsl:when test="starts-with(.,'/')"> <!-- keep absolute paths verbatim (barring the leading / ) -->
+			<xsl:value-of select="substring-after(.,'/')"/>
+		</xsl:when>
+		<xsl:otherwise>	
+			<xsl:call-template name="normpath">
+  				<xsl:with-param name="path">
+  					<xsl:call-template name="before">
+						<xsl:with-param name="text" select="$path"/>
+					</xsl:call-template>
+					<xsl:value-of select="."/>
+  				</xsl:with-param>
+  			</xsl:call-template>
+		</xsl:otherwise>
+	</xsl:choose>
+	</xsl:attribute>
+</xsl:template>
+
+<xsl:template match="meta"/> <!-- strip all meta tags -->
+
+<xsl:template match="meta[info/@contract]"> <!-- except contract -->
+	<xsl:copy-of select="info/@contract"/>
+</xsl:template>
+
+
+<xsl:template match="meta[@rel='link-mapping']/map-prefix/@to">
+	<xsl:choose>
+		<xsl:when test="starts-with(.,'/')"><xsl:value-of select="substring(.,2)"/></xsl:when> <!-- absolute paths in 3.0 are relative in 2.0 -->
+		<xsl:otherwise><xsl:value-of select="."/></xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+
+<xsl:template match="@id" mode="normalize-id">
+	<xsl:choose>
+		<xsl:when test="contains(@id,':')"><xsl:value-of select="substring-after(@id,':')"/></xsl:when>
+		<xsl:otherwise><xsl:value-of select="@id"/></xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+<xsl:template name="class"><xsl:param name="remove"/><xsl:param name="add"/>
+<!--  returns the value of the class attribute with the space-separated list of names in $remove taken out and those in $add added on (does not check for duplicates) -->
+	<xsl:param name="class" select="normalize-space(@class)"/>
+	<xsl:variable name="r">
+		<xsl:text> </xsl:text>
+		<xsl:choose>
+			<xsl:when test="contains($remove,' ')"><xsl:value-of select="substring-before($remove,' ')"/></xsl:when>
+			<xsl:otherwise><xsl:value-of select="$remove"/></xsl:otherwise>
+		</xsl:choose>
+		<xsl:text> </xsl:text>
+	</xsl:variable>
+	<xsl:variable name="c">
+		<xsl:choose>
+			<xsl:when test="contains(concat(' ',$class,' '),$r)">
+				<xsl:value-of select="substring-before(concat(' ',$class,' '),$r)"/>
+				<xsl:text> </xsl:text>
+				<xsl:value-of select="substring-after(concat(' ',$class,' '),$r)"/>
+			</xsl:when>
+			<xsl:otherwise><xsl:value-of select="$class"/></xsl:otherwise>
+		</xsl:choose>
+		<xsl:if test="normalize-space($add)!=''"><xsl:value-of select="concat(' ',normalize-space($add))"/></xsl:if>
+	</xsl:variable>
+	<xsl:choose>
+		<xsl:when test="contains($remove,' ')">
+			<xsl:call-template name="class">
+				<xsl:with-param name="remove" select="substring-after($remove,' ')"/>
+				<xsl:with-param name="class" select="$c"/>
+			</xsl:call-template>
+		</xsl:when>
+		<xsl:when test="normalize-space($c)!=''">
+			<xsl:attribute name="class">
+				<xsl:value-of select="normalize-space($c)"/>
+			</xsl:attribute>
+		</xsl:when>
+	</xsl:choose>
+</xsl:template>
+
+<xsl:template name="normpath"><xsl:param name="path"/>
+<!-- normalize out any ".." in the path in $path  -->
+<xsl:choose>
+	<xsl:when test="contains($path,'/../')">
+	<xsl:call-template name="normpath">
+		<xsl:with-param name="path">
+		<xsl:call-template name="before">
+			<xsl:with-param name="text" select="substring-before($path,'/../')"/>
+		</xsl:call-template>
+		<xsl:value-of select="substring-after($path,'/../')"/>
+		</xsl:with-param>
+		</xsl:call-template>
+	</xsl:when>
+	<xsl:otherwise><xsl:value-of select="$path"/></xsl:otherwise>
+</xsl:choose>
+</xsl:template>
+
+<!-- return all text before the last / -->
+<xsl:template name="before"><xsl:param name="text"/>
+<xsl:if test="contains($text,'/')">
+	<xsl:value-of select="substring-before($text,'/')"/>/<xsl:call-template name="before"><xsl:with-param name="text" select="substring-after($text,'/')"/></xsl:call-template>
+	</xsl:if>
+</xsl:template>
+
+<xsl:template name="DTD">
+<xsl:text disable-output-escaping="yes"><![CDATA[<!DOCTYPE SystemDefinition [
+<!ELEMENT SystemDefinition ( systemModel )>
+<!ATTLIST SystemDefinition
+  name CDATA #REQUIRED
+  schema CDATA #REQUIRED
+>
+<!-- all paths are relative to the environment variable specified by the root attribute, or SOURCEROOT if not.  -->
+
+<!-- System Model Section of DTD -->
+<!ELEMENT systemModel (layer+)>
+
+<!ELEMENT layer (block* | collection*)*>
+<!-- Kernel Services, Base Services, OS Services, Etc -->
+<!ATTLIST layer
+  name CDATA #REQUIRED
+  long-name CDATA #IMPLIED
+  levels NMTOKENS #IMPLIED
+  span CDATA #IMPLIED
+>
+
+<!ELEMENT block (subblock* | collection*)*>
+ <!-- Generic OS services, Comms Services, etc -->
+<!ATTLIST block
+  levels NMTOKENS #IMPLIED
+  span CDATA #IMPLIED
+  level NMTOKEN #IMPLIED
+  name CDATA #REQUIRED
+  long-name CDATA #IMPLIED
+>
+
+<!ELEMENT subblock (collection)*>
+<!-- Cellular Baseband Services, Networking Services, etc -->
+<!ATTLIST subblock
+  name CDATA #REQUIRED
+  long-name CDATA #IMPLIED
+>
+
+<!ELEMENT collection (component)*>
+<!-- Screen Driver, Content Handling, etc -->
+<!ATTLIST collection
+  name CDATA #REQUIRED
+  long-name CDATA #IMPLIED
+  level NMTOKEN #IMPLIED
+>
+
+<!ELEMENT component (unit)*>
+<!-- contains units or is a  package or prebuilt -->
+<!ATTLIST component
+  name CDATA #REQUIRED
+  long-name CDATA #IMPLIED
+  deprecated CDATA #IMPLIED
+  introduced CDATA #IMPLIED
+  contract CDATA #IMPLIED
+  plugin (Y|N) "N"
+  filter CDATA #IMPLIED
+  class NMTOKENS #IMPLIED
+  supports CDATA #IMPLIED
+  purpose ( optional | mandatory | development ) "optional"
+>
+
+<!ELEMENT unit EMPTY >
+<!-- must be buildable (bld.inf) -->
+<!-- bldFile  may someday be removed in favour of mrp -->
+<!ATTLIST unit
+  mrp CDATA #IMPLIED
+  filter CDATA #IMPLIED
+  bldFile CDATA #IMPLIED
+  root CDATA #IMPLIED
+  version NMTOKEN #IMPLIED
+  prebuilt NMTOKEN #IMPLIED
+  late (Y|N) #IMPLIED
+  priority CDATA #IMPLIED
+>
+]>
+]]></xsl:text>
+</xsl:template>
+</xsl:stylesheet>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metatools/sysdeftools/validate-sysdef.bat	Wed Jul 28 13:20:46 2010 +0100
@@ -0,0 +1,21 @@
+@rem Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+@rem All rights reserved.
+@rem This component and the accompanying materials are made available
+@rem under the terms of the License "Eclipse Public License v1.0"
+@rem which accompanies this distribution, and is available
+@rem at the URL "http://www.eclipse.org/legal/epl-v10.html".
+@rem
+@rem Initial Contributors:
+@rem Nokia Corporation - initial contribution.
+@rem
+@rem Contributors:
+@rem
+@rem Description: 
+@rem
+@setlocal
+@if .%1==. goto use
+@ java -jar %~dp0xalanj\xalan.jar   -xsl %~dpn0.xsl %*
+@goto end
+:use
+@ java -jar %~dp0xalanj\xalan.jar -in %~dpn0.xsl -xsl %~dp0lib\usage.xsl -param usage "%~n0"
+:end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metatools/sysdeftools/validate-sysdef.xsl	Wed Jul 28 13:20:46 2010 +0100
@@ -0,0 +1,56 @@
+<xsl:stylesheet  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+<!--Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+	All rights reserved.
+	This component and the accompanying materials are made available
+	under the terms of the License "Eclipse Public License v1.0"
+	which accompanies this distribution, and is available
+	at the URL "http://www.eclipse.org/legal/epl-v10.html".
+
+	Initial Contributors:
+	Nokia Corporation - initial contribution.
+	Contributors:
+	Description:
+	Validate a system definition file/files and output results as plain text
+-->
+	<xsl:output method="text"/>
+	<xsl:include href="lib/test-model.xsl"/>
+	<xsl:param name="level" select="3"/>  <!--<1/2/3> - (optional) The detail of the error messages. 1  = Errors only. 2 = Errors and Warnings. 3 = Notes as well (the default) -->
+	<xsl:param name="path-errors" select="0"/> <!--1 - (optional) If present, it will check to see if unit paths follow the coding standards-->
+
+
+<!--Description:Validates a system definition file or files and outputs the result as plain text
+-->
+<!--Input:<sysdef> - (required) The system definition XML or Model XML file to process. Sysdefs must be in the 3.0 format, and can be a fragment or stand-alone.-->
+<!--Output:<log> - (optional) The file to write the error log to. If not present it will write to stdout.-->
+
+
+<xsl:template name="Section"><xsl:param name="text"/><xsl:param name="sub"/>
+<xsl:text>&#xa;&#xa;</xsl:text>
+<xsl:value-of select="$text"/>
+<xsl:if test="$sub!=''"> (<xsl:value-of select="$sub"/>)</xsl:if>
+</xsl:template>
+
+
+<xsl:template name="Note"><xsl:param name="text"/><xsl:param name="sub"/>
+<xsl:if test="$level &gt;= 3">
+<xsl:text>&#xa;Note: </xsl:text>
+<xsl:value-of select="$text"/>
+<xsl:if test="$sub!=''"> (<xsl:value-of select="$sub"/>)</xsl:if>
+</xsl:if>
+</xsl:template>
+
+<xsl:template name="Warning"><xsl:param name="text"/><xsl:param name="sub"/>
+<xsl:if test="$level &gt;= 2">
+<xsl:text>&#xa;Warning: </xsl:text>
+<xsl:value-of select="$text"/>
+<xsl:if test="$sub!=''"> (<xsl:value-of select="$sub"/>)</xsl:if>
+</xsl:if>
+</xsl:template>
+
+<xsl:template name="Error"><xsl:param name="text"/><xsl:param name="sub"/>
+<xsl:text>&#xa;Error: </xsl:text>
+<xsl:value-of select="$text"/>
+<xsl:if test="$sub!=''"> (<xsl:value-of select="$sub"/>)</xsl:if>
+</xsl:template>
+
+</xsl:stylesheet>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/metatools/sysdeftools/xalanj/LICENSE.xalan	Wed Jul 28 13:20:46 2010 +0100
@@ -0,0 +1,55 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999 The Apache Software Foundation.  All rights 
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:  
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xalan", "Xerces", and "Apache Software Foundation" must
+ *    not be used to endorse or promote products derived from this
+ *    software without prior written permission. For written 
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ *    nor may "Apache" appear in their name, without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 1999, International
+ * Business Machines, Inc., http://www.apache.org.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
Binary file metatools/sysdeftools/xalanj/serializer.jar has changed
Binary file metatools/sysdeftools/xalanj/xalan.jar has changed
Binary file metatools/sysdeftools/xalanj/xercesImpl.jar has changed
Binary file metatools/sysdeftools/xalanj/xml-apis.jar has changed
--- a/package_definition.xml	Tue Jul 27 13:00:43 2010 +0800
+++ b/package_definition.xml	Wed Jul 28 13:20:46 2010 +0100
@@ -8,18 +8,23 @@
             <component filter="build_SFPhase1" id="rcomp" name="Resource Compiler" >
                 <unit bldFile="bintools/rcomp/group" mrp="bintools/rcomp/group/rcomp.mrp"/>
             </component>
-            <component filter="build_SFPhase1" id="checklib" name="checklib" >
+            <component filter="build_SFPhase1" id="checklib" name="Checklib" >
                 <unit bldFile="bintools/checklib/group" mrp="bintools/checklib/group/checklib.mrp"/>
             </component>
-            <component filter="build_SFPhase1" id="elftools" name="elftools" >
+            <component filter="build_SFPhase1" id="elftools" name="ELF Tools" >
                 <unit bldFile="bintools/elftools/group" mrp="bintools/elftools/group/elftools.mrp"/>
             </component>
         </collection>
         <collection id="srctools" level="middleware" name="Source Tools">
-            <component filter="build_SFPhase1" id="tranasm" name="tranasm" >
+            <component filter="build_SFPhase1" id="tranasm" name="Translate ASM">
                 <unit bldFile="srctools/tranasm/group" mrp="srctools/tranasm/group/tranasm.mrp"/>
             </component>
         </collection>
+        <collection id="metatools" level="middleware" name="Metadata Tools">
+            <component filter="build_SFPhase1" id="sysdeftools" name="System Definition Tools" introduced="^1">
+                <unit base="metatools/sysdeftools"/>
+            </component>
+        </collection>
         <collection id="e32tools" level="middleware" name="E32 Tools">
             <component filter="build_SFPhase1" id="elf2e32" name="elf2e32 (Postlinker)" >
                 <unit bldFile="e32tools/elf2e32/group" mrp="e32tools/elf2e32/group/elf2e32.mrp"/>