/*
 * Copyright (c) 2018, 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
 */

package org.eclipse.persistence.testing.sdo.helper.xmlhelper.loadandsave;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import junit.textui.TestRunner;

import org.eclipse.persistence.oxm.XMLMarshaller;
import org.eclipse.persistence.oxm.XMLUnmarshaller;
import org.eclipse.persistence.oxm.attachment.XMLAttachmentMarshaller;
import org.eclipse.persistence.oxm.attachment.XMLAttachmentUnmarshaller;
import org.eclipse.persistence.sdo.SDOConstants;
import org.eclipse.persistence.sdo.SDOType;
import org.eclipse.persistence.sdo.helper.SDOXMLHelper;

import commonj.sdo.DataObject;
import commonj.sdo.Type;
import commonj.sdo.helper.XMLDocument;

public class LoadAndSaveBase64AttachmentTestCases extends LoadAndSaveTestCases {
    private static String OPTIONS_CONTROL_FILE_NAME = "./org/eclipse/persistence/testing/sdo/helper/xmlhelper/EmployeeWithBase64AttachmentOptions.xml";
    private static String OPTIONS_CONTROL_ID = "OPTIONS";
    private static byte[] OPTIONS_CONTROL_BYTES = "OPTIONS".getBytes();

    public LoadAndSaveBase64AttachmentTestCases(String name) {
        super(name);
    }

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

        XMLMarshaller aMarshaller = ((SDOXMLHelper)xmlHelper).getXmlMarshaller();
        XMLUnmarshaller anUnmarshaller = ((SDOXMLHelper)xmlHelper).getXmlUnmarshaller();
        XMLAttachmentMarshaller anAttachmentMarshaller = new AttachmentMarshallerImpl("c_id0");
        XMLAttachmentUnmarshaller anAttachmentUnmarshaller = new AttachmentUnmarshallerImpl("Testing".getBytes());
        aMarshaller.setAttachmentMarshaller(anAttachmentMarshaller);
        anUnmarshaller.setAttachmentUnmarshaller(anAttachmentUnmarshaller);
    }

    @Override
    protected String getSchemaName() {
        return "./org/eclipse/persistence/testing/sdo/schemas/EmployeeWithBase64Attachment.xsd";
    }

    @Override
    protected String getControlFileName() {
        return ("./org/eclipse/persistence/testing/sdo/helper/xmlhelper/EmployeeWithBase64Attachment.xml");
    }

    @Override
    protected String getNoSchemaControlFileName() {
        return ("./org/eclipse/persistence/testing/sdo/helper/xmlhelper/EmployeeWithBase64Attachment.xml");
    }

    @Override
    protected String getControlRootURI() {
        return "http://www.example.org";
    }

    @Override
    protected String getControlRootName() {
        return "employeeType";
    }

    @Override
    protected String getRootInterfaceName() {
        return "EmployeeType";
    }

    @Override
    public void registerTypes() {
        SDOType stringType = (SDOType) typeHelper.getType("commonj.sdo", "String");
        SDOType bytesType = (SDOType) typeHelper.getType("commonj.sdo", "Bytes");
        SDOType propertyType = (SDOType) typeHelper.getType(SDOConstants.SDO_URL, SDOConstants.PROPERTY);

        // create a new Type for Customers
        DataObject customerType = dataFactory.create("commonj.sdo", "Type");
        customerType.set("uri", getControlRootURI());
        customerType.set("name", "EmployeeType");

        // create an idproperty
        addProperty(customerType, "id", stringType, false, false, true);

        // create a first name property
        addProperty(customerType, "name", stringType, false, false, true);

        // create a photo property
        DataObject photoProp = addProperty(customerType, "photo", bytesType, true, true, true);

        // now define the Customer type so that customers can be made
         Type customerSDOType = typeHelper.define(customerType);

        DataObject propDO = dataFactory.create(propertyType);
        propDO.set("name", getControlRootName());
        propDO.set("type", customerSDOType);
        typeHelper.defineOpenContentProperty(getControlRootURI(), propDO);
    }

    public void testLoadFromInputStreamSaveToOutputStreamWithOptions() throws Exception {
        defineTypes();

        DataObject loadOptions = dataFactory.create(SDOConstants.ORACLE_SDO_URL, SDOConstants.XMLHELPER_LOAD_OPTIONS);
        loadOptions.set(SDOConstants.ATTACHMENT_UNMARSHALLER_OPTION, new AttachmentUnmarshallerImpl(OPTIONS_CONTROL_BYTES));
        FileInputStream inputStream = new FileInputStream(OPTIONS_CONTROL_FILE_NAME);
        XMLDocument document = xmlHelper.load(inputStream, null, loadOptions);

        assertEquals(OPTIONS_CONTROL_BYTES, document.getRootObject().get("photo"));

        DataObject saveOptions = dataFactory.create(SDOConstants.ORACLE_SDO_URL, SDOConstants.XMLHELPER_LOAD_OPTIONS);
        saveOptions.set(SDOConstants.ATTACHMENT_MARSHALLER_OPTION, new AttachmentMarshallerImpl(OPTIONS_CONTROL_ID));
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        xmlHelper.save(document, outputStream, saveOptions);

        compareXML(OPTIONS_CONTROL_FILE_NAME, outputStream.toString());
    }

    public void testLoadFromReaderSaveToWriterWithOptions() throws Exception {
        defineTypes();

        DataObject options = dataFactory.create(SDOConstants.ORACLE_SDO_URL, SDOConstants.XMLHELPER_LOAD_OPTIONS);
        options.set(SDOConstants.ATTACHMENT_UNMARSHALLER_OPTION, new AttachmentUnmarshallerImpl(OPTIONS_CONTROL_BYTES));
        FileInputStream inputStream = new FileInputStream(OPTIONS_CONTROL_FILE_NAME);
        InputStreamReader reader = new InputStreamReader(inputStream);
        XMLDocument document = xmlHelper.load(reader, null, options);

        assertEquals(OPTIONS_CONTROL_BYTES, document.getRootObject().get("photo"));

        DataObject saveOptions = dataFactory.create(SDOConstants.ORACLE_SDO_URL, SDOConstants.XMLHELPER_LOAD_OPTIONS);
        saveOptions.set(SDOConstants.ATTACHMENT_MARSHALLER_OPTION, new AttachmentMarshallerImpl(OPTIONS_CONTROL_ID));
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        OutputStreamWriter writer = new OutputStreamWriter(outputStream);
        xmlHelper.save(document, writer, saveOptions);

        compareXML(OPTIONS_CONTROL_FILE_NAME, outputStream.toString());
    }

    public void testLoadFromSourceSaveToResultWithOptions() throws Exception {
        defineTypes();

        DataObject options = dataFactory.create(SDOConstants.ORACLE_SDO_URL, SDOConstants.XMLHELPER_LOAD_OPTIONS);
        options.set(SDOConstants.ATTACHMENT_UNMARSHALLER_OPTION, new AttachmentUnmarshallerImpl(OPTIONS_CONTROL_BYTES));
        FileInputStream inputStream = new FileInputStream(OPTIONS_CONTROL_FILE_NAME);
        StreamSource source = new StreamSource(inputStream);
        XMLDocument document = xmlHelper.load(source, null, options);

        assertEquals(OPTIONS_CONTROL_BYTES, document.getRootObject().get("photo"));

        DataObject saveOptions = dataFactory.create(SDOConstants.ORACLE_SDO_URL, SDOConstants.XMLHELPER_LOAD_OPTIONS);
        saveOptions.set(SDOConstants.ATTACHMENT_MARSHALLER_OPTION, new AttachmentMarshallerImpl(OPTIONS_CONTROL_ID));
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        StreamResult result = new StreamResult(outputStream);
        xmlHelper.save(document, result, saveOptions);

        compareXML(OPTIONS_CONTROL_FILE_NAME, outputStream.toString());
    }

}
