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