1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.student.contract.model.util;
17
18 import java.io.File;
19 import java.io.FileNotFoundException;
20 import java.io.FileOutputStream;
21 import java.io.PrintStream;
22 import java.text.BreakIterator;
23 import java.util.Collections;
24 import java.util.Date;
25 import java.util.Enumeration;
26 import java.util.HashMap;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Stack;
30 import org.apache.commons.lang.StringEscapeUtils;
31
32 import org.kuali.student.contract.model.MessageStructure;
33 import org.kuali.student.contract.model.ServiceContractModel;
34 import org.kuali.student.contract.model.XmlType;
35 import org.kuali.student.contract.writer.XmlWriter;
36
37
38
39
40
41 public class KradDictionaryCreator {
42
43 private ServiceContractModel model;
44 private ModelFinder finder;
45 private String directory;
46 private String className;
47 private XmlType xmlType;
48 private XmlWriter gwriter;
49 private XmlWriter mwriter;
50 private List<MessageStructure> messageStructures;
51 private boolean writeManual;
52 private boolean writeGenerated;
53
54 public KradDictionaryCreator(String directory,
55 ServiceContractModel model, String className, boolean writeManual, boolean writeGenerated) {
56 this.directory = directory;
57 this.model = model;
58 this.finder = new ModelFinder(this.model);
59 this.className = className;
60 this.xmlType = this.finder.findXmlType(className);
61 if (xmlType == null) {
62 throw new IllegalArgumentException(className);
63 }
64 this.messageStructures = this.finder.findMessageStructures(className);
65 this.writeManual = writeManual;
66 this.writeGenerated = writeGenerated;
67
68
69
70 }
71
72 public void write() {
73 this.initXmlWriters();
74 if (writeGenerated) {
75 this.writeSpringHeaderOpen(gwriter);
76 this.writeWarning(gwriter);
77 this.writeGeneratedImports(gwriter);
78 this.writeGeneratedObjectStructure(gwriter);
79 this.writeSpringHeaderClose(gwriter);
80 }
81 if (this.writeManual) {
82 this.writeSpringHeaderOpen(mwriter);
83 this.writeNote(mwriter);
84 this.writeManualImports(mwriter);
85 this.writeManualObjectStructure(mwriter);
86 this.writeSpringHeaderClose(mwriter);
87 }
88 }
89
90 private void initXmlWriters() {
91 String generatedFileName = "/ks-" + initUpper(className) + "-dictionary-generated.xml";
92 String manualFileName = "/ks-" + initUpper(className) + "-dictionary.xml";
93
94 File dir = new File(this.directory);
95
96
97 if (!dir.exists()) {
98 if (!dir.mkdirs()) {
99 throw new IllegalStateException("Could not create directory "
100 + this.directory);
101 }
102 }
103
104 if (writeGenerated) {
105 try {
106 PrintStream out = new PrintStream(new FileOutputStream(this.directory + "/" + generatedFileName, false));
107 this.gwriter = new XmlWriter(out, 0);
108 } catch (FileNotFoundException ex) {
109 throw new IllegalStateException(ex);
110 }
111 }
112 if (this.writeManual) {
113 try {
114 PrintStream out = new PrintStream(new FileOutputStream(this.directory + "/" + manualFileName, false));
115 this.mwriter = new XmlWriter(out, 0);
116 } catch (FileNotFoundException ex) {
117 throw new IllegalStateException(ex);
118 }
119 }
120 }
121
122 private static String initLower(String str) {
123 if (str == null) {
124 return null;
125 }
126 if (str.length() == 0) {
127 return str;
128 }
129 if (str.length() == 1) {
130 return str.toLowerCase();
131 }
132 return str.substring(0, 1).toLowerCase() + str.substring(1);
133 }
134
135 private static String initUpper(String str) {
136 if (str == null) {
137 return null;
138 }
139 if (str.length() == 0) {
140 return str;
141 }
142 if (str.length() == 1) {
143 return str.toUpperCase();
144 }
145 return str.substring(0, 1).toUpperCase() + str.substring(1);
146 }
147
148 private void writeSpringHeaderClose(XmlWriter out) {
149 out.decrementIndent();
150 out.indentPrintln("</beans>");
151 }
152
153 private void writeSpringHeaderOpen(XmlWriter out) {
154 out.indentPrintln("<!--");
155 out.indentPrintln(" Copyright 2011 The Kuali Foundation");
156 out.println("");
157 out.indentPrintln(" Licensed under the Educational Community License, Version 2.0 (the \"License\");");
158 out.indentPrintln(" you may not use this file except in compliance with the License.");
159 out.indentPrintln(" You may obtain a copy of the License at");
160 out.indentPrintln("");
161 out.indentPrintln(" http://www.opensource.org/licenses/ecl2.php");
162 out.println("");
163 out.indentPrintln(" Unless required by applicable law or agreed to in writing, software");
164 out.indentPrintln(" distributed under the License is distributed on an \"AS IS\" BASIS,");
165 out.indentPrintln(" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.");
166 out.indentPrintln(" See the License for the specific language governing permissions and");
167 out.indentPrintln(" limitations under the License.");
168 out.indentPrintln("-->");
169 out.indentPrintln("<beans xmlns=\"http://www.springframework.org/schema/beans\"");
170 out.indentPrintln("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
171 out.indentPrintln("xsi:schemaLocation=\""
172 + "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd" + "\">");
173 out.println("");
174 out.incrementIndent();
175 }
176
177 private void writeWarning(XmlWriter out) {
178 out.println("");
179 out.indentPrintln("<!-- ********************************************************");
180 out.incrementIndent();
181 out.indentPrintln(" WARNING ");
182 out.indentPrintln(" DO NOT UPDATE THIS FILE MANUALLY");
183 out.indentPrintln("This dictionary file was automatically generated on " + new Date());
184 out.indentPrintln("The DictionaryGeneratorMojo reads the service contract ");
185 out.indentPrintln("and creates these ks-XXXX-dictionary-generated.xml files.");
186 out.println("");
187 out.indentPrintln("If this file is out of sync with the contract re-run the mojo.");
188 out.println("");
189 out.indentPrintln("To add additional constraints or change these default values (perhaps");
190 out.indentPrintln("because the generator is not perfect) please update the corresponding ");
191 out.indentPrintln("ks-XXXX-dictionary.xml instead of this one.");
192 out.decrementIndent();
193 out.indentPrintln("************************************************************* -->");
194 }
195
196 private void writeNote(XmlWriter out) {
197 out.println("");
198 out.indentPrintln("<!-- ********************************************************");
199 out.incrementIndent();
200 out.indentPrintln(" NOTE");
201 out.indentPrintln(" THIS FILE WAS INTENDED TO BE MODIFIED");
202 out.println("");
203 out.indentPrintln("While this file was originally generated on " + new Date() + ", it");
204 out.indentPrintln("was intended to be subsequently modified by hand.");
205 out.indentPrintln("It imports a corresponding ks-XXXX-dictionary-generated.xml file, ");
206 out.indentPrintln("that was also automatically generated by the ContractDocMojo.");
207 out.indentPrintln("This file gives you the ability to layer on addiditional definitions and constrints");
208 out.indentPrintln("that are not/cannot be generated simply by reading the service contract.");
209 out.println("");
210 out.indentPrintln("The goal of this file is to be able to re-generate the corresponding");
211 out.indentPrintln("ks-XXXX-dictionary-generated.xml file without affecting these manually entered additions");
212 out.indentPrintln("that are encoded here.");
213 out.decrementIndent();
214 out.indentPrintln("************************************************************* -->");
215 }
216
217 private void writeGeneratedImports(XmlWriter out) {
218 out.indentPrintln("<import resource=\"classpath:ks-base-dictionary.xml\"/>");
219
220
221
222 }
223
224 private void writeManualImports(XmlWriter out) {
225 out.writeComment("This file gets generated during the build and put into the target/classes directory");
226 out.indentPrintln("<import resource=\"classpath:ks-" + initUpper(className) + "-dictionary-generated.xml\"/>");
227 }
228
229 private String stripListOffEnd(String name) {
230 if (name.endsWith("List")) {
231 return name.substring(0, name.length() - "List".length());
232 }
233 return name;
234 }
235
236 private void writeSubStructures(XmlType type, Stack<String> stack) {
237 boolean first = true;
238 for (MessageStructure ms : finder.findMessageStructures(type.getName())) {
239
240 if (ms.getShortName().equals("attributes")) {
241 continue;
242 }
243 XmlType st = finder.findXmlType(this.stripListOffEnd(ms.getType()));
244 if (st == null) {
245 throw new NullPointerException(ms.getType() + " does not exist in list of types with parents " + calcParents(stack));
246 }
247 if (!st.getPrimitive().equalsIgnoreCase(XmlType.COMPLEX)) {
248 continue;
249 }
250 if (first) {
251 first = false;
252 gwriter.indentPrintln("<ul>");
253 }
254 if (!stack.contains(st.getName())) {
255 stack.push(st.getName());
256 this.writeSubStructures(st, stack);
257 stack.pop();
258 }
259 }
260 if (!first) {
261 gwriter.indentPrintln("</ul>");
262 }
263 }
264
265 private String calcParents(Stack<String> stack) {
266 StringBuilder sb = new StringBuilder();
267 String dot = "";
268 Enumeration<String> en = stack.elements();
269 while (en.hasMoreElements()) {
270 sb.append(dot);
271 dot = ".";
272 sb.append(en.nextElement());
273 }
274 return sb.toString();
275 }
276
277 private void writeGeneratedObjectStructure(XmlWriter out) {
278
279 out.println("");
280 out.indentPrintln("<!-- " + className + "-->");
281 out.indentPrintln("<bean id=\"" + initUpper(className) + "-generated\" abstract=\"true\" parent=\"DataObjectEntry\">");
282 out.incrementIndent();
283 writeProperty("name", initLower(className), out);
284 writeProperty("objectClass", xmlType.getJavaPackage() + "." + initUpper(className), out);
285 writeProperty("objectLabel", calcObjectLabel(), out);
286 writeProperty("objectDescription", xmlType.getDesc(), out);
287 String titleAttribute = calcTitleAttribute();
288 if (titleAttribute != null) {
289 writeProperty("titleAttribute", titleAttribute, out);
290 }
291 out.indentPrintln("<property name=\"primaryKeys\">");
292 List<String> pks = calcPrimaryKeys();
293 if (pks != null && !pks.isEmpty()) {
294 out.incrementIndent();
295 out.indentPrintln("<list>");
296 out.incrementIndent();
297 for (String pk : pks) {
298 addValue(pk);
299 }
300 out.decrementIndent();
301 out.indentPrintln("</list>");
302 out.decrementIndent();
303 }
304 out.indentPrintln("</property>");
305 out.indentPrintln("<property name=\"attributes\">");
306 out.incrementIndent();
307 out.indentPrintln("<list>");
308 out.incrementIndent();
309 this.writeGeneratedAttributeRefBeans(className, null, new Stack<String>(), this.messageStructures, out);
310 out.decrementIndent();
311 out.indentPrintln("</list>");
312 out.decrementIndent();
313 out.indentPrintln("</property>");
314 out.decrementIndent();
315 out.indentPrintln("</bean>");
316
317
318 this.writeGeneratedAttributeDefinitions(className, null, new Stack<String>(), this.messageStructures, out);
319
320 }
321
322 private void addValue(String value) {
323 gwriter.indentPrintln("<value>" + value + "</value>");
324 }
325
326 private String calcObjectLabel() {
327 String label = this.className;
328 if (label.endsWith("Info")) {
329 label = label.substring(0, label.length() - "Info".length());
330 }
331 label = initUpper(label);
332 return splitCamelCase(label);
333 }
334
335
336 private static String splitCamelCase(String s) {
337 if (s == null) {
338 return null;
339 }
340 return s.replaceAll(
341 String.format("%s|%s|%s",
342 "(?<=[A-Z])(?=[A-Z][a-z])",
343 "(?<=[^A-Z])(?=[A-Z])",
344 "(?<=[A-Za-z])(?=[^A-Za-z])"),
345 " ");
346 }
347
348 private void writeGeneratedAttributeRefBeans(String currentClass, String parentName,
349 Stack<String> parents, List<MessageStructure> fields, XmlWriter out) {
350 if (parents.contains(currentClass)) {
351 return;
352 }
353 for (MessageStructure ms : fields) {
354
355 if (ms.getShortName().equals("attributes")) {
356 continue;
357 }
358 String name = calcName(parentName, ms);
359 String beanName = calcBeanName(name);
360 out.indentPrintln("<ref bean=\"" + beanName + "\"/>");
361
362 String childXmlTypeName = this.stripListOffEnd(ms.getType());
363 XmlType childXmlType = this.finder.findXmlType(childXmlTypeName);
364 if (childXmlType == null) {
365 throw new IllegalStateException(childXmlTypeName);
366 }
367 if (childXmlType.getPrimitive().equalsIgnoreCase(XmlType.COMPLEX)) {
368 parents.push(currentClass);
369 List<MessageStructure> childFields = this.finder.findMessageStructures(childXmlTypeName);
370
371
372
373 writeGeneratedAttributeRefBeans(childXmlTypeName, name, parents, childFields, out);
374 parents.pop();
375 }
376 }
377 }
378
379 private void writeGeneratedAttributeDefinitions(String currentClassName, String parentName,
380 Stack<String> parents, List<MessageStructure> fields, XmlWriter out) {
381 if (parents.contains(currentClassName)) {
382 return;
383 }
384 for (MessageStructure ms : fields) {
385
386 if (ms.getShortName().equals("attributes")) {
387 continue;
388 }
389 String name = calcName(parentName, ms);
390 String beanName = calcBeanName(name);
391 String childXmlTypeName = this.stripListOffEnd(ms.getType());
392 XmlType childXmlType = this.finder.findXmlType(childXmlTypeName);
393 if (childXmlType == null) {
394 throw new IllegalStateException(childXmlTypeName);
395 }
396 writeGeneratedAttributeDefinition(currentClassName, parentName, ms, out);
397
398
399 if (childXmlType.getPrimitive().equalsIgnoreCase(XmlType.COMPLEX)) {
400 parents.push(currentClassName);
401 List<MessageStructure> childFields = this.finder.findMessageStructures(childXmlTypeName);
402
403
404
405 writeGeneratedAttributeDefinitions(childXmlTypeName, name, parents, childFields, out);
406 parents.pop();
407 }
408 }
409 }
410
411 private boolean shouldWriteDetails(MessageStructure ms) {
412 if (predefinedFieldMap.get(ms.getShortName().toLowerCase()) == null) {
413 return true;
414 }
415 if (ms.isOverriden()) {
416 return true;
417 }
418
419 return false;
420 }
421
422 private void writeGeneratedAttributeDefinition(String currentClassName, String parentName, MessageStructure ms, XmlWriter out) {
423
424
425 String name = calcName(parentName, ms);
426 String beanName = calcBeanName(name);
427 String baseKualiType = this.calcBaseKualiType(ms);
428 out.println("");
429 out.indentPrintln("<bean id=\"" + beanName + "-generated\" abstract=\"true\" parent=\"" + baseKualiType + "\">");
430 out.incrementIndent();
431 writeProperty("name", name, out);
432 writeProperty("childEntryName", calcChildEntryName(ms), out);
433 if (this.shouldWriteDetails(ms)) {
434 writeProperty("required", calcRequired(ms), out);
435 writeProperty("shortLabel", calcShortLabel(ms), out);
436 writePropertyValue("summary", calcSummary(ms), out);
437 writeProperty("label", calcLabel(ms), out);
438 writePropertyValue("description", calcDescription(ms), out);
439 if (this.calcReadOnly(ms)) {
440 this.writeReadOnlyAttributeSecurity(out);
441 }
442 }
443 out.decrementIndent();
444
445
446
447
448 out.indentPrintln("</bean>");
449 }
450
451 private String calcBeanName(String name) {
452 return initUpper(className) + "." + name;
453 }
454
455 private String calcName(String parentName, MessageStructure ms) {
456 String name = this.calcChildEntryName(ms);
457 if (parentName == null) {
458 return name;
459 }
460 return parentName + "." + name;
461 }
462
463 private String calcChildEntryName(MessageStructure ms) {
464 String name = initLower(ms.getShortName());
465 return name;
466 }
467
468 private boolean calcReadOnly(MessageStructure ms) {
469 if (ms.getReadOnly() == null) {
470 return false;
471 }
472 return true;
473 }
474
475 private void writeReadOnlyAttributeSecurity(XmlWriter out) {
476 out.println("<property name=\"attributeSecurity\">");
477 out.println("<ref bean=\"BaseKuali.readOnlyAttributeSecurity\"/>");
478 out.println("</property>");
479 }
480
481 private String calcShortLabel(MessageStructure ms) {
482 return this.splitCamelCase(initUpper(ms.getShortName()));
483 }
484
485 private String calcLabel(MessageStructure ms) {
486 return ms.getName();
487 }
488
489 private String calcSummary(MessageStructure ms) {
490 BreakIterator bi = BreakIterator.getSentenceInstance();
491 String description = ms.getDescription();
492 if (description == null) {
493 return "???";
494 }
495 bi.setText(ms.getDescription());
496
497 if (bi.next() == BreakIterator.DONE) {
498 return ms.getDescription();
499 }
500 String firstSentence = description.substring(0, bi.current());
501 return firstSentence;
502 }
503
504 private String calcDescription(MessageStructure ms) {
505 return ms.getDescription();
506 }
507
508 private String calcRequired(MessageStructure ms) {
509 if (ms.getRequired() == null) {
510 return "false";
511 }
512 if (ms.getRequired().equalsIgnoreCase("Required")) {
513 return "true";
514 }
515
516 return "false";
517 }
518
519 private void writeManualObjectStructure(XmlWriter out) {
520
521 out.println("");
522 out.indentPrintln("<!-- " + className + "-->");
523 out.indentPrintln("<bean id=\"" + initUpper(className) + "-parent\" abstract=\"true\" parent=\"" + initUpper(className) + "-generated\">");
524 out.writeComment("insert any overrides to the generated object definitions here");
525 out.indentPrintln("</bean>");
526
527
528 out.indentPrintln("<bean id=\"" + initUpper(className) + "\" parent=\"" + initUpper(className) + "-parent\"/>");
529 out.println("");
530
531
532 this.writeManualAttributeDefinitions(className, null, new Stack<String>(), this.messageStructures, out);
533
534 }
535
536 private void writeManualAttributeDefinitions(String currentClass, String parentName,
537 Stack<String> parents, List<MessageStructure> fields, XmlWriter out) {
538 if (parents.contains(currentClass)) {
539 return;
540 }
541 for (MessageStructure ms : fields) {
542
543 if (ms.getShortName().equals("attributes")) {
544 continue;
545 }
546 String name = calcName(parentName, ms);
547 String beanName = calcBeanName(name);
548 String childXmlTypeName = this.stripListOffEnd(ms.getType());
549 XmlType childXmlType = this.finder.findXmlType(childXmlTypeName);
550 if (childXmlType == null) {
551 throw new IllegalStateException(childXmlTypeName);
552 }
553 writeManualAttributeDefinition(currentClass, parentName, ms, out);
554
555
556 if (childXmlType.getPrimitive().equalsIgnoreCase(XmlType.COMPLEX)) {
557 parents.push(currentClass);
558 List<MessageStructure> childFields = this.finder.findMessageStructures(childXmlTypeName);
559
560
561
562 writeManualAttributeDefinitions(childXmlTypeName, name, parents, childFields, out);
563 parents.pop();
564 }
565 }
566 }
567
568 private void writeManualAttributeDefinition(String currentClass, String parentName, MessageStructure ms, XmlWriter out) {
569
570
571 String name = calcName(parentName, ms);
572 String beanName = calcBeanName(name);
573
574 out.println("");
575 out.indentPrintln("<bean id=\"" + beanName + "-parent\" abstract=\"true\" parent=\"" + beanName + "-generated\">");
576 out.writeComment("insert any overrides to the generated attribute definitions here");
577 out.indentPrintln("</bean>");
578
579
580 out.indentPrintln("<bean id=\"" + beanName + "\" parent=\"" + beanName + "-parent\"/>");
581 }
582
583
584
585 private static Map<String, String> predefinedFieldMap = null;
586
587 {
588 Map<String, String> map = new HashMap<String, String>();
589 map.put("id", "BaseKuali.id");
590 map.put("key", "BaseKuali.key");
591 map.put("name", "BaseKuali.name");
592 map.put("descr", "BaseKuali.descr");
593 map.put("plain", "BaseKuali.descr.plain");
594 map.put("formatted", "BaseKuali.descr.formatted");
595 map.put("desc", "BaseKuali.desc");
596 map.put("typeKey", "BaseKuali.typeKey");
597 map.put("stateKey", "BaseKuali.stateKey");
598 map.put("type", "BaseKuali.type");
599 map.put("state", "BaseKuali.state");
600 map.put("effectiveDate", "BaseKuali.effectiveDate");
601 map.put("expirationDate", "BaseKuali.expirationDate");
602 map.put("meta", "BaseKuali.meta");
603 map.put("createTime", "BaseKuali.meta.createTime");
604 map.put("updateTime", "BaseKuali.meta.updateTime");
605 map.put("createId", "BaseKuali.meta.createId");
606 map.put("updateId", "BaseKuali.meta.updateId");
607 map.put("versionInd", "BaseKuali.meta.versionInd");
608
609 predefinedFieldMap = new HashMap(map.size());
610 for (String key : map.keySet()) {
611 predefinedFieldMap.put(key.toLowerCase(), map.get(key));
612 }
613 }
614
615
616
617
618 private static Map<String, String> endsWithMap = null;
619
620 {
621 Map<String, String> map = new HashMap<String, String>();
622 map.put("startDate", "BaseKuali.startDate");
623 map.put("endDate", "BaseKuali.endDate");
624 map.put("OrgId", "BaseKuali.orgId");
625 map.put("OrgIds", "BaseKuali.orgId");
626 map.put("PersonId", "BaseKuali.personId");
627 map.put("PersonIds", "BaseKuali.personId");
628 map.put("PrincipalId", "BaseKuali.principalId");
629 map.put("PrincipalIds", "BaseKuali.principalId");
630 map.put("CluId", "BaseKuali.cluId");
631 map.put("CluIds", "BaseKuali.cluId");
632 map.put("LuiId", "BaseKuali.luiId");
633 map.put("LuiIds", "BaseKuali.luiId");
634 map.put("AtpKey", "BaseKuali.atpKey");
635 map.put("AtpKeys", "BaseKuali.atpKey");
636 map.put("TermKey", "BaseKuali.termKey");
637 map.put("TermKeys", "BaseKuali.termKey");
638 map.put("CampusCalendarKey", "BaseKuali.campusCalendarKey");
639 map.put("CampusCalendarKeys", "BaseKuali.campusCalendarKey");
640 map.put("Code", "BaseKuali.code");
641
642 endsWithMap = new HashMap(map.size());
643 for (String key : map.keySet()) {
644 endsWithMap.put(key.toLowerCase(), map.get(key));
645 }
646 }
647
648
649
650
651
652 private static Map<String, String> typeMap = null;
653
654 {
655 Map<String, String> map = new HashMap<String, String>();
656 map.put("String", "BaseKuali.string");
657 map.put("DateTime", "BaseKuali.dateTime");
658 map.put("Date", "BaseKuali.date");
659 map.put("Boolean", "BaseKuali.boolean");
660 map.put("Integer", "BaseKuali.integer");
661 map.put("Complex", "BaseKuali.complex");
662
663 typeMap = new HashMap(map.size());
664 for (String key : map.keySet()) {
665 typeMap.put(key.toLowerCase (), map.get(key));
666 }
667 }
668
669 private String calcBaseKualiType(MessageStructure ms) {
670
671 String name = ms.getShortName();
672 String baseKualiType = predefinedFieldMap.get(name.toLowerCase());
673 if (baseKualiType != null) {
674 return baseKualiType;
675 }
676
677
678 for (String key : endsWithMap.keySet()) {
679 if (name.toLowerCase ().endsWith(key)) {
680 return endsWithMap.get(key);
681 }
682 }
683
684
685 String type = this.stripListOffEnd(ms.getType());
686 baseKualiType = typeMap.get(type.toLowerCase());
687 if (baseKualiType != null) {
688 return baseKualiType;
689 }
690
691
692 return "BaseKuali.string";
693
694 }
695
696 private String calcTitleAttribute() {
697 MessageStructure ms = null;
698 ms = this.findMessageStructure("name");
699 if (ms != null) {
700 return initLower(ms.getShortName());
701 }
702 ms = this.findMessageStructure("title");
703 if (ms != null) {
704 return initLower(ms.getShortName());
705 }
706 ms = this.findMessageStructureEndsWith("name");
707 if (ms != null) {
708 return initLower(ms.getShortName());
709 }
710 ms = this.findMessageStructureEndsWith("title");
711 if (ms != null) {
712 return initLower(ms.getShortName());
713 }
714 ms = this.findMessageStructure("key");
715 if (ms != null) {
716 return initLower(ms.getShortName());
717 }
718
719 System.out.println("XmlKradBaseDictionaryCreator: could not find a title attribute for " + this.className);
720
721
722
723
724 return null;
725 }
726
727 private MessageStructure findMessageStructureEndsWith(String shortNameEndsWith) {
728 shortNameEndsWith = shortNameEndsWith.toLowerCase();
729 for (MessageStructure ms : this.messageStructures) {
730 if (ms.getShortName().toLowerCase().endsWith(shortNameEndsWith)) {
731 return ms;
732 }
733 }
734 return null;
735 }
736
737 private MessageStructure findMessageStructure(String shortName) {
738 for (MessageStructure ms : this.messageStructures) {
739 if (ms.getShortName().equalsIgnoreCase(shortName)) {
740 return ms;
741 }
742 }
743 return null;
744 }
745
746 private MessageStructure getMessageStructure(String shortName) {
747 MessageStructure ms = this.findMessageStructure(shortName);
748 if (ms == null) {
749 throw new IllegalArgumentException(shortName);
750 }
751 return ms;
752 }
753
754 private List<String> calcPrimaryKeys() {
755 MessageStructure ms = null;
756 ms = this.findMessageStructure("id");
757 if (ms != null) {
758 return Collections.singletonList(initLower(ms.getShortName()));
759 }
760 ms = this.findMessageStructure("key");
761 if (ms != null) {
762 return Collections.singletonList(initLower(ms.getShortName()));
763 }
764
765 if (this.messageStructures.size() > 0) {
766 ms = this.messageStructures.get(0);
767 return Collections.singletonList(ms.getShortName());
768 }
769 return Collections.EMPTY_LIST;
770 }
771
772 private void writeProperty(String propertyName, String propertyValue, XmlWriter out) {
773 out.indentPrintln("<property name=\"" + propertyName + "\" value=\"" + replaceDoubleQuotes(propertyValue) + "\"/>");
774 }
775
776 private void writePropertyValue(String propertyName, String propertyValue, XmlWriter out) {
777 out.indentPrintln("<property name=\"" + propertyName + "\">");
778 out.incrementIndent();
779 out.indentPrintln("<value>");
780
781 out.println(escapeHtml(propertyValue));
782 out.indentPrintln("</value>");
783 out.decrementIndent();
784 out.indentPrintln("</property>");
785 }
786
787 private String escapeHtml(String str) {
788 if (str == null) {
789 return null;
790 }
791 return StringEscapeUtils.escapeHtml(str);
792 }
793
794 private String replaceDoubleQuotes(String str) {
795 if (str == null) {
796 return null;
797 }
798 return str.replace("\"", "'");
799 }
800 }