<commit_before>/**
 * Copyright (C) 2010 Orbeon, Inc.
 *
 * This program is free software; you can redistribute it and/or modify it under the terms of the
 * GNU Lesser General Public License as published by the Free Software Foundation; either version
 * 2.1 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Lesser General Public License for more details.
 *
 * The full text of the license is available at http://www.gnu.org/copyleft/lesser.html
 */
package org.orbeon.oxf.processor.sql.interpreters;

import org.dom4j.Node;
import org.jaxen.UnresolvableException;
import org.jaxen.VariableContext;
import org.orbeon.oxf.common.OXFException;
import org.orbeon.oxf.common.ValidationException;
import org.orbeon.oxf.processor.sql.SQLProcessor;
import org.orbeon.oxf.processor.sql.SQLProcessorInterpreterContext;
import org.orbeon.oxf.util.PooledXPathExpression;
import org.orbeon.oxf.util.XPathCache;
import org.orbeon.oxf.xml.XMLUtils;
import org.orbeon.oxf.xml.XPathUtils;
import org.orbeon.oxf.xml.dom4j.LocationData;
import org.orbeon.oxf.xml.dom4j.LocationSAXWriter;
import org.orbeon.saxon.dom4j.DocumentWrapper;
import org.orbeon.saxon.trans.XPathException;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.NamespaceSupport;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 *
 */
public class ValueOfCopyOfInterpreter extends SQLProcessor.InterpreterContentHandler {
    final DocumentWrapper wrapper;

    public ValueOfCopyOfInterpreter(SQLProcessorInterpreterContext interpreterContext) {
        super(interpreterContext, false);
        this.wrapper = new DocumentWrapper(interpreterContext.getCurrentNode().getDocument(), null, XPathCache.getGlobalConfiguration());
    }

    public void start(String uri, String localname, String qName, Attributes attributes) throws SAXException {
        final SQLProcessorInterpreterContext interpreterContext = getInterpreterContext();
        NamespaceSupport namespaceSupport = interpreterContext.getNamespaceSupport();
        ContentHandler output = interpreterContext.getOutput();

        namespaceSupport.pushContext();
        try {
            String selectString = attributes.getValue("select");

            // Variable context (obsolete)
            VariableContext variableContext = new VariableContext() {
                public Object getVariableValue(String namespaceURI, String prefix, String localName) throws UnresolvableException {
                    if (!SQLProcessor.SQL_NAMESPACE_URI.equals(namespaceURI))
                        throw new UnresolvableException("Unbound variable: {" + namespaceURI + "}" + localName);
                    if ("row-position".equals(localName)) {
                        return new Integer(interpreterContext.getRowPosition());
                    } else
                        throw new UnresolvableException("Unbound variable: {" + namespaceURI + "}" + localName);
                }
            };

            // Interpret expression
            Object result = XPathUtils.selectObjectValue(interpreterContext.getCurrentNode(), selectString,
                    interpreterContext.getPrefixesMap(), variableContext, interpreterContext.getFunctionContext());

            if ("value-of".equals(localname) || "copy-of".equals(localname)) {
                // Case of Number and String
                if (result instanceof Number) {
                    String stringValue;
                    if (result instanceof Float || result instanceof Double) {
                        stringValue = XMLUtils.removeScientificNotation(((Number) result).doubleValue());
                    } else {
                        stringValue = Long.toString(((Number) result).longValue());
                    } // FIXME: what about BigDecimal and BigInteger: can they be returned?
                    output.characters(stringValue.toCharArray(), 0, stringValue.length());
                } else if (result instanceof String) {
                    String stringValue = (String) result;
                    output.characters(stringValue.toCharArray(), 0, stringValue.length());
                } else if (result instanceof List) {
                    final List listResult = (List) result;
                    if ("value-of".equals(localname)) {
                        // Get string value
<commit_msg>Fix #349 SQL Processor: NPE in ValueOfCopyOfInterpreter<commit_after>/**
 * Copyright (C) 2010 Orbeon, Inc.
 *
 * This program is free software; you can redistribute it and/or modify it under the terms of the
 * GNU Lesser General Public License as published by the Free Software Foundation; either version
 * 2.1 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Lesser General Public License for more details.
 *
 * The full text of the license is available at http://www.gnu.org/copyleft/lesser.html
 */
package org.orbeon.oxf.processor.sql.interpreters;

import org.dom4j.Node;
import org.jaxen.UnresolvableException;
import org.jaxen.VariableContext;
import org.orbeon.oxf.common.OXFException;
import org.orbeon.oxf.common.ValidationException;
import org.orbeon.oxf.processor.sql.SQLProcessor;
import org.orbeon.oxf.processor.sql.SQLProcessorInterpreterContext;
import org.orbeon.oxf.util.PooledXPathExpression;
import org.orbeon.oxf.util.XPathCache;
import org.orbeon.oxf.xml.XMLUtils;
import org.orbeon.oxf.xml.XPathUtils;
import org.orbeon.oxf.xml.dom4j.LocationData;
import org.orbeon.oxf.xml.dom4j.LocationSAXWriter;
import org.orbeon.saxon.dom4j.DocumentWrapper;
import org.orbeon.saxon.trans.XPathException;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.NamespaceSupport;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 *
 */
public class ValueOfCopyOfInterpreter extends SQLProcessor.InterpreterContentHandler {
    DocumentWrapper wrapper = null;

    public ValueOfCopyOfInterpreter(SQLProcessorInterpreterContext interpreterContext) {
        super(interpreterContext, false);
    }

    public void start(String uri, String localname, String qName, Attributes attributes) throws SAXException {
        final SQLProcessorInterpreterContext interpreterContext = getInterpreterContext();
        NamespaceSupport namespaceSupport = interpreterContext.getNamespaceSupport();
        ContentHandler output = interpreterContext.getOutput();

        namespaceSupport.pushContext();
        try {
            String selectString = attributes.getValue("select");

            // Variable context (obsolete)
            VariableContext variableContext = new VariableContext() {
                public Object getVariableValue(String namespaceURI, String prefix, String localName) throws UnresolvableException {
                    if (!SQLProcessor.SQL_NAMESPACE_URI.equals(namespaceURI))
                        throw new UnresolvableException("Unbound variable: {" + namespaceURI + "}" + localName);
                    if ("row-position".equals(localName)) {
                        return new Integer(interpreterContext.getRowPosition());
                    } else
                        throw new UnresolvableException("Unbound variable: {" + namespaceURI + "}" + localName);
                }
            };

            // Interpret expression
            Object result = XPathUtils.selectObjectValue(interpreterContext.getCurrentNode(), selectString,
                    interpreterContext.getPrefixesMap(), variableContext, interpreterContext.getFunctionContext());
            if (wrapper == null)
                wrapper = new DocumentWrapper(interpreterContext.getCurrentNode().getDocument(), null, XPathCache.getGlobalConfiguration());

            if ("value-of".equals(localname) || "copy-of".equals(localname)) {
                // Case of Number and String
                if (result instanceof Number) {
                    String stringValue;
                    if (result instanceof Float || result instanceof Double) {
                        stringValue = XMLUtils.removeScientificNotation(((Number) result).doubleValue());
                    } else {
                        stringValue = Long.toString(((Number) result).longValue());
                    } // FIXME: what about BigDecimal and BigInteger: can they be returned?
                    output.characters(stringValue.toCharArray(), 0, stringValue.length());
                } else if (result instanceof String) {
                    String stringValue = (String) result;
                    output.characters(stringValue.toCharArray(), 0, stringValue.length());
                } else if (result instanceof List) {
                    final List listResult = (List) result;
                    if ("value-of".equals(localname)) {
                        // Get string value

{'fraction_non_alphanumeric': 0.08851648941884198, 'fraction_numerical': 0.0029004189494038026, 'mean_word_length': 2.8646741386467416, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 16}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4233562', 'n_tokens_mistral': 2388, 'n_tokens_neox': 2313, 'n_words': 613}