001: package net.sf.saxon.functions;
002:
003: import net.sf.saxon.expr.*;
004: import net.sf.saxon.om.Item;
005: import net.sf.saxon.trans.XPathException;
006: import net.sf.saxon.value.BooleanValue;
007: import net.sf.saxon.type.ItemType;
008: import net.sf.saxon.type.TypeHierarchy;
009: import net.sf.saxon.type.Type;
010:
011: /**
012: * This class supports the XPath functions boolean(), not(), true(), and false()
013: */
014:
015: public class BooleanFn extends SystemFunction {
016:
017: public static final int BOOLEAN = 0;
018: public static final int NOT = 1;
019: public static final int TRUE = 2;
020: public static final int FALSE = 3;
021:
022: /**
023: * Static analysis: prevent sorting of the argument
024: */
025:
026: public void checkArguments(StaticContext env) throws XPathException {
027: super .checkArguments(env);
028: if (operation == BOOLEAN || operation == NOT) {
029: XPathException err = TypeChecker.ebvError(argument[0], env
030: .getNamePool().getTypeHierarchy());
031: if (err != null) {
032: err.setLocator(this );
033: throw err;
034: }
035: Optimizer opt = env.getConfiguration().getOptimizer();
036: argument[0] = ExpressionTool.unsortedIfHomogeneous(opt,
037: argument[0], false);
038: }
039: }
040:
041: /**
042: * Perform optimisation of an expression and its subexpressions.
043: * <p/>
044: * <p>This method is called after all references to functions and variables have been resolved
045: * to the declaration of the function or variable, and after all type checking has been done.</p>
046: *
047: * @param opt the optimizer in use. This provides access to supporting functions; it also allows
048: * different optimization strategies to be used in different circumstances.
049: * @param env the static context of the expression
050: * @param contextItemType the static type of "." at the point where this expression is invoked.
051: * The parameter is set to null if it is known statically that the context item will be undefined.
052: * If the type of the context item is not known statically, the argument is set to
053: * {@link net.sf.saxon.type.Type#ITEM_TYPE}
054: * @return the original expression, rewritten if appropriate to optimize execution
055: * @throws net.sf.saxon.trans.StaticError if an error is discovered during this phase
056: * (typically a type error)
057: */
058:
059: public Expression optimize(Optimizer opt, StaticContext env,
060: ItemType contextItemType) throws XPathException {
061: Expression e = super .optimize(opt, env, contextItemType);
062: TypeHierarchy th = env.getNamePool().getTypeHierarchy();
063: if (e == this ) {
064: if (operation == BOOLEAN) {
065: if (th.isSubType(argument[0].getItemType(th),
066: Type.BOOLEAN_TYPE)) {
067: return argument[0];
068: }
069: } else if (operation == NOT) {
070: if (argument[0] instanceof ValueComparison) {
071: return ((ValueComparison) argument[0]).negate()
072: .optimize(opt, env, contextItemType);
073: } else if (argument[0] instanceof BooleanExpression) {
074: return ((BooleanExpression) argument[0])
075: .negate(env).optimize(opt, env,
076: contextItemType);
077: } else if (argument[0] instanceof BooleanFn) {
078: BooleanFn arg = (BooleanFn) argument[0];
079: if (arg.operation == BOOLEAN) {
080: argument[0] = arg.argument[0];
081: } else {
082: return arg.argument[0];
083: }
084: }
085: }
086: }
087: return this ;
088: }
089:
090: /**
091: * Evaluate the function
092: */
093:
094: public Item evaluateItem(XPathContext context)
095: throws XPathException {
096: return BooleanValue.get(effectiveBooleanValue(context));
097: }
098:
099: /**
100: * Evaluate the effective boolean value
101: */
102:
103: public boolean effectiveBooleanValue(XPathContext c)
104: throws XPathException {
105: try {
106: switch (operation) {
107: case BOOLEAN:
108: return argument[0].effectiveBooleanValue(c);
109: case NOT:
110: return !argument[0].effectiveBooleanValue(c);
111: case TRUE:
112: return true;
113: case FALSE:
114: return false;
115: default:
116: throw new UnsupportedOperationException(
117: "Unknown boolean operation");
118: }
119: } catch (XPathException e) {
120: if (e.getLocator() == null) {
121: e.setLocator(this );
122: }
123: throw e;
124: }
125: }
126:
127: }
128:
129: //
130: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
131: // you may not use this file except in compliance with the License. You may obtain a copy of the
132: // License at http://www.mozilla.org/MPL/
133: //
134: // Software distributed under the License is distributed on an "AS IS" basis,
135: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
136: // See the License for the specific language governing rights and limitations under the License.
137: //
138: // The Original Code is: all this file.
139: //
140: // The Initial Developer of the Original Code is Michael H. Kay.
141: //
142: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
143: //
144: // Contributor(s): none.
145: //
|