001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements. See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership. The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the  "License");
007     * you may not use this file except in compliance with the License.
008     * You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    /*
019     * $Id: When.java 468650 2006-10-28 07:03:30Z minchau $
020     */
021    
022    package org.apache.xalan.xsltc.compiler;
023    
024    import org.apache.xalan.xsltc.compiler.util.BooleanType;
025    import org.apache.xalan.xsltc.compiler.util.ClassGenerator;
026    import org.apache.xalan.xsltc.compiler.util.ErrorMsg;
027    import org.apache.xalan.xsltc.compiler.util.MethodGenerator;
028    import org.apache.xalan.xsltc.compiler.util.Type;
029    import org.apache.xalan.xsltc.compiler.util.TypeCheckError;
030    import org.apache.xalan.xsltc.compiler.util.Util;
031    
032    /**
033     * @author Jacek Ambroziak
034     * @author Santiago Pericas-Geertsen
035     * @author Morten Jorgensen
036     */
037    final class When extends Instruction {
038    
039        private Expression _test;
040        private boolean _ignore = false;
041    
042        public void display(int indent) {
043            indent(indent);
044            Util.println("When");
045            indent(indent + IndentIncrement);
046            System.out.print("test ");
047            Util.println(_test.toString());
048            displayContents(indent + IndentIncrement);
049        }
050                    
051        public Expression getTest() {
052            return _test;
053        }
054    
055        public boolean ignore() {
056            return(_ignore);
057        }
058    
059        public void parseContents(Parser parser) {
060            _test = parser.parseExpression(this, "test", null);
061    
062            // Ignore xsl:if when test is false (function-available() and
063            // element-available())
064            Object result = _test.evaluateAtCompileTime();
065            if (result != null && result instanceof Boolean) {
066                _ignore = !((Boolean) result).booleanValue();
067            }
068    
069            parseChildren(parser);
070    
071            // Make sure required attribute(s) have been set
072            if (_test.isDummy()) {
073                reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR, "test");
074            }
075        }
076    
077        /**
078         * Type-check this when element. The test should always be type checked,
079         * while we do not bother with the contents if we know the test fails.
080         * This is important in cases where the "test" expression tests for
081         * the support of a non-available element, and the <xsl:when> body contains
082         * this non-available element.
083         */
084        public Type typeCheck(SymbolTable stable) throws TypeCheckError {
085            // Type-check the test expression
086            if (_test.typeCheck(stable) instanceof BooleanType == false) {
087                _test = new CastExpr(_test, Type.Boolean);
088            }
089            // Type-check the contents (if necessary)
090            if (!_ignore) {
091                typeCheckContents(stable);
092            }
093    
094            return Type.Void;
095        }
096    
097        /**
098         * This method should never be called. An Otherwise object will explicitly
099         * translate the "test" expression and and contents of this element.
100         */
101        public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
102            final ErrorMsg msg = new ErrorMsg(ErrorMsg.STRAY_WHEN_ERR, this);
103            getParser().reportError(Constants.ERROR, msg);
104        }
105    }