1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.student.jpa.mojo;
17
18 import org.kuali.student.contract.model.ServiceContractModel;
19 import org.kuali.student.contract.model.ServiceMethod;
20 import org.kuali.student.contract.model.ServiceMethodError;
21 import org.kuali.student.contract.model.ServiceMethodParameter;
22 import org.kuali.student.contract.model.XmlType;
23 import org.kuali.student.contract.model.util.ModelFinder;
24 import org.kuali.student.contract.writer.JavaClassWriter;
25 import org.kuali.student.contract.writer.service.GetterSetterNameCalculator;
26 import org.kuali.student.contract.writer.service.MessageStructureTypeCalculator;
27 import org.kuali.student.contract.writer.service.ServiceExceptionWriter;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 import java.util.*;
32 import javax.persistence.CascadeType;
33 import javax.persistence.Column;
34 import javax.persistence.Entity;
35 import javax.persistence.FetchType;
36 import javax.persistence.NamedQueries;
37 import javax.persistence.NamedQuery;
38 import javax.persistence.OneToMany;
39 import javax.persistence.Table;
40 import javax.persistence.Temporal;
41 import javax.persistence.TemporalType;
42 import org.apache.commons.lang.StringUtils;
43 import org.kuali.student.contract.model.MessageStructure;
44
45
46
47
48
49 public class JpaEntityWriter extends JavaClassWriter {
50
51 private static final Logger log = LoggerFactory.getLogger(JpaEntityWriter.class);
52
53
54
55
56
57
58
59 protected static enum MethodType {
60
61 VALIDATE,
62 CREATE,
63 CREATE_BULK,
64 ADD,
65 UPDATE,
66 UPDATE_OTHER,
67 DELETE,
68 REMOVE,
69 DELETE_OTHER,
70 GET_CREATE,
71 GET_BY_ID,
72 GET_BY_IDS,
73 RICE_GET_BY_NAMESPACE_AND_NAME,
74 GET_IDS_BY_TYPE,
75 GET_IDS_BY_OTHER,
76 GET_INFOS_BY_OTHER,
77 GET_TYPE,
78 GET_TYPES,
79 SEARCH_FOR_IDS,
80 SEARCH_FOR_INFOS,
81 UNKNOWN
82 };
83
84
85
86
87 protected ServiceContractModel model;
88 protected ModelFinder finder;
89 private String directory;
90 private XmlType xmlType;
91
92
93
94
95
96
97
98 private String rootPackage;
99
100
101
102
103
104
105
106
107 protected String servKey;
108
109
110
111 private boolean isR1;
112 private List<ServiceMethod> methods;
113
114
115
116
117 public JpaEntityWriter(ServiceContractModel model,
118 String directory,
119 String rootPackage,
120 String servKey,
121 List<ServiceMethod> methods,
122 XmlType xmlType,
123 boolean isR1) {
124 super(directory, calcPackage(servKey, rootPackage), calcClassName(servKey, xmlType));
125 this.model = model;
126 this.finder = new ModelFinder(model);
127 this.directory = directory;
128 this.rootPackage = rootPackage;
129 this.servKey = servKey;
130 this.methods = methods;
131 this.xmlType = xmlType;
132 this.isR1 = isR1;
133 }
134
135 public JpaEntityWriter(ServiceContractModel model,
136 String directory,
137 String rootPackage,
138 String servKey,
139 List<ServiceMethod> methods,
140 XmlType xmlType,
141 boolean isR1,
142 String packageName,
143 String className) {
144 super(directory, packageName, className);
145 this.model = model;
146 this.finder = new ModelFinder(model);
147 this.directory = directory;
148 this.rootPackage = rootPackage;
149 this.servKey = servKey;
150 this.methods = methods;
151 this.xmlType = xmlType;
152 this.isR1 = isR1;
153 }
154
155
156
157
158
159
160
161
162
163
164
165 public static String calcPackage(String servKey, String rootPackage) {
166 String pack = rootPackage + ".";
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184 pack = pack + "service.impl.jpa." + servKey.toLowerCase();
185 return pack;
186 }
187
188
189
190
191
192
193 private boolean isRice() {
194 if (this.servKey.startsWith("RICE.")) {
195 return true;
196 }
197 return false;
198 }
199
200 protected static String fixServKey(String servKey) {
201 if (servKey.startsWith("RICE.")) {
202 return servKey.substring("RICE.".length());
203 }
204 return servKey;
205 }
206
207
208
209
210
211 public static String calcClassName(String servKey, XmlType xmlType) {
212 String name = calcInfcName(xmlType) + "Entity";
213 return name;
214 }
215
216 private String calcInfcName() {
217 String name = calcInfcName(xmlType);
218 String pkg = xmlType.getJavaPackage();
219 if (pkg.endsWith(".dto")) {
220 pkg = pkg.substring(0, pkg.length() - ".dto".length()) + ".infc";
221 }
222 importsAdd(pkg + "." + name);
223 return name;
224 }
225
226 private String calcInfoName() {
227 String name = initUpper(xmlType.getName());
228 String pkg = xmlType.getJavaPackage();
229 importsAdd(pkg + "." + name);
230 return name;
231 }
232
233 public static String calcInfcName(XmlType xmlType) {
234 String name = xmlType.getName();
235 if (name.endsWith("Info")) {
236 name = name.substring(0, name.length() - "Info".length());
237 }
238 name = GetterSetterNameCalculator.calcInitUpper(name);
239 return name;
240 }
241
242
243
244
245
246 protected MethodType calcMethodType(ServiceMethod method) {
247 if (this.isRice()) {
248 if (method.getName().contains("ByNamespaceCodeAndName")) {
249 return MethodType.RICE_GET_BY_NAMESPACE_AND_NAME;
250 }
251 if (method.getName().contains("ByNameAndNamespace")) {
252 return MethodType.RICE_GET_BY_NAMESPACE_AND_NAME;
253 }
254 if (method.getName().startsWith("get")) {
255 if (method.getParameters().size() == 1) {
256 if (!method.getReturnValue().getType().endsWith("List")) {
257 if (method.getParameters().get(0).getName().equals("id")) {
258 return MethodType.GET_BY_ID;
259 }
260
261 } else {
262 if (method.getParameters().get(0).getName().equals("ids")) {
263 return MethodType.GET_BY_IDS;
264 }
265 }
266 }
267 }
268 }
269 if (method.getName().startsWith("validate")) {
270 return MethodType.VALIDATE;
271 }
272 if (method.getName().startsWith("create")) {
273 if (this.findInfoParameter(method) != null) {
274 return MethodType.CREATE;
275 }
276 return MethodType.CREATE_BULK;
277 }
278 if (method.getName().startsWith("add")) {
279 return MethodType.ADD;
280 }
281 if (method.getName().startsWith("update")) {
282 if (this.findInfoParameter(method) != null) {
283 return MethodType.UPDATE;
284 }
285 return MethodType.UPDATE_OTHER;
286 }
287 if (method.getName().startsWith("delete")) {
288 if (method.getName().contains("By")) {
289 if (!method.getName().startsWith("deleteBy")) {
290 return MethodType.DELETE_OTHER;
291 }
292 }
293 if (method.getName().contains("For")) {
294 if (!method.getName().startsWith("deleteFor")) {
295 return MethodType.DELETE_OTHER;
296 }
297 }
298 return MethodType.DELETE;
299 }
300 if (method.getName().startsWith("remove")) {
301 return MethodType.REMOVE;
302 }
303
304 if (method.getName().startsWith("getCreate")) {
305 return MethodType.GET_CREATE;
306 }
307
308 if (method.getName().startsWith("get")) {
309 if (method.getName().endsWith("ByIds")) {
310 return MethodType.GET_BY_IDS;
311 }
312 if (method.getName().endsWith("ByKeys")) {
313 return MethodType.GET_BY_IDS;
314 }
315 if (method.getName().endsWith("ByType")) {
316 return MethodType.GET_IDS_BY_TYPE;
317 }
318 if (method.getReturnValue().getType().endsWith("TypeInfo")) {
319 return MethodType.GET_TYPE;
320 }
321 if (method.getReturnValue().getType().endsWith("TypeInfoList")) {
322 return MethodType.GET_TYPES;
323 }
324 if (method.getName().endsWith("ByType")) {
325 return MethodType.GET_IDS_BY_TYPE;
326 }
327 if (method.getParameters().size() >= 1 && method.getParameters().size() <= 2) {
328 if (!method.getReturnValue().getType().endsWith("List")) {
329
330 return MethodType.GET_BY_ID;
331
332 }
333 }
334 if (method.getName().contains("By")) {
335 if (method.getReturnValue().getType().equals("StringList")) {
336 return MethodType.GET_IDS_BY_OTHER;
337 }
338 if (method.getReturnValue().getType().endsWith("InfoList")) {
339 return MethodType.GET_INFOS_BY_OTHER;
340 }
341 }
342 }
343 if (method.getName().startsWith("searchFor")) {
344 if (method.getName().endsWith("Ids")) {
345 return MethodType.SEARCH_FOR_IDS;
346 }
347 if (method.getName().endsWith("Keys")) {
348 return MethodType.SEARCH_FOR_IDS;
349 }
350 return MethodType.SEARCH_FOR_INFOS;
351 }
352
353 return MethodType.UNKNOWN;
354 }
355
356 private String calcTableName(XmlType xmlType) {
357 String tableName = xmlType.getTableName();
358 if (tableName != null) {
359 return tableName;
360 }
361 return calcTableName(xmlType.getName());
362 }
363
364 private String calcTableName(String name) {
365 if (name.endsWith("Info")) {
366 name = name.substring(0, name.length() - "Info".length());
367 }
368 String tableName = "KSEN_" + splitCamelCase(name).toUpperCase();
369 tableName = applyAbbreviations(tableName.toUpperCase());
370 return tableName;
371 }
372
373
374
375 private static String splitCamelCase(String s) {
376 if (s == null) {
377 return null;
378 }
379 return s.replaceAll(String.format("%s|%s|%s",
380 "(?<=[A-Z])(?=[A-Z][a-z])", "(?<=[^A-Z])(?=[A-Z])",
381 "(?<=[A-Za-z])(?=[^A-Za-z])"), "_");
382 }
383
384 private String calcColumnName(MessageStructure ms) {
385 String name = ms.getColumnName();
386 if (name != null) {
387 return name;
388 }
389 if (ms.getShortName().equalsIgnoreCase("TypeKey")) {
390 String prefix = calcTableName(xmlType);
391 if (prefix.startsWith("KSEN_")) {
392 prefix = prefix.substring("KSEN_".length());
393 }
394
395
396 return prefix + "_TYPE";
397 }
398 if (ms.getShortName().equalsIgnoreCase("StateKey")) {
399 String prefix = calcTableName(xmlType);
400 if (prefix.startsWith("KSEN_")) {
401 prefix = prefix.substring("KSEN_".length());
402 }
403
404
405 return prefix + "_STATE";
406 }
407 name = splitCamelCase(ms.getShortName());
408 name = applyAbbreviations(name.toUpperCase());
409 return name;
410 }
411
412 private static final Map<String, String> ABBREVIATIONS = new LinkedHashMap<String, String>();
413
414
415 static {
416 ABBREVIATIONS.put("ABBREVIATION", "ABBREV");
417 ABBREVIATIONS.put("ACCOUNT", "ACCT");
418 ABBREVIATIONS.put("ACCOUNTING", "ACCT");
419 ABBREVIATIONS.put("ACCREDITING", "ACCRED");
420 ABBREVIATIONS.put("ACCREDIT", "ACCRED");
421 ABBREVIATIONS.put("ACCREDITATION", "ACCRED");
422 ABBREVIATIONS.put("ACTION", "ACTN");
423 ABBREVIATIONS.put("AFFILIATION", "AFFIL");
424 ABBREVIATIONS.put("AMOUNT", "AMT");
425 ABBREVIATIONS.put("APPLIED", "APPLD");
426 ABBREVIATIONS.put("APPLICATION", "APP");
427 ABBREVIATIONS.put("ALLOWABLE", "ALOW");
428 ABBREVIATIONS.put("ALTERNATE", "ALT");
429 ABBREVIATIONS.put("APPOINTMENT", "APPT");
430 ABBREVIATIONS.put("ASSOCIATED", "ASSO");
431 ABBREVIATIONS.put("ATTRIBUTE", "ATTR");
432 ABBREVIATIONS.put("CAMPUS", "CAMP");
433 ABBREVIATIONS.put("CANONICAL LEARNING UNIT", "CLU");
434 ABBREVIATIONS.put("CATEGORY", "CAT");
435 ABBREVIATIONS.put("CODE", "CD");
436 ABBREVIATIONS.put("COMPLETE", "COMP");
437 ABBREVIATIONS.put("COMPONENT", "CMP");
438 ABBREVIATIONS.put("CONTEXT", "CTX");
439 ABBREVIATIONS.put("CONTINUE", "CONT");
440 ABBREVIATIONS.put("COUNT", "CNT");
441 ABBREVIATIONS.put("CREDIT", "CR");
442 ABBREVIATIONS.put("CRITERIA", "CRIT");
443 ABBREVIATIONS.put("DATE", "DT");
444 ABBREVIATIONS.put("DEADLINE", "DEDLN");
445 ABBREVIATIONS.put("DEFAULT", "DEF");
446 ABBREVIATIONS.put("DEFINABLE", "DEFNBL");
447 ABBREVIATIONS.put("DEFINITION", "DEFN");
448 ABBREVIATIONS.put("DESCRIPTION", "DESCR");
449 ABBREVIATIONS.put("DISABLED", "DISBLD");
450 ABBREVIATIONS.put("DATE OVERRIDE", "DO");
451 ABBREVIATIONS.put("DOCUMENT", "DOC");
452 ABBREVIATIONS.put("DURATION", "DUR");
453 ABBREVIATIONS.put("DIVISION", "DIV");
454 ABBREVIATIONS.put("EFFECTIVE", "EFF");
455 ABBREVIATIONS.put("ENROLL", "ENRL");
456 ABBREVIATIONS.put("ENROLLED", "ENRL");
457 ABBREVIATIONS.put("ENROLLMENT", "ENRL");
458 ABBREVIATIONS.put("ENROLLABLE", "ENRL");
459 ABBREVIATIONS.put("ESTIMATE", "EST");
460 ABBREVIATIONS.put("EXEMPTION", "EXEMPT");
461 ABBREVIATIONS.put("EXPENDITURE", "EXPEND");
462 ABBREVIATIONS.put("EXPIRATION", "EXP");
463 ABBREVIATIONS.put("EXPIRED", "EXP");
464 ABBREVIATIONS.put("FLEXIBLE", "FLEX");
465 ABBREVIATIONS.put("FREQUENCY", "FREQ");
466 ABBREVIATIONS.put("GROUP", "GRP");
467 ABBREVIATIONS.put("HAZARD", "HAZR");
468 ABBREVIATIONS.put("HAZARDOUS", "HAZR");
469 ABBREVIATIONS.put("HEADER", "HDR");
470 ABBREVIATIONS.put("HIERARCHY", "HIRCHY");
471 ABBREVIATIONS.put("IDENTIFIER", "ID");
472 ABBREVIATIONS.put("INACTIVE", "INACV");
473 ABBREVIATIONS.put("INDEPENDENT", "INDPT");
474 ABBREVIATIONS.put("INDICATOR", "IND");
475 ABBREVIATIONS.put("INSTRUCTOR", "INSTR");
476 ABBREVIATIONS.put("INSTRUCTION", "INSTRN");
477 ABBREVIATIONS.put("INSTRUCTIONAL", "INSTRN");
478 ABBREVIATIONS.put("INTENSITY", "INTSTY");
479 ABBREVIATIONS.put("INTERVAL", "INTVL");
480 ABBREVIATIONS.put("LEARNING OBJECTIVE", "LO");
481 ABBREVIATIONS.put("LEARNING RESULT", "LR");
482 ABBREVIATIONS.put("LEARNING UNIT", "LU");
483 ABBREVIATIONS.put("LOCATION", "LOC");
484 ABBREVIATIONS.put("LONG", "LNG");
485 ABBREVIATIONS.put("LEVEL", "LVL");
486 ABBREVIATIONS.put("LIFECYCLE", "LIFCYC");
487 ABBREVIATIONS.put("MARKETING", "MKTG");
488 ABBREVIATIONS.put("MAXIMUM", "MAX");
489 ABBREVIATIONS.put("MEMBER", "MBR");
490 ABBREVIATIONS.put("MESSAGE", "MSG");
491 ABBREVIATIONS.put("MILESTONE", "MSTONE");
492 ABBREVIATIONS.put("MILLISECONDS", "MS");
493 ABBREVIATIONS.put("MINIMUM", "MIN");
494 ABBREVIATIONS.put("NAMESPACE", "NMSPC");
495 ABBREVIATIONS.put("NEXT", "NEXT");
496 ABBREVIATIONS.put("NUMBER", "NUM");
497 ABBREVIATIONS.put("OFFICIAL", "OFFIC");
498 ABBREVIATIONS.put("ORG ORG RELATION TYPE", "OORT");
499 ABBREVIATIONS.put("OPTION", "OPT");
500 ABBREVIATIONS.put("ORGANIZATION", "ORG");
501 ABBREVIATIONS.put("PARAMETER", "PARM");
502 ABBREVIATIONS.put("PARAMETER VALUE", "PV");
503 ABBREVIATIONS.put("PERCENT", "PERCT");
504 ABBREVIATIONS.put("PERIOD", "PRD");
505 ABBREVIATIONS.put("PERSON", "PERS");
506 ABBREVIATIONS.put("POSITION", "POS");
507 ABBREVIATIONS.put("PRIMARY", "PRI");
508 ABBREVIATIONS.put("PROCESS", "PROC");
509 ABBREVIATIONS.put("PUBLISH", "PUBL");
510 ABBREVIATIONS.put("PUBLISHING", "PUBL");
511 ABBREVIATIONS.put("QUANTITY", "QTY");
512 ABBREVIATIONS.put("RECOGNITIION", "RECOG");
513 ABBREVIATIONS.put("RECORD", "REC");
514 ABBREVIATIONS.put("REFERENCE", "REF");
515 ABBREVIATIONS.put("REGISTRATION", "REG");
516 ABBREVIATIONS.put("RELATION", "RELN");
517 ABBREVIATIONS.put("RELATIONSHIP", "RELN");
518 ABBREVIATIONS.put("ROLLOVER RESULT", "ROR");
519 ABBREVIATIONS.put("REQUEST", "RQST");
520 ABBREVIATIONS.put("REQUIRED", "REQ");
521 ABBREVIATIONS.put("REPONSIBLE", "RESP");
522 ABBREVIATIONS.put("RESOURCE", "RSRC");
523 ABBREVIATIONS.put("RESTRICTION", "RESTR");
524 ABBREVIATIONS.put("RESULT VALUE GROUP", "RVG");
525 ABBREVIATIONS.put("REVIEW", "REVIEW");
526 ABBREVIATIONS.put("RICH TEXT", "RT");
527 ABBREVIATIONS.put("SCHEDULE", "SCHED");
528 ABBREVIATIONS.put("SHORT", "SHRT");
529 ABBREVIATIONS.put("SLOT RULE", "SR");
530 ABBREVIATIONS.put("STANDARD", "STD");
531 ABBREVIATIONS.put("STATE", "ST");
532 ABBREVIATIONS.put("STATEMENT", "STMNT");
533 ABBREVIATIONS.put("STUDENT", "STU");
534 ABBREVIATIONS.put("STUDY", "STDY");
535 ABBREVIATIONS.put("SUBJECT", "SUBJ");
536 ABBREVIATIONS.put("SUFFIX", "SUFX");
537 ABBREVIATIONS.put("TEMPLATE", "TMPLT");
538 ABBREVIATIONS.put("TIME", "TM");
539 ABBREVIATIONS.put("TITLE", "TTL");
540 ABBREVIATIONS.put("TOTAL", "TOT");
541 ABBREVIATIONS.put("TRANSACTION", "TRANS");
542 ABBREVIATIONS.put("TYPE", "TYP");
543 ABBREVIATIONS.put("VARIATION", "VARTN");
544 ABBREVIATIONS.put("VERSION NUMBER", "VER_NBR");
545 ABBREVIATIONS.put("", "");
546 }
547
548 private String applyAbbreviations(String name) {
549
550
551 String[] parts = name.split("_");
552 for (int i = 0; i < parts.length; i++) {
553 String abbrev = ABBREVIATIONS.get(parts[i]);
554 if (abbrev != null) {
555 System.out.println("Replacing abbreviation " + parts[i] + " with " + abbrev);
556 parts[i] = abbrev;
557 }
558 }
559 name = StringUtils.join(parts, '_');
560 return name;
561 }
562
563 private boolean isNullable(MessageStructure ms) {
564 if (ms.getRequired() == null) {
565 return true;
566 }
567 if (ms.getRequired().equalsIgnoreCase("Required")) {
568 return false;
569 }
570
571
572 return true;
573 }
574
575 private String keyOrId() {
576
577 if (finder.findMessageStructure(xmlType.getName(), "id") != null) {
578 return "Id";
579 }
580 if (finder.findMessageStructure(xmlType.getName(), "key") != null) {
581 return "Key";
582 }
583 return "Id";
584 }
585
586 private boolean hasAttributes() {
587 for (MessageStructure ms : finder.findMessageStructures(xmlType.getName())) {
588 if (ms.getShortName().equals("attributes")) {
589 return true;
590 }
591 }
592 return false;
593 }
594
595 private boolean isMethodForThisType(XmlType xmlType, ServiceMethod method) {
596 String objectName = calcObjectName(method);
597 if (objectName == null) {
598 return false;
599 }
600 if (xmlType.getName().equalsIgnoreCase(objectName + "Info")) {
601 return true;
602 }
603 return false;
604 }
605
606
607
608
609 public void write() {
610 indentPrintln("@Entity");
611 importsAdd(Entity.class.getName());
612 String tableName = calcTableName(xmlType);
613 if (xmlType.getTableName() == null) {
614 indentPrintln("//TODO: JPAIMPL double check table name because it was calculated based on heuristics and may not match the actual table name");
615 }
616 indentPrintln("@Table(name = \"" + tableName + "\")");
617 importsAdd(Table.class.getName());
618
619
620
621
622
623
624 String className = calcClassName(servKey, xmlType);
625 String attributeEntity = JpaAttributeEntityWriter.calcClassName(servKey, xmlType);
626 indentPrintln("@NamedQueries({");
627 String comma = "";
628 for (ServiceMethod method : methods) {
629 if (!isMethodForThisType(xmlType, method)) {
630 continue;
631 }
632 MethodType methodType = calcMethodType(method);
633 switch (methodType) {
634 case GET_IDS_BY_TYPE:
635 indentPrint(comma);
636 comma = ",";
637 indentPrintln("@NamedQuery(name = \"" + className + ".getIdsByType\",");
638 indentPrintln(" query = \"select id from " + className + " where typeKey = :type\")");
639 break;
640 case GET_IDS_BY_OTHER:
641 indentPrintln("//TODO: JPAIMPL double check this JPQL queries to make sure they match the intention of the service method");
642 indentPrint(comma);
643 comma = ",";
644 String namedQuery = calcNamedQuery(method);
645 indentPrintln("@NamedQuery(name = \"" + className + "." + namedQuery + "\",");
646
647 indentPrint(" query = \"select id from " + className);
648 String and = " where ";
649 for (ServiceMethodParameter param : method.getParameters()) {
650 if (param.getType().equals("ContextInfo")) {
651 continue;
652 }
653 print(and);
654 and = " and ";
655 String paramName = initLower(param.getName());
656 print(paramName + " = :" + paramName);
657 }
658 println("\")");
659 break;
660 case GET_INFOS_BY_OTHER:
661 indentPrintln("//TODO: JPAIMPL double check this JPQL queries to make sure they match the intention of the service method");
662 indentPrint(comma);
663 comma = ",";
664 namedQuery = calcNamedQuery(method);
665 indentPrintln("@NamedQuery(name = \"" + className + "." + namedQuery + "\",");
666
667 indentPrint(" query = \"select " + className + " from " + className);
668 and = " where ";
669 for (ServiceMethodParameter param : method.getParameters()) {
670 if (param.getType().equals("ContextInfo")) {
671 continue;
672 }
673 print(and);
674 and = " and ";
675 String paramName = initLower(param.getName());
676 print(paramName + " = :" + paramName);
677 }
678 println("\")");
679 break;
680 }
681 }
682 indentPrintln("})");
683 importsAdd(NamedQueries.class.getName());
684 importsAdd(NamedQuery.class.getName());
685 indentPrint("public class " + calcClassName(servKey, xmlType));
686 println(" extends MetaEntity");
687 importsAdd("org.kuali.student.r2.common.entity.MetaEntity");
688
689 boolean hasAttributes = hasAttributes();
690 String attributeEntityName = JpaAttributeEntityWriter.calcClassName(servKey, xmlType);
691 if (hasAttributes) {
692 indentPrintln(" implements AttributeOwner<" + attributeEntityName + ">");
693 importsAdd("org.kuali.student.r2.common.entity.AttributeOwner");
694 }
695 openBrace();
696
697 for (MessageStructure ms : finder.findMessageStructures(xmlType.getName())) {
698 if (ms.getShortName().equalsIgnoreCase("id")) {
699 continue;
700 }
701 if (ms.getShortName().equalsIgnoreCase("meta")) {
702 continue;
703 }
704 if (ms.getShortName().equalsIgnoreCase("key")) {
705 continue;
706 }
707 if (ms.getShortName().equalsIgnoreCase("descr")) {
708 importsAdd(Column.class.getName());
709 importsAdd("org.kuali.student.r1.common.entity.KSEntityConstants");
710 indentPrintln("@Column(name = \"DESCR_PLAIN\", length = KSEntityConstants.EXTRA_LONG_TEXT_LENGTH, nullable = false)");
711 indentPrintln("private String descrPlain;");
712 indentPrintln("@Column(name = \"DESCR_FORMATTED\", length = KSEntityConstants.EXTRA_LONG_TEXT_LENGTH)");
713 indentPrintln("private String descrFormatted;");
714 continue;
715 }
716 if (ms.getShortName().equalsIgnoreCase("attributes")) {
717 importsAdd(OneToMany.class.getName());
718 importsAdd(CascadeType.class.getName());
719 importsAdd(FetchType.class.getName());
720 importsAdd(Set.class.getName());
721 importsAdd(HashSet.class.getName());
722 indentPrintln("@OneToMany(cascade = CascadeType.ALL, mappedBy = \"owner\", fetch = FetchType.EAGER, orphanRemoval = true)");
723 indentPrintln("private final Set<" + attributeEntity + "> attributes = new HashSet<" + attributeEntity + ">();");
724 JpaAttributeEntityWriter attrEntityWriter
725 = new JpaAttributeEntityWriter(model, directory, rootPackage, servKey, methods, xmlType, isR1, className);
726 attrEntityWriter.write();
727 continue;
728 }
729
730
731 importsAdd(Column.class.getName());
732 String columnName = calcColumnName(ms);
733 if (ms.getType().equalsIgnoreCase("Date")) {
734 importsAdd(Temporal.class.getName());
735 importsAdd(TemporalType.class.getName());
736 indentPrintln("@Temporal(TemporalType.TIMESTAMP)");
737 }
738 if (shouldAddJpaImplTodo(ms)) {
739 indentPrintln("//TODO: JPAIMPL double check column name it was calculated based on heuristics and may not match actual table column");
740 }
741 indentPrintln("@Column(name= \"" + columnName + "\", nullable=" + this.isNullable(ms) + ")");
742 String javaClass = this.calcType(ms.getType(), this.stripList(ms.getType()));
743 indentPrintln("private " + javaClass + " " + initLower(ms.getShortName()) + ";");
744 }
745
746 println("");
747
748
749
750
751
752
753
754
755
756 String infcName = this.calcInfcName();
757 println("");
758 indentPrintln("public " + className + "() {");
759 indentPrintln("}");
760 println("");
761 indentPrintln("public " + className + "(" + infcName + " dto) {");
762 incrementIndent();
763 indentPrintln("super(dto);");
764 String keyOrId = this.keyOrId();
765 indentPrintln("this.setId(dto.get" + keyOrId + "());");
766 indentPrintln("this.setTypeKey(dto.getTypeKey());");
767 indentPrintln("// TODO: JPAIMPL insert other fields that should only be specified on create");
768 indentPrintln("this.fromDto(dto);");
769 decrementIndent();
770 indentPrintln("}");
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793 println("");
794 indentPrintln("public void fromDto(" + infcName + " dto) {");
795 incrementIndent();
796 indentPrintln("super.fromDTO(dto);");
797 indentPrintln("// TODO: JPAIMPL move all fields that are only supposed to be only specified on create up to the constructor section (like type is)");
798 for (MessageStructure ms : finder.findMessageStructures(xmlType.getName())) {
799 if (ms.getShortName().equalsIgnoreCase("id")) {
800 continue;
801 }
802 if (ms.getShortName().equalsIgnoreCase("meta")) {
803 continue;
804 }
805 if (ms.getShortName().equalsIgnoreCase("key")) {
806 continue;
807 }
808 if (ms.getShortName().equalsIgnoreCase("typeKey")) {
809 continue;
810 }
811 if (ms.getShortName().equalsIgnoreCase("typeKey")) {
812 continue;
813 }
814 if (ms.getShortName().equalsIgnoreCase("descr")) {
815 println("");
816 indentPrintln("if (dto.getDescr() != null) {");
817 indentPrintln(" this.setDescrFormatted(dto.getDescr().getFormatted());");
818 indentPrintln(" this.setDescrPlain(dto.getDescr().getPlain());");
819 indentPrintln("} else {");
820 indentPrintln(" this.setDescrFormatted(null);");
821 indentPrintln(" this.setDescrPlain(null);");
822 indentPrintln("}");
823 println("");
824 continue;
825 }
826 if (ms.getShortName().equalsIgnoreCase("attributes")) {
827 importsAdd("org.kuali.student.r2.common.infc.Attribute");
828 println("");
829 indentPrintln("// dynamic attributes");
830 indentPrintln("this.getAttributes().clear();");
831 indentPrintln("for (Attribute att : dto.getAttributes()) {");
832 indentPrintln(" " + attributeEntityName + " attEntity = new " + attributeEntityName + "(att, this);");
833 indentPrintln(" this.getAttributes().add(attEntity);");
834 indentPrintln("}");
835 continue;
836 }
837
838 String upperName = initUpper(ms.getShortName());
839 indentPrintln("set" + upperName + "(dto.get" + upperName + "());");
840 }
841 decrementIndent();
842 indentPrintln("}");
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865 String infoName = this.calcInfoName();
866 println("");
867 indentPrintln("public " + infoName + " toDto() {");
868 incrementIndent();
869 indentPrintln(infoName + " info = new " + infoName + "();");
870 for (MessageStructure ms : finder.findMessageStructures(xmlType.getName())) {
871 if (ms.getShortName().equalsIgnoreCase("id")) {
872 indentPrintln("info.setId(getId());");
873 continue;
874 }
875 if (ms.getShortName().equalsIgnoreCase("meta")) {
876 indentPrintln("info.setMeta(super.toDTO());");
877 continue;
878 }
879 if (ms.getShortName().equalsIgnoreCase("key")) {
880 indentPrintln("info.setKey(getId());");
881 continue;
882 }
883 if (ms.getShortName().equalsIgnoreCase("descr")) {
884 importsAdd("org.kuali.student.r2.common.util.RichTextHelper");
885 indentPrintln("info.setDescr(new RichTextHelper().toRichTextInfo(getDescrPlain(), getDescrFormatted()));");
886 continue;
887 }
888 if (ms.getShortName().equalsIgnoreCase("attributes")) {
889 importsAdd("org.kuali.student.r2.common.dto.AttributeInfo");
890 println("");
891 indentPrintln("// dynamic attributes");
892 indentPrintln("for (" + attributeEntityName + " att : getAttributes()) {");
893 indentPrintln(" AttributeInfo attInfo = att.toDto();");
894 indentPrintln(" info.getAttributes().add(attInfo);");
895 indentPrintln("}");
896 continue;
897 }
898
899 String upperName = initUpper(ms.getShortName());
900 indentPrintln("info.set" + upperName + "(this.get" + upperName + "());");
901 }
902 indentPrintln("return info;");
903 decrementIndent();
904 indentPrintln("}");
905
906
907 for (MessageStructure ms : finder.findMessageStructures(xmlType.getName())) {
908 if (ms.getShortName().equalsIgnoreCase("id")) {
909 continue;
910 }
911 if (ms.getShortName().equalsIgnoreCase("meta")) {
912 continue;
913 }
914 if (ms.getShortName().equalsIgnoreCase("key")) {
915 continue;
916 }
917 if (ms.getShortName().equalsIgnoreCase("descr")) {
918 println("");
919 indentPrintln("public String getDescrPlain() {");
920 indentPrintln(" return this.descrPlain;");
921 indentPrintln("}");
922 println("");
923 indentPrintln("public void setDescrPlain(String descrPlain) {");
924 indentPrintln(" this.descrPlain = descrPlain;");
925 indentPrintln("}");
926 println("");
927 indentPrintln("public String getDescrFormatted() {");
928 indentPrintln(" return this.descrFormatted;");
929 indentPrintln("}");
930 println("");
931 indentPrintln("public void setDescrFormatted(String descrFormatted) {");
932 indentPrintln(" this.descrFormatted = descrFormatted;");
933 indentPrintln("}");
934 continue;
935 }
936 if (ms.getShortName().equalsIgnoreCase("attributes")) {
937 println("");
938 indentPrintln("@Override");
939 indentPrintln("public void setAttributes(Set<" + attributeEntityName + "> attributes) {");
940 incrementIndent();
941 indentPrintln("this.attributes.clear();");
942 indentPrintln("if (attributes != null) {");
943 indentPrintln(" this.attributes.addAll(attributes);");
944 indentPrintln("}");
945 decrementIndent();
946 indentPrintln("}");
947 println("");
948 indentPrintln("@Override");
949 indentPrintln("public Set<" + attributeEntityName + "> getAttributes() {");
950 indentPrintln(" return attributes;");
951 indentPrintln("}");
952 println("");
953 continue;
954 }
955 importsAdd(Column.class.getName());
956 String variableName = initLower(ms.getShortName());
957 String javaClass = this.calcType(ms.getType(), this.stripList(ms.getType()));
958 String upperName = initUpper(ms.getShortName());
959 println("");
960 indentPrintln("public " + javaClass + " get" + upperName + "() {");
961 indentPrintln(" return this." + variableName + ";");
962 indentPrintln("}");
963 println("");
964 indentPrintln("public void set" + upperName + "(" + javaClass + " " + variableName + ") {");
965 indentPrintln(" this." + variableName + " = " + variableName + ";");
966 indentPrintln("}");
967 }
968
969 println("");
970 closeBrace();
971
972 this.writeJavaClassAndImportsOutToFile();
973 this.getOut().close();
974 }
975
976 private boolean shouldAddJpaImplTodo(MessageStructure ms) {
977 if (ms.getColumnName() != null) {
978 return false;
979 }
980 if (ms.getShortName().equalsIgnoreCase("name")) {
981 return false;
982 }
983 if (ms.getShortName().equalsIgnoreCase("descr")) {
984 return false;
985 }
986 if (ms.getShortName().equalsIgnoreCase("effectiveDate")) {
987 return false;
988 }
989 if (ms.getShortName().equalsIgnoreCase("expirationDate")) {
990 return false;
991 }
992 return true;
993 }
994
995 private String getInvalidParameterException() {
996 if (this.isRice()) {
997 return "RiceIllegalArgumentException";
998 }
999 return "InvalidParameterException";
1000 }
1001
1002 private String getOperationFailedException() {
1003 if (this.isRice()) {
1004 return "RiceIllegalArgumentException";
1005 }
1006 return "OperationFailedException";
1007 }
1008
1009 private String getDoesNotExistException() {
1010 if (this.isRice()) {
1011 return "RiceIllegalArgumentException";
1012 }
1013 return "DoesNotExistException";
1014 }
1015
1016 private String getVersionMismatchException() {
1017 if (this.isRice()) {
1018 return "RiceIllegalStateException";
1019 }
1020 return "VersionMismatchException";
1021 }
1022
1023 private void writeThrowsNotImplemented(ServiceMethod method) {
1024 indentPrintln("throw new " + this.getOperationFailedException() + " (\"" + method.getName() + " has not been implemented\");");
1025 }
1026
1027 protected String initLower(String str) {
1028 return str.substring(0, 1).toLowerCase() + str.substring(1);
1029 }
1030
1031 private String calcCriteriaLookupServiceVariableName(ServiceMethod method) {
1032 String objectName = calcObjectName(method);
1033 String variableName = initLower(objectName) + "CriteriaLookupService";
1034 return variableName;
1035 }
1036
1037 private ServiceMethodParameter findIdParameter(ServiceMethod method) {
1038 String idFieldName = calcObjectName(method) + "Id";
1039 for (ServiceMethodParameter parameter : method.getParameters()) {
1040 if (parameter.getType().equals("String")) {
1041 if (parameter.getName().equals(idFieldName)) {
1042 return parameter;
1043 }
1044 }
1045 }
1046
1047
1048 if (method.getParameters().size() == 1) {
1049 for (ServiceMethodParameter parameter : method.getParameters()) {
1050 if (parameter.getType().equals("String")) {
1051 return parameter;
1052 }
1053 }
1054 }
1055
1056 for (ServiceMethodParameter parameter : method.getParameters()) {
1057 if (parameter.getType().equals("String")) {
1058 if (parameter.getName().endsWith("Id")) {
1059 return parameter;
1060 }
1061 }
1062 }
1063
1064 for (ServiceMethodParameter parameter : method.getParameters()) {
1065 if (parameter.getType().equals("String")) {
1066 if (!parameter.getName().endsWith("TypeKey")) {
1067 if (parameter.getName().endsWith("Key")) {
1068 return parameter;
1069 }
1070 }
1071 }
1072 }
1073 log.warn("Could not find the Id paramter for {}.{} so returning the first one", method.getService(), method.getName());
1074 return method.getParameters().get(0);
1075 }
1076
1077 private ServiceMethodParameter findContextParameter(ServiceMethod method) {
1078 for (ServiceMethodParameter parameter : method.getParameters()) {
1079 if (parameter.getType().equals("ContextInfo")) {
1080 return parameter;
1081 }
1082 }
1083 return null;
1084 }
1085
1086 private ServiceMethodParameter findInfoParameter(ServiceMethod method) {
1087 String objectName = calcObjectName(method);
1088 if (!this.isRice()) {
1089 objectName = objectName + "Info";
1090 }
1091 for (ServiceMethodParameter parameter : method.getParameters()) {
1092 if (parameter.getType().equals(objectName)) {
1093 return parameter;
1094 }
1095 }
1096 if (method.getParameters().size() >= 1) {
1097 return method.getParameters().get(0);
1098 }
1099 return null;
1100 }
1101
1102 private ServiceMethodParameter findTypeParameter(ServiceMethod method) {
1103 for (ServiceMethodParameter parameter : method.getParameters()) {
1104 if (parameter.getType().equals("String")) {
1105 if (parameter.getName().endsWith("TypeKey")) {
1106 return parameter;
1107 }
1108 if (parameter.getName().endsWith("Type")) {
1109 return parameter;
1110 }
1111 }
1112 }
1113 return null;
1114 }
1115
1116 private String calcDaoVariableName(ServiceMethod method) {
1117 String daoVariableName = this.calcObjectName(method);
1118 daoVariableName = this.initLower(daoVariableName) + "Dao";
1119 return daoVariableName;
1120 }
1121
1122 private String calcEntityClassName(ServiceMethod method) {
1123 String objectName = this.calcObjectName(method);
1124 objectName = objectName + "Entity";
1125 return objectName;
1126 }
1127
1128 protected String calcObjectName(ServiceMethod method) {
1129 if (method.getName().startsWith("create")) {
1130 return method.getName().substring("create".length());
1131 }
1132 if (method.getName().startsWith("update")) {
1133 return method.getName().substring("update".length());
1134 }
1135 if (method.getName().startsWith("validate")) {
1136 return method.getName().substring("validate".length());
1137 }
1138 if (method.getName().startsWith("delete")) {
1139 return method.getName().substring("delete".length());
1140 }
1141 if (method.getName().startsWith("get")) {
1142 if (method.getReturnValue().getType().equals("StringList")) {
1143 if (method.getName().contains("IdsBy")) {
1144 return method.getName().substring("get".length(),
1145 method.getName().indexOf("IdsBy"));
1146 }
1147 if (method.getName().contains("KeysBy")) {
1148 return method.getName().substring("get".length(),
1149 method.getName().indexOf("KeysBy"));
1150 }
1151 if (method.getName().contains("IdsFor")) {
1152 return method.getName().substring("get".length(),
1153 method.getName().indexOf("IdsFor"));
1154 }
1155 if (method.getName().contains("With")) {
1156 return method.getName().substring("get".length(),
1157 method.getName().indexOf("With"));
1158 }
1159 if (method.getName().contains("By")) {
1160 return method.getName().substring("get".length(),
1161 method.getName().indexOf("By"));
1162 }
1163 return method.getName().substring("get".length());
1164 }
1165 String name = method.getReturnValue().getType();
1166 if (name.endsWith("List")) {
1167 name = name.substring(0, name.length() - "List".length());
1168 }
1169 if (name.endsWith("Info")) {
1170 name = name.substring(0, name.length() - "Info".length());
1171 }
1172 return name;
1173 }
1174
1175 if (method.getName().startsWith("searchFor")) {
1176 if (method.getReturnValue().getType().equals("StringList")) {
1177 if (method.getName().endsWith("Ids")) {
1178 return method.getName().substring("searchFor".length(),
1179 method.getName().indexOf("Ids"));
1180 }
1181 if (method.getName().endsWith("Keys")) {
1182 return method.getName().substring("get".length(),
1183 method.getName().indexOf("Keys"));
1184 }
1185 return method.getName().substring("searchFor".length());
1186 }
1187 String name = method.getReturnValue().getType();
1188 if (name.endsWith("List")) {
1189 name = name.substring(0, name.length() - "List".length());
1190 }
1191 if (name.endsWith("Info")) {
1192 name = name.substring(0, name.length() - "Info".length());
1193 }
1194 return name;
1195 }
1196 if (method.getName().startsWith("add")) {
1197 return method.getName().substring("add".length());
1198 }
1199 if (method.getName().startsWith("remove")) {
1200 return method.getName().substring("remove".length());
1201 }
1202 String returnType = this.stripList(method.getReturnValue().getType());
1203 XmlType type = this.finder.findXmlType(returnType);
1204 if (type.getPrimitive().equals(XmlType.COMPLEX)) {
1205 return returnType;
1206 }
1207 return null;
1208 }
1209
1210 private String calcNamedQuery(ServiceMethod method) {
1211 String objectName = calcObjectName(method);
1212 if (objectName == null) {
1213 return null;
1214 }
1215 String name = method.getName();
1216 if (name.startsWith("get")) {
1217 name = name.substring("get".length());
1218 }
1219 if (name.startsWith(objectName)) {
1220 name = name.substring(objectName.length());
1221 }
1222
1223
1224
1225
1226
1227
1228
1229 if (!method.getReturnValue().getType().equals("StringList")) {
1230 if (name.startsWith("s")) {
1231 name = name.substring("s".length());
1232 }
1233 }
1234
1235 name = "get" + name;
1236 return name;
1237 }
1238
1239 private ServiceMethodParameter findCriteriaParam(ServiceMethod method) {
1240 for (ServiceMethodParameter param : method.getParameters()) {
1241 if (param.getType().equals("QueryByCriteria")) {
1242 return param;
1243 }
1244 }
1245 return null;
1246 }
1247
1248 private ServiceMethodParameter getTypeParameter(ServiceMethod method) {
1249 ServiceMethodParameter fallbackParam = null;
1250 for (ServiceMethodParameter parameter : method.getParameters()) {
1251 if (parameter.getName().endsWith("TypeKey")) {
1252 return parameter;
1253 }
1254 if (parameter.getType().equals("String")) {
1255 if (parameter.getName().toLowerCase().contains("type")) {
1256 fallbackParam = parameter;
1257 }
1258 }
1259 }
1260 return fallbackParam;
1261 }
1262
1263 private String calcInfoName(ServiceMethod method) {
1264 String objectName = this.calcObjectName(method);
1265 String infoName = objectName;
1266 if (!this.isRice()) {
1267 infoName = infoName + "Info";
1268 }
1269 return infoName;
1270 }
1271
1272 private String initUpper(String str) {
1273 return str.substring(0, 1).toUpperCase() + str.substring(1);
1274 }
1275
1276 private ServiceMethodParameter findIdListParameter(ServiceMethod method) {
1277 String idFieldName = calcObjectName(method) + "Ids";
1278 if (this.isRice()) {
1279 idFieldName = "ids";
1280 }
1281 for (ServiceMethodParameter parameter : method.getParameters()) {
1282 if (parameter.getType().equals("StringList")) {
1283 if (parameter.getName().equals(idFieldName)) {
1284 return parameter;
1285 }
1286 }
1287 }
1288
1289 for (ServiceMethodParameter parameter : method.getParameters()) {
1290 if (parameter.getType().equals("StringList")) {
1291 if (parameter.getName().endsWith("Ids")) {
1292 return parameter;
1293 }
1294 }
1295 }
1296
1297 for (ServiceMethodParameter parameter : method.getParameters()) {
1298 if (parameter.getType().equals("StringList")) {
1299 if (parameter.getName().endsWith("Keys")) {
1300 return parameter;
1301 }
1302 }
1303 }
1304 return null;
1305 }
1306
1307 private String stripList(String str) {
1308 return GetterSetterNameCalculator.stripList(str);
1309 }
1310
1311 private String calcExceptionClassName(ServiceMethodError error) {
1312 if (error.getClassName() == null) {
1313 return ServiceExceptionWriter.calcClassName(error.getType());
1314 }
1315 return error.getClassName();
1316 }
1317
1318 private String calcExceptionPackageName(ServiceMethodError error) {
1319 if (error.getClassName() == null) {
1320 return ServiceExceptionWriter.calcPackage(rootPackage);
1321 }
1322 return error.getPackageName();
1323 }
1324
1325 private String calcType(String type, String realType) {
1326 XmlType t = finder.findXmlType(this.stripList(type));
1327 String retType = MessageStructureTypeCalculator.calculate(this, model, type, realType,
1328 t.getJavaPackage());
1329 if (this.isRice()) {
1330 if (retType.equals("Boolean")) {
1331 retType = "boolean";
1332 }
1333 if (retType.equals("Void")) {
1334 retType = "void";
1335 }
1336 }
1337 return retType;
1338 }
1339 }