Package org.exist.xquery.functions.fn

Source Code of org.exist.xquery.functions.fn.FunDoc

/*
* eXist Open Source Native XML Database
* Copyright (C) 2001-2009 The eXist Project
* http://exist-db.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*  $Id$
*/
package org.exist.xquery.functions.fn;

import org.apache.log4j.Logger;

import org.exist.dom.DocumentImpl;
import org.exist.dom.DocumentSet;
import org.exist.dom.QName;
import org.exist.dom.StoredNode;
import org.exist.numbering.NodeId;
import org.exist.storage.UpdateListener;
import org.exist.xquery.*;
import org.exist.xquery.functions.xmldb.XMLDBModule;
import org.exist.xquery.util.DocUtils;
import org.exist.xquery.value.FunctionReturnSequenceType;
import org.exist.xquery.value.FunctionParameterSequenceType;
import org.exist.xquery.value.Item;
import org.exist.xquery.value.Sequence;
import org.exist.xquery.value.SequenceType;
import org.exist.xquery.value.Type;

/**
* Implements the built-in fn:doc() function.
*
* This will be replaced by XQuery's fn:doc() function.
*
* @author wolf
*/
public class FunDoc extends Function {

    protected static final Logger logger = Logger.getLogger(FunDoc.class);

    public final static FunctionSignature signature =
        new FunctionSignature(
            new QName("doc", Function.BUILTIN_FUNCTION_NS),
            "Returns the document node of $document-uri. " +
            XMLDBModule.ANY_URI,
            new SequenceType[] {
                new FunctionParameterSequenceType("document-uri", Type.STRING,
                    Cardinality.ZERO_OR_ONE, "The document URI")
            },
            new FunctionReturnSequenceType(Type.NODE, Cardinality.ZERO_OR_ONE,
                "the document node of $document-uri")
        );

    // fixit! - security warning
    private UpdateListener listener = null;

    /**
     * @param context
     */
    public FunDoc(XQueryContext context) {
        super(context, signature);
    }

    /**
     * @see org.exist.xquery.Expression#eval(Sequence, Item)
     */
    public Sequence eval(Sequence contextSequence, Item contextItem)
            throws XPathException {
        if (context.getProfiler().isEnabled()) {
            context.getProfiler().start(this);
            context.getProfiler().message(this, Profiler.DEPENDENCIES,
                "DEPENDENCIES", Dependency.getDependenciesName(this.getDependencies()));
            if (contextSequence != null)
                {context.getProfiler().message(this, Profiler.START_SEQUENCES,
                "CONTEXT SEQUENCE", contextSequence);}
            if (contextItem != null)
                {context.getProfiler().message(this, Profiler.START_SEQUENCES,
                "CONTEXT ITEM", contextItem.toSequence());}
        }
        Sequence result;
        final Sequence arg = getArgument(0).eval(contextSequence, contextItem);
        if (arg.isEmpty())
            {result = Sequence.EMPTY_SEQUENCE;}
        else {
            final String path = arg.itemAt(0).getStringValue();
            // TODO: disabled cache for now as it may cause concurrency issues
            // better use compile-time inspection and maybe a pragma to mark those
            // sections in the query that can be safely cached.
            // check if we can return a cached sequence
            //if (cached != null && path.equals(cachedPath)) {
                //return cached;
            //}
            try {
                result = DocUtils.getDocument(this.context, path);
                if (result.isEmpty() && context.isRaiseErrorOnFailedRetrieval()) {
                    throw new XPathException(this, ErrorCodes.FODC0002,
                        "Can not access '" + path + "'", arg);
                }
                //TODO: we still need a final decision about this. Also check base-uri.
                //if (result == Sequence.EMPTY_SEQUENCE)
                    //throw new XPathException(this, path + " is not an XML document");
                final DocumentSet docs = result.getDocumentSet();
                if (docs != null && DocumentSet.EMPTY_DOCUMENT_SET != docs) {
                    // only cache node sets (which have a non-empty document set)
                    registerUpdateListener();
                }
            } catch (final Exception e) {
                throw new XPathException(this, ErrorCodes.FODC0005, e.getMessage(), arg);
            }
        }
        if (context.getProfiler().isEnabled())
            {context.getProfiler().end(this, "", result);}
        return result;
    }

    protected void registerUpdateListener() {
        if (listener == null) {
            listener = new UpdateListener() {

                public void documentUpdated(DocumentImpl document, int event) {
                    // clear all
                }

                public void unsubscribe() {
                    FunDoc.this.listener = null;
                }

                public void nodeMoved(NodeId oldNodeId, StoredNode newNode) {
                    // not relevant
                }

                public void debug() {
                    logger.debug("UpdateListener: Line: " + getLine() +
                        ": " + FunDoc.this.toString());
                }
            };
            context.registerUpdateListener(listener);
        }
    }

    /**
     * @see org.exist.xquery.Expression#resetState(boolean)
     * @param postOptimization
     */
    public void resetState(boolean postOptimization) {
        super.resetState(postOptimization);
        if (!postOptimization) {
            listener = null;
        }
        getArgument(0).resetState(postOptimization);
    }
}
TOP

Related Classes of org.exist.xquery.functions.fn.FunDoc

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.