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.exception.MethodInvocationException;
24 import org.apache.velocity.runtime.parser.Parser;
25 import org.apache.velocity.util.TemplateNumber;
26
27 /**
28 * Handles <code>arg1 != arg2</code>
29 *
30 * This operator requires that the LHS and RHS are both of the
31 * same Class OR both are subclasses of java.lang.Number
32 *
33 * @author <a href="mailto:wglass@forio.com">Will Glass-Husain</a>
34 * @author <a href="mailto:pero@antaramusic.de">Peter Romianowski</a>
35 */
36 public class ASTNENode extends SimpleNode
37 {
38 /**
39 * @param id
40 */
41 public ASTNENode(int id)
42 {
43 super(id);
44 }
45
46 /**
47 * @param p
48 * @param id
49 */
50 public ASTNENode(Parser p, int id)
51 {
52 super(p, id);
53 }
54
55 /**
56 * @see org.apache.velocity.runtime.parser.node.SimpleNode#jjtAccept(org.apache.velocity.runtime.parser.node.ParserVisitor, java.lang.Object)
57 */
58 public Object jjtAccept(ParserVisitor visitor, Object data)
59 {
60 return visitor.visit(this, data);
61 }
62
63 /**
64 * @see org.apache.velocity.runtime.parser.node.SimpleNode#evaluate(org.apache.velocity.context.InternalContextAdapter)
65 */
66 public boolean evaluate( InternalContextAdapter context)
67 throws MethodInvocationException
68 {
69 Object left = jjtGetChild(0).value( context );
70 Object right = jjtGetChild(1).value( context );
71
72 /*
73 * null check
74 */
75
76 if ( left == null || right == null)
77 {
78 log.error((left == null ? "Left" : "Right")
79 + " side ("
80 + jjtGetChild( (left == null? 0 : 1) ).literal()
81 + ") of '!=' operation has null value."
82 + " Operation not possible. "
83 + context.getCurrentTemplateName() + " [line " + getLine()
84 + ", column " + getColumn() + "]");
85 return false;
86
87 }
88
89 /*
90 * convert to Number if applicable
91 */
92 if (left instanceof TemplateNumber)
93 {
94 left = ( (TemplateNumber) left).getAsNumber();
95 }
96 if (right instanceof TemplateNumber)
97 {
98 right = ( (TemplateNumber) right).getAsNumber();
99 }
100
101 /*
102 * If comparing Numbers we do not care about the Class.
103 */
104 if (left instanceof Number && right instanceof Number)
105 {
106 return MathUtils.compare ( (Number)left,(Number)right) != 0;
107 }
108
109
110 /**
111 * assume that if one class is a subclass of the other
112 * that we should use the equals operator
113 */
114
115 if (left.getClass().isAssignableFrom(right.getClass()) ||
116 right.getClass().isAssignableFrom(left.getClass()) )
117 {
118 return !left.equals( right );
119 }
120 else
121 {
122 /**
123 * Compare the String representations
124 */
125 if ((left.toString() == null) || (right.toString() == null))
126 {
127 boolean culprit = (left.toString() == null);
128 log.error((culprit ? "Left" : "Right")
129 + " string side "
130 + "String representation ("
131 + jjtGetChild((culprit ? 0 : 1) ).literal()
132 + ") of '!=' operation has null value."
133 + " Operation not possible. "
134 + context.getCurrentTemplateName() + " [line " + getLine()
135 + ", column " + getColumn() + "]");
136 return false;
137 }
138
139 else
140 {
141 return !left.toString().equals(right.toString());
142 }
143
144 }
145
146 }
147
148 /**
149 * @see org.apache.velocity.runtime.parser.node.SimpleNode#value(org.apache.velocity.context.InternalContextAdapter)
150 */
151 public Object value(InternalContextAdapter context)
152 throws MethodInvocationException
153 {
154 boolean val = evaluate(context);
155
156 return val ? Boolean.TRUE : Boolean.FALSE;
157 }
158
159 }