001 package org.apache.commons.ognl;
002
003 /*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements. See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership. The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License. You may obtain a copy of the License at
011 *
012 * http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied. See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022 import org.apache.commons.ognl.enhance.ExpressionCompiler;
023 import org.apache.commons.ognl.enhance.UnsupportedCompilationException;
024
025 /**
026 * $Id: ASTAnd.java 1194869 2011-10-29 11:10:16Z mcucchiara $
027 * @author Luke Blanshard (blanshlu@netscape.net)
028 * @author Drew Davidson (drew@ognl.org)
029 */
030 public class ASTAnd
031 extends BooleanExpression
032 {
033 /** Serial */
034 private static final long serialVersionUID = -4585941425250141812L;
035
036 /**
037 * TODO: javadoc
038 * @param id the id
039 */
040 public ASTAnd( int id )
041 {
042 super( id );
043 }
044
045 /**
046 * TODO: javadoc
047 * @param p the parser
048 * @param id the id
049 */
050 public ASTAnd( OgnlParser p, int id )
051 {
052 super( p, id );
053 }
054
055 /* (non-Javadoc)
056 * @see org.apache.commons.ognl.SimpleNode#jjtClose()
057 */
058 public void jjtClose()
059 {
060 flattenTree();
061 }
062
063 /* (non-Javadoc)
064 * @see org.apache.commons.ognl.SimpleNode#getValueBody(org.apache.commons.ognl.OgnlContext, java.lang.Object)
065 */
066 protected Object getValueBody( OgnlContext context, Object source )
067 throws OgnlException
068 {
069 Object result = null;
070 int last = children.length - 1;
071 for ( int i = 0; i <= last; ++i )
072 {
073 result = children[i].getValue( context, source );
074
075 if ( i != last && !OgnlOps.booleanValue( result ) )
076 {
077 break;
078 }
079 }
080
081 return result;
082 }
083
084 /* (non-Javadoc)
085 * @see org.apache.commons.ognl.SimpleNode#setValueBody(org.apache.commons.ognl.OgnlContext, java.lang.Object, java.lang.Object)
086 */
087 protected void setValueBody( OgnlContext context, Object target, Object value )
088 throws OgnlException
089 {
090 int last = children.length - 1;
091
092 for ( int i = 0; i < last; ++i )
093 {
094 Object v = children[i].getValue( context, target );
095
096 if ( !OgnlOps.booleanValue( v ) )
097 {
098 return;
099 }
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 }