import static org.junit.Assert.assertTrue;

import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Unmarshaller;

import com.acme.foo.XMLObject1;

import org.junit.Test;


/**
 * Test JAXB Error
 */
public class JAXBTest
{      
    @Test
    public void testLoadValidinvalidJAXB() throws Exception
    {
        
        JAXBContext jc = JAXBContext.newInstance("com.acme.foo");
        Unmarshaller xmlUnmarshaller = jc.createUnmarshaller();
        
        Path nonRootFileWithError = Paths.get("/", "NonRootObjectBadElement.xml");
        Path nonRootFileWithoutError = Paths.get("/", "NonRootObjectGoodElement.xml");
        Path eventDisplay = Paths.get("/", "RootObject.xml");
        
        // When this succeeds, it should return a JAXBElement.
        // This situation will fail due to a bad xml element.
        try (InputStream str = Files.newInputStream(nonRootFileWithError))
        {
            try
            {
                Object obj = xmlUnmarshaller.unmarshal(str);
                System.out.println("alarm " + obj);
                assertTrue(obj instanceof JAXBElement);
            }
            catch (Exception ex)
            {
                ex.printStackTrace();
            }
        }
        
        // When this succeeds, it should return a JAXBElement.
        // This situation will fail due to a bad xml element. (This is the same call as above)
        try (InputStream str = Files.newInputStream(nonRootFileWithError))
        {
            try
            {
                Object obj = xmlUnmarshaller.unmarshal(str);
                System.out.println("alarm " + obj);
                assertTrue(obj instanceof JAXBElement);
            }
            catch (Exception ex)
            {
                ex.printStackTrace();
            }
        }
        
        // When this succeeds, it should return a JAXBElement.
        // When this is commented out: the call below to unmarshal() will return
        // a JAXBElement with the XMLObject1 object in the value field. 
        // This should not happen.
        //
        // When this is not commented out: the call below to unmarshall() will
        // correctly return an XMLObject1
        try (InputStream str = Files.newInputStream(nonRootFileWithoutError))
        {
            try
            {
                Object obj = xmlUnmarshaller.unmarshal(str);
                System.out.println("sec " + obj);
                assertTrue(obj instanceof JAXBElement);
            }
            catch (Exception ex)
            {
                assertTrue(false);
                ex.printStackTrace();
            }
        }
        
        // When this succeeds, it should return a XMLObject1 object. 
        // It should NOT return a JAXBElement.
        // This will fail unless the block of code above is not commented out.
        try (InputStream str = Files.newInputStream(eventDisplay))
        {
            try
            {
                Object obj = xmlUnmarshaller.unmarshal(str);
                System.out.println("event " + obj);
                assertTrue(obj instanceof XMLObject1);
            }
            catch (Exception ex)
            {
                ex.printStackTrace();
            }
        }
    }

}