001: /*
002: * Copyright 2002,2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.apache.commons.jelly.expression.xpath;
017:
018: import java.util.Hashtable;
019: import java.util.Iterator;
020: import java.util.Map;
021:
022: import org.apache.commons.jelly.JellyContext;
023: import org.apache.commons.jelly.expression.Expression;
024: import org.apache.commons.jelly.expression.ExpressionSupport;
025: import org.apache.commons.jelly.impl.TagScript;
026: import org.apache.commons.logging.Log;
027: import org.apache.commons.logging.LogFactory;
028: import org.jaxen.SimpleNamespaceContext;
029: import org.jaxen.VariableContext;
030: import org.jaxen.XPath;
031: import org.jaxen.JaxenException;
032: import org.jaxen.dom4j.Dom4jXPath;
033:
034: /** An expression which returns an XPath object.
035: *
036: * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
037: * @version $Revision: 155420 $
038: */
039: public class XPathExpression extends ExpressionSupport implements
040: VariableContext {
041:
042: /** The Log to which logging calls will be made. */
043: private Log log = LogFactory.getLog(XPathExpression.class);
044:
045: private String text;
046: private Expression xpathExpr;
047: private JellyContext context;
048: private Map uris;
049:
050: public XPathExpression() {
051: }
052:
053: public XPathExpression(String text, Expression xpathExpr,
054: TagScript tagScript) {
055: this .text = text;
056: this .xpathExpr = xpathExpr;
057:
058: Map namespaceContext = tagScript.getNamespaceContext();
059:
060: this .uris = createUriMap(namespaceContext);
061: }
062:
063: public String toString() {
064: return getExpressionText();
065: }
066:
067: // Expression interface
068: //-------------------------------------------------------------------------
069: public String getExpressionText() {
070: return this .text;
071: }
072:
073: public Object evaluate(JellyContext context) {
074: this .context = context;
075:
076: try {
077: XPath xpath = new Dom4jXPath(this .xpathExpr
078: .evaluateAsString(context));
079:
080: xpath.setVariableContext(this );
081:
082: if (log.isDebugEnabled()) {
083: log.debug("Setting the namespace context to be: "
084: + uris);
085: }
086:
087: xpath.setNamespaceContext(new SimpleNamespaceContext(
088: this .uris));
089:
090: return xpath;
091: } catch (JaxenException e) {
092: log.error("Error constructing xpath", e);
093: }
094:
095: return null;
096: }
097:
098: // VariableContext interface
099: //-------------------------------------------------------------------------
100: public Object getVariableValue(String namespaceURI, String prefix,
101: String localName) {
102:
103: Object value = context.getVariable(localName);
104:
105: //log.debug( "Looking up XPath variable of name: " + localName + " value is: " + value );
106:
107: return value;
108: }
109:
110: // Implementation methods
111: //-------------------------------------------------------------------------
112:
113: /**
114: * Factory method to create a synchronized Map of non-null and non-blank
115: * namespace prefixes to namespace URIs
116: */
117: protected Map createUriMap(Map namespaceContext) {
118: // now lets clone the Map but ignoring default or null prefixes
119: Map uris = new Hashtable(namespaceContext.size());
120: for (Iterator iter = namespaceContext.entrySet().iterator(); iter
121: .hasNext();) {
122: Map.Entry entry = (Map.Entry) iter.next();
123: String prefix = (String) entry.getKey();
124: if (prefix != null && prefix.length() != 0) {
125: uris.put(prefix, entry.getValue());
126: }
127: }
128: return uris;
129: }
130: }
|