/*
 * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Blaise Doughan - 2.4.2 - initial implementation
package org.eclipse.persistence.testing.jaxb.xmlmarshaller;

import java.io.ByteArrayOutputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.List;

import jakarta.xml.bind.Binder;
import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.Marshaller;
import jakarta.xml.bind.Unmarshaller;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.stream.StreamSource;

import org.eclipse.persistence.jaxb.JAXBBinder;
import org.eclipse.persistence.jaxb.JAXBContextFactory;
import org.eclipse.persistence.testing.jaxb.xmlmarshaller.ListenerMarshal.MarshalEvent;
import org.eclipse.persistence.testing.jaxb.xmlmarshaller.ListenerUnmarshal.UnmarshalEvent;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.helpers.DefaultHandler;

import junit.framework.TestCase;

public class ListenerTestCases extends TestCase {

    private static String ROOT_XML = "<root><name>Foo</name><child/></root>";
    private static String ELEMENT_DECL_XML = "<ledo><name>Bar</name><child/></ledo>";

    private JAXBContext jc;

    public JAXBElement<ListenerElementDeclObject> getControlJAXBElement() {
        ListenerElementDeclObject ledo = new ListenerElementDeclObject();
        ledo.name = "Bar";
        ledo.child = new ListenerChildObject();
        ListenerObjectFactory objectFactory = new ListenerObjectFactory();
        return objectFactory.createElementDecl(ledo);
    }

    public ListenerRootObject getControlRootObject() {
        ListenerRootObject rootObject = new ListenerRootObject();
        rootObject.name = "Foo";
        rootObject.child = new ListenerChildObject();
        return rootObject;
    }

    @Override
    protected void setUp() throws Exception {
        jc = JAXBContextFactory.createContext(new Class[] {ListenerRootObject.class, ListenerElementDeclObject.class, ListenerObjectFactory.class}, null);
    }

    private void testMarshalListenerElementDecl(JAXBElement<ListenerElementDeclObject> jaxbElement, Marshaller marshaller, ListenerMarshal listener) throws Exception {
        List<MarshalEvent> events = listener.getEvents();
        assertEquals(6, events.size());

        assertEquals(true, events.get(0).isBeforeEvent());
        assertSame(jaxbElement, events.get(0).getSource());

        assertEquals(true, events.get(1).isBeforeEvent());
        assertSame(jaxbElement.getValue(), events.get(1).getSource());
        assertSame(marshaller, jaxbElement.getValue().beforeMarshalMarshaller);

        assertEquals(true, events.get(2).isBeforeEvent());
        assertSame(jaxbElement.getValue().child, events.get(2).getSource());
        assertSame(marshaller, jaxbElement.getValue().beforeMarshalMarshaller);

        assertEquals(false, events.get(3).isBeforeEvent());
        assertSame(jaxbElement.getValue().child, events.get(3).getSource());
        assertSame(marshaller, jaxbElement.getValue().child.afterMarshalMarshaller);

        assertEquals(false, events.get(4).isBeforeEvent());
        assertSame(jaxbElement.getValue(), events.get(4).getSource());
        assertSame(marshaller, jaxbElement.getValue().afterMarshalMarshaller);

        assertEquals(false, events.get(5).isBeforeEvent());
        assertSame(jaxbElement, events.get(5).getSource());
    }

    public void testMarshalListenerElementDecl_ContentHandler() throws Exception {
        JAXBElement<ListenerElementDeclObject> jaxbElement = getControlJAXBElement();

        Marshaller marshaller = jc.createMarshaller();
        ListenerMarshal listener = new ListenerMarshal();
        marshaller.setListener(listener);
        marshaller.marshal(jaxbElement, new DefaultHandler());

        testMarshalListenerElementDecl(jaxbElement, marshaller, listener);
    }

    public void testMarshalListenerElementDecl_Node() throws Exception {
        JAXBElement<ListenerElementDeclObject> jaxbElement = getControlJAXBElement();

        Marshaller marshaller = jc.createMarshaller();
        ListenerMarshal listener = new ListenerMarshal();
        marshaller.setListener(listener);

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document document = db.newDocument();
        marshaller.marshal(jaxbElement, document);

        testMarshalListenerElementDecl(jaxbElement, marshaller, listener);
    }

    public void testMarshalListenerElementDecl_OutputStream() throws Exception {
        JAXBElement<ListenerElementDeclObject> jaxbElement = getControlJAXBElement();

        Marshaller marshaller = jc.createMarshaller();
        ListenerMarshal listener = new ListenerMarshal();
        marshaller.setListener(listener);
        marshaller.marshal(jaxbElement, new ByteArrayOutputStream());

        testMarshalListenerElementDecl(jaxbElement, marshaller, listener);
    }

    public void testMarshalListenerElementDecl_Writer() throws Exception {
        JAXBElement<ListenerElementDeclObject> jaxbElement = getControlJAXBElement();

        Marshaller marshaller = jc.createMarshaller();
        ListenerMarshal listener = new ListenerMarshal();
        marshaller.setListener(listener);
        marshaller.marshal(jaxbElement, new StringWriter());

        testMarshalListenerElementDecl(jaxbElement, marshaller, listener);
    }

    public void testMarshalListenerElementDecl_XMLEventWriter() throws Exception {
        JAXBElement<ListenerElementDeclObject> jaxbElement = getControlJAXBElement();

        Marshaller marshaller = jc.createMarshaller();
        ListenerMarshal listener = new ListenerMarshal();
        marshaller.setListener(listener);

        XMLOutputFactory xof = XMLOutputFactory.newFactory();
        XMLEventWriter xew = xof.createXMLEventWriter(new StringWriter());
        marshaller.marshal(jaxbElement, xew);
        xew.close();

        testMarshalListenerElementDecl(jaxbElement, marshaller, listener);
    }

    public void testMarshalListenerElementDecl_XMLStreamWriter() throws Exception {
        JAXBElement<ListenerElementDeclObject> jaxbElement = getControlJAXBElement();

        Marshaller marshaller = jc.createMarshaller();
        ListenerMarshal listener = new ListenerMarshal();
        marshaller.setListener(listener);

        XMLOutputFactory xof = XMLOutputFactory.newFactory();
        XMLStreamWriter xsw = xof.createXMLStreamWriter(new StringWriter());
        marshaller.marshal(jaxbElement, xsw);
        xsw.close();

        testMarshalListenerElementDecl(jaxbElement, marshaller, listener);
    }

    private void testMarshalListenerRootObject(ListenerRootObject rootObject, Marshaller marshaller, ListenerMarshal listener) throws Exception {
        List<MarshalEvent> events = listener.getEvents();
        assertEquals(4, events.size());

        assertEquals(true, events.get(0).isBeforeEvent());
        assertSame(rootObject, events.get(0).getSource());
        assertSame(marshaller, rootObject.beforeMarshalMarshaller);

        assertEquals(true, events.get(1).isBeforeEvent());
        assertSame(rootObject.child, events.get(1).getSource());
        assertSame(marshaller, rootObject.child.beforeMarshalMarshaller);

        assertEquals(false, events.get(2).isBeforeEvent());
        assertSame(rootObject.child, events.get(2).getSource());
        assertSame(marshaller, rootObject.child.afterMarshalMarshaller);

        assertEquals(false, events.get(3).isBeforeEvent());
        assertSame(rootObject, events.get(3).getSource());
        assertSame(marshaller, rootObject.child.afterMarshalMarshaller);
    }

    public void testMarshalListenerRootObject_ContentHandler() throws Exception {
        ListenerRootObject rootObject = getControlRootObject();

        Marshaller marshaller = jc.createMarshaller();
        ListenerMarshal listener = new ListenerMarshal();
        marshaller.setListener(listener);
        marshaller.marshal(rootObject, new DefaultHandler());

        testMarshalListenerRootObject(rootObject, marshaller, listener);
    }

    public void testMarshalListenerRootObject_Node() throws Exception {
        ListenerRootObject rootObject = getControlRootObject();

        Marshaller marshaller = jc.createMarshaller();
        ListenerMarshal listener = new ListenerMarshal();
        marshaller.setListener(listener);

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document document = db.newDocument();
        marshaller.marshal(rootObject, document);

        testMarshalListenerRootObject(rootObject, marshaller, listener);
    }

    public void testMarshalListenerRootObject_OuputStream() throws Exception {
        ListenerRootObject rootObject = getControlRootObject();

        Marshaller marshaller = jc.createMarshaller();
        ListenerMarshal listener = new ListenerMarshal();
        marshaller.setListener(listener);
        marshaller.marshal(rootObject, new ByteArrayOutputStream());

        testMarshalListenerRootObject(rootObject, marshaller, listener);
    }

    public void testMarshalListenerRootObject_Writer() throws Exception {
        ListenerRootObject rootObject = getControlRootObject();

        Marshaller marshaller = jc.createMarshaller();
        ListenerMarshal listener = new ListenerMarshal();
        marshaller.setListener(listener);
        marshaller.marshal(rootObject, new StringWriter());

        testMarshalListenerRootObject(rootObject, marshaller, listener);
    }

    public void testMarshalListenerRootObject_XMLEventWriter() throws Exception {
        ListenerRootObject rootObject = getControlRootObject();

        Marshaller marshaller = jc.createMarshaller();
        ListenerMarshal listener = new ListenerMarshal();
        marshaller.setListener(listener);

        XMLOutputFactory xof = XMLOutputFactory.newFactory();
        XMLEventWriter xew = xof.createXMLEventWriter(new StringWriter());
        marshaller.marshal(rootObject, xew);
        xew.close();

        testMarshalListenerRootObject(rootObject, marshaller, listener);
    }

    public void testMarshalListenerRootObject_XMLStreamWriter() throws Exception {
        ListenerRootObject rootObject = getControlRootObject();

        Marshaller marshaller = jc.createMarshaller();
        ListenerMarshal listener = new ListenerMarshal();
        marshaller.setListener(listener);

        XMLOutputFactory xof = XMLOutputFactory.newFactory();
        XMLStreamWriter xsw = xof.createXMLStreamWriter(new StringWriter());
        marshaller.marshal(rootObject, xsw);
        xsw.close();

        testMarshalListenerRootObject(rootObject, marshaller, listener);
    }

    private void testUnmarshalListenerElementDecl(JAXBElement<ListenerElementDeclObject> jaxbElement, Unmarshaller unmarshaller, ListenerUnmarshal listener) throws Exception {
        List<UnmarshalEvent> events = listener.getEvents();
        assertEquals(6, events.size());

        assertEquals(true, events.get(0).isBeforeEvent());
        assertSame(jaxbElement, events.get(0).getTarget());
        assertNull(events.get(0).getParent());

        assertEquals(true, events.get(1).isBeforeEvent());
        assertSame(jaxbElement.getValue(), events.get(1).getTarget());
        assertSame(jaxbElement, events.get(1).getParent());
        assertSame(unmarshaller, jaxbElement.getValue().beforeUnmarshalUnmarshaller);
        assertSame(jaxbElement, jaxbElement.getValue().beforeUnmarshalParent);

        assertEquals(true, events.get(2).isBeforeEvent());
        assertSame(jaxbElement.getValue().child, events.get(2).getTarget());
        assertSame(jaxbElement.getValue(), events.get(2).getParent());
        assertSame(unmarshaller, jaxbElement.getValue().child.beforeUnmarshalUnmarshaller);
        assertSame(jaxbElement.getValue(), jaxbElement.getValue().child.beforeUnmarshalParent);

        assertEquals(false, events.get(3).isBeforeEvent());
        assertSame(jaxbElement.getValue().child, events.get(3).getTarget());
        assertSame(jaxbElement.getValue(), events.get(3).getParent());
        assertSame(unmarshaller, jaxbElement.getValue().child.afterUnmarshalUnmarshaller);
        assertSame(jaxbElement.getValue(), jaxbElement.getValue().child.afterUnmarshalParent);

        assertEquals(false, events.get(4).isBeforeEvent());
        assertSame(jaxbElement.getValue(), events.get(4).getTarget());
        assertSame(jaxbElement, events.get(4).getParent());
        assertSame(unmarshaller, jaxbElement.getValue().afterUnmarshalUnmarshaller);
        assertSame(jaxbElement, jaxbElement.getValue().afterUnmarshalParent);

        assertEquals(false, events.get(5).isBeforeEvent());
        assertSame(jaxbElement, events.get(5).getTarget());
        assertNull(events.get(5).getParent());
    }
/*
    public void testUnmarshalListenerElementDecl_InputSource() throws Exception {
        InputSource xml = new InputSource(new StringReader(ELEMENT_DECL_XML));

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        ListenerUnmarshal listener = new ListenerUnmarshal();
        unmarshaller.setListener(listener);
        JAXBElement<ListenerElementDeclObject> jaxbElement = (JAXBElement<ListenerElementDeclObject>) unmarshaller.unmarshal(xml);

        testUnmarshalListenerElementDecl(jaxbElement, unmarshaller, listener);
    }

    public void testUnmarshalListenerElementDecl_Node() throws Exception {
        InputSource inputSource = new InputSource(new StringReader(ELEMENT_DECL_XML));
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document document = db.parse(inputSource);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        ListenerUnmarshal listener = new ListenerUnmarshal();
        unmarshaller.setListener(listener);
        JAXBElement<ListenerElementDeclObject> jaxbElement = (JAXBElement<ListenerElementDeclObject>) unmarshaller.unmarshal(document);

        testUnmarshalListenerElementDecl(jaxbElement, unmarshaller, listener);
    }

    public void testUnmarshalListenerElementDecl_Reader() throws Exception {
        StringReader xml = new StringReader(ELEMENT_DECL_XML);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        ListenerUnmarshal listener = new ListenerUnmarshal();
        unmarshaller.setListener(listener);
        JAXBElement<ListenerElementDeclObject> jaxbElement = (JAXBElement<ListenerElementDeclObject>) unmarshaller.unmarshal(xml);

        testUnmarshalListenerElementDecl(jaxbElement, unmarshaller, listener);
    }

    public void testUnmarshalListenerElementDecl_Source() throws Exception {
        StringReader stringReader = new StringReader(ELEMENT_DECL_XML);
        StreamSource source = new StreamSource(stringReader);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        ListenerUnmarshal listener = new ListenerUnmarshal();
        unmarshaller.setListener(listener);
        JAXBElement<ListenerElementDeclObject> jaxbElement = (JAXBElement<ListenerElementDeclObject>) unmarshaller.unmarshal(source);

        testUnmarshalListenerElementDecl(jaxbElement, unmarshaller, listener);
    }

    public void testUnmarshalListenerElementDecl_XMLEventReader() throws Exception {
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        ListenerUnmarshal listener = new ListenerUnmarshal();
        unmarshaller.setListener(listener);

        XMLInputFactory xif = XMLInputFactory.newFactory();
        XMLEventReader xew = xif.createXMLEventReader(new StringReader(ELEMENT_DECL_XML));
        JAXBElement<ListenerElementDeclObject> jaxbElement = (JAXBElement<ListenerElementDeclObject>) unmarshaller.unmarshal(xew);

        testUnmarshalListenerElementDecl(jaxbElement, unmarshaller, listener);
    }

    public void testUnmarshalListenerElementDecl_XMLStreamReader() throws Exception {
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        ListenerUnmarshal listener = new ListenerUnmarshal();
        unmarshaller.setListener(listener);

        XMLInputFactory xif = XMLInputFactory.newFactory();
        XMLStreamReader xew = xif.createXMLStreamReader(new StringReader(ELEMENT_DECL_XML));
        JAXBElement<ListenerElementDeclObject> jaxbElement = (JAXBElement<ListenerElementDeclObject>) unmarshaller.unmarshal(xew);

        testUnmarshalListenerElementDecl(jaxbElement, unmarshaller, listener);
    }
*/
    private void testUnmarshalListenerRootObject(ListenerRootObject rootObject, Unmarshaller unmarshaller, ListenerUnmarshal listener) throws Exception {
        List<UnmarshalEvent> events = listener.getEvents();
        assertEquals(4, events.size());

        assertEquals(true, events.get(0).isBeforeEvent());
        assertSame(rootObject, events.get(0).getTarget());
        assertNull(events.get(0).getParent());
        assertSame(unmarshaller, rootObject.beforeUnmarshalUnmarshaller);
        assertNull(rootObject.beforeUnmarshalParent);

        assertEquals(true, events.get(1).isBeforeEvent());
        assertSame(rootObject.child, events.get(1).getTarget());
        assertSame(rootObject, events.get(1).getParent());
        assertSame(unmarshaller, rootObject.child.beforeUnmarshalUnmarshaller);
        assertSame(rootObject, rootObject.child.beforeUnmarshalParent);

        assertEquals(false, events.get(2).isBeforeEvent());
        assertSame(rootObject.child, events.get(2).getTarget());
        assertSame(rootObject, events.get(2).getParent());
        assertSame(unmarshaller, rootObject.child.afterUnmarshalUnmarshaller);
        assertSame(rootObject, rootObject.child.afterUnmarshalParent);

        assertEquals(false, events.get(3).isBeforeEvent());
        assertSame(rootObject, events.get(3).getTarget());
        assertNull(events.get(3).getParent());
        assertSame(unmarshaller, rootObject.afterUnmarshalUnmarshaller);
        assertNull(rootObject.afterUnmarshalParent);
    }

    public void testUnmarshalListenerRootObject_InputSource() throws Exception {
        InputSource xml = new InputSource(new StringReader(ROOT_XML));

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        ListenerUnmarshal listener = new ListenerUnmarshal();
        unmarshaller.setListener(listener);
        ListenerRootObject rootObject = (ListenerRootObject) unmarshaller.unmarshal(xml);

        testUnmarshalListenerRootObject(rootObject, unmarshaller, listener);
    }

    public void testUnmarshalListenerRootObject_Node() throws Exception {
        InputSource inputSource = new InputSource(new StringReader(ROOT_XML));
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document document = db.parse(inputSource);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        ListenerUnmarshal listener = new ListenerUnmarshal();
        unmarshaller.setListener(listener);
        ListenerRootObject rootObject = (ListenerRootObject) unmarshaller.unmarshal(document);

        testUnmarshalListenerRootObject(rootObject, unmarshaller, listener);
    }

    public void testUnmarshalListenerRootObject_Reader() throws Exception {
        StringReader xml = new StringReader(ROOT_XML);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        ListenerUnmarshal listener = new ListenerUnmarshal();
        unmarshaller.setListener(listener);
        ListenerRootObject rootObject = (ListenerRootObject) unmarshaller.unmarshal(xml);

        testUnmarshalListenerRootObject(rootObject, unmarshaller, listener);
    }

    public void testUnmarshalListenerRootObject_Source() throws Exception {
        StreamSource source = new StreamSource(new StringReader(ROOT_XML));

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        ListenerUnmarshal listener = new ListenerUnmarshal();
        unmarshaller.setListener(listener);
        ListenerRootObject rootObject = (ListenerRootObject) unmarshaller.unmarshal(source);

        testUnmarshalListenerRootObject(rootObject, unmarshaller, listener);
    }

    public void testUnmarshalListenerRootObject_XMLEventReader() throws Exception {
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        ListenerUnmarshal listener = new ListenerUnmarshal();
        unmarshaller.setListener(listener);

        XMLInputFactory xif = XMLInputFactory.newFactory();
        XMLEventReader xew = xif.createXMLEventReader(new StringReader(ROOT_XML));
        ListenerRootObject rootObject = (ListenerRootObject) unmarshaller.unmarshal(xew);

        testUnmarshalListenerRootObject(rootObject, unmarshaller, listener);
    }

    public void testUnmarshalListenerRootObject_XMLStreamReader() throws Exception {
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        ListenerUnmarshal listener = new ListenerUnmarshal();
        unmarshaller.setListener(listener);

        XMLInputFactory xif = XMLInputFactory.newFactory();
        XMLStreamReader xsw = xif.createXMLStreamReader(new StringReader(ROOT_XML));
        ListenerRootObject rootObject = (ListenerRootObject) unmarshaller.unmarshal(xsw);

        testUnmarshalListenerRootObject(rootObject, unmarshaller, listener);
    }

    private void testUnmarshalListenerRootObjectAsJAXBElement(JAXBElement<ListenerRootObject> jaxbElement, Unmarshaller unmarshaller, ListenerUnmarshal listener) throws Exception {
        List<UnmarshalEvent> events = listener.getEvents();
        assertEquals(6, events.size());

        assertEquals(true, events.get(0).isBeforeEvent());
        assertSame(jaxbElement, events.get(0).getTarget());
        assertNull(events.get(0).getParent());

        assertEquals(true, events.get(1).isBeforeEvent());
        assertSame(jaxbElement.getValue(), events.get(1).getTarget());
        assertSame(jaxbElement, events.get(1).getParent());
        assertSame(unmarshaller, jaxbElement.getValue().beforeUnmarshalUnmarshaller);
        assertSame(jaxbElement, jaxbElement.getValue().beforeUnmarshalParent);

        assertEquals(true, events.get(2).isBeforeEvent());
        assertSame(jaxbElement.getValue().child, events.get(2).getTarget());
        assertSame(jaxbElement.getValue(), events.get(2).getParent());
        assertSame(unmarshaller, jaxbElement.getValue().child.beforeUnmarshalUnmarshaller);
        assertSame(jaxbElement.getValue(), jaxbElement.getValue().child.beforeUnmarshalParent);

        assertEquals(false, events.get(3).isBeforeEvent());
        assertSame(jaxbElement.getValue().child, events.get(3).getTarget());
        assertSame(jaxbElement.getValue(), events.get(3).getParent());
        assertSame(unmarshaller, jaxbElement.getValue().child.afterUnmarshalUnmarshaller);
        assertSame(jaxbElement.getValue(), jaxbElement.getValue().child.afterUnmarshalParent);

        assertEquals(false, events.get(4).isBeforeEvent());
        assertSame(jaxbElement.getValue(), events.get(4).getTarget());
        assertSame(jaxbElement, events.get(4).getParent());
        assertSame(unmarshaller, jaxbElement.getValue().afterUnmarshalUnmarshaller);
        assertSame(jaxbElement, jaxbElement.getValue().afterUnmarshalParent);

        assertEquals(false, events.get(5).isBeforeEvent());
        assertSame(jaxbElement, events.get(5).getTarget());
        assertNull(events.get(5).getParent());
    }
/*
    public void testUnmarshalListenerRootObjectAsJAXBElement_Source() throws Exception {
        StringReader xml = new StringReader(ROOT_XML);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        ListenerUnmarshal listener = new ListenerUnmarshal();
        unmarshaller.setListener(listener);
        JAXBElement<ListenerRootObject> jaxbElement = unmarshaller.unmarshal(new StreamSource(xml), ListenerRootObject.class);

        testUnmarshalListenerRootObjectAsJAXBElement(jaxbElement, unmarshaller, listener);
    }

    public void testUnmarshalListenerRootObjectAsJAXBElement_XMLEventReader() throws Exception {
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        ListenerUnmarshal listener = new ListenerUnmarshal();
        unmarshaller.setListener(listener);

        XMLInputFactory xif = XMLInputFactory.newFactory();
        XMLEventReader xer = xif.createXMLEventReader(new StringReader(ROOT_XML));
        JAXBElement<ListenerRootObject> jaxbElement = unmarshaller.unmarshal(xer, ListenerRootObject.class);

        testUnmarshalListenerRootObjectAsJAXBElement(jaxbElement, unmarshaller, listener);
    }

    public void testUnmarshalListenerRootObjectAsJAXBElement_XMLStreamReader() throws Exception {
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        ListenerUnmarshal listener = new ListenerUnmarshal();
        unmarshaller.setListener(listener);

        XMLInputFactory xif = XMLInputFactory.newFactory();
        XMLStreamReader xsr = xif.createXMLStreamReader(new StringReader(ROOT_XML));
        JAXBElement<ListenerRootObject> jaxbElement = unmarshaller.unmarshal(xsr, ListenerRootObject.class);

        testUnmarshalListenerRootObjectAsJAXBElement(jaxbElement, unmarshaller, listener);
    }
*/

    public void testClassCallbacksForBinder() throws Exception {
        Binder binder = jc.createBinder();

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document doc = db.parse(new InputSource(new StringReader(ROOT_XML)));

        //marshal and unmarshal
        ListenerRootObject root = (ListenerRootObject) binder.unmarshal(doc);
        binder.marshal(root, db.newDocument());

        // just tests the fact that they are called
        assertNotNull(root.afterMarshalMarshaller);
        assertNotNull(root.beforeMarshalMarshaller);
        assertNotNull(root.afterUnmarshalUnmarshaller);
        assertNotNull(root.beforeUnmarshalUnmarshaller);
    }
}
