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

<!--
  ~ JBoss, Home of Professional Open Source
  ~ Copyright 2009 Red Hat Inc. and/or its affiliates and other
  ~ contributors as indicated by the @author tags. All rights reserved.
  ~ See the copyright.txt in the distribution for a full listing of
  ~ individual contributors.
  ~
  ~ This 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 software 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 software; if not, write to the Free
  ~ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  ~ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  -->
<xsl:stylesheet xmlns="urn:infinispan:config:5.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
   <xsl:output method="xml" indent="yes" version="1.0" encoding="UTF-8" omit-xml-declaration="no"/>

   <xsl:template match="/cache-config">
      <xsl:comment>
         This XSL stylesheet is generated by an converter from Coherence3.5.x into an Infinispan 5.1.x configuration.
         Eviction policies are translated to LRU, FIFO or NONE.
      </xsl:comment>
      <xsl:element name="infinispan">

         <xsl:element name="global">

            <transport/>

            <asyncListenerExecutor factory="org.infinispan.executors.DefaultExecutorFactory">
               <properties>
                  <property name="threadNamePrefix" value="AsyncTransportThread"/>
               </properties>
            </asyncListenerExecutor>

            <asyncTransportExecutor factory="org.infinispan.executors.DefaultExecutorFactory">
               <properties>
                  <property name="threadNamePrefix" value="AsyncListenerThread"/>
               </properties>
            </asyncTransportExecutor>

            <evictionScheduledExecutor factory="org.infinispan.executors.DefaultScheduledExecutorFactory">
               <properties>
                  <property name="threadNamePrefix" value="EvictionThread"/>
               </properties>
            </evictionScheduledExecutor>

            <replicationQueueScheduledExecutor factory="org.infinispan.executors.DefaultScheduledExecutorFactory">
               <properties>
                  <property name="threadNamePrefix" value="ReplicationQueueThread"/>
               </properties>
            </replicationQueueScheduledExecutor>

            <globalJmxStatistics jmxDomain="infinispan" enabled="true"/>

            <shutdown hookBehavior="DEFAULT"/>
         </xsl:element>

         <xsl:if test="caching-scheme-mapping/cache-mapping/cache-name='*'">
            <xsl:element name="default">
               <xsl:call-template name="generateCache"/>
            </xsl:element>
         </xsl:if>

         <xsl:for-each select="caching-scheme-mapping/cache-mapping">
            <xsl:if test="not(cache-name='*')">
               <xsl:element name="namedCache">
                  <xsl:attribute name="name">
                     <xsl:value-of select="cache-name"/>
                     <xsl:message terminate="no">TODO - please updated following name of the cache to match the one from your code: '<xsl:value-of select="cache-name"/>'
                     </xsl:message>
                  </xsl:attribute>
                  <xsl:call-template name="generateCache"/>
               </xsl:element>
            </xsl:if>
         </xsl:for-each>

      </xsl:element>
   </xsl:template>

   <xsl:template name="generateCache">
      <xsl:variable name="currentScheme" select="./scheme-name"/>
      <xsl:if test="/cache-config/caching-schemes/local-scheme/scheme-name = scheme-name">
         <xsl:for-each select="/cache-config/caching-schemes/local-scheme[scheme-name = $currentScheme]">
            <xsl:call-template name="processLocalScheme"/>
         </xsl:for-each>
      </xsl:if>
      
      <xsl:if test="/cache-config/caching-schemes/distributed-scheme/scheme-name = scheme-name">
         <xsl:element name="clustering">
            <xsl:attribute name="mode">distribution</xsl:attribute>
            <xsl:for-each select="/cache-config/caching-schemes/distributed-scheme[scheme-name = $currentScheme]">
               <xsl:if test="backup-count or key-partitioning">
                  <xsl:element name="hash">
                     <xsl:if test="backup-count">
                        <xsl:attribute name="numOwners"><xsl:value-of select="backup-count"/></xsl:attribute>
                     </xsl:if>
                     <xsl:if test="key-partitioning">
                        <xsl:message terminate="no">TODO - please migrate the custom partitioning algorithm</xsl:message>
                        <xsl:attribute name="class"><xsl:value-of select="key-partitioning"/></xsl:attribute>
                     </xsl:if>
                  </xsl:element>
               </xsl:if>
            
            </xsl:for-each>
            
         </xsl:element>
         <xsl:for-each select="/cache-config/caching-schemes/distributed-scheme[scheme-name = $currentScheme]/backing-map-scheme">
            <xsl:call-template name="processBackingMapScheme"/>
         </xsl:for-each>
      </xsl:if>
      <xsl:if test="/cache-config/caching-schemes/replicated-scheme/scheme-name = scheme-name">
         <xsl:element name="clustering">
         <xsl:attribute name="mode">replicated</xsl:attribute>
         </xsl:element>
         <xsl:for-each select="/cache-config/caching-schemes/replicated-scheme[scheme-name = $currentScheme]/backing-map-scheme">
            <xsl:call-template name="processBackingMapScheme"/>
         </xsl:for-each>
      </xsl:if>
      <xsl:if test="/cache-config/caching-schemes/optimistic-scheme/scheme-name = scheme-name">
         <xsl:message terminate="no">INFO - Optimistic scheme switched to MVCC: http://jbosscache.blogspot.com/2008/07/mvcc-has-landed.html</xsl:message>
         <xsl:element name="clustering">
            <xsl:attribute name="mode">replicated</xsl:attribute>
         </xsl:element>
         <xsl:for-each
               select="/cache-config/caching-schemes/optimistic-scheme[scheme-name = $currentScheme]/backing-map-scheme">
            <xsl:call-template name="processBackingMapScheme"/>
         </xsl:for-each>
      </xsl:if>

      <xsl:if test="/cache-config/caching-schemes/near-scheme/scheme-name = scheme-name">

      </xsl:if>


      <xsl:if test="(/cache-config/caching-schemes/external-scheme/scheme-name = scheme-name)
                 or (/cache-config/caching-schemes/paged-external-scheme/scheme-name = scheme-name)">
         <xsl:message terminate="no">WARN - infinispan only supports on-heap cache storage</xsl:message>
      </xsl:if>
      <xsl:if test="(/cache-config/caching-schemes/remote-cache-scheme/scheme-name = scheme-name)">
         <xsl:message terminate="no">TODO - Use one of the server modules (e.g. infinispan-server-rest) in order to configure Infinispan as a cache server</xsl:message>
      </xsl:if>
   </xsl:template>

    <xsl:template name="processBackingMapScheme">
       <xsl:if test="./local-scheme/scheme-ref">
          <xsl:variable name="schemeRefName" select="./local-scheme/scheme-ref"/>
          <xsl:message terminate="no">I'm entering here! '<xsl:value-of select="$schemeRefName"/>'</xsl:message>
          <xsl:for-each select="//local-scheme[scheme-name=$schemeRefName]">
             <xsl:call-template name="processLocalScheme"/>
          </xsl:for-each>
       </xsl:if>
       <xsl:if test="./external-scheme or ./paged-external-scheme">
          <xsl:message terminate="no">WARN - At the moment Infinispan only supports in memory schemes</xsl:message>
       </xsl:if>
       <xsl:if test="./class-scheme">
          <xsl:message terminate="no">WARN - This is a custom scheme particular to Coherence</xsl:message>
       </xsl:if>
       <xsl:if test="./overflow-scheme">
          <loader class="org.infinispan.loaders.cluster.ClusterCacheLoader" fetchPersistentState="false"
                  ignoreModifications="false" purgeOnStartup="false">
             <properties>
                <property name="remoteCallTimeout" value="10000"/>
             </properties>
          </loader>
       </xsl:if>
    </xsl:template>

   <xsl:template name="processLocalScheme">
      <xsl:if test="./eviction-policy">
         <xsl:if test="./eviction-policy='HYBRID'">
            <xsl:message terminate="no">Infinispan does not currently support HYBRID (adaptive) eviction policies. We are condering adding it in further releases: https://jira.jboss.org/jira/browse/ISPN-204</xsl:message>
            <xsl:element name="eviction">
               <xsl:attribute name="strategy">LRU</xsl:attribute>
               <xsl:call-template name="evictionAttributes"/>
            </xsl:element>
         </xsl:if>
         <xsl:if test="./expiry-delay">
            <xsl:element name="expiration">
               <xsl:attribute name="maxIdle">
                  <xsl:call-template name="extractTime">
                     <xsl:with-param name="baseStr">
                        <xsl:call-template name="extractActualValue">
                           <xsl:with-param name="baseStr">
                              <xsl:value-of select="./expiry-delay"/>
                           </xsl:with-param>
                        </xsl:call-template>
                     </xsl:with-param>
                  </xsl:call-template>
               </xsl:attribute>
            </xsl:element>
         </xsl:if>
         <xsl:if test="cachestore-scheme">
            <xsl:for-each select="cachestore-scheme">
               <xsl:call-template name="processCacheStoreScheme"/>
            </xsl:for-each>
         </xsl:if>
      </xsl:if>

   </xsl:template>

   <xsl:template name="processCacheStoreScheme">
      <xsl:choose>
         <xsl:when test="not(scheme-ref) and not(class-scheme) and not (remote-cache-scheme)">
            <loaders passivation="false" shared="false" preload="false">
               <loader class="org.infinispan.loaders.file.FileCacheStore" fetchPersistentState="false"
                       ignoreModifications="false" purgeOnStartup="false">

                  <!-- See the documentation for more configuration examples and flags. -->
                  <properties>
                     <property name="location" value="/tmp"/>
                  </properties>
               </loader>
            </loaders>
         </xsl:when>
         <xsl:otherwise>
           <xsl:message terminate="no">TODO - please migrate the cache store configuration manually</xsl:message>
         </xsl:otherwise>
      </xsl:choose>
      <xsl:if test="not(scheme-ref) and not(class-scheme) and not (remote-cache-scheme)">

      </xsl:if>
   </xsl:template>

   <xsl:template name="evictionAttributes">
      <xsl:if test="unit-calculator='BINARY'">
         <xsl:message terminate="no">TODO - Infinispan does not currently support computation based on the size of the
            cache, please adjust the eviction/maxEntries attribute to fit your need
         </xsl:message>
      </xsl:if>
      <xsl:if test="high-units">
         <xsl:attribute name="maxEntries">
            <xsl:call-template name="extractActualValue">
               <xsl:with-param name="baseStr" select="high-units"/>
            </xsl:call-template>
         </xsl:attribute>
      </xsl:if>
      <xsl:if test="flush-delay">
         <xsl:attribute name="wakeUpInterval">
            <xsl:call-template name="extractTime">
               <xsl:with-param name="baseStr" select="flush-delay"/>
            </xsl:call-template>
         </xsl:attribute>
      </xsl:if>
   </xsl:template>

   <xsl:template name="extractTime">
      <xsl:param name="baseStr"/>
      <xsl:if test="contains($baseStr,'MS')">
         <xsl:value-of select="substring-before($baseStr,'MS')"/>
      </xsl:if>
      <xsl:if test="contains($baseStr,'ms')">
         <xsl:value-of select="substring-before($baseStr,'MS')"/>
      </xsl:if>
      <xsl:if test="contains($baseStr,'S')">
         <xsl:value-of select="concat(substring-before($baseStr,'S'),'000')"/>
      </xsl:if>
      <xsl:if test="contains($baseStr,'s')">
         <xsl:value-of select="concat(substring-before($baseStr,'s'),'000')"/>
      </xsl:if>
      <xsl:if test="contains($baseStr,'M') and not (contains($baseStr,'MS'))">
         <xsl:value-of select="number(substring-before($baseStr,'M')) * 1000 * 60"/>
      </xsl:if>
      <xsl:if test="contains($baseStr,'m') and not (contains($baseStr,'ms'))">
         <xsl:value-of select="number(substring-before($baseStr,'m')) * 1000 * 60"/>
      </xsl:if>
      <xsl:if test="contains($baseStr,'h')">
         <xsl:value-of select="number(substring-before($baseStr,'h')) * 1000 * 60 * 60"/>
      </xsl:if>
      <xsl:if test="contains($baseStr,'H')">
         <xsl:value-of select="number(substring-before($baseStr,'H')) * 1000 * 60 * 60"/>
      </xsl:if>
      <xsl:if test="contains($baseStr,'D')">
         <xsl:value-of select="number(substring-before($baseStr,'D')) * 1000 * 60 * 60 * 24"/>
      </xsl:if>
      <xsl:if test="contains($baseStr,'d')">
         <xsl:value-of select="number(substring-before($baseStr,'d')) * 1000 * 60 * 60 * 24"/>
      </xsl:if>
   </xsl:template>

   <xsl:template name="extractActualValue">
      <xsl:param name="baseStr"/>
         <xsl:if test="contains($baseStr,'}')">
            <xsl:value-of select="substring-before(substring-after($baseStr,' '),'}')"/>
         </xsl:if>
         <xsl:if test="not(contains($baseStr,'}'))">
            <xsl:value-of select="$baseStr"/>
         </xsl:if>
   </xsl:template>

</xsl:stylesheet>