001/** 002 * Copyright 2005-2016 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.kns.web.struts.action; 017 018import org.apache.commons.lang.StringUtils; 019import org.apache.struts.action.ActionForm; 020import org.apache.struts.action.ActionForward; 021import org.apache.struts.action.ActionMapping; 022import org.kuali.rice.core.api.util.RiceConstants; 023import org.kuali.rice.kim.api.KimConstants; 024import org.kuali.rice.kim.api.services.KimApiServiceLocator; 025import org.kuali.rice.kns.lookup.LookupUtils; 026import org.kuali.rice.kns.lookup.Lookupable; 027import org.kuali.rice.kns.service.DocumentHelperService; 028import org.kuali.rice.kns.service.KNSServiceLocator; 029import org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService; 030import org.kuali.rice.kns.web.struts.form.LookupForm; 031import org.kuali.rice.kns.web.ui.Field; 032import org.kuali.rice.kns.web.ui.ResultRow; 033import org.kuali.rice.kns.web.ui.Row; 034import org.kuali.rice.krad.exception.AuthorizationException; 035import org.kuali.rice.krad.lookup.CollectionIncomplete; 036import org.kuali.rice.krad.util.GlobalVariables; 037import org.kuali.rice.krad.util.KRADConstants; 038import org.kuali.rice.krad.util.KRADUtils; 039import org.springframework.web.util.HtmlUtils; 040 041import javax.servlet.ServletException; 042import javax.servlet.http.HttpServletRequest; 043import javax.servlet.http.HttpServletResponse; 044import java.io.IOException; 045import java.util.ArrayList; 046import java.util.Collection; 047import java.util.Collections; 048import java.util.HashMap; 049import java.util.Iterator; 050import java.util.Map; 051 052/** 053 * This class handles Actions for lookup flow 054 * 055 * @deprecated Use {@link org.kuali.rice.krad.lookup.LookupController}. 056 */ 057@Deprecated 058public class KualiLookupAction extends KualiAction { 059 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(KualiLookupAction.class); 060 061 @Override 062 protected void checkAuthorization(ActionForm form, String methodToCall) throws AuthorizationException { 063 if (!(form instanceof LookupForm)) { 064 super.checkAuthorization(form, methodToCall); 065 } else { 066 try { 067 Class businessObjectClass = Class.forName(((LookupForm) form).getBusinessObjectClassName()); 068 if (!KimApiServiceLocator.getPermissionService().isAuthorizedByTemplate( 069 GlobalVariables.getUserSession().getPrincipalId(), KRADConstants.KNS_NAMESPACE, 070 KimConstants.PermissionTemplateNames.LOOK_UP_RECORDS, 071 KRADUtils.getNamespaceAndComponentSimpleName(businessObjectClass), 072 Collections.<String, String>emptyMap())) { 073 throw new AuthorizationException(GlobalVariables.getUserSession().getPerson().getPrincipalName(), 074 KimConstants.PermissionTemplateNames.LOOK_UP_RECORDS, 075 businessObjectClass.getSimpleName()); 076 } 077 } 078 catch (ClassNotFoundException e) { 079 LOG.warn("Unable to load BusinessObject class: " + ((LookupForm) form).getBusinessObjectClassName(), e); 080 super.checkAuthorization(form, methodToCall); 081 } 082 } 083 } 084 085 private static MaintenanceDocumentDictionaryService maintenanceDocumentDictionaryService; 086 private static DocumentHelperService documentHelperService; 087 private static MaintenanceDocumentDictionaryService getMaintenanceDocumentDictionaryService() { 088 if (maintenanceDocumentDictionaryService == null) { 089 maintenanceDocumentDictionaryService = KNSServiceLocator.getMaintenanceDocumentDictionaryService(); 090 } 091 return maintenanceDocumentDictionaryService; 092 } 093 private static DocumentHelperService getDocumentHelperService() { 094 if (documentHelperService == null) { 095 documentHelperService = KNSServiceLocator.getDocumentHelperService(); 096 } 097 return documentHelperService; 098 } 099 /** 100 * Checks if the user can create a document for this business object. Used to suppress the actions on the results. 101 * 102 * @param form 103 * @return 104 * @throws ClassNotFoundException 105 */ 106 protected void suppressActionsIfNeeded(ActionForm form) throws ClassNotFoundException { 107 if ((form instanceof LookupForm) && ( ((LookupForm)form).getBusinessObjectClassName() != null )) { 108 Class businessObjectClass = Class.forName( ((LookupForm)form).getBusinessObjectClassName() ); 109 // check if creating documents is allowed 110 String documentTypeName = getMaintenanceDocumentDictionaryService().getDocumentTypeName(businessObjectClass); 111 if ((documentTypeName != null) && !getDocumentHelperService().getDocumentAuthorizer(documentTypeName).canInitiate(documentTypeName, GlobalVariables.getUserSession().getPerson())) { 112 ((LookupForm)form).setSuppressActions( true ); 113 } 114 } 115 } 116 117 /** 118 * This method hides the criteria if set in parameter or lookupable 119 * 120 * @param form 121 */ 122 private void setCriteriaEnabled(ActionForm form) { 123 LookupForm lookupForm = (LookupForm) form; 124 if(lookupForm.isLookupCriteriaEnabled()) { 125 //only overide if it's enabled, if disabled don't call lookupable 126 } 127 } 128 /** 129 * This method hides actions that are not related to the maintenance (as opposed to suppressActionsIfNeeded) 130 * 131 * @param form 132 */ 133 private void suppressNonMaintActionsIfNeeded(ActionForm form) { 134 LookupForm lookupForm = (LookupForm) form; 135 if(lookupForm.getLookupable()!=null) { 136 if(StringUtils.isNotEmpty(lookupForm.getLookupable().getSupplementalMenuBar())) { 137 lookupForm.setSupplementalActionsEnabled(true); 138 } 139 140 } 141 } 142 143 @Override 144 public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, 145 HttpServletResponse response) throws Exception { 146 LookupForm lookupForm = (LookupForm) form; 147 148 request.setAttribute(KRADConstants.PARAM_MAINTENANCE_VIEW_MODE, KRADConstants.PARAM_MAINTENANCE_VIEW_MODE_LOOKUP); 149 suppressActionsIfNeeded(form); 150 suppressNonMaintActionsIfNeeded(form); 151 setCriteriaEnabled(form); 152 153 hideHeaderBarIfNeeded(form, request); 154 155 int numCols = KNSServiceLocator.getBusinessObjectDictionaryService().getLookupNumberOfColumns( 156 Class.forName(lookupForm.getBusinessObjectClassName())); 157 lookupForm.setNumColumns(numCols); 158 159 ActionForward forward = super.execute(mapping, form, request, response); 160 161 // apply conditional logic after all setting of field values has been completed 162 lookupForm.getLookupable().applyConditionalLogicForFieldDisplay(); 163 164 return forward; 165 } 166 167 private void hideHeaderBarIfNeeded(ActionForm form, HttpServletRequest request) { 168 if (!((LookupForm) form).isHeaderBarEnabled()) { 169 ((LookupForm) form).setHeaderBarEnabled(false); 170 } 171 } 172 173 174 /** 175 * Entry point to lookups, forwards to jsp for search render. 176 */ 177 public ActionForward start(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 178 return mapping.findForward(RiceConstants.MAPPING_BASIC); 179 } 180 181 /** 182 * search - sets the values of the data entered on the form on the jsp into a map and then searches for the results. 183 */ 184 public ActionForward search(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 185 LookupForm lookupForm = (LookupForm) form; 186 187 188 String methodToCall = findMethodToCall(form, request); 189 if (methodToCall.equalsIgnoreCase("search")) { 190 GlobalVariables.getUserSession().removeObjectsByPrefix(KRADConstants.SEARCH_METHOD); 191 } 192 193 194 195 Lookupable kualiLookupable = lookupForm.getLookupable(); 196 if (kualiLookupable == null) { 197 LOG.error("Lookupable is null."); 198 throw new RuntimeException("Lookupable is null."); 199 } 200 201 Collection displayList = new ArrayList(); 202 ArrayList<ResultRow> resultTable = new ArrayList<ResultRow>(); 203 204 // validate search parameters 205 kualiLookupable.validateSearchParameters(lookupForm.getFields()); 206 207 boolean bounded = true; 208 209 displayList = kualiLookupable.performLookup(lookupForm, resultTable, bounded); 210 211 if (kualiLookupable.isSearchUsingOnlyPrimaryKeyValues()) { 212 lookupForm.setSearchUsingOnlyPrimaryKeyValues(true); 213 lookupForm.setPrimaryKeyFieldLabels(kualiLookupable.getPrimaryKeyFieldLabels()); 214 } 215 else { 216 lookupForm.setSearchUsingOnlyPrimaryKeyValues(false); 217 lookupForm.setPrimaryKeyFieldLabels(KRADConstants.EMPTY_STRING); 218 } 219 220 if ( displayList instanceof CollectionIncomplete ){ 221 request.setAttribute("reqSearchResultsActualSize", ((CollectionIncomplete) displayList).getActualSizeIfTruncated()); 222 } else { 223 request.setAttribute("reqSearchResultsActualSize", displayList.size() ); 224 } 225 226 int resultsLimit = LookupUtils.getSearchResultsLimit(Class.forName(lookupForm.getBusinessObjectClassName())); 227 request.setAttribute("reqSearchResultsLimitedSize", resultsLimit); 228 229 // Determine if at least one table entry has an action available. If any non-breaking space ( or '\u00A0') characters 230 // exist in the URL's value, they will be converted to regular whitespace ('\u0020'). 231 boolean hasActionUrls = false; 232 for (Iterator<ResultRow> iterator = resultTable.iterator(); !hasActionUrls && iterator.hasNext();) { 233 if (StringUtils.isNotBlank(HtmlUtils.htmlUnescape(iterator.next().getActionUrls()).replace('\u00A0', '\u0020'))) { 234 hasActionUrls = true; 235 } 236 } 237 lookupForm.setActionUrlsExist(hasActionUrls); 238 239 request.setAttribute("reqSearchResults", resultTable); 240 241 if (request.getParameter(KRADConstants.SEARCH_LIST_REQUEST_KEY) != null) { 242 GlobalVariables.getUserSession().removeObject(request.getParameter(KRADConstants.SEARCH_LIST_REQUEST_KEY)); 243 } 244 245 request.setAttribute(KRADConstants.SEARCH_LIST_REQUEST_KEY, GlobalVariables.getUserSession().addObjectWithGeneratedKey(resultTable, KRADConstants.SEARCH_LIST_KEY_PREFIX)); 246 247 request.getParameter(KRADConstants.REFRESH_CALLER); 248 249 return mapping.findForward(RiceConstants.MAPPING_BASIC); 250 } 251 252 253 /** 254 * refresh - is called when one quickFinder returns to the previous one. Sets all the values and performs the new search. 255 */ 256 @Override 257 public ActionForward refresh(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 258 LookupForm lookupForm = (LookupForm) form; 259 Lookupable kualiLookupable = lookupForm.getLookupable(); 260 if (kualiLookupable == null) { 261 LOG.error("Lookupable is null."); 262 throw new RuntimeException("Lookupable is null."); 263 } 264 265 if(StringUtils.equals(lookupForm.getRefreshCaller(),"customLookupAction")) { 266 return this.customLookupableMethodCall(mapping, lookupForm, request, response); 267 } 268 269 Map<String, String> fieldValues = new HashMap(); 270 Map<String, String> values = lookupForm.getFields(); 271 272 for (Row row: kualiLookupable.getRows()) { 273 for (Field field: row.getFields()) { 274 if (field.getPropertyName() != null && !field.getPropertyName().equals("")) { 275 if (request.getParameter(field.getPropertyName()) != null) { 276 if(!Field.MULTI_VALUE_FIELD_TYPES.contains(field.getFieldType())) { 277 field.setPropertyValue(request.getParameter(field.getPropertyName())); 278 } else { 279 //multi value, set to values 280 field.setPropertyValues(request.getParameterValues(field.getPropertyName())); 281 } 282 } 283 } 284 else if (values.get(field.getPropertyName()) != null) { 285 field.setPropertyValue(values.get(field.getPropertyName())); 286 } 287 288 kualiLookupable.applyFieldAuthorizationsFromNestedLookups(field); 289 290 fieldValues.put(field.getPropertyName(), field.getPropertyValue()); 291 } 292 } 293 fieldValues.put("docFormKey", lookupForm.getFormKey()); 294 fieldValues.put("backLocation", lookupForm.getBackLocation()); 295 fieldValues.put("docNum", lookupForm.getDocNum()); 296 297 if (kualiLookupable.checkForAdditionalFields(fieldValues)) { 298 for (Row row: kualiLookupable.getRows()) { 299 for (Object element : row.getFields()) { 300 Field field = (Field) element; 301 if (field.getPropertyName() != null && !field.getPropertyName().equals("")) { 302 if (request.getParameter(field.getPropertyName()) != null) { 303// field.setPropertyValue(request.getParameter(field.getPropertyName())); 304 if(!Field.MULTI_VALUE_FIELD_TYPES.contains(field.getFieldType())) { 305 field.setPropertyValue(request.getParameter(field.getPropertyName())); 306 } else { 307 //multi value, set to values 308 field.setPropertyValues(request.getParameterValues(field.getPropertyName())); 309 } 310 //FIXME: any reason this is inside this "if" instead of the outer one, like above - this seems inconsistent 311 fieldValues.put(field.getPropertyName(), request.getParameter(field.getPropertyName())); 312 } 313 else if (values.get(field.getPropertyName()) != null) { 314 field.setPropertyValue(values.get(field.getPropertyName())); 315 } 316 } 317 } 318 } 319 } 320 return mapping.findForward(RiceConstants.MAPPING_BASIC); 321 } 322 323 /** 324 * Just returns as if return with no value was selected. 325 */ 326 public ActionForward cancel(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 327 LookupForm lookupForm = (LookupForm) form; 328 329 String backUrl = lookupForm.getBackLocation() + "?methodToCall=refresh&docFormKey=" + lookupForm.getFormKey()+"&docNum="+lookupForm.getDocNum(); 330 return new ActionForward(backUrl, true); 331 } 332 333 334 /** 335 * clearValues - clears the values of all the fields on the jsp. 336 */ 337 public ActionForward clearValues(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { 338 LookupForm lookupForm = (LookupForm) form; 339 Lookupable kualiLookupable = lookupForm.getLookupable(); 340 if (kualiLookupable == null) { 341 LOG.error("Lookupable is null."); 342 throw new RuntimeException("Lookupable is null."); 343 } 344 345 kualiLookupable.performClear(lookupForm); 346 347 348 return mapping.findForward(RiceConstants.MAPPING_BASIC); 349 } 350 351 352 public ActionForward viewResults(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 353 LookupForm lookupForm = (LookupForm) form; 354 if (lookupForm.isSearchUsingOnlyPrimaryKeyValues()) { 355 lookupForm.setPrimaryKeyFieldLabels(lookupForm.getLookupable().getPrimaryKeyFieldLabels()); 356 } 357 // KULRICE-12281- Turn off the ability to export results from certain lookups 358 if(StringUtils.isNotBlank(request.getParameter(KRADConstants.Lookup.VIEW_RESULTS_EXPORT_OPTION))) { 359 String componentName = Class.forName(lookupForm.getBusinessObjectClassName()).getSimpleName(); 360 String principalId = GlobalVariables.getUserSession().getPrincipalId(); 361 String principalUserName = GlobalVariables.getUserSession().getPrincipalName(); 362 Map<String, String> permissionDetails = new HashMap<String,String>(); 363 permissionDetails.put(KRADConstants.COMPONENT_NAME, componentName); 364 boolean isAuthorized = KimApiServiceLocator.getPermissionService().isAuthorizedByTemplate( 365 principalId,KRADConstants.KNS_NAMESPACE,KimConstants.PermissionTemplateNames.VIEW_RESULTS_EXPORT_ACTION, 366 permissionDetails,new HashMap<String,String>()); 367 if(!isAuthorized){ 368 throw new AuthorizationException(principalUserName, "Exporting the Lookup Results", componentName); 369 } 370 } 371 request.setAttribute(KRADConstants.SEARCH_LIST_REQUEST_KEY, request.getParameter(KRADConstants.SEARCH_LIST_REQUEST_KEY)); 372 request.setAttribute("reqSearchResults", GlobalVariables.getUserSession().retrieveObject(request.getParameter( 373 KRADConstants.SEARCH_LIST_REQUEST_KEY))); 374 request.setAttribute("reqSearchResultsActualSize", request.getParameter("reqSearchResultsActualSize")); 375 return mapping.findForward(RiceConstants.MAPPING_BASIC); 376 } 377 378 public ActionForward customLookupableMethodCall(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 379// lookupableMethodToCall 380 Lookupable kualiLookupable = ((LookupForm)form).getLookupable(); 381 if (kualiLookupable == null) { 382 LOG.error("Lookupable is null."); 383 throw new RuntimeException("Lookupable is null."); 384 } 385 386 boolean ignoreErrors=false; 387 if(StringUtils.equals(((LookupForm)form).getRefreshCaller(),"customLookupAction")) { 388 ignoreErrors=true; 389 } 390 391 if(kualiLookupable.performCustomAction(ignoreErrors)) { 392 //redo the search if the method comes back 393 return search(mapping, form, request, response); 394 } 395 return mapping.findForward(RiceConstants.MAPPING_BASIC); 396 397 } 398 399}