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

package javasoft.sqe.tests.bind.helpers.abstractmarshallerimpl;

import jakarta.xml.bind.helpers.AbstractMarshallerImpl;
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 jakarta.xml.bind.PropertyException;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
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 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 AbstractMarshallerImpl_CTTests extends CTTest {

    /**
     * Command line starter.
     */
    public static void main(String[] args) {
        AbstractMarshallerImpl_CTTests test = new AbstractMarshallerImpl_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();
    }

    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 {
            ParasiteMarshaller pm = new ParasiteMarshaller(this);

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

            if (!(veh instanceof DefaultValidationEventHandler)) {
                return Status.failed("what getEventHandler() returns is not an instance of DefaultValidationEventHandler"
                                   + ", returned is " + veh.getClass().getName());
            }

            return Status.passed("OK");

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

    public Status Get002( ) {
        try {
            ParasiteMarshaller pm = new ParasiteMarshaller(this);

            String enc = pm.getJavaEncoding("unexistentEncoding");
    
            return Status.failed("getJavaEncoding(\"unexistentEncoding\") returns " + enc 
                               + ", but should throw UnsupportedEncodingException");

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

    public Status Get003( ) {
        try {
            ParasiteMarshaller pm = new ParasiteMarshaller(this);

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

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

    public Status Get004( ) {
        try {
            ParasiteMarshaller pm = new ParasiteMarshaller(this);

            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("OK");
        } 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 {
            ParasiteMarshaller pm = new ParasiteMarshaller(this);

            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("OK");
        } catch (JAXBException jaxbe) {
            jaxbe.printStackTrace(ref);
            return Status.failed(jaxbe.toString());
        }
    }

    public Status Marshal002( ) {
        try {
            ParasiteMarshaller pm = new ParasiteMarshaller(this);

            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("OK");
        } 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 {
            ParasiteMarshaller pm = new ParasiteMarshaller(this);

            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("OK");
        } catch (JAXBException jaxbe) {
            jaxbe.printStackTrace(ref);
            return Status.failed(jaxbe.toString());
        }
    }

    public Status Marshal004( ) {
        try {
            ParasiteMarshaller pm = new ParasiteMarshaller(this);

            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("OK");
        } catch (JAXBException jaxbe) {
            jaxbe.printStackTrace(ref);
            return Status.failed(jaxbe.toString());
        }
    }

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

        try {
            ParasiteMarshaller pm = new ParasiteMarshaller(this);

            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());
        }
    }


}

class ParasiteMarshaller extends AbstractMarshallerImpl {
    Marshaller parent;
    public ParasiteMarshaller(CTTest test) throws JAXBException { 
        JAXBContext jc = test.getJAXBContext();
        parent = jc.createMarshaller();
    }
    public void marshal(Object obj, Result result) throws JAXBException {
        parent.marshal(obj, result);
    }
    public String getJavaEncoding(String encoding) throws java.io.UnsupportedEncodingException {
        return super.getJavaEncoding(encoding);
    }
}

