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 }