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.krad.service.impl; 017 018import java.util.ArrayList; 019import java.util.Collections; 020import java.util.HashMap; 021import java.util.HashSet; 022import java.util.Iterator; 023import java.util.List; 024import java.util.Map; 025import java.util.Set; 026 027import org.apache.commons.lang.StringUtils; 028import org.kuali.rice.core.api.criteria.QueryByCriteria; 029import org.kuali.rice.core.api.util.RiceConstants; 030import org.kuali.rice.kim.api.KimConstants.PermissionNames; 031import org.kuali.rice.kim.api.identity.Person; 032import org.kuali.rice.kim.api.identity.PersonService; 033import org.kuali.rice.kim.api.permission.PermissionService; 034import org.kuali.rice.kim.api.services.KimApiServiceLocator; 035import org.kuali.rice.kns.authorization.AuthorizationConstants; 036import org.kuali.rice.krad.data.DataObjectService; 037import org.kuali.rice.krad.document.Document; 038import org.kuali.rice.krad.document.authorization.PessimisticLock; 039import org.kuali.rice.krad.exception.AuthorizationException; 040import org.kuali.rice.krad.exception.PessimisticLockingException; 041import org.kuali.rice.krad.service.DataDictionaryService; 042import org.kuali.rice.krad.service.LegacyDataAdapter; 043import org.kuali.rice.krad.service.PessimisticLockService; 044import org.kuali.rice.krad.util.GlobalVariables; 045import org.kuali.rice.krad.util.KRADConstants; 046import org.kuali.rice.krad.util.KRADPropertyConstants; 047import org.springframework.beans.factory.annotation.Required; 048import org.springframework.transaction.annotation.Transactional; 049 050/** 051 * Service implementation for pessimistic locking 052 * 053 * @author Kuali Rice Team (rice.collab@kuali.org) 054 */ 055@Transactional 056public class PessimisticLockServiceImpl implements PessimisticLockService { 057 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PessimisticLockServiceImpl.class); 058 059 protected DataObjectService dataObjectService; 060 protected DataDictionaryService dataDictionaryService; 061 protected PermissionService permissionService; 062 protected PersonService personService; 063 064 /** 065 * @see org.kuali.rice.krad.service.PessimisticLockService#delete(java.lang.String) 066 */ 067 @Override 068 public void delete(String id) { 069 if (StringUtils.isBlank(id)) { 070 throw new IllegalArgumentException("An invalid blank id was passed to delete a Pessimistic Lock."); 071 } 072 PessimisticLock lock = dataObjectService.find(PessimisticLock.class, Long.valueOf(id)); 073 if ( lock == null ) { 074 throw new IllegalArgumentException("Pessimistic Lock with id " + id + " cannot be found in the database."); 075 } 076 Person user = GlobalVariables.getUserSession().getPerson(); 077 if ( (!lock.isOwnedByUser(user)) && (!isPessimisticLockAdminUser(user)) ) { 078 throw new AuthorizationException(user.getName(),"delete", "Pessimistick Lock (id " + id + ")"); 079 } 080 delete(lock); 081 } 082 083 private void delete(PessimisticLock lock) { 084 if ( LOG.isDebugEnabled() ) { 085 LOG.debug("Deleting lock: " + lock); 086 } 087 dataObjectService.delete(lock); 088 } 089 090 /** 091 * @see org.kuali.rice.krad.service.PessimisticLockService#generateNewLock(String) 092 */ 093 @Override 094 public PessimisticLock generateNewLock(String documentNumber) { 095 return generateNewLock(documentNumber, GlobalVariables.getUserSession().getPerson()); 096 } 097 098 /** 099 * @see org.kuali.rice.krad.service.PessimisticLockService#generateNewLock(java.lang.String) 100 */ 101 @Override 102 public PessimisticLock generateNewLock(String documentNumber, String lockDescriptor) { 103 return generateNewLock(documentNumber, lockDescriptor, GlobalVariables.getUserSession().getPerson()); 104 } 105 106 /** 107 * @see org.kuali.rice.krad.service.PessimisticLockService#generateNewLock(java.lang.String, org.kuali.rice.kim.api.identity.Person) 108 */ 109 @Override 110 public PessimisticLock generateNewLock(String documentNumber, Person user) { 111 return generateNewLock(documentNumber, PessimisticLock.DEFAULT_LOCK_DESCRIPTOR, user); 112 } 113 114 /** 115 * @see org.kuali.rice.krad.service.PessimisticLockService#generateNewLock(java.lang.String, java.lang.String, org.kuali.rice.kim.api.identity.Person) 116 */ 117 @Override 118 public PessimisticLock generateNewLock(String documentNumber, String lockDescriptor, Person user) { 119 PessimisticLock lock = new PessimisticLock(documentNumber, lockDescriptor, user, GlobalVariables.getUserSession()); 120 lock = save(lock); 121 if ( LOG.isDebugEnabled() ) { 122 LOG.debug("Generated new lock: " + lock); 123 } 124 return lock; 125 } 126 127 /** 128 * @see org.kuali.rice.krad.service.PessimisticLockService#getPessimisticLocksForDocument(java.lang.String) 129 */ 130 @Override 131 public List<PessimisticLock> getPessimisticLocksForDocument(String documentNumber) { 132 return new ArrayList<PessimisticLock>( dataObjectService.findMatching(PessimisticLock.class, 133 QueryByCriteria.Builder.forAttribute(KRADPropertyConstants.DOCUMENT_NUMBER, documentNumber) 134 .build()).getResults() ); 135 } 136 137 /** 138 * @see org.kuali.rice.krad.service.PessimisticLockService#getPessimisticLocksForSession(java.lang.String) 139 */ 140 @Override 141 public List<PessimisticLock> getPessimisticLocksForSession(String sessionId) { 142 return new ArrayList<PessimisticLock>( dataObjectService.findMatching(PessimisticLock.class, 143 QueryByCriteria.Builder.forAttribute(KRADPropertyConstants.SESSION_ID, sessionId) 144 .build()).getResults() ); 145 } 146 147 /** 148 * @see org.kuali.rice.krad.service.PessimisticLockService#isPessimisticLockAdminUser(org.kuali.rice.kim.api.identity.Person) 149 */ 150 @Override 151 public boolean isPessimisticLockAdminUser(Person user) { 152 return getPermissionService().isAuthorized( user.getPrincipalId(), KRADConstants.KNS_NAMESPACE, PermissionNames.ADMIN_PESSIMISTIC_LOCKING, 153 Collections.<String, String>emptyMap() ); 154 } 155 156 /** 157 * @see org.kuali.rice.krad.service.PessimisticLockService#releaseAllLocksForUser(java.util.List, org.kuali.rice.kim.api.identity.Person) 158 */ 159 @Override 160 public void releaseAllLocksForUser(List<PessimisticLock> locks, Person user) { 161 for (Iterator<PessimisticLock> iterator = locks.iterator(); iterator.hasNext();) { 162 PessimisticLock lock = iterator.next(); 163 if (lock.isOwnedByUser(user)) { 164 try { 165 delete(lock); 166 } catch ( RuntimeException ex ) { 167 if ( ex.getCause() != null && ex.getCause().getClass().equals( LegacyDataAdapter.OPTIMISTIC_LOCK_OJB_EXCEPTION_CLASS ) ) { 168 LOG.warn( "Suppressing Optimistic Lock Exception. Document Num: " + lock.getDocumentNumber()); 169 } else { 170 throw ex; 171 } 172 } 173 } 174 } 175 } 176 177 /** 178 * @see org.kuali.rice.krad.service.PessimisticLockService#releaseAllLocksForUser(java.util.List, org.kuali.rice.kim.api.identity.Person, java.lang.String) 179 */ 180 @Override 181 public void releaseAllLocksForUser(List<PessimisticLock> locks, Person user, String lockDescriptor) { 182 for (Iterator<PessimisticLock> iterator = locks.iterator(); iterator.hasNext();) { 183 PessimisticLock lock = iterator.next(); 184 if ( (lock.isOwnedByUser(user)) && (lockDescriptor.equals(lock.getLockDescriptor())) ) { 185 try { 186 delete(lock); 187 } catch ( RuntimeException ex ) { 188 if ( ex.getCause() != null && ex.getCause().getClass().equals( LegacyDataAdapter.OPTIMISTIC_LOCK_OJB_EXCEPTION_CLASS ) ) { 189 LOG.warn( "Suppressing Optimistic Lock Exception. Document Num: " + lock.getDocumentNumber()); 190 } else { 191 throw ex; 192 } 193 } 194 } 195 } 196 } 197 198 /** 199 * @see org.kuali.rice.krad.service.PessimisticLockService#save(org.kuali.rice.krad.document.authorization.PessimisticLock) 200 */ 201 @Override 202 public PessimisticLock save(PessimisticLock lock) { 203 if ( LOG.isDebugEnabled() ) { 204 LOG.debug("Saving lock: " + lock); 205 } 206 return dataObjectService.save(lock); 207 } 208 209 /** 210 * {@inheritDoc} 211 */ 212 @Override 213 public boolean establishPessimisticLocks(Document document, Person user, boolean canEdit) { 214 // establish pessimistic locks if needed 215 if (isPessimisticLockNeeded(document, user, canEdit)) { 216 PessimisticLock pessimisticLock = createNewPessimisticLock(document, user); 217 document.addPessimisticLock(pessimisticLock); 218 } 219 220 // find if any pessimistic locks are owned by the given user 221 for (PessimisticLock pessimisticLock : document.getPessimisticLocks()) { 222 if (pessimisticLock.isOwnedByUser(user)) { 223 return true; 224 } 225 } 226 227 return false; 228 } 229 230 /** 231 * Determines whether to add a pessimistic lock on the {@code document} for {@code user} based on the current 232 * pessimistic locks and edit modes. 233 * 234 * @param document the document on which the locks will be established 235 * @param user the user for which the locks are being established 236 * @param canEdit whether the user currently can edit the document 237 * 238 * @return true if a pessimistic lock should be added, false otherwise 239 */ 240 protected boolean isPessimisticLockNeeded(Document document, Person user, boolean canEdit) { 241 List<String> userOwnedLockDescriptors = new ArrayList<String>(); 242 Map<String, Set<String>> otherOwnedLockDescriptors = new HashMap<String,Set<String>>(); 243 244 // create the two lock containers that help determine whether to add a pessimistic lock 245 for (PessimisticLock pessimisticLock : document.getPessimisticLocks()) { 246 if (pessimisticLock.isOwnedByUser(user)) { 247 userOwnedLockDescriptors.add(pessimisticLock.getLockDescriptor()); 248 } else { 249 if (!otherOwnedLockDescriptors.containsKey(pessimisticLock.getLockDescriptor())) { 250 otherOwnedLockDescriptors.put(pessimisticLock.getLockDescriptor(), new HashSet<String>()); 251 } 252 253 String otherOwnerPrincipalId = pessimisticLock.getOwnedByUser().getPrincipalId(); 254 otherOwnedLockDescriptors.get(pessimisticLock.getLockDescriptor()).add(otherOwnerPrincipalId); 255 } 256 } 257 258 // double check whether the existing pessimistic locks are sane 259 checkExistingPessimisticLocks(document, userOwnedLockDescriptors, otherOwnedLockDescriptors); 260 261 // if no one has a lock on this document, then the document can be locked if the user can edit it 262 if (userOwnedLockDescriptors.isEmpty() && otherOwnedLockDescriptors.isEmpty()) { 263 return canEdit; 264 } 265 266 // if custom locking is turned on, then if the current user doesn't have a custom lock on this document and no 267 // one else has a custom lock on this document, then the document can be locked if the user can edit it 268 if (document.useCustomLockDescriptors()) { 269 String customLockDescriptor = document.getCustomLockDescriptor(user); 270 boolean userOwnsCustomLockDescriptor = userOwnedLockDescriptors.contains(customLockDescriptor); 271 boolean otherOwnsCustomLockDescriptor = otherOwnedLockDescriptors.containsKey(customLockDescriptor); 272 273 if (!userOwnsCustomLockDescriptor && !otherOwnsCustomLockDescriptor) { 274 return canEdit; 275 } 276 } 277 278 return false; 279 } 280 281 /** 282 * Check to make sure that the current user doesn't erroneously share the same lock with another user. 283 * 284 * @param document the document to check for erroneous locks 285 * @param userOwnedLockDescriptors the list of lock descriptors for the current user 286 * @param otherOwnedLockDescriptors the map of other lock descriptors to all of the other users that own them 287 */ 288 protected void checkExistingPessimisticLocks(Document document, List<String> userOwnedLockDescriptors, Map<String, Set<String>> otherOwnedLockDescriptors) { 289 for (String userOwnedLockDescriptor : userOwnedLockDescriptors) { 290 if (otherOwnedLockDescriptors.containsKey(userOwnedLockDescriptor)) { 291 Set<String> otherOwnerPrincipalIds = otherOwnedLockDescriptors.get(userOwnedLockDescriptor); 292 String workflowOwnerPrincipalId = getWorkflowPessimisticLockOwnerUser().getPrincipalId(); 293 boolean hasOtherOwners = !otherOwnerPrincipalIds.isEmpty(); 294 boolean hasMoreThanOneOtherOwner = otherOwnerPrincipalIds.size() > 1; 295 boolean hasWorkflowOwner = otherOwnerPrincipalIds.contains(workflowOwnerPrincipalId); 296 297 // if the lock has other owners, then if there is more than one other owner or if the single other owner 298 // is not the workflow user, then throw an error 299 if (hasOtherOwners && (hasMoreThanOneOtherOwner || !hasWorkflowOwner)) { 300 StringBuilder builder = new StringBuilder("Found an invalid lock status on document number "); 301 builder.append(document.getDocumentNumber()); 302 builder.append(" with current user and other user both having locks concurrently"); 303 304 if (document.useCustomLockDescriptors()) { 305 builder.append(" for custom lock descriptor '"); 306 builder.append(userOwnedLockDescriptor); 307 builder.append("'"); 308 } 309 310 builder.append("."); 311 312 LOG.debug(builder.toString()); 313 314 throw new PessimisticLockingException(builder.toString()); 315 } 316 } 317 } 318 } 319 320 /** 321 * Creates a new {@link PessimisticLock} on a {@code document} for a {@code user}. 322 * 323 * <p> 324 * If the {@code document} uses custom lock descriptors, then the new lock is generated with a custom lock 325 * descriptor for a portion of the document. Otherwise, it will create a lock over the entire document. 326 * </p> 327 * 328 * @param document the document on which the locks will be established 329 * @param user the user for which the locks are being established 330 * 331 * @return the newly created lock object 332 */ 333 protected PessimisticLock createNewPessimisticLock(Document document, Person user) { 334 if (document.useCustomLockDescriptors()) { 335 return generateNewLock(document.getDocumentNumber(), document.getCustomLockDescriptor(user), user); 336 } else { 337 return generateNewLock(document.getDocumentNumber(), user); 338 } 339 } 340 341 /** 342 * {@inheritDoc} 343 */ 344 @Override 345 @Deprecated 346 public Set getDocumentActions(Document document, Person user, Set<String> documentActions){ 347 if(documentActions.contains(KRADConstants.KUALI_ACTION_CAN_CANCEL) && !hasPreRouteEditAuthorization(document, user) ){ 348 documentActions.remove(KRADConstants.KUALI_ACTION_CAN_CANCEL); 349 } 350 if(documentActions.contains(KRADConstants.KUALI_ACTION_CAN_SAVE) && !hasPreRouteEditAuthorization(document, user)){ 351 documentActions.remove(KRADConstants.KUALI_ACTION_CAN_SAVE); 352 } 353 if(documentActions.contains(KRADConstants.KUALI_ACTION_CAN_ROUTE) && !hasPreRouteEditAuthorization(document, user)){ 354 documentActions.remove(KRADConstants.KUALI_ACTION_CAN_ROUTE); 355 } 356 if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_BLANKET_APPROVE) && !hasPreRouteEditAuthorization(document, user)){ 357 documentActions.remove(KRADConstants.KUALI_ACTION_CAN_BLANKET_APPROVE); 358 } 359 return documentActions; 360 } 361 362 363 /** 364 * This method checks to see that the given user has a lock on the document and return true if one is found. 365 * 366 * @param document - document to check 367 * @param user - current user 368 * @return true if the document is using Pessimistic Locking, the user has initiate authorization (see 369 * {@link #hasInitiateAuthorization(Document, Person)}), and the document has a lock owned by the given 370 * user. If the document is not using Pessimistic Locking the value returned will be that returned by 371 * {@link #hasInitiateAuthorization(Document, Person)}. 372 * 373 * @deprecated Different mechanism of obtaining authorization in KRAD 374 */ 375 @Deprecated 376 protected boolean hasPreRouteEditAuthorization(Document document, Person user) { 377 if (document.getPessimisticLocks().isEmpty()) { 378 return true; 379 } 380 for (Iterator<PessimisticLock> iterator = document.getPessimisticLocks().iterator(); iterator.hasNext();) { 381 PessimisticLock lock = iterator.next(); 382 if (lock.isOwnedByUser(user)) { 383 return true; 384 } 385 } 386 return false; 387 } 388 389 @Deprecated 390 protected boolean usesPessimisticLocking(Document document) { 391 return getDataDictionaryService().getDataDictionary().getDocumentEntry(document.getClass().getName()).getUsePessimisticLocking(); 392 } 393 394 395 /** 396 * This method creates a new {@link PessimisticLock} when Workflow processing requires one 397 * 398 * @param document - the document to create the lock against and add the lock to 399 * @see org.kuali.rice.kns.document.authorization.DocumentAuthorizer#establishWorkflowPessimisticLocking(org.kuali.rice.krad.document.Document) 400 */ 401 @Override 402 public void establishWorkflowPessimisticLocking(Document document) { 403 PessimisticLock lock = createNewPessimisticLock(document, getWorkflowPessimisticLockOwnerUser()); 404 document.addPessimisticLock(lock); 405 } 406 407 /** 408 * This method releases locks created via the {@link #establishWorkflowPessimisticLocking(Document)} method for the given document 409 * 410 * @param document - document to release locks from 411 * @see org.kuali.rice.kns.document.authorization.DocumentAuthorizer#releaseWorkflowPessimisticLocking(org.kuali.rice.krad.document.Document) 412 */ 413 @Override 414 public void releaseWorkflowPessimisticLocking(Document document) { 415 releaseAllLocksForUser(document.getPessimisticLocks(), getWorkflowPessimisticLockOwnerUser()); 416 document.refreshPessimisticLocks(); 417 } 418 419 /** 420 * This method identifies the user that should be used to create and clear {@link PessimisticLock} objects required by 421 * Workflow.<br> 422 * <br> 423 * The default is the Kuali system user defined by {@link RiceConstants#SYSTEM_USER}. This method can be overriden by 424 * implementing documents if another user is needed. 425 * 426 * @return a valid {@link Person} object 427 */ 428 protected Person getWorkflowPessimisticLockOwnerUser() { 429 String networkId = KRADConstants.SYSTEM_USER; 430 return getPersonService().getPersonByPrincipalName(networkId); 431 } 432 433 /** 434 * {@inheritDoc} 435 * 436 * This implementation will check the given document, editMode map, and user object to verify Pessimistic Locking. If the 437 * given edit mode map contains an 'entry type' edit mode then the system will check the locks already in existence on 438 * the document. If a valid lock for the given user is found the system will return the given edit mode map. If a valid 439 * lock is found but is owned by another user the edit mode map returned will have any 'entry type' edit modes removed. If the 440 * given document has no locks and the edit mode map passed in has at least one 'entry type' mode then a new 441 * {@link PessimisticLock} object will be created and set on the document for the given user.<br> 442 * <br> 443 * NOTE: This method is only called if the document uses pessimistic locking as described in the data dictionary file. 444 * 445 * @see org.kuali.rice.kns.document.authorization.DocumentAuthorizer#establishLocks(org.kuali.rice.krad.document.Document, 446 * java.util.Map, org.kuali.rice.kim.api.identity.Person) 447 */ 448 @Override 449 @Deprecated 450 public Map establishLocks(Document document, Map editMode, Person user) { 451 Map editModeMap = new HashMap(); 452 // givenUserLockDescriptors is a list of lock descriptors currently held on the document by the given user 453 List<String> givenUserLockDescriptors = new ArrayList<String>(); 454 // lockDescriptorUsers is a map with lock descriptors as keys and users other than the given user who hold a lock of each descriptor 455 Map<String,Set<Person>> lockDescriptorUsers = new HashMap<String,Set<Person>>(); 456 457 // build the givenUserLockDescriptors set and the lockDescriptorUsers map 458 for (PessimisticLock lock : document.getPessimisticLocks()) { 459 if (lock.isOwnedByUser(user)) { 460 // lock is owned by given user 461 givenUserLockDescriptors.add(lock.getLockDescriptor()); 462 } else { 463 // lock is not owned by the given user 464 if (!lockDescriptorUsers.containsKey(lock.getLockDescriptor())) { 465 lockDescriptorUsers.put(lock.getLockDescriptor(), new HashSet<Person>()); 466 } 467 lockDescriptorUsers.get(lock.getLockDescriptor()).add(lock.getOwnedByUser()); 468 } 469 } 470 471 // verify that no locks held by current user exist for any other user 472 for (String givenUserLockDescriptor : givenUserLockDescriptors) { 473 if ( (lockDescriptorUsers.containsKey(givenUserLockDescriptor)) && (lockDescriptorUsers.get(givenUserLockDescriptor).size() > 0) ) { 474 Set<Person> users = lockDescriptorUsers.get(givenUserLockDescriptor); 475 if ( (users.size() != 1) || (!getWorkflowPessimisticLockOwnerUser().getPrincipalId().equals(users.iterator().next().getPrincipalId())) ) { 476 String descriptorText = (document.useCustomLockDescriptors()) ? " using lock descriptor '" + givenUserLockDescriptor + "'" : ""; 477 String errorMsg = "Found an invalid lock status on document number " + document.getDocumentNumber() + "with current user and other user both having locks" + descriptorText + " concurrently"; 478 LOG.debug(errorMsg); 479 throw new PessimisticLockingException(errorMsg); 480 } 481 } 482 } 483 484 // check to see if the given user has any locks in the system at all 485 if (givenUserLockDescriptors.isEmpty()) { 486 // given user has no locks... check for other user locks 487 if (lockDescriptorUsers.isEmpty()) { 488 // no other user has any locks... set up locks for given user if user has edit privileges 489 if (isLockRequiredByUser(document, editMode, user)) { 490 document.addPessimisticLock(createNewPessimisticLock(document, editMode, user)); 491 } 492 editModeMap.putAll(editMode); 493 } else { 494 // at least one other user has at least one other lock... adjust edit mode for read only 495 if (document.useCustomLockDescriptors()) { 496 // check to see if the custom lock descriptor is already in use 497 String customLockDescriptor = document.getCustomLockDescriptor(user); 498 if (lockDescriptorUsers.containsKey(customLockDescriptor)) { 499 // at least one other user has this descriptor locked... remove editable edit modes 500 editModeMap = getEditModeWithEditableModesRemoved(editMode); 501 } else { 502 // no other user has a lock with this descriptor 503 if (isLockRequiredByUser(document, editMode, user)) { 504 document.addPessimisticLock(createNewPessimisticLock(document, editMode, user)); 505 } 506 editModeMap.putAll(editMode); 507 } 508 } else { 509 editModeMap = getEditModeWithEditableModesRemoved(editMode); 510 } 511 } 512 } else { 513 // given user already has at least one lock descriptor 514 if (document.useCustomLockDescriptors()) { 515 // get the custom lock descriptor and check to see if if the given user has a lock with that descriptor 516 String customLockDescriptor = document.getCustomLockDescriptor(user); 517 if (givenUserLockDescriptors.contains(customLockDescriptor)) { 518 // user already has lock that is required 519 editModeMap.putAll(editMode); 520 } else { 521 // user does not have lock for descriptor required 522 if (lockDescriptorUsers.containsKey(customLockDescriptor)) { 523 // another user has the lock descriptor that the given user requires... disallow lock and alter edit modes to have read only 524 editModeMap = getEditModeWithEditableModesRemoved(editMode); 525 } else { 526 // no other user has a lock with this descriptor... check if this user needs a lock 527 if (isLockRequiredByUser(document, editMode, user)) { 528 document.addPessimisticLock(createNewPessimisticLock(document, editMode, user)); 529 } 530 editModeMap.putAll(editMode); 531 } 532 } 533 } else { 534 // user already has lock and no descriptors are being used... use the existing edit modes 535 editModeMap.putAll(editMode); 536 } 537 } 538 539 return editModeMap; 540 } 541 542 /** 543 * This method is used to check if the given parameters warrant a new lock to be created for the given user. This method 544 * utilizes the {@link #isEntryEditMode(java.util.Map.Entry)} method. 545 * 546 * @param document - 547 * document to verify lock creation against 548 * @param editMode - 549 * edit modes list to check for 'entry type' edit modes 550 * @param user - 551 * user the lock will be 'owned' by 552 * @return true if the given edit mode map has at least one 'entry type' edit mode... false otherwise 553 */ 554 @Deprecated 555 protected boolean isLockRequiredByUser(Document document, Map editMode, Person user) { 556 // check for entry edit mode 557 for (Iterator iterator = editMode.entrySet().iterator(); iterator.hasNext();) { 558 Map.Entry entry = (Map.Entry) iterator.next(); 559 if (isEntryEditMode(entry)) { 560 return true; 561 } 562 } 563 return false; 564 } 565 566 /** 567 * This method is used to remove edit modes from the given map that allow the user to edit data on the document. This 568 * method utilizes the {@link #isEntryEditMode(java.util.Map.Entry)} method to identify if an edit mode is defined as an 569 * 'entry type' edit mode. It also uses the {@link #getEntryEditModeReplacementMode(java.util.Map.Entry)} method to replace 570 * any 'entry type' edit modes it finds. 571 * 572 * @param currentEditMode - 573 * current set of edit modes the user has assigned to them 574 * @return an adjusted edit mode map where 'entry type' edit modes have been removed or replaced using the 575 * {@link #getEntryEditModeReplacementMode} method 576 */ 577 @Deprecated 578 protected Map getEditModeWithEditableModesRemoved(Map currentEditMode) { 579 Map editModeMap = new HashMap(); 580 for (Iterator iterator = currentEditMode.entrySet().iterator(); iterator.hasNext();) { 581 Map.Entry entry = (Map.Entry) iterator.next(); 582 if (isEntryEditMode(entry)) { 583 editModeMap.putAll(getEntryEditModeReplacementMode(entry)); 584 } else { 585 editModeMap.put(entry.getKey(), entry.getValue()); 586 } 587 } 588 return editModeMap; 589 } 590 591 /** 592 * This method is used to check if the given {@link Map.Entry} is an 'entry type' edit mode and that the value is set to 593 * signify that this user has that edit mode available to them 594 * 595 * @param entry - 596 * the {@link Map.Entry} object that contains an edit mode such as the ones returned but 597 * {@link #getEditMode(Document, Person)} 598 * @return true if the given entry has a key signifying an 'entry type' edit mode and the value is equal to 599 * {@link #EDIT_MODE_DEFAULT_TRUE_VALUE}... false if not 600 */ 601 @Deprecated 602 protected boolean isEntryEditMode(Map.Entry entry) { 603 // check for FULL_ENTRY edit mode set to default true value 604 if (AuthorizationConstants.EditMode.FULL_ENTRY.equals(entry.getKey())) { 605 String fullEntryEditModeValue = (String)entry.getValue(); 606 return ( StringUtils.equalsIgnoreCase(KRADConstants.KUALI_DEFAULT_TRUE_VALUE, fullEntryEditModeValue) ); 607 } 608 return false; 609 } 610 611 /** 612 * This method is used to return values needed to replace the given 'entry type' edit mode {@link Map.Entry} with one that will not allow the user to enter data on the document 613 * 614 * @param entry - the current 'entry type' edit mode to replace 615 * @return a Map of edit modes that will be used to replace this edit mode (represented by the given entry parameter) 616 */ 617 protected Map getEntryEditModeReplacementMode(Map.Entry entry) { 618 Map editMode = new HashMap(); 619 editMode.put(AuthorizationConstants.EditMode.VIEW_ONLY, KRADConstants.KUALI_DEFAULT_TRUE_VALUE); 620 return editMode; 621 } 622 623 /** 624 * This method creates a new {@link PessimisticLock} object using the given document and user. If the document's 625 * useCustomLockDescriptors() method returns true then the new lock will also have a custom lock descriptor 626 * value set to the return value of the document's getCustomLockDescriptor(Person) method. 627 * 628 * @param document - 629 * document to place the lock on 630 * @param editMode - 631 * current edit modes for given user 632 * @param user - 633 * user who will 'own' the new lock object 634 * @return the newly created lock object 635 */ 636 @Deprecated 637 protected PessimisticLock createNewPessimisticLock(Document document, Map editMode, Person user) { 638 if (document.useCustomLockDescriptors()) { 639 return generateNewLock(document.getDocumentNumber(), document.getCustomLockDescriptor(user), user); 640 } else { 641 return generateNewLock(document.getDocumentNumber(), user); 642 } 643 } 644 645 public PersonService getPersonService() { 646 if ( personService == null ) { 647 personService = KimApiServiceLocator.getPersonService(); 648 } 649 return personService; 650 } 651 652 public DataDictionaryService getDataDictionaryService() { 653 return dataDictionaryService; 654 } 655 656 @Required 657 public void setDataDictionaryService(DataDictionaryService dataDictionaryService) { 658 this.dataDictionaryService = dataDictionaryService; 659 } 660 661 public PermissionService getPermissionService() { 662 if ( permissionService == null ) { 663 permissionService = KimApiServiceLocator.getPermissionService(); 664 } 665 return permissionService; 666 } 667 668 669 @Required 670 public void setDataObjectService(DataObjectService dataObjectService) { 671 this.dataObjectService = dataObjectService; 672 } 673} 674