com.caucho.xpath.expr.StringExpr Maven / Gradle / Ivy
/*
* Copyright (c) 1998-2018 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source 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, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
* Free SoftwareFoundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package com.caucho.xpath.expr;
import com.caucho.util.CharBuffer;
import com.caucho.xml.XmlChar;
import com.caucho.xpath.Expr;
import com.caucho.xpath.ExprEnvironment;
import com.caucho.xpath.XPathException;
import org.w3c.dom.Node;
import java.util.ArrayList;
import java.util.Iterator;
/**
* Implements the builtin XPath string expressions.
*/
public class StringExpr extends Expr {
// Code of the expression defined in Expr
private int _code;
// First argument
private Expr _left;
// Second argument
private Expr _right;
// Third
private Expr _third;
private String _value;
// Arguments for more than 3.
private ArrayList _args;
/**
* Create a StringExpression with three arguments.
*
* @param code the Expr code of the expression.
* @param left the first argument.
* @param right the second argument.
* @param third the third argument.
*/
public StringExpr(int code, Expr left, Expr right, Expr third)
{
_code = code;
_left = left;
_right = right;
_third = third;
}
public StringExpr(int code, Expr left, Expr right)
{
_code = code;
_left = left;
_right = right;
}
public StringExpr(int code, Expr expr)
{
_code = code;
_left = expr;
}
public StringExpr(String value)
{
_code = CONST;
_value = value;
}
/**
* Creates a string expression from a list of arguments.
*
* @param code Expr code for the function.
* @param args array list of the arguments.
*/
public StringExpr(int code, ArrayList args)
{
_code = code;
_args = args;
if (args.size() > 0)
_left = (Expr) args.get(0);
if (args.size() > 1)
_right = (Expr) args.get(1);
if (args.size() > 2)
_third = (Expr) args.get(2);
}
/**
* The StringExpr returns a string value.
*/
public boolean isString()
{
return true;
}
public String getValue()
{
return _value;
}
/**
* Evaluates the expression as an string.
*
* @param node the current node
* @param env the variable environment.
*
* @return the string representation of the expression.
*/
public String evalString(Node node, ExprEnvironment env)
throws XPathException
{
switch (_code) {
case CONST:
return _value;
case STRING:
return _left.evalString(node, env);
case CONCAT:
CharBuffer cb = CharBuffer.allocate();
for (int i = 0; i < _args.size(); i++)
((Expr) _args.get(i)).evalString(cb, node, env);
return cb.close();
case SUBSTRING_BEFORE:
String lstr = _left.evalString(node, env);
String rstr = _right.evalString(node, env);
int index = lstr.indexOf(rstr);
return index > 0 ? lstr.substring(0, index) : "";
case SUBSTRING_AFTER:
lstr = _left.evalString(node, env);
rstr = _right.evalString(node, env);
index = lstr.indexOf(rstr);
return index >= 0 ? lstr.substring(index + rstr.length()) : "";
case NORMALIZE:
lstr = _left.evalString(node, env);
return normalize(lstr);
case TRANSLATE:
lstr = _left.evalString(node, env);
rstr = _right.evalString(node, env);
String tstr = _third.evalString(node, env);
return translate(lstr, rstr, tstr);
case FORMAT_NUMBER:
return _left.evalString(node, env);
case LOCAL_PART:
Object lobj = _left.evalObject(node, env);
Node nodeValue = toNode(lobj);
if (nodeValue != null)
return nodeValue.getLocalName();
else
return "";
case NAMESPACE:
lobj = _left.evalObject(node, env);
nodeValue = toNode(lobj);
if (nodeValue != null) {
String uri = nodeValue.getNamespaceURI();
return uri != null ? uri : "";
}
else
return "";
case QNAME:
lobj = _left.evalObject(node, env);
nodeValue = toNode(lobj);
if (nodeValue != null)
return nodeValue.getNodeName();
else
return "";
case GENERATE_ID:
Iterator iter = _left.evalNodeSet(node, env);
return "G" + String.valueOf(System.identityHashCode(iter.next()));
case SYSTEM_PROPERTY:
lstr = _left.evalString(node, env);
if (lstr == null)
return "";
else if (lstr.equals("xsl:version"))
return "1.0";
else
return "";
case SUBSTRING:
lstr = _left.evalString(node, env);
if (lstr == null)
lstr = "";
double start = _right.evalNumber(node, env) - 1;
double end = lstr.length();
if (_third != null)
end = Math.round(start) + _third.evalNumber(node, env);
if (Double.isNaN(end) || Double.isNaN(start)) {
start = 0;
end = 0;
}
if (start < 0)
start = 0;
else if (lstr.length() < start)
start = lstr.length();
if (end < 0)
end = 0;
else if (end < start)
end = start;
else if (lstr.length() < end)
end = lstr.length();
return lstr.substring((int) (start + 0.5), (int) (end + 0.5));
default:
throw new RuntimeException("unknown code: " + _code);
}
}
/**
* Evaluate the expression as a boolean, i.e. evaluate it as a string
* and then convert it to a boolean.
*
* @param node the current node
* @param env the variable environment.
*
* @return the boolean representation of the expression.
*/
public boolean evalBoolean(Node node, ExprEnvironment env)
throws XPathException
{
String string = evalString(node, env);
return string != null && string.length() > 0;
}
/**
* Evaluate the expression as a double, i.e. evaluate it as a string
* and then convert it to a double.
*
* @param node the current node
* @param env the variable environment.
*
* @return the numeric representation of the expression.
*/
public double evalNumber(Node node, ExprEnvironment env)
throws XPathException
{
return stringToNumber(evalString(node, env));
}
/**
* Evaluate the expression as an object, i.e. return the string value.
*
* @param node the current node
* @param env the variable environment.
*
* @return the boolean representation of the expression.
*/
public Object evalObject(Node node, ExprEnvironment env)
throws XPathException
{
return evalString(node, env);
}
/**
* Normalize the string, converting all whitespace to a space and
* eliminating consecutive spaces.
*/
private String normalize(String string)
{
CharBuffer result = new CharBuffer();
int i = 0;
int len = string.length();
for (; i < len && XmlChar.isWhitespace(string.charAt(i)); i++) {
}
boolean lastIsWhitespace = false;
for (; i < len; i++) {
if (XmlChar.isWhitespace(string.charAt(i))) {
lastIsWhitespace = true;
}
else if (lastIsWhitespace) {
result.append(' ');
result.append(string.charAt(i));
lastIsWhitespace = false;
}
else
result.append(string.charAt(i));
}
return result.toString();
}
/**
* Translate the string, converting characters. translate("foo", "f", "b")
* returns "boo".
*
* @param string the string to translate.
* @param from characters to convert from.
* @param to the replacement characters.
*/
private String translate(String string, String from, String to)
{
CharBuffer result = new CharBuffer();
loop:
for (int i = 0; i < string.length(); i++) {
char ch = string.charAt(i);
for (int j = 0; j < from.length(); j++) {
if (ch == from.charAt(j)) {
if (to.length() > j)
result.append(to.charAt(j));
continue loop;
}
}
result.append(ch);
}
return result.toString();
}
/**
* Return the expression as a string. toString() returns a valid
* XPath expression. This lets applications like XSLT use toString()
* to print the string in the generated Java.
*/
public String toString()
{
switch (_code) {
case CONST:
CharBuffer cb = CharBuffer.allocate();
cb.append("'");
for (int i = 0; i < _value.length(); i++) {
char ch = _value.charAt(i);
switch (ch) {
case '\n':
cb.append("\\n");
break;
case '\r':
cb.append("\\r");
break;
case '\\':
cb.append("\\\\");
break;
case '\'':
cb.append("\\'\\'");
break;
case '"':
cb.append("\\\"");
break;
default:
cb.append(ch);
}
}
cb.append("'");
return cb.toString();
case STRING: return "string(" + _left + ")";
case CONCAT:
String result = "concat(";
for (int i = 0; i < _args.size(); i++) {
if (i > 0)
result = result + ", ";
result = result + _args.get(i);
}
return result + ")";
case SUBSTRING_BEFORE:
return "substring-before(" + _left + ", " + _right + ")";
case SUBSTRING_AFTER:
return "substring-after(" + _left + ", " + _right + ")";
case NORMALIZE:
return "normalize-space(" + _left + ")";
case TRANSLATE:
return "translate(" + _left + ", " + _right + ", " + _third + ")";
case FORMAT_NUMBER:
return "format-number(" + _left + ")";
case LOCAL_PART:
return "local-part(" + _left + ")";
case NAMESPACE:
return "namespace-uri(" + _left + ")";
case QNAME:
return "name(" + _left + ")";
case GENERATE_ID:
return "generate-id(" + _left + ")";
case SYSTEM_PROPERTY:
return "system-property(" + _left + ")";
case SUBSTRING:
return "substring(" + _left + "," + _right +
(_third == null ? "" : ("," + _third)) + ")";
case BASE_URI:
return "fn:base-uri(" + _left + ")";
default:
return super.toString();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy