Coverage Report - org.kuali.rice.kns.datadictionary.AttributeDefinition
 
Classes in this File Line Coverage Branch Coverage Complexity
AttributeDefinition
0%
0/105
0%
0/32
1.46
 
 1  
 /*
 2  
  * Copyright 2005-2008 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.opensource.org/licenses/ecl2.php
 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  
 
 17  
 package org.kuali.rice.kns.datadictionary;
 18  
 
 19  
 import java.util.List;
 20  
 
 21  
 import org.apache.commons.lang.ClassUtils;
 22  
 import org.apache.commons.lang.StringUtils;
 23  
 import org.apache.log4j.Logger;
 24  
 import org.kuali.rice.core.util.ClassLoaderUtils;
 25  
 import org.kuali.rice.core.web.format.Formatter;
 26  
 import org.kuali.rice.kns.datadictionary.control.ControlDefinition;
 27  
 import org.kuali.rice.kns.datadictionary.exception.AttributeValidationException;
 28  
 import org.kuali.rice.kns.datadictionary.exception.ClassValidationException;
 29  
 import org.kuali.rice.kns.datadictionary.validation.DataType;
 30  
 import org.kuali.rice.kns.datadictionary.validation.ValidationPattern;
 31  
 import org.kuali.rice.kns.datadictionary.validation.capability.CaseConstrainable;
 32  
 import org.kuali.rice.kns.datadictionary.validation.capability.Formatable;
 33  
 import org.kuali.rice.kns.datadictionary.validation.capability.HierarchicallyConstrainable;
 34  
 import org.kuali.rice.kns.datadictionary.validation.capability.LengthConstrainable;
 35  
 import org.kuali.rice.kns.datadictionary.validation.capability.MustOccurConstrainable;
 36  
 import org.kuali.rice.kns.datadictionary.validation.capability.PrerequisiteConstrainable;
 37  
 import org.kuali.rice.kns.datadictionary.validation.capability.RangeConstrainable;
 38  
 import org.kuali.rice.kns.datadictionary.validation.capability.ValidCharactersConstrainable;
 39  
 import org.kuali.rice.kns.datadictionary.validation.constraint.CaseConstraint;
 40  
 import org.kuali.rice.kns.datadictionary.validation.constraint.LookupConstraint;
 41  
 import org.kuali.rice.kns.datadictionary.validation.constraint.MustOccurConstraint;
 42  
 import org.kuali.rice.kns.datadictionary.validation.constraint.PrerequisiteConstraint;
 43  
 import org.kuali.rice.kns.datadictionary.validation.constraint.ValidCharactersConstraint;
 44  
 import org.kuali.rice.kns.uif.control.Control;
 45  
 
 46  
 /**
 47  
  * A single attribute definition in the DataDictionary, which contains
 48  
  * information relating to the display, validation, and general maintenance of a
 49  
  * specific attribute of an entry.
 50  
  * 
 51  
  * 
 52  
  */
 53  
 public class AttributeDefinition extends AttributeDefinitionBase implements CaseConstrainable, PrerequisiteConstrainable, Formatable, HierarchicallyConstrainable, MustOccurConstrainable, LengthConstrainable, RangeConstrainable, ValidCharactersConstrainable {
 54  
         private static final long serialVersionUID = -2490613377818442742L;
 55  
 
 56  0
         protected Boolean forceUppercase = Boolean.FALSE;
 57  
         
 58  
         protected DataType dataType;
 59  
         
 60  
         protected Integer minLength;
 61  
         protected Integer maxLength;
 62  
         protected Boolean unique;
 63  
 
 64  
         protected String exclusiveMin;
 65  
         protected String inclusiveMax;
 66  
 
 67  
         @Deprecated 
 68  
         protected ValidationPattern validationPattern;
 69  
 
 70  
         protected ControlDefinition control;
 71  
 
 72  
         // TODO: rename to control once ControlDefinition is removed
 73  
         protected Control controlField;
 74  
 
 75  
         protected String formatterClass;
 76  
 
 77  
         protected AttributeSecurity attributeSecurity;
 78  
 //        protected Constraint constraint;
 79  
         
 80  
         protected Boolean dynamic;
 81  
         
 82  
         // KS-style constraints 
 83  
         protected String customValidatorClass;
 84  
         protected ValidCharactersConstraint validCharactersConstraint;        
 85  
     protected CaseConstraint caseConstraint;
 86  
     protected List<PrerequisiteConstraint> dependencyConstraints;
 87  
         protected List<MustOccurConstraint> mustOccurConstraints;
 88  
         protected LookupConstraint lookupDefinition;// If the user wants to match
 89  
                 // against two searches, that search must be defined as  well
 90  
         protected String lookupContextPath;
 91  
         
 92  
         //TODO: This may not be required since we now use ComplexAttributeDefinition
 93  
         protected String childEntryName;
 94  
         
 95  
 
 96  0
         public AttributeDefinition() {
 97  
                 // Empty
 98  0
         }
 99  
 
 100  
         /**
 101  
          * forceUppercase = convert user entry to uppercase and always display
 102  
          * database value as uppercase.
 103  
          */
 104  
         public void setForceUppercase(Boolean forceUppercase) {
 105  0
                 this.forceUppercase = forceUppercase;
 106  0
         }
 107  
 
 108  
         public Boolean getForceUppercase() {
 109  0
                 return this.forceUppercase;
 110  
         }
 111  
 
 112  
         @Override
 113  
         public Integer getMaxLength() {
 114  0
                 return maxLength;
 115  
         }
 116  
 
 117  
         /**
 118  
          * The maxLength element determines the maximum size of the field for data
 119  
          * entry edit purposes and for display purposes.
 120  
          */
 121  
         public void setMaxLength(Integer maxLength) {
 122  0
                 this.maxLength = maxLength;
 123  0
         }
 124  
 
 125  
         @Override
 126  
         public String getExclusiveMin() {
 127  0
                 return exclusiveMin;
 128  
         }
 129  
 
 130  
         /**
 131  
          * The exclusiveMin element determines the minimum allowable value for data
 132  
          * entry editing purposes. Value can be an integer or decimal value such as
 133  
          * -.001 or 99.
 134  
          */
 135  
         public void setExclusiveMin(String exclusiveMin) {
 136  0
                 this.exclusiveMin = exclusiveMin;
 137  0
         }
 138  
 
 139  
         /**
 140  
          * The inclusiveMax element determines the maximum allowable value for data
 141  
          * entry editing purposes. Value can be an integer or decimal value such as
 142  
          * -.001 or 99.
 143  
          * 
 144  
          * JSTL: This field is mapped into the field named "exclusiveMax".
 145  
          */
 146  
         @Override
 147  
         public String getInclusiveMax() {
 148  0
                 return inclusiveMax;
 149  
         }
 150  
 
 151  
         /**
 152  
          * The inclusiveMax element determines the maximum allowable value for data
 153  
          * entry editing purposes. Value can be an integer or decimal value such as
 154  
          * -.001 or 99.
 155  
          * 
 156  
          * JSTL: This field is mapped into the field named "exclusiveMax".
 157  
          */
 158  
         public void setInclusiveMax(String inclusiveMax) {
 159  0
                 this.inclusiveMax = inclusiveMax;
 160  0
         }
 161  
 
 162  
         /**
 163  
          * @return true if a validationPattern has been set
 164  
          */
 165  
         public boolean hasValidationPattern() {
 166  0
                 return (validationPattern != null);
 167  
         }
 168  
 
 169  
         public ValidationPattern getValidationPattern() {
 170  0
                 return this.validationPattern;
 171  
         }
 172  
 
 173  
         /**
 174  
          * The validationPattern element defines the allowable character-level or
 175  
          * field-level values for an attribute.
 176  
          * 
 177  
          * JSTL: validationPattern is a Map which is accessed using a key of
 178  
          * "validationPattern". Each entry may contain some of the keys listed
 179  
          * below. The keys that may be present for a given attribute are dependent
 180  
          * upon the type of validationPattern.
 181  
          * 
 182  
          * maxLength (String) exactLength type allowWhitespace allowUnderscore
 183  
          * allowPeriod validChars precision scale allowNegative
 184  
          * 
 185  
          * The allowable keys (in addition to type) for each type are: Type****
 186  
          * ***Keys*** alphanumeric exactLength maxLength allowWhitespace
 187  
          * allowUnderscore allowPeriod
 188  
          * 
 189  
          * alpha exactLength maxLength allowWhitespace
 190  
          * 
 191  
          * anyCharacter exactLength maxLength allowWhitespace
 192  
          * 
 193  
          * charset validChars
 194  
          * 
 195  
          * numeric exactLength maxLength
 196  
          * 
 197  
          * fixedPoint allowNegative precision scale
 198  
          * 
 199  
          * floatingPoint allowNegative
 200  
          * 
 201  
          * date n/a emailAddress n/a javaClass n/a month n/a phoneNumber n/a
 202  
          * timestamp n/a year n/a zipcode n/a
 203  
          * 
 204  
          * Note: maxLength and exactLength are mutually exclusive. If one is
 205  
          * entered, the other may not be entered.
 206  
          * 
 207  
          * Note: See ApplicationResources.properties for exact regex patterns. e.g.
 208  
          * validationPatternRegex.date for regex used in date validation.
 209  
          */
 210  
         public void setValidationPattern(ValidationPattern validationPattern) {
 211  0
                 this.validationPattern = validationPattern;
 212  
                 
 213  
                 // FIXME: JLR - need to recreate this functionality using the ValidCharsConstraint logic
 214  0
         }
 215  
 
 216  
 
 217  
         /**
 218  
          * @return control
 219  
          */
 220  
         public ControlDefinition getControl() {
 221  0
                 return control;
 222  
         }
 223  
 
 224  
         /**
 225  
          * The control element defines the manner in which an attribute is displayed
 226  
          * and the manner in which the attribute value is entered.
 227  
          * 
 228  
          * JSTL: control is a Map representing an HTML control. It is accessed using
 229  
          * a key of "control". The table below shows the types of entries associated
 230  
          * with each type of control.
 231  
          * 
 232  
          ** Control Type** **Key** **Value** checkbox checkbox boolean String
 233  
          * 
 234  
          * hidden hidden boolean String
 235  
          * 
 236  
          * radio radio boolean String valuesFinder valuesFinder class name
 237  
          * businessObjectClass String keyAttribute String labelAttribute String
 238  
          * includeKeyInLabel boolean String
 239  
          * 
 240  
          * select select boolean String valuesFinder valuesFinder class name
 241  
          * businessObjectClass String keyAttribute String labelAttribute String
 242  
          * includeBlankRow boolean String includeKeyInLabel boolean String
 243  
          * 
 244  
          * apcSelect apcSelect boolean String paramNamespace String
 245  
          * parameterDetailType String parameterName String
 246  
          * 
 247  
          * text text boolean String size String
 248  
          * 
 249  
          * textarea textarea boolean String rows cols
 250  
          * 
 251  
          * currency currency boolean String size String formattedMaxLength String
 252  
          * 
 253  
          * kualiUser kualiUser boolean String universalIdAttributeName String
 254  
          * userIdAttributeName String personNameAttributeName String
 255  
          * 
 256  
          * lookupHidden lookupHidden boolean String
 257  
          * 
 258  
          * lookupReadonly lookupReadonly boolean String
 259  
          * 
 260  
          * @param control
 261  
          * @throws IllegalArgumentException
 262  
          *             if the given control is null
 263  
          */
 264  
         public void setControl(ControlDefinition control) {
 265  0
                 if (control == null) {
 266  0
                         throw new IllegalArgumentException("invalid (null) control");
 267  
                 }
 268  0
                 this.control = control;
 269  0
         }
 270  
 
 271  
         public boolean hasFormatterClass() {
 272  0
                 return (formatterClass != null);
 273  
         }
 274  
 
 275  
         @Override
 276  
         public String getFormatterClass() {
 277  0
                 return formatterClass;
 278  
         }
 279  
 
 280  
         /**
 281  
          * The formatterClass element is used when custom formatting is required for
 282  
          * display of the field value. This field specifies the name of the java
 283  
          * class to be used for the formatting. About 15 different classes are
 284  
          * available including BooleanFormatter, CurrencyFormatter, DateFormatter,
 285  
          * etc.
 286  
          */
 287  
         public void setFormatterClass(String formatterClass) {
 288  0
                 if (formatterClass == null) {
 289  0
                         throw new IllegalArgumentException("invalid (null) formatterClass");
 290  
                 }
 291  0
                 this.formatterClass = formatterClass;
 292  0
         }
 293  
 
 294  
         /**
 295  
          * Directly validate simple fields, call completeValidation on Definition
 296  
          * fields.
 297  
          * 
 298  
          * @see org.kuali.rice.kns.datadictionary.DataDictionaryEntry#completeValidation()
 299  
          */
 300  
         @Override
 301  
         public void completeValidation(Class<?> rootObjectClass, Class<?> otherObjectClass) {
 302  
                 try {
 303  0
                         if (!DataDictionary.isPropertyOf(rootObjectClass, getName())) {
 304  0
                                 throw new AttributeValidationException("property '" + getName() + "' is not a property of class '"
 305  
                                                 + rootObjectClass.getName() + "' (" + "" + ")");
 306  
                         }
 307  
 
 308  
                         //TODO currently requiring a control or controlField, but this should not be case (AttrField should probably do the check)
 309  0
                         if (getControl() == null && getControlField() == null) {
 310  0
                                 throw new AttributeValidationException("property '" + getName() + "' in class '"
 311  
                                                 + rootObjectClass.getName() + " does not have a control defined");
 312  
                         }
 313  
                         
 314  0
                         if(getControl() != null) {
 315  0
                             getControl().completeValidation(rootObjectClass, otherObjectClass);
 316  
                         }
 317  
 
 318  0
                         if (attributeSecurity != null) {
 319  0
                                 attributeSecurity.completeValidation(rootObjectClass, otherObjectClass);
 320  
                         }
 321  
 
 322  0
                         if (validationPattern != null) {
 323  0
                                 validationPattern.completeValidation();
 324  
                         }
 325  
 
 326  0
                         if (formatterClass != null) {
 327  
                                 try {
 328  0
                                         Class formatterClassObject = ClassUtils.getClass(ClassLoaderUtils.getDefaultClassLoader(),
 329  
                                                         getFormatterClass());
 330  0
                                         if (!Formatter.class.isAssignableFrom(formatterClassObject)) {
 331  0
                                                 throw new ClassValidationException("formatterClass is not a valid instance of "
 332  
                                                                 + Formatter.class.getName() + " instead was: " + formatterClassObject.getName());
 333  
                                         }
 334  
                                 }
 335  0
                                 catch (ClassNotFoundException e) {
 336  0
                                         throw new ClassValidationException("formatterClass could not be found: " + getFormatterClass(), e);
 337  0
                                 }
 338  
                         }
 339  
                 }
 340  0
                 catch (RuntimeException ex) {
 341  0
                         Logger.getLogger(getClass()).error(
 342  
                                         "Unable to validate attribute " + rootObjectClass + "." + getName() + ": " + ex.getMessage(), ex);
 343  0
                         throw ex;
 344  0
                 }
 345  0
         }
 346  
 
 347  
         /**
 348  
          * @see java.lang.Object#toString()
 349  
          */
 350  
         @Override
 351  
         public String toString() {
 352  0
                 return "AttributeDefinition for attribute " + getName();
 353  
         }
 354  
 
 355  
         /**
 356  
          * @return the attributeSecurity
 357  
          */
 358  
         public AttributeSecurity getAttributeSecurity() {
 359  0
                 return this.attributeSecurity;
 360  
         }
 361  
 
 362  
         /**
 363  
          * @param attributeSecurity
 364  
          *            the attributeSecurity to set
 365  
          */
 366  
         public void setAttributeSecurity(AttributeSecurity attributeSecurity) {
 367  0
                 this.attributeSecurity = attributeSecurity;
 368  0
         }
 369  
 
 370  
         public boolean hasAttributeSecurity() {
 371  0
                 return (attributeSecurity != null);
 372  
         }
 373  
 
 374  
         /**
 375  
          * This overridden method ...
 376  
          * 
 377  
          * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
 378  
          */
 379  
         @Override
 380  
         public void afterPropertiesSet() throws Exception {
 381  0
                 if (StringUtils.isEmpty(name)) {
 382  0
                         throw new RuntimeException("blank name for bean: " + id);
 383  
                 }
 384  
 
 385  0
                 if (validationPattern != null) {
 386  0
                         if (validCharactersConstraint == null) {
 387  0
                                 validCharactersConstraint = new ValidCharactersConstraint();
 388  
                         }
 389  
                         
 390  0
                         validCharactersConstraint.setValue(new StringBuilder().append("regex:").append(validationPattern.getRegexPattern()).toString());
 391  
                 }
 392  0
         }
 393  
 
 394  
         /**
 395  
          * @return the unique
 396  
          */
 397  
         public Boolean getUnique() {
 398  0
                 return this.unique;
 399  
         }
 400  
 
 401  
         /**
 402  
          * @param unique
 403  
          *            the unique to set
 404  
          */
 405  
         public void setUnique(Boolean unique) {
 406  0
                 this.unique = unique;
 407  0
         }
 408  
 
 409  
         /**
 410  
          * Default <code>Control</code> to use when the attribute is to be rendered
 411  
          * for the UI. Used by the UIF when a control is not defined for an
 412  
          * <code>AttributeField</code>
 413  
          * 
 414  
          * @return Control instance
 415  
          */
 416  
         public Control getControlField() {
 417  0
                 return this.controlField;
 418  
         }
 419  
 
 420  
         /**
 421  
          * Setter for the default control
 422  
          * 
 423  
          * @param controlField
 424  
          */
 425  
         public void setControlField(Control controlField) {
 426  0
                 this.controlField = controlField;
 427  0
         }
 428  
 
 429  
         /**
 430  
          * @return the minLength
 431  
          */
 432  
         public Integer getMinLength() {
 433  0
                 return this.minLength;
 434  
         }
 435  
 
 436  
         /**
 437  
          * @param minLength the minLength to set
 438  
          */
 439  
         public void setMinLength(Integer minLength) {
 440  0
                 this.minLength = minLength;
 441  0
         }
 442  
 
 443  
         /**
 444  
          * @return the dataType
 445  
          */
 446  
         @Override
 447  
         public DataType getDataType() {
 448  0
                 return this.dataType;
 449  
         }
 450  
 
 451  
         /**
 452  
          * @param dataType the dataType to set
 453  
          */
 454  
         public void setDataType(DataType dataType) {
 455  0
                 this.dataType = dataType;
 456  0
         }
 457  
         
 458  
         public void setDataType(String dataType) {
 459  0
                 this.dataType = DataType.valueOf(dataType);
 460  0
         }
 461  
 
 462  
         /**
 463  
          * @return the customValidatorClass
 464  
          */
 465  
         public String getCustomValidatorClass() {
 466  0
                 return this.customValidatorClass;
 467  
         }
 468  
 
 469  
         /**
 470  
          * @param customValidatorClass the customValidatorClass to set
 471  
          */
 472  
         public void setCustomValidatorClass(String customValidatorClass) {
 473  0
                 this.customValidatorClass = customValidatorClass;
 474  0
         }
 475  
 
 476  
         /**
 477  
          * @return the validChars
 478  
          */
 479  
         @Override
 480  
         public ValidCharactersConstraint getValidCharactersConstraint() {
 481  0
                 return this.validCharactersConstraint;
 482  
         }
 483  
 
 484  
         /**
 485  
          * @param validCharactersConstraint the validChars to set
 486  
          */
 487  
         public void setValidCharactersConstraint(ValidCharactersConstraint validCharactersConstraint) {
 488  0
                 this.validCharactersConstraint = validCharactersConstraint;
 489  0
         }
 490  
 
 491  
         /**
 492  
          * @return the caseConstraint
 493  
          */
 494  
         @Override
 495  
         public CaseConstraint getCaseConstraint() {
 496  0
                 return this.caseConstraint;
 497  
         }
 498  
 
 499  
         /**
 500  
          * @param caseConstraint the caseConstraint to set
 501  
          */
 502  
         public void setCaseConstraint(CaseConstraint caseConstraint) {
 503  0
                 this.caseConstraint = caseConstraint;
 504  0
         }
 505  
 
 506  
         /**
 507  
          * @return the requireConstraint
 508  
          */
 509  
         @Override
 510  
         public List<PrerequisiteConstraint> getPrerequisiteConstraints() {
 511  0
                 return this.dependencyConstraints;
 512  
         }
 513  
 
 514  
         /**
 515  
          * @param dependencyConstraints the requireConstraint to set
 516  
          */
 517  
         public void setPrerequisiteConstraints(List<PrerequisiteConstraint> dependencyConstraints) {
 518  0
                 this.dependencyConstraints = dependencyConstraints;
 519  0
         }
 520  
 
 521  
         /**
 522  
          * @return the occursConstraint
 523  
          */
 524  
         @Override
 525  
         public List<MustOccurConstraint> getMustOccurConstraints() {
 526  0
                 return this.mustOccurConstraints;
 527  
         }
 528  
 
 529  
         /**
 530  
          * @param mustOccurConstraints the occursConstraint to set
 531  
          */
 532  
         public void setMustOccurConstraints(List<MustOccurConstraint> mustOccurConstraints) {
 533  0
                 this.mustOccurConstraints = mustOccurConstraints;
 534  0
         }
 535  
 
 536  
         /**
 537  
          * @return the lookupDefinition
 538  
          */
 539  
         public LookupConstraint getLookupDefinition() {
 540  0
                 return this.lookupDefinition;
 541  
         }
 542  
 
 543  
         /**
 544  
          * @param lookupDefinition the lookupDefinition to set
 545  
          */
 546  
         public void setLookupDefinition(LookupConstraint lookupDefinition) {
 547  0
                 this.lookupDefinition = lookupDefinition;
 548  0
         }
 549  
 
 550  
         /**
 551  
          * @return the lookupContextPath
 552  
          */
 553  
         public String getLookupContextPath() {
 554  0
                 return this.lookupContextPath;
 555  
         }
 556  
 
 557  
         /**
 558  
          * @param lookupContextPath the lookupContextPath to set
 559  
          */
 560  
         public void setLookupContextPath(String lookupContextPath) {
 561  0
                 this.lookupContextPath = lookupContextPath;
 562  0
         }
 563  
 
 564  
         /**
 565  
          * @return the childEntryName
 566  
          */
 567  
         public String getChildEntryName() {
 568  0
                 return this.childEntryName;
 569  
         }
 570  
 
 571  
         /**
 572  
          * @param childEntryName the childEntryName to set
 573  
          */
 574  
         public void setChildEntryName(String childEntryName) {
 575  0
                 this.childEntryName = childEntryName;
 576  0
         }
 577  
 
 578  
         /**
 579  
          * @return the constraintMessage
 580  
          */
 581  
         public String getConstraint() {
 582  0
                 return this.constraint;
 583  
         }
 584  
 
 585  
         /**
 586  
          * @param constraintMessage the constraintMessage to set
 587  
          */
 588  
         public void setConstraint(String constraint) {
 589  0
                 this.constraint = constraint;
 590  0
         }
 591  
         
 592  
 //        /**
 593  
 //         * @return the constraint
 594  
 //         */
 595  
 //        public Constraint getConstraint() {
 596  
 //                return this.constraint;
 597  
 //        }
 598  
 //
 599  
 //        /**
 600  
 //         * @param constraint the constraint to set
 601  
 //         */
 602  
 //        public void setConstraint(Constraint constraint) {
 603  
 //                this.constraint = constraint;
 604  
 //        }
 605  
         
 606  
 }