Set in list type names in a smarter fashion

This commit is contained in:
Travis Burtrum 2017-06-02 01:59:17 -04:00
parent c1139447e4
commit f028853c15
2 changed files with 44 additions and 42 deletions

View File

@ -129,12 +129,5 @@ public interface JdbcMapper extends Closeable {
this.arrayNumberTypeName = arrayNumberTypeName; this.arrayNumberTypeName = arrayNumberTypeName;
this.arrayStringTypeName = arrayStringTypeName; this.arrayStringTypeName = arrayStringTypeName;
} }
public DatabaseType nonDefault(final DatabaseType def) {
if(this != DEFAULT)
return this;
//return def == DEFAULT ? STANDARD : def;
return def; // we guarantee this to be not DEFAULT in JdbcMapperProcessor
}
} }
} }

View File

@ -30,8 +30,7 @@ public class JdbcMapperProcessor extends AbstractProcessor {
private Types types; private Types types;
private TypeMirror sqlExceptionType, stringType, numberType, utilDateType, readerType, clobType, private TypeMirror sqlExceptionType, stringType, numberType, utilDateType, readerType, clobType,
byteArrayType, inputStreamType, fileType, blobType, sqlArrayType, collectionType byteArrayType, inputStreamType, fileType, blobType, sqlArrayType, collectionType;
;
private JdbcMapper.DatabaseType defaultDatabaseType; private JdbcMapper.DatabaseType defaultDatabaseType;
private String defaultArrayNumberTypeName, defaultArrayStringTypeName; private String defaultArrayNumberTypeName, defaultArrayStringTypeName;
@ -63,10 +62,10 @@ public class JdbcMapperProcessor extends AbstractProcessor {
final String databaseType = processingEnv.getOptions().get("JdbcMapper.databaseType"); final String databaseType = processingEnv.getOptions().get("JdbcMapper.databaseType");
defaultDatabaseType = databaseType == null ? JdbcMapper.DatabaseType.STANDARD : JdbcMapper.DatabaseType.valueOf(databaseType); defaultDatabaseType = databaseType == null ? JdbcMapper.DatabaseType.STANDARD : JdbcMapper.DatabaseType.valueOf(databaseType);
defaultArrayNumberTypeName = processingEnv.getOptions().get("JdbcMapper.arrayNumberTypeName"); defaultArrayNumberTypeName = processingEnv.getOptions().get("JdbcMapper.arrayNumberTypeName");
if(defaultArrayNumberTypeName == null || defaultArrayNumberTypeName.isEmpty()) if (defaultArrayNumberTypeName == null || defaultArrayNumberTypeName.isEmpty())
defaultArrayNumberTypeName = defaultDatabaseType.arrayNumberTypeName; defaultArrayNumberTypeName = defaultDatabaseType.arrayNumberTypeName;
defaultArrayStringTypeName = processingEnv.getOptions().get("JdbcMapper.arrayStringTypeName"); defaultArrayStringTypeName = processingEnv.getOptions().get("JdbcMapper.arrayStringTypeName");
if(defaultArrayStringTypeName == null || defaultArrayStringTypeName.isEmpty()) if (defaultArrayStringTypeName == null || defaultArrayStringTypeName.isEmpty())
defaultArrayStringTypeName = defaultDatabaseType.arrayStringTypeName; defaultArrayStringTypeName = defaultDatabaseType.arrayStringTypeName;
} }
@ -88,9 +87,19 @@ public class JdbcMapperProcessor extends AbstractProcessor {
} }
final TypeElement genClass = (TypeElement) element; final TypeElement genClass = (TypeElement) element;
final JdbcMapper.Mapper mapper = genClass.getAnnotation(JdbcMapper.Mapper.class); final JdbcMapper.Mapper mapper = genClass.getAnnotation(JdbcMapper.Mapper.class);
final JdbcMapper.DatabaseType databaseType = mapper.databaseType().nonDefault(defaultDatabaseType); final JdbcMapper.DatabaseType databaseType;
final String arrayNumberTypeName = !mapper.arrayNumberTypeName().isEmpty() ? mapper.arrayNumberTypeName() : defaultArrayNumberTypeName; final String arrayNumberTypeName, arrayStringTypeName;
final String arrayStringTypeName = !mapper.arrayStringTypeName().isEmpty() ? mapper.arrayStringTypeName() : defaultArrayStringTypeName; if (mapper.databaseType() == JdbcMapper.DatabaseType.DEFAULT) {
databaseType = defaultDatabaseType;
arrayNumberTypeName = !mapper.arrayNumberTypeName().isEmpty() ? mapper.arrayNumberTypeName() : defaultArrayNumberTypeName;
arrayStringTypeName = !mapper.arrayStringTypeName().isEmpty() ? mapper.arrayStringTypeName() : defaultArrayStringTypeName;
} else {
databaseType = mapper.databaseType();
arrayNumberTypeName = !mapper.arrayNumberTypeName().isEmpty() ? mapper.arrayNumberTypeName() :
(mapper.databaseType() == defaultDatabaseType ? defaultArrayNumberTypeName : mapper.databaseType().arrayNumberTypeName);
arrayStringTypeName = !mapper.arrayStringTypeName().isEmpty() ? mapper.arrayStringTypeName() :
(mapper.databaseType() == defaultDatabaseType ? defaultArrayStringTypeName : mapper.databaseType().arrayStringTypeName);
}
final String sqlParserMirror = getSqlParser(mapper).toString(); final String sqlParserMirror = getSqlParser(mapper).toString();
//final SQLParser parser = new SimpleSQLParser();//(SQLParser)Class.forName(mapper.sqlParser().getCanonicalName()).newInstance(); //final SQLParser parser = new SimpleSQLParser();//(SQLParser)Class.forName(mapper.sqlParser().getCanonicalName()).newInstance();
//final SQLParser parser = mapper.sqlParser().equals(SQLParser.class) ? new SimpleSQLParser() : mapper.sqlParser().newInstance(); //final SQLParser parser = mapper.sqlParser().equals(SQLParser.class) ? new SimpleSQLParser() : mapper.sqlParser().newInstance();
@ -179,8 +188,8 @@ public class JdbcMapperProcessor extends AbstractProcessor {
if (methodElement.getKind() != ElementKind.METHOD || !methodElement.getModifiers().contains(Modifier.ABSTRACT)) if (methodElement.getKind() != ElementKind.METHOD || !methodElement.getModifiers().contains(Modifier.ABSTRACT))
continue; continue;
final ExecutableElement eeMethod = (ExecutableElement) methodElement; final ExecutableElement eeMethod = (ExecutableElement) methodElement;
if(lookupCloseMethod) if (lookupCloseMethod)
if((closeMethod = getCloseMethod(eeMethod)) != null) { if ((closeMethod = getCloseMethod(eeMethod)) != null) {
lookupCloseMethod = false; lookupCloseMethod = false;
continue; // skip close method continue; // skip close method
} }
@ -245,7 +254,7 @@ public class JdbcMapperProcessor extends AbstractProcessor {
} }
unusedParams.remove(paramName); unusedParams.remove(paramName);
final String inColumnName = bindParamMatcher.group(2); final String inColumnName = bindParamMatcher.group(2);
if(inColumnName == null) { if (inColumnName == null) {
bindParams.add(bindParam); bindParams.add(bindParam);
bindParamMatcher.appendReplacement(sb, "?"); bindParamMatcher.appendReplacement(sb, "?");
} else { } else {
@ -273,7 +282,7 @@ public class JdbcMapperProcessor extends AbstractProcessor {
bindParamMatcher.appendTail(sb); bindParamMatcher.appendTail(sb);
sqlStatement = sb.toString(); sqlStatement = sb.toString();
for(final Map.Entry<String, VariableElement> unusedParam : unusedParams.entrySet()) { for (final Map.Entry<String, VariableElement> unusedParam : unusedParams.entrySet()) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, String.format("@JdbcMapper.SQL method has unused parameter '%s'", unusedParam.getKey()), unusedParam.getValue()); processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, String.format("@JdbcMapper.SQL method has unused parameter '%s'", unusedParam.getKey()), unusedParam.getValue());
} }
} }
@ -343,10 +352,10 @@ public class JdbcMapperProcessor extends AbstractProcessor {
} }
// look on super classes and interfaces recursively // look on super classes and interfaces recursively
if(lookupCloseMethod) if (lookupCloseMethod)
closeMethod = getCloseMethod(genClass); closeMethod = getCloseMethod(genClass);
if(closeMethod == null && (cachedPreparedStatements > 0 || doJndi)) { if (closeMethod == null && (cachedPreparedStatements > 0 || doJndi)) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@Jdbc.Mapper extended classes with cachedPreparedStatements or jndiNames must have a public void close() method to override or implement, because they must be closed", genClass); processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@Jdbc.Mapper extended classes with cachedPreparedStatements or jndiNames must have a public void close() method to override or implement, because they must be closed", genClass);
continue; continue;
} }
@ -361,7 +370,7 @@ public class JdbcMapperProcessor extends AbstractProcessor {
} }
// close method // close method
if(closeMethod != null) { if (closeMethod != null) {
// if cachedPreparedStatements > 0 or doJndi are true, class MUST have a close() method to override as it // if cachedPreparedStatements > 0 or doJndi are true, class MUST have a close() method to override as it
// MUST be called to clean up // MUST be called to clean up
w.write("\n\t@Override\n\tpublic void close() {\n"); w.write("\n\t@Override\n\tpublic void close() {\n");
@ -369,7 +378,7 @@ public class JdbcMapperProcessor extends AbstractProcessor {
w.write("\t\tfor(final PreparedStatement ps : psCache)\n\t\t\ttryClose(ps);\n"); w.write("\t\tfor(final PreparedStatement ps : psCache)\n\t\t\ttryClose(ps);\n");
if (doJndi) if (doJndi)
w.write("\t\ttryClose(ctx);\n\t\tif(ctx != null)\n\t\t\ttryClose(conn);\n"); w.write("\t\ttryClose(ctx);\n\t\tif(ctx != null)\n\t\t\ttryClose(conn);\n");
if(closeMethod.getEnclosingElement().getKind() != ElementKind.INTERFACE && !closeMethod.getEnclosingElement().equals(genClass)) if (closeMethod.getEnclosingElement().getKind() != ElementKind.INTERFACE && !closeMethod.getEnclosingElement().equals(genClass))
w.write("\t\tsuper.close();\n"); w.write("\t\tsuper.close();\n");
w.write("\t}\n"); w.write("\t}\n");
} }
@ -396,22 +405,22 @@ public class JdbcMapperProcessor extends AbstractProcessor {
String method = null; String method = null;
// special behavior // special behavior
if(param instanceof InListVariableElement) { if (param instanceof InListVariableElement) {
final boolean collection; final boolean collection;
final TypeMirror componentType; final TypeMirror componentType;
if(o.getKind() == TypeKind.ARRAY) { if (o.getKind() == TypeKind.ARRAY) {
collection = false; collection = false;
componentType = ((ArrayType)o).getComponentType(); componentType = ((ArrayType) o).getComponentType();
} else if(o.getKind() == TypeKind.DECLARED && types.isAssignable(o, collectionType)) { } else if (o.getKind() == TypeKind.DECLARED && types.isAssignable(o, collectionType)) {
collection = true; collection = true;
final DeclaredType dt = (DeclaredType)o; final DeclaredType dt = (DeclaredType) o;
if(dt.getTypeArguments().isEmpty()) { if (dt.getTypeArguments().isEmpty()) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@JdbcMapper.SQL in list syntax requires a Collection with a generic type parameter" +o.toString(), ((InListVariableElement)param).delegate); processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@JdbcMapper.SQL in list syntax requires a Collection with a generic type parameter" + o.toString(), ((InListVariableElement) param).delegate);
return; return;
} }
componentType = dt.getTypeArguments().get(0); componentType = dt.getTypeArguments().get(0);
} else { } else {
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@JdbcMapper.SQL in list syntax only valid on Collections or arrays" +o.toString(), ((InListVariableElement)param).delegate); processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@JdbcMapper.SQL in list syntax only valid on Collections or arrays" + o.toString(), ((InListVariableElement) param).delegate);
return; return;
} }
w.write("ps.setArray("); w.write("ps.setArray(");
@ -447,18 +456,18 @@ public class JdbcMapperProcessor extends AbstractProcessor {
w.write("conn.createArrayOf(\""); w.write("conn.createArrayOf(\"");
break; break;
default: default:
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "default DatabaseType? should never happen!!", ((InListVariableElement)param).delegate); processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "default DatabaseType? should never happen!!", ((InListVariableElement) param).delegate);
} }
w.write(type); w.write(type);
w.write("\", "); w.write("\", ");
w.write(variableName); w.write(variableName);
if(collection) if (collection)
w.write(".toArray()"); w.write(".toArray()");
w.write("));\n"); w.write("));\n");
return; return;
} }
final JdbcMapper.Blob blob = param.getAnnotation(JdbcMapper.Blob.class); final JdbcMapper.Blob blob = param.getAnnotation(JdbcMapper.Blob.class);
if(blob != null) { if (blob != null) {
if (types.isAssignable(o, stringType)) { if (types.isAssignable(o, stringType)) {
w.write("try {\n\t\t\t\tps.setBlob("); w.write("try {\n\t\t\t\tps.setBlob(");
w.write(Integer.toString(index)); w.write(Integer.toString(index));
@ -478,10 +487,10 @@ public class JdbcMapperProcessor extends AbstractProcessor {
} }
} else { } else {
final JdbcMapper.Clob clob = param.getAnnotation(JdbcMapper.Clob.class); final JdbcMapper.Clob clob = param.getAnnotation(JdbcMapper.Clob.class);
if(clob != null) { if (clob != null) {
if (types.isAssignable(o, stringType)) { if (types.isAssignable(o, stringType)) {
method = "Clob"; method = "Clob";
variableName = variableName + " == null ? null : new StringReader("+variableName+")"; variableName = variableName + " == null ? null : new StringReader(" + variableName + ")";
} else if (!(types.isAssignable(o, readerType) || types.isAssignable(o, clobType))) { } else if (!(types.isAssignable(o, readerType) || types.isAssignable(o, clobType))) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@JdbcMapper.Clob only valid for String, Clob, Reader", param); processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@JdbcMapper.Clob only valid for String, Clob, Reader", param);
return; return;
@ -492,7 +501,7 @@ public class JdbcMapperProcessor extends AbstractProcessor {
// we are going to put most common ones up top so it should execute faster normally // we are going to put most common ones up top so it should execute faster normally
// todo: avoid string concat here // todo: avoid string concat here
if(method == null) if (method == null)
if (o.getKind().isPrimitive() || types.isAssignable(o, stringType) || types.isAssignable(o, numberType)) { if (o.getKind().isPrimitive() || types.isAssignable(o, stringType) || types.isAssignable(o, numberType)) {
method = "Object"; method = "Object";
// java.util.Date support, put it in a Timestamp // java.util.Date support, put it in a Timestamp
@ -563,7 +572,7 @@ public class JdbcMapperProcessor extends AbstractProcessor {
return double.class; return double.class;
case ARRAY: case ARRAY:
// yuck // yuck
final TypeMirror arrayComponentType = ((ArrayType)tm).getComponentType(); final TypeMirror arrayComponentType = ((ArrayType) tm).getComponentType();
switch (arrayComponentType.getKind()) { switch (arrayComponentType.getKind()) {
case BOOLEAN: case BOOLEAN:
return boolean[].class; return boolean[].class;
@ -587,7 +596,7 @@ public class JdbcMapperProcessor extends AbstractProcessor {
return Class.forName("[L" + arrayComponentType.toString() + ";"); return Class.forName("[L" + arrayComponentType.toString() + ";");
} }
case DECLARED: case DECLARED:
if(!((DeclaredType)tm).getTypeArguments().isEmpty()) { if (!((DeclaredType) tm).getTypeArguments().isEmpty()) {
final String classWithGenerics = tm.toString(); final String classWithGenerics = tm.toString();
return Class.forName(classWithGenerics.substring(0, classWithGenerics.indexOf('<'))); return Class.forName(classWithGenerics.substring(0, classWithGenerics.indexOf('<')));
} }
@ -600,16 +609,16 @@ public class JdbcMapperProcessor extends AbstractProcessor {
public ExecutableElement getCloseMethod(final TypeElement genClass) { public ExecutableElement getCloseMethod(final TypeElement genClass) {
ExecutableElement ret = null; ExecutableElement ret = null;
for (final Element methodElement : genClass.getEnclosedElements()) { for (final Element methodElement : genClass.getEnclosedElements()) {
if((ret = getCloseMethod(methodElement)) != null) if ((ret = getCloseMethod(methodElement)) != null)
return ret; return ret;
} }
// superclasses // superclasses
final TypeMirror superclass = genClass.getSuperclass(); final TypeMirror superclass = genClass.getSuperclass();
if(superclass.getKind() == TypeKind.DECLARED && (ret = getCloseMethod((TypeElement)types.asElement(superclass))) != null) if (superclass.getKind() == TypeKind.DECLARED && (ret = getCloseMethod((TypeElement) types.asElement(superclass))) != null)
return ret; return ret;
// interfaces // interfaces
for(final TypeMirror iface : genClass.getInterfaces()) { for (final TypeMirror iface : genClass.getInterfaces()) {
if(iface.getKind() == TypeKind.DECLARED && (ret = getCloseMethod((TypeElement)types.asElement(iface))) != null) if (iface.getKind() == TypeKind.DECLARED && (ret = getCloseMethod((TypeElement) types.asElement(iface))) != null)
return ret; return ret;
} }
return ret; return ret;