View Javadoc

1   package org.apache.commons.ognl;
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.commons.ognl.enhance.ExpressionCompiler;
23  import org.apache.commons.ognl.enhance.UnsupportedCompilationException;
24  
25  /**
26   * $Id: ASTAnd.java 1194869 2011-10-29 11:10:16Z mcucchiara $
27   * @author Luke Blanshard (blanshlu@netscape.net)
28   * @author Drew Davidson (drew@ognl.org)
29   */
30  public class ASTAnd
31      extends BooleanExpression
32  {
33      /** Serial */
34      private static final long serialVersionUID = -4585941425250141812L;
35  
36      /**
37       * TODO: javadoc
38       * @param id the id
39       */
40      public ASTAnd( int id )
41      {
42          super( id );
43      }
44  
45      /**
46       * TODO: javadoc
47       * @param p the parser
48       * @param id the id
49       */
50      public ASTAnd( OgnlParser p, int id )
51      {
52          super( p, id );
53      }
54  
55      /* (non-Javadoc)
56       * @see org.apache.commons.ognl.SimpleNode#jjtClose()
57       */
58      public void jjtClose()
59      {
60          flattenTree();
61      }
62  
63      /* (non-Javadoc)
64       * @see org.apache.commons.ognl.SimpleNode#getValueBody(org.apache.commons.ognl.OgnlContext, java.lang.Object)
65       */
66      protected Object getValueBody( OgnlContext context, Object source )
67          throws OgnlException
68      {
69          Object result = null;
70          int last = children.length - 1;
71          for ( int i = 0; i <= last; ++i )
72          {
73              result = children[i].getValue( context, source );
74  
75              if ( i != last && !OgnlOps.booleanValue( result ) )
76              {
77                  break;
78              }
79          }
80  
81          return result;
82      }
83  
84      /* (non-Javadoc)
85       * @see org.apache.commons.ognl.SimpleNode#setValueBody(org.apache.commons.ognl.OgnlContext, java.lang.Object, java.lang.Object)
86       */
87      protected void setValueBody( OgnlContext context, Object target, Object value )
88          throws OgnlException
89      {
90          int last = children.length - 1;
91  
92          for ( int i = 0; i < last; ++i )
93          {
94              Object v = children[i].getValue( context, target );
95  
96              if ( !OgnlOps.booleanValue( v ) )
97              {
98                  return;
99              }
100         }
101 
102         children[last].setValue( context, target, value );
103     }
104 
105     /* (non-Javadoc)
106      * @see org.apache.commons.ognl.ExpressionNode#getExpressionOperator(int)
107      */
108     public String getExpressionOperator( int index )
109     {
110         return "&&";
111     }
112 
113     /* (non-Javadoc)
114      * @see org.apache.commons.ognl.BooleanExpression#getGetterClass()
115      */
116     public Class getGetterClass()
117     {
118         return null;
119     }
120 
121     /* (non-Javadoc)
122      * @see org.apache.commons.ognl.BooleanExpression#toGetSourceString(org.apache.commons.ognl.OgnlContext, java.lang.Object)
123      */
124     public String toGetSourceString( OgnlContext context, Object target )
125     {
126         if ( children.length != 2 )
127         {
128             throw new UnsupportedCompilationException(
129                 "Can only compile boolean expressions with two children." );
130         }
131 
132         String result = "";
133 
134         try
135         {
136 
137             String first = OgnlRuntime.getChildSource( context, target, children[0] );
138             if ( !OgnlOps.booleanValue( context.getCurrentObject() ) )
139             {
140                 throw new UnsupportedCompilationException(
141                     "And expression can't be compiled until all conditions are true." );
142             }
143 
144             if ( !OgnlRuntime.isBoolean( first ) && !context.getCurrentType().isPrimitive() )
145             {
146                 first = OgnlRuntime.getCompiler( context ).createLocalReference( context, first, context.getCurrentType() );
147             }
148 
149             String second = OgnlRuntime.getChildSource( context, target, children[1] );
150             if ( !OgnlRuntime.isBoolean( second ) && !context.getCurrentType().isPrimitive() )
151             {
152                 second = OgnlRuntime.getCompiler( context ).createLocalReference( context, second, context.getCurrentType() );
153             }
154 
155             result += "(org.apache.commons.ognl.OgnlOps.booleanValue(" + first + ")";
156 
157             result += " ? ";
158 
159             result += " ($w) (" + second + ")";
160             result += " : ";
161 
162             result += " ($w) (" + first + ")";
163 
164             result += ")";
165 
166             context.setCurrentObject( target );
167             context.setCurrentType( Object.class );
168         }
169         catch ( NullPointerException e )
170         {
171 
172             throw new UnsupportedCompilationException( "evaluation resulted in null expression." );
173         }
174         catch ( Throwable t )
175         {
176             throw OgnlOps.castToRuntime( t );
177         }
178 
179         return result;
180     }
181 
182     /* (non-Javadoc)
183      * @see org.apache.commons.ognl.ExpressionNode#toSetSourceString(org.apache.commons.ognl.OgnlContext, java.lang.Object)
184      */
185     public String toSetSourceString( OgnlContext context, Object target )
186     {
187         if ( children.length != 2 )
188         {
189             throw new UnsupportedCompilationException( "Can only compile boolean expressions with two children." );
190         }
191 
192         String pre = (String) context.get( "_currentChain" );
193         if ( pre == null )
194         {
195             pre = "";
196         }
197 
198         String result = "";
199 
200         try
201         {
202 
203             if ( !OgnlOps.booleanValue( children[0].getValue( context, target ) ) )
204             {
205                 throw new UnsupportedCompilationException(
206                     "And expression can't be compiled until all conditions are true." );
207             }
208 
209             String first =
210                 ExpressionCompiler.getRootExpression( children[0], context.getRoot(), context ) + pre
211                     + children[0].toGetSourceString( context, target );
212 
213             children[1].getValue( context, target );
214 
215             String second =
216                 ExpressionCompiler.getRootExpression( children[1], context.getRoot(), context ) + pre
217                     + children[1].toSetSourceString( context, target );
218 
219             if ( !OgnlRuntime.isBoolean( first ) )
220             {
221                 result += "if(org.apache.commons.ognl.OgnlOps.booleanValue(" + first + ")){";
222             }
223             else
224             {
225                 result += "if(" + first + "){";
226             }
227 
228             result += second;
229             result += "; } ";
230 
231             context.setCurrentObject( target );
232             context.setCurrentType( Object.class );
233 
234         }
235         catch ( Throwable t )
236         {
237             throw OgnlOps.castToRuntime( t );
238         }
239 
240         return result;
241     }
242     
243     /* (non-Javadoc)
244      * @see org.apache.commons.ognl.Node#accept(org.apache.commons.ognl.NodeVisitor, java.lang.Object)
245      */
246     public <R, P> R accept( NodeVisitor<? extends R, ? super P> visitor, P data )
247         throws OgnlException
248     {
249         return visitor.visit( this, data );
250     }
251 }