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: ASTOr.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 ASTOr
031 extends BooleanExpression
032 {
033 public ASTOr( int id )
034 {
035 super( id );
036 }
037
038 public ASTOr( OgnlParser p, int id )
039 {
040 super( p, id );
041 }
042
043 public void jjtClose()
044 {
045 flattenTree();
046 }
047
048 protected Object getValueBody( OgnlContext context, Object source )
049 throws OgnlException
050 {
051 Object result = null;
052 int last = children.length - 1;
053 for ( int i = 0; i <= last; ++i )
054 {
055 result = children[i].getValue( context, source );
056 if ( i != last && OgnlOps.booleanValue( result ) )
057 {
058 break;
059 }
060 }
061 return result;
062 }
063
064 protected void setValueBody( OgnlContext context, Object target, Object value )
065 throws OgnlException
066 {
067 int last = children.length - 1;
068 for ( int i = 0; i < last; ++i )
069 {
070 Object v = children[i].getValue( context, target );
071 if ( OgnlOps.booleanValue( v ) )
072 {
073 return;
074 }
075 }
076 children[last].setValue( context, target, value );
077 }
078
079 public String getExpressionOperator( int index )
080 {
081 return "||";
082 }
083
084 public Class getGetterClass()
085 {
086 return null;
087 }
088
089 public String toGetSourceString( OgnlContext context, Object target )
090 {
091 if ( children.length != 2 )
092 {
093 throw new UnsupportedCompilationException( "Can only compile boolean expressions with two children." );
094 }
095
096 String result = "(";
097
098 try
099 {
100
101 String first = OgnlRuntime.getChildSource( context, target, children[0] );
102 if ( !OgnlRuntime.isBoolean( first ) )
103 {
104 first = OgnlRuntime.getCompiler( context ).createLocalReference( context, first, context.getCurrentType() );
105 }
106
107 Class firstType = context.getCurrentType();
108
109 String second = OgnlRuntime.getChildSource( context, target, children[1] );
110 if ( !OgnlRuntime.isBoolean( second ) )
111 {
112 second = OgnlRuntime.getCompiler( context ).createLocalReference( context, second, context.getCurrentType() );
113 }
114
115 Class secondType = context.getCurrentType();
116
117 boolean mismatched =
118 ( firstType.isPrimitive( ) && !secondType.isPrimitive( ) ) || ( !firstType.isPrimitive( )
119 && secondType.isPrimitive( ) );
120
121 result += "org.apache.commons.ognl.OgnlOps.booleanValue(" + first + ")";
122
123 result += " ? ";
124
125 result += ( mismatched ? " ($w) " : "" ) + first;
126
127 result += " : ";
128
129 result += ( mismatched ? " ($w) " : "" ) + second;
130
131 result += ")";
132
133 context.setCurrentObject( target );
134 context.setCurrentType( Boolean.TYPE );
135
136 }
137 catch ( Throwable t )
138 {
139 throw OgnlOps.castToRuntime( t );
140 }
141
142 return result;
143 }
144
145 public String toSetSourceString( OgnlContext context, Object target )
146 {
147 if ( children.length != 2 )
148 {
149 throw new UnsupportedCompilationException( "Can only compile boolean expressions with two children." );
150 }
151
152 String pre = (String) context.get( "_currentChain" );
153 if ( pre == null )
154 {
155 pre = "";
156 }
157
158 String result = "";
159
160 try
161 {
162
163 children[0].getValue( context, target );
164
165 String first =
166 ExpressionCompiler.getRootExpression( children[0], context.getRoot(), context ) + pre
167 + children[0].toGetSourceString( context, target );
168 if ( !OgnlRuntime.isBoolean( first ) )
169 {
170 first = OgnlRuntime.getCompiler( context ).createLocalReference( context, first, Object.class );
171 }
172 children[1].getValue( context, target );
173
174 String second =
175 ExpressionCompiler.getRootExpression( children[1], context.getRoot(), context ) + pre
176 + children[1].toSetSourceString( context, target );
177 if ( !OgnlRuntime.isBoolean( second ) )
178 {
179 second = OgnlRuntime.getCompiler( context ).createLocalReference( context, second, context.getCurrentType() );
180 }
181 result += "org.apache.commons.ognl.OgnlOps.booleanValue(" + first + ")";
182
183 result += " ? ";
184
185 result += first;
186 result += " : ";
187
188 result += second;
189
190 context.setCurrentObject( target );
191
192 context.setCurrentType( Boolean.TYPE );
193
194 }
195 catch ( Throwable t )
196 {
197 throw OgnlOps.castToRuntime( t );
198 }
199
200 return result;
201 }
202
203 public <R, P> R accept( NodeVisitor<? extends R, ? super P> visitor, P data )
204 throws OgnlException
205 {
206 return visitor.visit( this, data );
207 }
208 }