001 /** 002 * Copyright 2005-2012 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.krad.uif.view; 017 018 import org.apache.commons.lang.StringUtils; 019 import org.kuali.rice.krad.uif.UifConstants.ViewType; 020 import org.kuali.rice.krad.uif.UifPropertyPaths; 021 import org.kuali.rice.krad.uif.container.CollectionGroup; 022 import org.kuali.rice.krad.uif.container.Group; 023 import org.kuali.rice.krad.uif.component.Component; 024 import org.kuali.rice.krad.uif.component.RequestParameter; 025 import org.kuali.rice.krad.uif.field.Field; 026 import org.kuali.rice.krad.web.form.LookupForm; 027 028 import java.util.Arrays; 029 import java.util.List; 030 031 /** 032 * View type for Maintenance documents 033 * 034 * <p> 035 * Supports doing a search against a data object class or performing a more advanced query. The view 036 * type is primarily made up of two groups, the search (or criteria) group and the results group. Many 037 * options are supported on the view to enable/disable certain features, like what actions are available 038 * on the search results. 039 * </p> 040 * 041 * <p> 042 * Works in conjunction with <code>LookupableImpl</code> which customizes the view and carries out the 043 * business functionality 044 * </p> 045 * 046 * @author Kuali Rice Team (rice.collab@kuali.org) 047 */ 048 public class LookupView extends FormView { 049 private static final long serialVersionUID = 716926008488403616L; 050 051 private Class<?> dataObjectClassName; 052 053 private Group criteriaGroup; 054 private CollectionGroup resultsGroup; 055 056 private Field resultsActionsField; 057 private Field resultsReturnField; 058 059 private List<Component> criteriaFields; 060 private List<Component> resultFields; 061 private List<String> defaultSortAttributeNames; 062 063 protected boolean defaultSortAscending = true; 064 065 @RequestParameter 066 private boolean hideReturnLinks = false; 067 @RequestParameter 068 private boolean suppressActions = false; 069 @RequestParameter 070 private boolean showMaintenanceLinks = false; 071 @RequestParameter 072 private boolean multipleValuesSelect = false; 073 074 @RequestParameter 075 private String returnTarget; 076 077 @RequestParameter 078 private boolean returnByScript; 079 080 private boolean lookupCriteriaEnabled = true; 081 private boolean supplementalActionsEnabled = false; 082 private boolean disableSearchButtons = false; 083 084 private Integer resultSetLimit = null; 085 086 private String maintenanceUrlMapping; 087 088 public LookupView() { 089 super(); 090 setViewTypeName(ViewType.LOOKUP); 091 setValidateDirty(false); 092 } 093 094 /** 095 * The following initialization is performed: 096 * 097 * <ul> 098 * <li>Set the abstractTypeClasses map for the lookup object path</li> 099 * </ul> 100 * 101 * @see org.kuali.rice.krad.uif.container.ContainerBase#performInitialization(org.kuali.rice.krad.uif.view.View, java.lang.Object) 102 */ 103 @Override 104 public void performInitialization(View view, Object model) { 105 initializeGroups(); 106 if (getItems().isEmpty()) { 107 setItems(Arrays.asList(getCriteriaGroup(), getResultsGroup())); 108 } 109 super.performInitialization(view, model); 110 111 // if this is a multi-value lookup, don't show return column 112 if (multipleValuesSelect) { 113 hideReturnLinks = true; 114 } 115 116 getAbstractTypeClasses().put(UifPropertyPaths.CRITERIA_FIELDS, getDataObjectClassName()); 117 if (StringUtils.isNotBlank(getDefaultBindingObjectPath())) { 118 getAbstractTypeClasses().put(getDefaultBindingObjectPath(), getDataObjectClassName()); 119 } 120 } 121 122 protected void initializeGroups() { 123 if ((getCriteriaGroup() != null) && (getCriteriaGroup().getItems().isEmpty())) { 124 getCriteriaGroup().setItems(getCriteriaFields()); 125 } 126 if (getResultsGroup() != null) { 127 if ((getResultsGroup().getItems().isEmpty()) && (getResultFields() != null)) { 128 getResultsGroup().setItems(getResultFields()); 129 } 130 if (getResultsGroup().getCollectionObjectClass() == null) { 131 getResultsGroup().setCollectionObjectClass(getDataObjectClassName()); 132 } 133 } 134 } 135 136 /** 137 * @see org.kuali.rice.krad.uif.container.ContainerBase#performApplyModel(org.kuali.rice.krad.uif.view.View, 138 * java.lang.Object) 139 */ 140 @Override 141 public void performApplyModel(View view, Object model, Component parent) { 142 LookupForm lookupForm = (LookupForm) model; 143 144 // TODO: need to check lookupForm.isAtLeastOneRowHasActions() somewhere 145 if (!isSuppressActions() && isShowMaintenanceLinks()) { 146 ((List<Field>) getResultsGroup().getItems()).add(0, getResultsActionsField()); 147 } 148 149 if (StringUtils.isNotBlank(lookupForm.getReturnFormKey()) && 150 StringUtils.isNotBlank(lookupForm.getReturnLocation()) && !isHideReturnLinks()) { 151 ((List<Field>) getResultsGroup().getItems()).add(0, getResultsReturnField()); 152 } 153 154 super.performApplyModel(view, model, parent); 155 } 156 157 /** 158 * @see org.kuali.rice.krad.uif.component.Component#getComponentPrototypes() 159 */ 160 @Override 161 public List<Component> getComponentPrototypes() { 162 List<Component> components = super.getComponentPrototypes(); 163 164 components.add(criteriaGroup); 165 components.add(resultsGroup); 166 components.add(resultsActionsField); 167 components.add(resultsReturnField); 168 components.addAll(criteriaFields); 169 components.addAll(resultFields); 170 171 return components; 172 } 173 174 public void applyConditionalLogicForFieldDisplay() { 175 // TODO: work into view lifecycle 176 // LookupViewHelperService lookupViewHelperService = (LookupViewHelperService) getViewHelperService(); 177 // Set<String> readOnlyFields = lookupViewHelperService.getConditionallyReadOnlyPropertyNames(); 178 // Set<String> requiredFields = lookupViewHelperService.getConditionallyRequiredPropertyNames(); 179 // Set<String> hiddenFields = lookupViewHelperService.getConditionallyHiddenPropertyNames(); 180 // if ( (readOnlyFields != null && !readOnlyFields.isEmpty()) || 181 // (requiredFields != null && !requiredFields.isEmpty()) || 182 // (hiddenFields != null && !hiddenFields.isEmpty()) 183 // ) { 184 // for (Field field : getResultsGroup().getItems()) { 185 // if (InputField.class.isAssignableFrom(field.getClass())) { 186 // InputField attributeField = (InputField) field; 187 // if (readOnlyFields != null && readOnlyFields.contains(attributeField.getBindingInfo().getBindingName())) { 188 // attributeField.setReadOnly(true); 189 // } 190 // if (requiredFields != null && requiredFields.contains(attributeField.getBindingInfo().getBindingName())) { 191 // attributeField.setRequired(Boolean.TRUE); 192 // } 193 // if (hiddenFields != null && hiddenFields.contains(attributeField.getBindingInfo().getBindingName())) { 194 // attributeField.setControl(LookupInquiryUtils.generateCustomLookupControlFromExisting(HiddenControl.class, null)); 195 // } 196 // } 197 // } 198 // } 199 } 200 201 /** 202 * Class name for the object the lookup applies to 203 * 204 * <p> 205 * The object class name is used to pick up a dictionary entry which will 206 * feed the attribute field definitions and other configuration. In addition 207 * it is to configure the <code>Lookupable</code> which will carry out the 208 * lookup action 209 * </p> 210 * 211 * @return Class<?> lookup data object class 212 */ 213 public Class<?> getDataObjectClassName() { 214 return this.dataObjectClassName; 215 } 216 217 /** 218 * Setter for the object class name 219 * 220 * @param dataObjectClassName 221 */ 222 public void setDataObjectClassName(Class<?> dataObjectClassName) { 223 this.dataObjectClassName = dataObjectClassName; 224 } 225 226 /** 227 * @return the hideReturnLinks 228 */ 229 public boolean isHideReturnLinks() { 230 return this.hideReturnLinks; 231 } 232 233 /** 234 * @param hideReturnLinks the hideReturnLinks to set 235 */ 236 public void setHideReturnLinks(boolean hideReturnLinks) { 237 this.hideReturnLinks = hideReturnLinks; 238 } 239 240 /** 241 * @return the suppressActions 242 */ 243 public boolean isSuppressActions() { 244 return this.suppressActions; 245 } 246 247 /** 248 * @param suppressActions the suppressActions to set 249 */ 250 public void setSuppressActions(boolean suppressActions) { 251 this.suppressActions = suppressActions; 252 } 253 254 /** 255 * @return the showMaintenanceLinks 256 */ 257 public boolean isShowMaintenanceLinks() { 258 return this.showMaintenanceLinks; 259 } 260 261 /** 262 * @param showMaintenanceLinks the showMaintenanceLinks to set 263 */ 264 public void setShowMaintenanceLinks(boolean showMaintenanceLinks) { 265 this.showMaintenanceLinks = showMaintenanceLinks; 266 } 267 268 /** 269 * Indicates whether multiple values select should be enabled for the lookup 270 * 271 * <p> 272 * When set to true, the select field is enabled for the lookup results group that allows the user 273 * to select one or more rows for returning 274 * </p> 275 * 276 * @return boolean true if multiple values should be enabled, false otherwise 277 */ 278 public boolean isMultipleValuesSelect() { 279 return multipleValuesSelect; 280 } 281 282 /** 283 * Setter for the multiple values select indicator 284 * 285 * @param multipleValuesSelect 286 */ 287 public void setMultipleValuesSelect(boolean multipleValuesSelect) { 288 this.multipleValuesSelect = multipleValuesSelect; 289 } 290 291 /** 292 * @return the resultsActionsField 293 */ 294 public Field getResultsActionsField() { 295 return this.resultsActionsField; 296 } 297 298 /** 299 * @param resultsActionsField the resultsActionsField to set 300 */ 301 public void setResultsActionsField(Field resultsActionsField) { 302 this.resultsActionsField = resultsActionsField; 303 } 304 305 /** 306 * @return the resultsReturnField 307 */ 308 public Field getResultsReturnField() { 309 return this.resultsReturnField; 310 } 311 312 /** 313 * @param resultsReturnField the resultsReturnField to set 314 */ 315 public void setResultsReturnField(Field resultsReturnField) { 316 this.resultsReturnField = resultsReturnField; 317 } 318 319 public Group getCriteriaGroup() { 320 return this.criteriaGroup; 321 } 322 323 public void setCriteriaGroup(Group criteriaGroup) { 324 this.criteriaGroup = criteriaGroup; 325 } 326 327 public CollectionGroup getResultsGroup() { 328 return this.resultsGroup; 329 } 330 331 public void setResultsGroup(CollectionGroup resultsGroup) { 332 this.resultsGroup = resultsGroup; 333 } 334 335 public List<Component> getCriteriaFields() { 336 return this.criteriaFields; 337 } 338 339 public void setCriteriaFields(List<Component> criteriaFields) { 340 this.criteriaFields = criteriaFields; 341 } 342 343 public List<Component> getResultFields() { 344 return this.resultFields; 345 } 346 347 public void setResultFields(List<Component> resultFields) { 348 this.resultFields = resultFields; 349 } 350 351 public List<String> getDefaultSortAttributeNames() { 352 return this.defaultSortAttributeNames; 353 } 354 355 public void setDefaultSortAttributeNames(List<String> defaultSortAttributeNames) { 356 this.defaultSortAttributeNames = defaultSortAttributeNames; 357 } 358 359 public boolean isDefaultSortAscending() { 360 return this.defaultSortAscending; 361 } 362 363 public void setDefaultSortAscending(boolean defaultSortAscending) { 364 this.defaultSortAscending = defaultSortAscending; 365 } 366 367 /** 368 * Retrieves the maximum number of records that will be listed 369 * as a result of the lookup search 370 * 371 * @return Integer result set limit 372 */ 373 public Integer getResultSetLimit() { 374 return resultSetLimit; 375 } 376 377 /** 378 * Setter for the result list limit 379 * 380 * @param resultSetLimit Integer specifying limit 381 */ 382 public void setResultSetLimit(Integer resultSetLimit) { 383 this.resultSetLimit = resultSetLimit; 384 } 385 386 /** 387 * Indicates whether a result set limit has been specified for the 388 * view 389 * 390 * @return true if this instance has a result set limit 391 */ 392 public boolean hasResultSetLimit() { 393 return (resultSetLimit != null); 394 } 395 396 /** 397 * @param returnTarget the returnTarget to set 398 */ 399 public void setReturnTarget(String returnTarget) { 400 this.returnTarget = returnTarget; 401 } 402 403 /** 404 * @return the returnTarget 405 */ 406 public String getReturnTarget() { 407 return returnTarget; 408 } 409 410 /** 411 * @return the returnByScript 412 */ 413 public boolean isReturnByScript() { 414 return returnByScript; 415 } 416 417 /** 418 * Setter for the flag to indicate that lookups will return the value 419 * by script and not a post 420 * 421 * @param returnByScript the returnByScript flag 422 */ 423 public void setReturnByScript(boolean returnByScript) { 424 this.returnByScript = returnByScript; 425 } 426 427 /** 428 * String that maps to the maintenance controller for the maintenance document (if any) associated with the 429 * lookup data object class 430 * 431 * <p> 432 * Mapping will be used to build the maintenance action links (such as edit, copy, and new). If not given, the 433 * default maintenance mapping will be used 434 * </p> 435 * 436 * @return String mapping string 437 */ 438 public String getMaintenanceUrlMapping() { 439 return maintenanceUrlMapping; 440 } 441 442 /** 443 * Setter for the URL mapping string that will be used to build up maintenance action URLs 444 * 445 * @param maintenanceUrlMapping 446 */ 447 public void setMaintenanceUrlMapping(String maintenanceUrlMapping) { 448 this.maintenanceUrlMapping = maintenanceUrlMapping; 449 } 450 }