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    }