org.xchain.framework.jxpath.ScopedJXPathContextImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.xchain.framework.jxpath.ScopedJXPathContextImpl.java

Source

/**
 *    Copyright 2011 meltmedia
 *
 *    Licensed 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.xchain.framework.jxpath;

import org.apache.commons.jxpath.PackageFunctions;
import org.apache.commons.jxpath.FunctionLibrary;
import org.apache.commons.jxpath.Functions;
import org.apache.commons.jxpath.JXPathContext;
import org.apache.commons.jxpath.Pointer;
import org.apache.commons.jxpath.ri.JXPathContextReferenceImpl;
import org.apache.commons.jxpath.JXPathException;
import org.xchain.framework.jxpath.GenericsWisePackageFunctions;
import org.xchain.framework.lifecycle.Lifecycle;

/**
 * An implementation of JXPathContext that installs an instance of scoped QName variables into the
 * context.
 *
 * @author Christian Trimble
 * @author Devon Tackett
 * @author John Trimble
 */
public class ScopedJXPathContextImpl extends JXPathContextReferenceImpl {
    private static final PackageFunctions GENERIC_FUNCTIONS = new GenericsWisePackageFunctions("", null);
    private Scope scope;

    public ScopedJXPathContextImpl(JXPathContext parentContext, Object contextBean, Scope scope) {
        super(parentContext, contextBean);
        this.scope = scope;
        // Create the variables with a reference to a possible parent context.
        setVariables(createQNameVariables(parentContext));

        // If present, use the namespaceResolver from the parentContext.
        if (parentContext != null)
            namespaceResolver = ((JXPathContextReferenceImpl) parentContext).getNamespaceResolver();

        setFunctions(createFunctions(parentContext));
        setLenient(true);
    }

    /**
     * Creates a new ScopedJXPathContextImpl.
     */
    public ScopedJXPathContextImpl(JXPathContext parentContext, Object contextBean, Pointer contextPointer,
            Scope scope) {
        super(parentContext, contextBean, contextPointer);
        this.scope = scope;
        // Create the variables with a reference to a possible parent context.
        setVariables(createQNameVariables(parentContext));

        // If present, use the namespaceResolver from the parentContext.
        if (parentContext != null)
            namespaceResolver = ((JXPathContextReferenceImpl) parentContext).getNamespaceResolver();

        setFunctions(createFunctions(parentContext));
        setLenient(true);
    }

    public JXPathContext getRelativeContext(Pointer pointer) {
        Object contextBean = pointer.getNode();
        if (contextBean == null) {
            throw new JXPathException("Cannot create a relative context for a non-existent node: " + pointer);
        }
        return new ScopedJXPathContextImpl(this, contextBean, pointer, scope);
    }

    /**
     * Creates the proper qName variables for this parent context.  If the given parentContext is
     * a LocalJXPathContext then the QNameVariables will be shared with the parentContext.  If the
     * given parentContext is not a LocalJXPathContext then the QNameVariables will be able to reference
     * variables in the parent context but values in the create QNameVariables will not be available to
     * the parent context.
     * 
     * @param parentContext The parent context to build from.
     * 
     * @return The ScopedQNameVariables for this JXPathContext.
     */
    private ScopedQNameVariables createQNameVariables(JXPathContext parentContext) {
        ScopedQNameVariables variables = null;

        if (parentContext != null) {
            // Create a new instance of the ScopedQNameVariables with a reference to the parent context's variables.
            variables = new ScopedQNameVariablesImpl(this, ((ScopedQNameVariables) parentContext.getVariables()),
                    scope);
        } else {
            // Create a new instance of the ScopedQNameVariables with no reference to the parent context.
            variables = new ScopedQNameVariablesImpl(this, null, scope);
        }
        return variables;
    }

    private Functions createFunctions(JXPathContext parent) {
        if (parent == null && Lifecycle.getLifecycleContext() != null) {
            FunctionLibrary library = new NamespaceResolvingFunctionLibrary(namespaceResolver);
            library.addFunctions(Lifecycle.getLifecycleContext().getFunctionLibrary());
            return library;
        } else if (parent != null) {
            return parent.getFunctions();
        } else {
            return getFunctions();
        }
    }

    /**
     * <p>This method corrects casting behavior for the Java 5 Enum type.</p>
     *
     * @param expression the expression to evaluate.
     * @param type the type of object to return.
     * @return the value returned after evaluating the expression.
     */
    /*
    public Object getValue( String jxpath, Class type )
    {
      if( Enum.class.isAssignableFrom(type) ) {
        Object value = super.getValue( jxpath, Object.class );
        if( value == null ) {
    return null;
        }
        else if( type.isAssignableFrom(value.getClass()) ) {
    return value;
        }
        else {
    return Enum.valueOf( type, value.toString() );
        }
      }
      else {
        return super.getValue( jxpath, type );
      }
    }
    */

    /**
     * Release all components generated in this context.
     */
    public void releaseComponents() {
        ScopedQNameVariablesImpl vars = (ScopedQNameVariablesImpl) getVariables();

        vars.releaseComponents();
    }

    public Scope getScope() {
        return scope;
    }

    /** 
     * Overridden to insure an instance of <code>GenericsWisePackageFunctions</code> is returned by
     * default, when a Functions instance hasn't been set explicitly, instead of a
     * <code>PackageFunctions</code> instance. 
     */
    @Override
    public Functions getFunctions() {
        if (this.functions != null)
            return this.functions;
        return ScopedJXPathContextImpl.GENERIC_FUNCTIONS;
    }
}