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.OgnlExpressionCompiler;
024    import org.apache.commons.ognl.enhance.UnsupportedCompilationException;
025    
026    import java.util.ArrayList;
027    import java.util.List;
028    
029    /**
030     * $Id: ASTList.java 1194869 2011-10-29 11:10:16Z mcucchiara $
031     * @author Luke Blanshard (blanshlu@netscape.net)
032     * @author Drew Davidson (drew@ognl.org)
033     */
034    public class ASTList
035        extends SimpleNode
036        implements NodeType
037    {
038        public ASTList( int id )
039        {
040            super( id );
041        }
042    
043        public ASTList( OgnlParser p, int id )
044        {
045            super( p, id );
046        }
047    
048        protected Object getValueBody( OgnlContext context, Object source )
049            throws OgnlException
050        {
051            List answer = new ArrayList( jjtGetNumChildren() );
052            for ( int i = 0; i < jjtGetNumChildren(); ++i )
053            {
054                answer.add( children[i].getValue( context, source ) );
055            }
056            return answer;
057        }
058    
059        public Class getGetterClass()
060        {
061            return null;
062        }
063    
064        public Class getSetterClass()
065        {
066            return null;
067        }
068    
069        public String toGetSourceString( OgnlContext context, Object target )
070        {
071            String result = "";
072            boolean array = false;
073    
074            if ( parent != null && ASTCtor.class.isInstance( parent ) && ( (ASTCtor) parent ).isArray() )
075            {
076    
077                array = true;
078            }
079    
080            context.setCurrentType( List.class );
081            context.setCurrentAccessor( List.class );
082    
083            if ( !array )
084            {
085                if ( jjtGetNumChildren() < 1 )
086                {
087                    return "java.util.Arrays.asList( new Object[0])";
088                }
089                result += "java.util.Arrays.asList( new Object[] ";
090            }
091    
092            result += "{ ";
093    
094            try
095            {
096    
097                for ( int i = 0; i < jjtGetNumChildren(); ++i )
098                {
099                    if ( i > 0 )
100                    {
101                        result = result + ", ";
102                    }
103    
104                    Class prevType = context.getCurrentType();
105    
106                    Object objValue = children[i].getValue( context, context.getRoot() );
107                    String value = children[i].toGetSourceString( context, target );
108    
109                    // to undo type setting of constants when used as method parameters
110                    if ( ASTConst.class.isInstance( children[i] ) )
111                    {
112    
113                        context.setCurrentType( prevType );
114                    }
115    
116                    value = ExpressionCompiler.getRootExpression( children[i], target, context ) + value;
117    
118                    String cast = "";
119                    if ( ExpressionCompiler.shouldCast( children[i] ) )
120                    {
121    
122                        cast = (String) context.remove( ExpressionCompiler.PRE_CAST );
123                    }
124                    if ( cast == null )
125                    {
126                        cast = "";
127                    }
128                    
129                    if ( !ASTConst.class.isInstance( children[i] ) )
130                    {
131                        value = cast + value;
132                    }
133                    Class ctorClass = (Class) context.get( "_ctorClass" );
134                    if ( array && ctorClass != null && !ctorClass.isPrimitive() )
135                    {
136    
137                        Class valueClass = value != null ? value.getClass() : null;
138                        if ( NodeType.class.isAssignableFrom( children[i].getClass() ) )
139                        {
140                            valueClass = ( (NodeType) children[i] ).getGetterClass();
141                        }
142                        final OgnlExpressionCompiler compiler = OgnlRuntime.getCompiler( context );
143                        if ( valueClass != null && ctorClass.isArray() )
144                        {
145    
146                            value =
147                                compiler
148                                    .createLocalReference( context, "(" + ExpressionCompiler.getCastString( ctorClass )
149                                        + ")org.apache.commons.ognl.OgnlOps.toArray(" + value + ", "
150                                        + ctorClass.getComponentType().getName() + ".class, true)", ctorClass );
151    
152                        }
153                        else if ( ctorClass.isPrimitive() )
154                        {
155    
156                            Class wrapClass = OgnlRuntime.getPrimitiveWrapperClass( ctorClass );
157    
158                            value =
159                                compiler
160                                    .createLocalReference( context, "((" + wrapClass.getName()
161                                        + ")org.apache.commons.ognl.OgnlOps.convertValue(" + value + ","
162                                        + wrapClass.getName() + ".class, true))." + OgnlRuntime.getNumericValueGetter(
163                                        wrapClass ), ctorClass );
164                        }
165                        else if ( ctorClass != Object.class )
166                        {
167    
168                            value =
169                                compiler
170                                    .createLocalReference( context, "(" + ctorClass.getName()
171                                        + ")org.apache.commons.ognl.OgnlOps.convertValue(" + value + ","
172                                        + ctorClass.getName() + ".class)", ctorClass );
173    
174                        }
175                        else if ( ( NodeType.class.isInstance( children[i] )
176                            && ( (NodeType) children[i] ).getGetterClass() != null
177                            && Number.class.isAssignableFrom( ( (NodeType) children[i] ).getGetterClass() ) )
178                            || valueClass.isPrimitive() )
179                        {
180    
181                            value = " ($w) (" + value + ")";
182                        }
183                        else if ( valueClass.isPrimitive() )
184                        {
185                            value = "($w) (" + value + ")";
186                        }
187    
188                    }
189                    else if ( ctorClass == null || !ctorClass.isPrimitive() )
190                    {
191    
192                        value = " ($w) (" + value + ")";
193                    }
194    
195                    if ( objValue == null || value.length() <= 0 )
196                    {
197                        value = "null";
198                    }
199                    result += value;
200                }
201    
202            }
203            catch ( Throwable t )
204            {
205                throw OgnlOps.castToRuntime( t );
206            }
207    
208            context.setCurrentType( List.class );
209            context.setCurrentAccessor( List.class );
210    
211            result += "}";
212    
213            if ( !array )
214            {
215                result += ")";
216            }
217            return result;
218        }
219    
220        public String toSetSourceString( OgnlContext context, Object target )
221        {
222            throw new UnsupportedCompilationException( "Can't generate setter for ASTList." );
223        }
224        
225        public <R, P> R accept( NodeVisitor<? extends R, ? super P> visitor, P data )
226            throws OgnlException
227        {
228            return visitor.visit( this, data );
229        }
230    }