blob: b91ffc3da53e7e86c2cf4dafbd478e3ed3bf5c5d [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.jelly.expression.xpath;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import org.apache.commons.jelly.JellyContext;
import org.apache.commons.jelly.JellyTagException;
import org.apache.commons.jelly.expression.Expression;
import org.apache.commons.jelly.expression.ExpressionSupport;
import org.apache.commons.jelly.impl.TagScript;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jaxen.SimpleNamespaceContext;
import org.jaxen.VariableContext;
import org.jaxen.XPath;
import org.jaxen.JaxenException;
import org.jaxen.dom4j.Dom4jXPath;
/** An expression which returns an XPath object.
*
* @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
* @version $Revision$
*/
public class XPathExpression extends ExpressionSupport implements VariableContext {
/** The Log to which logging calls will be made. */
private Log log = LogFactory.getLog(XPathExpression.class);
private String text;
private Expression xpathExpr;
private JellyContext context;
private Map uris;
public XPathExpression() {
}
public XPathExpression(String text,
Expression xpathExpr,
TagScript tagScript) {
this.text = text;
this.xpathExpr = xpathExpr;
Map namespaceContext = tagScript.getNamespaceContext();
this.uris = createUriMap(namespaceContext);
}
public String toString() {
return getExpressionText();
}
// Expression interface
//-------------------------------------------------------------------------
public String getExpressionText() {
return this.text;
}
public Object evaluate(JellyContext context) {
this.context = context;
try
{
XPath xpath = new Dom4jXPath( this.xpathExpr.evaluateAsString( context ) );
xpath.setVariableContext(this);
if (log.isDebugEnabled()) {
log.debug( "Setting the namespace context to be: " + uris );
}
xpath.setNamespaceContext( new SimpleNamespaceContext( this.uris ) );
return xpath;
}
catch (JaxenException e)
{
if (context.isSuppressExpressionExceptions())
log.error("Error constructing xpath", e);
else
throw (IllegalStateException)new IllegalStateException (e.getMessage()).initCause(e);
}
return null;
}
// VariableContext interface
//-------------------------------------------------------------------------
public Object getVariableValue(
String namespaceURI,
String prefix,
String localName) {
Object value = context.getVariable(localName);
//log.debug( "Looking up XPath variable of name: " + localName + " value is: " + value );
return value;
}
// Implementation methods
//-------------------------------------------------------------------------
/**
* Factory method to create a synchronized Map of non-null and non-blank
* namespace prefixes to namespace URIs
*/
protected Map createUriMap(Map namespaceContext) {
// now lets clone the Map but ignoring default or null prefixes
Map uris = new Hashtable(namespaceContext.size());
for (Iterator iter = namespaceContext.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry entry = (Map.Entry) iter.next();
String prefix = (String) entry.getKey();
if (prefix != null && prefix.length() != 0) {
uris.put(prefix, entry.getValue());
}
}
return uris;
}
}