View Javadoc

1   /*
2   	Copyright (c) 2009 Olivier Chafik, All Rights Reserved
3   	
4   	This file is part of JNAerator (http://jnaerator.googlecode.com/).
5   	
6   	JNAerator is free software: you can redistribute it and/or modify
7   	it under the terms of the GNU General Public License as published by
8   	the Free Software Foundation, either version 3 of the License, or
9   	(at your option) any later version.
10  	
11  	JNAerator is distributed in the hope that it will be useful,
12  	but WITHOUT ANY WARRANTY; without even the implied warranty of
13  	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  	GNU General Public License for more details.
15  	
16  	You should have received a copy of the GNU General Public License
17  	along with JNAerator.  If not, see <http://www.gnu.org/licenses/>.
18  */
19  package com.ochafik.lang.reflect;
20  
21  //import static org.junit.Assert.assertNull;
22  //import static org.junit.Assert.assertTrue;
23  
24  import java.lang.reflect.Field;
25  import java.lang.reflect.Method;
26  import java.lang.reflect.Type;
27  import java.util.HashMap;
28  import java.util.Map;
29  import java.util.Set;
30  import java.util.regex.Pattern;
31  
32  import com.ochafik.util.string.RegexUtils;
33  import com.ochafik.util.string.StringUtils;
34  
35  public class GettersAndSettersHelper {
36  	public static class GetterAndSetterInfo {
37  		public Method getter;
38  		public Method setter;
39  		//public Field field;
40  		public String fieldName;
41  		public boolean isFull() {
42  			return getter != null && setter != null;
43  		}
44  		public Class<?> elementType;
45  		public GetterAndSetterInfo(String fieldName, Class<?> elementType, Method getter, Method setter, Field field) {
46  			this.elementType = elementType;
47  			this.fieldName = fieldName;
48  			this.getter = getter;
49  			this.setter = setter;
50  			//this.field = field;
51  		}
52  		public GetterAndSetterInfo() {}
53  		public boolean isConsistent() {
54  			if (getter == null || setter == null)
55  				return true;
56  			
57  			Class<?>[] pts = setter.getParameterTypes();
58  			return pts.length == 1 && pts[0].isAssignableFrom(getter.getReturnType());
59  		}
60  	}
61  	
62  	public final Map<String, GetterAndSetterInfo> gettersAndSetters = new HashMap<String, GetterAndSetterInfo>();
63  	
64  	static Pattern getterSetterPattern = Pattern.compile("(is|get|set)([A-Z]\\w+)");
65  	
66  	public GettersAndSettersHelper(Class<?> type, FieldGetter fieldGetter) {
67  		this.fieldGetter = fieldGetter;
68  		for (Method method : type.getMethods()) {
69  			int nParams = method.getParameterTypes().length;
70  			if (nParams > 1)
71  				continue;
72  			
73  			String name = method.getName();
74  			String match[] = RegexUtils.match(name, getterSetterPattern);
75  			if (match != null) {
76  				Class<?> returnType = method.getReturnType();
77  				String fieldName = StringUtils.uncapitalize(match[2]);
78  				boolean isGetter = !match[1].equals("set");
79  				if (isGetter) {
80  					if (nParams == 0) {
81  						GetterAndSetterInfo getterAndSetter = getOrCreatePair(fieldName);
82  						if (getterAndSetter.getter != null) {
83  							if (getterAndSetter.getter.getReturnType().isAssignableFrom(returnType)) {
84  								// refinement
85  								getterAndSetter.getter = method;
86  							}
87  						} else {
88  							getterAndSetter.getter = method;
89  						}
90  
91  						if (!getterAndSetter.isConsistent())
92  							getterAndSetter.setter = null;
93  						
94  					}
95  					//assertNull("Already found getter " + getterAndSetter.getter, getterAndSetter.getter);
96  					//getterAndSetter.setFirst(method);
97  				} else if (nParams == 1) {
98  					GetterAndSetterInfo getterAndSetter = getOrCreatePair(fieldName);
99  					//assertNull("Already found setter " + getterAndSetter.setter, getterAndSetter.setter);
100 					//assert getterAndSetter.setter == null;
101 					getterAndSetter.setter = method;
102 					if (!getterAndSetter.isConsistent())
103 						getterAndSetter.setter = null;
104 				}
105 			}
106 		}
107 		/*
108 		for (Map.Entry<String, GetterAndSetterInfo> e : gettersAndSetters.entrySet()) {
109 			if (e.getValue().setter == null)
110 				continue;
111 			try {
112 				e.getValue().field = fieldGetter == null ? type.getField(e.getKey()) : fieldGetter.getField(type, e.getKey());
113 			} catch (Exception ex) {
114 				assertTrue("Failed to find field '" + e.getKey() + "' in " + type.getName(), false);
115 			}
116 		}*/
117 		/*for (Field field : type.getFields()) {
118 			GetterAndSetterInfo info = gettersAndSetters.get(field.getName());
119 			if (info == null)
120 				continue;
121 			info.field = field;
122 		}*/
123 	}
124 	final FieldGetter fieldGetter;
125 	public interface FieldGetter {
126 		public Field getField(Class<?> c, String name) throws SecurityException, NoSuchFieldException;
127 	}
128 	public Set<String> getFieldNames() {
129 		return gettersAndSetters.keySet();
130 	}
131 	public Method getGetter(String fieldName) {
132 		GetterAndSetterInfo pair = gettersAndSetters.get(fieldName);
133 		return pair == null ? null : pair.getter;
134 	}
135 	public Method getSetter(String fieldName) {
136 		GetterAndSetterInfo pair = gettersAndSetters.get(fieldName);
137 		return pair == null ? null : pair.setter;
138 	}
139 	public Type getFieldType(String fieldName) {
140 		GetterAndSetterInfo pair = gettersAndSetters.get(fieldName);
141 		if (pair == null)
142 			return null;
143 		if (pair.getter != null)
144 			return pair.getter.getGenericReturnType();
145 		if (pair.setter != null)
146 			return pair.setter.getGenericParameterTypes()[0];
147 		return null;
148 	}
149 	public void assertConsistentPair(GetterAndSetterInfo p) {
150 		if (p.getter != null && p.setter != null) {
151 			Class<?> getType = p.getter.getReturnType(),
152 				setType = p.setter.getParameterTypes()[0];
153 			
154 			//assertTrue("Setter argument cannot be given getter result", setType.isAssignableFrom(getType));
155 			assert setType.isAssignableFrom(getType);
156 		}
157 	}
158 	protected GetterAndSetterInfo getOrCreatePair(String fieldName) { 
159 		GetterAndSetterInfo getterAndSetter = gettersAndSetters.get(fieldName);
160 		if (getterAndSetter == null)
161 			gettersAndSetters.put(fieldName, getterAndSetter = new GetterAndSetterInfo());
162 		
163 		return getterAndSetter;
164 	}
165 }