View Javadoc
1   /*
2    * Copyright 2002-2014 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.expression.spel.ast;
18  
19  import org.springframework.asm.Label;
20  import org.springframework.asm.MethodVisitor;
21  import org.springframework.expression.EvaluationException;
22  import org.springframework.expression.spel.CodeFlow;
23  import org.springframework.expression.spel.ExpressionState;
24  import org.springframework.expression.spel.SpelEvaluationException;
25  import org.springframework.expression.spel.SpelMessage;
26  import org.springframework.expression.spel.support.BooleanTypedValue;
27  
28  /**
29   * Represents a NOT operation.
30   *
31   * @author Andy Clement
32   * @author Mark Fisher
33   * @author Oliver Becker
34   * @since 3.0
35   */
36  public class OperatorNot extends SpelNodeImpl {  // Not is a unary operator so does not extend BinaryOperator
37  
38  	public OperatorNot(int pos, SpelNodeImpl operand) {
39  		super(pos, operand);
40  		this.exitTypeDescriptor = "Z";
41  	}
42  
43  
44  	@Override
45  	public BooleanTypedValue getValueInternal(ExpressionState state) throws EvaluationException {
46  		try {
47  			Boolean value = this.children[0].getValue(state, Boolean.class);
48  			if (value == null) {
49  				throw new SpelEvaluationException(SpelMessage.TYPE_CONVERSION_ERROR, "null", "boolean");
50  			}
51  			return BooleanTypedValue.forValue(!value);
52  		}
53  		catch (SpelEvaluationException ex) {
54  			ex.setPosition(getChild(0).getStartPosition());
55  			throw ex;
56  		}
57  	}
58  
59  	@Override
60  	public String toStringAST() {
61  		return "!" + getChild(0).toStringAST();
62  	}
63  	
64  	@Override
65  	public boolean isCompilable() {
66  		SpelNodeImpl child = this.children[0];
67  		return (child.isCompilable() && CodeFlow.isBooleanCompatible(child.exitTypeDescriptor));
68  	}
69  	
70  	@Override
71  	public void generateCode(MethodVisitor mv, CodeFlow cf) {
72  		this.children[0].generateCode(mv, cf);
73  		cf.unboxBooleanIfNecessary(mv);
74  		Label elseTarget = new Label();
75  		Label endOfIf = new Label();
76  		mv.visitJumpInsn(IFNE,elseTarget);		
77  		mv.visitInsn(ICONST_1); // TRUE
78  		mv.visitJumpInsn(GOTO,endOfIf);
79  		mv.visitLabel(elseTarget);
80  		mv.visitInsn(ICONST_0); // FALSE
81  		mv.visitLabel(endOfIf);
82  		cf.pushDescriptor(this.exitTypeDescriptor);
83  	}
84  
85  }