package eu.osci.messagetypes;

import java.util.ArrayList;
import java.util.ResourceBundle;
import java.util.logging.Logger;

import javax.xml.bind.JAXBException;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service;

import org.w3._2005._08.addressing.AttributedURIType;

import com.sun.xml.ws.api.message.Header;
import com.sun.xml.ws.api.message.HeaderList;
import com.sun.xml.ws.api.message.Message;
import com.sun.xml.ws.developer.WSBindingProvider;

import eu.osci.AddressingHeaderTag;
import eu.osci.messageparts.OSCIFragmentCreator;
import eu.osci.messageparts.OSCIFragmentParser;


/**
 * This is the abstract parent class for all OSCI message types. It offers the general field and common
 * processing for all messages.<br>
 * Copyright © 2010 Freie Hansestadt Bremen. <br>
 * Created by bremen online services Entwicklungs- und Betriebsgesellschaft mbH & Co. KG. <br>
 * This library (Starter Kit) can be used by anybody according to the Bremer Lizenz für freie
 * Softwarebibliotheken. The license terms can be viewed at www.osci.de or can be ordered at the
 * OSCI-Leitstelle (Die Senatorin für Finanzen, Freie Hansestadt Bremen, Postfach 10 15 40, 28015 Bremen).
 * 
 * @author R. Lindemann
 */

public abstract class OSCIMessage
{

  /** Logger to log the messages. */
  private static Logger LOG = Logger.getLogger(OSCIMessage.class.getName());

  /** ResourceBundle object, for translation into the local language. */
  public static final ResourceBundle text = ResourceBundle.getBundle("eu.osci.Text",
                                                                     java.util.Locale.getDefault());

  /** The BindingProvider to add header elements. */
  protected WSBindingProvider bindingProvider = null;

  /** The port to send the message to the service. */
  protected Dispatch<Message> jaxbDispatch = null;

  /** The service that will be addressed. */
  protected Service wsService = null;

  /** Addressing 'To' attribute. */
  AttributedURIType to = null;

  boolean enableSetWSATo = false;

  /** Addressing 'MessageID' attribute. */
  AttributedURIType messageId = null;

  boolean enableSetWSAMessageId = false;

  /** Addressing 'Action' attribute. */
  AttributedURIType action = null;

  boolean enableSetWSAAction = false;

  ArrayList<Header> additionalHeaderList;

  /**
   * Returns the addressing action of the OSCI message. In most cases the action will be get out of the WSDL
   * file.
   */
  public AttributedURIType getAction()
  {
    return action;
  }

  /**
   * Sets the addressing 'Action' attribute. This setter has no sense in most cases because the 'Action'
   * attribute will be get out of the WSDL file. Be careful with this setter because if the framework will put
   * an 'Action' header into the SOAP message there will be two headers available.
   * 
   * @param _action The action element that will be used.
   */
  public void setAction(AttributedURIType _action)
  {
    enableSetWSAAction = true;
    this.action = _action;
  }

  /**
   * Returns the addressing 'To' attribute of the OSCI message. In the most cases the action will be get out
   * of the WSDL file.
   */
  public AttributedURIType getTo()
  {
    return to;
  }

  /**
   * Sets the addressing 'To' attribute. This setter has no sense in most cases because the 'To' attribute out
   * of the WSDL will be used. Be careful with this setter because if the framework will put a 'To' header
   * into the SOAP message there will be two headers available.
   * 
   * @param _to The 'To' element that will be used.
   */
  public void setTo(AttributedURIType _to)
  {
    enableSetWSATo = true;
    this.to = _to;
  }

  /**
   * Returns the addressing 'MessageID' attribute of the OSCI message.
   */
  public AttributedURIType getMessageId()
  {
    return messageId;
  }

  /**
   * Parses the addressing header from the incoming/sent OSCI message.
   * 
   * @param headerList Header list of the incoming/sent OSCI message.
   * @throws JAXBException In the cases of parsing errors.
   */
  protected void interpretWSAHeaders(HeaderList headerList) throws JAXBException
  {
    // ### Addressing Header ############
    messageId = (AttributedURIType)OSCIFragmentParser.createAddressingHeader(headerList,
                                                                             AddressingHeaderTag.MESSAGEID);
    to = (AttributedURIType)OSCIFragmentParser.createAddressingHeader(headerList, AddressingHeaderTag.TO);
    action = (AttributedURIType)OSCIFragmentParser.createAddressingHeader(headerList,
                                                                          AddressingHeaderTag.ACTION);
  }

  /**
   * Sets the addressing 'MessageID' attribute. This setter has no sense in most cases because the 'MessageID'
   * attribute will be created by the framework and overwriting is not allowed. Be careful with this setter,
   * because if the framework will put a 'MessageID' header into the SOAP message there will be two headers
   * available.
   * 
   * @param _messageId That will by used for the message to send.
   */
  public void setMessageId(AttributedURIType _messageId)
  {
    enableSetWSAMessageId = true;
    this.messageId = _messageId;
  }

  /**
   * Prepares the send message. The additional OSCI header, the optional WS-Trust header and some optional
   * addressing header will be added to the SOAP message.
   * 
   * @param headerList A list of the header that will be added to the SOAP message.
   * @throws JAXBException In cases of serialisation errors.
   */
  protected void prepareSendMessage(ArrayList<Header> headerList) throws JAXBException
  {
    // ################### wsa:To #################
    // Will be taken out of the WSDL in most cases.
    if (to != null && enableSetWSATo)
    {
      LOG.fine("Special addressing header 'To' added");
      bindingProvider.setAddress(to.getValue());
      headerList.add(OSCIFragmentCreator.createAddressingHeader(AddressingHeaderTag.TO, to));
    }
    // ################### wsa:Action #################
    // Will be taken out of the WSDL in most cases.
    if (action != null && enableSetWSAAction)
    {
      LOG.fine("Special ddressing header 'Action' added");
      headerList.add(OSCIFragmentCreator.createAddressingHeader(AddressingHeaderTag.ACTION, action));
    }
    // Will be created by the framework in most cases.
    if (messageId != null && enableSetWSAMessageId)
    {
      LOG.fine("Special addressing header 'MessageID' added");
      headerList.add(OSCIFragmentCreator.createAddressingHeader(AddressingHeaderTag.MESSAGEID, messageId));
    }
    // Will set additional headers.
    if (additionalHeaderList != null && additionalHeaderList.size() > 0)
    {
      LOG.fine("Special addressing header 'MessageID' added");
      headerList.addAll(additionalHeaderList);
    }
  }

  /**
   * Returns the additional headers.
   */
  public ArrayList<Header> getAdditionalHeaderList()
  {
    return additionalHeaderList;
  }

  /**
   * Adds a list of additional not specified headers.
   * 
   * @param _additionalHeaderList List of soap headers.
   */
  public void setAdditionalHeaderList(ArrayList<Header> _additionalHeaderList)
  {
    this.additionalHeaderList = _additionalHeaderList;
  }

}
