/*
 * 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:
//     Blaise Doughan - 2.4 - initial implementation
package org.eclipse.persistence.testing.jaxb.jaxbcontext.sessioneventlistener;

import java.io.StringReader;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.Unmarshaller;

import junit.framework.TestCase;

import org.eclipse.persistence.jaxb.JAXBContextFactory;
import org.eclipse.persistence.jaxb.JAXBContextProperties;
import org.eclipse.persistence.jaxb.TypeMappingInfo;
import org.eclipse.persistence.sessions.SessionEventListener;

public class SessionEventListenerTestCases extends TestCase {

    private static final String XML = "<address><id>123</id></address>";

    private SessionEventListener sessionEventListener = null;


    @Override
    protected void setUp() throws Exception {
        sessionEventListener = new TestSessionEventListener();
        Address.INSTANTIATION_COUNTER = 0;
    }

    public void testClassArrayMap() throws Exception {
        Map<String, Object> properties = new HashMap<String, Object>(1);
        properties.put(JAXBContextProperties.SESSION_EVENT_LISTENER, sessionEventListener);
        JAXBContext jc = JAXBContextFactory.createContext(new Class[] {Address.class}, properties);
        assertEquals(0, Address.INSTANTIATION_COUNTER);
        unmarshalTest(jc);
    }

    public void testClassArrayMapClassLoader() throws Exception {
        Map<String, Object> properties = new HashMap<String, Object>(1);
        properties.put(JAXBContextProperties.SESSION_EVENT_LISTENER, sessionEventListener);
        JAXBContext jc = JAXBContextFactory.createContext(new Class[] {Address.class}, properties, Address.class.getClassLoader());
        assertEquals(0, Address.INSTANTIATION_COUNTER);
        unmarshalTest(jc);
    }

    public void testContextPathClassLoaderMap() throws Exception {
        Map<String, Object> properties = new HashMap<String, Object>(1);
        properties.put(JAXBContextProperties.SESSION_EVENT_LISTENER, sessionEventListener);
        JAXBContext jc = JAXBContextFactory.createContext("org.eclipse.persistence.testing.jaxb.jaxbcontext.sessioneventlistener", Address.class.getClassLoader(), properties);
        assertEquals(0, Address.INSTANTIATION_COUNTER);
        unmarshalTest(jc);
    }

    public void testTypeArrayMapClassLoader() throws Exception {
        Map<String, Object> properties = new HashMap<String, Object>(1);
        properties.put(JAXBContextProperties.SESSION_EVENT_LISTENER, sessionEventListener);
        JAXBContext jc = JAXBContextFactory.createContext(new Type[] {Address.class}, properties, Address.class.getClassLoader());
        assertEquals(0, Address.INSTANTIATION_COUNTER);
        unmarshalTest(jc);
    }

    public void testTypeMappingInfoArrayMapClassLoader() throws Exception {
        Map<String, Object> properties = new HashMap<String, Object>(1);
        properties.put(JAXBContextProperties.SESSION_EVENT_LISTENER, sessionEventListener);
        TypeMappingInfo[] typeMappingInfos = new TypeMappingInfo[1];
        TypeMappingInfo typeMappingInfo = new TypeMappingInfo();
        typeMappingInfo.setType(Address.class);
        typeMappingInfos[0] = typeMappingInfo;
        JAXBContext jc = JAXBContextFactory.createContext(typeMappingInfos, properties, Address.class.getClassLoader());
        assertEquals(0, Address.INSTANTIATION_COUNTER);
        unmarshalTest(jc);
    }

    private void unmarshalTest(JAXBContext jc) throws Exception{
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Object test = unmarshaller.unmarshal(new StringReader(XML));
        assertEquals(getControlObject(), test);
    }

    private AddressAddedByEvent getControlObject() {
        AddressAddedByEvent control = new AddressAddedByEvent();
        control.setId(123);
        return control;
    }

}
