View Javadoc

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           *  convert to Number if applicable
74           */
75          if (left instanceof TemplateNumber)
76          {
77             left = ( (TemplateNumber) left).getAsNumber();
78          }
79          if (right instanceof TemplateNumber)
80          {
81             right = ( (TemplateNumber) right).getAsNumber();
82          }
83  
84         /*
85          * If comparing Numbers we do not care about the Class.
86          */
87         if (left instanceof Number && right instanceof Number)
88         {
89              return MathUtils.compare ( (Number)left,(Number)right) != 0;
90         }
91  
92          /**
93           * if both are not null, then assume that if one class
94           * is a subclass of the other that we should use the equals operator
95           */
96          if (left != null && right != null &&
97              (left.getClass().isAssignableFrom(right.getClass()) ||
98               right.getClass().isAssignableFrom(left.getClass())))
99          {
100             return !left.equals( right );
101         }
102 
103         /*
104          * Ok, time to compare string values
105          */
106         left = (left == null) ? null : left.toString();
107         right = (right == null) ? null: right.toString();
108 
109         if (left == null && right == null)
110         {
111             if (log.isDebugEnabled())
112             {
113                 log.debug("Both right (" + getLiteral(false) + " and left "
114                           + getLiteral(true) + " sides of '!=' operation returned null."
115                           + "If references, they may not be in the context."
116                           + getLocation(context));
117             }
118             return false;
119         }
120         else if (left == null || right == null)
121         {
122             if (log.isDebugEnabled())
123             {
124                 log.debug((left == null ? "Left" : "Right")
125                         + " side (" + getLiteral(left == null)
126                         + ") of '!=' operation has null value. If it is a "
127                         + "reference, it may not be in the context or its "
128                         + "toString() returned null. " + getLocation(context));
129 
130             }
131             return true;
132         }
133         else
134         {
135             return !left.equals(right);
136         }
137     }
138 
139     private String getLiteral(boolean left)
140     {
141         return jjtGetChild(left ? 0 : 1).literal();
142     }
143 
144     /**
145      * @see org.apache.velocity.runtime.parser.node.SimpleNode#value(org.apache.velocity.context.InternalContextAdapter)
146      */
147     public Object value(InternalContextAdapter context)
148         throws MethodInvocationException
149     {
150         boolean val = evaluate(context);
151 
152         return val ? Boolean.TRUE : Boolean.FALSE;
153     }
154 
155 }