package eu.osci.messagetypes;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
import java.net.URL;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.namespace.QName;
import javax.xml.transform.TransformerException;

import org.junit.Test;
import org.w3._2005._08.addressing.EndpointReferenceType;

import com.sun.xml.ws.api.SOAPVersion;
import com.sun.xml.ws.api.message.Header;
import com.sun.xml.ws.api.message.HeaderList;
import com.sun.xml.ws.api.message.Headers;

import eu.osci._2008._05.common.urn.messagetypes.letterstyle.LetterStyleMessageType;
import eu.osci.helper.EndpointLocator;
import eu.osci.helper.LetterStyleHelper;
import eu.osci.messageparts.JaxbContextHolder;
import eu.osci.messageparts.OSCIFragmentCreator;


/**
 * Test class for the {@link OSCIMsgBoxFetchRequest}.<br>
 * Tests all the different fetch selectors from the OSCIMsgBoxFetchRequest class and some important header
 * elements. To run this tests an implementation must be installed under the URL declared in the static field
 * MessageParent.URL_MSGBOX_HOST. The installation of the msgBox must provide WSDLs under the URL
 * MessageParent.URL_WSDL_USER, MessageParent.URL_WSDL_Synchron, MessageParent.URL_WSDL_GERNERIC_USER,
 * MessageParent.WSA_REPLY_TO.<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
 */
// TODO > Version 1.0 for the messageId and relatesTo test must be a test implemented with multiple id.
public class TestOSCIMsgBoxFetchRequest extends MessageParent
{

  private static Logger LOG = Logger.getLogger(TestOSCIMsgBoxFetchRequest.class.getName());

  public static final QName QNAME_PORT_USER = new QName("http://messagebox.osci20.bos-bremen.de",
                                                        "LetterStyle");

  public static QName QNAME_LETTER_STYLE_ROOT_ELEM = new QName(
                                                               "http://www.osci.eu/2008/05/common/urn/messageTypes/LetterStyle",
                                                               "LetterStyleMessage");

  /**
   * Fetches all new OSCI messages. At first there will be sent three OSCIRequest messages to prepare the
   * test.<br>
   * To fetch the OSCI messages, there will be used an OSCIMsgBoxFetchRequest and then an
   * OSCIMsgBoxGetNextRequest. Finally an OSCIMsgBoxCloseRequest will be used to finish the transaction.<br>
   * Expected behaviour: Successful sending of the OSCI message without any exceptions. The items pending
   * element will be checked in all steps.
   */
  @Test
  public void testFetchAll()
  {
    LOG.fine("Start testFetchAll");
    try
    {
      MessageParent.sendToMsgBox(true);
      MessageParent.sendToMsgBox(true);
      MessageParent.sendToMsgBox(true);

      OSCIMsgBoxFetchRequest req = new OSCIMsgBoxFetchRequest(new URL(URL_WSDL_USER), SERVICE, FETCH_PORT);
      req.setSelectionAll(true, OSCIFragmentCreator.createEndpointRef(URL_WSDL_USER));
      OSCIMsgBoxFetchResponse rsp = req.sendRequest();
      assertFalse("No message found for selection", rsp.noMessageFoundForSelection());
      assertTrue("Wrong count of pending items found: "
                 + rsp.getMsgBoxResponse().getItemsPending().intValue(), rsp.getMsgBoxResponse()
                                                                            .getItemsPending()
                                                                            .intValue() >= 2);
      assertNotNull("No request iterator.", rsp.getMsgBoxResponse().getMsgBoxRequestID());
      assertTrue("No request iterator.", rsp.getMsgBoxResponse().getMsgBoxRequestID().length() > 0);
      checkBody(rsp);
      // ########## Fetch next message ###########
      OSCIMsgBoxGetNextRequest nextReq = new OSCIMsgBoxGetNextRequest(req);

      rsp = nextReq.sendFetchRequest(new String[]{rsp.getReceiveMessage().getMessageId().getValue()});
      assertFalse("No message found for selection", rsp.noMessageFoundForSelection());
      assertTrue("Wrong count of pending items found: "
                 + rsp.getMsgBoxResponse().getItemsPending().intValue(), rsp.getMsgBoxResponse()
                                                                            .getItemsPending()
                                                                            .intValue() >= 1);
      assertNotNull("No request iterator.", rsp.getMsgBoxResponse().getMsgBoxRequestID());
      assertTrue("No request iterator.", rsp.getMsgBoxResponse().getMsgBoxRequestID().length() > 0);
      checkBody(rsp);
      // ##########now sending the close msg. ################
      OSCIMsgBoxCloseRequest close = new OSCIMsgBoxCloseRequest(nextReq);
      close.sendRequest(new String[]{rsp.getReceiveMessage().getMessageId().getValue()});
    }
    catch (Exception ex)
    {
      LOG.log(Level.SEVERE, "Error: ", ex);
      fail("Sending testFetchAll request failed. Error: " + ex.getMessage());
    }
  }

  @Test
  public void testAdditionalHeaders() throws Exception
  {
    ByteArrayInputStream encData = new ByteArrayInputStream(XML_ENC_DATA.getBytes());
    EndpointLocator endpointLocator = new EndpointLocator(new URL(URL_WSDL_USER));
    endpointLocator.usePort(FIRST_PORT_TO_USE);
    OSCIRequest req = new OSCIRequest(endpointLocator);
    req.setReceptionReceiptDemand(false, false, WSA_REPLY_TO);

    LetterStyleMessageType jaxb = LetterStyleHelper.getLetterStyle("subject", "Here now the content");
    Header header = Headers.create(SOAPVersion.SOAP_12,
                                   JaxbContextHolder.getLetterStyleJaxBContext().createMarshaller(),
                                   LetterStyleHelper.QNAME_LETTER_STYLE,
                                   jaxb);
    HeaderList headerList = new HeaderList();
    headerList.add(header);
    req.setAdditionalHeaderList(headerList);
    req.sendMessage(encData);
    assertEquals("AddionalHeader not 1", 1, req.getAdditionalHeaderList().size());
    // now fetch the message
    OSCIMsgBoxFetchRequest reqFetch = new OSCIMsgBoxFetchRequest(new URL(URL_WSDL_USER), SERVICE, FETCH_PORT);
    reqFetch.setSelectionByMessageId(new String[]{req.getMessageId().getValue()},
                                     OSCIFragmentCreator.createEndpointRef(URL_WSDL_USER));
    OSCIMsgBoxFetchResponse rsp = reqFetch.sendRequest();
    assertFalse("No message found for selection", rsp.noMessageFoundForSelection());
    assertEquals("Wrong status list count: ", BigInteger.valueOf(0), rsp.getMsgBoxResponse()
                                                                        .getItemsPending());
    assertNotNull("No request iterator.", rsp.getMsgBoxResponse().getMsgBoxRequestID());
    assertTrue("No request iterator.", rsp.getMsgBoxResponse().getMsgBoxRequestID().length() > 0);
    assertEquals("AddionalHeader not 1", 1, rsp.getReceiveMessage().getAdditionalHeaderList().size());
    assertEquals("AddionalHeader not 1", "LetterStyleMessage", rsp.getReceiveMessage()
                                                                  .getAdditionalHeaderList()
                                                                  .get(0)
                                                                  .getLocalPart());

    checkBody(rsp);

  }

  /**
   * Fetches OSCI messages by the RelatesTo parameter. First there will be sent two OSCI messages that will be
   * fetched with an OSCIMsgBoxFetchRequest and an OSCIMsgBoxGetNextRequest message. Finally an
   * OSCIMsgBoxCloseRequest will finish the transaction.<br>
   * Expected behaviour: Successful sending of the OSCI message without any exceptions. The items pending
   * element will be checked in all steps.
   */
  @Test
  public void testRelatesTo()
  {
    LOG.fine("Start testRelatesTo");
    try
    {
      String relates1 = OSCIFragmentCreator.createUUID();
      // ########## Sending the messages ###########
      MessageParent.sendToMsgBox(OSCIFragmentCreator.createRelatesTo(relates1), true);
      MessageParent.sendToMsgBox(OSCIFragmentCreator.createRelatesTo(relates1), true);
      EndpointReferenceType fetchRef = OSCIFragmentCreator.createEndpointRef(URL_WSDL_USER);
      OSCIMsgBoxFetchRequest req = new OSCIMsgBoxFetchRequest(new URL(URL_WSDL_USER), SERVICE, FETCH_PORT);
      req.setSelectionByRelatesTo(new String[]{relates1}, fetchRef);
      // ########## Fetch one message ###########
      OSCIMsgBoxFetchResponse rsp = req.sendRequest();
      assertFalse("No message found for selection", rsp.noMessageFoundForSelection());
      assertEquals("Wrong count of pending items.", 1, rsp.getMsgBoxResponse().getItemsPending().intValue());


      assertNotNull("No request iterator.", rsp.getMsgBoxResponse().getMsgBoxRequestID());
      assertTrue("No request iterator.", rsp.getMsgBoxResponse().getMsgBoxRequestID().length() > 0);
      checkBody(rsp);
      // ########## Fetch next message ###########
      OSCIMsgBoxGetNextRequest nextReq = new OSCIMsgBoxGetNextRequest(req);
      rsp = nextReq.sendFetchRequest(new String[]{rsp.getReceiveMessage().getMessageId().getValue()});
      assertFalse("No message found for selection", rsp.noMessageFoundForSelection());
      assertEquals("Wrong count of pending items.", 0, rsp.getMsgBoxResponse().getItemsPending().intValue());
      assertNotNull("No request iterator.", rsp.getMsgBoxResponse().getMsgBoxRequestID());
      assertTrue("No request iterator.", rsp.getMsgBoxResponse().getMsgBoxRequestID().length() > 0);
      checkBody(rsp);
      // ##########now sending the close msg. ################
      OSCIMsgBoxCloseRequest close = new OSCIMsgBoxCloseRequest(nextReq);
      close.sendRequest(new String[]{rsp.getReceiveMessage().getMessageId().getValue()});
    }
    catch (Exception ex)
    {
      LOG.log(Level.SEVERE, "Error: ", ex);
      fail("Sending testFetchAll request failed. Error: " + ex.getMessage());
    }
  }

  /**
   * Fetches OSCI messages by date. First there will be send three OSCI messages with different parameters
   * which will be fetched with an OSCIMsgBoxFetchRequest and an OSCIMsgBoxGetNextRequest message. Finally an
   * OSCIMsgBoxCloseRequest will finish the transaction.<br>
   * Expected behaviour: Successful sending of the OSCI message without any exceptions. The items pending
   * element will be checked in all steps.
   */
  @Test
  public void testByDate()
  {
    LOG.fine("Start testByDate");
    try
    {
      Date startTime = new Date();
      MessageParent.sendToMsgBox(true);
      MessageParent.sendToMsgBox(OSCIFragmentCreator.createRelatesTo(OSCIFragmentCreator.createUUID()), true);
      MessageParent.sendToMsgBox(true, 1);
      OSCIMsgBoxFetchRequest req = new OSCIMsgBoxFetchRequest(new URL(URL_WSDL_USER), SERVICE, FETCH_PORT);
      req.setSelectionByDate(startTime,
                             new Date(),
                             true,
                             OSCIFragmentCreator.createEndpointRef(URL_WSDL_USER));
      OSCIMsgBoxFetchResponse rsp = req.sendRequest();
      assertFalse("No message found for selection", rsp.noMessageFoundForSelection());
      assertEquals("Wrong status list count: ", BigInteger.valueOf(2), rsp.getMsgBoxResponse()
                                                                          .getItemsPending());
      assertNotNull("No request iterator.", rsp.getMsgBoxResponse().getMsgBoxRequestID());
      assertTrue("No request iterator.", rsp.getMsgBoxResponse().getMsgBoxRequestID().length() > 0);
      checkBody(rsp);
      // ########## Fetch next message ###########
      OSCIMsgBoxGetNextRequest nextReq = new OSCIMsgBoxGetNextRequest(req);

      rsp = nextReq.sendFetchRequest(new String[]{rsp.getReceiveMessage().getMessageId().getValue()});
      assertFalse("No message found for selection", rsp.noMessageFoundForSelection());
      assertEquals("Wrong count of pending items.", 1, rsp.getMsgBoxResponse().getItemsPending().intValue());
      assertNotNull("No request iterator.", rsp.getMsgBoxResponse().getMsgBoxRequestID());
      assertTrue("No request iterator.", rsp.getMsgBoxResponse().getMsgBoxRequestID().length() > 0);
      checkBody(rsp);
      // ##########now sending the close msg. ################
      OSCIMsgBoxCloseRequest close = new OSCIMsgBoxCloseRequest(nextReq);
      close.sendRequest(new String[]{rsp.getReceiveMessage().getMessageId().getValue()});
    }
    catch (Exception ex)
    {
      LOG.log(Level.SEVERE, "Error: ", ex);
      fail("Sending testByDate request failed. Error: " + ex.getMessage());
    }
  }

  /**
   * Fetches an OSCI message with the selection for messageID. At first there will be sent an OSCI message
   * that will be fetched in this test.<br>
   * Expected behaviour: Successful sending of the OSCI message without any exceptions.
   */
  @Test
  public void testMessageId()
  {
    LOG.fine("Start testMessageId");
    try
    {
      OSCIMessage req = MessageParent.sendToMsgBox(true);
      OSCIMsgBoxFetchRequest reqFetch = new OSCIMsgBoxFetchRequest(new URL(URL_WSDL_USER), SERVICE,
                                                                   FETCH_PORT);
      reqFetch.setSelectionByMessageId(new String[]{req.getMessageId().getValue()},
                                       OSCIFragmentCreator.createEndpointRef(URL_WSDL_USER));
      OSCIMsgBoxFetchResponse rsp = reqFetch.sendRequest();
      assertFalse("No message found for selection", rsp.noMessageFoundForSelection());
      assertEquals("Wrong status list count: ", BigInteger.valueOf(0), rsp.getMsgBoxResponse()
                                                                          .getItemsPending());
      assertNotNull("No request iterator.", rsp.getMsgBoxResponse().getMsgBoxRequestID());
      assertTrue("No request iterator.", rsp.getMsgBoxResponse().getMsgBoxRequestID().length() > 0);
      checkBody(rsp);
    }
    catch (Exception ex)
    {
      LOG.log(Level.SEVERE, "Error: ", ex);
      // EndpointReferenceType fetchRef = OSCIFragmentCreator.createEndpointRef(URL_WSDL_USER);
      fail("Sending testMessageId request failed. Error: " + ex.getMessage());
    }
  }

  /**
   * Fetches an OSCI message with the selection for messageID. At first there will be sent an OSCI message
   * that will be fetched in this test.<br>
   * Expected behaviour: Successful sending of the OSCI message without any exceptions.
   */
  @Test
  public void testReceptionReceipt()
  {
    LOG.fine("Start testReceptionReceipt");
    try
    {
      // Sending the message
      ByteArrayInputStream encData = new ByteArrayInputStream(XML_ENC_DATA.getBytes());
      EndpointLocator endpointLocator = new EndpointLocator(new URL(URL_WSDL_USER));
      endpointLocator.usePort(FIRST_PORT_TO_USE);
      OSCIRequest req = new OSCIRequest(endpointLocator);
      req.setReceptionReceiptDemand(false, false, WSA_REPLY_TO);
      req.sendMessage(encData);
      String msgId = req.getMessageId().getValue();
      // Check how many messages relates to the previous
      OSCIMsgBoxFetchRequest relatesFetch = new OSCIMsgBoxFetchRequest(new URL(WSA_REPLY_TO), SERVICE,
                                                                       FETCH_PORT);
      EndpointReferenceType fetchRef = OSCIFragmentCreator.createEndpointRef(WSA_REPLY_TO);
      relatesFetch.setSelectionByRelatesTo(new String[]{msgId}, fetchRef);
      OSCIMsgBoxFetchResponse rspRelates = relatesFetch.sendRequest();
      assertTrue("No message found for selection", rspRelates.noMessageFoundForSelection());
      // fetch the message
      OSCIMsgBoxFetchRequest reqFetch = new OSCIMsgBoxFetchRequest(new URL(URL_WSDL_USER), SERVICE,
                                                                   FETCH_PORT);

      reqFetch.setSelectionByMessageId(new String[]{req.getMessageId().getValue()},
                                       OSCIFragmentCreator.createEndpointRef(URL_WSDL_USER));
      OSCIMsgBoxFetchResponse rsp = reqFetch.sendRequest();

      assertFalse("No message found for selection", rsp.noMessageFoundForSelection());
      assertEquals("Wrong status list count: ", BigInteger.valueOf(0), rsp.getMsgBoxResponse()
                                                                          .getItemsPending());
      assertNotNull("No request iterator.", rsp.getMsgBoxResponse().getMsgBoxRequestID());
      assertTrue("No request iterator.", rsp.getMsgBoxResponse().getMsgBoxRequestID().length() > 0);

      checkBody(rsp);
      // TODO was ist hier mit Ende Dialog
      // TODO send the receiptionReceipt

      // now look for the fetch notification message again
      // rspRelates = relatesFetch.sendRequest();
      // assertFalse("No message found for selection", rspRelates.noMessageFoundForSelection());
      // assertEquals("Wrong messageid received.", msgId, rspRelates.getReceiveMessage()
      // .getRelatesTo()
      // .get(0)
      // .getValue());

    }
    catch (Exception ex)
    {
      LOG.log(Level.SEVERE, "Error: ", ex);
      fail("Sending testReceptionReceipt request failed. Error: " + ex.getMessage());
    }
  }

  /**
   * Fetches an OSCI message from a generic endpoint with the selection for messageID. At first there will be
   * sent an OSCI message that will be fetched in this test.<br>
   * Expected behaviour: Successful sending of the OSCI message without any exceptions. Checks some values of
   * the OSCIMsgBoxFetchResponse.
   */
  @Test
  public void testGenericMsgBoxByMessageId()
  {
    LOG.fine("Start testGenericMsgBoxByMessageId");
    try
    {
      ByteArrayInputStream encData = new ByteArrayInputStream(XML_ENC_DATA.getBytes());
      EndpointLocator endpointLocator = new EndpointLocator(new URL(URL_WSDL_GERNERIC_USER));
      LOG.fine("Service: " + endpointLocator.getServiceList().length);
      endpointLocator.usePort("LetterStyle");
      LOG.fine("Port: "
               + endpointLocator.getPortForTypeOfBusinessScenario(endpointLocator.getTypeOfBusinessScenario()));
      OSCIRequest req = new OSCIRequest(endpointLocator);
      req.sendMessage(encData);
      OSCIMsgBoxFetchRequest reqFetch = new OSCIMsgBoxFetchRequest(new URL(URL_WSDL_GERNERIC_USER), SERVICE,
                                                                   FETCH_PORT);
      reqFetch.setSelectionByMessageId(new String[]{req.getMessageId().getValue()},
                                       OSCIFragmentCreator.createEndpointRef(URL_WSDL_GERNERIC_USER));
      OSCIMsgBoxFetchResponse fetchRSP = reqFetch.sendRequest();
      assertFalse("No message found for selection", fetchRSP.noMessageFoundForSelection());
      assertEquals("Wrong status list count: ", BigInteger.valueOf(0), fetchRSP.getMsgBoxResponse()
                                                                               .getItemsPending());
      assertNotNull("No request iterator.", fetchRSP.getMsgBoxResponse().getMsgBoxRequestID());
      assertTrue("No request iterator.", fetchRSP.getMsgBoxResponse().getMsgBoxRequestID().length() > 0);
      checkBody(fetchRSP);
    }
    catch (Exception ex)
    {
      LOG.log(Level.SEVERE, "Error: ", ex);
      fail("Sending testGenericMsgBoxByMessageId request failed. Error: " + ex.getMessage());
    }
  }

  /**
   * Tests the search by date with an endpoint and a typeOfBusinessScenario. First there will be sent three
   * OSCI messages with different typeOfBusinessScenario. At first a configured OSCIMsgBoxFetchRequest with
   * the first typeOfBusinessScenario will be send and the second message with this typeOfBusinessScenario
   * will be fetched with an OSCIMsgBoxGetNextRequest. Finally an OSCIMsgBoxCloseRequest will finish the
   * transaction. After these a new OSCIMsgBoxFetchRequest will be configured with another
   * typeOfBusinessScenario to fetch the last message. <br>
   * Expected behaviour: Successful sending of the OSCI message without any exceptions. The items pending
   * element will be checked in all steps.
   */
  @Test
  public void testTypeOfBusinessScenario()
  {
    LOG.fine("Start testTypeOfBusinessScenario");
    try
    {
      Date startTime = new Date();
      OSCIMessage req = MessageParent.sendToMsgBox(true, 0);
      req = MessageParent.sendToMsgBox(true, 0);
      String type1 = ((OSCIRequest)req).getTypeOfBusinessScenario();
      req = MessageParent.sendToMsgBox(true, 1);
      String type2 = ((OSCIRequest)req).getTypeOfBusinessScenario();
      OSCIMsgBoxFetchRequest reqFetch = new OSCIMsgBoxFetchRequest(new URL(URL_WSDL_USER), SERVICE,
                                                                   FETCH_PORT);
      reqFetch.setSelectionByDate(startTime,
                                  new Date(),
                                  true,
                                  OSCIFragmentCreator.createEndpointReferenceParameter(URL_WSDL_USER, type1));

      OSCIMsgBoxFetchResponse rsp = reqFetch.sendRequest();
      assertFalse("No message found for selection", rsp.noMessageFoundForSelection());
      assertEquals("Wrong status list count: ", BigInteger.valueOf(1), rsp.getMsgBoxResponse()
                                                                          .getItemsPending());
      assertNotNull("No request iterator.", rsp.getMsgBoxResponse().getMsgBoxRequestID());
      assertTrue("No request iterator.", rsp.getMsgBoxResponse().getMsgBoxRequestID().length() > 0);
      checkBody(rsp);

      // ########## Fetch next message ###########
      OSCIMsgBoxGetNextRequest nextReq = new OSCIMsgBoxGetNextRequest(reqFetch);
      rsp = nextReq.sendFetchRequest(new String[]{rsp.getReceiveMessage().getMessageId().getValue()});
      assertFalse("No message found for selection", rsp.noMessageFoundForSelection());
      assertEquals("Wrong count of pending items.", 0, rsp.getMsgBoxResponse().getItemsPending().intValue());
      assertNotNull("No request iterator.", rsp.getMsgBoxResponse().getMsgBoxRequestID());
      assertTrue("No request iterator.", rsp.getMsgBoxResponse().getMsgBoxRequestID().length() > 0);
      checkBody(rsp);
      // ##########now sending the close msg. ################
      OSCIMsgBoxCloseRequest close = new OSCIMsgBoxCloseRequest(nextReq);
      close.sendRequest(new String[]{rsp.getReceiveMessage().getMessageId().getValue()});
      // ################# now fetching the second type ofBusCon ###########
      reqFetch = new OSCIMsgBoxFetchRequest(new URL(URL_WSDL_USER), SERVICE, FETCH_PORT);
      reqFetch.setSelectionByDate(startTime,
                                  new Date(),
                                  true,
                                  OSCIFragmentCreator.createEndpointReferenceParameter(URL_WSDL_USER, type2));
      rsp = reqFetch.sendRequest();
      assertFalse("No message found for selection", rsp.noMessageFoundForSelection());
      assertEquals("Wrong status list count: ", BigInteger.valueOf(0), rsp.getMsgBoxResponse()
                                                                          .getItemsPending());
      assertNotNull("No request iterator.", rsp.getMsgBoxResponse().getMsgBoxRequestID());
      assertTrue("No request iterator.", rsp.getMsgBoxResponse().getMsgBoxRequestID().length() > 0);
      checkBody(rsp);
    }
    catch (Exception ex)
    {
      LOG.log(Level.SEVERE, "Error: ", ex);
      fail("Sending testTypeOfBusinessScenario request failed. Error: " + ex.getMessage());
    }
  }

  /**
   * Tests the case that there are no OSCI messages available for the selection. No OSCI message will send
   * before and the selection will be 'by date'.<br>
   * Expected behaviour: Successful sending of the OSCI message without any exceptions. In the
   * OSCIMsgBoxFetchResponse the NoMessageAvailable element is present.
   */
  @Test
  public void testNoMessageAvailable()
  {
    LOG.fine("Start testNoMessageAvailable");
    try
    {
      OSCIMsgBoxFetchRequest reqFetch = new OSCIMsgBoxFetchRequest(new URL(URL_WSDL_USER), SERVICE,
                                                                   FETCH_PORT);
      reqFetch.setSelectionByDate(new Date(),
                                  new Date(),
                                  true,
                                  OSCIFragmentCreator.createEndpointRef(URL_WSDL_USER));
      OSCIMsgBoxFetchResponse rsp = reqFetch.sendRequest();
      assertTrue("No message found for selection", rsp.noMessageFoundForSelection());
      assertEquals("Unexpected request iterator. Did not found 'NoElementIterator'",
                   "NoElementIterator",
                   rsp.getMsgBoxResponse().getMsgBoxRequestID());
      assertNotNull("MsgBoxResponseType is null", rsp.getMsgBoxResponse());
      assertNotNull("NoMessageAvailable is null", rsp.getMsgBoxResponse().getNoMessageAvailable());
      assertEquals("Wrong reason in NoMessageAvailable. ",
                   "NoSelectionFoundForMessageRequest",
                   rsp.getMsgBoxResponse().getNoMessageAvailable().getReason());
    }
    catch (Exception ex)
    {
      LOG.log(Level.SEVERE, "Error: ", ex);
      fail("Sending testNoMessageAvailable request failed. Error: " + ex.getMessage());
    }
  }

  private void checkBody(OSCIMsgBoxFetchResponse rsp) throws TransformerException
  {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    rsp.getReceiveMessageStream(out);
    assertTrue("Expected body not available.", out.toByteArray().length > 100);
    LOG.fine("The body: " + out);
  }

  /**
   * Sends an OSCIRequest to the msgBox with a fetchNotificationDemand header. In that moment when the OSCI
   * message will be fetched, the message box sends a message to the configured FetchNotificationDemand URL.
   * The test sends a message to the message box, fetches this message and look into the messsgeBox to find
   * the FetchNotification message with a new OSCIMsgBoxFetchRequest. <br>
   * Expected behaviour: Successful sending of the OSCI message without any exceptions.
   */
  @Test
  public void testFetchNotification()
  {
    LOG.fine("Start testFetchNotification");
    try
    {
      ByteArrayInputStream encData = new ByteArrayInputStream(XML_ENC_DATA.getBytes());
      EndpointLocator endpointLocator = new EndpointLocator(new URL(URL_WSDL_USER));
      endpointLocator.usePort(FIRST_PORT_TO_USE);
      OSCIRequest req = new OSCIRequest(endpointLocator);
      req.setFetchedNotificationDemand(WSA_REPLY_TO);
      req.sendMessage(encData);
      String msgId = req.getMessageId().getValue();

      // Check how many messages relates to the previous
      OSCIMsgBoxFetchRequest relatesFetch = new OSCIMsgBoxFetchRequest(new URL(WSA_REPLY_TO), SERVICE,
                                                                       FETCH_PORT);
      EndpointReferenceType fetchRef = OSCIFragmentCreator.createEndpointRef(WSA_REPLY_TO);
      relatesFetch.setSelectionByRelatesTo(new String[]{msgId}, fetchRef);

      OSCIMsgBoxFetchResponse rspRelates = relatesFetch.sendRequest();
      assertTrue("No message found for selection", rspRelates.noMessageFoundForSelection());
      // now fetch the message
      OSCIMsgBoxFetchRequest reqFetch = new OSCIMsgBoxFetchRequest(new URL(URL_WSDL_USER), SERVICE,
                                                                   FETCH_PORT);
      req.getMessageId().getValue();
      reqFetch.setSelectionByMessageId(new String[]{req.getMessageId().getValue()},
                                       OSCIFragmentCreator.createEndpointRef(URL_WSDL_USER));
      OSCIMsgBoxFetchResponse rsp2 = reqFetch.sendRequest();
      assertFalse("No message found for selection", rsp2.noMessageFoundForSelection());
      assertEquals("Wrong status list count: ", BigInteger.valueOf(0), rsp2.getMsgBoxResponse()
                                                                           .getItemsPending());
      assertNotNull("No request iterator.", rsp2.getMsgBoxResponse().getMsgBoxRequestID());
      assertTrue("No request iterator.", rsp2.getMsgBoxResponse().getMsgBoxRequestID().length() > 0);
      checkBody(rsp2);
      // now look for the fetch notification message again
      rspRelates = relatesFetch.sendRequest();
      assertFalse("No message found for selection", rspRelates.noMessageFoundForSelection());
      assertEquals("Wrong messageid received.", msgId, rspRelates.getReceiveMessage()
                                                                 .getRelatesTo()
                                                                 .get(0)
                                                                 .getValue());
      // ##########now sending the close msg. ################
      OSCIMsgBoxCloseRequest close = new OSCIMsgBoxCloseRequest(relatesFetch);
      close.sendRequest(new String[]{rspRelates.getReceiveMessage().getMessageId().getValue()});
    }
    catch (Exception ex)
    {
      LOG.log(Level.SEVERE, "Error: ", ex);
      fail("Sending testFetchNotification request failed. Error: " + ex.getMessage());
    }
  }

  /**
   * Configures the addressing header fields and the OSCI header fields of an OSCI message. <br>
   * Expected behaviour: Successful sending of the OSCI message without any exceptions. The changed addressing
   * header should be the correct values.
   * 
   * @throws Exception Should be thrown in all error cases.
   */
  @Test
  public void testFields() throws Exception
  {
    LOG.fine("Start testAddressingFields");

    OSCIRequest sendReq = (OSCIRequest)sendToMsgBox(true);
    String msgId = sendReq.getMessageId().getValue();
    // String faultTo = "http://myFaultURI.com";
    String from = "http://myFromURI.com";
    String replyURL = "http://replyURL.de";

    OSCIMsgBoxFetchRequest req = new OSCIMsgBoxFetchRequest(new URL(URL_WSDL_USER), SERVICE, FETCH_PORT);
    req.setSelectionByMessageId(new String[]{msgId}, OSCIFragmentCreator.createEndpointRef(URL_WSDL_USER));
    // Test all header elements
    // should better not set
    // req.setAction("")
    req.setFrom(OSCIFragmentCreator.createEndpointRef(from));
    // should better not set
    // req.setMessageId(_messageId);
    // should better not set
    // req.setReplyTo(OSCIFragmentCreator.createEndpointRef(replyURL));

    // should better not set
    // req.setTo(_to);
    // should better not set
    // req.setTypeOfBusinessScenario(null);
    req.sendRequest();
    assertEquals("AddionalHeader not 0", 0, req.getAdditionalHeaderList().size());

    assertNotNull("no from header found.", req.getFrom());
    assertEquals("Wrong url in from header.", from, req.getFrom().getAddress().getValue());
    assertNotNull("no type of bus con.", req.getTypeOfBusinessScenario());
    assertNotNull("Wrong addretype filter textssing entry for 'Action' element.", req.getAction().getValue());
    assertNotNull("Wrong addressing entry for 'MessageID' element.", req.getMessageId().getValue());
    LOG.fine("ReplyTo: " + req.getReplyTo().getAddress().getValue());
    assertNotSame("Wrong addressing entry for 'ReplyTo' element.", replyURL, req.getReplyTo()
                                                                                .getAddress()
                                                                                .getValue());
    assertNotNull("Wrong addressing entry for 'To' element.", req.getTo().getValue());
  }

}
