/*
 * #%L
 * Bitrepository Protocol
 * 
 * $Id$
 * $HeadURL$
 * %%
 * Copyright (C) 2010 - 2011 The State and University Library, The Royal Library and The State Archives, Denmark
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as 
 * published by the Free Software Foundation, either version 2.1 of the 
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public 
 * License along with this program.  If not, see
 * <http://www.gnu.org/licenses/lgpl-2.1.html>.
 * #L%
 */
package org.bitrepository.protocol;

import java.io.InputStream;
import java.util.Iterator;

import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;

import org.bitrepository.bitrepositorymessages.GetChecksumsFinalResponse;
import org.bitrepository.protocol.message.ExampleMessageFactory;
import org.jaccept.structure.ExtendedTestCase;
import org.testng.annotations.Test;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

/**
 * Test whether we are able to create message objects from xml. The input XML is the example code defined in the
 * message-xml, thereby also testing whether this is valid. *
 */
public class MessageCreationTest extends ExtendedTestCase {

    @Test(groups = {"regressiontest"})
    public void messageCreationTest() throws Exception {
        addDescription("Tests if we are able to create message objects from xml. The input XML is the example code " +
        "defined in the message-xml, thereby also testing whether this is valid.");
        String[] messageNames = getMessageNames();
        for (String messageName : messageNames) {
            addStep("Creating " + messageName + " message" , 
            "The test is able to instantiate message based on the example in the message-xml modules");
            ExampleMessageFactory.createMessage(
                    Class.forName(GetChecksumsFinalResponse.class.getPackage().getName() + "." + messageName));
        }
    }

    /**
     * Generates the list of messages to test by parsing the message xsd file.
     *
     * @return List of messages to test
     */
    private String[] getMessageNames() throws Exception {
        InputStream f = Thread.currentThread().getContextClassLoader().getResourceAsStream("xsd/BitRepositoryMessages.xsd");
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true);
        Document doc = factory.newDocumentBuilder().parse(f);

        XPathFactory xPathFactory = XPathFactory.newInstance();
        XPath xpath = xPathFactory.newXPath();
        xpath.setNamespaceContext(getNamespaceContext());
        XPathExpression expr = xpath.compile("/xs:schema/xs:element");
        Object result = expr.evaluate(doc, XPathConstants.NODESET);
        NodeList nodes = (NodeList) result;

        String[] messageNames = new String[nodes.getLength()];
        for (int i = 0; i < nodes.getLength(); i++) {
            messageNames[i] = nodes.item(i).getAttributes().getNamedItem("name")
            .getNodeValue();
        }
        return messageNames;
    }

    /** Needed by XPath to handle the namespaces. */
    private NamespaceContext getNamespaceContext() {
        NamespaceContext ctx = new NamespaceContext() {
            public String getNamespaceURI(String prefix) {
                String uri;
                if (prefix.equals("xs")) {
                    uri = "http://www.w3.org/2001/XMLSchema";
                } else if (prefix.equals("xsi")) {
                    uri = "http://www.w3.org/2001/XMLSchema-instance";
                } else if (prefix.equals("bre")) {
                    uri = "http://bitrepository.org/BitRepositoryElements.xsd";
                } else {
                    uri = null;
                }
                return uri;
            }

            // Dummy implementation - not used!
            @SuppressWarnings("rawtypes")
            public Iterator getPrefixes(String val) {
                return null;
            }

            // Dummy implemenation - not used!
            public String getPrefix(String uri) {
                return null;
            }
        };
        return ctx;
    }
}

@@ -917,16 +917,44 @@
 tocol;%0A%0A
+import java.io.IOException;%0A
 import j
@@ -1001,16 +1001,53 @@
 rator;%0A%0A
+import javax.xml.bind.JAXBException;%0A
 import j
@@ -1294,69 +1294,266 @@
 org.
-bitrepository.bitrepositorymessages.GetChecksumsFinalResponse
+apache.activemq.util.ByteArrayInputStream;%0Aimport org.apache.commons.io.IOUtils;%0Aimport org.bitrepository.bitrepositorymessages.GetChecksumsFinalResponse;%0Aimport org.bitrepository.bitrepositorymessages.AlarmMessage;%0Aimport org.bitrepository.common.JaxbHelper
 ;%0Aim
@@ -1755,16 +1755,49 @@
 odeList;
+%0Aimport org.xml.sax.SAXException;
 %0A%0A/**%0A *
@@ -2772,24 +2772,898 @@
      %7D%0A    %7D
+%0A    %0A    @Test(groups = %7B%22regressiontest%22%7D, expectedExceptions = SAXException.class)%0A    public void badDateMessageTest() throws IOException, SAXException, JAXBException %7B%0A        addDescription(%22Test to ensure that messages carrying dates will provide offset.%22);%0A        String messagePath = ExampleMessageFactory.PATH_TO_EXAMPLES + %22BadMessages/%22 + %0A                %22BadDateAlarmMessage%22 + ExampleMessageFactory.EXAMPLE_FILE_POSTFIX;%0A        String message = IOUtils.toString(Thread.currentThread().getContextClassLoader().getResourceAsStream(messagePath));%0A        JaxbHelper jaxbHelper = new JaxbHelper(ExampleMessageFactory.PATH_TO_SCHEMA, ExampleMessageFactory.SCHEMA_NAME);%0A        jaxbHelper.validate(new ByteArrayInputStream(message.getBytes()));%0A        AlarmMessage am = jaxbHelper.loadXml(AlarmMessage.class, new ByteArrayInputStream(message.getBytes()));%0A    %7D
 %0A%0A    /**%0A  

add a test to ensure that messages won't be accepted when missing utc offset