/**
* 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.orbeon.dom.Node;
import org.orbeon.dom.saxon.DocumentWrapper;
import org.orbeon.oxf.common.OXFException;
import org.orbeon.oxf.common.ValidationException;
import org.orbeon.oxf.processor.sql.SQLFunctionLibrary;
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.XPath;
import org.orbeon.oxf.util.XPathCache;
import org.orbeon.oxf.xml.XPathUtils;
import org.orbeon.oxf.xml.dom4j.LocationData;
import org.orbeon.oxf.xml.dom4j.LocationSAXWriter;
import org.orbeon.saxon.om.Item;
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");
// Interpret expression
final Object result = XPathUtils.selectObjectValue(
interpreterContext.getCurrentNode(),
selectString,
interpreterContext.getPrefixesMap(),
SQLFunctionLibrary.instance(),
interpreterContext.getFunctionContextOrNull()
);
if (wrapper == null)
wrapper = new DocumentWrapper(interpreterContext.getCurrentNode().getDocument(), null, XPath.GlobalConfiguration());
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 = Util.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<Node> listResult = (List) result;
if ("value-of".equals(localname)) {
// Get string value
final String stringValue;
if (listResult.size() > 0) {
// Wrap all elements of the list
final List<Item> newList = new ArrayList<Item>(listResult.size());
for (Iterator<Node> i = listResult.iterator(); i.hasNext();) {
newList.add(wrapper.wrap(i.next()));
}
stringValue = XPathCache.evaluateAsString(newList, 1, "string(.)",
null, null, null, null, null, null, null);
} else {
// It's just an empty list
stringValue = "";
}
output.characters(stringValue.toCharArray(), 0, stringValue.length());
} else {
LocationSAXWriter saxw = new LocationSAXWriter();
saxw.setContentHandler(output);
for (Iterator i = ((List) result).iterator(); i.hasNext();) {
Node node = (Node) i.next();
saxw.write(node);
}
}
} else if (result instanceof Node) {
if ("value-of".equals(localname)) {
// Get string value
// TODO: use XPathCache.evaluateAsString()
PooledXPathExpression expr = XPathCache.getXPathExpression(
wrapper.getConfiguration(), wrapper.wrap((Node) result), "string(.)", null);
String stringValue = (String) expr.evaluateSingleToJavaReturnToPoolOrNull();
output.characters(stringValue.toCharArray(), 0, stringValue.length());
} else {
LocationSAXWriter saxw = new LocationSAXWriter();
saxw.setContentHandler(output);
saxw.write((Node) result);
}
} else
throw new OXFException("Unexpected XPath result type: " + result.getClass());
} else {
throw new OXFException("Invalid element: " + qName);
}
} catch (Exception e) {
throw new ValidationException(e, new LocationData(getDocumentLocator()));
}
}
public void end(String uri, String localname, String qName) throws SAXException {
getInterpreterContext().getNamespaceSupport().popContext();
}
}