<!--
	 ******************************************************
	 *
	 *                       NOTICE
	 *
	 *   THIS SOFTWARE IS THE PROPERTY OF AND CONTAINS
	 *   CONFIDENTIAL INFORMATION OF INFOR AND SHALL NOT
	 *   BE DISCLOSED WITHOUT PRIOR WRITTEN PERMISSION.
	 *   LICENSED CUSTOMERS MAY COPY AND ADAPT THIS
	 *   SOFTWARE FOR THEIR OWN USE IN ACCORDANCE WITH
	 *   THE TERMS OF THEIR SOFTWARE LICENSE AGREEMENT.
	 *   ALL OTHER RIGHTS RESERVED.
	 *
	 *   COPYRIGHT (c) 2007 INFOR. ALL RIGHTS RESERVED.
	 *   THE WORD AND DESIGN MARKS SET FORTH HEREIN ARE
	 *   TRADEMARKS AND/OR REGISTERED TRADEMARKS OF INFOR
	 *   AND/OR RELATED AFFILIATES AND SUBSIDIARIES. ALL
	 *   RIGHTS RESERVED. ALL OTHER TRADEMARKS LISTED
	 *   HEREIN ARE THE PROPERTY OF THEIR RESPECTIVE
	 *   OWNERS. WWW.INFOR.COM.
	 *
	 ******************************************************
 -->
 <xsl:stylesheet version="2.0" 
		xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
		xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
		xmlns:oagis="http://www.openapplications.org/oagis/9"
		xmlns:oacl="http://www.openapplications.org/oagis/9/codelists" 
		xmlns:udt="http://www.openapplications.org/oagis/9/unqualifieddatatypes/1.1" 
		xmlns:qdt="http://www.openapplications.org/oagis/9/qualifieddatatypes/1.1" 
		xmlns:ccts="urn:un:unece:uncefact:documentation:1.1"
		xmlns:foo="http://foo"
        exclude-result-prefixes="udt foo"> 
	<xsl:strip-space elements="*"/>
	
	<xsl:param name="suppressComponents"/>

	<xsl:template match="/">
		<!--<xsl:variable name="comm" select="substring-after(comment(  ),'Revision: ')"/>
		<xsl:variable name="version" select="substring($comm,1,3)"/>-->
		<BusinessInterface>
			<xsl:apply-templates select="*/xsd:complexType[xsd:sequence[xsd:any]]" mode="datatype"/>		
			<xsl:apply-templates select="*/xsd:complexType[contains(@name,'DataAreaType')]">
				<!--<xsl:with-param name="versionId" select="$version"/>-->
			</xsl:apply-templates>
			<xsl:apply-templates select="*/xsd:complexType[xsd:simpleContent]" mode="datatype"/>
			<xsl:apply-templates select="*/xsd:simpleType" mode="datatype"/>
			<xsl:apply-templates select="*/xsd:element[xsd:complexType]" mode="datatype"/>
		</BusinessInterface>
	</xsl:template>
	
	<xsl:template match="xsd:complexType[xsd:sequence[xsd:any]]" mode="datatype">
		<Datatype>
			<name><xsl:value-of select="@name"/></name>
			<description></description>
  			<type>simple</type>
  			<primitiveDatatype>anyType</primitiveDatatype>
  			<nativeDatatype></nativeDatatype>
  			<schema></schema>
  			<isTranslatable>false</isTranslatable>
  			<documentation></documentation>
  			<xsl:apply-templates select="xsd:attribute" mode="datatype"/>
  			<xsl:apply-templates select="xsd:annotation/xsd:documentation"/>
		</Datatype>
	</xsl:template>
	
	<xsl:template match="xsd:attribute" mode="datatype">
		<!--xsl:message>Found DatatypeRelationship [<xsl:value-of select="@name"/>] ...</xsl:message-->
		<DatatypeRelationship>
			<name><xsl:value-of select="@name"/></name>
			<description></description>
			<datatype><xsl:value-of select="@type"/></datatype>
			<isQualifier>true</isQualifier>
			<position><xsl:value-of select="position()"/></position>
			<documentation></documentation>
			<xsl:apply-templates select="xsd:annotation/xsd:documentation"/>
	</DatatypeRelationship>
	</xsl:template>
	
	<xsl:template match="*/xsd:element[xsd:complexType]" mode="datatype">
		<!--xsl:message>Found complex Datatype [<xsl:value-of select="@name"/>]...</xsl:message-->
		<Datatype>
			<name><xsl:value-of select="@name"/></name>
			<description></description>
  			<type>complex</type>
  			<primitiveDatatype>string</primitiveDatatype>
  			<schema></schema>
  			<isTranslatable>false</isTranslatable>
  			<documentation></documentation>
  			<xsl:apply-templates select="xsd:complexType/xsd:sequence/xsd:element" mode="datatype"/>
  			<xsl:variable name="noun" select="xsd:complexType/xsd:complexContent/xsd:extension/@base"/>
  			<xsl:apply-templates select="/*/xsd:complexType[@name=$noun and count(xsd:sequence[xsd:any])=0 and count(xsd:simpleContent)=0]" mode="datatype"/>
  			<xsl:apply-templates select="xsd:annotation/xsd:documentation"/>
		</Datatype>
	</xsl:template>
	
	<xsl:template match="*/xsd:complexType[count(xsd:sequence[xsd:any])=0 and count(xsd:simpleContent)=0]" mode="datatype">
		<xsl:variable name="noun" select="xsd:complexContent/xsd:extension/@base"/>
		<xsl:apply-templates select="/*/xsd:complexType[@name=$noun and count(xsd:sequence[xsd:any])=0 and count(xsd:simpleContent)=0]" mode="datatype"/>
		<xsl:apply-templates select="xsd:sequence/xsd:element" mode="datatype"/>
		<xsl:apply-templates select="xsd:attribute" mode="datatype"/> 
	</xsl:template>
	
	<xsl:template match="xsd:complexType/xsd:sequence/xsd:element" mode="datatype">
		<DatatypeRelationship>
		    <name><xsl:value-of select="@name"/></name>
		    <description></description>
		    <isQualifier>false</isQualifier>
		    <position><xsl:value-of select="position()"/></position>
		    <datatype><xsl:value-of select="@type"/></datatype>
		</DatatypeRelationship>
	</xsl:template>
	
	<xsl:template match="xsd:complexType[contains(@name,'DataAreaType')]">
		<!--<xsl:param name="versionId"/>-->
		
		<!--xsl:message>Start processing bid[<xsl:value-of select="xsd:sequence/xsd:element[position()=2]/@ref"/>]</xsl:message-->
		<BusinessInterfaceDefinition>			
			<name><xsl:value-of select="xsd:sequence/xsd:element[position()=2]/@ref"/></name>
			<status>developing</status>
			<xsl:apply-templates select="xsd:sequence/xsd:element[position()=2]"/>
			<type>bod</type>
			<isTransactional>false</isTransactional>
			<!--<versionID><xsl:value-of select="$versionId"/></versionID>-->	
		</BusinessInterfaceDefinition>	
		<!--xsl:message>End processing bid[<xsl:value-of select="xsd:sequence/xsd:element[position()=2]/@ref"/>]</xsl:message-->
	</xsl:template>
	
	<xsl:template match="xsd:extension">
		<xsl:param name="component"/>
		<xsl:param name="prefix"/>
		<xsl:param name="onlyAttributeRelationship"/>

		<!--xsl:message>Start processing [<xsl:value-of select="@base"/>] : xsd:extension ...</xsl:message-->
		<xsl:variable name="noun" select="@base"/>
		<xsl:apply-templates select="/*/xsd:complexType[@name=$noun and count(xsd:complexContent[xsd:extension/@base=$noun])=0 and count(xsd:simpleContent[xsd:extension/@base=$noun])=0]">
			<xsl:with-param name="component" select="$component"/>		
			<xsl:with-param name="prefix" select="$prefix"/>		
			<xsl:with-param name="onlyAttributeRelationship" select="$onlyAttributeRelationship"/>		
		</xsl:apply-templates>			
		<xsl:apply-templates>
			<xsl:with-param name="component" select="$component"/>		
			<xsl:with-param name="prefix" select="$prefix"/>		
			<xsl:with-param name="onlyAttributeRelationship" select="$onlyAttributeRelationship"/>		
		</xsl:apply-templates>
		<!--xsl:message>End processing [<xsl:value-of select="@base"/>] : xsd:extension ...</xsl:message-->
	</xsl:template>
	
	<xsl:template match="xsd:attributeGroup[@ref]">
		<xsl:param name="component"/>
		<xsl:param name="prefix"/>
		<xsl:param name="onlyAttributeRelationship"/>

		<!--xsl:message>Start processing [<xsl:value-of select="@ref"/>] : xsd:attributeGroup ...</xsl:message-->
		<xsl:variable name="ref" select="@ref"/>
		<xsl:apply-templates select="/*/xsd:attributeGroup[@name=$ref]">	
			<xsl:with-param name="component" select="$component"/>		
			<xsl:with-param name="prefix" select="$prefix"/>		
			<xsl:with-param name="onlyAttributeRelationship" select="$onlyAttributeRelationship"/>		
		</xsl:apply-templates>
		<!--xsl:message>End processing [<xsl:value-of select="@ref"/>] : xsd:attributeGroup ...</xsl:message-->
	</xsl:template>
		
	<xsl:template match="xsd:attribute">
		<xsl:param name="component"/>
		<xsl:param name="prefix"/>
		<xsl:param name="onlyAttributeRelationship"/>
	
		<xsl:choose>
			<xsl:when test="$onlyAttributeRelationship='true'">
				<AttributeRelationship>
					<name><xsl:value-of select="@name"/></name>
					<attribute><xsl:value-of select="$prefix"/><xsl:value-of select="@name"/></attribute>
				</AttributeRelationship>
			</xsl:when>
			<xsl:otherwise>
				<!--xsl:message>Start processing [<xsl:value-of select="$prefix"/><xsl:value-of select="@name"/>] = bi:qualifier ...</xsl:message-->
				<Attribute>
					<name><xsl:value-of select="concat($prefix,@name)"/></name>
					<type>qualifier</type>
					<xsl:choose>
						<xsl:when test="@type">
							<datatype><xsl:value-of select="@type"/></datatype>
						</xsl:when>
						<xsl:otherwise>
							<!-- Unknown types will default to a stringType datatype -->
							<datatype>StringType</datatype>							
						</xsl:otherwise>
					</xsl:choose>

					<isIdentifier>false</isIdentifier>
					<isMandatory>
						<xsl:choose>
							<xsl:when test="@use='required'">true</xsl:when>
							<xsl:otherwise>false</xsl:otherwise>
						</xsl:choose>
					</isMandatory>
					<isReadOnly>false</isReadOnly>	
					<xsl:apply-templates select="xsd:annotation/xsd:documentation"/>				
				</Attribute>
				<!--xsl:message>End processing [<xsl:value-of select="$prefix"/><xsl:value-of select="@name"/>] = bi:qualifier ...</xsl:message-->				
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
	
	<xsl:template match="xsd:group[@ref]">
		<xsl:param name="component"/>
		<xsl:param name="prefix"/>
		<xsl:param name="onlyAttributeRelationship"/>

		<!--xsl:message>Start processing [<xsl:value-of select="@ref"/>] : xsd:group ...</xsl:message-->
		<xsl:variable name="ref" select="@ref"/>
		<!-- also apply for groups, see defect 939 -->
		<xsl:apply-templates select="/*/xsd:group[@name=$ref]/xsd:sequence/xsd:group">	
			<xsl:with-param name="component" select="$component"/>		
			<xsl:with-param name="prefix" select="$prefix"/>		
			<xsl:with-param name="onlyAttributeRelationship" select="$onlyAttributeRelationship"/>		
		</xsl:apply-templates>
		<xsl:apply-templates select="/*/xsd:group[@name=$ref]/xsd:sequence/xsd:element">	
			<xsl:with-param name="component" select="$component"/>		
			<xsl:with-param name="prefix" select="$prefix"/>		
			<xsl:with-param name="onlyAttributeRelationship" select="$onlyAttributeRelationship"/>		
		</xsl:apply-templates>
		<xsl:apply-templates select="/*/xsd:group[@name=$ref]/xsd:element">	
			<xsl:with-param name="component" select="$component"/>		
			<xsl:with-param name="prefix" select="$prefix"/>		
			<xsl:with-param name="onlyAttributeRelationship" select="$onlyAttributeRelationship"/>		
		</xsl:apply-templates>
		<!--xsl:message>End processing [<xsl:value-of select="@ref"/>] : xsd:group ...</xsl:message-->
	</xsl:template>

	<xsl:template match="xsd:element[@type]">
		<xsl:param name="component"/>
		<xsl:param name="prefix"/>
		<xsl:param name="onlyAttributeRelationship"/>
		<xsl:param name="foundFromRef"/>
		<!--xsl:message>Start element type processing [xsd:element[type=<xsl:value-of select="@type"/>, prefix=<xsl:value-of select="$prefix"/>, name=<xsl:value-of select="@name"/>], onlyAttrRels=<xsl:value-of select="$onlyAttributeRelationship"/>, foundFromRef=<xsl:value-of select="$foundFromRef"/>]] ...</xsl:message-->
		<xsl:variable name="type" select="@type"/>
		<xsl:choose>
			<!-- see defect 886: when an element is a simple type with attributes, translate it into an attribute with qualifiers -->
			<xsl:when test="/*/xsd:complexType[xsd:simpleContent and @name=$type] or /*/xsd:simpleType[@name=$type] or $type='UserAreaType' or /*/xsd:complexType[(xsd:sequence/xsd:element[@type] or (xsd:group and $foundFromRef!='true'))and @name=$type]">
				<xsl:choose>
					<xsl:when test="$onlyAttributeRelationship='true' and $foundFromRef!='true'">
						<!-- see defect 937: AttributeRelationship in this case -->
						<AttributeRelationship>
							<!--xsl:message>Relation created (type) foundFromRef=<xsl:value-of select="$foundFromRef"/>[xsd:element[type=<xsl:value-of select="@type"/>, name=<xsl:value-of select="$prefix"/><xsl:value-of select="@name"/>], onlyAttrRels=<xsl:value-of select="$onlyAttributeRelationship"/>]] ...</xsl:message-->
							<name><xsl:value-of select="@name"/></name>
							<position><xsl:value-of select="position()"/></position>
							<attribute><xsl:value-of select="$prefix"/><xsl:value-of select="@name"/></attribute>
						</AttributeRelationship>
					</xsl:when>
					<xsl:when test="/*/xsd:complexType[(xsd:sequence/xsd:element[@type] or xsd:group) and @name=$type and $onlyAttributeRelationship!='true']">
						<xsl:choose>
							<xsl:when test="$foundFromRef!='true'">
								<Attribute>
									<name><xsl:value-of select="concat($prefix,@name)"/></name>
									<type>group</type>
									<isIdentifier>false</isIdentifier>
									<isMandatory>false</isMandatory>
									<isReadOnly>false</isReadOnly>					
									<xsl:apply-templates select="/*/xsd:complexType[@name=$type]">
										<xsl:with-param name="component" select="$component"/>		
										<xsl:with-param name="prefix" select="concat($prefix,@name,'_')"/>
										<xsl:with-param name="onlyAttributeRelationship" select="'true'"/>
									</xsl:apply-templates>
									<xsl:apply-templates select="/*/xsd:element[@name=$type and @type=$type]/xsd:annotation/xsd:documentation"/>
								</Attribute>
								<xsl:apply-templates select="/*/xsd:complexType[(xsd:simpleContent or xsd:complexContent or xsd:sequence or xsd:group) and @name=$type]">
									<xsl:with-param name="component" select="$component"/>		
									<xsl:with-param name="prefix" select="concat($prefix,@name,'_')"/>		
									<xsl:with-param name="onlyAttributeRelationship" select="$onlyAttributeRelationship"/>		
								</xsl:apply-templates>
							</xsl:when>
							<xsl:otherwise>
								<xsl:apply-templates select="/*/xsd:complexType[(xsd:simpleContent or xsd:complexContent or xsd:sequence or xsd:group) and @name=$type]">
									<xsl:with-param name="component" select="$component"/>		
									<xsl:with-param name="prefix" select="$prefix"/>		
									<xsl:with-param name="onlyAttributeRelationship" select="$onlyAttributeRelationship"/>		
								</xsl:apply-templates>
							</xsl:otherwise>
						</xsl:choose>
					</xsl:when>
					<xsl:otherwise> 
						<xsl:if test="$onlyAttributeRelationship!='true'">
						<Attribute>
							<name><xsl:value-of select="concat($prefix,@name)"/></name>
		                    <type>simple</type>
							<!--xsl:message>Simple Attribute created (type) foundFromRef=<xsl:value-of select="$foundFromRef"/>[xsd:element[type=<xsl:value-of select="@type"/>, prefix=<xsl:value-of select="$prefix"/>, name=<xsl:value-of select="@name"/>], onlyAttrRels=<xsl:value-of select="$onlyAttributeRelationship"/>]] ...</xsl:message-->
							<xsl:choose>
								<xsl:when test="/*/xsd:complexType[@name=$type and count(xsd:sequence[xsd:any])=0 and count(xsd:simpleContent)=0]">
			                    	<datatype><xsl:value-of select="//xsd:complexType[@name=$type]/xsd:complexContent/xsd:extension/@base"/></datatype>
								</xsl:when>
								<xsl:otherwise> 
			                    	<datatype><xsl:value-of select="$type"/></datatype>
								</xsl:otherwise> 
							</xsl:choose>
		                    <isIdentifier>false</isIdentifier>
		                    <isMandatory>false</isMandatory>
		                    <isReadOnly>false</isReadOnly>
		                    <xsl:apply-templates select="/*/xsd:complexType[@name=$type]/xsd:simpleContent/xsd:extension">
								<xsl:with-param name="component" select="$component"/>		
								<xsl:with-param name="prefix" select="concat($prefix,@name,'_')"/>		
								<xsl:with-param name="onlyAttributeRelationship" select="'true'"/>
							</xsl:apply-templates>
						</Attribute>
						</xsl:if>
						<!--xsl:message>Simple Attribute <xsl:value-of select="concat($prefix,@name)"/> sibling start</xsl:message-->
						<xsl:choose>
							<xsl:when test="$foundFromRef!='true'">
								<xsl:apply-templates select="/*/xsd:complexType[(xsd:simpleContent or xsd:complexContent or xsd:sequence or xsd:group) and @name=$type]">
									<xsl:with-param name="component" select="$component"/>		
									<xsl:with-param name="prefix" select="concat($prefix,@name,'_')"/>		
									<xsl:with-param name="onlyAttributeRelationship" select="$onlyAttributeRelationship"/>		
								</xsl:apply-templates>
							</xsl:when>
							<xsl:otherwise>
								<xsl:apply-templates select="/*/xsd:complexType[(xsd:simpleContent or xsd:complexContent or xsd:sequence or xsd:group) and @name=$type]">
									<xsl:with-param name="component" select="$component"/>		
									<xsl:with-param name="prefix" select="$prefix"/>		
									<xsl:with-param name="onlyAttributeRelationship" select="$onlyAttributeRelationship"/>		
								</xsl:apply-templates>
							</xsl:otherwise>
						</xsl:choose>
						<!--xsl:message>Simple Attribute <xsl:value-of select="concat($prefix,@name)"/> sibling end</xsl:message-->
					</xsl:otherwise>
				</xsl:choose>
			</xsl:when>
			<xsl:otherwise>
				<xsl:apply-templates select="/*/xsd:complexType[(xsd:simpleContent or xsd:complexContent or xsd:sequence or xsd:group) and @name=$type]">
					<xsl:with-param name="component" select="$component"/>		
					<xsl:with-param name="prefix" select="$prefix"/>		
					<xsl:with-param name="onlyAttributeRelationship" select="$onlyAttributeRelationship"/>		
				</xsl:apply-templates>
			</xsl:otherwise>
		</xsl:choose>
		<!--xsl:message>End element type processing [xsd:element[type=<xsl:value-of select="@type"/>]] ...</xsl:message-->
	</xsl:template>

	<xsl:template match="xsd:element[@ref]">
		<xsl:param name="component"/>
		<xsl:param name="prefix"/>
		<xsl:param name="onlyAttributeRelationship"/>
		
		<xsl:variable name="ref" select="@ref"/>
		<xsl:variable name="type" select="/*/xsd:element[@name=$ref]/@type"/>
		<xsl:variable name="typedef" select="foo:typeOfElement(/,., $ref)"/>
		<!--xsl:message>Start element ref processing [<xsl:value-of select="concat($prefix,@ref)"/>] = bi:<xsl:value-of select="$typedef"/> ...</xsl:message-->		
		<xsl:choose>
			<xsl:when test="$onlyAttributeRelationship='true'">
				<xsl:if test="$typedef='simple' or $typedef='group' or $typedef='complex' or ($suppressComponents and $typedef='component')">
					<AttributeRelationship>
						<name><xsl:value-of select="@ref"/></name>
						<position><xsl:value-of select="position()"/></position>
						<attribute><xsl:value-of select="$prefix"/><xsl:value-of select="@ref"/></attribute>
					</AttributeRelationship>
				</xsl:if>
			</xsl:when>
			<xsl:otherwise>
				<!--xsl:message>Start processing [<xsl:value-of select="concat($prefix,@ref)"/>] = bi:<xsl:value-of select="$typedef"/> ...</xsl:message-->		
				<xsl:choose>
					<!-- <xsl:when test="/*/xsd:complexType[xsd:simpleContent and @name=$type] or /*/xsd:simpleType[@name=$type]"> -->
					<xsl:when test="$typedef='simple'">
						<Attribute>
							<name><xsl:value-of select="concat($prefix,@ref)"/></name>
							<type>simple</type>
							<xsl:choose>
								<xsl:when test="/*/xsd:complexType[@name=$type and count(xsd:sequence[xsd:any])=0 and count(xsd:simpleContent)=0]">
			                    	<datatype><xsl:value-of select="//xsd:complexType[@name=$type]/xsd:complexContent/xsd:extension/@base"/></datatype>
								</xsl:when>
								<xsl:otherwise> 
			                    	<datatype><xsl:value-of select="$type"/></datatype>
								</xsl:otherwise> 
							</xsl:choose>
							<isIdentifier>false</isIdentifier>
							<isMandatory>false</isMandatory>
							<isReadOnly>false</isReadOnly>					
							<xsl:apply-templates select="/*/xsd:complexType[@name=$type]/xsd:simpleContent/xsd:extension/xsd:attribute">
								<xsl:with-param name="component" select="$component"/>		
								<xsl:with-param name="prefix" select="concat($prefix,$ref,'_')"/>
								<xsl:with-param name="onlyAttributeRelationship" select="'true'"/>
							</xsl:apply-templates>
							<xsl:apply-templates select="/*/xsd:element[@name=$ref and @type=$type]/xsd:annotation/xsd:documentation"/>
						</Attribute>
						<xsl:apply-templates select="/*/xsd:complexType[@name=$type]/xsd:simpleContent/xsd:extension/xsd:attribute">
							<xsl:with-param name="component" select="$component"/>		
							<xsl:with-param name="prefix" select="concat($prefix,$ref,'_')"/>
							<xsl:with-param name="onlyAttributeRelationship" select="'false'"/>
						</xsl:apply-templates>
					</xsl:when>
		
					<xsl:when test="$typedef='group'">
						<Attribute>
							<name><xsl:value-of select="concat($prefix,@ref)"/></name>
							<type>group</type>
							<isIdentifier>false</isIdentifier>
							<isMandatory>false</isMandatory>
							<isReadOnly>false</isReadOnly>					
							<xsl:if test="not (starts-with($prefix, concat($ref, '_')) or contains($prefix, concat('_', $ref, '_')))">
								<!--xsl:message>Group <xsl:value-of select="concat($prefix,@ref)"/> children start</xsl:message-->
								<xsl:apply-templates select="/*/xsd:element[@name=$ref]">
									<xsl:with-param name="component" select="$component"/>		
									<xsl:with-param name="prefix" select="concat($prefix,$ref,'_')"/>
									<xsl:with-param name="onlyAttributeRelationship" select="'true'"/>
									<xsl:with-param name="foundFromRef" select="'true'"/>
								</xsl:apply-templates>
								<!--xsl:message>Group <xsl:value-of select="concat($prefix,@ref)"/> children end</xsl:message-->
							</xsl:if>
							<xsl:apply-templates select="/*/xsd:element[@name=$ref and @type=$type]/xsd:annotation/xsd:documentation"/>
						</Attribute>
						
						<xsl:if test="not (starts-with($prefix, concat($ref, '_')) or contains($prefix, concat('_', $ref, '_')))">
							<xsl:apply-templates select="/*/xsd:element[@name=$ref]">
								<xsl:with-param name="component" select="$component"/>		
								<xsl:with-param name="prefix" select="concat($prefix,$ref,'_')"/>
								<xsl:with-param name="foundFromRef" select="'true'"/>
							</xsl:apply-templates>
						</xsl:if>
					</xsl:when>
		
					<!-- <xsl:when test="/*/xsd:complexType[(xsd:complexContent or xsd:sequence) and @name=$type]"> -->
					<xsl:when test="$typedef='component'">
						<!-- <xsl:message>Component, comp [<xsl:value-of select="$component"/>], prefix [<xsl:value-of select="$prefix"/>], ref [<xsl:value-of select="$ref"/>]</xsl:message> -->		
						<xsl:choose>
							<xsl:when test="$component">
								<xsl:choose>
									<xsl:when test="$suppressComponents">
										<Attribute>
											<name><xsl:value-of select="concat($prefix,@ref)"/></name>	
											<type>group</type>
											<isIdentifier>false</isIdentifier>
											<isMandatory>false</isMandatory>
											<isReadOnly>false</isReadOnly>					
											<xsl:if test="not (starts-with($prefix, concat($ref, '_')) or contains($prefix, concat('_', $ref, '_')))">
												<xsl:apply-templates select="/*/xsd:element[@name=$ref]">
													<xsl:with-param name="component" select="$component"/>
													<xsl:with-param name="prefix" select="concat($prefix,$ref,'_')"/>
													<xsl:with-param name="onlyAttributeRelationship" select="'true'"/>		
													<xsl:with-param name="foundFromRef" select="'true'"/>
												</xsl:apply-templates>
											</xsl:if>
											<xsl:apply-templates select="/*/xsd:element[@name=$ref and @type=$type]/xsd:annotation/xsd:documentation"/>
										</Attribute>
										<xsl:choose>
											<xsl:when test="not (starts-with($prefix, concat($ref, '_')) or contains($prefix, concat('_', $ref, '_')))">
												<xsl:apply-templates select="/*/xsd:element[@name=$ref]">
													<xsl:with-param name="component" select="$component"/>
													<xsl:with-param name="prefix" select="concat($prefix,$ref,'_')"/>
													<xsl:with-param name="foundFromRef" select="'true'"/>
												</xsl:apply-templates>
											</xsl:when>
											<xsl:otherwise>
												<xsl:message>Loop for Component, ref [<xsl:value-of select="$ref"/>] prefix [<xsl:value-of select="$prefix"/>]</xsl:message>	
											</xsl:otherwise>
										</xsl:choose>
									</xsl:when>
									<xsl:otherwise>
										<Relationship>
											<name><xsl:value-of select="@ref"/></name>
											<type>aggregation</type>
											<xsl:choose>
												<xsl:when test="@maxOccurs">
													<xsl:choose>
														<xsl:when test="@minOccurs">
															<xsl:if test="@minOccurs='0'">
																<multiplicity>zeroToOne</multiplicity>
															</xsl:if>
															<xsl:if test="@minOccurs='0' and @maxOccurs='unbounded'">
																<multiplicity>zeroToMany</multiplicity>
															</xsl:if>
														</xsl:when>
														<xsl:otherwise>
															<xsl:if test="@maxOccurs='unbounded'">
																<multiplicity>oneToMany</multiplicity>
															</xsl:if>
														</xsl:otherwise>
													</xsl:choose>
												</xsl:when>
												<xsl:otherwise>
													<xsl:choose>
														<xsl:when test="@minOccurs and @minOccurs='0'">
															<multiplicity>zeroToOne</multiplicity>
														</xsl:when>
														<xsl:otherwise>
															<multiplicity>oneToOne</multiplicity>
														</xsl:otherwise>
													</xsl:choose>
												</xsl:otherwise>
											</xsl:choose>
											
											<Component>
												<name><xsl:value-of select="concat($prefix,@ref)"/></name>				
												<xsl:if test="not (starts-with($component, concat($ref, '_')) or contains($component, concat('_', $ref, '_')))">
													<xsl:apply-templates select="/*/xsd:element[@name=$ref]">
														<xsl:with-param name="component" select="concat($component,$prefix,$ref,'_')"/>		
													</xsl:apply-templates>
												</xsl:if>
												<xsl:apply-templates select="/*/xsd:element[@name=$ref and @type=$type]/xsd:annotation/xsd:documentation"/>
											</Component>
										</Relationship>
									</xsl:otherwise>
								</xsl:choose>
							</xsl:when>
							<xsl:otherwise>					
								<xsl:apply-templates select="/*/xsd:element[@name=$ref]">
									<xsl:with-param name="component" select="concat($component,$ref,'_')"/>		
								</xsl:apply-templates>
								<xsl:apply-templates select="/*/xsd:element[@name=$ref and @type=$type]/xsd:annotation/xsd:documentation"/>
							</xsl:otherwise>
						</xsl:choose>
					</xsl:when>
					
					<xsl:when test="$typedef='complex'">
						<Attribute>
							<name><xsl:value-of select="concat($prefix,@ref)"/></name>
							<type>complex</type>
							<datatype><xsl:value-of select="@ref"/></datatype>
							<isIdentifier>false</isIdentifier>
							<isMandatory>false</isMandatory>
							<isReadOnly>false</isReadOnly>					
							<xsl:apply-templates select="/*/xsd:element[@name=$ref]/xsd:complexType">
								<xsl:with-param name="component" select="$component"/>		
								<xsl:with-param name="prefix" select="concat($prefix,$ref,'_')"/>
								<xsl:with-param name="onlyAttributeRelationship" select="'true'"/>
							</xsl:apply-templates>
							<xsl:apply-templates select="/*/xsd:element[@name=$ref]/xsd:annotation/xsd:documentation"/>
						</Attribute>
						<xsl:apply-templates select="/*/xsd:element[@name=$ref]/xsd:complexType">
							<xsl:with-param name="component" select="$component"/>		
							<xsl:with-param name="prefix" select="concat($prefix,$ref,'_')"/>
							<xsl:with-param name="onlyAttributeRelationship" select="'false'"/>
						</xsl:apply-templates>
					</xsl:when>
					
					<xsl:otherwise>
						<xsl:message>ERROR[unknown element <xsl:value-of select="concat($component,$prefix,@ref)"/>]</xsl:message>
					</xsl:otherwise>
				</xsl:choose>
			</xsl:otherwise>
		</xsl:choose>
		<!--xsl:message>End element ref processing [<xsl:value-of select="concat($component,$prefix,@ref)"/>] = bi:<xsl:value-of select="$typedef"/> ...</xsl:message-->
	</xsl:template>	
	
	<!-- 
		Return an xsl:sequence with elements containing all types of 
		all xsd:element's, xsd:sequence's and xsd:complexType's of the 
		input xsd:sequence. Is privately used by the foo:typeOfSequence()
		function.
		
		@param		root		the root of the XML document
		@param		element		the xsd:sequence element to be checked
		@return					all types of the xsd:sequence element, which can be either 'group' or 'component'.
	-->		
	<!-- PRIVATE --><xsl:function name="foo:typeOfSequenceAA">
		<xsl:param name="root"/>
		<xsl:param name="element"/>
		<xsl:param name="prefix"/>

		<xsl:sequence select="'group'"/>
		
		<xsl:for-each select="$element/xsd:element[@ref]">
			<xsl:variable name="ref" select="./@ref"/>
			<xsl:if test="not (starts-with($prefix, concat($ref, '_')) or contains($prefix, concat('_', $ref, '_')))">
				<xsl:sequence select="foo:typeOfElement($root,., concat($prefix, '_', $ref))"/>
			</xsl:if>
		</xsl:for-each>
		
		<xsl:for-each select="$element/xsd:group[@ref]">
			<xsl:variable name="ref" select="./@ref"/>
			<xsl:sequence select="foo:typeOfSequenceAA($root,$root/*/xsd:group[@name=$ref]/xsd:sequence, $prefix)"/>
		</xsl:for-each>

		<xsl:for-each select="$element/xsd:choice">
			<xsl:for-each select="./xsd:sequence">
				<xsl:sequence select="foo:typeOfSequenceAA($root,., $prefix)"/>
			</xsl:for-each>
			<xsl:for-each select="./xsd:element[@ref]">
				<xsl:variable name="ref" select="./@ref"/>
				<xsl:if test="not (starts-with($prefix, concat($ref, '_')) or contains($prefix, concat('_', $ref, '_')))">
					<xsl:sequence select="foo:typeOfElement($root,., concat($prefix, '_', $ref))"/>
				</xsl:if>
			</xsl:for-each>
		</xsl:for-each>
	</xsl:function>

	<!-- 
		Return an xsl:sequence with one element containing the type of the input xsd:sequence. 
		
		@param		root		the root of the XML document
		@param		element		the xsd:sequence element to be checked
		@return					the type of the complexType element, which can be either 'group' or 'component'.
	-->		
	<xsl:function name="foo:typeOfSequence" as="xsd:string">
		<xsl:param name="root"/>
		<xsl:param name="element"/>
		<xsl:param name="prefix"/>

		<xsl:variable name="type" select="foo:typeOfSequenceAA($root,$element, $prefix)"/>
		<xsl:choose>
			<xsl:when test="exists(index-of($type,'component'))"><xsl:sequence select="'component'"/></xsl:when>
			<xsl:otherwise><xsl:sequence select="'group'"/></xsl:otherwise>
		</xsl:choose>
	</xsl:function>
		
	<!-- 
		Return an xsl:sequence with one element containing the type of the input xsd:complexType. 
		
		@param		root		the root of the XML document
		@param		element		the xsd:complexType element to be checked
		@return					the type of the xsd:complexType element, which can be either 'group' or 'component'.
	-->		
	<xsl:function name="foo:typeOfComplexType" as="xsd:string">
		<xsl:param name="root"/>
		<xsl:param name="element"/>
		<xsl:param name="prefix"/>
		<xsl:param name="prevbase"/>

		<xsl:choose>
			<xsl:when test="$element/xsd:sequence">
				<xsl:sequence select="foo:typeOfSequence($root,$element/xsd:sequence, $prefix)"/>
			</xsl:when>
			
			<xsl:when test="$element/xsd:complexContent">
				<xsl:variable name="base" select="$element/xsd:complexContent/xsd:extension/@base"/>
				<xsl:choose>
					<xsl:when test="$base=$prevbase">
						<xsl:choose>
							<xsl:when test="$element/xsd:complexContent/xsd:extension/xsd:sequence">
								<xsl:sequence select="foo:typeOfSequence($root,$element/xsd:sequence, $prefix)"/>
							</xsl:when>
							<xsl:when test="$element/xsd:complexContent/xsd:extension">
								<xsl:sequence select="foo:typeOfComplexType($root,$root/*/xsd:complexType[@name=$base], $prefix, $base)"/>
							</xsl:when>
							<xsl:otherwise><xsl:sequence select="'group'"/></xsl:otherwise>
						</xsl:choose>
					</xsl:when>
					<xsl:otherwise>
						<xsl:variable name="typedef" select="foo:typeOfComplexType($root,$root/*/xsd:complexType[@name=$base], $prefix, $base)"/>
						
						<xsl:choose>
							<xsl:when test="$typedef='component'">
								<xsl:sequence select="'component'"/>
							</xsl:when>
							<xsl:otherwise>
								<xsl:choose>
									<xsl:when test="$element/xsd:complexContent/xsd:extension/xsd:sequence">
										<xsl:sequence select="foo:typeOfSequence($root,$element/xsd:sequence, $prefix)"/>
									</xsl:when>
									<xsl:when test="$element/xsd:complexContent/xsd:extension">
										<xsl:sequence select="foo:typeOfComplexType($root,$root/*/xsd:complexType[@name=$base], $prefix, $base)"/>
									</xsl:when>
									<xsl:otherwise><xsl:sequence select="'group'"/></xsl:otherwise>
								</xsl:choose>
							</xsl:otherwise>
						</xsl:choose>	
					</xsl:otherwise>
				</xsl:choose>

			</xsl:when>

			<xsl:when test="$element/xsd:group">
				<xsl:variable name="ref" select="$element/xsd:group/@ref"/>
				<xsl:sequence select="foo:typeOfSequence($root,$root/*/xsd:group[@name=$ref]/xsd:sequence, $prefix)"/>
			</xsl:when>
			
			<xsl:when test="$element/xsd:simpleContent">
				<xsl:sequence select="'simple'"/>		
			</xsl:when>
			
			<xsl:otherwise>
				<xsl:sequence select="'group'"/>		
			</xsl:otherwise>
		</xsl:choose>
	</xsl:function>
	
	<!-- 
		Return an xsl:sequence with one element containing the type of the input element. 
		
		@param		root		the root of the XML document
		@param		element		the element to be checked
		@return					the type of the element, which can be either 'simple', 'group' or 'component'.
	-->
	<xsl:function name="foo:typeOfElement" as="xsd:string">
		<xsl:param name="root"/>
		<xsl:param name="element"/>
		<xsl:param name="prefix"/>
		
		<xsl:variable name="ref" select="$element/@ref"/>
		<xsl:variable name="type" select="$root/*/xsd:element[@name=$ref]/@type"/>		
		<xsl:variable name="maxOccurs" select="$element/@maxOccurs"/>		

		<xsl:choose>
			<xsl:when test="$root/*/xsd:complexType[xsd:simpleContent and @name=$type] or $root/*/xsd:simpleType[@name=$type] or $type='UserAreaType'">
				<xsl:sequence select="'simple'"/>
			</xsl:when>
			<xsl:when test="$root/*/xsd:complexType[(xsd:complexContent or xsd:sequence or xsd:group) and @name=$type]">
				<xsl:choose>
					<xsl:when test="$maxOccurs='unbounded'">
						<xsl:sequence select="'component'"/>
					</xsl:when>
					<xsl:otherwise>
						<xsl:sequence select="foo:typeOfComplexType($root,$root/*/xsd:complexType[(xsd:complexContent or xsd:sequence or xsd:group) and @name=$type], $prefix, '')"/>
					</xsl:otherwise>
				</xsl:choose>
			</xsl:when>
			<xsl:otherwise>
				<xsl:choose>
					<xsl:when test="$root/*/xsd:element[@name=$ref]/xsd:complexType">
						<xsl:sequence select="'complex'"/>
					</xsl:when>
					<xsl:otherwise>
						<!--xsl:message>Unknown Type, prefix:<xsl:value-of select="$prefix"/> ref:<xsl:value-of select="$ref"/> type:<xsl:value-of select="$type"/></xsl:message-->
						<xsl:sequence select="'unknown'"/>
					</xsl:otherwise>
				</xsl:choose>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:function>		

	<!-- Creates documentation attributes based upon the 'any' contents of the annotation elements -->	
	<xsl:template match="xsd:documentation">
	<description>
		<xsl:variable name="plaintext" select="substring(text(),1,50)"/>
		<xsl:choose>
			<xsl:when test="string-length($plaintext)>0">
				<!-- shows the first 50 characters of the plain text in the documentation -->
				<xsl:value-of select="$plaintext"/>
			</xsl:when>
			<xsl:otherwise>
				<xsl:choose>
					<xsl:when test="child::ccts:Definition or child::ccts:DefinitionText">
						<xsl:apply-templates select="ccts:Definition|ccts:DefinitionText"/>
					</xsl:when>
					<xsl:otherwise>
						<!-- shows the first 50 characters of the 'dirty' text in the documentation, such as text in <ccts:...> elements -->
						<xsl:variable name="dirtytext">
             				<xsl:for-each select="child::*">
								<xsl:copy-of select="concat('&lt;',name(),'&gt;',text(),'&lt;/',name(),'&gt;','&#xA;')"/>
							</xsl:for-each>
          				</xsl:variable>
						<xsl:value-of select="substring($dirtytext,1,50)"/>
					</xsl:otherwise>
				</xsl:choose>
			</xsl:otherwise>
		</xsl:choose>
	</description>
	<documentation>
		<xsl:variable name="dirtytext">
     		<xsl:for-each select="child::*">
				<xsl:copy-of select="concat('&lt;',name(),'&gt;',text(),'&lt;/',name(),'&gt;','&#xA;')"/>
			</xsl:for-each>
  		</xsl:variable>
		<xsl:value-of select="$dirtytext"/>
		<xsl:value-of select="text()"/>
	</documentation>
	</xsl:template>
	
	<xsl:template match="ccts:Definition|ccts:DefinitionText">
		<xsl:value-of select="substring(.,1,50)"/>
	</xsl:template>
	
	<xsl:template match="xsd:complexType[xsd:simpleContent]" mode="datatype">
		<!--xsl:message>Found datatype [<xsl:value-of select="@name"/>] ...</xsl:message-->
		<Datatype>
			<name><xsl:value-of select="@name"/></name>
			<xsl:choose>
				<xsl:when test="starts-with(xsd:simpleContent/xsd:extension/@base,'xsd:')">
					<primitiveDatatype><xsl:value-of select="substring-after(xsd:simpleContent/xsd:extension/@base,'xsd:')"/></primitiveDatatype>						
				</xsl:when>
				<xsl:otherwise>
					<xsl:choose>
						<xsl:when test="contains(xsd:simpleContent/xsd:extension/@base,':')">					
							<base><xsl:value-of select="substring-after(xsd:simpleContent/xsd:extension/@base,':')"/></base>
						</xsl:when>
						<xsl:otherwise>
							<base><xsl:value-of select="xsd:simpleContent/xsd:extension/@base"/></base>
						</xsl:otherwise>
					</xsl:choose>						
					<primitiveDatatype>anyType</primitiveDatatype>						
				</xsl:otherwise>
			</xsl:choose>
			<xsl:apply-templates select="xsd:simpleContent/xsd:extension/xsd:attribute" mode="datatype"/>
			<xsl:apply-templates select="xsd:annotation/xsd:documentation"/>
		</Datatype>		
	</xsl:template>
	
	<xsl:template match="xsd:simpleContent/xsd:extension/xsd:attribute" mode="datatype">
	<!--xsl:message>Found DatatypeRelationship [<xsl:value-of select="@name"/>] ...</xsl:message-->
	<DatatypeRelationship>
		<name><xsl:value-of select="@name"/></name>
		<xsl:choose>
			<xsl:when test="@type = 'xsd:anyURI'">
				<datatype>URIType</datatype>
			</xsl:when>
			<xsl:when test="@type = 'xsd:hexBinary'">
				<datatype>HexBinaryObjectType</datatype>
			</xsl:when>
			<xsl:when test="@type = 'xsd:gYear'">
				<datatype>YearDateType</datatype>
			</xsl:when>
			<xsl:when test="@type = 'xsd:gYearMonth'">
				<datatype>YearMonthDateType</datatype>
			</xsl:when>
			<xsl:when test="@type = 'xsd:float'">
				<datatype>FloatNumericType</datatype>
			</xsl:when>
			<xsl:when test="@type = 'xsd:double'">
				<datatype>DoubleNumericType</datatype>
			</xsl:when>
			<xsl:when test="@type = 'xsd:integer'">
				<datatype>IntegerNumericType</datatype>
			</xsl:when>
			<xsl:when test="@type = 'xsd:positiveInteger'">
				<datatype>PositiveIntegerNumericType</datatype>
			</xsl:when>
			<xsl:when test="@type = 'xsd:negativeInteger'">
				<datatype>NegativeIntegerNumericType</datatype>
			</xsl:when>
			<xsl:when test="@type = 'xsd:nonPositiveInteger'">
				<datatype>NonPositiveIntegerNumericType</datatype>
			</xsl:when>
			<xsl:when test="@type = 'xsd:nonNegativeInteger'">
				<datatype>NonNegativeIntegerNumericType</datatype>
			</xsl:when>
			<xsl:when test="@type = 'xsd:duration'">
				<datatype>DurationMeasureType</datatype>
			</xsl:when>
			<xsl:when test="@type = 'xsd:language'">
				<datatype>LanguageCodeContentType</datatype>
			</xsl:when>
			<xsl:when test="starts-with(@type,'xsd:')">
					<xsl:variable name="typetext" select="substring-after(@type,'xsd:')"/>
					<xsl:variable name="capitalfirstletter" select="upper-case(substring($typetext,1,1))"/>
					<xsl:variable name="capitalizedtext" select="concat($capitalfirstletter,substring($typetext,2))"/>
					<datatype><xsl:value-of select="concat($capitalizedtext,'Type')"/></datatype>					
			</xsl:when>
			<xsl:otherwise>
				<xsl:choose>
					<xsl:when test="contains(@type,':')">
						<datatype><xsl:value-of select="substring-after(@type,':')"/></datatype>
					</xsl:when>
					<xsl:otherwise>
						<datatype><xsl:value-of select="@type"/></datatype>
					</xsl:otherwise>
				</xsl:choose>
			</xsl:otherwise>
		</xsl:choose>
		<isQualifier>true</isQualifier>
		<position><xsl:value-of select="position()"/></position>
		<xsl:apply-templates select="xsd:annotation/xsd:documentation"/>
	</DatatypeRelationship>
	</xsl:template>
	
	<!-- Transform an xsd:simpleType into a Datatype artifact -->
	<xsl:template match="xsd:simpleType[xsd:union]" mode="datatype">
		<!--xsl:message>Found datatype [<xsl:value-of select="@name"/>] xsd:union ...</xsl:message-->
		<xsl:variable name="memberTypes" select="xsd:union/@memberTypes"/>
		<xsl:variable name="name" select="@name"/>
		<xsl:if test="not (contains($memberTypes, concat(':', $name, ' ')))">
			<Datatype>
				<name><xsl:value-of select="@name"/></name>
				<primitiveDatatype>anyType</primitiveDatatype>
				<xsl:apply-templates select="xsd:annotation/xsd:documentation"/>						
			</Datatype>
		</xsl:if>
	</xsl:template>
	
	<xsl:template match="xsd:simpleType[xsd:restriction]" mode="datatype">
		<!--xsl:message>Found datatype [<xsl:value-of select="@name"/>] ...</xsl:message-->
		<Datatype>
			<name><xsl:value-of select="@name"/></name>
			<xsl:choose>
				<xsl:when test="starts-with(xsd:restriction/@base,'xsd:')">
					<primitiveDatatype><xsl:value-of select="substring-after(xsd:restriction/@base,'xsd:')"/></primitiveDatatype>						
				</xsl:when>
				<xsl:otherwise>
					<primitiveDatatype>anyType</primitiveDatatype>
					<xsl:choose>
						<xsl:when test="contains(xsd:restriction/@base,':')">					
							<base><xsl:value-of select="substring-after(xsd:restriction/@base,':')"/></base>
						</xsl:when>
						<xsl:otherwise>
							<base><xsl:value-of select="xsd:restriction/@base"/></base>
						</xsl:otherwise>
					</xsl:choose>					
				</xsl:otherwise>
			</xsl:choose>
			<xsl:for-each select="xsd:restriction/*">
				<Facet>
					<type><xsl:value-of select="local-name(.)"/></type>
					<value><xsl:value-of select="@value"/></value>
					<xsl:apply-templates select="xsd:annotation/xsd:documentation"/>
				</Facet>
			</xsl:for-each>
			<xsl:apply-templates select="xsd:annotation/xsd:documentation"/>	
		</Datatype>
	</xsl:template>

	<!-- Transform an xsd:simpleType into a Datatype artifact -->
	<xsl:template match="xsd:simpleType" mode="datatype">
		<!--xsl:message>Found datatype [<xsl:value-of select="@name"/>] xsd:simpleType ...</xsl:message-->
		<Datatype>
			<name><xsl:value-of select="@name"/></name>
			<primitiveDatatype>anyType</primitiveDatatype>
			<xsl:apply-templates select="xsd:annotation/xsd:documentation"/>						
		</Datatype>
	</xsl:template>
	
</xsl:stylesheet>
