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 }