/*
 * 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:
// dmccann - Mar 2/2009 - 2.0 - Initial implementation
package org.eclipse.persistence.testing.oxm.schemamodelgenerator;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.Iterator;
import java.util.Vector;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.internal.oxm.Namespace;
import org.eclipse.persistence.internal.oxm.XMLConversionManager;
import org.eclipse.persistence.internal.oxm.schema.SchemaModelGenerator;
import org.eclipse.persistence.internal.oxm.schema.SchemaModelProject;
import org.eclipse.persistence.internal.oxm.schema.model.Schema;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.oxm.XMLContext;
import org.eclipse.persistence.oxm.XMLDescriptor;
import org.eclipse.persistence.oxm.XMLLogin;
import org.eclipse.persistence.oxm.XMLMarshaller;
import org.eclipse.persistence.oxm.platform.SAXPlatform;
import org.eclipse.persistence.oxm.platform.XMLPlatform;
import org.eclipse.persistence.sessions.DatabaseSession;
import org.eclipse.persistence.sessions.Project;
import org.eclipse.persistence.testing.jaxb.JAXBXMLComparer;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import junit.framework.TestCase;

/**
 * Parent class for the schema model generation test cases.
 *
 */
public class GenerateSchemaTestCases extends TestCase {
    protected SchemaModelGenerator sg;
    protected DocumentBuilder parser;
    protected JAXBXMLComparer comparer;
    protected static final String TMP_DIR = System.getenv("T_WORK") == null
            ? System.getProperty("java.io.tmpdir") : System.getenv("T_WORK");

    public GenerateSchemaTestCases(String name) throws Exception {
        super(name);
        sg = new SchemaModelGenerator(XMLConversionManager.getDefaultXMLManager());
        DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
        builderFactory.setIgnoringElementContentWhitespace(true);
        builderFactory.setNamespaceAware(true);
        parser = builderFactory.newDocumentBuilder();
        comparer = new JAXBXMLComparer();
    }

    /**
     * Login the session to ensure that the descriptors are initialized.
     *
     */
    protected void loginProject(Project prj) {
        XMLPlatform platform = new SAXPlatform();
        prj.setLogin(new XMLLogin(platform));
        DatabaseSession session = prj.createDatabaseSession();
        session.setLogLevel(SessionLog.OFF);
        for (Iterator<ClassDescriptor> descriptorIt = prj.getOrderedDescriptors().iterator(); descriptorIt.hasNext();) {
            ClassDescriptor descriptor = descriptorIt.next();
            if (descriptor.getJavaClass() == null) {
                descriptor.setJavaClass(session.getDatasourcePlatform().getConversionManager().convertClassNameToClass(descriptor.getJavaClassName()));
            }
        }
        session.login();
    }

    /**
     * Write the given schema to the T_WORK folder.
     *
     */
    protected void writeSchema(Schema generatedSchema) {
        try {
            Project p = new SchemaModelProject();
            Vector namespaces = generatedSchema.getNamespaceResolver().getNamespaces();
            for (int i = 0; i < namespaces.size(); i++) {
                Namespace next = (Namespace)namespaces.get(i);
                ((XMLDescriptor) p.getDescriptor(Schema.class)).getNamespaceResolver().put(next.getPrefix(), next.getNamespaceURI());
            }
            XMLContext context = new XMLContext(p);
            XMLMarshaller marshaller = context.createMarshaller();
            FileWriter generatedSchemaWriter = new FileWriter(new File(TMP_DIR, "generatedSchema.xsd"));
            marshaller.marshal(generatedSchema, generatedSchemaWriter);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /**
     * For debugging - write the given schema to System out.
     *
     */
    protected void outputSchema(Schema generatedSchema){
        Project p = new SchemaModelProject();
        Vector namespaces = generatedSchema.getNamespaceResolver().getNamespaces();
        for (int i = 0; i < namespaces.size(); i++) {
            Namespace next = (Namespace)namespaces.get(i);
            ((XMLDescriptor)p.getDescriptor(Schema.class)).getNamespaceResolver().put(next.getPrefix(), next.getNamespaceURI());
        }
        XMLContext context = new XMLContext(p);
        XMLMarshaller marshaller = context.createMarshaller();
        StringWriter generatedSchemaWriter = new StringWriter();
        marshaller.marshal(generatedSchema, generatedSchemaWriter);
        System.out.println(generatedSchemaWriter.toString());
    }

    /**
     * Compares a schema model Schema (as a string) against a string representation
     * of an XML schema.
     *
     */
    protected boolean compareSchemaStrings(Schema generatedSchema, String controlSchema){
        Project p = new SchemaModelProject();
        Vector namespaces = generatedSchema.getNamespaceResolver().getNamespaces();
        for (int i = 0; i < namespaces.size(); i++) {
            Namespace next = (Namespace)namespaces.get(i);
            ((XMLDescriptor) p.getDescriptor(Schema.class)).getNamespaceResolver().put(next.getPrefix(), next.getNamespaceURI());
        }
        XMLContext context = new XMLContext(p);
        XMLMarshaller marshaller = context.createMarshaller();
        StringWriter generatedSchemaWriter = new StringWriter();
        marshaller.marshal(generatedSchema, generatedSchemaWriter);
        return generatedSchemaWriter.toString().equals(controlSchema);
    }

    /**
     * Utility for reading in an XML schema file and returning it as a string.
     *
     */
    protected String getSchemaAsString(BufferedReader reader, int available) {
        StringBuffer sb = new StringBuffer(available);
        try {
            char[] chars = new char[available];
            int numRead = 0;
            while( (numRead = reader.read(chars)) > -1){
                sb.append(String.valueOf(chars));
            }
            reader.close();
        } catch (Exception x) {
            x.printStackTrace();
        }
        return sb.toString();
    }

    /**
     * Return a Document for a given XML Schema.
     *
     * @param xsdResource indicates the .xsd file to be parsed into a Document
     * @see Document
     */
    protected Document getDocument(String xsdResource) {
        Document document = null;
        try {
            InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(xsdResource);
            document = parser.parse(inputStream);
            removeEmptyTextNodes(document);
            inputStream.close();
        } catch (Exception x) {
            x.printStackTrace();
        }
        return document;
    }

    /**
     * Return a Document for a given EclipseLink schema model Schema.
     *
     * @see Document
     */
    protected Document getDocument(Schema schema) {
        Document document = parser.newDocument();

        Project p = new SchemaModelProject();
        for (Iterator<Namespace> nameIt = schema.getNamespaceResolver().getNamespaces().iterator(); nameIt.hasNext(); ) {
            Namespace next = nameIt.next();
            ((XMLDescriptor) p.getDescriptor(Schema.class)).getNamespaceResolver().put(next.getPrefix(), next.getNamespaceURI());
        }

        XMLContext context = new XMLContext(p);
        XMLMarshaller marshaller = context.createMarshaller();
        marshaller.marshal(schema, document);

        return document;
    }

    /**
     * Removes any empty child text nodes.
     *
     */
    protected void removeEmptyTextNodes(Node node) {
        NodeList nodeList = node.getChildNodes();
        Node childNode;
        for (int x = nodeList.getLength() - 1; x >= 0; x--) {
            childNode = nodeList.item(x);
            if (childNode.getNodeType() == Node.TEXT_NODE) {
                if (childNode.getNodeValue().trim().equals("")) {
                    node.removeChild(childNode);
                }
            } else if (childNode.getNodeType() == Node.ELEMENT_NODE) {
                removeEmptyTextNodes(childNode);
            }
        }
    }
}
