/*
 * Copyright (c) 1998, 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:
//     Denise Smith - 2.4 - May 2012
package org.eclipse.persistence.testing.jaxb.json.emptyroot;

import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.Marshaller;
import jakarta.xml.bind.Unmarshaller;
import javax.xml.namespace.QName;
import javax.xml.transform.stream.StreamSource;

import org.eclipse.persistence.jaxb.BeanValidationMode;
import org.eclipse.persistence.jaxb.JAXBContext;
import org.eclipse.persistence.jaxb.JAXBContextFactory;
import org.eclipse.persistence.jaxb.JAXBContextProperties;
import org.eclipse.persistence.jaxb.MarshallerProperties;
import org.eclipse.persistence.jaxb.UnmarshallerProperties;
import org.eclipse.persistence.oxm.XMLConstants;
import org.eclipse.persistence.testing.oxm.OXTestCase;

public class EmptyNullMarshalUnmarshalTestCases extends OXTestCase{

    private static final String EMPTY_JSON = "{}";
    private JAXBContext ctx;
    private JAXBContext ctxNoRoot;

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

    @Override
    public void setUp() throws Exception{
        super.setUp();
        Map<String, Object> props = new HashMap<String, Object>();
        props.put(JAXBContextProperties.MEDIA_TYPE, "application/json");
        props.put(JAXBContextProperties.BEAN_VALIDATION_MODE, BeanValidationMode.NONE);
        Map<String, String> namespaces = new HashMap<String, String>();
        namespaces.put(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi");
        props.put(JAXBContextProperties.NAMESPACE_PREFIX_MAPPER, namespaces);

        ctx = (JAXBContext) JAXBContextFactory.createContext(new Class<?>[]{Root.class}, props);
        ctxNoRoot = (JAXBContext) JAXBContextFactory.createContext(new Class<?>[]{RootNoXmlRootElement.class}, props);
    }

    public void testJAXBElementNullValueIncludeRootTrue() throws Exception{
        StringWriter sw = new StringWriter();
        JAXBElement<Object> obj = new JAXBElement<Object>(new QName(XMLConstants.EMPTY_STRING),Object.class, null );
        Marshaller m = ctx.createMarshaller();
        m.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, true);
        m.marshal(obj, sw);
        compareStrings("testJAXBElementNullValueIncludeRootTrue", EMPTY_JSON, sw.getBuffer().toString());
    }

    public void testJAXBElementNullValueIncludeRootFalse() throws Exception{
        StringWriter sw = new StringWriter();
        JAXBElement<Object> obj = new JAXBElement<Object>(new QName(XMLConstants.EMPTY_STRING),Object.class, null );

        Marshaller m = ctx.createMarshaller();
        m.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
        m.marshal(obj, sw);
        compareStrings("testJAXBElementNullValueIncludeRootFalse", EMPTY_JSON, sw.getBuffer().toString());
    }

    public void testJAXBElementEmptyValueIncludeRootTrue() throws Exception{
        StringWriter sw = new StringWriter();
        JAXBElement<Object> obj = new JAXBElement<Object>(new QName(XMLConstants.EMPTY_STRING),Object.class, new Root() );
        Marshaller m = ctx.createMarshaller();
        m.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, true);
        m.marshal(obj, sw);
        String expectedString = "{\"xsi.type\":\"root\"}";
        compareStrings("testJAXBElementEmptyValueIncludeRootTrue", expectedString, sw.getBuffer().toString());
    }

    public void testJAXBElementEmptyValueIncludeRootFalse() throws Exception{
        StringWriter sw = new StringWriter();
        JAXBElement<Object> obj = new JAXBElement<Object>(new QName(XMLConstants.EMPTY_STRING),Object.class, new Root() );

        Marshaller m = ctx.createMarshaller();
        m.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
        m.marshal(obj, sw);
        String expectedString = "{\"xsi.type\":\"root\"}";
        compareStrings("testJAXBElementEmptyValueIncludeRootFalse", expectedString, sw.getBuffer().toString());
    }

    public void testJAXBElementEmptyValueNoRootIncludeRootTrue() throws Exception{
        StringWriter sw = new StringWriter();
        JAXBElement<Object> obj = new JAXBElement<Object>(new QName(XMLConstants.EMPTY_STRING),Object.class, new RootNoXmlRootElement() );
        Marshaller m = ctxNoRoot.createMarshaller();
        m.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, true);
        m.marshal(obj, sw);
        String expectedString = "{\"xsi.type\":\"rootNoXmlRootElement\"}";
        compareStrings("testJAXBElementEmptyValueNoRootIncludeRootTrue", expectedString, sw.getBuffer().toString());
    }

    public void testJAXBElementEmptyValueNoRootIncludeRootFalse() throws Exception{
        StringWriter sw = new StringWriter();
        JAXBElement<Object> obj = new JAXBElement<Object>(new QName(XMLConstants.EMPTY_STRING),Object.class, new RootNoXmlRootElement() );

        Marshaller m = ctxNoRoot.createMarshaller();
        m.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
        m.marshal(obj, sw);
        String expectedString = "{\"xsi.type\":\"rootNoXmlRootElement\"}";
        compareStrings("testJAXBElementEmptyValueNoRootIncludeRootFalse", expectedString, sw.getBuffer().toString());
    }

    public void testEmptyIncludeRootTrue() throws Exception{
        StringWriter sw = new StringWriter();
        Object obj = new Root();
        Marshaller m = ctx.createMarshaller();
        m.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, true);
        m.marshal(obj, sw);
        String expected = "{\"root\":{}}";
        compareStrings("testEmptyIncludeRootTrue", expected, sw.getBuffer().toString());
    }

    public void testEmptyIncludeRootFalse() throws Exception{
        StringWriter sw = new StringWriter();
        Object obj = new Root();
        Marshaller m = ctx.createMarshaller();
        m.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
        m.marshal(obj, sw);
        compareStrings("testEmptyIncludeRootFalse", EMPTY_JSON, sw.getBuffer().toString());
    }

    public void testEmptyNoRootIncludeRootTrue() throws Exception{
        StringWriter sw = new StringWriter();
        Object obj = new RootNoXmlRootElement();
        Marshaller m = ctxNoRoot.createMarshaller();
        m.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, true);
        m.marshal(obj, sw);
        compareStrings("testEmptyNoRootIncludeRootTrue", EMPTY_JSON, sw.getBuffer().toString());
    }

    public void testEmptyNoRootIncludeRootFalse() throws Exception{
        StringWriter sw = new StringWriter();
        Object obj = new RootNoXmlRootElement();
        Marshaller m = ctxNoRoot.createMarshaller();
        m.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
        m.marshal(obj, sw);
        compareStrings("testEmptyNoRootIncludeRootFalse", EMPTY_JSON, sw.getBuffer().toString());
    }

    public void testListJAXBElementIncludeRootTrue() throws Exception{
        StringWriter sw = new StringWriter();
        JAXBElement<Object> obj = new JAXBElement<Object>(new QName(XMLConstants.EMPTY_STRING),Object.class, new Root() );
        JAXBElement<Object> obj2 = new JAXBElement<Object>(new QName(XMLConstants.EMPTY_STRING),Object.class, new Root() );
        List theList = new ArrayList();
        theList.add(obj);
        theList.add(obj2);
        Marshaller m = ctx.createMarshaller();
        m.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, true);
        m.marshal(theList, sw);
        String expectedString = "[{\"xsi.type\":\"root\"},{\"xsi.type\":\"root\"}]";
        compareStrings("testJAXBElementEmptyValueIncludeRootTrue", expectedString, sw.getBuffer().toString());
    }

    public void testListJAXBElementIncludeRootFalse() throws Exception{
        StringWriter sw = new StringWriter();
        JAXBElement<Object> obj = new JAXBElement<Object>(new QName(XMLConstants.EMPTY_STRING),Object.class, new Root() );
        JAXBElement<Object> obj2 = new JAXBElement<Object>(new QName(XMLConstants.EMPTY_STRING),Object.class, new Root() );
        List theList = new ArrayList();
        theList.add(obj);
        theList.add(obj2);

        Marshaller m = ctx.createMarshaller();
        m.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
        m.marshal(theList, sw);
        String expectedString = "[{\"xsi.type\":\"root\"},{\"xsi.type\":\"root\"}]";
        compareStrings("testJAXBElementEmptyValueIncludeRootFalse", expectedString, sw.getBuffer().toString());
    }

    public void testUnmarshalIncludeRootTrue() throws Exception{
        Unmarshaller unmarshaller = ctx.createUnmarshaller();
        unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, true);
        StringReader reader = new StringReader("{}");
        Object o = unmarshaller.unmarshal(reader);
        assertNull(o);
    }

    public void testUnmarshalIncludeRootFalse() throws Exception{
        Unmarshaller unmarshaller = ctx.createUnmarshaller();
        unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
        StringReader reader = new StringReader("{}");
        Object o = unmarshaller.unmarshal(reader);
        assertNull(o);
    }

    public void testUnmarshalClassIncludeRootTrue() throws Exception{
        Unmarshaller unmarshaller = ctx.createUnmarshaller();
        unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, true);
        StringReader reader = new StringReader("{}");
        Object o = unmarshaller.unmarshal(new StreamSource(reader), Root.class);
        assertTrue (o instanceof JAXBElement);
        JAXBElement controlObj = new JAXBElement(new QName(XMLConstants.EMPTY_STRING),Root.class, null );
        compareJAXBElementObjects(controlObj, (JAXBElement)o);
    }

    public void testUnmarshalClassIncludeRootFalse() throws Exception{
        Unmarshaller unmarshaller = ctx.createUnmarshaller();
        unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
        StringReader reader = new StringReader("{}");
        Object o = unmarshaller.unmarshal(new StreamSource(reader), Root.class);

        assertTrue (o instanceof JAXBElement);
        JAXBElement controlObj = new JAXBElement(new QName(XMLConstants.EMPTY_STRING),Root.class, new Root() );
        compareJAXBElementObjects(controlObj, (JAXBElement)o);
    }


    public void testUnmarshalNoRootTypeAttrIncludeRootFalse() throws Exception{
        Unmarshaller unmarshaller = ctxNoRoot.createUnmarshaller();
        unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
        StringReader reader = new StringReader("{\"xsi.type\":\"rootNoXmlRootElement\"}");
        StringReader reader2 = new StringReader("{\"xsi.type\":\"rootNoXmlRootElement\"}");
        Object o = unmarshaller.unmarshal(new StreamSource(reader), RootNoXmlRootElement.class);
        assertTrue (o instanceof JAXBElement);
        JAXBElement controlObj = new JAXBElement(new QName(XMLConstants.EMPTY_STRING),RootNoXmlRootElement.class, new RootNoXmlRootElement() );
        compareJAXBElementObjects(controlObj, (JAXBElement)o);

        o = unmarshaller.unmarshal(new StreamSource(reader2));
        assertTrue (o instanceof JAXBElement);
        controlObj = new JAXBElement(new QName(XMLConstants.EMPTY_STRING), Object.class, new RootNoXmlRootElement() );
        compareJAXBElementObjects(controlObj, (JAXBElement)o);
    }

    public void testUnmarshalTypeAttrIncludeRootFalse() throws Exception{
        Unmarshaller unmarshaller = ctx.createUnmarshaller();
        unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
        StringReader reader = new StringReader("{\"xsi.type\":\"root\"}");
        StringReader reader2 = new StringReader("{\"xsi.type\":\"root\"}");
        Object o = unmarshaller.unmarshal(new StreamSource(reader), Root.class);

        assertTrue (o instanceof JAXBElement);
        JAXBElement controlObj = new JAXBElement(new QName(XMLConstants.EMPTY_STRING),Root.class, new Root() );
        compareJAXBElementObjects(controlObj, (JAXBElement)o);

        Object o2 = unmarshaller.unmarshal(new StreamSource(reader2));
        assertTrue (o instanceof JAXBElement);
        controlObj = new JAXBElement(new QName(XMLConstants.EMPTY_STRING),Root.class, new Root() );
        compareJAXBElementObjects(controlObj, (JAXBElement)o);

    }


    public void testUnmarshalEmptyListIncludeRootTrue() throws Exception{
        Unmarshaller unmarshaller = ctx.createUnmarshaller();
        unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, true);
        StringReader reader = new StringReader("[]");
        Object o = unmarshaller.unmarshal(new StreamSource(reader));
        assertEquals(new ArrayList(), o);
    }

    public void testUnmarshalEmptyListIncludeRootFalse() throws Exception{
        Unmarshaller unmarshaller = ctx.createUnmarshaller();
        unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
        StringReader reader = new StringReader("[]");
        Object o = unmarshaller.unmarshal(new StreamSource(reader));
        assertEquals(new ArrayList(), o);
    }

    public void testUnmarshalEmptyListObjectIncludeRootTrue() throws Exception{
        Unmarshaller unmarshaller = ctx.createUnmarshaller();
        unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, true);
        StringReader reader = new StringReader("[{}]");
        Object o = unmarshaller.unmarshal(new StreamSource(reader));

        assertTrue (o instanceof List);
        assertEquals(1, ((List)o).size());
        assertNull(((List)o).get(0));

        //JAXBElement controlObj = new JAXBElement(new QName(XMLConstants.EMPTY_STRING),Object.class, null );
        //compareJAXBElementObjects(controlObj, (JAXBElement)((List)o).get(0));
        //fail();
    }

    public void testUnmarshalEmptyListObjectIncludeRootFalse() throws Exception{
        Unmarshaller unmarshaller = ctx.createUnmarshaller();
        unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
        StringReader reader = new StringReader("[{}]");
        Object o = unmarshaller.unmarshal(new StreamSource(reader));

        assertTrue (o instanceof List);
        assertEquals(1, ((List)o).size());
        assertNull(((List)o).get(0));
        //JAXBElement controlObj = new JAXBElement(new QName(XMLConstants.EMPTY_STRING),Object.class, null );
        //compareJAXBElementObjects(controlObj, (JAXBElement)((List)o).get(0));
    }

    public void testUnmarshalEmptyListObjectClassIncludeRootTrue() throws Exception{
        Unmarshaller unmarshaller = ctx.createUnmarshaller();
        unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, true);
        StringReader reader = new StringReader("[{}]");
        JAXBElement<Root> o = unmarshaller.unmarshal(new StreamSource(reader), Root.class);
        //assertTrue (o instanceof JAXBElement);
        //JAXBElement controlObj = new JAXBElement(new QName(XMLConstants.EMPTY_STRING),Root.class, new Root() );
        //compareJAXBElementObjects(controlObj, (JAXBElement)o);

        assertTrue(o.getDeclaredType().equals(Root.class));
        assertTrue(o.getName().equals(new QName("")));

        Object value = o.getValue();
        assertTrue (value instanceof List);
        assertEquals(1, ((List)value).size());


        JAXBElement controlObj = new JAXBElement(new QName(XMLConstants.EMPTY_STRING),Root.class, null );
        compareJAXBElementObjects(controlObj, (JAXBElement)((List)value).get(0));
    }

    public void testUnmarshalEmptyListObjectClassIncludeRootFalse() throws Exception{
        Unmarshaller unmarshaller = ctx.createUnmarshaller();
        unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
        StringReader reader = new StringReader("[{}]");
        JAXBElement<Root> o = unmarshaller.unmarshal(new StreamSource(reader),Root.class);

        assertTrue(o.getDeclaredType().equals(Root.class));
        assertTrue(o.getName().equals(new QName("")));

        Object value = o.getValue();
        assertTrue (value instanceof List);
        assertEquals(1, ((List)value).size());

        assertTrue(((List)value).get(0) instanceof Root);
        assertNull(((Root)((List)value).get(0)).something);
    }

    protected void compareStrings(String test, String expectedString, String testString) {
        log(test);
        log("Expected (With All Whitespace Removed):");
        log(expectedString);
        log("\nActual (With All Whitespace Removed):");
        testString = testString.replaceAll("[ \b\t\n\r]", "");
        log(testString);
        assertEquals(expectedString, testString);
    }
}
