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