<?xml version="1.0"?>

<!--
 This file is part of GMetaDOM
 a generic bind package for the Document Object Model API.
 Copyright (C) 2001-2002  Luca Padovani <luca.padovani@cs.unibo.it>
               2001 Claudio Sacerdoti Coen <sacerdot@cs.unibo.it>
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.
 
 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.
 
 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

 For more information, please visit the project home page
 http://gmetadom.sourceforge.net
 or send an email to <luca.padovani@cs.unibo.it>
-->

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:import href="xslutils.xsl"/>

<xsl:output method="text"/>
<xsl:param name="module" select="'Core'"/>
<xsl:param name="uriprefix" select="''"/>
<xsl:param name="annotations" select="''"/>

<xsl:template match="interface">
<xsl:variable name="prefix">
  <xsl:call-template name="gdomePrefixOfType">
    <xsl:with-param name="type" select="@name"/>
  </xsl:call-template>
</xsl:variable>

<xsl:variable name="lcmodule">
 <xsl:call-template name="toLowerCase">
  <xsl:with-param name="string" select="$module"/>
 </xsl:call-template>
</xsl:variable>

and <xsl:value-of select="$lcmodule"/>
 <xsl:text> (obj : T</xsl:text>
 <xsl:value-of select="@name"/>
 <xsl:text>.t) =
 object
</xsl:text>
<xsl:if test="@name = 'Node'">
 <!-- There must be a solution better than this if -->
 <xsl:text>  inherit (eventTarget (obj :&gt; TEventTarget.t))
</xsl:text>
</xsl:if>
<xsl:if test="@inherits">
 <xsl:variable name="lcinherits">
  <xsl:call-template name="toLowerCase">
   <xsl:with-param name="string" select="@inherits"/>
  </xsl:call-template>
 </xsl:variable>
 <xsl:text>  inherit (</xsl:text><xsl:value-of select="$lcinherits"/> (obj :&gt; T<xsl:value-of select="@inherits"/>.t))
</xsl:if>
 <xsl:text>  method as_</xsl:text><xsl:value-of select="@name"/>
 <xsl:text> = obj
</xsl:text>
<xsl:apply-templates select="attribute">
  <xsl:with-param name="interface" select="@name"/>
  <xsl:with-param name="prefix" select="$prefix"/>
</xsl:apply-templates>
<xsl:apply-templates select="method">
  <xsl:with-param name="interface" select="@name"/>
  <xsl:with-param name="prefix" select="$prefix"/>
</xsl:apply-templates>
<xsl:text> end</xsl:text>
</xsl:template>

<xsl:template match="attribute">
  <xsl:param name="interface" select="''"/>
  <xsl:param name="prefix" select="''"/>
  <xsl:variable name="name" select="@name"/>
  <xsl:text>  method get_</xsl:text><xsl:value-of select="$name"/>
  <xsl:text> = </xsl:text>
  <xsl:variable name="isNullable" select="document($annotations)/Annotations/Attribute[@name = $name]/@nullable = 'yes'"/>
  <xsl:call-template name="call_pre_method">
   <xsl:with-param name="type" select="@type"/>
   <xsl:with-param name="isNullable" select="$isNullable"/>
   <xsl:with-param name="action">
    <xsl:text>I</xsl:text><xsl:value-of select="$interface"/>.<xsl:text>get_</xsl:text><xsl:value-of select="@name"/>
    <xsl:text> ~this:obj</xsl:text>
   </xsl:with-param>
  </xsl:call-template>
  <xsl:if test="not(@readonly)">
   <xsl:text>  method set_</xsl:text><xsl:value-of select="@name"/>
   <xsl:text> ~value = </xsl:text>
   <xsl:text>I</xsl:text><xsl:value-of select="$module"/>.set_<xsl:value-of select="@name"/><xsl:text> ~this:obj</xsl:text>
   <xsl:call-template name="pre_method_object_of_object">
    <xsl:with-param name="name" select="'value'"/>
    <xsl:with-param name="type" select="@type"/>
    <xsl:with-param name="isNullable" select="$isNullable"/>
   </xsl:call-template>
   <xsl:text>
</xsl:text>
  </xsl:if>
</xsl:template>

<xsl:template name="call_pre_method">
 <xsl:param name="type" select="/.."/>
 <xsl:param name="isNullable" select="/.."/>
 <xsl:param name="action" select="/.."/>
 <xsl:variable name="isNotPrimitiveType">
  <xsl:call-template name="isNotPrimitiveType">
   <xsl:with-param name="type" select="$type"/>
  </xsl:call-template>
 </xsl:variable>
 <xsl:if test="string($isNotPrimitiveType) = 'true'">
  <xsl:text>let obj = </xsl:text>
 </xsl:if>
 <xsl:copy-of select="$action"/>
 <xsl:if test="string($isNotPrimitiveType) = 'true'">
  <xsl:text> in </xsl:text>
  <xsl:if test="$isNullable">match obj with None -&gt; None | Some obj -&gt; Some (</xsl:if>
  <xsl:variable name="lctype">
   <xsl:call-template name="toLowerCase">
    <xsl:with-param name="string" select="$type"/>
   </xsl:call-template>
  </xsl:variable>
  <xsl:text>new </xsl:text><xsl:value-of select="$lctype"/><xsl:text> obj</xsl:text>
  <xsl:if test="$isNullable">)</xsl:if>
 </xsl:if>
<xsl:text>
</xsl:text>
</xsl:template>

<xsl:template match="method" >
  <xsl:param name="interface" select="''"/>
  <xsl:param name="prefix" select="''"/>
  <xsl:param name="name" select="@name"/>
  <xsl:text>  method </xsl:text>
  <xsl:value-of select="@name"/>
  <xsl:apply-templates mode="left" select="parameters">
   <xsl:with-param name="@name"/>
  </xsl:apply-templates>
  <xsl:text> = </xsl:text>
  <xsl:call-template name="call_pre_method">
   <xsl:with-param name="type" select="returns/@type"/>
   <xsl:with-param name="isNullable" select="document($annotations)/Annotations/Method[@name = $name]/@nullable = 'yes'"/>
   <xsl:with-param name="action">
    <xsl:text>I</xsl:text><xsl:value-of select="$interface"/>.<xsl:value-of select="@name"/><xsl:text> ~this:obj </xsl:text>
    <xsl:apply-templates mode="right" select="parameters">
     <xsl:with-param name="name" select="@name"/>
    </xsl:apply-templates>
   </xsl:with-param>
  </xsl:call-template>
</xsl:template>

<xsl:template match="parameters" mode="left">
  <xsl:param name="name" select="''"/>
  <xsl:apply-templates select="param" mode="left">
    <xsl:with-param name="methodName" select="$name"/>
  </xsl:apply-templates>
</xsl:template>

<xsl:template match="parameters" mode="right">
  <xsl:param name="name" select="''"/>
  <xsl:apply-templates select="param" mode="right">
    <xsl:with-param name="methodName" select="$name"/>
  </xsl:apply-templates>
</xsl:template>

<xsl:template match="param" mode="left">
  <xsl:param name="methodName" select="''"/> ~<xsl:call-template name="ocamlify-param-name"><xsl:with-param name="name" select="@name"/></xsl:call-template>
</xsl:template>

<xsl:template match="param" mode="right">
 <xsl:param name="methodName" select="''"/>
 <xsl:variable name="name" select="@name"/>
 <xsl:call-template name="pre_method_object_of_object">
  <xsl:with-param name="name" select="@name"/>
  <xsl:with-param name="type" select="@type"/>
  <xsl:with-param name="isNullable" select="document($annotations)/Annotations/Method[@name = $methodName]/Param[@name = $name]/@nullable = 'yes'"/>
 </xsl:call-template>
</xsl:template>

<xsl:template name="pre_method_object_of_object">
 <xsl:param name="name" select="/.."/>
 <xsl:param name="type" select="/.."/>
 <xsl:param name="isNullable" select="/.."/>
 <xsl:text> ~</xsl:text>
 <xsl:variable name="oname">
  <xsl:call-template name="ocamlify-param-name">
   <xsl:with-param name="name" select="$name"/>
  </xsl:call-template>
 </xsl:variable>
 <xsl:value-of select="$oname"/>
 <xsl:variable name="isNotPrimitiveType">
  <xsl:call-template name="isNotPrimitiveType">
   <xsl:with-param name="type" select="$type"/>
  </xsl:call-template>
 </xsl:variable>
 <xsl:if test="string($isNotPrimitiveType) = 'true'">
  <xsl:text>:(</xsl:text>
  <xsl:if test="$isNullable">
   <xsl:text>match </xsl:text>
   <xsl:value-of select="$oname"/>
   <xsl:text> with None -&gt; None | Some </xsl:text>
   <xsl:value-of select="$oname"/>
   <xsl:text> -&gt; Some </xsl:text>
  </xsl:if>
  <xsl:text>(</xsl:text>
  <xsl:value-of select="$oname"/>
  <xsl:text> : </xsl:text>
  <xsl:call-template name="toLowerCase">
   <xsl:with-param name="string" select="$type"/>
  </xsl:call-template>
  <xsl:text>)#as_</xsl:text><xsl:value-of select="$type"/>
  <xsl:text>)</xsl:text>
 </xsl:if>
</xsl:template>

<xsl:template name="ocamlify-param-name">
  <xsl:param name="name" select="''"/>
  <xsl:choose>
    <xsl:when test="$name = 'type'">typ</xsl:when>
    <xsl:otherwise><xsl:value-of select="$name"/></xsl:otherwise>
  </xsl:choose>
</xsl:template>

</xsl:stylesheet>
