1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.mybatis.scripting.velocity;
17
18 import java.io.IOException;
19 import java.io.StringWriter;
20 import java.io.Writer;
21 import java.util.Iterator;
22
23 import org.apache.velocity.context.InternalContextAdapter;
24 import org.apache.velocity.exception.TemplateInitException;
25 import org.apache.velocity.exception.VelocityException;
26 import org.apache.velocity.runtime.RuntimeServices;
27 import org.apache.velocity.runtime.directive.StopCommand;
28 import org.apache.velocity.runtime.parser.node.ASTReference;
29 import org.apache.velocity.runtime.parser.node.ASTStringLiteral;
30 import org.apache.velocity.runtime.parser.node.Node;
31 import org.apache.velocity.runtime.parser.node.StandardParserTreeConstants;
32 import org.apache.velocity.util.introspection.Info;
33
34
35
36
37 public class InDirective extends RepeatDirective {
38
39
40
41
42 private String var;
43
44 private String open = "(";
45
46 private String close = ")";
47
48 private String separator = ", ";
49
50 private String column = "";
51
52 @Override
53 public String getName() {
54 return "in";
55 }
56
57 @Override
58 public void init(RuntimeServices rs, InternalContextAdapter context, Node node) {
59 super.init(rs, context, node);
60 final int n = node.jjtGetNumChildren() - 1;
61 for (int i = 1; i < n; i++) {
62 Node child = node.jjtGetChild(i);
63 if (i == 1) {
64 if (child.getType() == StandardParserTreeConstants.JJTREFERENCE) {
65 this.var = ((ASTReference) child).getRootString();
66 } else {
67 throw new TemplateInitException("Syntax error", getTemplateName(), getLine(), getColumn());
68 }
69 } else if (child.getType() == StandardParserTreeConstants.JJTSTRINGLITERAL) {
70 String value = (String) ((ASTStringLiteral) child).value(context);
71 if (i == 2) {
72 this.column = value;
73 }
74 } else {
75 throw new TemplateInitException("Syntax error", getTemplateName(), getLine(), getColumn());
76 }
77 }
78 this.uberInfo = new Info(this.getTemplateName(), getLine(), getColumn());
79 }
80
81 @Override
82 public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException {
83 Object listObject = node.jjtGetChild(0).value(context);
84 if (listObject == null) {
85 return false;
86 }
87
88 Iterator<?> iterator = null;
89
90 try {
91 iterator = this.rsvc.getUberspect().getIterator(listObject, this.uberInfo);
92 } catch (RuntimeException e) {
93 throw e;
94 } catch (Exception ee) {
95 String msg = "Error getting iterator for #in at " + this.uberInfo;
96 this.rsvc.getLog().error(msg, ee);
97 throw new VelocityException(msg, ee);
98 }
99
100 if (iterator == null) {
101 throw new VelocityException("Invalid collection");
102 }
103
104 int counter = 0;
105 Object o = context.get(this.var);
106
107 ParameterMappingCollector collector = (ParameterMappingCollector) context
108 .get(SQLScriptSource.MAPPING_COLLECTOR_KEY);
109 String savedItemKey = collector.getItemKey();
110 collector.setItemKey(this.var);
111 RepeatScope foreach = new RepeatScope(this, context.get(getName()), this.var);
112 context.put(getName(), foreach);
113
114 NullHolderContext nullHolderContext = null;
115 Object value = null;
116 StringWriter buffer = new StringWriter();
117
118 while (iterator.hasNext()) {
119
120 if (counter % MAX_IN_CLAUSE_SIZE == 0) {
121 buffer.append(this.open);
122 buffer.append(this.column);
123 buffer.append(" IN ");
124 buffer.append(this.open);
125 }
126
127 value = iterator.next();
128 put(context, this.var, value);
129 foreach.index++;
130 foreach.hasNext = iterator.hasNext();
131
132 try {
133 if (value == null) {
134 if (nullHolderContext == null) {
135 nullHolderContext = new NullHolderContext(this.var, context);
136 }
137 node.jjtGetChild(node.jjtGetNumChildren() - 1).render(nullHolderContext, buffer);
138 } else {
139 node.jjtGetChild(node.jjtGetNumChildren() - 1).render(context, buffer);
140 }
141 } catch (StopCommand stop) {
142 if (stop.isFor(this)) {
143 break;
144 }
145 clean(context, o, collector, savedItemKey);
146
147
148 buffer.close();
149 throw stop;
150 }
151 counter++;
152
153 if ((counter > 0 && counter % MAX_IN_CLAUSE_SIZE == 0) || !iterator.hasNext()) {
154 buffer.append(this.close);
155 buffer.append(this.close);
156 if (iterator.hasNext()) {
157 buffer.append(" OR ");
158 }
159 } else if (iterator.hasNext()) {
160 buffer.append(this.separator);
161 }
162
163 }
164 String content = buffer.toString().trim();
165 if (!"".equals(content)) {
166 writer.append(this.open);
167 writer.append(content);
168 writer.append(this.close);
169 } else {
170 writer.append(this.open);
171 writer.append(this.open);
172 writer.append(this.column);
173 writer.append(" NOT IN ");
174 writer.append(this.open);
175 writer.append(" NULL ");
176 writer.append(this.close);
177 writer.append(this.close);
178 writer.append(this.close);
179 }
180 clean(context, o, collector, savedItemKey);
181 return true;
182 }
183
184 @Override
185 public int getType() {
186 return BLOCK;
187 }
188
189 }