View Javadoc
1   /*
2    * Copyright 2002-2014 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.expression.spel.ast;
18  
19  import java.util.ArrayList;
20  import java.util.LinkedList;
21  import java.util.List;
22  
23  import org.springframework.expression.PropertyAccessor;
24  
25  /**
26   * Utilities methods for use in the Ast classes.
27   *
28   * @author Andy Clement
29   * @since 3.0.2
30   */
31  public abstract class AstUtils {
32  
33  	/**
34  	 * Determines the set of property resolvers that should be used to try and access a
35  	 * property on the specified target type. The resolvers are considered to be in an
36  	 * ordered list, however in the returned list any that are exact matches for the input
37  	 * target type (as opposed to 'general' resolvers that could work for any type) are
38  	 * placed at the start of the list. In addition, there are specific resolvers that
39  	 * exactly name the class in question and resolvers that name a specific class but it
40  	 * is a supertype of the class we have. These are put at the end of the specific resolvers
41  	 * set and will be tried after exactly matching accessors but before generic accessors.
42  	 * @param targetType the type upon which property access is being attempted
43  	 * @return a list of resolvers that should be tried in order to access the property
44  	 */
45  	public static List<PropertyAccessor> getPropertyAccessorsToTry(
46  			Class<?> targetType, List<PropertyAccessor> propertyAccessors) {
47  
48  		List<PropertyAccessor> specificAccessors = new ArrayList<PropertyAccessor>();
49  		List<PropertyAccessor> generalAccessors = new ArrayList<PropertyAccessor>();
50  		for (PropertyAccessor resolver : propertyAccessors) {
51  			Class<?>[] targets = resolver.getSpecificTargetClasses();
52  			if (targets == null) {  // generic resolver that says it can be used for any type
53  				generalAccessors.add(resolver);
54  			}
55  			else {
56  				if (targetType != null) {
57  					int pos = 0;
58  					for (Class<?> clazz : targets) {
59  						if (clazz == targetType) {  // put exact matches on the front to be tried first?
60  							specificAccessors.add(pos++, resolver);
61  						}
62  						else if (clazz.isAssignableFrom(targetType)) {  // put supertype matches at the end of the
63  							// specificAccessor list
64  							generalAccessors.add(resolver);
65  						}
66  					}
67  				}
68  			}
69  		}
70  		List<PropertyAccessor> resolvers = new LinkedList<PropertyAccessor>();
71  		resolvers.addAll(specificAccessors);
72  		resolvers.addAll(generalAccessors);
73  		return resolvers;
74  	}
75  
76  }