/* Copyright (c) 2009-2011 Olivier Chafik, All Rights Reserved This file is part of JNAerator (http://jnaerator.googlecode.com/). JNAerator is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. JNAerator is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with JNAerator. If not, see <http://www.gnu.org/licenses/>. */ package com.ochafik.lang.reflect; //import static org.junit.Assert.assertNull; //import static org.junit.Assert.assertTrue; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import java.util.regex.Pattern; import com.ochafik.util.string.RegexUtils; import com.ochafik.util.string.StringUtils; public class GettersAndSettersHelper { public static class GetterAndSetterInfo { public Method getter; public Method setter; //public Field field; public String fieldName; public boolean isFull() { return getter != null && setter != null; } public Class<?> elementType; public GetterAndSetterInfo(String fieldName, Class<?> elementType, Method getter, Method setter, Field field) { this.elementType = elementType; this.fieldName = fieldName; this.getter = getter; this.setter = setter; //this.field = field; } public GetterAndSetterInfo() {} public boolean isConsistent() { if (getter == null || setter == null) return true; Class<?>[] pts = setter.getParameterTypes(); if (pts.length != 1) return false; Class<?> pt = pts[0]; if (!pt.isAssignableFrom(getter.getReturnType())) { //System.out.println("Setter with " + pt.getName() + " not consistent with getter returning " + getter.getReturnType().getName()); return false; } return true; } } public final Map<String, GetterAndSetterInfo> gettersAndSetters = new LinkedHashMap<String, GetterAndSetterInfo>(); static Pattern getterSetterPattern = Pattern.compile("(is|get|set)([A-Z]\\w+)"); public GettersAndSettersHelper(Class<?> type, FieldGetter fieldGetter) { this.fieldGetter = fieldGetter; for (Method method : type.getMethods()) { int nParams = method.getParameterTypes().length; if (nParams > 1) continue; String name = method.getName(); String match[] = RegexUtils.match(name, getterSetterPattern); if (match != null) { Class<?> returnType = method.getReturnType(); String fieldName = StringUtils.uncapitalize(match[2]); boolean isGetter = !match[1].equals("set"); if (isGetter) { if (nParams == 0) { GetterAndSetterInfo getterAndSetter = getOrCreatePair(fieldName); if (getterAndSetter.getter != null) { if (getterAndSetter.getter.getReturnType().isAssignableFrom(returnType)) { // refinement getterAndSetter.getter = method; } } else { getterAndSetter.getter = method; } if (!getterAndSetter.isConsistent()) getterAndSetter.setter = null; } //assertNull("Already found getter " + getterAndSetter.getter, getterAndSetter.getter); //getterAndSetter.setFirst(method); } else if (nParams == 1) { GetterAndSetterInfo getterAndSetter = getOrCreatePair(fieldName); //assertNull("Already found setter " + getterAndSetter.setter, getterAndSetter.setter); //assert getterAndSetter.setter == null; if (getterAndSetter.setter == null) { getterAndSetter.setter = method; if (!getterAndSetter.isConsistent()) getterAndSetter.setter = null; } } } } /* for (Map.Entry<String, GetterAndSetterInfo> e : gettersAndSetters.entrySet()) { if (e.getValue().setter == null) continue; try { e.getValue().field = fieldGetter == null ? type.getField(e.getKey()) : fieldGetter.getField(type, e.getKey()); } catch (Exception ex) { assertTrue("Failed to find field '" + e.getKey() + "' in " + type.getName(), false); } }*/ /*for (Field field : type.getFields()) { GetterAndSetterInfo info = gettersAndSetters.get(field.getName()); if (info == null) continue; info.field = field; }*/ } final FieldGetter fieldGetter; public interface FieldGetter { public Field getField(Class<?> c, String name) throws SecurityException, NoSuchFieldException; } public Set<String> getFieldNames() { return gettersAndSetters.keySet(); } public Method getGetter(String fieldName) { GetterAndSetterInfo pair = gettersAndSetters.get(fieldName); return pair == null ? null : pair.getter; } public Method getSetter(String fieldName) { GetterAndSetterInfo pair = gettersAndSetters.get(fieldName); return pair == null ? null : pair.setter; } public Type getFieldType(String fieldName) { GetterAndSetterInfo pair = gettersAndSetters.get(fieldName); if (pair == null) return null; if (pair.getter != null) return pair.getter.getGenericReturnType(); if (pair.setter != null) return pair.setter.getGenericParameterTypes()[0]; return null; } public void assertConsistentPair(GetterAndSetterInfo p) { if (p.getter != null && p.setter != null) { Class<?> getType = p.getter.getReturnType(), setType = p.setter.getParameterTypes()[0]; //assertTrue("Setter argument cannot be given getter result", setType.isAssignableFrom(getType)); assert setType.isAssignableFrom(getType); } } protected GetterAndSetterInfo getOrCreatePair(String fieldName) { GetterAndSetterInfo getterAndSetter = gettersAndSetters.get(fieldName); if (getterAndSetter == null) gettersAndSetters.put(fieldName, getterAndSetter = new GetterAndSetterInfo()); return getterAndSetter; } }