Package org.apache.cocoon.components.expression.jxpath

Source Code of org.apache.cocoon.components.expression.jxpath.JXPathExpression$VariableAdapter

/*
* 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.components.expression.jxpath;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.apache.cocoon.components.expression.Expression;
import org.apache.cocoon.components.expression.ExpressionContext;
import org.apache.cocoon.components.expression.ExpressionException;
import org.apache.cocoon.components.expression.jexl.JSIntrospector;
import org.apache.cocoon.util.jxpath.NamespacesTablePointer;
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 449189 2006-09-23 06:52:29Z crossley $
*/
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(ExpressionContext context)
        throws ExpressionException{
        return this.compiledExpression.getValue(getContext(context));
    }

    public Iterator iterate(ExpressionContext context)
        throws ExpressionException {
        final JXPathContext jxpathContext = getContext(context);
        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(ExpressionContext context, Object value)
        throws ExpressionException {
        this.compiledExpression.setValue(getContext(context), 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(ExpressionContext context) throws ExpressionException {
        Iterator iter =
            this.compiledExpression.iteratePointers(getContext(context));
        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(ExpressionContext context) {
        // This could be made more efficient by caching the
        // JXPathContext within the Context object.
        JXPathContext jxcontext = JXPathContext.newContext(context.getContextBean());
        jxcontext.setVariables(new VariableAdapter(context));
        jxcontext.setLenient(this.lenient);
        jxcontext.setNamespaceContextPointer(new NamespacesTablePointer(context.getNamespaces()));
        return jxcontext;
    }

    private static class VariableAdapter implements Variables {
        private ExpressionContext context;

        public VariableAdapter(ExpressionContext context) {
            this.context = context;
        }

        public void declareVariable(String name, Object value) {
            this.context.put(name, value);
        }

        public Object getVariable(String name) {
            return this.context.get(name);
        }

        public boolean isDeclaredVariable(String name) {
            return this.context.containsKey(name);
        }

        public void undeclareVariable(String name) {
            throw new UnsupportedOperationException("Operation undeclareVariable is not supported");
        }
    }
}
TOP

Related Classes of org.apache.cocoon.components.expression.jxpath.JXPathExpression$VariableAdapter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.