1 /*
2 * Copyright 2006-2011 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 org.apache.commons.lang.StringUtils;
20 import org.kuali.rice.core.api.config.property.ConfigurationService;
21 import org.kuali.rice.krad.datadictionary.DataDictionaryDefinitionBase;
22 import org.kuali.rice.krad.datadictionary.HelpDefinition;
23 import org.kuali.rice.krad.datadictionary.SortDefinition;
24 import org.kuali.rice.krad.datadictionary.exception.DuplicateEntryException;
25 import org.kuali.rice.krad.service.KRADServiceLocator;
26 import org.kuali.rice.krad.util.KRADConstants;
27
28 import java.util.ArrayList;
29 import java.util.LinkedHashMap;
30 import java.util.List;
31 import java.util.Map;
32
33 /**
34 * Contains lookup-related information relating to the parent BusinessObject.
35 * <p/>
36 * The lookup element is used to specify the rules for "looking up"
37 * a business object. These specifications define the following:
38 * How to specify the search criteria used to locate a set of business objects
39 * How to display the search results
40 * <p/>
41 * DD: See LookupDefinition.java
42 * <p/>
43 * JSTL: The lookup element is a Map which is accessed using
44 * a key of "lookup". This map contains the following keys:
45 * lookupableID (String, optional)
46 * title (String)
47 * menubar (String, optional)
48 * defaultSort (Map, optional)
49 * lookupFields (Map)
50 * resultFields (Map)
51 * resultSetLimit (String, optional)
52 * <p/>
53 * See LookupMapBuilder.java
54 * <p/>
55 * Note: the setters do copious amounts of validation, to facilitate generating errors during the parsing process.
56 */
57 @Deprecated
58 public class LookupDefinition extends DataDictionaryDefinitionBase {
59 private static final long serialVersionUID = 6733008572890721359L;
60
61 protected String lookupableID;
62 protected String title;
63 protected String menubar;
64 protected SortDefinition defaultSort;
65
66 protected List<FieldDefinition> lookupFields = new ArrayList<FieldDefinition>();
67 protected Map<String, FieldDefinition> lookupFieldMap = new LinkedHashMap<String, FieldDefinition>();
68 protected List<FieldDefinition> resultFields = new ArrayList<FieldDefinition>();
69 protected Map<String, FieldDefinition> resultFieldMap = new LinkedHashMap<String, FieldDefinition>();
70
71 protected Integer resultSetLimit = null;
72
73 protected String extraButtonSource;
74 protected String extraButtonParams;
75
76 protected String searchIconOverride;
77
78 protected int numOfColumns;
79
80 protected HelpDefinition helpDefinition;
81 protected String helpUrl;
82
83 protected boolean translateCodes = false;
84 protected boolean disableSearchButtons = false;
85
86 public LookupDefinition() {
87 }
88
89 /**
90 * The lookupableID element identifies the name of the Spring bean which
91 * will be used to obtain the lookupable helper service for the business object.
92 * For example, the Balance.xml file has a lookupableId = "glBalanceLookupable".
93 * The KualiSpringBeansGL.xml file determines that the helper service will be an
94 * instance of BalanceLookupableHelperServiceImpl.
95 * <p/>
96 * If this field is omitted, the default bean id used will be kualiLookupable which uses
97 * the KualiLookupableHelperServiceImpl helper service.
98 */
99 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.getPropertyString(KRADConstants.EXTERNALIZABLE_IMAGES_URL_KEY)).replace("${externalizable.images.url}",
165 kualiConfigurationservice.getPropertyString(KRADConstants.APPLICATION_EXTERNALIZABLE_IMAGES_URL_KEY));
166 this.menubar = this.menubar.replace("${application.url}", kualiConfigurationservice.getPropertyString(
167 KRADConstants.APPLICATION_URL_KEY));
168 }
169
170
171 /**
172 * @return true if this instance has a default sort defined
173 */
174 public boolean hasDefaultSort() {
175 return (defaultSort != null);
176 }
177
178 /**
179 * @return defaultSort
180 */
181 public SortDefinition getDefaultSort() {
182 return defaultSort;
183 }
184
185 /**
186 * The defaultSort element specifies the sequence in which the
187 * lookup search results should be displayed. It contains an
188 * ascending/descending indicator and a list of attribute names.
189 * <p/>
190 * DD: See SortDefinition.java
191 * <p/>
192 * JSTL: defaultSort is a Map with the following keys:
193 * sortAscending (boolean String)
194 * sortAttributes (Map)
195 * <p/>
196 * By the time JSTL export occurs, the optional attributeName from the defaultSort
197 * tag will have been converted into the first contained sortAttribute
198 * <p/>
199 * See LookupMapBuilder.java
200 *
201 * @throws IllegalArgumentException if the given defaultSort is blank
202 */
203 public void setDefaultSort(SortDefinition defaultSort) {
204 if (defaultSort == null) {
205 throw new IllegalArgumentException("invalid (null) defaultSort");
206 }
207 this.defaultSort = defaultSort;
208 }
209
210 /**
211 * @return List of attributeNames of all lookupField FieldDefinitions associated with this LookupDefinition, in the order in
212 * which they were added
213 */
214 public List getLookupFieldNames() {
215 List fieldNames = new ArrayList();
216 fieldNames.addAll(this.lookupFieldMap.keySet());
217
218 return fieldNames;
219 }
220
221 /**
222 * @return Collection of all lookupField FieldDefinitions associated with this LookupDefinition, in the order in which they were
223 * added
224 */
225 public List<FieldDefinition> getLookupFields() {
226 return lookupFields;
227 }
228
229 /**
230 * @param fieldName
231 * @return FieldDefinition associated with the named lookup field, or null if there is none
232 */
233 public FieldDefinition getLookupField(String attributeName) {
234 return lookupFieldMap.get(attributeName);
235 }
236
237 /**
238 * @return List of attributeNames of all resultField FieldDefinitions associated with this LookupDefinition, in the order in
239 * which they were added
240 */
241 public List<String> getResultFieldNames() {
242 List<String> fieldNames = new ArrayList<String>();
243 fieldNames.addAll(resultFieldMap.keySet());
244
245 return fieldNames;
246 }
247
248 /**
249 * @return Collection of all resultField FieldDefinitions associated with this LookupDefinition, in the order in which they were
250 * added
251 */
252 public List<FieldDefinition> getResultFields() {
253 return resultFields;
254 }
255
256
257 /**
258 * @param fieldName
259 * @return FieldDefinition associated with the named result field, or null if there is none
260 */
261 public FieldDefinition getResultField(String attributeName) {
262 return resultFieldMap.get(attributeName);
263 }
264
265 /**
266 * The resultSetLimit element specifies the maximum number of records that will be listed
267 * as a result of the lookup search.
268 */
269 public void setResultSetLimit(Integer resultSetLimit) {
270 this.resultSetLimit = resultSetLimit;
271 }
272
273 /**
274 * @return true if this instance has a result set limit
275 */
276 public boolean hasResultSetLimit() {
277 return (resultSetLimit != null);
278 }
279
280
281 /**
282 * The resultSetLimit element specifies the maximum number of records that will be listed
283 * as a result of the lookup search.
284 */
285 public Integer getResultSetLimit() {
286 return resultSetLimit;
287 }
288
289 /**
290 * Directly validate simple fields, call completeValidation on Definition fields.
291 *
292 * @see org.kuali.rice.krad.datadictionary.DataDictionaryDefinition#completeValidation(java.lang.Class, java.lang.Object)
293 */
294 public void completeValidation(Class rootBusinessObjectClass, Class otherBusinessObjectClass) {
295 if (hasDefaultSort()) {
296 defaultSort.completeValidation(rootBusinessObjectClass, null);
297 }
298
299 for (FieldDefinition lookupField : lookupFields) {
300 lookupField.completeValidation(rootBusinessObjectClass, null);
301 }
302
303 for (FieldDefinition resultField : resultFields) {
304 resultField.completeValidation(rootBusinessObjectClass, null);
305 }
306 }
307
308 /**
309 * @return true if this instance has extraButtonSource
310 */
311 public boolean hasExtraButtonSource() {
312 return extraButtonSource != null;
313 }
314
315 /**
316 * @return extraButtonSource
317 */
318 public String getExtraButtonSource() {
319 return extraButtonSource;
320 }
321
322 /**
323 * The extraButton element is used to define additional buttons which will
324 * appear on the lookup screen next to the Search and Clear buttons.
325 * You can define the image source and additional html parameters for
326 * each button.
327 * <p/>
328 * The extraButtonSource element defines the location of an image file
329 * to use for the extra button.
330 *
331 * @throws IllegalArgumentException if the given source is blank
332 */
333 public void setExtraButtonSource(String extraButtonSource) {
334 if (StringUtils.isBlank(extraButtonSource)) {
335 throw new IllegalArgumentException("invalid (blank) button source");
336 }
337 this.extraButtonSource = extraButtonSource;
338 }
339
340 /**
341 * @return true if this instance has extraButtonParams
342 */
343 public boolean hasExtraButtonParams() {
344 return extraButtonParams != null;
345 }
346
347 /**
348 * @return extraButtonParams
349 */
350 public String getExtraButtonParams() {
351 return extraButtonParams;
352 }
353
354 /**
355 * The extraButton element is used to define additional buttons which will
356 * appear on the lookup screen next to the Search and Clear buttons.
357 * You can define the image source and additional html parameters for
358 * each button.
359 * <p/>
360 * The extraButtonParams contains extra HTML parameters that be associated
361 * with the button.
362 */
363 public void setExtraButtonParams(String extraButtonParams) {
364 this.extraButtonParams = extraButtonParams;
365 }
366
367
368 /**
369 * @return true if this instance has an alternate icon to use for lookup icon
370 */
371 public boolean hasSearchIconOverride() {
372 return searchIconOverride != null;
373 }
374
375 /**
376 * @return search icon override url
377 */
378 public String getSearchIconOverride() {
379 return searchIconOverride;
380 }
381
382 /**
383 * The searchIconOverride element is used to define alternative icons
384 * appear on the lookup screen next to the Search and Clear buttons.
385 * You can define the image source.
386 *
387 * @throws IllegalArgumentException if the given source is blank
388 */
389 public void setSearchIconOverride(String searchIconOverride) {
390 if (StringUtils.isBlank(searchIconOverride)) {
391 throw new IllegalArgumentException("invalid (blank) search icon override");
392 }
393 this.searchIconOverride = searchIconOverride;
394 }
395
396
397 public String toString() {
398 return "LookupDefinition '" + getTitle() + "'";
399 }
400
401 /**
402 * The lookupFields element defines the set of fields in which the user
403 * can enter values representing search selection criteria. A search result
404 * record will be returned only if the criteria entered in all the
405 * lookup fields are met.
406 * <p/>
407 * DD: See LookupDefinition.java
408 * <p/>
409 * JSTL: lookupFields is a Map which is accessed using a key of "lookupFields".
410 * This map contains the following keys:
411 * attributeName of first lookup field
412 * attributeName of second lookup field
413 * etc.
414 * The corresponding values are lookupField Export Maps.
415 * See LookupMapBuilder.java.
416 * <p/>
417 * The lookupField element defines one lookup search
418 * criterion field.
419 * DD: See LookupDefinition.java.
420 * <p/>
421 * JSTL: lookupField is a Map which is accessed by a key
422 * which is the attributeName of a lookup field. This map contains
423 * entries with the following keys:
424 * "attributeName" (String)
425 * "required" (boolean String)
426 * <p/>
427 * lookupField attribute definitions:
428 * <p/>
429 * required = true means that the user must enter something
430 * into the search criterion lookup field
431 * forceLookup = this attribute is not used
432 * noLookup = true means that field should not include magnifying glass (i.e. quickfinder)
433 */
434 public void setLookupFields(List<FieldDefinition> lookupFields) {
435 lookupFieldMap.clear();
436 for (FieldDefinition lookupField : lookupFields) {
437 if (lookupField == null) {
438 throw new IllegalArgumentException("invalid (null) lookupField");
439 }
440 String keyName = lookupField.getAttributeName();
441 if (lookupFieldMap.containsKey(keyName)) {
442 throw new DuplicateEntryException("duplicate lookupField entry for attribute '" + keyName + "'");
443 }
444
445 lookupFieldMap.put(keyName, lookupField);
446 }
447 this.lookupFields = lookupFields;
448 }
449
450 /**
451 * The resultFields element specifies the list of fields that are shown as a result
452 * of the lookup search.
453 * <p/>
454 * JSTL: resultFields is a Map which is accesseed by a key of "resultFields".
455 * This map contains entries with the following keys:
456 * attributeName of first result field
457 * attributeName of second result field
458 * etc.
459 * The corresponding values are ExportMap's
460 * <p/>
461 * The ExportMaps are accessed using a key of attributeName.
462 * Each ExportMap contains a single entry as follows:
463 * "attributeName"
464 * The corresponding value is the attributeName of the field.
465 * <p/>
466 * See LookupMapBuilder.java.
467 */
468 public void setResultFields(List<FieldDefinition> resultFields) {
469 resultFieldMap.clear();
470 for (FieldDefinition resultField : resultFields) {
471 if (resultField == null) {
472 throw new IllegalArgumentException("invalid (null) resultField");
473 }
474
475 String keyName = resultField.getAttributeName();
476 if (resultFieldMap.containsKey(keyName)) {
477 throw new DuplicateEntryException("duplicate resultField entry for attribute '" + keyName + "'");
478 }
479
480 resultFieldMap.put(keyName, resultField);
481 }
482 this.resultFields = resultFields;
483 }
484
485 /**
486 * @return the numOfColumns
487 */
488 public int getNumOfColumns() {
489 return this.numOfColumns;
490 }
491
492 /**
493 * @param numOfColumns the numOfColumns to set
494 */
495 public void setNumOfColumns(int numOfColumns) {
496 this.numOfColumns = numOfColumns;
497 }
498
499 /**
500 * @return the helpDefinition
501 */
502 public HelpDefinition getHelpDefinition() {
503 return this.helpDefinition;
504 }
505
506 /**
507 * @param helpDefinition the helpDefinition to set
508 */
509 public void setHelpDefinition(HelpDefinition helpDefinition) {
510 this.helpDefinition = helpDefinition;
511 }
512
513 /**
514 * @return the helpUrl
515 */
516 public String getHelpUrl() {
517 return this.helpUrl;
518 }
519
520 /**
521 * @param helpUrl the helpUrl to set
522 */
523 public void setHelpUrl(String helpUrl) {
524 this.helpUrl = helpUrl;
525 }
526
527 public boolean isTranslateCodes() {
528 return this.translateCodes;
529 }
530
531 public void setTranslateCodes(boolean translateCodes) {
532 this.translateCodes = translateCodes;
533 }
534
535 public boolean isDisableSearchButtons() {
536 return this.disableSearchButtons;
537 }
538
539 public void setDisableSearchButtons(boolean disableSearchButtons) {
540 this.disableSearchButtons = disableSearchButtons;
541 }
542
543 }