/*
 * Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved.
 */

package javasoft.sqe.tests.bind.marshaller;

import jakarta.xml.bind.Marshaller;
import javax.xml.transform.Result;
import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.Marshaller;
import jakarta.xml.bind.helpers.DefaultValidationEventHandler;
import jakarta.xml.bind.ValidationEventHandler;
import java.io.UnsupportedEncodingException;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import jakarta.xml.bind.PropertyException;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Node;
import java.io.OutputStream;
import java.io.IOException;
import java.io.StringWriter;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamResult;
import javasoft.sqe.tests.api.jakarta.xml.bind.ErrorCollector;
import javasoft.sqe.javatest.Status;
import java.io.PrintWriter;
import javasoft.sqe.tests.api.jakarta.xml.bind.CTTest;

public class Marshaller_CTTests extends CTTest {

    /**
     * Command line starter.
     */
    public static void main(String[] args) {
        Marshaller_CTTests test = new Marshaller_CTTests();
        PrintWriter err = new PrintWriter(System.err, true);
        PrintWriter out = new PrintWriter(System.out, true);
        Status status = test.run(args, err, out);
        err.flush();
        out.flush();
        status.exit();
    }

    Marshaller getMarshaller() throws JAXBException {
        JAXBContext jc = getJAXBContext();
        return jc.createMarshaller();
    }
    
    static class CustomHandler extends DefaultHandler {
        public StringBuffer log = new StringBuffer();
        public void startDocument() throws SAXException {
            log.append("startDocument();\n");
            super.startDocument();
        }
        public void endDocument() throws SAXException {
            log.append("endDocument();\n");
            super.endDocument();
        }
    }

    static class StringBufferOutputStream extends OutputStream {
        public StringBuffer buffer = new StringBuffer();
        public void write(int b) throws IOException {
            buffer.append((char)b);
        }
    }

    public Status Get001( ) {
        try {
            Marshaller pm = getMarshaller();

            ValidationEventHandler veh = pm.getEventHandler();
    
            if (veh == null) {
                return Status.failed("getEventHandler() returns null");
            }

            return Status.passed("OKAY");

        } catch (JAXBException jaxbe) {
            jaxbe.printStackTrace(ref);
            return Status.failed(jaxbe.toString());
        }
    }

    public Status Get003( ) {
        try {
            Marshaller pm = getMarshaller();

            Object prop = pm.getProperty("unexistentProperty");
    
            return Status.failed("getProperty(\"unexistentProperty\") returns " + prop
                               + ", but should throw PropertyException");

        } catch (PropertyException pe) {
            return Status.passed("OKAY");
        } catch (JAXBException jaxbe) {
            jaxbe.printStackTrace(ref);
            return Status.failed(jaxbe.toString());
        }
    }

    public Status Get004( ) {
        try {
            Marshaller pm = getMarshaller();

            pm.setProperty("jaxb.encoding", "UTF-8");
            Object prop = pm.getProperty("jaxb.encoding");

            if (prop == null || ! (prop.equals("UTF-8"))) {
                return Status.failed("what getProperty(\"jaxb.encoding\") returns " + prop
                                   + " instead of \"UTF-8\"");
            }

            return Status.passed("OKAY");
        } catch (PropertyException pe) {
            pe.printStackTrace(ref);
            return Status.failed(pe.toString());
        } catch (JAXBException jaxbe) {
            jaxbe.printStackTrace(ref);
            return Status.failed(jaxbe.toString());
        }
    }

    public Status Marshal001( ) {
        try {
            Marshaller pm = getMarshaller();

            CustomHandler ch = new CustomHandler();

            pm.marshal((new ObjectFactory()).createRoot("test"), ch);

            if (ch.log.toString().indexOf("startDocument();") == -1) {
                ref.println("Marshal001: " + ch.log);
                return Status.failed("no startDocument() event is logged.");
            }

            if (ch.log.toString().indexOf("endDocument();") == -1) {
                ref.println("Marshal001: " + ch.log);
                return Status.failed("no endDocument() event is logged.");
            }

            return Status.passed("OKAY");
        } catch (JAXBException jaxbe) {
            jaxbe.printStackTrace(ref);
            return Status.failed(jaxbe.toString());
        }
    }

    public Status Marshal002( ) {
        try {
            Marshaller pm = getMarshaller();

            Node node = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();

            pm.marshal((new ObjectFactory()).createRoot("test"), node);

            if (! (node.hasChildNodes())) {
                return Status.failed("the node gets no child nodes.");
            }

            return Status.passed("OKAY");
        } catch (FactoryConfigurationError fce) {
            return Status.failed(fce.toString());
        } catch (ParserConfigurationException pce) {
            return Status.failed(pce.toString());
        } catch (JAXBException jaxbe) {
            jaxbe.printStackTrace(ref);
            return Status.failed(jaxbe.toString());
        }
    }

    public Status Marshal003( ) {
        try {
            Marshaller pm = getMarshaller();

            StringBufferOutputStream sbos = new StringBufferOutputStream();

            pm.marshal((new ObjectFactory()).createRoot("test.Marshal003"), sbos);

            if (sbos.buffer.toString().indexOf("test.Marshal003") == -1) {
                return Status.failed("cannot find string \"test.Marshal003\" in " 
                               + "the marshalled document: " + sbos.buffer);
            }

            return Status.passed("OKAY");
        } catch (JAXBException jaxbe) {
            jaxbe.printStackTrace(ref);
            return Status.failed(jaxbe.toString());
        }
    }

    public Status Marshal004( ) {
        try {
            Marshaller pm = getMarshaller();

            StringWriter sw = new StringWriter();

            pm.marshal((new ObjectFactory()).createRoot("test.Marshal004"), sw);

            if (sw.getBuffer().toString().indexOf("test.Marshal004") == -1) {
                return Status.failed("cannot find string \"test.Marshal004\" in " 
                               + "the marshalled document: " + sw.toString());
            }

            return Status.passed("OKAY");
        } catch (JAXBException jaxbe) {
            jaxbe.printStackTrace(ref);
            return Status.failed(jaxbe.toString());
        }
    }

    public Status Marshal005( ) {
        try {
            Marshaller pm = getMarshaller();

            Node node = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
            DOMResult domResult = new DOMResult(node);

            pm.marshal((new ObjectFactory()).createRoot("test"), (Result)domResult);

            if (! (domResult.getNode().hasChildNodes())) {
                return Status.failed("the node gets no child nodes.");
            }

            return Status.passed("OKAY");
        } catch (FactoryConfigurationError fce) {
            return Status.failed(fce.toString());
        } catch (ParserConfigurationException pce) {
            return Status.failed(pce.toString());
        } catch (JAXBException jaxbe) {
            jaxbe.printStackTrace(ref);
            return Status.failed(jaxbe.toString());
        }
    }

    public Status Marshal006( ) {
        try {
            Marshaller pm = getMarshaller();

            CustomHandler ch = new CustomHandler();
            SAXResult saxResult = new SAXResult(ch);

            pm.marshal((new ObjectFactory()).createRoot("test"), (Result)saxResult);

            if (ch.log.toString().indexOf("startDocument();") == -1) {
                ref.println("Marshal006: " + ch.log);
                return Status.failed("no startDocument() event is logged.");
            }

            if (ch.log.toString().indexOf("endDocument();") == -1) {
                ref.println("Marshal006: " + ch.log);
                return Status.failed("no endDocument() event is logged.");
            }

            return Status.passed("OKAY");
        } catch (JAXBException jaxbe) {
            jaxbe.printStackTrace(ref);
            return Status.failed(jaxbe.toString());
        }
    }

    public Status Marshal007( ) {
        try {
            Marshaller pm = getMarshaller();

            StringWriter sw = new StringWriter();
            StreamResult streamResult = new StreamResult(sw);

            pm.marshal((new ObjectFactory()).createRoot("test.Marshal007"), (Result)streamResult);

            if (sw.getBuffer().toString().indexOf("test.Marshal007") == -1) {
                return Status.failed("cannot find string \"test.Marshal007\" in " 
                               + "the marshalled document: " + sw.toString());
            }

            return Status.passed("OKAY");
        } catch (JAXBException jaxbe) {
            jaxbe.printStackTrace(ref);
            return Status.failed(jaxbe.toString());
        }
    }

    public Status Set001( ) {
        ErrorCollector eh = new ErrorCollector();

        try {
            Marshaller pm = getMarshaller();

            pm.setEventHandler(eh);
            if (pm.getEventHandler() != eh) {
                return Status.passed("getEventHandler() returns " + pm.getEventHandler() 
                                   + " instead of " + eh);
            }

            return Status.passed("OKAY");
        } catch (JAXBException jaxbe) {
            jaxbe.printStackTrace(ref);
            return Status.failed(jaxbe.toString());
        }
    }


}

