001/** 002 * Copyright 2005-2018 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.krad.uif.widget; 017 018import org.apache.commons.lang.StringUtils; 019import org.kuali.rice.krad.bo.DataObjectRelationship; 020import org.kuali.rice.krad.bo.ExternalizableBusinessObject; 021import org.kuali.rice.krad.datadictionary.parse.BeanTag; 022import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute; 023import org.kuali.rice.krad.datadictionary.parse.BeanTags; 024import org.kuali.rice.krad.service.KRADServiceLocatorWeb; 025import org.kuali.rice.krad.service.ModuleService; 026import org.kuali.rice.krad.uif.UifConstants; 027import org.kuali.rice.krad.uif.UifParameters; 028import org.kuali.rice.krad.uif.component.BindingInfo; 029import org.kuali.rice.krad.uif.component.Component; 030import org.kuali.rice.krad.uif.component.MethodInvokerConfig; 031import org.kuali.rice.krad.uif.container.CollectionGroup; 032import org.kuali.rice.krad.uif.container.DialogGroup; 033import org.kuali.rice.krad.uif.element.Action; 034import org.kuali.rice.krad.uif.field.FieldGroup; 035import org.kuali.rice.krad.uif.field.InputField; 036import org.kuali.rice.krad.uif.lifecycle.LifecycleEventListener; 037import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle; 038import org.kuali.rice.krad.uif.lifecycle.ViewLifecycleRestriction; 039import org.kuali.rice.krad.uif.util.LifecycleElement; 040import org.kuali.rice.krad.uif.util.ViewModelUtils; 041import org.kuali.rice.krad.uif.view.View; 042import org.kuali.rice.krad.util.KRADConstants; 043import org.kuali.rice.krad.util.KRADUtils; 044import org.kuali.rice.krad.web.form.UifFormBase; 045 046import java.util.ArrayList; 047import java.util.HashMap; 048import java.util.List; 049import java.util.Map; 050 051/** 052 * Widget for navigating to a lookup from a field (called a quickfinder). 053 * 054 * @author Kuali Rice Team (rice.collab@kuali.org) 055 */ 056@BeanTags({@BeanTag(name = "quickFinder", parent = "Uif-QuickFinder"), 057 @BeanTag(name = "quickFinderByScript", parent = "Uif-QuickFinderByScript"), 058 @BeanTag(name = "collectionQuickFinder", parent = "Uif-CollectionQuickFinder")}) 059 060public class QuickFinder extends WidgetBase implements LifecycleEventListener { 061 062 private static final long serialVersionUID = 3302390972815386785L; 063 064 // lookup configuration 065 private String baseLookupUrl; 066 private String dataObjectClassName; 067 private String viewName; 068 069 private boolean returnByScript; 070 private String readOnlyLookupFields; 071 private String referencesToRefresh; 072 private String lookupCollectionName; 073 private String lookupCollectionId; 074 075 private Map<String, String> fieldConversions; 076 private Map<String, String> lookupParameters; 077 private Map<String, String> additionalLookupParameters; 078 079 private Action quickfinderAction; 080 081 private String lookupDialogId; 082 private boolean openInDialog; 083 084 // lookup view options 085 private Boolean renderReturnLink; 086 private Boolean renderResultActions; 087 private Boolean autoSearch; 088 private Boolean renderLookupCriteria; 089 private Boolean renderCriteriaActions; 090 private Boolean hideCriteriaOnSearch; 091 private Boolean renderMaintenanceLinks; 092 private Boolean multipleValuesSelect; 093 094 private String callbackMethodToCall; 095 private MethodInvokerConfig callbackMethod; 096 private Map<String, String> callbackContext; 097 098 public QuickFinder() { 099 super(); 100 101 fieldConversions = new HashMap<String, String>(); 102 lookupParameters = new HashMap<String, String>(); 103 lookupDialogId = ""; 104 } 105 106 /** 107 * The following initialization is performed: 108 * 109 * <ul> 110 * <li>Registers an event on the quickfinder action</li> 111 * </ul> 112 * 113 * {@inheritDoc} 114 */ 115 @Override 116 public void performInitialization(Object model) { 117 super.performInitialization(model); 118 119 ViewLifecycle viewLifecycle = ViewLifecycle.getActiveLifecycle(); 120 viewLifecycle.registerLifecycleCompleteListener(quickfinderAction, this); 121 } 122 123 /** 124 * Inherits readOnly from parent if not explicitly populated. 125 * 126 * {@inheritDoc} 127 */ 128 @Override 129 public void afterEvaluateExpression() { 130 super.afterEvaluateExpression(); 131 132 if (getReadOnly() == null) { 133 Component parent = ViewLifecycle.getPhase().getParent(); 134 setReadOnly(parent == null ? null : parent.getReadOnly()); 135 } 136 } 137 138 /** 139 * The following finalization is performed: 140 * 141 * <ul> 142 * <li>Sets up the quickfinder based on whether the parent is an input field or collection group</li> 143 * <li>Adds action parameters to the quickfinder action based on the quickfinder configuration</li> 144 * <li>Adds callback parameters to post data if present</li> 145 * </ul> 146 * 147 * {@inheritDoc} 148 */ 149 @Override 150 public void performFinalize(Object model, LifecycleElement parent) { 151 super.performFinalize(model, parent); 152 153 if (parent instanceof Component && Boolean.TRUE.equals(((Component) parent).getReadOnly())) { 154 setRender(false); 155 } 156 157 if (!isRender()) { 158 return; 159 } 160 161 View view = ViewLifecycle.getActiveLifecycle().getView(); 162 163 if (parent instanceof InputField) { 164 setupForInputField(view, model, (InputField) parent); 165 166 // add field conversions as accessible binding paths 167 if (isRender()) { 168 for (String toField : fieldConversions.values()) { 169 ViewLifecycle.getViewPostMetadata().addAccessibleBindingPath(toField); 170 } 171 } 172 } else if (parent instanceof CollectionGroup) { 173 setupForCollectionGroup(view, model, (CollectionGroup) parent); 174 } 175 176 setupQuickfinderAction(view, model, parent); 177 178 addCallbackParametersIfPresent(); 179 } 180 181 /** 182 * If quickfinder not manually configured attempts to find a relationship to build the quickfinder on, then also 183 * adjusts the path for any configured field conversions, lookup parameters, and refresh refreshes. 184 * 185 * @param view view instance the quickfinder is associated with 186 * @param model object containing the view data 187 * @param inputField input field instance the quickfinder should apply to 188 */ 189 protected void setupForInputField(View view, Object model, InputField inputField) { 190 // if quickfinder class name not specified, attempt to find a relationship to build the quickfinder from 191 if (StringUtils.isBlank(dataObjectClassName)) { 192 DataObjectRelationship relationship = getRelationshipForField(view, model, inputField); 193 194 // if no relationship found cannot have a quickfinder 195 if (relationship == null) { 196 setRender(false); 197 198 return; 199 } 200 201 dataObjectClassName = relationship.getRelatedClass().getName(); 202 203 if ((fieldConversions == null) || fieldConversions.isEmpty()) { 204 generateFieldConversions(relationship); 205 } 206 207 if ((lookupParameters == null) || lookupParameters.isEmpty()) { 208 generateLookupParameters(relationship); 209 } 210 } 211 212 // adjust paths based on associated attribute field 213 updateFieldConversions(inputField.getBindingInfo()); 214 updateLookupParameters(inputField.getBindingInfo()); 215 updateReferencesToRefresh(inputField.getBindingInfo()); 216 217 // add the quickfinders action as an input field addon 218 inputField.addPostInputAddon(quickfinderAction); 219 } 220 221 /** 222 * Retrieves any {@link org.kuali.rice.krad.bo.DataObjectRelationship} that is associated with the given 223 * field and has a configured lookup view. 224 * 225 * @param view view instance the quickfinder is associated with 226 * @param model object containing the view data 227 * @param field input field instance the quickfinder should apply to 228 * @return data object relationship for the field, or null if one could not be found 229 */ 230 protected DataObjectRelationship getRelationshipForField(View view, Object model, InputField field) { 231 String propertyName = field.getBindingInfo().getBindingName(); 232 233 // get object instance and class for parent 234 Object parentObject = ViewModelUtils.getParentObjectForMetadata(view, model, field); 235 Class<?> parentObjectClass = null; 236 if (parentObject != null) { 237 parentObjectClass = parentObject.getClass(); 238 } 239 240 // get relationship from metadata service 241 if (parentObjectClass != null) { 242 return KRADServiceLocatorWeb.getLegacyDataAdapter().getDataObjectRelationship(parentObject, 243 parentObjectClass, propertyName, "", true, true, false); 244 } 245 246 return null; 247 } 248 249 /** 250 * Generates the lookup field conversions based on the references from the given relationship. 251 * 252 * @param relationship relationship field conversions will be generated from 253 */ 254 protected void generateFieldConversions(DataObjectRelationship relationship) { 255 fieldConversions = new HashMap<String, String>(); 256 257 for (Map.Entry<String, String> entry : relationship.getParentToChildReferences().entrySet()) { 258 String fromField = entry.getValue(); 259 String toField = entry.getKey(); 260 261 fieldConversions.put(fromField, toField); 262 } 263 } 264 265 /** 266 * Generates the lookup parameters based on the references from the given relationship. 267 * 268 * @param relationship relationship lookup parameters will be generated from 269 */ 270 protected void generateLookupParameters(DataObjectRelationship relationship) { 271 lookupParameters = new HashMap<String, String>(); 272 273 for (Map.Entry<String, String> entry : relationship.getParentToChildReferences().entrySet()) { 274 String fromField = entry.getKey(); 275 String toField = entry.getValue(); 276 277 if (relationship.getUserVisibleIdentifierKey() == null || relationship.getUserVisibleIdentifierKey().equals( 278 fromField)) { 279 lookupParameters.put(fromField, toField); 280 } 281 } 282 } 283 284 /** 285 * Adjusts the path on the field conversion to property to match the binding path prefix of the 286 * given {@link org.kuali.rice.krad.uif.component.BindingInfo}. 287 * 288 * @param bindingInfo binding info instance to copy binding path prefix from 289 */ 290 protected void updateFieldConversions(BindingInfo bindingInfo) { 291 Map<String, String> adjustedFieldConversions = new HashMap<String, String>(); 292 for (String fromField : fieldConversions.keySet()) { 293 String toField = fieldConversions.get(fromField); 294 295 if (!StringUtils.startsWith(toField, bindingInfo.getBindingPathPrefix())) { 296 String adjustedToFieldPath = bindingInfo.getPropertyAdjustedBindingPath(toField); 297 adjustedFieldConversions.put(fromField, adjustedToFieldPath); 298 } else { 299 adjustedFieldConversions.put(fromField, toField); 300 } 301 } 302 303 this.fieldConversions = adjustedFieldConversions; 304 } 305 306 /** 307 * Adjusts the path on the lookup parameter from property to match the binding path prefix of the 308 * given {@link org.kuali.rice.krad.uif.component.BindingInfo}. 309 * 310 * @param bindingInfo binding info instance to copy binding path prefix from 311 */ 312 protected void updateLookupParameters(BindingInfo bindingInfo) { 313 Map<String, String> adjustedLookupParameters = new HashMap<String, String>(); 314 for (String fromField : lookupParameters.keySet()) { 315 String toField = lookupParameters.get(fromField); 316 String adjustedFromFieldPath = bindingInfo.getPropertyAdjustedBindingPath(fromField); 317 318 adjustedLookupParameters.put(adjustedFromFieldPath, toField); 319 } 320 321 this.lookupParameters = adjustedLookupParameters; 322 } 323 324 /** 325 * Adjust the path on the referencesToRefresh parameter to match the binding path prefix of the 326 * given {@link org.kuali.rice.krad.uif.component.BindingInfo}. 327 * 328 * @param bindingInfo binding info instance to copy binding path prefix from 329 */ 330 protected void updateReferencesToRefresh(BindingInfo bindingInfo) { 331 List<String> adjustedReferencesToRefresh = new ArrayList<String>(); 332 333 if (referencesToRefresh == null) { 334 referencesToRefresh = new String(); 335 } 336 337 for (String reference : StringUtils.split(referencesToRefresh, KRADConstants.REFERENCES_TO_REFRESH_SEPARATOR)) { 338 adjustedReferencesToRefresh.add(bindingInfo.getPropertyAdjustedBindingPath(reference)); 339 } 340 341 this.referencesToRefresh = StringUtils.join(adjustedReferencesToRefresh, 342 KRADConstants.REFERENCES_TO_REFRESH_SEPARATOR); 343 } 344 345 /** 346 * Configures the quickfinder for the given collection group instance by setting the data object class, 347 * field conversions, and lookup collection name (if necessary). 348 * 349 * @param view view instance the quickfinder is associated with 350 * @param model object containing the view data 351 * @param collectionGroup collection group instance to build quickfinder for 352 */ 353 protected void setupForCollectionGroup(View view, Object model, CollectionGroup collectionGroup) { 354 // check to see if data object class is configured for lookup, if so we will assume it should be enabled 355 // if not and the class configured for the collection group is lookupable, use that 356 if (StringUtils.isBlank(getDataObjectClassName())) { 357 Class<?> collectionObjectClass = collectionGroup.getCollectionObjectClass(); 358 359 boolean isCollectionClassLookupable = KRADServiceLocatorWeb.getViewDictionaryService().isLookupable( 360 collectionObjectClass); 361 if (isCollectionClassLookupable) { 362 setDataObjectClassName(collectionObjectClass.getName()); 363 364 // use PK fields for collection class as default field conversions 365 if ((fieldConversions == null) || fieldConversions.isEmpty()) { 366 List<String> collectionObjectPKFields = 367 KRADServiceLocatorWeb.getLegacyDataAdapter().listPrimaryKeyFieldNames( 368 collectionObjectClass); 369 370 fieldConversions = new HashMap<String, String>(); 371 for (String pkField : collectionObjectPKFields) { 372 fieldConversions.put(pkField, pkField); 373 } 374 } 375 } else { 376 // no available data object class to lookup so disable quickfinder 377 setRender(false); 378 } 379 } 380 381 // set the lookup return collection name to this collection path 382 if (isRender() && StringUtils.isBlank(getLookupCollectionName())) { 383 setLookupCollectionName(collectionGroup.getBindingInfo().getBindingPath()); 384 } 385 386 if (isRender() && StringUtils.isBlank(getLookupCollectionId())) { 387 setLookupCollectionId(collectionGroup.getId()); 388 } 389 } 390 391 /** 392 * Adjusts the id for the quickfinder action, and then adds action parameters for passing along the 393 * quickfinder configuration to the lookup view. 394 * 395 * @param view view instance the quickfinder is associated with 396 * @param model object containing the view data 397 * @param parent component instance the quickfinder is associated with 398 */ 399 protected void setupQuickfinderAction(View view, Object model, LifecycleElement parent) { 400 quickfinderAction.setId(getId() + UifConstants.IdSuffixes.ACTION); 401 402 if (openInDialog) { 403 String lightboxScript = null; 404 String actionScript = quickfinderAction.getActionScript(); 405 if (actionScript == null) { 406 actionScript = ""; 407 } 408 String dialogId = quickfinderAction.getActionParameter(UifParameters.DIALOG_ID); 409 410 // if the dialog id is still blank, then look in the initial request parameters in case this was 411 // a request from a nested component (i.e., an action invoked as a result of another action) 412 if (StringUtils.isBlank(dialogId)) { 413 UifFormBase form = (UifFormBase) model; 414 Map<String, String[]> requestParameters = form.getInitialRequestParameters(); 415 if (requestParameters != null) { 416 String[] dialogIds = requestParameters.get(UifParameters.DIALOG_ID); 417 if (dialogIds != null && dialogIds.length > 0) { 418 dialogId = dialogIds[0]; 419 } 420 } 421 } 422 423 // set the quickfinder's dialog id when invoked from within a dialog 424 // this accounts for the quickfinder being on the dialog field in which case the dialog is the parent, and 425 // for the quickfinder being in a nested sub-collection in the dialog in which case the dialog is the 426 // quickfinder's parent's (the nested sub-collection) parent 427 if (StringUtils.isBlank(dialogId)) { 428 Object superParent = parent.getContext().get(UifConstants.ContextVariableNames.PARENT); 429 if (superParent != null) { 430 if (superParent instanceof DialogGroup) { 431 dialogId = ((DialogGroup) superParent).getId(); 432 } else if (superParent instanceof CollectionGroup) { 433 CollectionGroup parentCollection = (CollectionGroup) superParent; 434 superParent = parentCollection.getContext().get(UifConstants.ContextVariableNames.PARENT); 435 if (superParent instanceof FieldGroup) { 436 FieldGroup parentFieldGroup = (FieldGroup) superParent; 437 superParent = parentFieldGroup.getContext().get(UifConstants.ContextVariableNames.PARENT); 438 if (superParent instanceof DialogGroup) { 439 dialogId = ((DialogGroup) superParent).getId(); 440 } 441 } 442 } 443 } 444 } 445 446 // let lookup know that it's been called from a dialog by passing its dialog id if present 447 if (StringUtils.isBlank(dialogId)) { 448 lightboxScript = UifConstants.JsFunctions.SHOW_LOOKUP_DIALOG + "(\"" + quickfinderAction.getId() + "\"," 449 + returnByScript + ",\"" + lookupDialogId + "\");"; 450 } else { 451 lightboxScript = UifConstants.JsFunctions.SHOW_LOOKUP_DIALOG + "(\"" + quickfinderAction.getId() + "\"," 452 + returnByScript + ",\"" + lookupDialogId + "\",\"" + dialogId + "\");"; 453 454 // also add the dialog id to the action parameters so that even other nested components have it 455 // no matter the depth of the nodes 456 quickfinderAction.addActionParameter(UifParameters.DIALOG_ID, dialogId); 457 } 458 459 quickfinderAction.setActionScript(actionScript + lightboxScript); 460 } 461 462 quickfinderAction.addActionParameter(UifParameters.BASE_LOOKUP_URL, baseLookupUrl); 463 464 Class dataObjectClass = getDataObjectClass(dataObjectClassName); 465 ModuleService responsibleModuleService = 466 KRADServiceLocatorWeb.getKualiModuleService().getResponsibleModuleService(dataObjectClass); 467 if (responsibleModuleService != null && responsibleModuleService.isExternalizable(dataObjectClass)) { 468 if (ExternalizableBusinessObject.class.isAssignableFrom(dataObjectClass)) { 469 Class implementationClass = responsibleModuleService.getExternalizableBusinessObjectImplementation( 470 dataObjectClass.asSubclass(ExternalizableBusinessObject.class)); 471 if (implementationClass != null) { 472 dataObjectClassName = implementationClass.getName(); 473 } 474 } 475 } 476 477 quickfinderAction.addActionParameter(UifParameters.DATA_OBJECT_CLASS_NAME, dataObjectClassName); 478 479 if (!fieldConversions.isEmpty()) { 480 quickfinderAction.addActionParameter(UifParameters.CONVERSION_FIELDS, KRADUtils.buildMapParameterString( 481 fieldConversions)); 482 } 483 484 if (!lookupParameters.isEmpty()) { 485 quickfinderAction.addActionParameter(UifParameters.LOOKUP_PARAMETERS, KRADUtils.buildMapParameterString( 486 lookupParameters)); 487 } 488 489 addActionParameterIfNotNull(UifParameters.VIEW_NAME, viewName); 490 addActionParameterIfNotNull(UifParameters.READ_ONLY_FIELDS, readOnlyLookupFields); 491 addActionParameterIfNotNull(UifParameters.RENDER_RETURN_LINK, renderReturnLink); 492 addActionParameterIfNotNull(UifParameters.RENDER_RESULT_ACTIONS, renderResultActions); 493 addActionParameterIfNotNull(UifParameters.REFERENCES_TO_REFRESH, referencesToRefresh); 494 addActionParameterIfNotNull(UifParameters.AUTO_SEARCH, autoSearch); 495 addActionParameterIfNotNull(UifParameters.RENDER_LOOKUP_CRITERIA, renderLookupCriteria); 496 addActionParameterIfNotNull(UifParameters.RENDER_CRITERIA_ACTIONS, renderCriteriaActions); 497 addActionParameterIfNotNull(UifParameters.HIDE_CRITERIA_ON_SEARCH, hideCriteriaOnSearch); 498 addActionParameterIfNotNull(UifParameters.RENDER_MAINTENANCE_LINKS, renderMaintenanceLinks); 499 addActionParameterIfNotNull(UifParameters.MULTIPLE_VALUES_SELECT, multipleValuesSelect); 500 addActionParameterIfNotNull(UifParameters.LOOKUP_COLLECTION_NAME, lookupCollectionName); 501 addActionParameterIfNotNull(UifParameters.LOOKUP_COLLECTION_ID, lookupCollectionId); 502 addActionParameterIfNotNull(UifParameters.QUICKFINDER_ID, getId()); 503 504 //insert additional lookup parameters. 505 if (additionalLookupParameters != null) { 506 //copy additional parameters to actionParameters 507 Map<String, String> actionParameters = quickfinderAction.getActionParameters(); 508 actionParameters.putAll(additionalLookupParameters); 509 quickfinderAction.setActionParameters(actionParameters); 510 } 511 512 quickfinderAction.performFinalize(model, parent); 513 } 514 515 private Class<?> getDataObjectClass(String className) { 516 Class<?> dataObjectClass; 517 518 try { 519 dataObjectClass = Class.forName(className); 520 } catch (ClassNotFoundException e) { 521 throw new RuntimeException("Unable to get class for name: " + className, e); 522 } 523 524 return dataObjectClass; 525 } 526 527 /** 528 * Utility method to add an action parameter to the quickfinder action if the given parameter value 529 * is non blank. 530 * 531 * @param parameterName name of the parameter to add 532 * @param parameterValue value for the parameter to add 533 */ 534 protected void addActionParameterIfNotNull(String parameterName, Object parameterValue) { 535 if ((parameterValue != null) && StringUtils.isNotBlank(parameterValue.toString())) { 536 quickfinderAction.addActionParameter(parameterName, parameterValue.toString()); 537 } 538 } 539 540 /** 541 * Adds post context data for the quickfinder so when the lookup return occurs the focus and jump point 542 * of the quickfinder action can be retrieved. 543 * 544 * {@inheritDoc} 545 */ 546 @Override 547 public void processEvent(ViewLifecycle.LifecycleEvent lifecycleEvent, View view, Object model, 548 LifecycleElement eventComponent) { 549 Action finalQuickfinderAction = (Action) eventComponent; 550 551 // add post metadata for focus point when the associated lookup returns 552 ViewLifecycle.getViewPostMetadata().addComponentPostData(this, UifConstants.PostMetadata.QUICKFINDER_FOCUS_ID, 553 finalQuickfinderAction.getFocusOnIdAfterSubmit()); 554 ViewLifecycle.getViewPostMetadata().addComponentPostData(this, UifConstants.PostMetadata.QUICKFINDER_JUMP_TO_ID, 555 finalQuickfinderAction.getJumpToIdAfterSubmit()); 556 } 557 558 /** 559 * Adds callback method and its parameters to post data so that when a refresh occurs it knows 560 * which view is returned from and possibly which collection line the quickfinder was on. 561 */ 562 protected void addCallbackParametersIfPresent() { 563 if (StringUtils.isNotBlank(callbackMethodToCall)) { 564 ViewLifecycle.getViewPostMetadata().addComponentPostData(this, 565 UifConstants.PostMetadata.QUICKFINDER_CALLBACK_METHOD_TO_CALL, callbackMethodToCall); 566 } 567 568 if (callbackMethod != null) { 569 ViewLifecycle.getViewPostMetadata().addComponentPostData(this, 570 UifConstants.PostMetadata.QUICKFINDER_CALLBACK_METHOD, callbackMethod); 571 } 572 573 if (callbackContext != null && !callbackContext.isEmpty()) { 574 ViewLifecycle.getViewPostMetadata().addComponentPostData(this, 575 UifConstants.PostMetadata.QUICKFINDER_CALLBACK_CONTEXT, callbackContext); 576 } 577 } 578 579 /** 580 * Returns the URL for the lookup for which parameters will be added. 581 * 582 * <p>The base URL includes the domain, context, and controller mapping for the lookup invocation. Parameters are 583 * then added based on configuration to complete the URL. This is generally defaulted to the application URL and 584 * internal KRAD servlet mapping, but can be changed to invoke another application such as the Rice standalone 585 * server</p> 586 * 587 * @return lookup base URL 588 */ 589 @BeanTagAttribute 590 public String getBaseLookupUrl() { 591 return this.baseLookupUrl; 592 } 593 594 /** 595 * @see QuickFinder#getBaseLookupUrl() 596 */ 597 public void setBaseLookupUrl(String baseLookupUrl) { 598 this.baseLookupUrl = baseLookupUrl; 599 } 600 601 /** 602 * Full class name the lookup should be provided for. 603 * 604 * <p>This is passed on to the lookup request for the data object the lookup should be rendered for. This is then 605 * used by the lookup framework to select the lookup view (if more than one lookup view exists for the same 606 * data object class name, the {@link #getViewName()} property should be specified to select the view to 607 * render).</p> 608 * 609 * @return lookup class name 610 */ 611 @BeanTagAttribute 612 public String getDataObjectClassName() { 613 return this.dataObjectClassName; 614 } 615 616 /** 617 * @see QuickFinder#getDataObjectClassName() 618 */ 619 public void setDataObjectClassName(String dataObjectClassName) { 620 this.dataObjectClassName = dataObjectClassName; 621 } 622 623 /** 624 * When multiple target lookup views exists for the same data object class, the view name can be set to 625 * determine which one to use. 626 * 627 * <p>When creating multiple lookup views for the same data object class, the view name can be specified for the 628 * different versions (for example 'simple' and 'advanced'). When multiple lookup views exist the view name must 629 * be sent with the data object class for the request. Note the view id can be alternatively used to uniquely 630 * identify the lookup view</p> 631 * 632 * @return String name of lookup view 633 */ 634 @BeanTagAttribute 635 public String getViewName() { 636 return this.viewName; 637 } 638 639 /** 640 * @see QuickFinder#getViewName() 641 */ 642 public void setViewName(String viewName) { 643 this.viewName = viewName; 644 } 645 646 /** 647 * Indicates whether the lookup return should occur through script, or by refresing the page (making server 648 * request). 649 * 650 * <p>For quickfinders that do not need any additional server side action, return through script can be 651 * much faster and prevents a page refresh.</p> 652 * 653 * @return boolean true if the return should occur through script, false if not (default) 654 */ 655 @BeanTagAttribute 656 public boolean isReturnByScript() { 657 return returnByScript; 658 } 659 660 /** 661 * @see QuickFinder#isReturnByScript() 662 */ 663 public void setReturnByScript(boolean returnByScript) { 664 this.returnByScript = returnByScript; 665 } 666 667 /** 668 * Comma delimited String of property names on the lookup view that should be read only. 669 * 670 * <p>When requesting a lookup view, property names for fields that are rendered as search criteria can be marked 671 * as read-only. This is usually done when a lookup parameter for that property is sent in and the user should 672 * not be allowed to change the value</p> 673 * 674 * @return property names (delimited by a comma) whose criteria fields should be read-only on the 675 * lookup view 676 */ 677 @BeanTagAttribute 678 public String getReadOnlyLookupFields() { 679 return this.readOnlyLookupFields; 680 } 681 682 /** 683 * @see QuickFinder#setReadOnlyLookupFields(java.lang.String) 684 */ 685 public void setReadOnlyLookupFields(String readOnlyLookupFields) { 686 this.readOnlyLookupFields = readOnlyLookupFields; 687 } 688 689 /** 690 * List of property names on the model that should be refreshed when the lookup returns. 691 * 692 * <p>Note this is only relevant when the return by script option is not enabled (meaning the server will be 693 * invoked 694 * on the lookup return call)</p> 695 * 696 * <p>When a lookup return call is made (to return a result value) the controller refresh method will be invoked. 697 * If 698 * refresh properties are configured, a call to refresh those references from the database will be made. This is 699 * useful if the lookup returns a foreign key field and the related record is needed.</p> 700 * 701 * @return list of property names to refresh 702 */ 703 @BeanTagAttribute 704 public String getReferencesToRefresh() { 705 return this.referencesToRefresh; 706 } 707 708 /** 709 * @see QuickFinder#getReferencesToRefresh() 710 */ 711 public void setReferencesToRefresh(String referencesToRefresh) { 712 this.referencesToRefresh = referencesToRefresh; 713 } 714 715 /** 716 * Map that determines what properties from a result lookup row (if selected) will be returned to properties on 717 * the calling view. 718 * 719 * <p>The purpose of using the lookup is to search for a particular value and return that value to the form being 720 * completed. In order for the lookup framework to return the field back to us, we must specify the name of the 721 * field on the data object class whose value we need, and the name of the field on the calling view. Furthermore, 722 * we can choose to have the lookup return additional fields that populate other form fields or informational 723 * properties (see ‘Field Queries and Informational Properties’). These pairs of fields are known as 724 * ‘field conversions’.</p> 725 * 726 * <p>The fieldConversions property is a Map. Each entry represents a field that will be returned back from the 727 * lookup, with the entry key being the field name on the data object class, and the entry value being the field 728 * name on the calling view. It is helpful to think of this as a from-to mapping. Pulling from the data object 729 * field (map key) to the calling view field (map value).</p> 730 * 731 * @return mapping of lookup data object property names to view property names 732 */ 733 @BeanTagAttribute 734 public Map<String, String> getFieldConversions() { 735 return this.fieldConversions; 736 } 737 738 /** 739 * @see QuickFinder#getFieldConversions() 740 */ 741 public void setFieldConversions(Map<String, String> fieldConversions) { 742 this.fieldConversions = fieldConversions; 743 } 744 745 /** 746 * Map that determines what properties from a calling view will be sent to properties on that are rendered 747 * for the lookup view's search fields (they can be hidden). 748 * 749 * <p> When invoking a lookup view, we can pre-populate search fields on the lookup view with data from the view 750 * that called the lookup. The user can then perform the search with these values, or (if edited is allowed or 751 * the fields are not hidden) change the passed in values. When the lookup is invoked, the values for the 752 * properties configured within the lookup parameters Map will be pulled and passed along as values for the 753 * lookup view properties</p> 754 * 755 * @return mapping of calling view properties to lookup view search fields 756 */ 757 @BeanTagAttribute 758 public Map<String, String> getLookupParameters() { 759 return this.lookupParameters; 760 } 761 762 /** 763 * @see QuickFinder#getLookupParameters() 764 */ 765 public void setLookupParameters(Map<String, String> lookupParameters) { 766 this.lookupParameters = lookupParameters; 767 } 768 769 /** 770 * Indicates whether the return links for lookup results should be rendered. 771 * 772 * <p>A lookup view can be invoked to allow the user to select a value (or set of values) to return back to the 773 * calling view. For single value lookups this is done with a return link that is rendered for each row. This 774 * return link can be disabled by setting this property to false</p> 775 * 776 * @return true if the return link should not be shown, false if it should be 777 */ 778 @BeanTagAttribute 779 public Boolean getRenderReturnLink() { 780 return this.renderReturnLink; 781 } 782 783 /** 784 * @see QuickFinder#getRenderReturnLink() 785 */ 786 public void setRenderReturnLink(Boolean renderReturnLink) { 787 this.renderReturnLink = renderReturnLink; 788 } 789 790 /** 791 * Indicates whether the maintenance actions (or others) are rendered on the invoked lookup view. 792 * 793 * <p>By default a lookup view will add an actions column for the result table that display maintenance links (in 794 * addition to a new link at the top of the page) if a maintenance action is available. Custom links can also be 795 * added to the action column as necessary. This flag can be set to true to suppress the rendering of the actions 796 * for the lookup call.</p> 797 * 798 * @return true if actions should be rendered, false if not 799 */ 800 @BeanTagAttribute 801 public Boolean getRenderResultActions() { 802 return renderResultActions; 803 } 804 805 /** 806 * @see QuickFinder#getRenderResultActions() 807 */ 808 public void setRenderResultActions(Boolean renderResultActions) { 809 this.renderResultActions = renderResultActions; 810 } 811 812 /** 813 * Indicates whether the search should be executed when first rendering the lookup view. 814 * 815 * <p>By default the lookup view is rendered, the user enters search values and executes the results. This flag can 816 * be set to true to indicate the search should be performed before showing the screen to the user. This is 817 * generally used when search criteria is being passed in as well</p> 818 * 819 * @return true if the search should be performed initially, false if not 820 */ 821 @BeanTagAttribute 822 public Boolean getAutoSearch() { 823 return this.autoSearch; 824 } 825 826 /** 827 * @see org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute#name() 828 */ 829 public void setAutoSearch(Boolean autoSearch) { 830 this.autoSearch = autoSearch; 831 } 832 833 /** 834 * Indicates whether the lookup criteria (search group) should be enabled on the invoked lookup view. 835 * 836 * <p> Setting the this to false will not display the lookup criteria but only the results. Therefore this is only 837 * useful when setting {@link #getAutoSearch()} to true and passing in criteria</p> 838 * 839 * @return true if lookup criteria should be displayed, false if not 840 */ 841 @BeanTagAttribute 842 public Boolean getRenderLookupCriteria() { 843 return this.renderLookupCriteria; 844 } 845 846 /** 847 * @see QuickFinder#getRenderLookupCriteria() 848 */ 849 public void setRenderLookupCriteria(Boolean renderLookupCriteria) { 850 this.renderLookupCriteria = renderLookupCriteria; 851 } 852 853 /** 854 * Indicates whether the criteria actions (footer) should be rendered on the invoked lookup view. 855 * 856 * @return boolean true if actions should be rendered (default), false if not 857 */ 858 @BeanTagAttribute 859 public Boolean getRenderCriteriaActions() { 860 return this.renderCriteriaActions; 861 } 862 863 /** 864 * @see QuickFinder#getRenderCriteriaActions() 865 */ 866 public void setRenderCriteriaActions(Boolean renderCriteriaActions) { 867 this.renderCriteriaActions = renderCriteriaActions; 868 } 869 870 /** 871 * Indicates whether the lookup criteria should be hidden when a search is executed. 872 * 873 * @return boolean true if criteria should be hidden, false if not 874 */ 875 @BeanTagAttribute 876 public Boolean getHideCriteriaOnSearch() { 877 return hideCriteriaOnSearch; 878 } 879 880 /** 881 * @see QuickFinder#getHideCriteriaOnSearch() 882 */ 883 public void setHideCriteriaOnSearch(Boolean hideCriteriaOnSearch) { 884 this.hideCriteriaOnSearch = hideCriteriaOnSearch; 885 } 886 887 /** 888 * Indicates whether the maintenance action links should be rendered for the invoked lookup view. 889 * 890 * <p>If a maintenance view exists for the data object associated with the lookup view, the framework will add 891 * links to initiate a new maintenance document. This flag can be used to disable the rendering of these links</p> 892 * 893 * <p> Note this serves similar purpose to {@link #getRenderResultActions()} but the intent is to only remove the 894 * maintenance links in this situation, not the complete actions column</p> 895 * 896 * @return true if maintenance links should be shown on the lookup view, false if not 897 */ 898 @BeanTagAttribute 899 public Boolean getRenderMaintenanceLinks() { 900 return this.renderMaintenanceLinks; 901 } 902 903 /** 904 * @see QuickFinder#getRenderMaintenanceLinks() 905 */ 906 public void setRenderMaintenanceLinks(Boolean renderMaintenanceLinks) { 907 this.renderMaintenanceLinks = renderMaintenanceLinks; 908 } 909 910 /** 911 * Action component that is used to rendered for the field for invoking the quickfinder action (bringing up the 912 * lookup). 913 * 914 * <p>Through the action configuration the image (or link, button) rendered for the quickfinder can be modified. In 915 * addition to other action component settings</p> 916 * 917 * @return Action instance rendered for quickfinder 918 */ 919 @ViewLifecycleRestriction(exclude=UifConstants.ViewPhases.FINALIZE) 920 @BeanTagAttribute(type = BeanTagAttribute.AttributeType.BYTYPE) 921 public Action getQuickfinderAction() { 922 return this.quickfinderAction; 923 } 924 925 /** 926 * @see QuickFinder#getQuickfinderAction() 927 */ 928 public void setQuickfinderAction(Action quickfinderAction) { 929 this.quickfinderAction = quickfinderAction; 930 } 931 932 /** 933 * The id of the DialogGroup to use when the openInDialog property is true. 934 * 935 * <p>The DialogGroup should only contain an iframe for its items. When not set, a default dialog 936 * will be used.</p> 937 * 938 * @return the id of the dialog to use for this quickfinder 939 */ 940 @BeanTagAttribute 941 public String getLookupDialogId() { 942 return lookupDialogId; 943 } 944 945 /** 946 * @see QuickFinder#getLookupDialogId() 947 */ 948 public void setLookupDialogId(String lookupDialogId) { 949 this.lookupDialogId = lookupDialogId; 950 } 951 952 /** 953 * True if the quickfinder's lookup should be opened in a dialog; true is the default setting for the 954 * bean. 955 * 956 * @return true if the lookup should be opened in a dialog, false to open in a new window 957 */ 958 @BeanTagAttribute 959 public boolean isOpenInDialog() { 960 return openInDialog; 961 } 962 963 /** 964 * @see QuickFinder#isOpenInDialog() 965 */ 966 public void setOpenInDialog(boolean openInDialog) { 967 this.openInDialog = openInDialog; 968 } 969 970 /** 971 * Indicates whether the invoked lookup view should allow multiple values to be selected and returned. 972 * 973 * @return true if multi-value lookup should be requested, false for normal lookup 974 */ 975 @BeanTagAttribute 976 public Boolean getMultipleValuesSelect() { 977 return multipleValuesSelect; 978 } 979 980 /** 981 * @see QuickFinder#getMultipleValuesSelect() 982 */ 983 public void setMultipleValuesSelect(Boolean multipleValuesSelect) { 984 this.multipleValuesSelect = multipleValuesSelect; 985 } 986 987 /** 988 * For the case of multi-value lookup, indicates the collection that should be populated with 989 * the return results. 990 * 991 * <p>Note when the quickfinder is associated with a {@link CollectionGroup}, this property is 992 * set automatically from the collection name associated with the group</p> 993 * 994 * @return collection name (must be full binding path) 995 */ 996 @BeanTagAttribute 997 public String getLookupCollectionName() { 998 return lookupCollectionName; 999 } 1000 1001 /** 1002 * @see QuickFinder#getLookupCollectionName() 1003 */ 1004 public void setLookupCollectionName(String lookupCollectionName) { 1005 this.lookupCollectionName = lookupCollectionName; 1006 } 1007 1008 /** 1009 * For the case of multi-value lookup, indicates the collection id that should be populated with 1010 * the return results. 1011 * 1012 * <p>Note when the quickfinder is associated with a {@link CollectionGroup}, this property is 1013 * set automatically from the collection id associated with the group</p> 1014 * 1015 * @return collection id 1016 */ 1017 @BeanTagAttribute 1018 public String getLookupCollectionId() { 1019 return lookupCollectionId; 1020 } 1021 1022 /** 1023 * @see QuickFinder#getLookupCollectionId() 1024 */ 1025 public void setLookupCollectionId(String lookupCollectionId) { 1026 this.lookupCollectionId = lookupCollectionId; 1027 } 1028 1029 /** 1030 * The additional parameters that were passed to the quickFinder. 1031 * 1032 * @return additionalLookupParameters - map of additional lookup parameters 1033 */ 1034 @BeanTagAttribute 1035 public Map<String, String> getAdditionalLookupParameters() { 1036 return additionalLookupParameters; 1037 } 1038 1039 /** 1040 * @see QuickFinder#getAdditionalLookupParameters() 1041 */ 1042 public void setAdditionalLookupParameters(Map<String, String> additionalLookupParameters) { 1043 this.additionalLookupParameters = additionalLookupParameters; 1044 } 1045 1046 /** 1047 * The name of the callback method to invoke in the view helper service that checks 1048 * request parameters to indicate what view is being returned from. 1049 * 1050 * @return callbackMethodToCall - the name of the callback method 1051 */ 1052 public String getCallbackMethodToCall() { 1053 return callbackMethodToCall; 1054 } 1055 1056 /** 1057 * @see QuickFinder#getCallbackMethodToCall() 1058 */ 1059 public void setCallbackMethodToCall(String callbackMethodToCall) { 1060 this.callbackMethodToCall = callbackMethodToCall; 1061 } 1062 1063 /** 1064 * The specific method invoker to use to invoke the callback method to call. 1065 * 1066 * @return callbackMethod - the method invoker 1067 */ 1068 public MethodInvokerConfig getCallbackMethod() { 1069 return callbackMethod; 1070 } 1071 1072 /** 1073 * @see QuickFinder#getCallbackMethod() 1074 */ 1075 public void setCallbackMethod(MethodInvokerConfig callbackMethod) { 1076 this.callbackMethod = callbackMethod; 1077 } 1078 1079 /** 1080 * The context of parameters to be provided to the callback method to call. 1081 * 1082 * @return callbackContext - map of parameters 1083 */ 1084 public Map<String, String> getCallbackContext() { 1085 return callbackContext; 1086 } 1087 1088 /** 1089 * @see QuickFinder#getCallbackContext() 1090 */ 1091 public void setCallbackContext(Map<String, String> callbackContext) { 1092 this.callbackContext = callbackContext; 1093 } 1094}