<?xml version="1.0" encoding="UTF-8"?>

<!-- Copyright. INRIA : contributor(s) : Priscille Durville                        -->
<!--                                                                               -->
<!--  edelweiss@sophia.inria.fr                                                    -->
<!--                                                                               -->
<!--  This software is a computer program whose purpose is dedicated to ontologies -->
<!--  creation, modification and visualisation.                                    -->
<!--                                                                               -->
<!--  This software is governed by the CeCILL-C license under French law and       -->
<!--  abiding by the rules of distribution of free software.  You can  use,        -->
<!--  modify and/ or redistribute the software under the terms of the CeCILL-C     -->
<!--  license as circulated by CEA, CNRS and INRIA at the following URL            -->
<!--  "http://www.cecill.info".                                                    -->
<!--                                                                               -->
<!--  As a counterpart to the access to the source code and  rights to copy,       -->
<!--  modify and redistribute granted by the license, users are provided only      -->
<!--  with a limited warranty  and the software's author,  the holder of the       -->
<!--  economic rights,  and the successive licensors  have only  limited           -->
<!--  liability.                                                                   -->
<!--                                                                               -->
<!--  In this respect, the user's attention is drawn to the risks associated       -->
<!--  with loading,  using,  modifying and/or developing or reproducing the        -->
<!--  software by the user in light of its specific status of free software,       -->
<!--  that may mean  that it is complicated to manipulate,  and  that  also        -->
<!--  therefore means  that it is reserved for developers  and  experienced        -->
<!--  professionals having in-depth computer knowledge. Users are therefore        -->
<!--  encouraged to load and test the software's suitability as regards their      -->
<!--  requirements in conditions enabling the security of their systems and/or     -->
<!--  data to be ensured and,  more generally, to use and operate it in the        -->
<!--  same conditions as regards security.                                         -->
<!--                                                                               -->
<!-- The fact that you are presently reading this means that you have had          -->
<!--  knowledge of the CeCILL-C license and that you accept its terms.             -->

<!-- Topicmap (XTM syntax) to ECCO ontology (RDFS extended syntax).                -->
<!-- @author Priscille Durville                                                    -->

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
 	xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 	xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
 	xmlns:owl="http://www.w3.org/2002/07/owl#"
 	xmlns:topic="http://www.topicmaps.org/xtm/1.0/" 
 	xmlns:xlink="http://www.w3.org/1999/xlink">

<xsl:output method="xml" indent="yes" omit-xml-declaration="no" encoding="UTF-8" />
	
	<xsl:param name="suffix" select="''" /><!-- optional : suffix use by namespace generation -->
  <xsl:param name="name" select="''" /><!-- optional : ontology's name -->
	<xsl:param name="lang" select="''" /><!-- optional : used for labels language declaration -->
	
	<!-- Ontology namespaces -->
	<xsl:variable name="owl" select="'http://www.w3.org/2002/07/owl#'" />
	<xsl:variable name="rdf" select="'http://www.w3.org/1999/02/22-rdf-syntax-ns#'" />
	
	<!-- Topic map namespaces utilities -->
	<xsl:variable name="langages" select="'http://www.topicmaps.org/xtm/1.0/language.xtm#'" />
	
	<!-- Predefined topics -->
	<xsl:variable name="instanceOfTopic" select="'http://www.topicmaps.org/xtm/1.0/core.xtm#class-instance'" />
	<xsl:variable name="classRole" select="'http://www.topicmaps.org/xtm/1.0/core.xtm#class'" />
	<xsl:variable name="instanceRole" select="'http://www.topicmaps.org/xtm/1.0/core.xtm#instance'" />
	
	<xsl:variable name="isaTopic" select="'http://www.topicmaps.org/xtm/1.0/core.xtm#superclass-subclass'" />
	<xsl:variable name="parentRole" select="'http://www.topicmaps.org/xtm/1.0/core.xtm#superclass'" />
	<xsl:variable name="childRole" select="'http://www.topicmaps.org/xtm/1.0/core.xtm#subclass'" />
	
	<xsl:variable name="topicConcept" select="'http://cmap.coginst.uwf.edu/#concept'" />
	<xsl:variable name="topicProp" select="'http://cmap.coginst.uwf.edu/#linkingPhrase'" />
	<xsl:variable name="incoming" select="'http://cmap.coginst.uwf.edu/#incoming'" />
	<xsl:variable name="outgoing" select="'http://cmap.coginst.uwf.edu/#outgoing'" />
	
	<!-- Subsumption is supposed to be represented by either an instanceOf association or an 'is a' custom link, -->
	<!-- and instanciation by either a superclass-subclass association or an 'instance of' custom link. -->
	<xsl:variable name="isa" select="'is a'" />
	<xsl:variable name="instanceof" select="'instance of'" />
	
	<xsl:variable name="base">http://ns.inria.fr/generated-{$suffix}#</xsl:variable>
	<xsl:template match="topic:topicMap">
        <rdf:RDF xml:base="http://ns.inria.fr/generated-{$suffix}#">

            <owl:Ontology rdf:about="">
                <xsl:if test="not($name = '')"><rdfs:label><xsl:value-of select="$name" /></rdfs:label></xsl:if>
                <owl:versionInfo>1.0</owl:versionInfo>
            </owl:Ontology>

            <xsl:for-each select="topic:topic">
                <xsl:variable name="currenttopic"><xsl:value-of select="@id" /></xsl:variable>
                <xsl:choose>
                    <!-- rdfs:Class and instances -->
                    <xsl:when test="topic:instanceOf/topic:subjectIndicatorRef/@xlink:href=$topicConcept">
                        <!-- test if it is a concept or an instance -->
                        <xsl:variable name="current"><xsl:value-of select="@id" /></xsl:variable>
                        <xsl:variable name="isAnInstance">
                            <xsl:for-each select="../topic:topic[(normalize-space(string(topic:baseName/topic:baseNameString/text())) = $instanceof) and (topic:instanceOf/topic:subjectIndicatorRef/@xlink:href = $topicProp)]">
                                <xsl:variable name="subClassProp">#<xsl:value-of select="@id" /></xsl:variable>
                                <xsl:for-each select="../topic:association[topic:instanceOf/topic:topicRef/@xlink:href = $subClassProp]">
                                    <xsl:if test="topic:member[(topic:topicRef/@xlink:href = concat('#', $current)) and (topic:roleSpec/topic:subjectIndicatorRef/@xlink:href = $incoming)]">1</xsl:if>
                                </xsl:for-each>
                            </xsl:for-each>
                        </xsl:variable>
                        <!-- apply the templates for concepts or instances -->
                        <xsl:choose>
                            <xsl:when test="string-length($isAnInstance) > 0"><xsl:call-template name="Instance" /></xsl:when>
                            <xsl:otherwise><xsl:call-template name="Class" /></xsl:otherwise>
                        </xsl:choose>
                    </xsl:when>
                    
                    <!-- other instances -->
                    <xsl:when test="topic:instanceOf/topic:topicRef">
                        <xsl:call-template name="Instance" />
                    </xsl:when>
                    
                    <!-- rdf:Property -->
                    <xsl:when test="topic:instanceOf/topic:subjectIndicatorRef/@xlink:href=$topicProp">
                        <xsl:call-template name="Prop" />
                    </xsl:when>
                    
                    <!-- other rdf:Property -->
                    <xsl:when test="concat('#', @id) = /topic:topicMap/topic:association/topic:instanceOf/topic:topicRef/@xlink:href">
                        <xsl:call-template name="Prop" />
                    </xsl:when>
                    
                    <xsl:when test="../topic:association[topic:instanceOf/topic:subjectIndicatorRef/@xlink:href = $instanceOfTopic]/topic:member[(topic:roleSpec/topic:subjectIndicatorRef/@xlink:href = $instanceRole) and (topic:topicRef/@xlink:href = concat('#', $currenttopic))]">
                        <xsl:call-template name="Instance" />
                    </xsl:when>
                    
                    <!-- default to class -->
                    <xsl:otherwise>
                        <xsl:call-template name="Class" />
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each>
        </rdf:RDF>
	</xsl:template>
	
	<xsl:template name="Class">
        <xsl:variable name="current"><xsl:value-of select="@id" /></xsl:variable>
        <rdfs:Class rdf:ID="T{$current}"><!-- 'T' to ensure that the ID's first character is a letter. -->
            <!-- label(s) -->
            <xsl:apply-templates select="topic:baseName" />
            
            <!-- subClassOf : detecting case 1 (default 'isa' association) -->
            <xsl:for-each select="../topic:association/topic:member[(topic:roleSpec/topic:subjectIndicatorRef/@xlink:href = $childRole) and (topic:topicRef/@xlink:href = concat('#', $current))]">
                <xsl:if test="../topic:instanceOf/topic:subjectIndicatorRef[@xlink:href = $isaTopic]">
                    <xsl:for-each select="../topic:member[(topic:roleSpec/topic:subjectIndicatorRef/@xlink:href = $parentRole)]">
                        <xsl:variable name="parentClass"><xsl:value-of select="topic:topicRef/@xlink:href" /></xsl:variable>
                        <rdfs:subClassOf rdf:resource="#T{substring-after($parentClass, '#')}" />
                    </xsl:for-each>
                </xsl:if>
            </xsl:for-each>
            
            <!-- subClassOf : detecting case 2 (custom 'isa' association) -->
            <xsl:for-each select="../topic:topic[(normalize-space(string(topic:baseName/topic:baseNameString/text())) = $isa) and (topic:instanceOf/topic:subjectIndicatorRef/@xlink:href = $topicProp)]">
                <xsl:variable name="subClassProp">#<xsl:value-of select="@id" /></xsl:variable>
                <xsl:for-each select="../topic:association[topic:instanceOf/topic:topicRef/@xlink:href = $subClassProp]">
                    <xsl:if test="topic:member[(topic:topicRef/@xlink:href = concat('#', $current)) and (topic:roleSpec/topic:subjectIndicatorRef/@xlink:href = $incoming)]">
                        <xsl:for-each select="topic:member[topic:roleSpec/topic:subjectIndicatorRef/@xlink:href = $outgoing]">
                            <xsl:variable name="parentClass"><xsl:value-of select="topic:topicRef/@xlink:href" /></xsl:variable>
                            <rdfs:subClassOf rdf:resource="#T{substring-after($parentClass, '#')}" />
                        </xsl:for-each>
                    </xsl:if>
                </xsl:for-each>
            </xsl:for-each>
            
            <!-- isDefinedBy -->
            <xsl:apply-templates select="topic:occurence" mode="class" />
     
        </rdfs:Class>
	</xsl:template>
	
	<xsl:template name="Prop">
        <xsl:variable name="currentLabel"><xsl:value-of select="normalize-space(topic:baseName/topic:baseNameString)" /></xsl:variable>
        <xsl:if test="(normalize-space(string($currentLabel)) != $isa) and (normalize-space(string($currentLabel)) != $instanceof)">
            <xsl:variable name="current"><xsl:value-of select="@id" /></xsl:variable>
            <rdf:Property rdf:ID="t{$current}"><!-- 't' to ensure that the ID's first character is a letter. -->
                <!-- label(s) -->
                <xsl:apply-templates select="topic:baseName" />
                
                <!-- rdfs:domain, rdfs:range -->
                <xsl:variable name="refcurrent">#<xsl:value-of select="$current" /></xsl:variable>
                <xsl:for-each select="../topic:association[child::topic:instanceOf/topic:topicRef/@xlink:href = $refcurrent]">
                    <xsl:for-each select="topic:member[topic:roleSpec/topic:subjectIndicatorRef/@xlink:href = $incoming]">
                        <xsl:variable name="domain"><xsl:value-of select="topic:topicRef/@xlink:href" /></xsl:variable>
                        <rdfs:domain rdf:resource="#T{substring-after($domain, '#')}" />
                    </xsl:for-each>
                    <xsl:for-each select="topic:member[topic:roleSpec/topic:subjectIndicatorRef/@xlink:href = $outgoing]">
                        <xsl:variable name="range"><xsl:value-of select="topic:topicRef/@xlink:href" /></xsl:variable>
                        <rdfs:range rdf:resource="#T{substring-after($range, '#')}" />
                    </xsl:for-each>
                </xsl:for-each>
                
                <xsl:if test="not(../topic:association[child::topic:instanceOf/topic:topicRef/@xlink:href = $refcurrent]/topic:member[(topic:roleSpec/topic:subjectIndicatorRef/@xlink:href = $incoming) or (topic:roleSpec/topic:subjectIndicatorRef/@xlink:href = $outgoing)])">
                    <rdf:type rdf:resource="owl:SymmetricProperty" />
                </xsl:if>
                
            </rdf:Property>
        </xsl:if>
	</xsl:template>
	
	<xsl:template name="Instance">
        <xsl:variable name="current"><xsl:value-of select="@id" /></xsl:variable>
      
        <!-- case 1 : default association -->
        <xsl:variable name="type1">
            <xsl:for-each select="../topic:association[topic:instanceOf/topic:subjectIndicatorRef/@xlink:href = $instanceOfTopic]">
                <xsl:if test="topic:member[(topic:roleSpec/topic:subjectIndicatorRef/@xlink:href = $instanceRole) and (topic:topicRef/@xlink:href = concat('#', $current))]">
                    <xsl:value-of select="substring-after(topic:member[topic:roleSpec/topic:subjectIndicatorRef/@xlink:href = $classRole]/topic:topicRef/@xlink:href, '#')" />
                </xsl:if>
            </xsl:for-each>
        </xsl:variable>
            
        <!-- case 2 : shortcut for default association -->
        <xsl:variable name="type2">
            <xsl:if test="topic:instanceOf/topic:topicRef">
                <xsl:value-of select="substring-after(topic:instanceOf/topic:topicRef/@xlink:href, '#')" />
            </xsl:if>
        </xsl:variable>
           
        <!-- case 3 : custom association -->
        <xsl:variable name="type3">
            <xsl:for-each select="../topic:topic[(normalize-space(string(topic:baseName/topic:baseNameString/text())) = $instanceof) and (topic:instanceOf/topic:subjectIndicatorRef/@xlink:href = $topicProp)]">
                <xsl:variable name="instanceOfProp">#<xsl:value-of select="@id" /></xsl:variable>
                <xsl:for-each select="../topic:association[topic:instanceOf/topic:topicRef/@xlink:href = $instanceOfProp]">
                    <xsl:if test="topic:member[(topic:topicRef/@xlink:href = concat('#', $current)) and (topic:roleSpec/topic:subjectIndicatorRef/@xlink:href = $incoming)]">
                    <xsl:value-of select="substring-after(topic:member[topic:roleSpec/topic:subjectIndicatorRef/@xlink:href = $outgoing]/topic:topicRef/@xlink:href, '#')" /></xsl:if>
                </xsl:for-each>
            </xsl:for-each>
        </xsl:variable>
        
        <xsl:variable name="type">
            <xsl:choose>
                <xsl:when test="normalize-space($type1) != ''"><xsl:value-of select="normalize-space($type1)" /></xsl:when>
                <xsl:when test="normalize-space($type2) != ''"><xsl:value-of select="normalize-space($type2)" /></xsl:when>
                <xsl:otherwise><xsl:value-of select="normalize-space($type3)" /></xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        
        <xsl:element name="geni:T{$type}" namespace="http://ns.inria.fr/ecco2/generated-{$suffix}#">
            <xsl:attribute name="rdf:about" namespace="{$rdf}">#T<xsl:value-of select="@id" /></xsl:attribute>
            <xsl:apply-templates select="topic:baseName" />
            <xsl:apply-templates select="topic:occurence" mode="instance" />
            
            <xsl:for-each select="../topic:association[topic:member/topic:topicRef/@xlink:href = concat('#', $current)]">
                <xsl:if test="topic:instanceOf/topic:topicRef"><!-- ensure that it is not a subjectIndicatorRef with a isaTopic or an instanceOfTopic -->
                    <xsl:variable name="prop"><xsl:value-of select="substring-after(topic:instanceOf/topic:topicRef/@xlink:href, '#')" /></xsl:variable>
                    <xsl:if test="(normalize-space(../topic:topic[@id = $prop]/topic:baseName/topic:baseNameString) != $isa) and (normalize-space(../topic:topic[@id = $prop]/topic:baseName/topic:baseNameString) != $instanceof)">
                        <xsl:variable name="newprop">T<xsl:value-of select="$prop" /></xsl:variable>
                        <xsl:for-each select="topic:member[topic:topicRef/@xlink:href != concat('#', $current)]">
                            <xsl:element name="{$newprop}" namespace="{$base}">
                                <xsl:attribute name="rdf:resource" namespace="{$rdf}"><xsl:value-of select="concat('#T', substring-after(topic:topicRef/@xlink:href, '#'))" /></xsl:attribute>
                            </xsl:element>
                        </xsl:for-each>
                    </xsl:if>
                </xsl:if>
            </xsl:for-each>
        </xsl:element>
	</xsl:template>

    
    <xsl:template match="topic:baseName">
        <xsl:choose>
            <xsl:when test="starts-with(topic:scope/topic:subjectIndicatorRef/@xlink:href, $langages)">
                <xsl:variable name="realLang"><xsl:value-of select="substring-after(topic:scope/topic:subjectIndicatorRef/@xlink:href, $langages)" /></xsl:variable>
                <rdfs:label xml:lang="{$realLang}"><xsl:value-of select="normalize-space(topic:baseNameString)" /></rdfs:label>
            </xsl:when>
            <xsl:when test="$lang != ''">
                <rdfs:label xml:lang="{$lang}"><xsl:value-of select="normalize-space(topic:baseNameString)" /></rdfs:label>
            </xsl:when>
            <xsl:otherwise>
                <rdfs:label><xsl:value-of select="normalize-space(topic:baseNameString)" /></rdfs:label>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    
    
    <xsl:template match="topic:occurrence" mode="class">
        <xsl:if test="topic:resourceRef">
            <xsl:variable name="tmp"><xsl:value-of select="concat('#T', substring-after(topic:resourceRef/@xlink:href, '#'))" /></xsl:variable>
            <rdfs:isDefinedBy rdf:resource="{$tmp}" />
        </xsl:if>
    </xsl:template>
    
    <xsl:template match="topic:occurrence" mode="instance">
        <xsl:variable name="prop">t<xsl:value-of select="substring-after(topic:instanceOf/topic:topicRef/@xlink:href, '#')" /></xsl:variable>
        <!-- triplet : current_instance occurence_instanceOf_prop resourceRef_value -->
        <xsl:if test="topic:resourceRef">
            <xsl:element name="{$prop}" namespace="http://ns.inria.fr/ecco2/generated-{$date}#">
                <xsl:attribute name="rdf:resource" namespace="{$rdf}"><xsl:value-of select="concat('#T', substring-after(topic:resourceRef/@xlink:href, '#'))" /></xsl:attribute>
            </xsl:element>
        </xsl:if>
        <!-- triplet : current_instance occurence_instanceOf_prop resourceData_value -->
        <xsl:if test="topic:resourceData and topic:instanceOf/topic:topicRef">
            <xsl:element name="{$prop}" namespace="{$base}"><xsl:value-of select="topic:resourceData" /></xsl:element>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>
