<?xml version='1.0'?> 
<!--
 
 Licensed to the Apache Software Foundation (ASF) under one
 or more contributor license agreements.  See the NOTICE file
 distributed with this work for additional information
 regarding copyright ownership.  The ASF licenses this file
 to you 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
 
   http://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="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:amq="http://amq.org"> 

<!-- this class contains the templates for generating java source code for a given framing model -->
<xsl:import href="utils.xsl"/>
<xsl:output method="text" indent="yes" name="textFormat"/> 

<xsl:param name="registry_name"/>

<xsl:template match="/"> 
    <xsl:apply-templates mode="generate-multi" select="frames"/>
    <xsl:apply-templates mode="generate-registry" select="frames"/>
</xsl:template>

<!-- processes all frames outputting the classes in a single stream -->
<!-- (useful for debugging etc) -->
<xsl:template match="frame" mode="generate-single"> 
    <xsl:call-template name="generate-class">
        <xsl:with-param name="f" select="."/>
    </xsl:call-template>
</xsl:template>

<!-- generates seperate file for each class/frame -->
<xsl:template match="frame" mode="generate-multi"> 
    <xsl:variable name="uri" select="concat(@name, '.java')"/> 
    wrote <xsl:value-of select="$uri"/> 
    <xsl:result-document href="{$uri}" format="textFormat"> 
    <xsl:call-template name="generate-class">
        <xsl:with-param name="f" select="."/>
    </xsl:call-template>
    </xsl:result-document> 
</xsl:template> 

<!-- main class generation template -->
<xsl:template name="generate-class"> 
    <xsl:param name="f"/>
package org.openamq.framing;

import org.apache.mina.common.ByteBuffer;

/**
 * This class is autogenerated, do not modify. [From <xsl:value-of select="$f/parent::frames/@protocol"/>]
 */
public class <xsl:value-of select="$f/@name"/> extends AMQMethodBody implements EncodableAMQDataBlock
{ 
    public static final int CLASS_ID = <xsl:value-of select="$f/@class-id"/>; 	
    public static final int METHOD_ID = <xsl:value-of select="$f/@method-id"/>; 	

    <xsl:for-each select="$f/field"> 
        <xsl:text>public </xsl:text><xsl:value-of select="@java-type"/>
        <xsl:text> </xsl:text>
        <xsl:value-of select="@name"/>;    
    </xsl:for-each> 

    protected int getClazz()
    {
        return <xsl:value-of select="$f/@class-id"/>;
    }
   
    protected int getMethod()
    {
        return <xsl:value-of select="$f/@method-id"/>;
    }

    protected int getBodySize()
    {
        <xsl:choose> 
        <xsl:when test="$f/field">
        return
        <xsl:for-each select="$f/field">
            <xsl:if test="position() != 1">+
            </xsl:if>
            <xsl:value-of select="amq:field-length(.)"/>
        </xsl:for-each>		 
        ;
        </xsl:when>
        <xsl:otherwise>return 0;</xsl:otherwise>
        </xsl:choose> 
    }

    protected void writeMethodPayload(ByteBuffer buffer)
    {
        <xsl:for-each select="$f/field">
            <xsl:if test="@type != 'bit'">
                <xsl:value-of select="amq:encoder(.)"/>;
            </xsl:if>
            <xsl:if test="@type = 'bit' and @boolean-index = 1">
                <xsl:text>EncodingUtils.writeBooleans(buffer, new boolean[]{</xsl:text>
                <xsl:value-of select="$f/field[@type='bit']/@name" separator=", "/>});
            </xsl:if>
        </xsl:for-each>		 
    }

    public void populateMethodBodyFromBuffer(ByteBuffer buffer) throws AMQFrameDecodingException
    {
        <xsl:for-each select="$f/field">
            <xsl:value-of select="amq:decoder(.)"/>;
        </xsl:for-each>		 
    }

    public String toString()
    {
        StringBuffer buf = new StringBuffer(super.toString());
        <xsl:for-each select="$f/field">
            <xsl:text>buf.append(" </xsl:text><xsl:value-of select="@name"/>: ").append(<xsl:value-of select="@name"/>);
        </xsl:for-each> 
        return buf.toString();
    }

    public static AMQFrame createAMQFrame(int channelId<xsl:if test="$f/field">, </xsl:if><xsl:value-of select="$f/field/concat(@java-type, ' ', @name)" separator=", "/>)
    {
        <xsl:value-of select="@name"/> body = new <xsl:value-of select="@name"/>();
        <xsl:for-each select="$f/field">
            <xsl:value-of select="concat('body.', @name, ' = ', @name)"/>;
        </xsl:for-each>		 
        AMQFrame frame = new AMQFrame();
        frame.channel = channelId;
        frame.bodyFrame = body;
        return frame;
    }
} 
</xsl:template> 

<xsl:template match="/" mode="generate-registry">
     <xsl:text>Matching root for registry mode!</xsl:text>
     <xsl:value-of select="."/> 
     <xsl:apply-templates select="frames" mode="generate-registry"/>
</xsl:template>

<xsl:template match="registries" mode="generate-registry">
Wrote MethodBodyDecoderRegistry.java
    <xsl:result-document href="MethodBodyDecoderRegistry.java" format="textFormat">package org.openamq.framing;

import java.util.Map;
import java.util.HashMap;
import org.apache.log4j.Logger;
import org.openamq.AMQException;

/**
 * This class is autogenerated, do not modify.
 */
public final class MethodBodyDecoderRegistry
{
    private static final Logger _log = Logger.getLogger(MethodBodyDecoderRegistry.class);

    private static final Map _classMethodProductToMethodBodyMap = new HashMap();

    static
    {
        <xsl:for-each select="registry">
            <xsl:value-of select="concat(@name, '.register(_classMethodProductToMethodBodyMap)')"/>;         
        </xsl:for-each>
    }

    public static AMQMethodBody get(int clazz, int method) throws AMQFrameDecodingException
    {
	Class bodyClass = (Class) _classMethodProductToMethodBodyMap.get(new Integer(clazz * 1000 + method));
	if (bodyClass != null)
	{
	    try
	    {
	        return (AMQMethodBody) bodyClass.newInstance();
	    }
	    catch (Exception e)
	    {
	    	throw new AMQFrameDecodingException(_log, "Unable to instantiate body class for class " + clazz + " and method " + method + ": " + e, e);
	    }
	}
	else
	{
	    throw new AMQFrameDecodingException(_log, "Unable to find a suitable decoder for class " + clazz + " and method " + method);
	}    
    }
}
</xsl:result-document>
</xsl:template>

<xsl:template match="frames" mode="list-registry">	
    <xsl:if test="$registry_name">

    <xsl:variable name="file" select="concat($registry_name, '.java')"/> 
    wrote <xsl:value-of select="$file"/> 
    <xsl:result-document href="{$file}" format="textFormat">package org.openamq.framing;

import java.util.Map;

/**
 * This class is autogenerated, do not modify. [From <xsl:value-of select="@protocol"/>]
 */
class <xsl:value-of select="$registry_name"/>
{
    static void register(Map map)
    {
        <xsl:for-each select="frame">
            <xsl:text>map.put(new Integer(</xsl:text>
            <xsl:value-of select="@class-id"/>         
	    <xsl:text> * 1000 + </xsl:text> 
            <xsl:value-of select="@method-id"/>         
	    <xsl:text>), </xsl:text> 
            <xsl:value-of select="concat(@name, '.class')"/>);         
        </xsl:for-each>
    }
}
    </xsl:result-document>

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

</xsl:stylesheet>
