From f58e107ff563b5a229920b70f7bf43053b8ed225 Mon Sep 17 00:00:00 2001 From: moparisthebest Date: Wed, 8 Nov 2017 23:21:40 -0500 Subject: [PATCH] Look at all implemented classes for methods+fields in JdbcMapperProcessor --- .../codegen/CompileTimeRowToObjectMapper.java | 85 +++++++++++-------- .../jdbc/codegen/JdbcMapperProcessor.java | 15 +++- 2 files changed, 61 insertions(+), 39 deletions(-) diff --git a/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/CompileTimeRowToObjectMapper.java b/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/CompileTimeRowToObjectMapper.java index f3fe057..f62b632 100644 --- a/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/CompileTimeRowToObjectMapper.java +++ b/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/CompileTimeRowToObjectMapper.java @@ -140,6 +140,14 @@ public class CompileTimeRowToObjectMapper { } } + public static List getAllImplementedTypes(final DeclaredType type, final List ret) { + ret.add(type); + for(final TypeMirror tm : JdbcMapperProcessor.getTypes().directSupertypes(type)) + if(tm.getKind() == TypeKind.DECLARED && !tm.toString().equals("java.lang.Object")) + getAllImplementedTypes((DeclaredType) tm, ret); + return ret; + } + /** * Build the structures necessary to do the mapping * @@ -172,49 +180,52 @@ public class CompileTimeRowToObjectMapper { mapFields.put(keys[i], null); } - // public methods todo: does this do super methods too? - for (Element e : ((TypeElement)declaredReturnType.asElement()).getEnclosedElements()) { - if(e.getKind() != ElementKind.METHOD) - continue; - final ExecutableElement m = (ExecutableElement)e; - //System.out.printf("method: '%s', isSetterMethod: '%s'\n", m, isSetterMethod(m)); - if (isSetterMethod(m)) { - String fieldName = m.getSimpleName().toString().substring(3).toUpperCase(); - //System.out.println("METHOD-fieldName1: "+fieldName); - if (!mapFields.containsKey(fieldName)) { - fieldName = strippedKeys.get(fieldName); - if (fieldName == null) - continue; - //System.out.println("METHOD-fieldName2: "+fieldName); - } - final Element field = mapFields.get(fieldName); - // check for overloads - if (field == null) { - mapFields.put(fieldName, m); - } else { - // todo: does this work? - // fix for 'overloaded' methods when it comes to stripped keys, we want the exact match - final String thisName = m.getSimpleName().toString().substring(3).toUpperCase(); - final String previousName = field.getSimpleName().toString().substring(3).toUpperCase(); - //System.out.printf("thisName: '%s', previousName: '%s', mapFields.containsKey(thisName): %b, strippedKeys.containsKey(previousName): %b\n", thisName, previousName, mapFields.containsKey(thisName), strippedKeys.containsKey(previousName)); - if(mapFields.containsKey(thisName) && strippedKeys.containsKey(previousName)) { - mapFields.put(fieldName, m); - } else if (!mapFields.containsKey(previousName) || !strippedKeys.containsKey(thisName)) { - throw new MapperException("Unable to choose between overloaded methods '" + m.getSimpleName().toString() - + "' and '" + field.getSimpleName().toString() + "' for field '" + fieldName + "' on the '" + _returnTypeClass.toString() + "' class. Mapping is done using " - + "a case insensitive comparison of SQL ResultSet columns to field " - + "names and public setter methods on the return class. Columns are also " - + "stripped of '_' and compared if no match is found with them."); + final List allTypes = getAllImplementedTypes(declaredReturnType, new ArrayList<>()); + + // public methods + // have to loop to get super methods too + for (final DeclaredType clazz : allTypes) { + for (Element e : ((TypeElement) clazz.asElement()).getEnclosedElements()) { + if (e.getKind() != ElementKind.METHOD) + continue; + final ExecutableElement m = (ExecutableElement) e; + //System.out.printf("method: '%s', isSetterMethod: '%s'\n", m, isSetterMethod(m)); + if (isSetterMethod(m)) { + String fieldName = m.getSimpleName().toString().substring(3).toUpperCase(); + //System.out.println("METHOD-fieldName1: "+fieldName); + if (!mapFields.containsKey(fieldName)) { + fieldName = strippedKeys.get(fieldName); + if (fieldName == null) + continue; + //System.out.println("METHOD-fieldName2: "+fieldName); + } + final Element field = mapFields.get(fieldName); + // check for overloads + if (field == null) { + mapFields.put(fieldName, m); + } else { + // todo: does this work? + // fix for 'overloaded' methods when it comes to stripped keys, we want the exact match + final String thisName = m.getSimpleName().toString().substring(3).toUpperCase(); + final String previousName = field.getSimpleName().toString().substring(3).toUpperCase(); + //System.out.printf("thisName: '%s', previousName: '%s', mapFields.containsKey(thisName): %b, strippedKeys.containsKey(previousName): %b\n", thisName, previousName, mapFields.containsKey(thisName), strippedKeys.containsKey(previousName)); + if (mapFields.containsKey(thisName) && strippedKeys.containsKey(previousName)) { + mapFields.put(fieldName, m); + } else if (!mapFields.containsKey(previousName) || !strippedKeys.containsKey(thisName)) { + throw new MapperException("Unable to choose between overloaded methods '" + m.getSimpleName().toString() + + "' and '" + field.getSimpleName().toString() + "' for field '" + fieldName + "' on the '" + _returnTypeClass.toString() + "' class. Mapping is done using " + + "a case insensitive comparison of SQL ResultSet columns to field " + + "names and public setter methods on the return class. Columns are also " + + "stripped of '_' and compared if no match is found with them."); + } + // then the 'overloaded' method is already correct } - // then the 'overloaded' method is already correct } } } // fix for 8813: include inherited and non-public fields - for (DeclaredType clazz = declaredReturnType; clazz != null && !clazz.toString().equals("java.lang.Object"); - clazz = clazz.getEnclosingType().getKind() == TypeKind.DECLARED ? (DeclaredType)clazz.getEnclosingType() : null - ) { + for (final DeclaredType clazz : allTypes) { //System.out.println("fields in class: "+Arrays.toString(classFields)); for (Element e : ((TypeElement)clazz.asElement()).getEnclosedElements()) { if(e.getKind() != ElementKind.FIELD) diff --git a/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/JdbcMapperProcessor.java b/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/JdbcMapperProcessor.java index a0f1d40..740e8c6 100644 --- a/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/JdbcMapperProcessor.java +++ b/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/JdbcMapperProcessor.java @@ -32,7 +32,17 @@ public class JdbcMapperProcessor extends AbstractProcessor { private static final Pattern paramPattern = Pattern.compile("\\{(([^\\s]+)\\s+(([Nn][Oo][Tt]\\s+)?[Ii][Nn]\\s+))?([^}]+)\\}"); - private Types types; + private static Types types; + private static Messager messager; + + public static Types getTypes() { + return types; + } + + public static Messager getMessager() { + return messager; + } + private TypeMirror sqlExceptionType, stringType, numberType, utilDateType, readerType, clobType, byteArrayType, inputStreamType, fileType, blobType, sqlArrayType, collectionType, calendarType, cleanerType; //IFJAVA8_START @@ -51,7 +61,8 @@ public class JdbcMapperProcessor extends AbstractProcessor { @Override public synchronized void init(final ProcessingEnvironment processingEnv) { super.init(processingEnv); - this.types = processingEnv.getTypeUtils(); + types = processingEnv.getTypeUtils(); + messager = processingEnv.getMessager(); final Elements elements = processingEnv.getElementUtils(); sqlExceptionType = elements.getTypeElement(SQLException.class.getCanonicalName()).asType(); stringType = elements.getTypeElement(String.class.getCanonicalName()).asType();