/*
 * 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:
//     Oracle - initial API and implementation from Oracle TopLink

package org.eclipse.persistence.internal.xr;

// Javase imports
import static org.eclipse.persistence.internal.helper.ClassConstants.STRING;
import static org.eclipse.persistence.internal.oxm.Constants.BASE_64_BINARY_QNAME;
import static org.eclipse.persistence.internal.oxm.Constants.DATE_QNAME;
import static org.eclipse.persistence.internal.oxm.Constants.DATE_TIME_QNAME;
import static org.eclipse.persistence.internal.oxm.Constants.INT_QNAME;
import static org.eclipse.persistence.internal.oxm.Constants.TIME_QNAME;
import static org.eclipse.persistence.internal.xr.Util.DEFAULT_ATTACHMENT_MIMETYPE;
import static org.eclipse.persistence.internal.xr.Util.EMPTY_STR;
import static org.eclipse.persistence.internal.xr.Util.SLASH_CHAR;
import static org.eclipse.persistence.internal.xr.Util.SXF_QNAME;
import static org.eclipse.persistence.internal.xr.Util.TEMP_DOC;
import static org.eclipse.persistence.internal.xr.Util.sqlToXmlName;
import static org.eclipse.persistence.internal.xr.sxf.SimpleXMLFormat.DEFAULT_SIMPLE_XML_FORMAT_TAG;
import static org.eclipse.persistence.internal.xr.sxf.SimpleXMLFormat.DEFAULT_SIMPLE_XML_TAG;
import static org.eclipse.persistence.oxm.XMLConstants.SCHEMA_INSTANCE_URL;
import static org.eclipse.persistence.oxm.XMLConstants.SCHEMA_URL;
import static org.eclipse.persistence.oxm.XMLConstants.XMLNS_URL;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.sql.Blob;
import java.sql.Date;
import java.sql.SQLException;
import java.sql.SQLXML;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Vector;

// Java extension imports
import jakarta.activation.DataHandler;
import javax.xml.namespace.QName;

// EclipseLink imports
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.DBWSException;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.internal.databaseaccess.DatasourceCall;
import org.eclipse.persistence.internal.databaseaccess.OutputParameterForCallableStatement;
import org.eclipse.persistence.internal.descriptors.InstantiationPolicy;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.jpa.JPAQuery;
import org.eclipse.persistence.internal.oxm.XMLConversionManager;
import org.eclipse.persistence.internal.oxm.conversion.Base64;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedClassForName;
import org.eclipse.persistence.internal.security.PrivilegedGetConstructorFor;
import org.eclipse.persistence.internal.security.PrivilegedGetDeclaredMethod;
import org.eclipse.persistence.internal.security.PrivilegedInvokeConstructor;
import org.eclipse.persistence.internal.security.PrivilegedMethodInvoker;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.DatabaseSessionImpl;
import org.eclipse.persistence.internal.xr.sxf.SimpleXMLFormat;
import org.eclipse.persistence.internal.xr.sxf.SimpleXMLFormatModel;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.mappings.AttributeAccessor;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.structures.ObjectRelationalDatabaseField;
import org.eclipse.persistence.oxm.NamespaceResolver;
import org.eclipse.persistence.oxm.XMLDescriptor;
import org.eclipse.persistence.oxm.XMLRoot;
import org.eclipse.persistence.oxm.mappings.XMLBinaryDataMapping;
import org.eclipse.persistence.oxm.mappings.XMLDirectMapping;
import org.eclipse.persistence.oxm.mappings.XMLFragmentCollectionMapping;
import org.eclipse.persistence.oxm.schema.XMLSchemaReference;
import org.eclipse.persistence.oxm.schema.XMLSchemaURLReference;
import org.eclipse.persistence.queries.DataReadQuery;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.ReadObjectQuery;
import org.eclipse.persistence.sessions.DatabaseRecord;
import org.eclipse.persistence.sessions.Session;
import org.w3c.dom.Element;

/**
 * <p><b>INTERNAL:</b>An XR QueryOperation is an executable representation of a <code>SELECT</code>
 * operation on the database.
 *
 * @author Mike Norman - michael.norman@oracle.com
 * @since EclipseLink 1.x
 */
public class QueryOperation extends Operation {
    public static final String ORACLEOPAQUE_STR = "oracle.sql.OPAQUE";
    private static final String IORACLEOPAQUE_STR = "oracle.jdbc.OracleOpaque";
    protected static final String RESULT_STR = "result";
    protected static final String XMLTYPEFACTORY_STR = "org.eclipse.persistence.internal.platform.database.oracle.xdb.XMLTypeFactoryImpl";
    protected static final String GETSTRING_METHOD = "getString";
    protected static final String ATTACHMENT_STR = "/attachment";
    protected static final String CURSOR_OF_STR = "cursor of ";
    protected static final String DATAHANDLER_STR = "DataHandler";
    protected static final String RESULTS_STR = "results";
    protected static final String VALUEOBJECT_STR = "ValueObject";
    protected static final String VALUE_STR = "value";
    protected static final String SIMPLEXML_FORMAT_STR = "/simple-xml-format";
    protected static final String SIMPLEXML_STR = "simpleXML";
    protected static final String DATABASEQUERY_STR = "databasequery";
    protected static final String ITEMS_STR = "ITEMS";
    protected static final String XSD_STR = "xmlns:xsd";
    protected static final String XSI_STR = "xmlns:xsi";
    protected static final String XSITYPE_STR = "xsi:type";
    protected static final String BASE64_BINARY_STR = "xsd:base64Binary";

    protected Result result;
    protected QueryHandler queryHandler;
    protected boolean userDefined = true;

    public QueryOperation() {
        super();
    }

    public Result getResult() {
        return result;
    }
    public void setResult(Result result) {
        this.result = result;
    }

    public QueryHandler getQueryHandler() {
        return queryHandler;
    }
    public void setQueryHandler(QueryHandler queryHandler) {
        this.queryHandler = queryHandler;
    }

    public boolean isUserDefined() {
        return userDefined;
    }
    public void setUserDefined(boolean userDefined) {
        this.userDefined = userDefined;
    }

    @Override
    public boolean isCollection() {
        return result != null && result.isCollection();
    }

    public boolean isSimpleXMLFormat() {
        return result != null && result.getSimpleXMLFormat() != null;
    }

    public boolean isAttachment() {
        return result != null && result.getAttachment() != null;
    }

    public QName getResultType() {
        if (result != null) {
            return result.getType();
        }
        return null;
    }

    @Override
    public boolean hasResponse() {
        return result != null;
    }

    @Override
    public void validate(XRServiceAdapter xrService) {
        super.validate(xrService);
        QName resultType = result == null ? null : result.getType();
        if (resultType != null) {
            if (!resultType.getNamespaceURI().equals(SCHEMA_URL)) {
                boolean sxf = resultType.getLocalPart().equals(DEFAULT_SIMPLE_XML_FORMAT_TAG) ||
                    resultType.getLocalPart().equals(CURSOR_OF_STR + DEFAULT_SIMPLE_XML_FORMAT_TAG);
                // check descriptor for Schema's high-level element type 'resultType'
                if (!sxf && !xrService.descriptorsByQName.containsKey(resultType)) {
                        throw DBWSException.resultHasNoMapping(resultType.toString(), name);
                }
            }
        }
        if (queryHandler != null) {
            queryHandler.validate(xrService, this);
        }
    }

    // Made static final for performance reasons.
    private static final class DataHandlerInstantiationPolicy extends InstantiationPolicy {
        private final String mimeType;
        public DataHandlerInstantiationPolicy(String mimeType) {
            super();
            this.mimeType = mimeType;
        }
        @Override
        public Object buildNewInstance() throws DescriptorException {
            return new DataHandler(null, mimeType);
        }
    }

    @Override
    public void initialize(XRServiceAdapter xrService) {
        super.initialize(xrService);
        if (queryHandler == null) {
            // session query instead of named query
            DatabaseQuery dq = xrService.getORSession().getQuery(name);
            if (dq != null) {
                queryHandler = new QueryHandler(){
                    @Override
                    public void initializeDatabaseQuery(XRServiceAdapter xrService, QueryOperation queryOperation) {
                        // do nothing
                    }
                    @Override
                    public void initializeArguments(XRServiceAdapter xrService,
                        QueryOperation queryOperation, DatabaseQuery databaseQuery) {
                        // do nothing
                    }
                    @Override
                    public void initializeCall(XRServiceAdapter xrService,
                        QueryOperation queryOperation, DatabaseQuery databaseQuery) {
                        // do nothing
                    }
                };
                queryHandler.setDatabaseQuery(dq);
            }
        }
        if (queryHandler == null) {
            throw DBWSException.couldNotLocateQueryForSession(name,
                xrService.getORSession().getName());
        }
        queryHandler.initialize(xrService, this);
        Session oxSession = xrService.getOXSession();
        QName resultType = result == null ? null : result.getType();
        addSimpleXMLFormatModelDescriptor(xrService);
        addValueObjectDescriptor(xrService);
        if (resultType == null) {
            if (isAttachment()) {
                Attachment attachment = result.getAttachment();
                XMLDescriptor descriptor =
                    (XMLDescriptor)oxSession.getProject().getClassDescriptor(DataHandler.class);
                if (descriptor == null) {
                    descriptor = new XMLDescriptor();
                    descriptor.setAlias(DATAHANDLER_STR);
                    descriptor.setJavaClass(DataHandler.class);
                    descriptor.setInstantiationPolicy(new DataHandlerInstantiationPolicy(attachment.getMimeType()));
                    XMLBinaryDataMapping mapping = new XMLBinaryDataMapping();
                    mapping.setAttributeName(RESULTS_STR);
                    mapping.setAttributeAccessor(new AttributeAccessor() {
                        @Override
                        public Object getAttributeValueFromObject(Object object)
                            throws DescriptorException {
                            Object result = null;
                            DataHandler dataHandler = (DataHandler)object;
                            try {
                                result = dataHandler.getContent();
                                if (result instanceof InputStream) {
                                    try (InputStream is = (InputStream) result) {
                                        byte[] buf = new byte[2048];
                                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
                                        int bytesRead = is.read(buf);
                                        while (bytesRead >= 0) {
                                            baos.write(buf, 0, bytesRead);
                                            bytesRead = is.read(buf);
                                        }
                                        result = baos.toByteArray();
                                    }
                                }
                            } catch (IOException e) {
                                // ignore
                            }
                            return result;
                        }
                        @Override
                        public void setAttributeValueInObject(Object object, Object value)
                            throws DescriptorException {
                        }
                    });
                    mapping.setXPath(DEFAULT_SIMPLE_XML_FORMAT_TAG + SLASH_CHAR +
                        DEFAULT_SIMPLE_XML_TAG + ATTACHMENT_STR);
                    mapping.setSwaRef(true);
                    mapping.setShouldInlineBinaryData(false);
                    mapping.setMimeType(attachment.getMimeType());
                    descriptor.addMapping(mapping);
                    NamespaceResolver nr = new NamespaceResolver();
                    descriptor.setNamespaceResolver(nr);
                    oxSession.getProject().addDescriptor(descriptor);
                    ((DatabaseSessionImpl)oxSession)
                        .initializeDescriptorIfSessionAlive(descriptor);
                    xrService.getXMLContext().storeXMLDescriptorByQName(descriptor);
                }
            }
        }
    }

    protected void addValueObjectDescriptor(XRServiceAdapter xrService) {
        Session oxSession = xrService.getOXSession();
        XMLDescriptor descriptor = (XMLDescriptor)oxSession.getProject().getClassDescriptor(
            ValueObject.class);
        if (descriptor == null) {
            descriptor = new XMLDescriptor();
            descriptor.setAlias(VALUEOBJECT_STR);
            descriptor.setJavaClass(ValueObject.class);
            XMLDirectMapping mapping = new XMLDirectMapping();
            mapping.setAttributeName(VALUE_STR);
            mapping.setXPath(VALUE_STR);
            descriptor.addMapping(mapping);
            NamespaceResolver nr = new NamespaceResolver();
            descriptor.setNamespaceResolver(nr);
            oxSession.getProject().addDescriptor(descriptor);
            ((DatabaseSessionImpl)oxSession)
                .initializeDescriptorIfSessionAlive(descriptor);
            xrService.getXMLContext().storeXMLDescriptorByQName(descriptor);
        }
    }

    protected void addSimpleXMLFormatModelDescriptor(XRServiceAdapter xrService) {
        if (isSimpleXMLFormat()) {
            Session oxSession = xrService.getOXSession();
            XMLDescriptor simpleXMLFormatDescriptor = (XMLDescriptor)oxSession.
                getProject().getClassDescriptor(SimpleXMLFormatModel.class);
            if (simpleXMLFormatDescriptor == null) {
                simpleXMLFormatDescriptor = new XMLDescriptor();
                simpleXMLFormatDescriptor.setJavaClass(SimpleXMLFormatModel.class);
                simpleXMLFormatDescriptor.setAlias(DEFAULT_SIMPLE_XML_FORMAT_TAG);
                simpleXMLFormatDescriptor.setDefaultRootElement(DEFAULT_SIMPLE_XML_FORMAT_TAG);
                XMLFragmentCollectionMapping xmlTag = new XMLFragmentCollectionMapping();
                xmlTag.setAttributeName(SIMPLEXML_STR);
                xmlTag.setXPath(DEFAULT_SIMPLE_XML_TAG);
                simpleXMLFormatDescriptor.addMapping(xmlTag);
                NamespaceResolver nr = new NamespaceResolver();
                simpleXMLFormatDescriptor.setNamespaceResolver(nr);
                XMLSchemaURLReference schemaReference = new XMLSchemaURLReference(EMPTY_STR);
                schemaReference.setSchemaContext(SIMPLEXML_FORMAT_STR);
                schemaReference.setType(XMLSchemaReference.COMPLEX_TYPE);
                simpleXMLFormatDescriptor.setSchemaReference(schemaReference);
                oxSession.getProject().addDescriptor(simpleXMLFormatDescriptor);
                ((DatabaseSessionImpl)oxSession)
                    .initializeDescriptorIfSessionAlive(simpleXMLFormatDescriptor);
                xrService.getXMLContext().storeXMLDescriptorByQName(simpleXMLFormatDescriptor);
            }
        }
    }

    /**
     * Execute <code>SELECT</code> operation on the database
     * @param   xrService parent <code>XRService</code> that owns this <code>Operation</code>
     * @param   invocation contains runtime argument values to be bound to the list of
     *          {@link Parameter}'s.
     * @return  result - the result of the underlying <code>SELECT</code> operation on
     *          the database, or <code>null</code>.
     *
     * @see  Operation
     */
    @Override
    @SuppressWarnings({"unchecked"})
    public Object invoke(XRServiceAdapter xrService, Invocation invocation) {
        DatabaseQuery query = queryHandler.getDatabaseQuery();

        if (query.getProperty(DATABASEQUERY_STR) != null) {
            query = (DatabaseQuery) query.getProperty(DATABASEQUERY_STR);
        }

        // a named query created via ORM metadata processing does not have
        // parameters set, however, the operation should
        List<Object> argVals = new ArrayList<>();
        if (query.getArguments().size() == 0) {
            int idx = 0;
            for (Parameter param : getParameters()) {
                // for custom SQL query (as configured via ORM metadata
                // processing) we add args by position
                query.addArgument(Integer.toString(++idx), Util.SCHEMA_2_CLASS.get(param.getType()));
                argVals.add(invocation.getParameter(param.getName()));
            }
        } else {
            // need to set argument values
            for (Parameter param : getParameters()) {
                argVals.add(invocation.getParameter(param.getName()));
            }
        }
        // for SimpleXML + DataReadQuery we need to set MAP result type
        if (isSimpleXMLFormat() && query.isDataReadQuery()) {
            ((DataReadQuery) query).setResultType(DataReadQuery.MAP);
        }

        // now execute the query
        Object value = xrService.getORSession().getActiveSession().executeQuery(query, argVals);

        if (value != null) {
            // a recent change in core results in an empty vector being returned in cases
            // where before we'd expect an int value (typically 1) - need to handle this
            if (result != null && (result.getType() == INT_QNAME || result.getType().equals(SXF_QNAME))) {
                if (value instanceof ArrayList && ((ArrayList<?>) value).isEmpty()) {
                    ((ArrayList<Integer>) value).add(1);
                } else  if (value instanceof Vector && ((Vector<?>) value).isEmpty()) {
                    ((Vector<Integer>) value).add(1);
                }
            }

            // JPA spec returns an ArrayList<Object[]> for stored procedure queries - will need to unwrap.
            // Note that for legacy deployment XML projects this is not the case.
            if (value instanceof ArrayList) {
                ArrayList<?> returnedList = (ArrayList<?>) value;
                if (returnedList.size() > 0 && returnedList.get(0) instanceof Object[]) {
                    Object[] objs = (Object[]) returnedList.get(0);
                    if (isCollection()) {
                        value = new ArrayList<>();
                        for (Object obj : objs) {
                            ((ArrayList<Object>) value).add(obj);
                        }
                    } else {
                        value = objs[0];
                    }
                }
            }

            // handle SimpleXML
            if (isSimpleXMLFormat()) {
                value = createSimpleXMLFormat(xrService, value);
            } else {
                if (!isCollection() && value instanceof Vector) {
                    // JPAQuery will return a single result in a Vector
                    if (((Vector<?>) value).isEmpty()) {
                        return null;
                    }
                    value = ((Vector<?>) value).firstElement();
                }

                QName resultType = getResultType();
                if (resultType != null) {
                    // handle binary content
                    if (isAttachment() || (!isCollection() && resultType.equals(BASE_64_BINARY_QNAME))) {
                        String mimeType = DEFAULT_ATTACHMENT_MIMETYPE;
                        if (isAttachment() && result.getAttachment().getMimeType() != null) {
                            mimeType = result.getAttachment().getMimeType();
                        }
                        // handle BLOB types
                        if (value instanceof Blob) {
                            value = xrService.getOXSession().
                                    getDatasourcePlatform().getConversionManager().
                                    convertObject(value, ClassConstants.APBYTE);
                        }
                        return AttachmentHelper.buildAttachmentHandler((byte[])value, mimeType);
                    }
                    if (resultType.getNamespaceURI().equals(SCHEMA_URL)) {
                        // handle primitive types
                        ValueObject vo = new ValueObject();
                        vo.value = value;
                        value = vo;
                    } else {
                        Object targetObject = value;
                        if (xrService.descriptorsByQName.containsKey(resultType)) {
                            XMLDescriptor xdesc = xrService.descriptorsByQName.get(resultType);
                            ClassDescriptor desc = xrService.getORSession().getDescriptorForAlias(xdesc.getAlias());
                            if (desc.isAggregateDescriptor() && !desc.isObjectRelationalDataTypeDescriptor() && !desc.isRelationalDescriptor()) {
                                if (isCollection()) {
                                    XRDynamicEntity_CollectionWrapper xrCollWrapper = new XRDynamicEntity_CollectionWrapper();
                                    Vector<AbstractRecord> results = (Vector<AbstractRecord>)value;
                                    for (int i = 0, len = results.size(); i < len; i++) {
                                        Object o = desc.getObjectBuilder().buildNewInstance();
                                        populateTargetObjectFromRecord(desc.getMappings(), results.get(i), o, (AbstractSession)xrService.getORSession());
                                        xrCollWrapper.add(o);
                                    }
                                    targetObject = xrCollWrapper;
                                } else {
                                    targetObject = desc.getObjectBuilder().buildNewInstance();
                                    populateTargetObjectFromRecord(desc.getMappings(), (AbstractRecord) value, targetObject, (AbstractSession)xrService.getORSession());
                                }
                            } else if (isCollection() && value instanceof Vector) {
                                // could be a collection of populated objects, in which case we just return it
                                if (((Vector<?>) value).size() > 0 && !(((Vector<?>) value).get(0) instanceof AbstractRecord)) {
                                    return value;
                                }
                                XRDynamicEntity_CollectionWrapper xrCollWrapper = new XRDynamicEntity_CollectionWrapper();
                                Vector<AbstractRecord> results = (Vector<AbstractRecord>)value;
                                for (int i = 0, len = results.size(); i < len; i++) {
                                    Object o = desc.getObjectBuilder().buildNewInstance();
                                    populateTargetObjectFromRecord(desc.getMappings(), results.get(i), o, (AbstractSession)xrService.getORSession());
                                    xrCollWrapper.add(o);
                                }
                                targetObject = xrCollWrapper;
                            } else if (value instanceof AbstractRecord) {
                                targetObject = desc.getObjectBuilder().buildNewInstance();
                                populateTargetObjectFromRecord(desc.getMappings(), (AbstractRecord) value, targetObject, (AbstractSession)xrService.getORSession());
                            }
                        }
                        if (value instanceof ArrayList) {
                            XMLDescriptor xdesc = xrService.descriptorsByQName.get(resultType);
                            ClassDescriptor desc = xrService.getORSession().getDescriptorForAlias(xdesc.getAlias());
                            targetObject = desc.getObjectBuilder().buildNewInstance();
                            Object[] objs = new Object[1];
                            objs[0] = ((ArrayList<?>)value).get(0);
                            DatabaseRecord dr = new DatabaseRecord();
                            dr.add(new DatabaseField(ITEMS_STR), objs);
                            populateTargetObjectFromRecord(desc.getMappings(), dr, targetObject, (AbstractSession)xrService.getORSession());
                        }
                        value = targetObject;
                    }
                }
            }
        }
        return value;
    }

    protected void populateTargetObjectFromRecord(Vector<DatabaseMapping> mappings,
        AbstractRecord record, Object targetObject, AbstractSession session) {
        ReadObjectQuery roq = new ReadObjectQuery();
        roq.setSession(session);
        for (DatabaseMapping dm : mappings) {
            dm.readFromRowIntoObject(record, null, targetObject, null, roq, session, true);
        }
    }

    @SuppressWarnings({"unchecked"})
    public Object createSimpleXMLFormat(XRServiceAdapter xrService, Object value) {
        XMLRoot xmlRoot = new XMLRoot();
        SimpleXMLFormat simpleXMLFormat = result.getSimpleXMLFormat();
        String tempSimpleXMLFormatTag = SimpleXMLFormat.DEFAULT_SIMPLE_XML_FORMAT_TAG;
        String simpleXMLFormatTag = simpleXMLFormat.getSimpleXMLFormatTag();
        if (simpleXMLFormatTag != null && !EMPTY_STR.equals(simpleXMLFormatTag)) {
            tempSimpleXMLFormatTag = simpleXMLFormatTag;
        }
        xmlRoot.setLocalName(tempSimpleXMLFormatTag);
        String tempXMLTag = DEFAULT_SIMPLE_XML_TAG;
        String xmlTag = simpleXMLFormat.getXMLTag();
        if (xmlTag != null && !EMPTY_STR.equals(xmlTag)) {
            tempXMLTag = xmlTag;
        }
        Vector<DatabaseRecord> records = null;
        if (value instanceof ArrayList) {
            // JPA query results in a list of raw values
            // Here we have raw values returned as opposed to DatabaseRecords - this means
            // we need to figure out the tag names based on the call's output parameters.
            // assumes JPAQuery
            JPAQuery jpaQuery = (JPAQuery) queryHandler.getDatabaseQuery();
            // to match field names with results, we need to gather the database fields from each of the Output parameters
            List<DatabaseField> paramFlds = new ArrayList<>();
            DatasourceCall dsCall = (DatasourceCall) jpaQuery.getDatabaseQuery().getDatasourceCall();
            for (Object obj : dsCall.getParameters()) {
                if (obj instanceof OutputParameterForCallableStatement) {
                    paramFlds.add(((OutputParameterForCallableStatement) obj).getOutputField());
                } else if (obj instanceof Object[]) {
                    Object[] objArray = (Object[]) obj;
                    for (int i = 0; i < objArray.length; i++) {
                        Object o = objArray[i];
                        if (o instanceof OutputParameterForCallableStatement) {
                            paramFlds.add(((OutputParameterForCallableStatement) o).getOutputField());
                        }
                    }
                }
            }
            // now create a record using DatabaseField/value pairs
            DatabaseRecord dr = new DatabaseRecord();
            if (paramFlds.size() > 0) {
                for (int i=0; i <  ((ArrayList<?>) value).size(); i++) {
                    dr.add(paramFlds.get(i), ((ArrayList<?>) value).get(i));
                }
            } else {
                dr.add(new DatabaseField(RESULT_STR), ((ArrayList<?>) value).get(0));
            }
            records = new Vector<>();
            records.add(dr);
        } else if (value instanceof Vector) {
            Class<?> vectorContent = ((Vector<?>)value).firstElement().getClass();
            if (DatabaseRecord.class.isAssignableFrom(vectorContent)) {
                records = (Vector<DatabaseRecord>)value;
            } else {
                records = new Vector<>();
                DatabaseRecord dr = new DatabaseRecord();
                dr.add(new DatabaseField(RESULT_STR), ((Vector<?>)value).firstElement());
                records.add(dr);
            }
        } else {
            records = new Vector<>();
            DatabaseRecord dr = new DatabaseRecord();
            dr.add(new DatabaseField(RESULT_STR), value);
            records.add(dr);
        }
        SimpleXMLFormatModel simpleXMLFormatModel = new SimpleXMLFormatModel();
        XMLConversionManager conversionManager =
            (XMLConversionManager) xrService.getOXSession().getDatasourcePlatform().getConversionManager();
        SessionLog log = xrService.getOXSession().getSessionLog();
        for (DatabaseRecord dr : records) {
            Element rowElement = TEMP_DOC.createElement(tempXMLTag);
            for (DatabaseField field : dr.getFields()) {
                // handle complex types, i.e. ones we have a descriptor for
                if (field instanceof ObjectRelationalDatabaseField) {
                    ObjectRelationalDatabaseField ordtField = (ObjectRelationalDatabaseField) field;
                    if (xrService.getOXSession().getDescriptor(ordtField.getType()) != null) {
                        xrService.getXMLContext().createMarshaller().marshal(dr.get(field), rowElement);
                        continue;
                    }
                }
                Object fieldValue = dr.get(field);
                if (fieldValue != null) {
                    if (fieldValue instanceof Calendar) {
                        Calendar cValue = (Calendar)fieldValue;
                        fieldValue = conversionManager.convertObject(cValue, STRING, DATE_TIME_QNAME);
                    }
                    if (fieldValue instanceof Date) {
                        Date dValue = (Date)fieldValue;
                        fieldValue = conversionManager.convertObject(dValue, STRING, DATE_QNAME);
                    } else if (fieldValue instanceof Time) {
                        Time tValue = (Time)fieldValue;
                        fieldValue = conversionManager.convertObject(tValue, STRING, TIME_QNAME);
                    } else if (fieldValue instanceof Timestamp) {
                        Timestamp tsValue = (Timestamp)fieldValue;
                        fieldValue = conversionManager.convertObject(tsValue, STRING, DATE_TIME_QNAME);
                    } else if (fieldValue instanceof Blob) {
                        fieldValue = conversionManager.convertObject(fieldValue, ClassConstants.APBYTE);
                    } else if (SQLXML.class.isAssignableFrom(fieldValue.getClass())) {
                        // handle XMLType case where an oracle.jdbc.driver.OracleSQLXML instance was returned
                        SQLXML sqlXml = (SQLXML) fieldValue;
                        try {
                            String str = sqlXml.getString();
                            sqlXml.free();
                            // Oracle 12c appends a \n character to the xml string
                            fieldValue = str.endsWith("\n") ? str.substring(0, str.length() - 1) : str;
                        } catch (SQLException e) {
                            log.logThrowable(SessionLog.FINE, SessionLog.DBWS, e);
                        }
                    } else if (fieldValue.getClass().getName().equalsIgnoreCase(ORACLEOPAQUE_STR)) {
                        // handle XMLType case where an oracle.sql.OPAQUE instance was returned
                        try {
                            Class<?> oracleOPAQUE;
                            Class<?> xmlTypeFactoryClass;
                            Constructor<?> xmlTypeFactoryConstructor;
                            Object xmlTypeFactory;
                            Method getStringMethod;
                            if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
                                oracleOPAQUE = AccessController.doPrivileged(new PrivilegedClassForName<>(IORACLEOPAQUE_STR, true, this.getClass().getClassLoader()));
                                xmlTypeFactoryClass = AccessController.doPrivileged(new PrivilegedClassForName<>(XMLTYPEFACTORY_STR, true, this.getClass().getClassLoader()));
                                xmlTypeFactoryConstructor = AccessController.doPrivileged(new PrivilegedGetConstructorFor<>(xmlTypeFactoryClass, new Class<?>[0], true));
                                xmlTypeFactory = AccessController.doPrivileged(new PrivilegedInvokeConstructor<>(xmlTypeFactoryConstructor, new Object[0]));
                                getStringMethod = AccessController.doPrivileged(new PrivilegedGetDeclaredMethod(xmlTypeFactoryClass, GETSTRING_METHOD, new Class<?>[] {oracleOPAQUE}));
                                fieldValue = AccessController.doPrivileged(new PrivilegedMethodInvoker<>(getStringMethod, xmlTypeFactory, new Object[] {fieldValue}));
                            } else {
                                oracleOPAQUE = PrivilegedAccessHelper.getClassForName(IORACLEOPAQUE_STR, false, this.getClass().getClassLoader());
                                xmlTypeFactoryClass = PrivilegedAccessHelper.getClassForName(XMLTYPEFACTORY_STR, true, this.getClass().getClassLoader());
                                xmlTypeFactoryConstructor = PrivilegedAccessHelper.getConstructorFor(xmlTypeFactoryClass, new Class<?>[0], true);
                                xmlTypeFactory = PrivilegedAccessHelper.invokeConstructor(xmlTypeFactoryConstructor, new Object[0]);
                                getStringMethod = PrivilegedAccessHelper.getDeclaredMethod(xmlTypeFactoryClass, GETSTRING_METHOD, new Class<?>[] {oracleOPAQUE});
                                fieldValue = PrivilegedAccessHelper.invokeMethod(getStringMethod, xmlTypeFactory, new Object[] {fieldValue});
                            }
                        } catch (ReflectiveOperationException | PrivilegedActionException e) {
                            // if the required resources are not available there's nothing we can do...
                            log.logThrowable(SessionLog.FINE, SessionLog.DBWS, e);
                        }
                    }

                    String elementName;
                    if (field.getName() == null || (elementName = sqlToXmlName(field.getName())).equals(EMPTY_STR)) {
                        // return arg from stored function has no name
                       elementName = RESULT_STR;
                    }
                    Element columnElement = TEMP_DOC.createElement(elementName);
                    rowElement.appendChild(columnElement);
                    String fieldValueString = fieldValue.toString();
                    // handle binary content - attachments dealt with in invoke() above
                    if (result.getType().equals(BASE_64_BINARY_QNAME)) {
                        fieldValueString = Helper.buildHexStringFromBytes(Base64.base64Encode((byte[])fieldValue));
                        columnElement.setAttributeNS(XMLNS_URL, XSD_STR, SCHEMA_URL);
                        columnElement.setAttributeNS(XMLNS_URL, XSI_STR, SCHEMA_INSTANCE_URL);
                        columnElement.setAttributeNS(SCHEMA_INSTANCE_URL, XSITYPE_STR, BASE64_BINARY_STR);
                    }
                    columnElement.appendChild(TEMP_DOC.createTextNode(fieldValueString));
                }
            }
            simpleXMLFormatModel.simpleXML.add(rowElement);
        }
        xmlRoot.setObject(simpleXMLFormatModel);
        return xmlRoot;
    }
}
