1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.ibatis.submitted.language;
17
18 import java.io.StringReader;
19 import java.io.StringWriter;
20 import java.util.HashMap;
21 import java.util.Map;
22 import org.apache.ibatis.builder.BuilderException;
23 import org.apache.ibatis.mapping.BoundSql;
24 import org.apache.ibatis.mapping.SqlSource;
25 import org.apache.ibatis.session.Configuration;
26 import org.apache.velocity.Template;
27 import org.apache.velocity.VelocityContext;
28 import org.apache.velocity.app.Velocity;
29 import org.apache.velocity.runtime.RuntimeServices;
30 import org.apache.velocity.runtime.RuntimeSingleton;
31 import org.apache.velocity.runtime.parser.node.SimpleNode;
32
33
34
35
36 public class VelocitySqlSource implements SqlSource {
37
38 public static final String PARAMETER_OBJECT_KEY = "_parameter";
39 public static final String DATABASE_ID_KEY = "_databaseId";
40
41 private final Configuration configuration;
42 private final Template script;
43
44 static {
45 Velocity.setProperty("runtime.log", "target/velocity.log");
46 Velocity.init();
47 }
48
49 public VelocitySqlSource(Configuration configuration, String scriptText) {
50 this.configuration = configuration;
51 try {
52 RuntimeServices runtimeServices = RuntimeSingleton.getRuntimeServices();
53 StringReader reader = new StringReader(scriptText);
54 Template template = new Template();
55 template.setName("Template name");
56 SimpleNode node = runtimeServices.parse(reader, template);
57 script = new Template();
58 script.setRuntimeServices(runtimeServices);
59 script.setData(node);
60 script.initDocument();
61 } catch (Exception ex) {
62 throw new BuilderException("Error parsing velocity script", ex);
63 }
64 }
65
66 @Override
67 public BoundSql getBoundSql(Object parameterObject) {
68 Map<String, Object> bindings = createBindings(parameterObject, configuration);
69 VelocityContext context = new VelocityContext(bindings);
70 StringWriter sw = new StringWriter();
71 script.merge(context, sw);
72 VelocitySqlSourceBuilderceBuilder.html#VelocitySqlSourceBuilder">VelocitySqlSourceBuilder sqlSourceParser = new VelocitySqlSourceBuilder(configuration);
73 Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass();
74 SqlSource sqlSource = sqlSourceParser.parse(sw.toString(), parameterType);
75 BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
76 for (Map.Entry<String, Object> entry : bindings.entrySet()) {
77 boundSql.setAdditionalParameter(entry.getKey(), entry.getValue());
78 }
79 return boundSql;
80
81 }
82
83 public static Map<String, Object> createBindings(Object parameterObject, Configuration configuration) {
84 Map<String, Object> bindings = new HashMap<>();
85 bindings.put(PARAMETER_OBJECT_KEY, parameterObject);
86 bindings.put(DATABASE_ID_KEY, configuration.getDatabaseId());
87 bindings.put("it", new IteratorParameter(bindings));
88 return bindings;
89 }
90
91 public static class IteratorParameter {
92
93 private static final String PREFIX = "__frch_";
94 private int count = 0;
95 private final Map<String, Object> bindings;
96
97 public IteratorParameter(Map<String, Object> bindings) {
98 this.bindings = bindings;
99 }
100
101 public String next(Object prop) {
102 StringBuilder sb = new StringBuilder();
103 String name = sb.append(PREFIX).append("_ITEM").append("_").append(count++).toString();
104 bindings.put(name, prop);
105 return name;
106 }
107 }
108 }