/*
 * 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:
//     David McCann - 2.3 - Initial implementation
package org.eclipse.persistence.testing.sdo.helper.typehelper;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import junit.textui.TestRunner;

import org.eclipse.persistence.oxm.XMLConstants;
import org.eclipse.persistence.sdo.SDOConstants;
import org.eclipse.persistence.sdo.SDODataObject;
import org.eclipse.persistence.sdo.SDOProperty;
import org.eclipse.persistence.sdo.SDOType;
import org.eclipse.persistence.sdo.helper.DefaultSchemaLocationResolver;
import org.eclipse.persistence.sdo.helper.SDOHelperContext;
import org.eclipse.persistence.sdo.helper.SDOXSDHelper;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import commonj.sdo.helper.DataFactory;
import commonj.sdo.helper.HelperContext;
import commonj.sdo.helper.TypeHelper;
import commonj.sdo.helper.XSDHelper;
import commonj.sdo.impl.HelperProvider;

public class SDOTypeHelperAppInfoTestCases extends junit.framework.TestCase  {
    private boolean customContext;
    protected DocumentBuilderFactory dbf;
    protected Document doc;
    protected HelperContext aHelperContext;
    protected XSDHelper xsdHelper;
    protected DataFactory dataFactory;
    protected TypeHelper typeHelper;
    protected Element aiElement;
    protected Element aiElementProp;
    protected SDOType sdoTypeType;
    private static final String CUSTOM_CTX = "customContext";
    private static final String APP_INFO = "xsd:appinfo";
    private static final String NAME = "name";
    private static final String URI = "uri";
    private static final String TYPE = "type";
    private static final String ATT = "attribute";
    private static final String TYPENO = "Typeno";
    private static final String PROPNO = "Propno";
    private static final String XMLNS = "xmlns";
    private static final String KEY = "key";
    private static final String PROPERTY = "property";
    private static final String MYDO = "myDO";
    private static final String MYPROP = "myProperty";
    private static final String MYURI = "myUri";
    private static final String TYPE_APP_INFO = "http://xmlns.oracle.com/adf/svc/metadata/type";
    private static final String PROPERTY_APP_INFO = "http://xmlns.oracle.com/adf/svc/metadata/property";
    private static final String TYPE_APP_INFO_STRING = "<xsd:appinfo source=\"http://xmlns.oracle.com/adf/svc/metadata/type\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><key xmlns=\"http://xmlns.oracle.com/adf/svc/metadata/type\"><attribute>Typeno</attribute></key></xsd:appinfo>";
    private static final String PROPERTY_APP_INFO_STRING = "<xsd:appinfo source=\"http://xmlns.oracle.com/adf/svc/metadata/property\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><key xmlns=\"http://xmlns.oracle.com/adf/svc/metadata/property\"><attribute>Propno</attribute></key></xsd:appinfo>";

    public SDOTypeHelperAppInfoTestCases(String name) {
        super(name);
        customContext = Boolean.getBoolean(CUSTOM_CTX);
    }

    public static void main(String[] args) {
        String[] arguments = { "-c", "org.eclipse.persistence.testing.sdo.helper.typehelper.SDOTypeHelperAppInfoTestCases" };
        TestRunner.main(arguments);
    }

    @Override
    public void setUp() {
        HelperContext aHelperContext;
        if (customContext) {
            // default to instance of a HelperContext
            aHelperContext = new SDOHelperContext();
        } else {
            // default to static context (Global)
            aHelperContext = HelperProvider.getDefaultContext();
        }
        typeHelper = aHelperContext.getTypeHelper();
        dbf = DocumentBuilderFactory.newInstance();
        try {
            doc = dbf.newDocumentBuilder().newDocument();
        } catch (ParserConfigurationException e) {
            fail("setUp failed: \n" + e.getMessage());
        }
        xsdHelper = aHelperContext.getXSDHelper();
        typeHelper = aHelperContext.getTypeHelper();
        dataFactory = aHelperContext.getDataFactory();

        // setup AppInfoElement for Type:
        // <xsd:appinfo source="http://xmlns.oracle.com/adf/svc/metadata/type">
        //   <key xmlns="http://xmlns.oracle.com/adf/svc/metadata/type">
        //     <attribute>Typeno</attribute>
        //   </key>
        // </xsd:appinfo>
        Element attElement = doc.createElementNS(TYPE_APP_INFO, ATT);
        attElement.appendChild(doc.createTextNode(TYPENO));
        Element keyElement = doc.createElementNS(TYPE_APP_INFO, KEY);
        keyElement.setAttribute(XMLNS, TYPE_APP_INFO);
        keyElement.appendChild(attElement);
        aiElement = doc.createElementNS(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI, APP_INFO);
        aiElement.setAttribute(SDOConstants.APPINFO_SOURCE_ATTRIBUTE, TYPE_APP_INFO);
        aiElement.appendChild(keyElement);

        // setup AppInfoElement for Property:
        // <xsd:appinfo source="http://xmlns.oracle.com/adf/svc/metadata/property">
        //   <key xmlns="http://xmlns.oracle.com/adf/svc/metadata/property">
        //     <attribute>Propno</attribute>
        //   </key>
        // </xsd:appinfo>
        Element attElementProp = doc.createElementNS(PROPERTY_APP_INFO, ATT);
        attElementProp.appendChild(doc.createTextNode(PROPNO));
        Element keyElementProp = doc.createElementNS(PROPERTY_APP_INFO, KEY);
        keyElementProp.setAttribute(XMLNS, PROPERTY_APP_INFO);
        keyElementProp.appendChild(attElementProp);
        aiElementProp = doc.createElementNS(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI, APP_INFO);
        aiElementProp.setAttribute(SDOConstants.APPINFO_SOURCE_ATTRIBUTE, PROPERTY_APP_INFO);
        aiElementProp.appendChild(keyElementProp);

        sdoTypeType = (SDOType) typeHelper.getType(SDOConstants.SDO_URL, SDOConstants.TYPE);
    }

    /**
     * Tests setting appinfo elements on a Type and Property via
     * dataObject.set(Property, Object) API.
     *
     * Positive test.
     */
    public void testAppInfoElements() {
        List<Element> aieList = new ArrayList<Element>();
        aieList.add(aiElement);
        List<Element> aiePropList = new ArrayList<Element>();
        aiePropList.add(aiElementProp);

        // create the data object
        SDODataObject dataObject = (SDODataObject) dataFactory.create(sdoTypeType);
        dataObject.set(NAME, MYDO);
        dataObject.set(URI, MYURI);
        dataObject.set(SDOConstants.APPINFO_PROPERTY, aieList);

        // create a property
        SDODataObject prop = (SDODataObject) dataObject.createDataObject(PROPERTY);
        prop.set(NAME, MYPROP);
        prop.set(TYPE, SDOConstants.SDO_STRING);
        prop.set(SDOConstants.APPINFO_PROPERTY, aiePropList);

        // create the type
        SDOType newType = (SDOType) typeHelper.define(dataObject);

        //======
        //DefaultSchemaLocationResolver resolver = new DefaultSchemaLocationResolver(new HashMap<QName, String>());
        //List<Object> types = new ArrayList<Object>();
        //types.add(newType);
        //String generatedSchema = ((SDOXSDHelper)xsdHelper).generate(types, resolver);
        //System.out.println(generatedSchema);
        //======

        // validate that AppInfoElements were handled correctly on Type and Property
        // Type
        assertNotNull("Type [newType] is null", newType);
        assertTrue("Type does not have AppInfoElements set as expected", newType.getAppInfoElements() != null);
        assertTrue("Expected AppInfoElements list of size [1] on Type, but was [" + newType.getAppInfoElements().size() + "]", newType.getAppInfoElements().size() == 1);
        String val = ((Element)newType.getAppInfoElements().get(0)).getAttribute(SDOConstants.APPINFO_SOURCE_ATTRIBUTE);
        assertNotNull("AppInfoElement source on Type is empty/null", val != null && val.length() > 0);
        assertTrue("Expected AppInfoElement source ["+TYPE_APP_INFO+"] on Type but was [" + val + "]", val.equals(TYPE_APP_INFO));
        String appInfoString = xsdHelper.getAppinfo(newType, TYPE_APP_INFO);
        assertEquals("Expected getAppInfo() to return ["+TYPE_APP_INFO_STRING+"] but was ["+appInfoString+"]", TYPE_APP_INFO_STRING, appInfoString);
        // Property
        SDOProperty myProp = newType.getProperty(MYPROP);
        assertNotNull("Property [myProperty] is null", myProp);
        assertTrue("Property does not have AppInfoElements set as expected", myProp.getAppInfoElements() != null);
        assertTrue("Expected AppInfoElements list of size [1] on Property, but was [" + myProp.getAppInfoElements().size() + "]", myProp.getAppInfoElements().size() == 1);
        val = ((Element)myProp.getAppInfoElements().get(0)).getAttribute(SDOConstants.APPINFO_SOURCE_ATTRIBUTE);
        assertNotNull("AppInfoElement source on Property is empty/null", val != null && val.length() > 0);
        assertTrue("Expected AppInfoElement source ["+PROPERTY_APP_INFO+"] on Property but was [" + val + "]", val.equals(PROPERTY_APP_INFO));
        appInfoString = xsdHelper.getAppinfo(myProp, PROPERTY_APP_INFO);
        assertEquals("Expected getAppInfo() to return ["+PROPERTY_APP_INFO_STRING+"] but was ["+appInfoString+"]", PROPERTY_APP_INFO_STRING, appInfoString);
    }

    /**
     * Test error handling by setting a single Element as opposed to the
     * expected List<Element>.
     *
     * Negative test.
     */
    public void testSingleAppInfoElement() {
        // create the data object
        SDODataObject dataObject = (SDODataObject) dataFactory.create(sdoTypeType);
        dataObject.set(NAME, MYDO);
        dataObject.set(URI, MYURI);

        // the following should cause an IllegalArgumentException
        try {
            dataObject.set(SDOConstants.APPINFO_PROPERTY, aiElement);
        } catch (IllegalArgumentException iaex) {
            // success
        } catch (Exception x) {
            fail("An unexpected exception occurred: \n" + x.getMessage());
        }
    }
}
