/*
 * 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.XMLUnmarshaller;
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.oxm.OXMXMLComparer;
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 OXMXMLComparer 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 OXMXMLComparer();
    }

    /**
     * Login the session to ensure that the descriptors are initialized.
     *
     */
    protected void loginProject(Project prj) {
        XMLPlatform<XMLUnmarshaller> 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);
            }
        }
    }
}
