Clover Coverage Report - KS Common 1.2-M4-SNAPSHOT (Aggregated)
Coverage timestamp: Wed Jul 20 2011 12:23:34 EDT
../../../../../../../img/srcFileCovDistChart9.png 9% of files have more coverage
389   858   142   9.73
172   791   0.37   20
40     3.55  
2    
 
  DictionaryFormatter       Line # 23 388 0% 141 79 86.8% 0.8681135
  DictionaryFormatter.FieldDefinitionNameComparator       Line # 221 1 0% 1 0 100% 1.0
 
  (14)
 
1    package org.kuali.student.common.dictionary.service.impl;
2   
3    import java.util.ArrayList;
4    import java.util.Collections;
5    import java.util.Comparator;
6    import java.util.HashSet;
7    import java.util.LinkedHashMap;
8    import java.util.List;
9    import java.util.Map;
10    import java.util.Set;
11   
12    import org.kuali.student.common.dictionary.dto.CaseConstraint;
13    import org.kuali.student.common.dictionary.dto.CommonLookupParam;
14    import org.kuali.student.common.dictionary.dto.Constraint;
15    import org.kuali.student.common.dictionary.dto.DataType;
16    import org.kuali.student.common.dictionary.dto.FieldDefinition;
17    import org.kuali.student.common.dictionary.dto.LookupConstraint;
18    import org.kuali.student.common.dictionary.dto.ObjectStructureDefinition;
19    import org.kuali.student.common.dictionary.dto.RequiredConstraint;
20    import org.kuali.student.common.dictionary.dto.ValidCharsConstraint;
21    import org.kuali.student.common.dictionary.dto.WhenConstraint;
22   
 
23    public class DictionaryFormatter
24    {
25   
26    private StringBuilder builder = new StringBuilder (5000);
27    private ObjectStructureDefinition os;
28    private String rowSeperator = "\n";
29    private String colSeperator = "|";
30    private String name;
31    private String className;
32    private boolean processSubstructures = false;
33    private int level;
34    private Map<String, ObjectStructureDefinition> subStructuresToProcess =
35    new LinkedHashMap ();
36    private Set<ObjectStructureDefinition> subStructuresAlreadyProcessed;
37   
 
38  145 toggle public DictionaryFormatter (String name,
39    String className,
40    ObjectStructureDefinition os,
41    Set<ObjectStructureDefinition> subStructuresAlreadyProcessed,
42    int level,
43    boolean processSubstructures)
44    {
45  145 this.name = name;
46  145 this.className = className;
47  145 this.os = os;
48  145 this.subStructuresAlreadyProcessed = subStructuresAlreadyProcessed;
49  145 this.level = level;
50  145 this.processSubstructures = processSubstructures;
51    }
52    public static final String UNBOUNDED = "unbounded";
53   
 
54  0 toggle public String getRowSeperator ()
55    {
56  0 return rowSeperator;
57    }
58   
 
59  0 toggle public void setRowSeperator (String rowSeperator)
60    {
61  0 this.rowSeperator = rowSeperator;
62    }
63   
 
64  0 toggle public String getColSeparator ()
65    {
66  0 return colSeperator;
67    }
68   
 
69  0 toggle public void setColSeparator (String separator)
70    {
71  0 this.colSeperator = separator;
72    }
73   
 
74  5640 toggle private String pad (String str, int size)
75    {
76  5640 StringBuilder padStr = new StringBuilder (size);
77  5640 padStr.append (str);
78  73195 while (padStr.length () < size)
79    {
80  67555 padStr.append (' ');
81    }
82  5640 return padStr.toString ();
83    }
84   
 
85  145 toggle public String formatForWiki ()
86    {
87  145 builder.append (rowSeperator);
88    // builder.append ("======= start dump of object structure definition ========");
89  145 builder.append (rowSeperator);
90  145 builder.append ("h" + level + ". " + calcNotSoSimpleName (name));
91  145 builder.append ("{anchor:" + name + "}");
92  145 builder.append (rowSeperator);
93  145 if (className != null)
94    {
95  145 builder.append ("The corresponding java class for this dictionary object is "
96    + os.getName ());
97    }
98  145 if (os.isHasMetaData ())
99    {
100  72 builder.append (rowSeperator);
101  72 builder.append ("The dictionary says this object holds metadata");
102    }
103  145 builder.append (rowSeperator);
104  145 builder.append (colSeperator);
105  145 builder.append (colSeperator);
106  145 builder.append ("Field");
107  145 builder.append (colSeperator);
108  145 builder.append (colSeperator);
109  145 builder.append ("Required?");
110  145 builder.append (colSeperator);
111  145 builder.append (colSeperator);
112  145 builder.append ("DataType");
113  145 builder.append (colSeperator);
114  145 builder.append (colSeperator);
115  145 builder.append ("Length");
116  145 builder.append (colSeperator);
117  145 builder.append (colSeperator);
118  145 builder.append ("Dynamic or Hidden");
119  145 builder.append (colSeperator);
120  145 builder.append (colSeperator);
121  145 builder.append ("Default");
122  145 builder.append (colSeperator);
123  145 builder.append (colSeperator);
124  145 builder.append ("Repeats?");
125  145 builder.append (colSeperator);
126  145 builder.append (colSeperator);
127  145 builder.append ("Valid Characters");
128  145 builder.append (colSeperator);
129  145 builder.append (colSeperator);
130  145 builder.append ("Lookup");
131  145 builder.append (colSeperator);
132  145 builder.append (colSeperator);
133  145 builder.append ("Cross Field");
134  145 builder.append (colSeperator);
135  145 builder.append (colSeperator);
136  145 builder.append (rowSeperator);
137  145 for (FieldDefinition fd : getSortedFields ())
138    {
139  940 builder.append (colSeperator);
140  940 builder.append (pad (fd.getName (), 30));
141  940 builder.append (colSeperator);
142  940 builder.append (pad (calcRequired (fd), 10));
143  940 builder.append (colSeperator);
144  940 builder.append (pad (calcDataType (fd), 25));
145  940 builder.append (colSeperator);
146  940 builder.append (pad (calcLength (fd), 15));
147  940 builder.append (colSeperator);
148  940 builder.append (pad (calcDynamicOrHidden (fd), 7));
149  940 builder.append (colSeperator);
150  940 builder.append (pad (calcDefaultValue (fd), 15));
151  940 builder.append (colSeperator);
152  940 builder.append (calcRepeating (fd));
153  940 builder.append (colSeperator);
154  940 builder.append (calcValidCharsMinMax (fd));
155  940 builder.append (colSeperator);
156  940 builder.append (calcLookup (fd));
157  940 builder.append (colSeperator);
158  940 builder.append (calcCrossField (fd));
159  940 builder.append (colSeperator);
160  940 builder.append (rowSeperator);
161    }
162  145 List<String> discrepancies = null;
163  145 if (className == null)
164    {
165  0 discrepancies = new ArrayList (1);
166  0 discrepancies.add (
167    "There is no corresponding java class for this dictionary object structure");
168    }
169    else
170    {
171  145 discrepancies = new Dictionary2BeanComparer (className, os).compare ();
172    }
173  145 if (discrepancies.size () > 0)
174    {
175  40 builder.append ("h" + (level + 1) + ". " + discrepancies.size ()
176    + " discrepancie(s) found in "
177    + calcSimpleName (name));
178  40 builder.append (rowSeperator);
179  40 builder.append (formatAsString (discrepancies));
180  40 builder.append (rowSeperator);
181    }
182   
183    // builder.append ("======= end dump of object structure definition ========");
184  145 builder.append (rowSeperator);
185  145 Set<ObjectStructureDefinition> subStructuresAlreadyProcessedBeforeProcessingSubStructures =
186    new HashSet ();
187  145 subStructuresAlreadyProcessedBeforeProcessingSubStructures.addAll (
188    subStructuresAlreadyProcessed);
189  145 for (String subName : this.subStructuresToProcess.keySet ())
190    {
191  86 ObjectStructureDefinition subOs = this.subStructuresToProcess.get (subName);
192  86 if ( ! subStructuresAlreadyProcessedBeforeProcessingSubStructures.contains (
193    subOs))
194    {
195  86 this.subStructuresAlreadyProcessed.add (subOs);
196    // System.out.println ("formatting substructure " + subName);
197  86 Class<?> subClazz = getClass (subOs.getName ());
198  86 DictionaryFormatter formatter =
199    new DictionaryFormatter (subName, subOs.getName (),
200    subOs,
201    subStructuresAlreadyProcessed,
202    level + 1,
203    this.processSubstructures);
204  86 builder.append (formatter.formatForWiki ());
205  86 builder.append (rowSeperator);
206    }
207    }
208   
209  145 return builder.toString ();
210    }
211   
212   
213   
 
214  145 toggle private List<FieldDefinition> getSortedFields ()
215    {
216  145 List<FieldDefinition> fields = os.getAttributes ();
217  145 Collections.sort (fields, new FieldDefinitionNameComparator ());
218  145 return fields;
219    }
220   
 
221    private static class FieldDefinitionNameComparator implements Comparator <FieldDefinition>
222    {
 
223  1457 toggle @Override
224    public int compare (FieldDefinition o1, FieldDefinition o2)
225    {
226  1457 return o1.getName ().toLowerCase ().compareTo (o2.getName ().toLowerCase ());
227    }
228   
229    }
230   
 
231  230 toggle private Class getClass (String className)
232    {
233  230 try
234    {
235  230 return Class.forName (className);
236    }
237    catch (ClassNotFoundException ex)
238    {
239  53 return null;
240    // throw new IllegalArgumentException ("Could not find class for " + className);
241    }
242    }
243   
 
244  40 toggle private String formatAsString (List<String> discrepancies)
245    {
246  40 int i = 0;
247  40 StringBuilder builder = new StringBuilder ();
248  40 for (String discrep : discrepancies)
249    {
250  64 i ++;
251  64 builder.append (i + ". " + discrep + "\n");
252    }
253  40 return builder.toString ();
254    }
255   
 
256  940 toggle private String calcDataType (FieldDefinition fd)
257    {
258  940 if (fd.getDataType ().equals (DataType.COMPLEX))
259    {
260  144 if (fd.getDataObjectStructure () == null)
261    {
262  0 throw new IllegalArgumentException (
263    fd.getName () + " is complex but does not have a sub-structure defined");
264    }
265  144 Class subClazz = this.getClass (fd.getDataObjectStructure ().getName ());
266  144 String subStrucName = calcComplexSubStructureName (fd);
267    // process if explicity asking for substructures OR the field is a freestanding field
268    // so it won't be processed by just processing all of the DTO's and their sub-objects
269  144 if (this.processSubstructures || subClazz == null)
270    {
271  102 if ( ! this.subStructuresAlreadyProcessed.contains (
272    fd.getDataObjectStructure ()))
273    {
274    // System.out.println ("Adding " + subStrucName + " to set to be processed");
275  86 this.subStructuresToProcess.put (subStrucName, fd.getDataObjectStructure ());
276    }
277    }
278  144 return "[" + calcNotSoSimpleName (subStrucName) + "|#" + subStrucName + "]";
279    }
280  796 return fd.getDataType ().toString ();
281    }
282   
 
283  940 toggle private String calcDefaultValue (FieldDefinition fd)
284    {
285  940 if (fd.getDefaultValue () != null)
286    {
287  13 return fd.getDefaultValue ().toString ();
288    }
289  927 return " ";
290    }
291   
292   
 
293  940 toggle private String calcDynamicOrHidden (FieldDefinition fd)
294    {
295  940 if (fd.isHide ())
296    {
297  0 if (fd.isDynamic ())
298    {
299  0 return "dynamic and hidden";
300    }
301  0 return "hidden";
302    }
303  940 if (fd.isDynamic ())
304    {
305  30 return "dynamic";
306    }
307  910 return " ";
308    }
309   
 
310  144 toggle private String calcComplexSubStructureName (FieldDefinition fd)
311    {
312  144 if (this.processSubstructures)
313    {
314  99 return name + "." + fd.getName () + "." + calcSimpleName (
315    fd.getDataObjectStructure ().getName ());
316    }
317  45 return calcSimpleName (fd.getDataObjectStructure ().getName ());
318    }
319   
 
320  654 toggle private String calcSimpleName (String name)
321    {
322  654 if (name.lastIndexOf (".") != -1)
323    {
324  626 name = name.substring (name.lastIndexOf (".") + 1);
325    }
326  654 return name;
327    }
328   
 
329  289 toggle private String calcNotSoSimpleName (String name)
330    {
331  289 if (name.lastIndexOf (".") == -1)
332    {
333  54 return name;
334    }
335  235 String simpleName = calcSimpleName (name);
336  235 String fieldName = calcSimpleName (name.substring (0, name.length ()
337    - simpleName.length ()
338    - 1));
339  235 return fieldName + "." + simpleName;
340    }
341   
 
342  940 toggle private String calcRequired (FieldDefinition fd)
343    {
344  940 if (fd.getMaxOccurs () != null)
345    {
346  940 if ( ! fd.getMaxOccurs ().equals (UNBOUNDED))
347    {
348  781 if (Integer.parseInt (fd.getMaxOccurs ()) == 0)
349    {
350  3 return "Not allowed";
351    }
352    }
353    }
354   
355  937 if (fd.getMinOccurs () != null)
356    {
357  179 if (fd.getMinOccurs () >= 1)
358    {
359  121 return "required";
360    }
361    }
362   
363  816 return " ";
364    // return "optional";
365    }
366    private static final String LINK_TO_DEFINITIONS =
367    "KULSTG:Formatted View of Base Dictionary#Valid Character Definitions";
368   
 
369  940 toggle private String calcValidChars (FieldDefinition fd)
370    {
371  940 if (fd.getValidChars () == null)
372    {
373  605 return " ";
374    }
375  335 return calcValidChars (fd.getValidChars ());
376    }
377   
 
378  351 toggle private String calcValidChars (ValidCharsConstraint cons)
379    {
380  351 String labelKey = cons.getLabelKey ();
381  351 if (labelKey == null)
382    {
383  142 labelKey = "validation.validChars";
384    }
385  351 String validChars = escapeWiki (cons.getValue ());
386  351 String descr = "[" + labelKey + "|" + LINK_TO_DEFINITIONS + "]" + "\\\\\n"
387    + validChars;
388  351 return descr;
389    }
390   
 
391  351 toggle private String escapeWiki (String str)
392    {
393  351 StringBuilder bldr = new StringBuilder (str.length ());
394  12974 for (int i = 0; i < str.length (); i ++)
395    {
396  12623 char c = str.charAt (i);
397  12623 switch (c)
398    {
399  65 case '{':
400  65 case '}':
401  602 case '[':
402  602 case ']':
403  54 case '|':
404  1388 bldr.append ('\\');
405    }
406  12623 bldr.append (c);
407    }
408  351 return bldr.toString ();
409    }
410   
 
411  940 toggle private String calcLookup (FieldDefinition fd)
412    {
413  940 if (fd.getLookupDefinition () == null)
414    {
415  867 return " ";
416    }
417  73 return calcLookup (fd.getLookupDefinition ());
418    }
419   
 
420  92 toggle private String calcLookup (LookupConstraint lc)
421    {
422  92 StringBuilder bldr = new StringBuilder ();
423  92 bldr.append (lc.getId ());
424    // this is the search description not the lookup description
425    // builder.append (" - ");
426    // builder.append (lc.getDesc ());
427  92 String and = "";
428  92 bldr.append ("\\\\");
429  92 bldr.append ("\n");
430  92 bldr.append ("Implemented using search: ");
431  92 String searchPage = calcWikiSearchPage (lc.getSearchTypeId ());
432  92 bldr.append ("[" + lc.getSearchTypeId () + "|" + searchPage + "#"
433    + lc.getSearchTypeId () + "]");
434  92 List<CommonLookupParam> configuredParameters = filterConfiguredParams (
435    lc.getParams ());
436  92 if (configuredParameters.size () > 0)
437    {
438  50 bldr.append ("\\\\");
439  50 bldr.append ("\n");
440  50 bldr.append (" where ");
441  50 and = "";
442  50 for (CommonLookupParam param : configuredParameters)
443    {
444  69 bldr.append (and);
445  69 and = " and ";
446  69 bldr.append (param.getName ());
447  69 bldr.append ("=");
448  69 if (param.getDefaultValueString () != null)
449    {
450  29 bldr.append (param.getDefaultValueString ());
451  29 continue;
452    }
453  40 if (param.getDefaultValueList () != null)
454    {
455  40 String comma = "";
456  40 for (String defValue : param.getDefaultValueList ())
457    {
458  41 bldr.append (comma);
459  41 comma = ", ";
460  41 bldr.append (defValue);
461    }
462    }
463    }
464    }
465  92 return bldr.toString ();
466    }
467   
 
468  940 toggle private String calcValidCharsMinMax (FieldDefinition fd)
469    {
470  940 String validChars = calcValidChars (fd);
471  940 String minMax = calcMinMax (fd);
472  940 String and = " and ";
473  940 if (validChars.trim ().equals (""))
474    {
475  605 return minMax;
476    }
477  335 if (minMax.trim ().equals (""))
478    {
479  335 return validChars;
480    }
481  0 return validChars + "\\\\\n" + minMax;
482    }
483   
 
484  940 toggle private String calcMinMax (FieldDefinition fd)
485    {
486  940 if (fd.getExclusiveMin () == null)
487    {
488  939 if (fd.getInclusiveMax () == null)
489    {
490  939 return " ";
491    }
492  0 return "Must be <= " + fd.getInclusiveMax ();
493    }
494  1 if (fd.getInclusiveMax () == null)
495    {
496  0 return "Must be > " + fd.getExclusiveMin ();
497    }
498  1 return "Must be > " + fd.getExclusiveMin () + " and < "
499    + fd.getInclusiveMax ();
500    }
501    private static final String PAGE_PREFIX = "Formatted View of ";
502    private static final String PAGE_SUFFIX = " Searches";
503   
 
504  92 toggle private String calcWikiSearchPage (String searchType)
505    {
506  92 return PAGE_PREFIX + calcWikigPageAbbrev (searchType) + PAGE_SUFFIX;
507    }
508   
 
509  92 toggle private String calcWikigPageAbbrev (String searchType)
510    {
511  92 if (searchType == null)
512    {
513  0 return null;
514    }
515  92 if (searchType.equals ("enumeration.management.search"))
516    {
517  9 return "EM";
518    }
519  83 if (searchType.startsWith ("lu."))
520    {
521  0 return "LU";
522    }
523  83 if (searchType.startsWith ("cluset."))
524    {
525  0 return "LU";
526    }
527  83 if (searchType.startsWith ("lo."))
528    {
529  0 return "LO";
530    }
531  83 if (searchType.startsWith ("lrc."))
532    {
533  2 return "LRC";
534    }
535  81 if (searchType.startsWith ("comment."))
536    {
537  0 return "Comment";
538    }
539  81 if (searchType.startsWith ("org."))
540    {
541  39 return "Organization";
542    }
543  42 if (searchType.startsWith ("atp."))
544    {
545  36 return "ATP";
546    }
547  6 if (searchType.startsWith ("subjectCode."))
548    {
549  6 return "SC";
550    }
551  0 throw new IllegalArgumentException ("Unknown type of search: " + searchType);
552    }
553   
 
554  92 toggle private List<CommonLookupParam> filterConfiguredParams (
555    List<CommonLookupParam> params)
556    {
557  92 List list = new ArrayList ();
558  92 if (params == null)
559    {
560  0 return list;
561    }
562  92 if (params.size () == 0)
563    {
564  5 return list;
565    }
566  87 for (CommonLookupParam param : params)
567    {
568  184 if (param.getDefaultValueString () != null)
569    {
570  29 list.add (param);
571  29 continue;
572    }
573  155 if (param.getDefaultValueList () != null)
574    {
575  40 list.add (param);
576    }
577    }
578  87 return list;
579    }
580   
 
581  940 toggle private String calcRepeating (FieldDefinition fd)
582    {
583  940 if (fd.getMaxOccurs () == null)
584    {
585  0 return "???";
586    }
587  940 if (fd.getMaxOccurs ().equals (UNBOUNDED))
588    {
589  159 if (fd.getMinOccurs () != null && fd.getMinOccurs () > 1)
590    {
591  0 return "repeating: minimum " + fd.getMinOccurs () + " times";
592    }
593  159 return "repeating: unlimited";
594    }
595  781 if (Integer.parseInt (fd.getMaxOccurs ()) == 0)
596    {
597  3 return "NOT USED";
598    }
599  778 if (Integer.parseInt (fd.getMaxOccurs ()) == 1)
600    {
601  778 return " ";
602    // return "single";
603    }
604   
605  0 if (fd.getMinOccurs () != null)
606    {
607  0 if (fd.getMinOccurs () > 1)
608    {
609  0 return "repeating: " + fd.getMinOccurs () + " to " + fd.getMaxOccurs ()
610    + " times";
611    }
612    }
613  0 return "repeating: maximum " + fd.getMaxOccurs () + " times";
614    }
615   
 
616  940 toggle private String calcLength (FieldDefinition fd)
617    {
618  940 if (fd.getMaxLength () != null)
619    {
620  657 if (fd.getMinLength () != null && fd.getMinLength () != 0)
621    {
622  529 if (Integer.parseInt (fd.getMaxLength ()) == fd.getMinLength ())
623    {
624  11 return ("(must be " + fd.getMaxLength () + ")");
625    }
626  518 return "(" + fd.getMinLength () + " to " + fd.getMaxLength () + ")";
627    }
628  128 return "(up to " + fd.getMaxLength () + ")";
629    }
630  283 if (fd.getMinLength () != null)
631    {
632  0 return "(over " + fd.getMinLength () + ")";
633    }
634  283 return " ";
635    }
636   
 
637  940 toggle private String calcCrossField (FieldDefinition fd)
638    {
639  940 StringBuilder b = new StringBuilder ();
640  940 String semicolon = "";
641  940 String cfr = calcCrossFieldRequire (fd);
642  940 if (cfr != null)
643    {
644  10 b.append (semicolon);
645  10 semicolon = "; ";
646  10 b.append (cfr);
647    }
648  940 String cfw = calcCrossFieldWhen (fd);
649  940 if (cfw != null)
650    {
651  106 b.append (semicolon);
652  106 semicolon = "; ";
653  106 b.append (cfw);
654    }
655  940 if (b.length () == 0)
656    {
657  824 return " ";
658    }
659  116 return b.toString ();
660    }
661   
 
662  940 toggle private String calcCrossFieldRequire (FieldDefinition fd)
663    {
664  940 if (fd.getRequireConstraint () == null)
665    {
666  0 return null;
667    }
668  940 if (fd.getRequireConstraint ().size () == 0)
669    {
670  930 return null;
671    }
672  10 StringBuilder b = new StringBuilder ();
673  10 String comma = "";
674  10 b.append ("if not empty then ");
675  10 for (RequiredConstraint rc : fd.getRequireConstraint ())
676    {
677  10 b.append (comma);
678  10 comma = ", ";
679  10 b.append (rc.getFieldPath ());
680    }
681  10 if (fd.getRequireConstraint ().size () == 1)
682    {
683  10 b.append (" is");
684    }
685    else
686    {
687  0 b.append (" are");
688    }
689  10 b.append (" also required");
690  10 return b.toString ();
691    }
692   
 
693  940 toggle private String calcCrossFieldWhen (FieldDefinition fd)
694    {
695  940 if (fd.getCaseConstraint () == null)
696    {
697  834 return null;
698    }
699  106 StringBuilder b = new StringBuilder ();
700  106 CaseConstraint cc = fd.getCaseConstraint ();
701  106 for (WhenConstraint wc : cc.getWhenConstraint ())
702    {
703  151 b.append ("\\\\");
704  151 b.append ("\n");
705  151 b.append ("when ");
706  151 b.append (cc.getFieldPath ());
707  151 b.append (" ");
708  151 if ( ! cc.isCaseSensitive ())
709    {
710  151 b.append ("ignoring case ");
711    }
712  151 b.append (cc.getOperator ());
713  151 b.append (" ");
714   
715  151 b.append ("\\\\");
716  151 b.append ("\n");
717  151 String comma = "";
718  151 for (Object value : wc.getValues ())
719    {
720  372 b.append (comma);
721  372 comma = " or ";
722  372 b.append (asString (value));
723    }
724  151 b.append ("\\\\");
725  151 b.append ("\n");
726  151 b.append ("then override constraint:"
727    + calcOverride (fd, wc.getConstraint ()));
728    }
729  106 return b.toString ();
730    }
731   
 
732  151 toggle private String calcOverride (FieldDefinition fd, Constraint cons)
733    {
734  151 StringBuilder b = new StringBuilder ();
735  151 b.append (calcOverride ("serviceSide", fd.isServerSide (),
736    cons.isServerSide ()));
737  151 b.append (calcOverride ("exclusiveMin", fd.getExclusiveMin (),
738    cons.getExclusiveMin ()));
739  151 b.append (calcOverride ("inclusiveMax", fd.getInclusiveMax (),
740    cons.getInclusiveMax ()));
741  151 String minOccursMessage = calcOverride ("minOccurs", fd.getMinOccurs (),
742    cons.getMinOccurs ());
743  151 if ( ! minOccursMessage.trim ().equals (""))
744    {
745  128 if (cons.getMinOccurs () != null && cons.getMinOccurs () == 1)
746    {
747  121 minOccursMessage = " REQUIRED";
748    }
749    }
750  151 b.append (minOccursMessage);
751  151 b.append (calcOverride ("validchars", fd.getValidChars (),
752    cons.getValidChars ()));
753  151 b.append (calcOverride ("lookup", fd.getLookupDefinition (),
754    cons.getLookupDefinition ()));
755    //TODO: other more complex constraints
756  151 return b.toString ();
757    }
758   
 
759  151 toggle private String calcOverride (String attribute, LookupConstraint val1,
760    LookupConstraint val2)
761    {
762  151 if (val1 == val2)
763    {
764  122 return "";
765    }
766  29 if (val1 == null && val2 != null)
767    {
768  0 return " add lookup " + this.calcLookup (val2);
769    }
770  29 if (val1 != null && val2 == null)
771    {
772  10 return " remove lookup constraint";
773    }
774  19 return " change lookup to " + calcLookup (val2);
775    }
776   
 
777  151 toggle private String calcOverride (String attribute, ValidCharsConstraint val1,
778    ValidCharsConstraint val2)
779    {
780  151 if (val1 == val2)
781    {
782  128 return "";
783    }
784  23 if (val1 == null && val2 != null)
785    {
786  16 return " add validchars " + calcValidChars (val2);
787    }
788  7 if (val1 != null && val2 == null)
789    {
790  7 return " remove validchars constraint";
791    }
792  0 return " change validchars to " + calcValidChars (val2);
793    }
794   
 
795  151 toggle private String calcOverride (String attribute, boolean val1, boolean val2)
796    {
797  151 if (val1 == val2)
798    {
799  151 return "";
800    }
801  0 return " " + attribute + "=" + val2;
802    }
803   
 
804  302 toggle private String calcOverride (String attribute, String val1, String val2)
805    {
806  302 if (val1 == null && val2 == null)
807    {
808  298 return "";
809    }
810  4 if (val1 == val2)
811    {
812  0 return "";
813    }
814  4 if (val1 == null)
815    {
816  4 return " " + attribute + "=" + val2;
817    }
818  0 if (val1.equals (val2))
819    {
820  0 return "";
821    }
822  0 return " " + attribute + "=" + val2;
823    }
824   
 
825  151 toggle private String calcOverride (String attribute, Object val1, Object val2)
826    {
827  151 if (val1 == null && val2 == null)
828    {
829  22 return "";
830    }
831  129 if (val1 == val2)
832    {
833  1 return "";
834    }
835  128 if (val1 == null)
836    {
837  118 return " " + attribute + "=" + val2;
838    }
839  10 if (val1.equals (val2))
840    {
841  0 return "";
842    }
843  10 return " " + attribute + "=" + asString (val2);
844    }
845   
 
846  382 toggle private String asString (Object value)
847    {
848  382 if (value == null)
849    {
850  4 return "null";
851    }
852  378 if (value instanceof String)
853    {
854  372 return (String) value;
855    }
856  6 return value.toString ();
857    }
858    }