/*
* eXist Open Source Native XML Database
* Copyright (C) 2001-06 Wolfgang M. Meier
* wolfgang@exist-db.org
* http://exist.sourceforge.net
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id$
*/
package org.exist.xquery;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.TreeMap;
import org.exist.dom.QName;
import org.exist.source.Source;
import org.exist.xquery.value.Sequence;
import org.exist.storage.DBBroker;
/**
* Default implementation of an {@link org.exist.xquery.ExternalModule}.
*
* @author Wolfgang Meier (wolfgang@exist-db.org)
*/
public class ExternalModuleImpl implements ExternalModule {
private String mNamespaceURI;
private String mPrefix;
private boolean isReady = false;
final private TreeMap mFunctionMap = new TreeMap();
final private TreeMap mGlobalVariables = new TreeMap();
final private TreeMap mStaticVariables = new TreeMap();
private Source mSource = null;
private XQueryContext mContext = null;
public ExternalModuleImpl(String namespaceURI, String prefix) {
mNamespaceURI = namespaceURI;
mPrefix = prefix;
}
public void setNamespace(String prefix, String namespace) {
this.mPrefix = prefix;
this.mNamespaceURI = namespace;
}
public void setIsReady(boolean ready) {
this.isReady = ready;
}
public boolean isReady() {
return false;
}
/* (non-Javadoc)
* @see org.exist.xquery.Module#getDescription()
*/
public String getDescription() {
return "User defined module";
}
/* (non-Javadoc)
* @see org.exist.xquery.Module#getReleaseVersion()
*/
public String getReleaseVersion() {
return "user-defined";
}
public UserDefinedFunction getFunction(QName qname, int arity) {
FunctionId id = new FunctionId(qname, arity);
return (UserDefinedFunction) mFunctionMap.get(id);
}
/* (non-Javadoc)
* @see org.exist.xquery.ExternalModule#declareFunction(org.exist.xquery.UserDefinedFunction)
*/
public void declareFunction(UserDefinedFunction func) {
mFunctionMap.put(func.getSignature().getFunctionId(), func);
}
/* (non-Javadoc)
* @see org.exist.xquery.Module#getNamespaceURI()
*/
public String getNamespaceURI() {
return mNamespaceURI;
}
/* (non-Javadoc)
* @see org.exist.xquery.Module#getDefaultPrefix()
*/
public String getDefaultPrefix() {
return mPrefix;
}
/* (non-Javadoc)
* @see org.exist.xquery.Module#isInternalModule()
*/
public boolean isInternalModule() {
return false;
}
/* (non-Javadoc)
* @see org.exist.xquery.Module#listFunctions()
*/
public FunctionSignature[] listFunctions() {
FunctionSignature signatures[] = new FunctionSignature[mFunctionMap.size()];
int j = 0;
for (Iterator i = mFunctionMap.values().iterator(); i.hasNext(); j++) {
signatures[j] = ((UserDefinedFunction) i.next()).getSignature();
}
return signatures;
}
/* (non-Javadoc)
* @see org.exist.xquery.Module#getSignatureForFunction(org.exist.dom.QName)
*/
public Iterator getSignaturesForFunction(QName qname) {
ArrayList signatures = new ArrayList(2);
for (Iterator i = mFunctionMap.values().iterator(); i.hasNext(); ) {
UserDefinedFunction func = (UserDefinedFunction) i.next();
if(func.getName().compareTo(qname) == 0)
signatures.add(func.getSignature());
}
return signatures.iterator();
}
/* (non-Javadoc)
* @see org.exist.xquery.Module#declareVariable(org.exist.dom.QName, java.lang.Object)
*/
public Variable declareVariable(QName qname, Object value) throws XPathException {
Sequence val = XPathUtil.javaObjectToXPath(value, mContext);
Variable var = (Variable) mStaticVariables.get(qname);
if (var == null) {
var = new Variable(qname);
mStaticVariables.put(qname, var);
}
var.setValue(val);
return var;
}
public Variable declareVariable(Variable var) {
mStaticVariables.put(var.getQName(), var);
return var;
}
public void declareVariable(QName qname, VariableDeclaration decl) throws XPathException {
if (!qname.getNamespaceURI().equals(getNamespaceURI()))
throw new XPathException(decl, "err:XQST0048: It is a static error if a function " +
"or variable declared in a library module is not in the target namespace of the library module.");
mGlobalVariables.put(qname, decl);
}
public boolean isVarDeclared(QName qname) {
if (mGlobalVariables.get(qname) != null)
return true;
return mStaticVariables.get(qname) != null;
}
/* (non-Javadoc)
* @see org.exist.xquery.Module#resolveVariable(org.exist.dom.QName)
*/
public Variable resolveVariable(QName qname) throws XPathException {
VariableDeclaration decl = (VariableDeclaration)mGlobalVariables.get(qname);
Variable var = (Variable) mStaticVariables.get(qname);
if(decl != null && (var == null || var.getValue() == null)) {
decl.eval(null);
var = (Variable) mStaticVariables.get(qname);
}
return var;
}
public void analyzeGlobalVars() throws XPathException {
for (Iterator it = mGlobalVariables.values().iterator(); it.hasNext();) {
VariableDeclaration decl = (VariableDeclaration) it.next();
decl.resetState(false);
decl.analyze(new AnalyzeContextInfo());
}
}
public Source getSource() {
return mSource;
}
public void setSource(Source source) {
mSource = source;
}
public void setContext(XQueryContext context) {
mContext = context;
}
public XQueryContext getContext() {
return mContext;
}
/* (non-Javadoc)
* @see org.exist.xquery.ExternalModule#moduleIsValid()
*/
public boolean moduleIsValid(DBBroker broker) {
return mSource.isValid(broker) == Source.VALID;
}
public void reset(XQueryContext xqueryContext) {
mContext.reset();
mStaticVariables.clear();
}
private Expression rootExpression = null;
/**
* Set the root expression for this context.
*
* @param expr
*/
public void setRootExpression( Expression expr ) {
rootExpression = expr;
}
/**
* Returns the root expression associated with this context.
*
* @return root expression
*/
public Expression getRootExpression() {
return rootExpression;
}
}