1 package org.apache.velocity.runtime.parser.node;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21
22 import org.apache.velocity.context.InternalContextAdapter;
23 import org.apache.velocity.runtime.parser.Parser;
24 import org.apache.velocity.runtime.parser.ParserVisitor;
25
26 import org.apache.velocity.exception.MethodInvocationException;
27
28 import org.apache.velocity.util.TemplateNumber;
29
30 /**
31 * Handles <code>arg1 != arg2</code>
32 *
33 * This operator requires that the LHS and RHS are both of the
34 * same Class OR both are subclasses of java.lang.Number
35 *
36 * @author <a href="mailto:wglass@forio.com">Will Glass-Husain</a>
37 * @author <a href="mailto:pero@antaramusic.de">Peter Romianowski</a>
38 */
39 public class ASTNENode extends SimpleNode
40 {
41 /**
42 * @param id
43 */
44 public ASTNENode(int id)
45 {
46 super(id);
47 }
48
49 /**
50 * @param p
51 * @param id
52 */
53 public ASTNENode(Parser p, int id)
54 {
55 super(p, id);
56 }
57
58 /**
59 * @see org.apache.velocity.runtime.parser.node.SimpleNode#jjtAccept(org.apache.velocity.runtime.parser.ParserVisitor, java.lang.Object)
60 */
61 public Object jjtAccept(ParserVisitor visitor, Object data)
62 {
63 return visitor.visit(this, data);
64 }
65
66 /**
67 * @see org.apache.velocity.runtime.parser.node.SimpleNode#evaluate(org.apache.velocity.context.InternalContextAdapter)
68 */
69 public boolean evaluate( InternalContextAdapter context)
70 throws MethodInvocationException
71 {
72 Object left = jjtGetChild(0).value( context );
73 Object right = jjtGetChild(1).value( context );
74
75 /*
76 * null check
77 */
78
79 if ( left == null || right == null)
80 {
81 log.error((left == null ? "Left" : "Right")
82 + " side ("
83 + jjtGetChild( (left == null? 0 : 1) ).literal()
84 + ") of '!=' operation has null value."
85 + " Operation not possible. "
86 + context.getCurrentTemplateName() + " [line " + getLine()
87 + ", column " + getColumn() + "]");
88 return false;
89
90 }
91
92 /*
93 * convert to Number if applicable
94 */
95 if (left instanceof TemplateNumber)
96 {
97 left = ( (TemplateNumber) left).getAsNumber();
98 }
99 if (right instanceof TemplateNumber)
100 {
101 right = ( (TemplateNumber) right).getAsNumber();
102 }
103
104 /*
105 * If comparing Numbers we do not care about the Class.
106 */
107 if (left instanceof Number && right instanceof Number)
108 {
109 return MathUtils.compare ( (Number)left,(Number)right) != 0;
110 }
111
112
113 /**
114 * assume that if one class is a subclass of the other
115 * that we should use the equals operator
116 */
117
118 if (left.getClass().isAssignableFrom(right.getClass()) ||
119 right.getClass().isAssignableFrom(left.getClass()) )
120 {
121 return !left.equals( right );
122 }
123 else
124 {
125 /**
126 * Compare the String representations
127 */
128 if ((left.toString() == null) || (right.toString() == null))
129 {
130 boolean culprit = (left.toString() == null);
131 log.error((culprit ? "Left" : "Right")
132 + " string side "
133 + "String representation ("
134 + jjtGetChild((culprit ? 0 : 1) ).literal()
135 + ") of '!=' operation has null value."
136 + " Operation not possible. "
137 + context.getCurrentTemplateName() + " [line " + getLine()
138 + ", column " + getColumn() + "]");
139 return false;
140 }
141
142 else
143 {
144 return !left.toString().equals(right.toString());
145 }
146
147 }
148
149 }
150
151 /**
152 * @see org.apache.velocity.runtime.parser.node.SimpleNode#value(org.apache.velocity.context.InternalContextAdapter)
153 */
154 public Object value(InternalContextAdapter context)
155 throws MethodInvocationException
156 {
157 boolean val = evaluate(context);
158
159 return val ? Boolean.TRUE : Boolean.FALSE;
160 }
161
162 }