001 /** 002 * Copyright 2005-2011 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 */ 016 package org.kuali.rice.kns.datadictionary; 017 018 import org.apache.commons.lang.StringUtils; 019 import org.kuali.rice.core.api.config.property.ConfigurationService; 020 import org.kuali.rice.krad.datadictionary.DataDictionaryDefinitionBase; 021 import org.kuali.rice.krad.datadictionary.HelpDefinition; 022 import org.kuali.rice.krad.datadictionary.SortDefinition; 023 import org.kuali.rice.krad.datadictionary.exception.DuplicateEntryException; 024 import org.kuali.rice.krad.service.KRADServiceLocator; 025 import org.kuali.rice.krad.util.KRADConstants; 026 027 import java.util.ArrayList; 028 import java.util.LinkedHashMap; 029 import java.util.List; 030 import java.util.Map; 031 032 /** 033 * Contains lookup-related information relating to the parent BusinessObject. 034 * <p/> 035 * The lookup element is used to specify the rules for "looking up" 036 * a business object. These specifications define the following: 037 * How to specify the search criteria used to locate a set of business objects 038 * How to display the search results 039 * <p/> 040 * DD: See LookupDefinition.java 041 * <p/> 042 * JSTL: The lookup element is a Map which is accessed using 043 * a key of "lookup". This map contains the following keys: 044 * lookupableID (String, optional) 045 * title (String) 046 * menubar (String, optional) 047 * defaultSort (Map, optional) 048 * lookupFields (Map) 049 * resultFields (Map) 050 * resultSetLimit (String, optional) 051 * <p/> 052 * See LookupMapBuilder.java 053 * <p/> 054 * Note: the setters do copious amounts of validation, to facilitate generating errors during the parsing process. 055 */ 056 @Deprecated 057 public class LookupDefinition extends DataDictionaryDefinitionBase { 058 private static final long serialVersionUID = 6733008572890721359L; 059 060 protected String lookupableID; 061 protected String title; 062 protected String menubar; 063 protected SortDefinition defaultSort; 064 065 protected List<FieldDefinition> lookupFields = new ArrayList<FieldDefinition>(); 066 protected Map<String, FieldDefinition> lookupFieldMap = new LinkedHashMap<String, FieldDefinition>(); 067 protected List<FieldDefinition> resultFields = new ArrayList<FieldDefinition>(); 068 protected Map<String, FieldDefinition> resultFieldMap = new LinkedHashMap<String, FieldDefinition>(); 069 070 protected Integer resultSetLimit = null; 071 protected Integer multipleValuesResultSetLimit = null; 072 073 protected String extraButtonSource; 074 protected String extraButtonParams; 075 076 protected String searchIconOverride; 077 078 protected int numOfColumns; 079 080 protected HelpDefinition helpDefinition; 081 protected String helpUrl; 082 083 protected boolean translateCodes = false; 084 protected boolean disableSearchButtons = false; 085 086 public LookupDefinition() { 087 } 088 089 /** 090 * The lookupableID element identifies the name of the Spring bean which 091 * will be used to obtain the lookupable helper service for the business object. 092 * For example, the Balance.xml file has a lookupableId = "glBalanceLookupable". 093 * The KualiSpringBeansGL.xml file determines that the helper service will be an 094 * instance of BalanceLookupableHelperServiceImpl. 095 * <p/> 096 * If this field is omitted, the default bean id used will be kualiLookupable which uses 097 * the KualiLookupableHelperServiceImpl helper service. 098 */ 099 public void setLookupableID(String lookupableID) { 100 if (lookupableID == null) { 101 throw new IllegalArgumentException("invalid (null) lookupableID"); 102 } 103 104 this.lookupableID = lookupableID; 105 } 106 107 /** 108 * @return custom lookupable id 109 */ 110 public String getLookupableID() { 111 return this.lookupableID; 112 } 113 114 /** 115 * @return title 116 */ 117 public String getTitle() { 118 return title; 119 } 120 121 /** 122 * Sets title to the given value. 123 * 124 * @param title 125 * @throws IllegalArgumentException if the given title is blank 126 */ 127 public void setTitle(String title) { 128 if (StringUtils.isBlank(title)) { 129 throw new IllegalArgumentException("invalid (blank) title"); 130 } 131 this.title = title; 132 } 133 134 /** 135 * @return true if this instance has a menubar 136 */ 137 public boolean hasMenubar() { 138 return (menubar != null); 139 } 140 141 /** 142 * @return menubar 143 */ 144 public String getMenubar() { 145 return menubar; 146 } 147 148 /** 149 * The menubar element is used to add additional html code 150 * to the header line on the lookup screen. 151 * <p/> 152 * For example, Account.xml uses this element to 153 * add the "create new global" button to the Account Lookup header. 154 * 155 * @throws IllegalArgumentException if the given menubar is blank 156 */ 157 public void setMenubar(String menubar) { 158 if (StringUtils.isBlank(menubar)) { 159 throw new IllegalArgumentException("invalid (blank) menubar"); 160 } 161 // TODO: catch exception if service locator call fails 162 ConfigurationService kualiConfigurationservice = KRADServiceLocator.getKualiConfigurationService(); 163 this.menubar = menubar.replace("${kr.externalizable.images.url}", 164 kualiConfigurationservice.getPropertyValueAsString(KRADConstants.EXTERNALIZABLE_IMAGES_URL_KEY)).replace("${externalizable.images.url}", 165 kualiConfigurationservice.getPropertyValueAsString( 166 KRADConstants.APPLICATION_EXTERNALIZABLE_IMAGES_URL_KEY)); 167 this.menubar = this.menubar.replace("${application.url}", kualiConfigurationservice.getPropertyValueAsString( 168 KRADConstants.APPLICATION_URL_KEY)); 169 } 170 171 172 /** 173 * @return true if this instance has a default sort defined 174 */ 175 public boolean hasDefaultSort() { 176 return (defaultSort != null); 177 } 178 179 /** 180 * @return defaultSort 181 */ 182 public SortDefinition getDefaultSort() { 183 return defaultSort; 184 } 185 186 /** 187 * The defaultSort element specifies the sequence in which the 188 * lookup search results should be displayed. It contains an 189 * ascending/descending indicator and a list of attribute names. 190 * <p/> 191 * DD: See SortDefinition.java 192 * <p/> 193 * JSTL: defaultSort is a Map with the following keys: 194 * sortAscending (boolean String) 195 * sortAttributes (Map) 196 * <p/> 197 * By the time JSTL export occurs, the optional attributeName from the defaultSort 198 * tag will have been converted into the first contained sortAttribute 199 * <p/> 200 * See LookupMapBuilder.java 201 * 202 * @throws IllegalArgumentException if the given defaultSort is blank 203 */ 204 public void setDefaultSort(SortDefinition defaultSort) { 205 if (defaultSort == null) { 206 throw new IllegalArgumentException("invalid (null) defaultSort"); 207 } 208 this.defaultSort = defaultSort; 209 } 210 211 /** 212 * @return List of attributeNames of all lookupField FieldDefinitions associated with this LookupDefinition, in the order in 213 * which they were added 214 */ 215 public List getLookupFieldNames() { 216 List fieldNames = new ArrayList(); 217 fieldNames.addAll(this.lookupFieldMap.keySet()); 218 219 return fieldNames; 220 } 221 222 /** 223 * @return Collection of all lookupField FieldDefinitions associated with this LookupDefinition, in the order in which they were 224 * added 225 */ 226 public List<FieldDefinition> getLookupFields() { 227 return lookupFields; 228 } 229 230 /** 231 * @param fieldName 232 * @return FieldDefinition associated with the named lookup field, or null if there is none 233 */ 234 public FieldDefinition getLookupField(String attributeName) { 235 return lookupFieldMap.get(attributeName); 236 } 237 238 /** 239 * @return List of attributeNames of all resultField FieldDefinitions associated with this LookupDefinition, in the order in 240 * which they were added 241 */ 242 public List<String> getResultFieldNames() { 243 List<String> fieldNames = new ArrayList<String>(); 244 fieldNames.addAll(resultFieldMap.keySet()); 245 246 return fieldNames; 247 } 248 249 /** 250 * @return Collection of all resultField FieldDefinitions associated with this LookupDefinition, in the order in which they were 251 * added 252 */ 253 public List<FieldDefinition> getResultFields() { 254 return resultFields; 255 } 256 257 258 /** 259 * @param fieldName 260 * @return FieldDefinition associated with the named result field, or null if there is none 261 */ 262 public FieldDefinition getResultField(String attributeName) { 263 return resultFieldMap.get(attributeName); 264 } 265 266 /** 267 * The resultSetLimit element specifies the maximum number of records that will be listed 268 * as a result of the lookup search. 269 */ 270 public void setResultSetLimit(Integer resultSetLimit) { 271 this.resultSetLimit = resultSetLimit; 272 } 273 274 /** 275 * @return true if this instance has a result set limit 276 */ 277 public boolean hasResultSetLimit() { 278 return (resultSetLimit != null); 279 } 280 281 282 /** 283 * The resultSetLimit element specifies the maximum number of records that will be listed 284 * as a result of the lookup search. 285 */ 286 public Integer getResultSetLimit() { 287 return resultSetLimit; 288 } 289 290 /** 291 * The multipleValuesResultSetLimit element specifies the maximum number of records that will be listed 292 * as a result of a multiple values lookup search. 293 */ 294 public void setMultipleValuesResultSetLimit(Integer multipleValuesResultSetLimit) { 295 this.multipleValuesResultSetLimit = multipleValuesResultSetLimit; 296 } 297 298 /** 299 * @return true if this instance has a multiple values result set limit 300 */ 301 public boolean hasMultipleValuesResultSetLimit() { 302 return (multipleValuesResultSetLimit != null); 303 } 304 305 306 /** 307 * The multipleValuesResultSetLimit element specifies the maximum number of records that will be listed 308 * as a result of a multiple values lookup search. 309 */ 310 public Integer getMultipleValuesResultSetLimit() { 311 return multipleValuesResultSetLimit; 312 } 313 314 /** 315 * Directly validate simple fields, call completeValidation on Definition fields. 316 * 317 * @see org.kuali.rice.krad.datadictionary.DataDictionaryDefinition#completeValidation(java.lang.Class, java.lang.Object) 318 */ 319 public void completeValidation(Class rootBusinessObjectClass, Class otherBusinessObjectClass) { 320 if (hasDefaultSort()) { 321 defaultSort.completeValidation(rootBusinessObjectClass, null); 322 } 323 324 for (FieldDefinition lookupField : lookupFields) { 325 lookupField.completeValidation(rootBusinessObjectClass, null); 326 } 327 328 for (FieldDefinition resultField : resultFields) { 329 resultField.completeValidation(rootBusinessObjectClass, null); 330 } 331 } 332 333 /** 334 * @return true if this instance has extraButtonSource 335 */ 336 public boolean hasExtraButtonSource() { 337 return extraButtonSource != null; 338 } 339 340 /** 341 * @return extraButtonSource 342 */ 343 public String getExtraButtonSource() { 344 return extraButtonSource; 345 } 346 347 /** 348 * The extraButton element is used to define additional buttons which will 349 * appear on the lookup screen next to the Search and Clear buttons. 350 * You can define the image source and additional html parameters for 351 * each button. 352 * <p/> 353 * The extraButtonSource element defines the location of an image file 354 * to use for the extra button. 355 * 356 * @throws IllegalArgumentException if the given source is blank 357 */ 358 public void setExtraButtonSource(String extraButtonSource) { 359 if (StringUtils.isBlank(extraButtonSource)) { 360 throw new IllegalArgumentException("invalid (blank) button source"); 361 } 362 this.extraButtonSource = extraButtonSource; 363 } 364 365 /** 366 * @return true if this instance has extraButtonParams 367 */ 368 public boolean hasExtraButtonParams() { 369 return extraButtonParams != null; 370 } 371 372 /** 373 * @return extraButtonParams 374 */ 375 public String getExtraButtonParams() { 376 return extraButtonParams; 377 } 378 379 /** 380 * The extraButton element is used to define additional buttons which will 381 * appear on the lookup screen next to the Search and Clear buttons. 382 * You can define the image source and additional html parameters for 383 * each button. 384 * <p/> 385 * The extraButtonParams contains extra HTML parameters that be associated 386 * with the button. 387 */ 388 public void setExtraButtonParams(String extraButtonParams) { 389 this.extraButtonParams = extraButtonParams; 390 } 391 392 393 /** 394 * @return true if this instance has an alternate icon to use for lookup icon 395 */ 396 public boolean hasSearchIconOverride() { 397 return searchIconOverride != null; 398 } 399 400 /** 401 * @return search icon override url 402 */ 403 public String getSearchIconOverride() { 404 return searchIconOverride; 405 } 406 407 /** 408 * The searchIconOverride element is used to define alternative icons 409 * appear on the lookup screen next to the Search and Clear buttons. 410 * You can define the image source. 411 * 412 * @throws IllegalArgumentException if the given source is blank 413 */ 414 public void setSearchIconOverride(String searchIconOverride) { 415 if (StringUtils.isBlank(searchIconOverride)) { 416 throw new IllegalArgumentException("invalid (blank) search icon override"); 417 } 418 this.searchIconOverride = searchIconOverride; 419 } 420 421 422 public String toString() { 423 return "LookupDefinition '" + getTitle() + "'"; 424 } 425 426 /** 427 * The lookupFields element defines the set of fields in which the user 428 * can enter values representing search selection criteria. A search result 429 * record will be returned only if the criteria entered in all the 430 * lookup fields are met. 431 * <p/> 432 * DD: See LookupDefinition.java 433 * <p/> 434 * JSTL: lookupFields is a Map which is accessed using a key of "lookupFields". 435 * This map contains the following keys: 436 * attributeName of first lookup field 437 * attributeName of second lookup field 438 * etc. 439 * The corresponding values are lookupField Export Maps. 440 * See LookupMapBuilder.java. 441 * <p/> 442 * The lookupField element defines one lookup search 443 * criterion field. 444 * DD: See LookupDefinition.java. 445 * <p/> 446 * JSTL: lookupField is a Map which is accessed by a key 447 * which is the attributeName of a lookup field. This map contains 448 * entries with the following keys: 449 * "attributeName" (String) 450 * "required" (boolean String) 451 * <p/> 452 * lookupField attribute definitions: 453 * <p/> 454 * required = true means that the user must enter something 455 * into the search criterion lookup field 456 * forceLookup = this attribute is not used 457 * noLookup = true means that field should not include magnifying glass (i.e. quickfinder) 458 */ 459 public void setLookupFields(List<FieldDefinition> lookupFields) { 460 lookupFieldMap.clear(); 461 for (FieldDefinition lookupField : lookupFields) { 462 if (lookupField == null) { 463 throw new IllegalArgumentException("invalid (null) lookupField"); 464 } 465 String keyName = lookupField.getAttributeName(); 466 if (lookupFieldMap.containsKey(keyName)) { 467 throw new DuplicateEntryException("duplicate lookupField entry for attribute '" + keyName + "'"); 468 } 469 470 lookupFieldMap.put(keyName, lookupField); 471 } 472 this.lookupFields = lookupFields; 473 } 474 475 /** 476 * The resultFields element specifies the list of fields that are shown as a result 477 * of the lookup search. 478 * <p/> 479 * JSTL: resultFields is a Map which is accesseed by a key of "resultFields". 480 * This map contains entries with the following keys: 481 * attributeName of first result field 482 * attributeName of second result field 483 * etc. 484 * The corresponding values are ExportMap's 485 * <p/> 486 * The ExportMaps are accessed using a key of attributeName. 487 * Each ExportMap contains a single entry as follows: 488 * "attributeName" 489 * The corresponding value is the attributeName of the field. 490 * <p/> 491 * See LookupMapBuilder.java. 492 */ 493 public void setResultFields(List<FieldDefinition> resultFields) { 494 resultFieldMap.clear(); 495 for (FieldDefinition resultField : resultFields) { 496 if (resultField == null) { 497 throw new IllegalArgumentException("invalid (null) resultField"); 498 } 499 500 String keyName = resultField.getAttributeName(); 501 if (resultFieldMap.containsKey(keyName)) { 502 throw new DuplicateEntryException("duplicate resultField entry for attribute '" + keyName + "'"); 503 } 504 505 resultFieldMap.put(keyName, resultField); 506 } 507 this.resultFields = resultFields; 508 } 509 510 /** 511 * @return the numOfColumns 512 */ 513 public int getNumOfColumns() { 514 return this.numOfColumns; 515 } 516 517 /** 518 * @param numOfColumns the numOfColumns to set 519 */ 520 public void setNumOfColumns(int numOfColumns) { 521 this.numOfColumns = numOfColumns; 522 } 523 524 /** 525 * @return the helpDefinition 526 */ 527 public HelpDefinition getHelpDefinition() { 528 return this.helpDefinition; 529 } 530 531 /** 532 * @param helpDefinition the helpDefinition to set 533 */ 534 public void setHelpDefinition(HelpDefinition helpDefinition) { 535 this.helpDefinition = helpDefinition; 536 } 537 538 /** 539 * @return the helpUrl 540 */ 541 public String getHelpUrl() { 542 return this.helpUrl; 543 } 544 545 /** 546 * @param helpUrl the helpUrl to set 547 */ 548 public void setHelpUrl(String helpUrl) { 549 this.helpUrl = helpUrl; 550 } 551 552 public boolean isTranslateCodes() { 553 return this.translateCodes; 554 } 555 556 public void setTranslateCodes(boolean translateCodes) { 557 this.translateCodes = translateCodes; 558 } 559 560 public boolean isDisableSearchButtons() { 561 return this.disableSearchButtons; 562 } 563 564 public void setDisableSearchButtons(boolean disableSearchButtons) { 565 this.disableSearchButtons = disableSearchButtons; 566 } 567 568 }