Coverage Report - org.kuali.rice.krad.util.MaintenanceUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
MaintenanceUtils
0%
0/216
0%
0/128
4.56
 
 1  
 /*
 2  
  * Copyright 2006-2011 The Kuali Foundation
 3  
  *
 4  
  * Licensed under the Educational Community License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  * http://www.opensource.org/licenses/ecl2.php
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 
 17  
 package org.kuali.rice.krad.util;
 18  
 
 19  
 import java.util.Collection;
 20  
 import java.util.HashMap;
 21  
 import java.util.HashSet;
 22  
 import java.util.Iterator;
 23  
 import java.util.List;
 24  
 import java.util.Map;
 25  
 import java.util.Properties;
 26  
 import java.util.Set;
 27  
 import java.util.StringTokenizer;
 28  
 
 29  
 import org.apache.commons.lang.StringUtils;
 30  
 import org.kuali.rice.core.api.config.property.ConfigurationService;
 31  
 import org.kuali.rice.core.util.RiceKeyConstants;
 32  
 import org.kuali.rice.kew.api.WorkflowDocument;
 33  
 import org.kuali.rice.kew.exception.WorkflowException;
 34  
 import org.kuali.rice.krad.bo.BusinessObject;
 35  
 import org.kuali.rice.krad.datadictionary.AttributeSecurity;
 36  
 import org.kuali.rice.krad.datadictionary.MaintainableCollectionDefinition;
 37  
 import org.kuali.rice.krad.datadictionary.MaintainableFieldDefinition;
 38  
 import org.kuali.rice.krad.datadictionary.MaintainableItemDefinition;
 39  
 import org.kuali.rice.krad.datadictionary.MaintainableSectionDefinition;
 40  
 import org.kuali.rice.krad.datadictionary.MaintenanceDocumentEntry;
 41  
 import org.kuali.rice.krad.document.MaintenanceDocument;
 42  
 import org.kuali.rice.krad.exception.KualiExceptionIncident;
 43  
 import org.kuali.rice.krad.exception.ValidationException;
 44  
 import org.kuali.rice.krad.lookup.LookupUtils;
 45  
 import org.kuali.rice.krad.lookup.SelectiveReferenceRefresher;
 46  
 import org.kuali.rice.krad.maintenance.Maintainable;
 47  
 import org.kuali.rice.krad.service.DataDictionaryService;
 48  
 import org.kuali.rice.krad.service.KRADServiceLocator;
 49  
 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
 50  
 import org.kuali.rice.krad.service.KualiExceptionIncidentService;
 51  
 import org.kuali.rice.krad.service.MaintenanceDocumentDictionaryService;
 52  
 import org.kuali.rice.krad.service.MaintenanceDocumentService;
 53  
 import org.kuali.rice.krad.web.ui.Field;
 54  
 import org.kuali.rice.krad.web.ui.Row;
 55  
 import org.kuali.rice.krad.web.ui.Section;
 56  
 import org.kuali.rice.krad.workflow.service.WorkflowDocumentService;
 57  
 
 58  
 public final class MaintenanceUtils {
 59  0
     private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(MaintenanceUtils.class);
 60  
 
 61  
     private static MaintenanceDocumentService maintenanceDocumentService;
 62  
     private static WorkflowDocumentService workflowDocumentService;
 63  
     private static ConfigurationService kualiConfigurationService;
 64  
     private static KualiExceptionIncidentService kualiExceptionIncidentService;
 65  
     private static MaintenanceDocumentDictionaryService maintenanceDocumentDictionaryService;
 66  
     private static DataDictionaryService dataDictionaryService;
 67  
 
 68  0
     private MaintenanceUtils() {
 69  0
         throw new UnsupportedOperationException("do not call");
 70  
     }
 71  
 
 72  
     /**
 73  
      * Returns the field templates defined in the maint dictionary xml files. Field templates are used in multiple value lookups.
 74  
      * When doing a MV lookup on a collection, the returned BOs are not necessarily of the same type as the elements of the
 75  
      * collection. Therefore, a means of mapping between the fields for the 2 BOs are necessary. The template attribute of
 76  
      * <maintainableField>s contained within <maintainableCollection>s tells us this mapping. Example: a
 77  
      * <maintainableField name="collectionAttrib" template="lookupBOAttrib"> definition means that when a list of BOs are
 78  
      * returned, the lookupBOAttrib value of the looked up BO will be placed into the collectionAttrib value of the BO added to the
 79  
      * collection
 80  
      *
 81  
      * @param sections       the sections of a document
 82  
      * @param collectionName the name of a collection. May be a nested collection with indices (e.g. collA[1].collB)
 83  
      * @return
 84  
      */
 85  
     public static Map<String, String> generateMultipleValueLookupBOTemplate(List<MaintainableSectionDefinition> sections, String collectionName) {
 86  0
         MaintainableCollectionDefinition definition = findMaintainableCollectionDefinition(sections, collectionName);
 87  0
         if (definition == null) {
 88  0
             return null;
 89  
         }
 90  0
         Map<String, String> template = null;
 91  
 
 92  0
         for (MaintainableFieldDefinition maintainableField : definition.getMaintainableFields()) {
 93  0
             String templateString = maintainableField.getTemplate();
 94  0
             if (StringUtils.isNotBlank(templateString)) {
 95  0
                 if (template == null) {
 96  0
                     template = new HashMap<String, String>();
 97  
                 }
 98  0
                 template.put(maintainableField.getName(), templateString);
 99  
             }
 100  0
         }
 101  0
         return template;
 102  
     }
 103  
 
 104  
     /**
 105  
      * Finds the MaintainableCollectionDefinition corresponding to the given collection name. For example, if the collection name is
 106  
      * "A.B.C", it will attempt to find the MaintainableCollectionDefinition for C that is nested in B that is nested under A. This
 107  
      * may not work correctly if there are duplicate collection definitions within the sections
 108  
      *
 109  
      * @param sections       the sections of a maint doc
 110  
      * @param collectionName the name of a collection, relative to the root of the BO being maintained. This value may have index
 111  
      *                       values (e.g. [1]), but these are ignored.
 112  
      * @return
 113  
      */
 114  
     public static MaintainableCollectionDefinition findMaintainableCollectionDefinition(List<MaintainableSectionDefinition> sections, String collectionName) {
 115  0
         String[] collectionNameParts = StringUtils.split(collectionName, ".");
 116  0
         for (MaintainableSectionDefinition section : sections) {
 117  0
             MaintainableCollectionDefinition collDefinition = findMaintainableCollectionDefinitionHelper(section.getMaintainableItems(), collectionNameParts, 0);
 118  0
             if (collDefinition != null) {
 119  0
                 return collDefinition;
 120  
             }
 121  0
         }
 122  0
         return null;
 123  
     }
 124  
 
 125  
     private static <E extends MaintainableItemDefinition> MaintainableCollectionDefinition findMaintainableCollectionDefinitionHelper(Collection<E> items, String[] collectionNameParts, int collectionNameIndex) {
 126  0
         if (collectionNameParts.length <= collectionNameIndex) {
 127  
             // we've gone too far down the nesting without finding it
 128  0
             return null;
 129  
         }
 130  
 
 131  
         // we only care about the coll name, and not the index, since the coll definitions do not include the indexing characters,
 132  
         // i.e. [ and ]
 133  0
         String collectionToFind = StringUtils.substringBefore(collectionNameParts[collectionNameIndex], "[");
 134  0
         for (MaintainableItemDefinition item : items) {
 135  0
             if (item instanceof MaintainableCollectionDefinition) {
 136  0
                 MaintainableCollectionDefinition collection = (MaintainableCollectionDefinition) item;
 137  0
                 if (collection.getName().equals(collectionToFind)) {
 138  
                     // we found an appropriate coll, now we have to see if we need to recurse even more (more nested collections),
 139  
                     // or just return the one we found.
 140  0
                     if (collectionNameIndex == collectionNameParts.length - 1) {
 141  
                         // we're at the last part of the name, so we return
 142  0
                         return collection;
 143  
                     } else {
 144  
                         // go deeper
 145  0
                         return findMaintainableCollectionDefinitionHelper(collection.getMaintainableCollections(), collectionNameParts, collectionNameIndex + 1);
 146  
                     }
 147  
                 }
 148  0
             }
 149  
         }
 150  0
         return null;
 151  
     }
 152  
 
 153  
     /**
 154  
      * Checks to see if there has been an override lookup declared for the maintenance field. If so, the override will be used for
 155  
      * the quickfinder and lookup utils will not be called. If no override was given, LookupUtils.setFieldQuickfinder will be called
 156  
      * to set the system generated quickfinder based on the attributes relationship to the parent business object.
 157  
      *
 158  
      * @return Field with quickfinder set if one was found
 159  
      */
 160  
     public static final Field setFieldQuickfinder(BusinessObject businessObject, String attributeName, MaintainableFieldDefinition maintainableFieldDefinition, Field field, List<String> displayedFieldNames, SelectiveReferenceRefresher srr) {
 161  0
         if (maintainableFieldDefinition.getOverrideLookupClass() != null && StringUtils.isNotBlank(maintainableFieldDefinition.getOverrideFieldConversions())) {
 162  0
             field.setQuickFinderClassNameImpl(maintainableFieldDefinition.getOverrideLookupClass().getName());
 163  0
             field.setFieldConversions(maintainableFieldDefinition.getOverrideFieldConversions());
 164  0
             field.setBaseLookupUrl(LookupUtils.getBaseLookupUrl(false));
 165  0
             field.setReferencesToRefresh(LookupUtils.convertReferencesToSelectCollectionToString(
 166  
                     srr.getAffectedReferencesFromLookup(businessObject, attributeName, "")));
 167  0
             return field;
 168  
         }
 169  0
         if (maintainableFieldDefinition.isNoLookup()) {
 170  0
             return field;
 171  
         }
 172  0
         return LookupUtils.setFieldQuickfinder(businessObject, null, false, 0, attributeName, field, displayedFieldNames, maintainableFieldDefinition.isNoLookup());
 173  
     }
 174  
 
 175  
     public static final Field setFieldQuickfinder(BusinessObject businessObject, String collectionName, boolean addLine, int index,
 176  
                                                   String attributeName, Field field, List<String> displayedFieldNames, Maintainable maintainable, MaintainableFieldDefinition maintainableFieldDefinition) {
 177  0
         if (maintainableFieldDefinition.getOverrideLookupClass() != null && StringUtils.isNotBlank(maintainableFieldDefinition.getOverrideFieldConversions())) {
 178  0
             if (maintainable != null) {
 179  0
                 String collectionPrefix = "";
 180  0
                 if (collectionName != null) {
 181  0
                     if (addLine) {
 182  0
                         collectionPrefix = KRADConstants.MAINTENANCE_ADD_PREFIX + collectionName + ".";
 183  
                     } else {
 184  0
                         collectionPrefix = collectionName + "[" + index + "].";
 185  
                     }
 186  
                 }
 187  0
                 field.setQuickFinderClassNameImpl(maintainableFieldDefinition.getOverrideLookupClass().getName());
 188  
 
 189  0
                 String prefixedFieldConversions = prefixFieldConversionsDestinationsWithCollectionPrefix(maintainableFieldDefinition.getOverrideFieldConversions(), collectionPrefix);
 190  0
                 field.setFieldConversions(prefixedFieldConversions);
 191  0
                 field.setBaseLookupUrl(LookupUtils.getBaseLookupUrl(false));
 192  0
                 field.setReferencesToRefresh(LookupUtils.convertReferencesToSelectCollectionToString(
 193  
                         maintainable.getAffectedReferencesFromLookup(businessObject, attributeName, collectionPrefix)));
 194  
             }
 195  0
             return field;
 196  
         }
 197  0
         if (maintainableFieldDefinition.isNoLookup()) {
 198  0
             return field;
 199  
         }
 200  0
         return LookupUtils.setFieldQuickfinder(businessObject, collectionName, addLine, index,
 201  
                 attributeName, field, displayedFieldNames, maintainable);
 202  
     }
 203  
 
 204  
     private static String prefixFieldConversionsDestinationsWithCollectionPrefix(String originalFieldConversions, String collectionPrefix) {
 205  0
         StringBuilder buf = new StringBuilder();
 206  0
         StringTokenizer tok = new StringTokenizer(originalFieldConversions, KRADConstants.FIELD_CONVERSIONS_SEPARATOR);
 207  0
         boolean needsSeparator = false;
 208  0
         while (tok.hasMoreTokens()) {
 209  0
             String conversionPair = tok.nextToken();
 210  0
             if (StringUtils.isBlank(conversionPair)) {
 211  0
                 continue;
 212  
             }
 213  
 
 214  0
             String fromValue = StringUtils.substringBefore(conversionPair, KRADConstants.FIELD_CONVERSION_PAIR_SEPARATOR);
 215  0
             String toValue = StringUtils.substringAfter(conversionPair, KRADConstants.FIELD_CONVERSION_PAIR_SEPARATOR);
 216  
 
 217  0
             if (needsSeparator) {
 218  0
                 buf.append(KRADConstants.FIELD_CONVERSIONS_SEPARATOR);
 219  
             }
 220  0
             needsSeparator = true;
 221  
 
 222  0
             buf.append(fromValue).append(KRADConstants.FIELD_CONVERSION_PAIR_SEPARATOR).append(collectionPrefix).append(toValue);
 223  0
         }
 224  0
         return buf.toString();
 225  
     }
 226  
 
 227  
     public static final void setFieldDirectInquiry(BusinessObject businessObject, String attributeName, MaintainableFieldDefinition maintainableFieldDefinition, Field field, List<String> displayedFieldNames) {
 228  0
         LookupUtils.setFieldDirectInquiry(businessObject, attributeName, field);
 229  0
     }
 230  
 
 231  
     public static final void setFieldDirectInquiry(BusinessObject businessObject, String collectionName, boolean addLine, int index,
 232  
                                                    String attributeName, Field field, List<String> displayedFieldNames, Maintainable maintainable, MaintainableFieldDefinition maintainableFieldDefinition) {
 233  0
         LookupUtils.setFieldDirectInquiry(businessObject, attributeName, field);
 234  0
     }
 235  
 
 236  
     /**
 237  
      * Given a section, returns a comma delimited string of all fields, representing the error keys that exist for a section
 238  
      *
 239  
      * @param section a section
 240  
      * @return
 241  
      */
 242  
     public static String generateErrorKeyForSection(Section section) {
 243  0
         Set<String> fieldPropertyNames = new HashSet<String>();
 244  0
         addRowsToErrorKeySet(section.getRows(), fieldPropertyNames);
 245  
 
 246  0
         StringBuilder buf = new StringBuilder();
 247  0
         buf.append(section.getSectionId()).append(",");
 248  
 
 249  0
         Iterator<String> nameIter = fieldPropertyNames.iterator();
 250  0
         while (nameIter.hasNext()) {
 251  0
             buf.append(nameIter.next());
 252  0
             if (nameIter.hasNext()) {
 253  0
                 buf.append(",");
 254  
             }
 255  
         }
 256  
 
 257  0
         if (section.getContainedCollectionNames() != null && section.getContainedCollectionNames().size() > 0) {
 258  0
             buf.append(",");
 259  
 
 260  0
             Iterator<String> collectionIter = section.getContainedCollectionNames().iterator();
 261  0
             while (collectionIter.hasNext()) {
 262  0
                 buf.append(KRADConstants.MAINTENANCE_NEW_MAINTAINABLE + collectionIter.next());
 263  0
                 if (collectionIter.hasNext()) {
 264  0
                     buf.append(",");
 265  
                 }
 266  
             }
 267  
         }
 268  
 
 269  0
         return buf.toString();
 270  
     }
 271  
 
 272  
     /**
 273  
      * This method recurses through all the fields of the list of rows and adds each field's property name to the set if it starts
 274  
      * with Constants.MAINTENANCE_NEW_MAINTAINABLE
 275  
      *
 276  
      * @param listOfRows
 277  
      * @param errorKeys
 278  
      * @see KRADConstants#MAINTENANCE_NEW_MAINTAINABLE
 279  
      */
 280  
     protected static void addRowsToErrorKeySet(List<Row> listOfRows, Set<String> errorKeys) {
 281  0
         if (listOfRows == null) {
 282  0
             return;
 283  
         }
 284  0
         for (Row row : listOfRows) {
 285  0
             List<Field> fields = row.getFields();
 286  0
             if (fields == null) {
 287  0
                 continue;
 288  
             }
 289  0
             for (Field field : fields) {
 290  0
                 String fieldPropertyName = field.getPropertyName();
 291  0
                 if (fieldPropertyName != null && fieldPropertyName.startsWith(KRADConstants.MAINTENANCE_NEW_MAINTAINABLE)) {
 292  0
                     errorKeys.add(field.getPropertyName());
 293  
                 }
 294  0
                 addRowsToErrorKeySet(field.getContainerRows(), errorKeys);
 295  0
             }
 296  0
         }
 297  0
     }
 298  
 
 299  
     public static boolean isMaintenanceDocumentCreatingNewRecord(String maintenanceAction) {
 300  0
         if (KRADConstants.MAINTENANCE_EDIT_ACTION.equalsIgnoreCase(maintenanceAction)) {
 301  0
             return false;
 302  0
         } else if (KRADConstants.MAINTENANCE_NEWWITHEXISTING_ACTION.equalsIgnoreCase(maintenanceAction)) {
 303  0
             return false;
 304  0
         } else if (KRADConstants.MAINTENANCE_DELETE_ACTION.equalsIgnoreCase(maintenanceAction)) {
 305  0
             return false;
 306  0
         } else if (KRADConstants.MAINTENANCE_NEW_ACTION.equalsIgnoreCase(maintenanceAction)) {
 307  0
             return true;
 308  0
         } else if (KRADConstants.MAINTENANCE_COPY_ACTION.equalsIgnoreCase(maintenanceAction)) {
 309  0
             return true;
 310  
         } else {
 311  0
             return true;
 312  
         }
 313  
     }
 314  
 
 315  
     /**
 316  
      * This method will throw a {@link ValidationException} if there is a valid locking document in existence and throwExceptionIfLocked is true.
 317  
      */
 318  
     public static void checkForLockingDocument(MaintenanceDocument document, boolean throwExceptionIfLocked) {
 319  0
         LOG.info("starting checkForLockingDocument (by MaintenanceDocument)");
 320  
 
 321  
         // get the docHeaderId of the blocking docs, if any are locked and blocking
 322  
         //String blockingDocId = getMaintenanceDocumentService().getLockingDocumentId(document);
 323  0
         String blockingDocId = document.getNewMaintainableObject().getLockingDocumentId();
 324  0
         checkDocumentBlockingDocumentId(blockingDocId, throwExceptionIfLocked);
 325  0
     }
 326  
 
 327  
     /**
 328  
      * This method will throw a {@link ValidationException} if there is a valid locking document in existence and throwExceptionIfLocked is true.
 329  
      */
 330  
     public static void checkForLockingDocument(Maintainable maintainable, boolean throwExceptionIfLocked) {
 331  0
         LOG.info("starting checkForLockingDocument (by Maintainable)");
 332  
 
 333  
         // get the docHeaderId of the blocking docs, if any are locked and blocking
 334  
         //String blockingDocId = getMaintenanceDocumentService().getLockingDocumentId(maintainable, null);
 335  0
         String blockingDocId = maintainable.getLockingDocumentId();
 336  0
         checkDocumentBlockingDocumentId(blockingDocId, throwExceptionIfLocked);
 337  0
     }
 338  
 
 339  
     private static void checkDocumentBlockingDocumentId(String blockingDocId, boolean throwExceptionIfLocked) {
 340  
         // if we got nothing, then no docs are blocking, and we're done
 341  0
         if (StringUtils.isBlank(blockingDocId)) {
 342  0
             return;
 343  
         }
 344  
 
 345  0
         if (LOG.isInfoEnabled()) {
 346  0
             LOG.info("Locking document found:  docId = " + blockingDocId + ".");
 347  
         }
 348  
 
 349  
         // load the blocking locked document
 350  0
         WorkflowDocument lockedDocument = null;
 351  
         try {
 352  
             // need to perform this check to prevent an exception from being thrown by the
 353  
             // createWorkflowDocument call - the throw itself causes transaction rollback problems to
 354  
             // occur, even though the exception would be caught here
 355  0
             if (getWorkflowDocumentService().workflowDocumentExists(blockingDocId)) {
 356  0
                 lockedDocument = getWorkflowDocumentService().loadWorkflowDocument(blockingDocId, GlobalVariables.getUserSession().getPerson());
 357  
             }
 358  0
         } catch (Exception ex) {
 359  
             // clean up the lock and notify the admins
 360  0
             LOG.error("Unable to retrieve locking document specified in the maintenance lock table: " + blockingDocId, ex);
 361  
 
 362  0
             cleanOrphanLocks(blockingDocId, ex);
 363  0
             return;
 364  0
         }
 365  0
         if (lockedDocument == null) {
 366  0
             LOG.warn("Locking document header for " + blockingDocId + "came back null.");
 367  0
             cleanOrphanLocks(blockingDocId, null);
 368  
         }
 369  
 
 370  
         // if we can ignore the lock (see method notes), then exit cause we're done
 371  0
         if (lockCanBeIgnored(lockedDocument)) {
 372  0
             return;
 373  
         }
 374  
 
 375  
         // build the link URL for the blocking document
 376  0
         Properties parameters = new Properties();
 377  0
         parameters.put(KRADConstants.PARAMETER_DOC_ID, blockingDocId);
 378  0
         parameters.put(KRADConstants.PARAMETER_COMMAND, KRADConstants.METHOD_DISPLAY_DOC_SEARCH_VIEW);
 379  0
         String blockingUrl = UrlFactory.parameterizeUrl(getKualiConfigurationService().getPropertyString(KRADConstants.WORKFLOW_URL_KEY) + "/" + KRADConstants.DOC_HANDLER_ACTION, parameters);
 380  0
         if (LOG.isDebugEnabled()) {
 381  0
             LOG.debug("blockingUrl = '" + blockingUrl + "'");
 382  0
             LOG.debug("Maintenance record: " + lockedDocument.getApplicationDocumentId() + "is locked.");
 383  
         }
 384  0
         String[] errorParameters = {blockingUrl, blockingDocId};
 385  
 
 386  
         // If specified, add an error to the ErrorMap and throw an exception; otherwise, just add a warning to the ErrorMap instead.
 387  0
         if (throwExceptionIfLocked) {
 388  
             // post an error about the locked document
 389  0
             GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_ERRORS, RiceKeyConstants.ERROR_MAINTENANCE_LOCKED, errorParameters);
 390  0
             throw new ValidationException("Maintenance Record is locked by another document.");
 391  
         } else {
 392  
             // Post a warning about the locked document.
 393  0
             GlobalVariables.getMessageMap().putWarning(KRADConstants.GLOBAL_MESSAGES, RiceKeyConstants.WARNING_MAINTENANCE_LOCKED, errorParameters);
 394  
         }
 395  0
     }
 396  
 
 397  
     /**
 398  
      * This method guesses whether the current user should be allowed to change a document even though it is locked. It probably
 399  
      * should use Authorization instead? See KULNRVSYS-948
 400  
      *
 401  
      * @param lockedDocument
 402  
      * @return
 403  
      * @throws WorkflowException
 404  
      */
 405  
     private static boolean lockCanBeIgnored(WorkflowDocument lockedDocument) {
 406  
         // TODO: implement real authorization for Maintenance Document Save/Route - KULNRVSYS-948
 407  0
         if (lockedDocument == null) {
 408  0
             return true;
 409  
         }
 410  
 
 411  
         // get the user-id. if no user-id, then we can do this test, so exit
 412  0
         String userId = GlobalVariables.getUserSession().getPrincipalId().trim();
 413  0
         if (StringUtils.isBlank(userId)) {
 414  0
             return false; // dont bypass locking
 415  
         }
 416  
 
 417  
         // if the current user is not the initiator of the blocking document
 418  0
         if (!userId.equalsIgnoreCase(lockedDocument.getInitiatorPrincipalId().trim())) {
 419  0
             return false;
 420  
         }
 421  
 
 422  
         // if the blocking document hasn't been routed, we can ignore it
 423  0
         return lockedDocument.isInitiated();
 424  
     }
 425  
 
 426  
     private static void cleanOrphanLocks(String lockingDocumentNumber, Exception workflowException) {
 427  
         // put a try/catch around the whole thing - the whole reason we are doing this is to prevent data errors
 428  
         // from stopping a document
 429  
         try {
 430  
             // delete the locks for this document since it does not seem to exist
 431  0
             getMaintenanceDocumentService().deleteLocks(lockingDocumentNumber);
 432  
             // notify the incident list
 433  0
             Map<String, String> parameters = new HashMap<String, String>(1);
 434  0
             parameters.put(KRADConstants.PARAMETER_DOC_ID, lockingDocumentNumber);
 435  0
             KualiExceptionIncident kei = getKualiExceptionIncidentService().getExceptionIncident(workflowException, parameters);
 436  0
             getKualiExceptionIncidentService().report(kei);
 437  0
         } catch (Exception ex) {
 438  0
             LOG.error("Unable to delete and notify upon locking document retrieval failure.", ex);
 439  0
         }
 440  0
     }
 441  
 
 442  
     private static MaintenanceDocumentService getMaintenanceDocumentService() {
 443  0
         if (maintenanceDocumentService == null) {
 444  0
             maintenanceDocumentService = KRADServiceLocatorWeb.getMaintenanceDocumentService();
 445  
         }
 446  0
         return maintenanceDocumentService;
 447  
     }
 448  
 
 449  
     private static WorkflowDocumentService getWorkflowDocumentService() {
 450  0
         if (workflowDocumentService == null) {
 451  0
             workflowDocumentService = KRADServiceLocatorWeb.getWorkflowDocumentService();
 452  
         }
 453  0
         return workflowDocumentService;
 454  
     }
 455  
 
 456  
     private static ConfigurationService getKualiConfigurationService() {
 457  0
         if (kualiConfigurationService == null) {
 458  0
             kualiConfigurationService = KRADServiceLocator.getKualiConfigurationService();
 459  
         }
 460  0
         return kualiConfigurationService;
 461  
     }
 462  
 
 463  
     private static KualiExceptionIncidentService getKualiExceptionIncidentService() {
 464  0
         if (kualiExceptionIncidentService == null) {
 465  0
             kualiExceptionIncidentService = KRADServiceLocatorWeb.getKualiExceptionIncidentService();
 466  
         }
 467  0
         return kualiExceptionIncidentService;
 468  
     }
 469  
 
 470  
     private static MaintenanceDocumentDictionaryService getMaintenanceDocumentDictionaryService() {
 471  0
         if (maintenanceDocumentDictionaryService == null) {
 472  0
             maintenanceDocumentDictionaryService = KRADServiceLocatorWeb.getMaintenanceDocumentDictionaryService();
 473  
         }
 474  0
         return maintenanceDocumentDictionaryService;
 475  
     }
 476  
 
 477  
     private static DataDictionaryService getDataDictionaryService() {
 478  0
         if (dataDictionaryService == null) {
 479  0
             dataDictionaryService = KRADServiceLocatorWeb.getDataDictionaryService();
 480  
         }
 481  0
         return dataDictionaryService;
 482  
     }
 483  
 
 484  
     public static Map<String, AttributeSecurity> retrievePropertyPathToAttributeSecurityMappings(String docTypeName) {
 485  0
         Map<String, AttributeSecurity> results = new HashMap<String, AttributeSecurity>();
 486  0
         MaintenanceDocumentEntry entry = getMaintenanceDocumentDictionaryService().getMaintenanceDocumentEntry(docTypeName);
 487  0
         String className = entry.getBusinessObjectClass().getName();
 488  
 
 489  0
         for (MaintainableSectionDefinition section : entry.getMaintainableSections()) {
 490  0
             for (MaintainableItemDefinition item : section.getMaintainableItems()) {
 491  0
                 if (item instanceof MaintainableFieldDefinition) {
 492  0
                     MaintainableFieldDefinition field = (MaintainableFieldDefinition) item;
 493  0
                     AttributeSecurity attributeSecurity = getDataDictionaryService().getAttributeSecurity(className, field.getName());
 494  0
                     if (attributeSecurity != null) {
 495  0
                         results.put(field.getName(), attributeSecurity);
 496  
                     }
 497  0
                 } else if (item instanceof MaintainableCollectionDefinition) {
 498  0
                     addMaintenanceDocumentCollectionPathToSecurityMappings(results, "", (MaintainableCollectionDefinition) item);
 499  
                 }
 500  
             }
 501  
         }
 502  0
         return results;
 503  
     }
 504  
 
 505  
     private static void addMaintenanceDocumentCollectionPathToSecurityMappings(Map<String, AttributeSecurity> mappings, String propertyPathPrefix, MaintainableCollectionDefinition collectionDefinition) {
 506  0
         propertyPathPrefix = propertyPathPrefix + collectionDefinition.getName() + ".";
 507  0
         String boClassName = collectionDefinition.getBusinessObjectClass().getName();
 508  0
         for (MaintainableFieldDefinition field : collectionDefinition.getMaintainableFields()) {
 509  0
             AttributeSecurity attributeSecurity = getDataDictionaryService().getAttributeSecurity(boClassName, field.getName());
 510  0
             if (attributeSecurity != null) {
 511  0
                 mappings.put(propertyPathPrefix + field.getName(), attributeSecurity);
 512  
             }
 513  0
         }
 514  0
         for (MaintainableCollectionDefinition nestedCollection : collectionDefinition.getMaintainableCollections()) {
 515  0
             addMaintenanceDocumentCollectionPathToSecurityMappings(mappings, propertyPathPrefix, nestedCollection);
 516  
         }
 517  0
     }
 518  
 }