1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.student.remote.impl.mojo;
17
18 import java.util.ArrayList;
19 import java.util.HashSet;
20 import java.util.List;
21 import java.util.Set;
22 import java.util.Stack;
23 import org.kuali.rice.core.api.criteria.Predicate;
24 import org.kuali.rice.core.api.criteria.PredicateFactory;
25 import org.kuali.rice.core.api.criteria.QueryByCriteria;
26 import org.kuali.student.admin.ui.mojo.AdminUiLookupableWriter;
27 import org.kuali.student.contract.model.MessageStructure;
28 import org.kuali.student.contract.model.Service;
29
30 import org.kuali.student.contract.model.ServiceContractModel;
31 import org.kuali.student.contract.model.ServiceMethod;
32 import org.kuali.student.contract.model.ServiceMethodError;
33 import org.kuali.student.contract.model.ServiceMethodParameter;
34 import org.kuali.student.contract.model.XmlType;
35 import org.kuali.student.contract.model.util.ModelFinder;
36 import org.kuali.student.contract.writer.JavaClassWriter;
37 import org.kuali.student.contract.writer.service.GetterSetterNameCalculator;
38 import org.kuali.student.contract.writer.service.MessageStructureTypeCalculator;
39 import org.kuali.student.contract.writer.service.ServiceExceptionWriter;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43
44
45
46
47 public class RemoteImplServiceTestWriter extends JavaClassWriter {
48
49 private static final Logger log = LoggerFactory.getLogger(RemoteImplServiceTestWriter.class);
50 private ServiceContractModel model;
51 private ModelFinder finder;
52 private String directory;
53 private String rootPackage;
54 private String servKey;
55 private List<ServiceMethod> methods;
56 private Service service;
57
58 public RemoteImplServiceTestWriter(ServiceContractModel model,
59 String directory,
60 String rootPackage,
61 String servKey,
62 List<ServiceMethod> methods) {
63 super(directory + "/test/java", calcPackage(servKey, rootPackage), calcClassName(servKey));
64 this.model = model;
65 this.finder = new ModelFinder(model);
66 this.directory = directory;
67 this.rootPackage = rootPackage;
68 this.servKey = servKey;
69 this.service = finder.findService(servKey);
70 this.methods = methods;
71 }
72
73 public static String calcPackage(String servKey, String rootPackage) {
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93 return rootPackage;
94 }
95
96 public static String calcClassName(String servKey) {
97 String name = GetterSetterNameCalculator.calcInitUpper(servKey + "ServiceRemoteImplTest");
98 if (name.startsWith("RICE.")) {
99 name = name.substring("RICE.".length());
100 }
101 return name;
102 }
103
104 private static enum MethodType {
105
106 VALIDATE, CREATE, UPDATE
107 };
108
109 private MethodType calcMethodType(ServiceMethod method) {
110 if (method.getName().startsWith("validate")) {
111 return MethodType.VALIDATE;
112 }
113 if (method.getName().startsWith("create")) {
114 return MethodType.CREATE;
115 }
116 if (method.getName().startsWith("update")) {
117 return MethodType.UPDATE;
118 }
119 return null;
120 }
121
122
123
124
125
126
127 public void write() {
128 String serviceName = service.getName();
129 indentPrintln("//@Ignore");
130 indentPrintln("public class " + calcClassName(servKey));
131
132 openBrace();
133 importsAdd("org.junit.*");
134 XmlType contextInfo = finder.findXmlType("contextInfo");
135 importsAdd(contextInfo.getJavaPackage() + "." + contextInfo.getName());
136 indentPrintln("private static ContextInfo contextInfo;");
137
138 indentPrintln("private static " + serviceName + "RemoteImpl service;");
139 indentPrintln("");
140 indentPrintln("");
141 indentPrintln("@BeforeClass");
142 indentPrintln("public static void setUpClass() throws Exception");
143 openBrace();
144 indentPrintln("service = new " + serviceName + "RemoteImpl();");
145 indentPrintln("service.setHostUrl(RemoteServiceConstants.ENV2_URL);");
146 indentPrintln("//service.setHostUrl(RemoteServiceConstants.LOCAL_HOST_EMBEDDED_URL);");
147 indentPrintln("contextInfo = new ContextInfo();");
148 indentPrintln("contextInfo.setPrincipalId(\"TESTUSER\");");
149 closeBrace();
150 indentPrintln("");
151 indentPrintln("@AfterClass");
152 indentPrintln("public static void tearDownClass() throws Exception");
153 openBrace();
154 closeBrace();
155 indentPrintln("");
156 indentPrintln("@Before");
157 indentPrintln("public void setUp()");
158 openBrace();
159 closeBrace();
160 indentPrintln("");
161 indentPrintln("@After");
162 indentPrintln("public void tearDown()");
163 openBrace();
164 closeBrace();
165 indentPrintln("");
166
167
168 Set<XmlType> types = this.getMainXmlTypesUsedByService(methods);
169 if (types.isEmpty()) {
170 log.warn("No types defined for servKey: " + servKey);
171 return;
172 }
173
174 log.info("Generating search by criteria tests for " + types.size() + " in " + servKey);
175 for (XmlType type : types) {
176 this.writeTestMethodsForXmlType(type);
177 }
178 closeBrace();
179
180 this.writeJavaClassAndImportsOutToFile();
181 this.getOut().close();
182 }
183
184 private void writeTestMethodsForXmlType(XmlType xmlType) {
185 ServiceMethod searchMethod = AdminUiLookupableWriter.findSearchMethod(xmlType, methods);
186 if (searchMethod == null) {
187 log.warn("No search method found for " + this.servKey + "." + xmlType.getName());
188 return;
189
190 }
191 String infoClass = GetterSetterNameCalculator.calcInitUpper(xmlType.getName());
192 importsAdd(xmlType.getJavaPackage() + "." + xmlType.getName());
193 indentPrintln("");
194 indentPrintln("@Test");
195 indentPrintln("public void testSearch" + infoClass + "All () throws Exception");
196 openBrace();
197 importsAdd(QueryByCriteria.class.getName());
198 importsAdd(Predicate.class.getName());
199 importsAdd(PredicateFactory.class.getName());
200 indentPrintln("QueryByCriteria.Builder qBuilder = QueryByCriteria.Builder.create();");
201 indentPrintln("qBuilder.setMaxResults (30);");
202 importsAdd(List.class.getName());
203 String returnType = "List<" + infoClass + ">";
204 if (searchMethod.getReturnValue().getType().endsWith("QueryResults")) {
205 returnType = searchMethod.getReturnValue().getType();
206 XmlType returnXmlType = finder.findXmlType(returnType);
207 importsAdd (returnXmlType.getJavaPackage() + "." + returnType);
208 }
209 indentPrint(returnType + " infos = service." + searchMethod.getName());
210 String comma = "(";
211 for (ServiceMethodParameter param : searchMethod.getParameters()) {
212 print(comma);
213 comma = ", ";
214 if (param.getType().equals("QueryByCriteria")) {
215 print("qBuilder.build()");
216 continue;
217 }
218 if (param.getType().equals("ContextInfo")) {
219 print("contextInfo");
220 continue;
221 }
222 log.warn(servKey + "." + searchMethod.getName() + " param=" + param.getName() + " " + param.getType() + " cannot be specified in search");
223 }
224 println(");");
225 closeBrace();
226
227
228 indentPrintln("");
229 indentPrintln("@Test");
230 indentPrintln("public void testSearch" + infoClass + "KeywordSearch () throws Exception");
231 openBrace();
232 importsAdd(QueryByCriteria.class.getName());
233 importsAdd(Predicate.class.getName());
234 importsAdd(PredicateFactory.class.getName());
235 indentPrintln("QueryByCriteria.Builder qBuilder = QueryByCriteria.Builder.create();");
236 importsAdd(ArrayList.class.getName());
237 indentPrintln("List<Predicate> pList = new ArrayList<Predicate>();");
238 indentPrintln("pList.add(PredicateFactory.equal(\"keywordSearch\", \"xyzzysomethingnothingmatches\"));");
239 indentPrintln("qBuilder.setPredicates(PredicateFactory.and(pList.toArray(new Predicate[pList.size()])));");
240 indentPrintln("qBuilder.setMaxResults (30);");
241 importsAdd(List.class.getName());
242 indentPrint(returnType + " infos = service." + searchMethod.getName());
243 comma = "(";
244 for (ServiceMethodParameter param : searchMethod.getParameters()) {
245 print(comma);
246 comma = ", ";
247 if (param.getType().equals("QueryByCriteria")) {
248 print("qBuilder.build()");
249 continue;
250 }
251 if (param.getType().equals("ContextInfo")) {
252 print("contextInfo");
253 continue;
254 }
255 log.warn(servKey + "." + searchMethod.getName() + " param=" + param.getName() + " " + param.getType() + " cannot be specified in search");
256 }
257 println(");");
258 closeBrace();
259
260 this.writeFieldTests(infoClass, returnType, searchMethod, xmlType, new Stack<XmlType>(), "");
261 }
262
263 private void writeFieldTests(String infoClass, String returnType, ServiceMethod searchMethod, XmlType type, Stack<XmlType> parents, String prefix) {
264
265 if (parents.contains(type)) {
266 return;
267 }
268 parents.push(type);
269 for (MessageStructure ms : finder.findMessageStructures(type.getName())) {
270 String fieldName = GetterSetterNameCalculator.calcInitLower(ms.getShortName());
271 if (!prefix.isEmpty()) {
272 fieldName = prefix + "." + fieldName;
273 }
274 String fieldNameCamel = GetterSetterNameCalculator.dot2Camel(fieldName);
275 if (ms.getShortName().equalsIgnoreCase("versionInd")) {
276 indentPrintln("// TODO: deal with seaching on the version indicator which is a string in the contract but a number in the database");
277 continue;
278 }
279 if (ms.getType().equalsIgnoreCase("AttributeInfoList")) {
280 indentPrintln("// TODO: deal with dynamic attributes");
281 continue;
282 }
283 if (ms.getType().endsWith("List")) {
284 indentPrintln("// TODO: deal with " + fieldName + " which is a List");
285 continue;
286 }
287 XmlType fieldType = finder.findXmlType(ms.getType());
288 if (fieldType.getPrimitive().equalsIgnoreCase(XmlType.COMPLEX)) {
289
290 this.writeFieldTests(infoClass, returnType, searchMethod, fieldType, parents, fieldName);
291 continue;
292 }
293 if (!ms.getType().equalsIgnoreCase("String")) {
294 indentPrintln("// TODO: deal with " + fieldName + " which is a " + ms.getType());
295 continue;
296 }
297
298 indentPrintln("");
299 indentPrintln("@Test");
300 indentPrintln("public void testSearch" + infoClass + "By" + fieldNameCamel + " () throws Exception");
301 openBrace();
302 indentPrintln("QueryByCriteria.Builder qBuilder = QueryByCriteria.Builder.create();");
303 indentPrintln("List<Predicate> pList = new ArrayList<Predicate>();");
304 indentPrintln("pList.add(PredicateFactory.equal(\"" + fieldName + "\", \"xyzzysomethingnothingmatches\"));");
305 indentPrintln("qBuilder.setPredicates(PredicateFactory.and(pList.toArray(new Predicate[pList.size()])));");
306 indentPrintln("qBuilder.setMaxResults (30);");
307 indentPrint(returnType + " infos = service." + searchMethod.getName());
308 String comma = "(";
309 for (ServiceMethodParameter param : searchMethod.getParameters()) {
310 print(comma);
311 comma = ", ";
312 if (param.getType().equals("QueryByCriteria")) {
313 print("qBuilder.build()");
314 continue;
315 }
316 if (param.getType().equals("ContextInfo")) {
317 print("contextInfo");
318 continue;
319 }
320 log.warn(servKey + "." + searchMethod.getName() + " param=" + param.getName() + " " + param.getType() + " cannot be specified in search");
321 }
322 println(");");
323 closeBrace();
324
325 }
326 parents.pop();
327 }
328
329 private String calcType(String type, String realType) {
330 XmlType t = finder.findXmlType(this.stripList(type));
331 return MessageStructureTypeCalculator.calculate(this, model, type, realType,
332 t.getJavaPackage());
333 }
334
335 private String stripList(String str) {
336 return GetterSetterNameCalculator.stripList(str);
337 }
338
339 private String calcExceptionClassName(ServiceMethodError error) {
340 if (error.getClassName() == null) {
341 return ServiceExceptionWriter.calcClassName(error.getType());
342 }
343 return error.getClassName();
344 }
345
346 private String calcExceptionPackageName(ServiceMethodError error) {
347 if (error.getClassName() == null) {
348 return ServiceExceptionWriter.calcPackage(rootPackage);
349 }
350 return error.getPackageName();
351 }
352
353 private Set<XmlType> getMainXmlTypesUsedByService(List<ServiceMethod> methods) {
354 Set<XmlType> set = new HashSet();
355 for (ServiceMethod method : methods) {
356 if (method.getReturnValue().getType().endsWith("List")) {
357 continue;
358 }
359 XmlType returnType = finder.findXmlType(method.getReturnValue().getType());
360 if (returnType == null) {
361 continue;
362 }
363 if (!returnType.getPrimitive().equalsIgnoreCase(XmlType.COMPLEX)) {
364 continue;
365 }
366
367 if (returnType.getName().equalsIgnoreCase("TypeInfo")) {
368 if (!servKey.equalsIgnoreCase("type")) {
369 continue;
370 }
371 }
372
373 if (returnType.getName().equalsIgnoreCase("StateInfo")) {
374 if (!servKey.equalsIgnoreCase("state")) {
375 continue;
376 }
377 }
378
379
380
381
382
383
384
385
386
387 if (method.getName().startsWith("get")) {
388 List<ServiceMethodParameter> params = this.getNonContextParameters(method.getParameters());
389 if (params.size() == 1) {
390 if (params.get(0).getType().equalsIgnoreCase("String")) {
391 set.add(returnType);
392 continue;
393 }
394 }
395 }
396 }
397 return set;
398 }
399
400
401 private List<ServiceMethodParameter> getNonContextParameters (List <ServiceMethodParameter> params) {
402 List<ServiceMethodParameter> list = new ArrayList<ServiceMethodParameter> ();
403 for (ServiceMethodParameter param : params) {
404 if (param.getType().equalsIgnoreCase("ContextInfo")) {
405 continue;
406 }
407 list.add (param);
408 }
409 return list;
410 }
411 private List<MessageStructure> getFieldsToSearchOn(XmlType xmlType) {
412 List<MessageStructure> list = new ArrayList<MessageStructure>();
413 for (MessageStructure ms : finder.findMessageStructures(xmlType.getName())) {
414 XmlType msType = finder.findXmlType(ms.getType());
415
416 if (msType.getPrimitive().equalsIgnoreCase(XmlType.COMPLEX)) {
417 continue;
418 }
419 list.add(ms);
420 }
421 return list;
422 }
423 }