/** 
 * 
 * Copyright 2004 Protique Ltd
 * 
 * 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 
 * 
 * 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. 
 * 
 **/
package org.activemq.test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

import javax.jms.DeliveryMode;
import javax.jms.JMSException;

import junit.framework.TestCase;

import org.activemq.io.WireFormat;
import org.activemq.message.ActiveMQMapMessage;
import org.activemq.message.ActiveMQMessage;
import org.activemq.message.ActiveMQObjectMessage;
import org.activemq.message.ActiveMQQueue;
import org.activemq.message.ActiveMQTextMessage;
import org.activemq.message.ActiveMQTopic;
import org.activemq.message.Packet;

/**
 * @version $Revision: 1.1.1.1 $
 */
public abstract class WireFormatTestSupport extends TestCase {
    protected WireFormat wireFormat;

    public void testMessage() throws Exception {
        ActiveMQMessage expected = createMessage();
        Packet actual = writeThenReadPacket(expected);
        assertMessage(expected, (ActiveMQMessage) actual);
    }

    public void testTextMessage() throws Exception {
        ActiveMQTextMessage expected = createTextMessage();
        Packet actual = writeThenReadPacket(expected);
        assertTextMessage(expected, (ActiveMQTextMessage) actual);
    }

    public void testObjectMessage() throws Exception {
        ActiveMQObjectMessage expected = createObjectMessage();
        Packet actual = writeThenReadPacket(expected);
        assertObjectMessage(expected, (ActiveMQObjectMessage) actual);
    }

    public void testMapMessage() throws Exception {
        ActiveMQMapMessage expected = createMapMessage();
        Packet actual = writeThenReadPacket(expected);
        assertMapMessage(expected, (ActiveMQMapMessage) actual);
    }

    protected void assertTextMessage(ActiveMQTextMessage expected, ActiveMQTextMessage actual) throws JMSException {
        assertMessage(expected, actual);
        assertEquals("text", expected.getText(), actual.getText());
    }

    protected ActiveMQTextMessage createTextMessage() throws JMSException {
        ActiveMQTextMessage answer = new ActiveMQTextMessage();
        answer.setText("This is some text");
        configureMessage(answer);
        return answer;
    }

    protected void assertObjectMessage(ActiveMQObjectMessage expected, ActiveMQObjectMessage actual) throws JMSException {
        assertMessage(expected, actual);
        assertEquals("object", expected.getObject(), actual.getObject());
    }

    protected ActiveMQObjectMessage createObjectMessage() throws JMSException {
        ActiveMQObjectMessage answer = new ActiveMQObjectMessage();
        answer.setObject("This is some text");
        configureMessage(answer);
        return answer;
    }

    protected void assertMapMessage(ActiveMQMapMessage expected, ActiveMQMapMessage actual) throws JMSException {
        assertMessage(expected, actual);
        assertEquals("propertyBool", expected.getBooleanProperty("propertyBool"), actual.getBooleanProperty("propertyBool"));
        assertEquals("propertyByte", expected.getByteProperty("propertyByte"), actual.getByteProperty("propertyByte"));
        assertEquals("propertyDouble", expected.getDoubleProperty("propertyDouble"), actual.getDoubleProperty("propertyDouble"));
        assertEquals("propertyFloat", expected.getFloatProperty("propertyFloat"), actual.getFloatProperty("propertyFloat"));
        assertEquals("propertyInt", expected.getIntProperty("propertyInt"), actual.getIntProperty("propertyInt"));
        assertEquals("propertyLong", expected.getLongProperty("propertyLong"), actual.getLongProperty("propertyLong"));
        assertEquals("propertyShort", expected.getShortProperty("propertyShort"), actual.getShortProperty("propertyShort"));
        assertEquals("propertyString", expected.getStringProperty("propertyString"), actual.getStringProperty("propertyString"));
    }

    protected ActiveMQMapMessage createMapMessage() throws JMSException {
        ActiveMQMapMessage answer = new ActiveMQMapMessage();
        answer.setBooleanProperty("propertyBool", true);
        answer.setByteProperty("propertyByte", (byte) 44);
        answer.setDoubleProperty("propertyDouble", 123.456);
        answer.setFloatProperty("propertyFloat", (float) 22.223456);
        answer.setIntProperty("propertyInt", 1234567);
        answer.setLongProperty("propertyLong", 1234567890L);
        answer.setShortProperty("propertyShort", (short) 1234);
        answer.setStringProperty("propertyString", "This is some text");
        configureMessage(answer);
        return answer;
    }

    protected void assertMessage(ActiveMQMessage expected, ActiveMQMessage actual) throws JMSException {
        assertEquals("getBooleanProperty", expected.getBooleanProperty("fooBool"), actual.getBooleanProperty("fooBool"));
        assertEquals("getByteProperty", expected.getByteProperty("fooByte"), actual.getByteProperty("fooByte"));
        //assertEquals("consumerID", expected.getConsumerId(), actual.getConsumerId());
        assertEquals("getEntryBrokerName", expected.getEntryBrokerName(), actual.getEntryBrokerName());
        assertEquals("getJMSClientID", expected.getJMSClientID(), actual.getJMSClientID());
        assertEquals("getJMSCorrelationID", expected.getJMSCorrelationID(), actual.getJMSCorrelationID());
        assertEquals("getJMSDeliveryMode", expected.getJMSDeliveryMode(), actual.getJMSDeliveryMode());
        assertEquals("getJMSDestination", expected.getJMSDestination(), actual.getJMSDestination());
        assertEquals("getJMSExpiration", expected.getJMSExpiration(), actual.getJMSExpiration());
        assertEquals("getJMSMessageID", expected.getJMSMessageID(), actual.getJMSMessageID());
        assertEquals("getJMSPriority", expected.getJMSPriority(), actual.getJMSPriority());
        assertEquals("getJMSReplyTo", expected.getJMSReplyTo(), actual.getJMSReplyTo());
        assertEquals("getJMSType", expected.getJMSType(), actual.getJMSType());
        //assertEquals("getProducerID", expected.getProducerID(), actual.getProducerID());
        assertEquals("getStringProperty", expected.getStringProperty("fooString"), actual.getStringProperty("fooString"));
        assertEquals("getTransactionId", expected.getTransactionId(), actual.getTransactionId());
    }

    protected ActiveMQMessage createMessage() throws JMSException {
        ActiveMQMessage answer = new ActiveMQMessage();
        configureMessage(answer);
        return answer;
    }

    protected void configureMessage(ActiveMQMessage answer) throws JMSException {
        answer.setBooleanProperty("fooBool", true);
        answer.setByteProperty("fooByte", (byte) 12);
        answer.setConsumerIdentifer("consumerId");
        answer.setEntryBrokerName("entryBroker");
        answer.setJMSClientID("myClientID");
        answer.setJMSCorrelationID("myCorrelationID");
        answer.setJMSDeliveryMode(DeliveryMode.PERSISTENT);
        answer.setJMSDestination(new ActiveMQTopic("FOO.BAR"));
        answer.setJMSExpiration(1234);
        answer.setJMSMessageID("message:123");
        answer.setJMSPriority(2);
        answer.setJMSReplyTo(new ActiveMQQueue("BAR.REPLY"));
        answer.setJMSType("Cheddar");
        answer.setStringProperty("fooString", "Whatnot");
        answer.setTransactionId("myTxnID");
        answer.setExternalMessageId(true);
    }

    protected void setUp() throws Exception {
        wireFormat = createWireFormat();
    }

    protected abstract WireFormat createWireFormat();


    protected void assertEquals(String message, double expected, double actual) {
        assertEquals(message, new Double(expected), new Double(actual));
    }

    protected Packet writeThenReadPacket(ActiveMQMessage expected) throws IOException, JMSException {
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        wireFormat.writePacket(expected, new DataOutputStream(buffer));
        Packet actual = wireFormat.readPacket(createDataIn(buffer));
        return actual;
    }

    protected DataInputStream createDataIn(ByteArrayOutputStream buffer) {
        return new DataInputStream(new ByteArrayInputStream(buffer.toByteArray()));
    }
}
