1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.ibatis.builder.annotation;
17
18 import java.lang.reflect.Method;
19 import java.util.HashMap;
20
21 import org.apache.ibatis.builder.BuilderException;
22 import org.apache.ibatis.builder.SqlSourceBuilder;
23 import org.apache.ibatis.mapping.BoundSql;
24 import org.apache.ibatis.mapping.SqlSource;
25 import org.apache.ibatis.session.Configuration;
26
27
28
29
30 public class ProviderSqlSource implements SqlSource {
31
32 private SqlSourceBuilder sqlSourceParser;
33 private Class<?> providerType;
34 private Method providerMethod;
35 private boolean providerTakesParameterObject;
36
37 public ProviderSqlSource(Configuration config, Object provider) {
38 String providerMethodName = null;
39 try {
40 this.sqlSourceParser = new SqlSourceBuilder(config);
41 this.providerType = (Class<?>) provider.getClass().getMethod("type").invoke(provider);
42 providerMethodName = (String) provider.getClass().getMethod("method").invoke(provider);
43
44 for (Method m : this.providerType.getMethods()) {
45 if (providerMethodName.equals(m.getName())) {
46 if (m.getParameterTypes().length < 2
47 && m.getReturnType() == String.class) {
48 this.providerMethod = m;
49 this.providerTakesParameterObject = m.getParameterTypes().length == 1;
50 }
51 }
52 }
53 } catch (Exception e) {
54 throw new BuilderException("Error creating SqlSource for SqlProvider. Cause: " + e, e);
55 }
56 if (this.providerMethod == null) {
57 throw new BuilderException("Error creating SqlSource for SqlProvider. Method '"
58 + providerMethodName + "' not found in SqlProvider '" + this.providerType.getName() + "'.");
59 }
60 }
61
62 @Override
63 public BoundSql getBoundSql(Object parameterObject) {
64 SqlSource sqlSource = createSqlSource(parameterObject);
65 return sqlSource.getBoundSql(parameterObject);
66 }
67
68 private SqlSource createSqlSource(Object parameterObject) {
69 try {
70 String sql;
71 if (providerTakesParameterObject) {
72 sql = (String) providerMethod.invoke(providerType.newInstance(), parameterObject);
73 } else {
74 sql = (String) providerMethod.invoke(providerType.newInstance());
75 }
76 Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass();
77 return sqlSourceParser.parse(sql, parameterType, new HashMap<String, Object>());
78 } catch (Exception e) {
79 throw new BuilderException("Error invoking SqlProvider method ("
80 + providerType.getName() + "." + providerMethod.getName()
81 + "). Cause: " + e, e);
82 }
83 }
84
85 }