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   *  @version $Id: ASTEQNode.java 517553 2007-03-13 06:09:58Z wglass $
36   */
37  public class ASTEQNode extends SimpleNode
38  {
39      /**
40       * @param id
41       */
42      public ASTEQNode(int id)
43      {
44          super(id);
45      }
46  
47      /**
48       * @param p
49       * @param id
50       */
51      public ASTEQNode(Parser p, int id)
52      {
53          super(p, id);
54      }
55  
56      /**
57       * @see org.apache.velocity.runtime.parser.node.SimpleNode#jjtAccept(org.apache.velocity.runtime.parser.node.ParserVisitor, java.lang.Object)
58       */
59      public Object jjtAccept(ParserVisitor visitor, Object data)
60      {
61          return visitor.visit(this, data);
62      }
63  
64      /**
65       *   Calculates the value of the logical expression
66       *
67       *     arg1 == arg2
68       *
69       *   All class types are supported.   Uses equals() to
70       *   determine equivalence.  This should work as we represent
71       *   with the types we already support, and anything else that
72       *   implements equals() to mean more than identical references.
73       *
74       *
75       *  @param context  internal context used to evaluate the LHS and RHS
76       *  @return true if equivalent, false if not equivalent,
77       *          false if not compatible arguments, or false
78       *          if either LHS or RHS is null
79       * @throws MethodInvocationException
80       */
81      public boolean evaluate(InternalContextAdapter context)
82          throws MethodInvocationException
83      {
84          Object left = jjtGetChild(0).value(context);
85          Object right = jjtGetChild(1).value(context);
86  
87          /*
88           *  they could be null if they are references and not in the context
89           */
90  
91          if (left == null || right == null)
92          {
93              log.error((left == null ? "Left" : "Right")
94                             + " side ("
95                             + jjtGetChild( (left == null? 0 : 1) ).literal()
96                             + ") of '==' operation "
97                             + "has null value. "
98                             + "If a reference, it may not be in the context."
99                             + " Operation not possible. "
100                            + context.getCurrentTemplateName() + " [line " + getLine()
101                            + ", column " + getColumn() + "]");
102             return false;
103         }
104 
105         /*
106          *  convert to Number if applicable
107          */
108         if (left instanceof TemplateNumber)
109         {
110            left = ( (TemplateNumber) left).getAsNumber();
111         }
112         if (right instanceof TemplateNumber)
113         {
114            right = ( (TemplateNumber) right).getAsNumber();
115         }
116 
117        /*
118         * If comparing Numbers we do not care about the Class.
119         */
120 
121        if (left instanceof Number && right instanceof Number)
122        {
123            return MathUtils.compare( (Number)left, (Number)right) == 0;
124        }
125 
126 
127 
128        /**
129         * assume that if one class is a subclass of the other
130         * that we should use the equals operator
131         */
132 
133         if (left.getClass().isAssignableFrom(right.getClass()) ||
134                 right.getClass().isAssignableFrom(left.getClass()) )
135         {
136             return left.equals( right );
137         }
138         else
139         {
140             /**
141              * Compare the String representations
142              */
143             if ((left.toString() == null) || (right.toString() == null))
144             {
145         	boolean culprit =  (left.toString() == null);
146                 log.error((culprit ? "Left" : "Right")
147                         + " string side "
148                         + "String representation ("
149                         + jjtGetChild((culprit ? 0 : 1) ).literal()
150                         + ") of '!=' operation has null value."
151                         + " Operation not possible. "
152                         + context.getCurrentTemplateName() + " [line " + getLine()
153                         + ", column " + getColumn() + "]");
154 
155                 return false;
156             }
157 
158             else
159             {
160                 return left.toString().equals(right.toString());
161             }
162         }
163 
164     }
165 
166     /**
167      * @see org.apache.velocity.runtime.parser.node.SimpleNode#value(org.apache.velocity.context.InternalContextAdapter)
168      */
169     public Object value(InternalContextAdapter context)
170         throws MethodInvocationException
171     {
172         return evaluate(context) ? Boolean.TRUE : Boolean.FALSE;
173     }
174 }