1 package org.synchronoss.cpo.core;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 import java.lang.reflect.InvocationTargetException;
26 import java.util.ArrayList;
27 import java.util.Collection;
28 import java.util.HashMap;
29 import java.util.List;
30 import java.util.Map.Entry;
31 import java.util.Set;
32 import org.slf4j.Logger;
33 import org.synchronoss.cpo.core.meta.MethodMapEntry;
34 import org.synchronoss.cpo.core.meta.MethodMapper;
35 import org.synchronoss.cpo.core.meta.domain.CpoArgument;
36 import org.synchronoss.cpo.core.meta.domain.CpoAttribute;
37 import org.synchronoss.cpo.core.meta.domain.CpoClass;
38 import org.synchronoss.cpo.core.meta.domain.CpoFunction;
39 import org.synchronoss.cpo.core.parser.BoundExpressionParser;
40
41
42
43
44
45
46
47 public abstract class CpoStatementFactory implements CpoReleasable {
48
49
50 private static final long serialVersionUID = 1L;
51
52 private Logger localLogger = null;
53
54 private List<CpoReleasable> releasables = new ArrayList<>();
55 private static final String WHERE_MARKER = "__CPO_WHERE__";
56 private static final String ORDERBY_MARKER = "__CPO_ORDERBY__";
57
58 private CpoStatementFactory() {
59
60 }
61
62
63
64
65
66
67 public CpoStatementFactory(Logger localLogger) {
68 this.localLogger = localLogger;
69 }
70
71
72
73
74
75
76 public Logger getLocalLogger() {
77 return localLogger;
78 }
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96 protected <T> String buildSql(
97 CpoClass cpoClass,
98 String sql,
99 Collection<CpoWhere> wheres,
100 Collection<CpoOrderBy> orderBy,
101 Collection<CpoNativeFunction> nativeQueries,
102 List<BindAttribute> bindValues)
103 throws CpoException {
104 StringBuilder sqlText = new StringBuilder();
105
106 sqlText.append(sql);
107
108 if (wheres != null) {
109 for (CpoWhere where : wheres) {
110 BindableWhereBuilder<T> jwb = new BindableWhereBuilder<>(cpoClass);
111 BindableCpoWhere jcw = (BindableCpoWhere) where;
112
113
114 jcw.acceptDFVisitor(jwb);
115
116 if (sqlText.indexOf(jcw.getName()) == -1) {
117 sqlText.append(" ");
118 sqlText.append(jwb.getWhereClause());
119 bindValues.addAll(jwb.getBindValues());
120 } else {
121 sqlText = replaceMarker(sqlText, jcw.getName(), jwb, bindValues);
122 }
123 }
124 }
125
126
127 if (orderBy != null) {
128 HashMap<String, StringBuilder> mapOrderBy = new HashMap<>();
129 for (CpoOrderBy ob : orderBy) {
130 StringBuilder sb = mapOrderBy.get(ob.getMarker());
131 if (sb == null) {
132 sb = new StringBuilder(" ORDER BY ");
133 mapOrderBy.put(ob.getMarker(), sb);
134 } else {
135 sb.append(",");
136 }
137 sb.append(ob.toString(cpoClass));
138 }
139
140 Set<Entry<String, StringBuilder>> entries = mapOrderBy.entrySet();
141 for (Entry<String, StringBuilder> entry : entries) {
142 if (sqlText.indexOf(entry.getKey()) == -1) {
143 sqlText.append(entry.getValue().toString());
144 } else {
145 sqlText = replaceMarker(sqlText, entry.getKey(), entry.getValue().toString());
146 }
147 }
148 }
149
150 if (nativeQueries != null) {
151 for (CpoNativeFunction cnq : nativeQueries) {
152 if (cnq.getMarker() == null || sqlText.indexOf(cnq.getMarker()) == -1) {
153 if (cnq.getExpression() != null && !cnq.getExpression().isEmpty()) {
154 sqlText.append(" ");
155 sqlText.append(cnq.getExpression());
156 }
157 } else {
158 sqlText = replaceMarker(sqlText, cnq.getMarker(), cnq.getExpression());
159 }
160 }
161 }
162
163
164 sqlText = replaceMarker(sqlText, WHERE_MARKER, "");
165 sqlText = replaceMarker(sqlText, ORDERBY_MARKER, "");
166
167 return sqlText.toString();
168 }
169
170 private StringBuilder replaceMarker(StringBuilder source, String marker, String replace) {
171 int attrOffset;
172 int fromIndex = 0;
173 int mLength = marker.length();
174 String replaceText = replace == null ? "" : replace;
175 int rLength = replaceText.length();
176
177
178 if (source != null && !source.isEmpty()) {
179 while ((attrOffset = source.indexOf(marker, fromIndex)) != -1) {
180 source.replace(attrOffset, attrOffset + mLength, replaceText);
181 fromIndex = attrOffset + rLength;
182 }
183 }
184
185
186 return source;
187 }
188
189 private <T> StringBuilder replaceMarker(
190 StringBuilder source,
191 String marker,
192 BindableWhereBuilder<T> jwb,
193 List<BindAttribute> bindValues) {
194 int attrOffset;
195 int fromIndex = 0;
196 int mLength = marker.length();
197 String replace = jwb.getWhereClause();
198 int rLength = replace.length();
199 Collection<BindAttribute> jwbBindValues = jwb.getBindValues();
200
201
202 if (source != null && !source.isEmpty()) {
203 while ((attrOffset = source.indexOf(marker, fromIndex)) != -1) {
204 source.replace(attrOffset, attrOffset + mLength, replace);
205 fromIndex = attrOffset + rLength;
206 bindValues.addAll(
207 BoundExpressionParser.getBindMarkerIndexes(source.substring(0, attrOffset)).size(),
208 jwbBindValues);
209 }
210 }
211
212
213 return source;
214 }
215
216
217
218
219
220
221
222 public void AddReleasable(CpoReleasable releasable) {
223 if (releasable != null) {
224 releasables.add(releasable);
225 }
226 }
227
228
229
230
231
232 @Override
233 public void release() throws CpoException {
234 for (CpoReleasable releasable : releasables) {
235 try {
236 releasable.release();
237 } catch (CpoException ce) {
238 localLogger.error("Error Releasing Prepared Statement Transform Object", ce);
239 throw ce;
240 }
241 }
242 }
243
244
245
246
247
248
249
250
251
252
253 public List<BindAttribute> getBindValues(CpoFunction function, Object obj) throws CpoException {
254 List<BindAttribute> bindValues = new ArrayList<>();
255 List<CpoArgument> arguments = function.getArguments();
256 for (CpoArgument argument : arguments) {
257 if (argument == null) {
258 throw new CpoException("CpoArgument is null!");
259 }
260 bindValues.add(new BindAttribute(argument.getAttribute(), obj));
261 }
262 return bindValues;
263 }
264
265
266
267
268
269
270
271
272
273 public void setBindValues(Collection<BindAttribute> bindValues) throws CpoException {
274
275 if (bindValues != null) {
276 int index = getStartingIndex();
277
278
279
280 for (BindAttribute bindAttr : bindValues) {
281 Object bindObject = bindAttr.bindObject();
282 CpoAttribute cpoAttribute = bindAttr.cpoAttribute();
283
284
285
286 MethodMapEntry<?, ?> jsm =
287 ((MethodMapper<?>) getMethodMapper()).getDataMethodMapEntry(bindObject.getClass());
288
289 if (jsm != null) {
290 try {
291 if (cpoAttribute == null) {
292 localLogger.debug("{}={}", bindAttr.name(), bindObject);
293 } else {
294 localLogger.debug("{}={}", cpoAttribute.getDataName(), bindObject);
295 }
296 jsm.getBsSetter().invoke(this.getBindableStatement(), index++, bindObject);
297 } catch (IllegalAccessException iae) {
298 String msg = "Error Accessing Prepared Statement Setter: ";
299 throw new CpoException(msg, iae);
300 } catch (InvocationTargetException ite) {
301 String msg = "Error Invoking Prepared Statement Setter: ";
302 throw new CpoException(msg, ite);
303 }
304 } else {
305 CpoData cpoData = getCpoData(cpoAttribute, index++);
306 cpoData.invokeSetter(bindObject);
307 }
308 }
309 }
310 }
311
312 protected abstract MethodMapper getMethodMapper();
313
314 protected abstract CpoData getCpoData(CpoAttribute cpoAttribute, int index);
315
316 protected abstract Object getBindableStatement();
317
318 protected abstract int getStartingIndex();
319 }