/*
 * 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, Integer.valueOf(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());
        }
    }

}
