/*
 * Copyright (c) 2012, 2021 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:
//  - rbarkhouse - 07 December 2012 - 2.4 - Initial implementation
package org.eclipse.persistence.testing.jaxb.events;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;

import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.Marshaller;
import javax.xml.namespace.QName;

import junit.framework.TestCase;

import org.eclipse.persistence.jaxb.JAXBContextFactory;

public class JAXBElementTestCases extends TestCase {

    private Marshaller marshaller;
    private MarshalListenerImpl mListener;

    public JAXBElementTestCases(String name) throws Exception {
        super(name);
    }

    @Override
    public String getName() {
        return "Marshaller.Listener tests with JAXBElements " + super.getName();
    }

    @Override
    public void setUp() throws Exception {
        super.setUp();

        mListener = new MarshalListenerImpl();

        JAXBContext context = JAXBContextFactory.createContext(new Class[] { Employee.class }, null);

        marshaller = context.createMarshaller();
        marshaller.setListener(mListener);
    }

    private Object getControlObjectUnmapped() {
        return new JAXBElement<Integer>(new QName("year"), Integer.class, 1942);
    }

    private Object getControlObjectMapped() {
        return new Employee();
    }

    public void testBeforeMarshalUnmapped() throws Exception {
        marshaller.marshal(getControlObjectUnmapped(), new ByteArrayOutputStream());
        assertEquals(1, mListener.beforeClasses.size());
        assertEquals(JAXBElement.class, mListener.beforeClasses.get(0));
    }

    public void testAfterMarshalUnmapped() throws Exception {
        marshaller.marshal(getControlObjectUnmapped(), new ByteArrayOutputStream());

        assertEquals(1, mListener.afterClasses.size());
        assertEquals(JAXBElement.class, mListener.afterClasses.get(0));
    }

    public void testBeforeMarshalMapped() throws Exception {
        marshaller.marshal(getControlObjectMapped(), new ByteArrayOutputStream());

        assertEquals(1, mListener.beforeClasses.size());
        assertEquals(Employee.class, mListener.beforeClasses.get(0));
    }

    public void testAfterMarshalMapped() throws Exception {
        marshaller.marshal(getControlObjectMapped(), new ByteArrayOutputStream());
        assertEquals(1, mListener.afterClasses.size());
        assertEquals(Employee.class, mListener.afterClasses.get(0));
    }

    public void testBeforeMarshalMappedJAXBElement() throws Exception {
        Object obj = getControlObjectMapped();
        JAXBElement elem = new JAXBElement(new QName("root"), obj.getClass(), obj);
        marshaller.marshal(elem, new ByteArrayOutputStream());

        assertEquals(2, mListener.beforeClasses.size());
        assertEquals(JAXBElement.class, mListener.beforeClasses.get(0));
        assertEquals(Employee.class, mListener.beforeClasses.get(1));
    }

    public void testAfterMarshalMappedJAXBElement() throws Exception {
        Object obj = getControlObjectMapped();
        JAXBElement elem = new JAXBElement(new QName("root"), obj.getClass(), obj);

        marshaller.marshal(elem, new ByteArrayOutputStream());

        assertEquals(2, mListener.afterClasses.size());
        assertEquals(Employee.class, mListener.afterClasses.get(0));
        assertEquals(JAXBElement.class, mListener.afterClasses.get(1));
     }



    // ========================================================================

    private class MarshalListenerImpl extends Marshaller.Listener {
        public List<Class> beforeClasses;
        public List<Class> afterClasses;

        public MarshalListenerImpl(){
            beforeClasses = new ArrayList<Class>();
            afterClasses = new ArrayList<Class>();
        }

        @Override
        public void beforeMarshal(Object source) {
            beforeClasses.add(source.getClass());
        }

        @Override
        public void afterMarshal(Object source) {
            afterClasses.add(source.getClass());
        }
    }

}
