001/** 002 * Copyright 2005-2015 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.rice.kns.datadictionary; 017 018import org.apache.commons.lang.StringUtils; 019import org.kuali.rice.kns.service.BusinessObjectMetaDataService; 020import org.kuali.rice.kns.service.KNSServiceLocator; 021import org.kuali.rice.krad.datadictionary.DataDictionary; 022import org.kuali.rice.krad.datadictionary.DataDictionaryDefinitionBase; 023import org.kuali.rice.krad.datadictionary.RelationshipDefinition; 024import org.kuali.rice.krad.datadictionary.exception.AttributeValidationException; 025import org.kuali.rice.krad.datadictionary.exception.ClassValidationException; 026import org.kuali.rice.krad.datadictionary.mask.Mask; 027import org.kuali.rice.krad.valuefinder.ValueFinder; 028 029/** 030 * Contains field-related information for DataDictionary entries. Used by lookups and inquiries. 031 * 032 * Note: the setters do copious amounts of validation, to facilitate generating errors during the parsing process. 033 * 034 * @deprecated Use {@link org.kuali.rice.krad.uif.field.Field} subclasses. 035 */ 036@Deprecated 037public class FieldDefinition extends DataDictionaryDefinitionBase implements FieldDefinitionI { 038 private static final long serialVersionUID = -3426603523049661524L; 039 040 protected String attributeName; 041 protected boolean required = false; 042 protected boolean forceInquiry = false; 043 protected boolean noInquiry = false; 044 protected boolean noDirectInquiry = false; 045 protected boolean forceLookup = false; 046 protected boolean noLookup = false; 047 protected boolean useShortLabel = false; 048 protected String defaultValue; 049 protected Class<? extends ValueFinder> defaultValueFinderClass; 050 protected String quickfinderParameterString; 051 protected Class<? extends ValueFinder> quickfinderParameterStringBuilderClass; 052 053 protected Integer maxLength = null; 054 055 protected String displayEditMode; 056 protected Mask displayMask; 057 058 protected boolean hidden = false; 059 protected boolean readOnly = false; 060 061 protected boolean treatWildcardsAndOperatorsAsLiteral = false; 062 063 protected String alternateDisplayAttributeName; 064 protected String additionalDisplayAttributeName; 065 066 protected boolean triggerOnChange; 067 protected boolean total = false; 068 069 public FieldDefinition() { 070 } 071 072 073 /** 074 * @return attributeName 075 */ 076 public String getAttributeName() { 077 return attributeName; 078 } 079 080 /** 081 * Sets attributeName to the given value. 082 * 083 * @param attributeName 084 * @throws IllegalArgumentException if the given attributeName is blank 085 */ 086 public void setAttributeName(String attributeName) { 087 if (StringUtils.isBlank(attributeName)) { 088 throw new IllegalArgumentException("invalid (blank) attributeName"); 089 } 090 this.attributeName = attributeName; 091 } 092 093 094 /** 095 * @return true if this attribute is required 096 */ 097 public boolean isRequired() { 098 return required; 099 } 100 101 102 /** 103 required = true means that the user must enter something 104 into the search criterion lookup field 105 */ 106 public void setRequired(boolean required) { 107 this.required = required; 108 } 109 110 111 /** 112 * @return Returns the forceInquiry. 113 */ 114 public boolean isForceInquiry() { 115 return forceInquiry; 116 } 117 118 119 /** 120 * forceInquiry = true means that the displayed field value will 121 always be made inquirable (this attribute is not used within the code). 122 */ 123 public void setForceInquiry(boolean forceInquiry) { 124 this.forceInquiry = forceInquiry; 125 } 126 127 /** 128 * @return Returns the forceLookup. 129 */ 130 public boolean isForceLookup() { 131 return forceLookup; 132 } 133 134 /** 135 * forceLookup = this attribute is not used 136 */ 137 public void setForceLookup(boolean forceLookup) { 138 this.forceLookup = forceLookup; 139 } 140 141 /** 142 * @return Returns the noInquiry. 143 */ 144 public boolean isNoInquiry() { 145 return noInquiry; 146 } 147 148 /** 149 * @return Returns a boolean value indicating whether or not to provide 150 * a direct inquiry for the lookup field 151 */ 152 public boolean isNoDirectInquiry() 153 { 154 return noDirectInquiry; 155 } 156 157 /** 158 * noInquiry = true means that the displayed field will never be made inquirable. 159 */ 160 public void setNoInquiry(boolean noInquiry) { 161 this.noInquiry = noInquiry; 162 } 163 164 /** 165 * @param noInquiry If true, the displayed field will not have a direct 166 * inquiry facility 167 */ 168 public void setNoDirectInquiry(boolean noDirectInquiry) { 169 this.noDirectInquiry = noDirectInquiry; 170 } 171 172 /** 173 * @return Returns the noLookup. 174 */ 175 public boolean isNoLookup() { 176 return noLookup; 177 } 178 179 /** 180 * noLookup = true means that field should not include magnifying glass (i.e. quickfinder) 181 */ 182 public void setNoLookup(boolean noLookup) { 183 this.noLookup = noLookup; 184 } 185 186 187 /** 188 * @return the useShortLabel 189 */ 190 public boolean isUseShortLabel() { 191 return this.useShortLabel; 192 } 193 194 195 /** 196 * @param useShortLabel the useShortLabel to set 197 */ 198 public void setUseShortLabel(boolean useShortLabel) { 199 this.useShortLabel = useShortLabel; 200 } 201 202 203 /** 204 * @return Returns the defaultValue. 205 */ 206 public String getDefaultValue() { 207 return defaultValue; 208 } 209 210 211 /** 212 The defaultValue element will pre-load the specified value 213 into the field. 214 */ 215 public void setDefaultValue(String defaultValue) { 216 this.defaultValue = defaultValue; 217 } 218 219 /** 220 * the quickfinderParameterString is a comma separated list of parameter/value pairs, of the format 221 * "param1=value1,param2=value2", where the parameters correspond to attributes of the target class 222 * for the quickfinder, and the values to literals that those attributes will default to when the 223 * quickfinder is used. 224 * @return the quickfinderParameterString 225 */ 226 public String getQuickfinderParameterString() { 227 return this.quickfinderParameterString; 228 } 229 230 /** 231 * @param quickfinderParameterString the quickfinderParameterString to set. See {@link #getQuickfinderParameterString()} 232 */ 233 public void setQuickfinderParameterString(String quickfinderParameterString) { 234 this.quickfinderParameterString = quickfinderParameterString; 235 } 236 237 238 /** 239 * the quickfinderParameterStringBuilderClass specifies the java class that will be used 240 * to determine the default value(s) for field(s) on the target lookup when the quickfinder 241 * is used. The classname specified in this field must implement 242 * {@link org.kuali.rice.krad.valuefinder.ValueFinder}. See {@link #getQuickfinderParameterString()} 243 * for the result string format. 244 * @return the quickfinderParameterStringBuilderClass 245 */ 246 public Class<? extends ValueFinder> getQuickfinderParameterStringBuilderClass() { 247 return this.quickfinderParameterStringBuilderClass; 248 } 249 250 /** 251 * See {@link #getQuickfinderParameterStringBuilderClass()} 252 * @param quickfinderParameterStringBuilderClass the quickfinderParameterStringBuilderClass to set 253 */ 254 public void setQuickfinderParameterStringBuilderClass( 255 Class<? extends ValueFinder> quickfinderParameterStringBuilderClass) { 256 if (quickfinderParameterStringBuilderClass == null) { 257 throw new IllegalArgumentException("invalid (null) quickfinderParameterStringBuilderClass"); 258 } 259 this.quickfinderParameterStringBuilderClass = quickfinderParameterStringBuilderClass; 260 } 261 262 /** 263 * Directly validate simple fields. 264 * 265 * @see org.kuali.rice.krad.datadictionary.DataDictionaryDefinition#completeValidation(java.lang.Class, java.lang.Object) 266 */ 267 public void completeValidation(Class rootBusinessObjectClass, Class otherBusinessObjectClass) { 268 BusinessObjectMetaDataService boMetadataService = KNSServiceLocator.getBusinessObjectMetaDataService(); 269 270 if (!DataDictionary.isPropertyOf(rootBusinessObjectClass, getAttributeName())) { 271 throw new AttributeValidationException("unable to find attribute '" + attributeName + "' in rootBusinessObjectClass '" + rootBusinessObjectClass.getName() + "' (" + "" + ")"); 272 } 273 274 if (StringUtils.isNotBlank(getAlternateDisplayAttributeName())) { 275 if (!DataDictionary.isPropertyOf(rootBusinessObjectClass, getAlternateDisplayAttributeName())) { 276 throw new AttributeValidationException("unable to find attribute named '" + getName() + "' in rootBusinessObjectClass '" + rootBusinessObjectClass.getName() + "' (" + "" + ")"); 277 } 278 } 279 280 if (StringUtils.isNotBlank(getAdditionalDisplayAttributeName())) { 281 if (!DataDictionary.isPropertyOf(rootBusinessObjectClass, getAdditionalDisplayAttributeName())) { 282 throw new AttributeValidationException("unable to find attribute named '" + getName() + "' in rootBusinessObjectClass '" + rootBusinessObjectClass.getName() + "' (" + "" + ")"); 283 } 284 } 285 286 if (defaultValueFinderClass != null && defaultValue != null) { 287 throw new AttributeValidationException("Both defaultValue and defaultValueFinderClass can not be specified on attribute " + getAttributeName() + " in rootBusinessObjectClass " + rootBusinessObjectClass.getName()); 288 } 289 290 validateQuickfinderParameters(rootBusinessObjectClass, boMetadataService); 291 292 if (forceInquiry == true && noInquiry == true) { 293 throw new AttributeValidationException("Both forceInquiry and noInquiry can not be set to true on attribute " + getAttributeName() + " in rootBusinessObjectClass " + rootBusinessObjectClass.getName()); 294 } 295 if (forceLookup == true && noLookup == true) { 296 throw new AttributeValidationException("Both forceLookup and noLookup can not be set to true on attribute " + getAttributeName() + " in rootBusinessObjectClass " + rootBusinessObjectClass.getName()); 297 } 298 } 299 300 301 /** 302 * This method does validation on the quickfinderParameterString and quickfinderParameterStringBuilderClass members 303 * 304 * @param rootBusinessObjectClass 305 * @param boMetadataService 306 */ 307 private void validateQuickfinderParameters(Class rootBusinessObjectClass, 308 BusinessObjectMetaDataService boMetadataService) { 309 if (quickfinderParameterStringBuilderClass != null && quickfinderParameterString != null) { 310 throw new AttributeValidationException("Both quickfinderParameterString and quickfinderParameterStringBuilderClass can not be specified on attribute " + getAttributeName() + " in rootBusinessObjectClass " + rootBusinessObjectClass.getName()); 311 } 312 313 // String used for building exception messages 314 String quickfinderParameterStringSource = "quickfinderParameterString"; 315 316 if (quickfinderParameterStringBuilderClass != null) { 317 try { 318 quickfinderParameterStringSource = "quickfinderParameterStringBuilderClass " + quickfinderParameterStringBuilderClass.getCanonicalName(); 319 quickfinderParameterString = quickfinderParameterStringBuilderClass.newInstance().getValue(); 320 } catch (InstantiationException e) { 321 throw new ClassValidationException("unable to create new instance of "+ quickfinderParameterStringSource +" while validating rootBusinessObjectClass '"+ rootBusinessObjectClass.getName() +"'", e); 322 } catch (IllegalAccessException e) { 323 throw new ClassValidationException("unable to create new instance of "+ quickfinderParameterStringSource +" while validating rootBusinessObjectClass '"+ rootBusinessObjectClass.getName() +"'", e); 324 } 325 } 326 327 if (!StringUtils.isEmpty(quickfinderParameterString)) { 328 // quickfinderParameterString will look something like "campusTypeCode=P,active=Y" 329 for (String quickfinderParam : quickfinderParameterString.split(",")) { // this is guaranteed to return at least one 330 if (quickfinderParam.contains("=")) { 331 String propertyName = quickfinderParam.split("=")[0]; 332 RelationshipDefinition relationship = boMetadataService.getBusinessObjectRelationshipDefinition(rootBusinessObjectClass, attributeName); 333 Class targetClass = relationship.getTargetClass(); 334 335 // This is insufficient to ensure the property is valid for a lookup default, but it's better than nothing. 336 if (!DataDictionary.isPropertyOf(targetClass, propertyName)) { 337 throw new ClassValidationException("malformed parameter string '"+ quickfinderParameterString +"' from "+ quickfinderParameterStringSource + 338 ", '"+ propertyName +"' is not a property of "+ targetClass +"' for rootBusinessObjectClass '"+ rootBusinessObjectClass.getName() +"'"); 339 } 340 341 } else { 342 throw new ClassValidationException("malformed parameter string '"+ quickfinderParameterString +"' from "+ quickfinderParameterStringSource + 343 " for rootBusinessObjectClass '"+ rootBusinessObjectClass.getName() +"'"); 344 } 345 } 346 } 347 } 348 349 350 /** 351 * @see java.lang.Object#toString() 352 */ 353 public String toString() { 354 return "FieldDefinition for attribute " + getAttributeName(); 355 } 356 357 358 public String getName() { 359 return attributeName; 360 } 361 362 363 public String getDisplayEditMode() { 364 return displayEditMode; 365 } 366 367 368 /* 369 The document authorizer classes have a method getEditMode, which is a map of edit mode to 370 value mappings. Depending on the context, the value of the mapping may be relevant, and the logic determining 371 whether the value is relevant is often implemented in the JSP/tag layer. 372 373 Fields on a document (particularily maintenance documents) may be associated with 374 an edit mode. If the edit mode is mapped to a relevant value, then the all fields associated with the edit mode 375 will be rendered unhidden. 376 377 The displayEditMode element is used to specify the edit mode that will be associated with the field. 378 If the document authorizer returns a map with this edit mode mapped to a proper value, then the field will be unhidden to the user. 379 */ 380 public void setDisplayEditMode(String displayEditMode) { 381 this.displayEditMode = displayEditMode; 382 } 383 384 385 public Mask getDisplayMask() { 386 return displayMask; 387 } 388 389 /** 390 * The displayMask element specifies the type of masking to 391 be used to hide the value from un-authorized users. 392 There are three types of masking. 393 */ 394 public void setDisplayMask(Mask displayMask) { 395 this.displayMask = displayMask; 396 } 397 398 399 400 public boolean isReadOnlyAfterAdd() { 401 return false; 402 } 403 404 405 /** 406 * Gets the maxLength attribute. 407 * @return Returns the maxLength. 408 */ 409 public Integer getMaxLength() { 410 return maxLength; 411 } 412 413 414 /** 415 * maxLength = the maximum allowable length of the field in the lookup result fields. In other contexts, 416 like inquiries, this field has no effect. 417 */ 418 public void setMaxLength(Integer maxLength) { 419 this.maxLength = maxLength; 420 } 421 422 /** 423 * @return custom defaultValue class 424 */ 425 public Class<? extends ValueFinder> getDefaultValueFinderClass() { 426 return this.defaultValueFinderClass; 427 } 428 429 /** 430 The defaultValueFinderClass specifies the java class that will be 431 used to determine the default value of a field. The classname 432 specified in this field must implement ValueFinder 433 */ 434 public void setDefaultValueFinderClass(Class<? extends ValueFinder> defaultValueFinderClass) { 435 if (defaultValueFinderClass == null) { 436 throw new IllegalArgumentException("invalid (null) defaultValueFinderClass"); 437 } 438 this.defaultValueFinderClass = defaultValueFinderClass; 439 } 440 441 /** 442 * @return the hidden 443 */ 444 public boolean isHidden() { 445 return this.hidden; 446 } 447 448 /** 449 * @param hidden 450 * If the ControlDefinition.isHidden == true then a corresponding LookupDefinition would 451 * automatically be removed from the search criteria. In some cases you might want the 452 * hidden field to be used as a search criteria. For example, in PersonImpl.xml a client 453 * might want to have the campus code hidden and preset to Bloomington. So when the search 454 * is run, only people from the bloomington campus are returned. 455 * 456 * So, if you want to have a hidden search criteria, set this variable to true. Defaults to 457 * false. 458 */ 459 public void setHidden(boolean hidden) { 460 this.hidden = hidden; 461 } 462 463 /** 464 * @return the readOnly 465 */ 466 public boolean isReadOnly() { 467 return this.readOnly; 468 } 469 470 /** 471 * @param readOnly the readOnly to set 472 */ 473 public void setReadOnly(boolean readOnly) { 474 this.readOnly = readOnly; 475 } 476 477 public boolean isTriggerOnChange() { 478 return this.triggerOnChange; 479 } 480 481 public void setTriggerOnChange(boolean triggerOnChange) { 482 this.triggerOnChange = triggerOnChange; 483 } 484 485 /** 486 * @return the treatWildcardsAndOperatorsAsLiteralOnLookups 487 */ 488 public boolean isTreatWildcardsAndOperatorsAsLiteral() { 489 return this.treatWildcardsAndOperatorsAsLiteral; 490 } 491 492 493 /** 494 * @param treatWildcardsAndOperatorsAsLiteralOnLookups the treatWildcardsAndOperatorsAsLiteralOnLookups to set 495 */ 496 public void setTreatWildcardsAndOperatorsAsLiteral( 497 boolean treatWildcardsAndOperatorsAsLiteralOnLookups) { 498 this.treatWildcardsAndOperatorsAsLiteral = treatWildcardsAndOperatorsAsLiteralOnLookups; 499 } 500 501 502 public String getAlternateDisplayAttributeName() { 503 return this.alternateDisplayAttributeName; 504 } 505 506 507 public void setAlternateDisplayAttributeName(String alternateDisplayAttributeName) { 508 this.alternateDisplayAttributeName = alternateDisplayAttributeName; 509 } 510 511 512 public String getAdditionalDisplayAttributeName() { 513 return this.additionalDisplayAttributeName; 514 } 515 516 517 public void setAdditionalDisplayAttributeName(String additionalDisplayAttributeName) { 518 this.additionalDisplayAttributeName = additionalDisplayAttributeName; 519 } 520 521 522 public boolean isTotal() { 523 return this.total; 524 } 525 526 527 public void setTotal(boolean total) { 528 this.total = total; 529 } 530 531}