<?xml version="1.0" encoding="UTF-8"?>
<!--
  Copyright 2022 UCAIug

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  https://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

  See the License for the specific language governing permissions and
  limitations under the License.
-->
<xsl:stylesheet version="1.0"
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:xs="http://www.w3.org/2001/XMLSchema"
	xmlns:a="http://langdale.com.au/2005/Message#"
	xmlns:sawsdl="http://www.w3.org/ns/sawsdl"
	xmlns="http://langdale.com.au/2009/Indent">

	<xsl:output indent="yes" method="xml" encoding="utf-8" />
	<xsl:param name="version"/>
	<xsl:param name="baseURI"/>
	<xsl:param name="envelope">Profile</xsl:param>

	<xsl:template name="ident">
		<xsl:param name="name" select="@name"/>
		<xsl:text>"</xsl:text><xsl:value-of select="$name"/><xsl:text>"</xsl:text>
	</xsl:template>
	
	<xsl:param name="mridType">CHAR VARYING(30)</xsl:param>

	<xsl:template name="type">
		<xsl:text> </xsl:text>
		<xsl:choose>
			<xsl:when test="@xstype = 'string'">CHAR VARYING(30)</xsl:when>
			<xsl:when test="@xstype = 'integer' or @xstype = 'int'">INTEGER</xsl:when>
			<xsl:when test="@xstype = 'float'">DOUBLE PRECISION</xsl:when>
			<xsl:when test="@xstype = 'double'">DOUBLE PRECISION</xsl:when>
			<xsl:when test="@xstype = 'boolean'">CHAR(1)</xsl:when>
			<xsl:otherwise>CHAR VARYING(30)</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
	
	<xsl:template name="notnull">
		<xsl:if test="@minOccurs > 0"> NOT NULL</xsl:if>
	</xsl:template>
 
	<xsl:template match="a:Catalog">
		<!--  the top level template  -->
		<document>
			<list indent="-- ">
				<item>Schema for <xsl:value-of select="$envelope" /></item>
				<item>Generated by CIMTool https://cimtool.ucaiug.io/</item>
			</list>
		    <xsl:apply-templates/>
			<item/>
		    <xsl:apply-templates mode="constraints"/>
		</document>
	</xsl:template>

	<xsl:template match="a:ComplexType|a:Root">
		<!-- a table -->
		<item/>
		<xsl:call-template name="annotate" />
		<item>CREATE TABLE <xsl:call-template name="ident"/></item>
		<list begin="(" indent="    " delim="," end=");"> 
		    <item>"mRID" <xsl:value-of select="$mridType"/> NOT NULL UNIQUE</item>
		    <xsl:apply-templates/>
		</list>
	</xsl:template>

	<xsl:template match="a:ComplexType|a:Root" mode="constraints" >
		<xsl:apply-templates mode="constraints"/>
	</xsl:template>
	
	<xsl:template match="a:SuperType" mode="constraints">
		<list indent="-- ">subclass-superclass constraint</list>
		<item>
		    ALTER TABLE 
			<xsl:call-template name="ident">
		        <xsl:with-param name="name" select="../@name"/>
			</xsl:call-template>
		    ADD FOREIGN KEY ( "mRID" ) REFERENCES 
		    <xsl:call-template name="ident"/>
		    ( "mRID" );
		</item> 
	</xsl:template>

	<xsl:template match="a:EnumeratedType">
		<!-- a reference table for an enumeration -->
		<item/>
		<xsl:call-template name="annotate" />
		<item>
		    CREATE TABLE <xsl:call-template name="ident"/>
		    ( "name" CHAR VARYING(30) UNIQUE );
		</item>    

		<xsl:variable name="name" select="@name"/>
		<xsl:for-each select="a:EnumeratedValue">
			<!-- inserts one value into a reference table -->
			<xsl:call-template name="annotate" />
			<item>
				INSERT INTO 
    		    <xsl:call-template name="ident">
    			    <xsl:with-param name="name" select="$name"/>
    		    </xsl:call-template> 
			    ( "name" ) VALUES ( '<xsl:value-of select="@name"/>' );
			</item>
		</xsl:for-each>
	</xsl:template>

	<xsl:template match="a:Instance|a:Reference">
		<xsl:if test="@maxOccurs &lt;= 1 and @name != 'mRID'">
			<!-- a foreign key column -->
			<decorate>
				<xsl:call-template name="annotate" />
				<item>
					<xsl:call-template name="ident"/>
					<xsl:value-of select="$mridType"/>
					<xsl:call-template name="notnull"/>
				</item>
			</decorate>
		</xsl:if>
	</xsl:template>
	
	<xsl:template match="a:Instance|a:Reference" mode="constraints">
		<xsl:if test="@maxOccurs &lt;= 1 and @name != 'mRID'">
			<list indent="-- ">association constraint</list>
			<item>
				ALTER TABLE
				<xsl:call-template name="ident">
					<xsl:with-param name="name" select="../@name"/>
				</xsl:call-template>
				ADD FOREIGN KEY ( <xsl:call-template name="ident"/> ) 
				REFERENCES   
	   			<xsl:call-template name="ident">
					<xsl:with-param name="name" select="@type"/>
				</xsl:call-template> 
				( "mRID" ); 
			</item> 
		</xsl:if>
	</xsl:template>
	
	<xsl:template match="a:Enumerated">
		<!-- a foreign key column for a reference table -->
		<decorate>
			<xsl:call-template name="annotate" />
			<item>
				<xsl:call-template name="ident"/>
				CHAR VARYING(30)
				<xsl:call-template name="notnull"/>
			</item>
		</decorate>
	</xsl:template>
	
	<xsl:template match="a:Enumerated" mode="constraints">
		<list indent="-- ">enumerated value constraint</list>
		<item>
			ALTER TABLE
			<xsl:call-template name="ident">
				<xsl:with-param name="name" select="../@name"/>
			</xsl:call-template>
			ADD FOREIGN KEY ( <xsl:call-template name="ident"/> ) 
			REFERENCES 
   			<xsl:call-template name="ident">
				<xsl:with-param name="name" select="@type"/>
			</xsl:call-template> 
			( "name" );
		</item> 
	</xsl:template>

	<xsl:template match="a:Simple|a:Domain">
		<!-- a simple column  -->
		<xsl:if test="@maxOccurs &lt;= 1 and @name != 'mRID'">
			<decorate>
				<xsl:call-template name="annotate" />
				<item>
					<xsl:call-template name="ident"/>
					<xsl:call-template name="type"/>
					<xsl:call-template name="notnull"/>
				</item>
			</decorate>
		</xsl:if>
	</xsl:template>

	<xsl:template name="annotate">
		<!--  generate and annotation -->
		<list indent="-- ">
			<xsl:apply-templates mode="annotate"/>
		</list>
	</xsl:template>

	<xsl:template match="a:Comment|a:Note" mode="annotate">
		<!--  generate human readable annotation -->
		<wrap width="70">
			<xsl:value-of select="."/>
		</wrap>
	</xsl:template>

	<xsl:template match="text()">
		<!--  dont pass text through  -->
	</xsl:template>

	<xsl:template match="node()" mode="constraints">
		<!-- dont pass any defaults in constraints mode -->
	</xsl:template>

	<xsl:template match="node()" mode="annotate">
		<!-- dont pass any defaults in annotate mode -->
	</xsl:template>

</xsl:stylesheet>
