throw new EXistException("function " + fnName + " not defined"); Function func = Function.createFunction(clazz);
throw new XPathException("function " + fnName + " not defined"); Function func = Function.createFunction(context, clazz); func.setArguments(params);
	public static Expression createFunction(		StaticContext context,		PathExpr parent,		String fnName,		Vector params)		throws EXistException, PermissionDeniedException {		Expression step = null;		if (fnName.equals("document")) {			DocumentSet docs = null;			if (params.size() == 0)				docs = context.getBroker().getAllDocuments();			else {				docs = new DocumentSet();				String next;				DocumentImpl doc;				for (int i = 0; i < params.size(); i++) {					next = ((PathExpr) params.elementAt(i)).getLiteralValue();					doc = (DocumentImpl) context.getBroker().getDocument(next);					if (doc != null)						docs.add(doc);				}			}			step = new RootNode();			parent.add(step);			parent.setDocumentSet(docs);		}		if (fnName.equals("collection") || fnName.equals("xcollection")) {			DocumentSet docs = new DocumentSet();			boolean inclusive = fnName.equals("collection");			String next;			DocumentSet temp;			for (int i = 0; i < params.size(); i++) {				next = ((PathExpr) params.elementAt(i)).getLiteralValue();				temp =					context.getBroker().getDocumentsByCollection(						next,						inclusive);				docs.addAll(temp);			}			step = new RootNode();			parent.add(step);			parent.setDocumentSet(docs);		}		if (fnName.equals("doctype")) {			DocumentSet docs = new DocumentSet();			String next;			DocumentSet temp;			for (int i = 0; i < params.size(); i++) {				next = ((PathExpr) params.elementAt(i)).getLiteralValue();				temp = context.getBroker().getDocumentsByDoctype(next);				docs.addAll(temp);			}			step = new RootNode();			parent.add(step);			parent.setDocumentSet(docs);		}		// near(node-set, string)		if (fnName.equals("near")) {			if (params.size() < 2)				throw new IllegalArgumentException("Function near requires two arguments");			PathExpr p1 = (PathExpr) params.elementAt(1);			if (p1.getLength() == 0)				throw new IllegalArgumentException("Second argument to near is empty");			Expression e1 = p1.getExpression(0);			ExtNear near = new ExtNear();			near.addTerm(e1);			near.setPath((PathExpr) params.elementAt(0));			if(params.size() > 2) {				p1 = (PathExpr) params.elementAt(2);				if(p1.getLength() == 0)					throw new IllegalArgumentException("Distance argument to near is empty");				near.setDistance(p1);			}			step = near;			parent.addPath(near);		}		// ends-with(node-set, string)		if (fnName.equals("starts-with")) {			if (params.size() < 2)				throw new IllegalArgumentException("Function starts-with requires two arguments");			PathExpr p0 = (PathExpr) params.elementAt(0);			PathExpr p1 = (PathExpr) params.elementAt(1);			if (p1.getLength() == 0)				throw new IllegalArgumentException("Second argument to starts-with is empty");			Expression e1 = p1.getExpression(0);			if (e1 instanceof Literal				&& p0.returnsType() == Type.NODE) {				Literal l = (Literal) e1;				l.setLiteral(l.getLiteral() + '%');				GeneralComparison op = new GeneralComparison(p0, e1, Constants.EQ);				parent.addPath(op);				step = op;			}		}		// ends-with(node-set, string)		if (fnName.equals("ends-with")) {			if (params.size() < 2)				throw new IllegalArgumentException("Function ends-with requires two arguments");			PathExpr p0 = (PathExpr) params.elementAt(0);			PathExpr p1 = (PathExpr) params.elementAt(1);			if (p1.getLength() == 0)				throw new IllegalArgumentException("Second argument to ends-with is empty");			Expression e1 = p1.getExpression(0);			if (e1 instanceof Literal				&& p0.returnsType() == Type.NODE) {				Literal l = (Literal) e1;				l.setLiteral('%' + l.getLiteral());				GeneralComparison op = new GeneralComparison(p0, e1, Constants.EQ);				parent.addPath(op);				step = op;			}		}		// contains(node-set, string)		if (fnName.equals("contains")) {			if (params.size() < 2)				throw new IllegalArgumentException("Function contains requires two arguments");			PathExpr p0 = (PathExpr) params.elementAt(0);			PathExpr p1 = (PathExpr) params.elementAt(1);			if (p1.getLength() == 0)				throw new IllegalArgumentException("Second argument to contains is empty");			Expression e1 = p1.getExpression(0);			if (e1 instanceof Literal				&& p0.returnsType() == Type.NODE) {				Literal l = (Literal) e1;				l.setLiteral('%' + l.getLiteral() + '%');				GeneralComparison op = new GeneralComparison(p0, e1, Constants.EQ);				parent.addPath(op);				step = op;			}		}		if (step == null) {			String clazz = context.getClassForFunction(fnName);			if (clazz == null)				throw new EXistException("function " + fnName + " not defined");			Function func = Function.createFunction(clazz);			parent.addPath(func);			for (int i = 0; i < params.size(); i++)				func.addArgument((PathExpr) params.elementAt(i));			step = func;		}		return step;	}