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