Java tutorial
/* * 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.cocoon.el.impl.jxpath; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import org.apache.cocoon.el.Expression; import org.apache.cocoon.el.ExpressionException; import org.apache.cocoon.el.impl.jexl.JSIntrospector; import org.apache.cocoon.el.objectmodel.ObjectModel; import org.apache.cocoon.xml.util.NamespacesTable; import org.apache.commons.jxpath.CompiledExpression; import org.apache.commons.jxpath.JXPathContext; import org.apache.commons.jxpath.Pointer; import org.apache.commons.jxpath.Variables; import org.mozilla.javascript.NativeArray; import org.w3c.dom.Node; /** * @version SVN $Id: JXPathExpression.java 587751 2007-10-24 02:41:36Z vgritsenko $ */ public class JXPathExpression implements Expression { private final String language; private final String expression; private final CompiledExpression compiledExpression; private boolean lenient = false; public static final String LENIENT = "lenient"; public JXPathExpression(String language, String expression) throws ExpressionException { this.language = language; this.expression = expression; this.compiledExpression = JXPathContext.compile(expression); } public Object evaluate(ObjectModel objectModel) throws ExpressionException { return this.compiledExpression.getValue(getContext(objectModel)); } public Iterator iterate(ObjectModel objectModel) throws ExpressionException { final JXPathContext jxpathContext = getContext(objectModel); Object val = this.compiledExpression.getPointer(jxpathContext, this.expression).getNode(); // FIXME: workaround for JXPath bug if (val instanceof NativeArray) return new JSIntrospector.NativeArrayIterator((NativeArray) val); else return new Iterator() { Iterator iter = compiledExpression.iteratePointers(jxpathContext); public boolean hasNext() { return iter.hasNext(); } public Object next() { return ((Pointer) iter.next()).getNode(); } public void remove() { iter.remove(); } }; } public void assign(ObjectModel objectModel, Object value) throws ExpressionException { this.compiledExpression.setValue(getContext(objectModel), value); } public String getExpression() { return this.expression; } public String getLanguage() { return this.language; } public void setProperty(String property, Object value) { if (LENIENT.equals(property)) this.lenient = ((Boolean) value).booleanValue(); } // Hack: try to prevent JXPath from converting result to a String public Object getNode(ObjectModel objectModel) throws ExpressionException { Iterator iter = this.compiledExpression.iteratePointers(getContext(objectModel)); if (iter.hasNext()) { Pointer first = (Pointer) iter.next(); if (iter.hasNext()) { List result = new LinkedList(); result.add(first.getNode()); boolean dom = (first.getNode() instanceof Node); while (iter.hasNext()) { Object obj = ((Pointer) iter.next()).getNode(); dom = dom && (obj instanceof Node); result.add(obj); } Object[] arr; if (dom) { arr = new Node[result.size()]; } else { arr = new Object[result.size()]; } result.toArray(arr); return arr; } return first.getNode(); } return null; } private JXPathContext getContext(ObjectModel objectModel) { // This could be made more efficient by caching the // JXPathContext within the Context object. JXPathContext jxobjectModel = JXPathContext.newContext(objectModel.get(ObjectModel.CONTEXTBEAN)); jxobjectModel.setVariables(new VariableAdapter(objectModel)); jxobjectModel.setLenient(this.lenient); jxobjectModel.setNamespaceContextPointer( new NamespacesTablePointer((NamespacesTable) objectModel.get(ObjectModel.NAMESPACE))); return jxobjectModel; } private static class VariableAdapter implements Variables { private ObjectModel objectModel; public VariableAdapter(ObjectModel objectModel) { this.objectModel = objectModel; } public void declareVariable(String name, Object value) { this.objectModel.put(name, value); } public Object getVariable(String name) { return this.objectModel.get(name); } public boolean isDeclaredVariable(String name) { return this.objectModel.containsKey(name); } public void undeclareVariable(String name) { throw new UnsupportedOperationException("Operation undeclareVariable is not supported"); } } }