/*
 * Copyright (c) 1998, 2020 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:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.sdo.helper.delegates;

import commonj.sdo.Property;
import commonj.sdo.Type;
import commonj.sdo.helper.HelperContext;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import org.eclipse.persistence.sdo.SDOConstants;
import org.eclipse.persistence.sdo.SDOProperty;
import org.eclipse.persistence.sdo.SDOType;
import org.eclipse.persistence.sdo.helper.DefaultSchemaResolver;
import org.eclipse.persistence.sdo.helper.SDOSchemaGenerator;
import org.eclipse.persistence.sdo.helper.SDOTypesGenerator;
import org.eclipse.persistence.sdo.helper.SDOXSDHelper;
import org.eclipse.persistence.sdo.helper.SchemaLocationResolver;
import org.eclipse.persistence.sdo.helper.SchemaResolver;
import org.eclipse.persistence.exceptions.SDOException;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.oxm.NamespaceResolver;
import org.eclipse.persistence.oxm.XMLField;
import org.eclipse.persistence.oxm.record.FormattedWriterRecord;
import org.eclipse.persistence.oxm.record.WriterRecord;
import org.w3c.dom.Element;

/**
 * <p><b>Purpose</b>: Provides access to additional information when the Type or Property is defined by an XML Schema (XSD)..
 * <p><b>Responsibilities</b>:<ul>
 * <li> Define methods defines Types from an XSD.
 * <li> Generate methods an XSD from Types.
 * <li> Other Methods return null/false otherwise or if the information is unavailable.
 * </ul>
 */
public class SDOXSDHelperDelegate implements SDOXSDHelper {

    /*Map of global attributes keyed on qname*/
    private Map globalAttributes;

    /*Map of global elements keyed on qname*/
    private Map globalElements;

    // hold the context containing all helpers so that we can preserve inter-helper relationships
    private HelperContext aHelperContext;

    public SDOXSDHelperDelegate(HelperContext aContext) {
        aHelperContext = aContext;
        globalAttributes = new HashMap();
        initOpenProps();
        globalElements = new HashMap();
    }

    /**
     * Returns the local name as declared in the XSD.
     * @param type to return local name for.
     * @return the local name as declared in the XSD.
     */
    @Override
    public String getLocalName(Type type) {
        if (type == null) {
            return null;
        }
        return ((SDOType)type).getXsdLocalName();
    }

    /**
     * Returns the local name as declared in the XSD.
     * @param property to return local name for.
     * @return the local name as declared in the XSD.
     */
    @Override
    public String getLocalName(Property property) {
        if (property == null) {
            return null;
        }
        return ((SDOProperty)property).getXsdLocalName();
    }

    /**
     * Returns the namespace URI as declared in the XSD.
     * @param type to return namespace URI for.
     * @return the namespace URI as declared in the XSD.
     */
    @Override
    public String getNamespaceURI(Type type) {
        if (type == null) {
            return null;
        }
        return type.getURI();
    }

    /**
     * Returns the namespace URI as declared in the XSD.
     * @param property to return namespace URI for.
     * @return the namespace URI as declared in the XSD.
     */
    @Override
    public String getNamespaceURI(Property property) {
        if (property == null) {
            return null;
        }
        String uri = null;
        if (property.isOpenContent()) {
            uri = ((SDOProperty)property).getUri();
        } else {
            DatabaseMapping mapping = ((SDOProperty)property).getXmlMapping();
            if (mapping != null) {
                XMLField xmlField = (XMLField) mapping.getField();
                if (xmlField != null && xmlField.getXPathFragment() != null) {
                    uri = xmlField.getXPathFragment().getNamespaceURI();
                }
            }
        }
        return uri == null ? "" : uri;
    }

    /**
     * Returns true if the property is declared as an attribute in the XSD.
     * Returns false if not known or for advanced cases.
     * It is possible for both isAttribute and isElement to return false
     * but they will not both return true.
     * @param property to identify if an attribute.
     * @return true if the property is declared as an attribute in the XSD.
     */
    @Override
    public boolean isAttribute(Property property) {
        if (property == null) {
            return false;
        }
        SDOProperty sdoProperty = (SDOProperty) property;
        Object value = sdoProperty.get(SDOConstants.XMLELEMENT_PROPERTY);
        if ((value != null) && value instanceof Boolean) {
            boolean isElement = ((Boolean)value).booleanValue();
            if (isElement) {
                return false;
            }
        }

        if ((sdoProperty.getOpposite() != null) && (sdoProperty.getOpposite().isContainment())) {
            return false;
        } else if (sdoProperty.isMany() || sdoProperty.isContainment() || sdoProperty.isNullable()) {
            return false;
        }

        // Case: open content non-attribute property
        return true;
    }

    /**
     * Returns true if the property is declared as an element in the XSD.
     * Returns false if not known or for advanced cases.
     * It is possible for both isAttribute and isElement to return false
     * but they will not both return true.
     * @param property to identify if an element.
     * @return true if the property is declared as an element in the XSD.
     */
    @Override
    public boolean isElement(Property property) {
        if (property == null) {
            return false;
        }
        SDOProperty sdoProperty = (SDOProperty) property;
        Object value = sdoProperty.get(SDOConstants.XMLELEMENT_PROPERTY);
        if ((value != null) && value instanceof Boolean) {
            return ((Boolean)value).booleanValue();
        }

        if ((sdoProperty.getOpposite() != null) && (sdoProperty.getOpposite().isContainment())) {
            return false;
        } else if (sdoProperty.isMany() || sdoProperty.isContainment() || sdoProperty.isNullable()) {
            return true;
        }

        return false;
    }

    /**
     * Returns true if the Type is declared to contain mixed content.
     * A DataObject's mixed content values are typically accessed via a Sequence.
     * @param type to identify if mixed content.
     * @return true if the Type is declared to contain mixed content.
     */
    @Override
    public boolean isMixed(Type type) {
        if (type == null) {
            return false;
        }
        return type.isSequenced();
    }

    /**
     * Indicates if this helper contains XSD information for the specified type.
     * @param type the type.
     * @return true if this helper contains XSD information for the specified type.
     */
    @Override
    public boolean isXSD(Type type) {
        if (type == null) {
            return false;
        }
        return ((SDOType)type).isXsd();
    }

    /**
     * Returns the Property defined by the named global element or attribute
     *   in the targetNamespace uri, or null if not found.
     * @param uri The uri of the targetNamespace.
     * @param propertyName The name of the global property.
     * @param isElement is true for global elements, false for global attributes.
     * @return the Property defined by the named global element or attribute
     *    in the targetNamespace uri, or null if not found.
     */
    @Override
    public Property getGlobalProperty(String uri, String propertyName, boolean isElement) {
        QName qname = new QName(uri, propertyName);
        return getGlobalProperty(qname, isElement);
    }

    @Override
    public Property getGlobalProperty(QName qname, boolean isElement) {
        if (isElement) {
            return (Property)getGlobalElements().get(qname);
        } else {
            return (Property)getGlobalAttributes().get(qname);
        }
    }

    /**
     * Return the appinfo declared for this Type and source.
     * The appinfo start and end tags and content are returned.
     * The xml namespace context is preserved in the appinfo element.
     * If more than one appinfo with the same source is declared on the same
     * Type their contents are concatenated.
     * @param type the type with the appinfo declaration
     * @param source the source of the appinfo declaration.
     * @return the appinfo declared for this Type and source.
     */
    @Override
    public String getAppinfo(Type type, String source) {
        if (type == null) {
            throw SDOException.noAppInfoForNull();
        }
        if (source == null) {
            source = "";
        }
        return (String)((SDOType)type).getAppInfoMap().get(source);
    }

    /**
     * Return the content of the appinfo declared for this Property and source.
     * If the property is defined by ref= the appinfo of the referenced
     * element or attribute is included.
     * The appinfo start and end tags and content are returned.
     * The xml namespace context is preserved in the appinfo element.
     * If more than one appinfo with the same source is declared on the same
     * Type their contents are concatenated.
     * @param property the Property with the appinfo declaration
     * @param source the source of the appinfo declaration.
     * @return the appinfo declared for this Property and source.
     */
    @Override
    public String getAppinfo(Property property, String source) {
        if (property == null) {
            throw SDOException.noAppInfoForNull();
        }
        if (source == null) {
            source = "";
        }
        return (String)((SDOProperty)property).getAppInfoMap().get(source);
    }

    /**
     * Define the XML Schema as Types.
     * The Types are available through TypeHelper and DataGraph getType() methods.
     * Same as define(new StringReader(xsd), null)
     * @param xsd the XML Schema.
     * @return the defined Types.
     * @throws IllegalArgumentException if the Types could not be defined.
     */
    @Override
    public synchronized List define(String xsd) {
        StringReader reader = new StringReader(xsd);
        SchemaResolver schemaResolver = new DefaultSchemaResolver();
        return define(reader, schemaResolver);
    }

    /**
     * Define XML Schema as Types.
     * The Types are available through TypeHelper and DataGraph getType() methods.
     * @param xsdReader reader to an XML Schema.
     * @param schemaLocation the URI of the location of the schema, used
     *    for processing relative imports and includes.  May be null if not used.
     * @return the defined Types.
     * @throws IllegalArgumentException if the Types could not be defined.
     */
    @Override
    public synchronized List define(Reader xsdReader, String schemaLocation) {
        DefaultSchemaResolver schemaResolver = new DefaultSchemaResolver();
        schemaResolver.setBaseSchemaLocation(schemaLocation);

        return define(new StreamSource(xsdReader), schemaResolver);
    }

    /**
     * Define XML Schema as Types.
     * The Types are available through TypeHelper and DataGraph getType() methods.
     * @param xsdReader reader to an XML Schema.
     * @param schemaResolver the URI of the location of the schema, used
     *    for processing relative imports and includes.  May be null if not used.
     * @return the defined Types.
     * @throws IllegalArgumentException if the Types could not be defined.
     */
    public synchronized List define(Reader xsdReader, SchemaResolver schemaResolver) {
        return define(new StreamSource(xsdReader), schemaResolver);
    }

    @Override
    public synchronized List define(Source xsdSource, SchemaResolver schemaResolver) {
        return new SDOTypesGenerator(aHelperContext).define(xsdSource, schemaResolver);
    }

    /**
     * Define XML Schema as Types.
     * The Types are available through TypeHelper and DataGraph getType() methods.
     * @param xsdInputStream input stream to an XML Schema.
     * @param schemaLocation the URI of the location of the schema, used
     *    for processing relative imports and includes.  May be null if not used.
     * @return the defined Types.
     * @throws IllegalArgumentException if the Types could not be defined.
     */
    @Override
    public synchronized List define(InputStream xsdInputStream, String schemaLocation) {
        InputStreamReader xsdReader = new InputStreamReader(xsdInputStream);
        return define(xsdReader, schemaLocation);
    }

    /**
     * Generate an XML Schema Declaration (XSD) from Types.
     * Same as generate(types, null);
     * @param types a List containing the Types
     * @return a String containing the generated XSD.
     * @throws IllegalArgumentException if the XSD could not be generated.
     */
    @Override
    public String generate(List types) {
        HashMap map = null;
        return generate(types, map);
    }

    /**
     * Generate an XML Schema Declaration (XSD) from Types.
     * Round trip from SDO to XSD to SDO is supported.
     * Round trip from XSD to SDO to XSD is not supported.
     *  Use the original schema if one exists instead of generating a new one, as
     *  the generated XSD validates a different set of documents than the original XSD.
     * Generating an XSD does not affect the XSDHelper or the Types.
     * The Types must all have the same URI.
     * The result is a String containing the generated XSD.
     * All Types referenced with the same URI will be generated in the XSD
     *  and the list will be expanded to include all types generated.
     * Any Types referenced with other URIs will cause
     *  imports to be produced as appropriate.
     * Imports will include a schemaLocation if a Map is provided with an entry
     *  of the form key=import target namespace, value=schemaLocation
     * @param types a List containing the Types
     * @param namespaceToSchemaLocation map of target namespace to schema locations or null
     * @return a String containing the generated XSD.
     * @throws IllegalArgumentException if the XSD could not be generated.
     */
    @Override
    public String generate(List types, Map namespaceToSchemaLocation) {
        return new SDOSchemaGenerator(aHelperContext).generate(types, namespaceToSchemaLocation);
    }

    @Override
    public String generate(List types, SchemaLocationResolver schemaLocationResolver) {
        return new SDOSchemaGenerator(aHelperContext).generate(types, schemaLocationResolver);
    }

    /**
      * Assign a map of properties representing global attributes keyed on QName
      * @param globalAttributes  a Map of global elements keyed on QName
      */
    public void setGlobalAttributes(Map globalAttributes) {
        this.globalAttributes = globalAttributes;
    }

    /**
      * Return a map of properties representing global attributes keyed on QName
      * @return a map of global attributes keyed on QName
      */
    private Map getGlobalAttributes() {
        return globalAttributes;
    }

    private void initOpenProps() {
        getGlobalAttributes().put(SDOConstants.MIME_TYPE_QNAME, SDOConstants.MIME_TYPE_PROPERTY);
        getGlobalAttributes().put(SDOConstants.MIME_TYPE_PROPERTY_QNAME, SDOConstants.MIME_TYPE_PROPERTY_PROPERTY);

        Property xmlSchemaTypeProperty = aHelperContext.getTypeHelper().getOpenContentProperty(SDOConstants.SDO_URL, SDOConstants.XML_SCHEMA_TYPE_NAME);
        getGlobalAttributes().put(SDOConstants.SCHEMA_TYPE_QNAME, xmlSchemaTypeProperty);

        getGlobalAttributes().put(SDOConstants.JAVA_CLASS_QNAME, SDOConstants.JAVA_CLASS_PROPERTY);
        getGlobalAttributes().put(SDOConstants.XML_ELEMENT_QNAME, SDOConstants.XMLELEMENT_PROPERTY);

        Property xmlDataTypeProperty = aHelperContext.getTypeHelper().getOpenContentProperty(SDOConstants.SDOXML_URL, SDOConstants.SDOXML_DATATYPE);
        getGlobalAttributes().put(SDOConstants.XML_DATATYPE_QNAME, xmlDataTypeProperty);

        getGlobalAttributes().put(SDOConstants.XML_ID_PROPERTY_QNAME, SDOConstants.ID_PROPERTY);
        getGlobalAttributes().put(SDOConstants.DOCUMENTATION_PROPERTY_QNAME, SDOConstants.DOCUMENTATION_PROPERTY);

        getGlobalAttributes().put(SDOConstants.APPINFO_PROPERTY_QNAME, SDOConstants.APPINFO_PROPERTY);
    }

    /**
      * Assign a map of properties representing global elements keyed on QName
      * @param globalElements  a Map of global elements keyed on QName
      */
    public void setGlobalElements(Map globalElements) {
        this.globalElements = globalElements;
    }

    /**
      * Return a map of properties representing global elements keyed on QName
      * @return a map of global elements keyed on QName
      */
    private Map getGlobalElements() {
        return globalElements;
    }

    /**
      * INTERNAL:
      */
    @Override
    public Map buildAppInfoMap(List appInfoElements) {
        HashMap appInfoMap = new HashMap();

        // Build AppInfo map
        if (appInfoElements != null) {
            for (int i = 0; i < appInfoElements.size(); i++) {
                Element nextElement = (Element)appInfoElements.get(i);

                if (nextElement.getNamespaceURI().equals(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI) && nextElement.getLocalName().equals("appinfo")) {
                    String key = nextElement.getAttribute(SDOConstants.APPINFO_SOURCE_ATTRIBUTE);
                    String value = (String)appInfoMap.get(key);
                    StringWriter sw = new StringWriter();
                    WriterRecord wrec = new WriterRecord();
                    wrec.setWriter(sw);
                    wrec.node(nextElement, new NamespaceResolver());
                    wrec.flush();
                    appInfoMap.put(key, value == null ? sw.toString() : value + sw.toString());
                }
            }
        }
        return appInfoMap;
    }

    @Override
    public void reset() {
        globalAttributes = new HashMap();
        initOpenProps();
        globalElements = new HashMap();
    }

    @Override
    public HelperContext getHelperContext() {
        return aHelperContext;
    }

    @Override
    public void setHelperContext(HelperContext helperContext) {
        aHelperContext = helperContext;
    }

    public String getStringFromAppInfoElement(Element appInfo) {
        FormattedWriterRecord record = new FormattedWriterRecord();
        record.setWriter(new StringWriter());
        record.node(appInfo, new NamespaceResolver());
        return record.getWriter().toString();
    }

    /**
      * INTERNAL:
      *
      * @param qname
      * @param prop
      * @param isElement
      * Register the given property with the given qname.
      */
    @Override
    public void addGlobalProperty(QName qname, Property prop, boolean isElement) {
        ((SDOProperty)prop).setUri(qname.getNamespaceURI());
        if (isElement) {
            getGlobalElements().put(qname, prop);
        } else {
            getGlobalAttributes().put(qname, prop);
        }
    }
}
