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