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    }