/*
 * 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.
 */
package flex.messaging.services.messaging.adapters;

import flex.messaging.MessageException;

import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.ObjectMessage;
import javax.jms.TextMessage;
import javax.jms.Topic;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicPublisher;
import javax.jms.TopicSession;
import javax.naming.NamingException;
import java.io.Serializable;
import java.util.Map;

/**
 * A <code>JMSProducer</code> subclass specifically for JMS Topic publishers.
 *
 *
 */
public class JMSTopicProducer extends JMSProducer
{
    /* JMS related variables */
    private TopicPublisher publisher;

    /**
     * Starts <code>JMSTopicProducer</code>.
     */
    public void start() throws NamingException, JMSException
    {
        super.start();

        // Establish topic
        Topic topic = null;
        try
        {
            topic = (Topic)destination;
        }
        catch (ClassCastException cce)
        {
            // JMS topic proxy for JMS destination ''{0}'' has a destination type of ''{1}'' which is not Topic.
            MessageException me = new MessageException();
            me.setMessage(JMSConfigConstants.NON_TOPIC_DESTINATION, new Object[] {destinationJndiName, destination.getClass().getName()});
            throw me;
        }

        // Create connection
        try
        {
            TopicConnectionFactory topicFactory = (TopicConnectionFactory)connectionFactory;
            if (connectionCredentials != null)
                connection = topicFactory.createTopicConnection(connectionCredentials.getUsername(), connectionCredentials.getPassword());
            else
                connection = topicFactory.createTopicConnection();
        }
        catch (ClassCastException cce)
        {
            // JMS topic proxy for JMS destination ''{0}'' has a connection factory of type ''{1}'' which is not TopicConnectionFactory.
            MessageException me = new MessageException();
            me.setMessage(JMSConfigConstants.NON_TOPIC_FACTORY, new Object[] {destinationJndiName, connectionFactory.getClass().getName()});
            throw me;
        }

        // Create topic session on the connection
        TopicConnection topicConnection = (TopicConnection)connection;
        session = topicConnection.createTopicSession(false /* Always nontransacted */, getAcknowledgeMode());

        // Create publisher on the topic session
        TopicSession topicSession = (TopicSession)session;
        publisher = topicSession.createPublisher(topic);
        producer = publisher;

        // Start the connection
        connection.start();
    }

    void sendObjectMessage(Serializable obj, Map properties) throws JMSException
    {
        if (obj == null)
            return;

        ObjectMessage message = session.createObjectMessage();
        message.setObject(obj);
        copyHeadersToProperties(properties, message);
        publisher.publish(message, getDeliveryMode(), messagePriority, getTimeToLive(properties));
    }

    void sendTextMessage(String text, Map properties) throws JMSException
    {
        if (text == null)
            return;

        TextMessage message = session.createTextMessage();
        message.setText(text);
        copyHeadersToProperties(properties, message);
        publisher.publish(message, getDeliveryMode(), messagePriority, getTimeToLive(properties));
    }

    @Override
    void sendMapMessage(Map<String, ?> map, Map properties) throws JMSException
    {
        if (map == null)
            return;

        MapMessage message = session.createMapMessage();
        for (Map.Entry<String, ?> entry : map.entrySet())
            message.setObject(entry.getKey(), entry.getValue());
        copyHeadersToProperties(properties, message);
        publisher.publish(message, getDeliveryMode(), messagePriority, getTimeToLive(properties));
    }
}
