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.kew.doctype.service.impl;
017
018import org.apache.commons.lang.StringUtils;
019import org.kuali.rice.coreservice.framework.CoreFrameworkServiceLocator;
020import org.kuali.rice.kew.api.KewApiConstants;
021import org.kuali.rice.kew.doctype.bo.DocumentType;
022import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
023import org.kuali.rice.kim.api.KimConstants;
024import org.kuali.rice.kim.api.permission.PermissionService;
025import org.kuali.rice.kim.api.services.KimApiServiceLocator;
026import org.kuali.rice.kns.document.authorization.DocumentAuthorizerBase;
027import org.kuali.rice.krad.datadictionary.DocumentEntry;
028import org.kuali.rice.krad.datadictionary.MaintenanceDocumentEntry;
029import org.kuali.rice.krad.document.Document;
030import org.kuali.rice.krad.maintenance.MaintenanceDocument;
031import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
032import org.kuali.rice.krad.util.KRADConstants;
033import org.kuali.rice.krad.util.KRADUtils;
034
035import java.util.*;
036
037/**
038 * Base class which implements default KIM permission checks for various workflow document actions.
039 * This implementation can be used as a base class for a DocumentTypePermissionService or DocumentTypeAuthorizer implementation
040 * @see org.kuali.rice.kew.doctype.service.DocumentTypePermissionService
041 * @see DocumentTypePermissionServiceImpl
042 * @see org.kuali.rice.kew.framework.document.security.DocumentTypeAuthorizer
043 * @see KimDocumentTypeAuthorizer
044 * @author Kuali Rice Team (rice.collab@kuali.org)
045 * @since 2.1.3
046 */
047public class DocumentActionsPermissionBase {
048    private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DocumentActionsPermissionBase.class);
049
050    /**
051     * Implements {@link org.kuali.rice.kew.doctype.service.DocumentTypePermissionService#canInitiate(String, org.kuali.rice.kew.doctype.bo.DocumentType)}
052     */
053    public boolean canInitiate(String principalId, DocumentType documentType) {
054        validatePrincipalId(principalId);
055        validateDocumentType(documentType);
056
057        Map<String, String> permissionDetails = buildDocumentTypePermissionDetails(documentType, null, null, null);
058        if (useKimPermission(KRADConstants.KUALI_RICE_SYSTEM_NAMESPACE, KewApiConstants.INITIATE_PERMISSION, permissionDetails, true)) {
059            return getPermissionService().isAuthorizedByTemplate(principalId, KRADConstants.KUALI_RICE_SYSTEM_NAMESPACE,
060                    KewApiConstants.INITIATE_PERMISSION, permissionDetails, new HashMap<String, String>());
061        }
062        return true;
063    }
064
065    /**
066     * Implements {@link org.kuali.rice.kew.doctype.service.DocumentTypePermissionService#canRoute(String, org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue)}
067     */
068    public boolean canRoute(String principalId, DocumentRouteHeaderValue document) {
069        validatePrincipalId(principalId);
070        validateDocument(document);
071        String documentId = document.getDocumentId();
072        DocumentType documentType = document.getDocumentType();
073        String documentStatus = document.getDocRouteStatus();
074        String initiatorPrincipalId = document.getInitiatorWorkflowId();
075        validateDocumentType(documentType);
076        validateDocumentStatus(documentStatus);
077        validatePrincipalId(initiatorPrincipalId);
078
079        if (!documentType.isPolicyDefined(org.kuali.rice.kew.api.doctype.DocumentTypePolicy.INITIATOR_MUST_ROUTE)) {
080            Map<String, String> permissionDetails = buildDocumentTypePermissionDetails(documentType, documentStatus, null, null);
081            Map<String, String> roleQualifiers = buildDocumentRoleQualifiers(document, permissionDetails.get(KewApiConstants.ROUTE_NODE_NAME_DETAIL));
082
083            if (LOG.isDebugEnabled()) {
084                LOG.debug("Permission details values: " + permissionDetails);
085                LOG.debug("Role qualifiers values: " + roleQualifiers);
086            }
087            if (useKimPermission(KewApiConstants.KEW_NAMESPACE, KewApiConstants.ROUTE_PERMISSION, permissionDetails, true)) {
088                return getPermissionService().isAuthorizedByTemplate(principalId, KewApiConstants.KEW_NAMESPACE,
089                        KewApiConstants.ROUTE_PERMISSION, permissionDetails, roleQualifiers);
090            }
091        }
092
093        if (documentType.getInitiatorMustRoutePolicy().getPolicyValue()) {
094            return executeInitiatorPolicyCheck(principalId, initiatorPrincipalId, documentStatus);
095        }
096        return true;
097    }
098
099    /**
100     * Provides base implementaiton for {@link org.kuali.rice.kew.doctype.service.DocumentTypePermissionService#canSuperUserApproveSingleActionRequest(String, org.kuali.rice.kew.doctype.bo.DocumentType, java.util.List, String)}
101     */
102    protected boolean canSuperUserApproveSingleActionRequest(String principalId, DocumentType documentType,
103                                                             Collection<String> routeNodeNames, String routeStatusCode) {
104        validatePrincipalId(principalId);
105        validateDocumentType(documentType);
106
107        List<Map<String, String>> permissionDetailList = buildDocumentTypePermissionDetailsForNodes(documentType, routeNodeNames, routeStatusCode, null);
108        // loop over permission details, only one of them needs to be authorized
109        PermissionService permissionService = getPermissionService();
110        for (Map<String, String> permissionDetails : permissionDetailList) {
111            if (permissionService.isAuthorizedByTemplate(principalId, KewApiConstants.KEW_NAMESPACE,
112                    KewApiConstants.SUPER_USER_APPROVE_SINGLE_ACTION_REQUEST, permissionDetails, new HashMap<String, String>())) {
113                return true;
114            }
115        }
116        return false;
117    }
118
119    /**
120     * Implements {@link org.kuali.rice.kew.doctype.service.DocumentTypePermissionService#canSuperUserApproveDocument(String, org.kuali.rice.kew.doctype.bo.DocumentType, java.util.List, String)}
121     */
122    protected boolean canSuperUserApproveDocument(String principalId, DocumentType documentType,
123                                                  Collection<String> routeNodeNames, String routeStatusCode) {
124        validatePrincipalId(principalId);
125        validateDocumentType(documentType);
126
127        List<Map<String, String>> permissionDetailList = buildDocumentTypePermissionDetailsForNodes(documentType, routeNodeNames, routeStatusCode, null);
128        // loop over permission details, only one of them needs to be authorized
129        PermissionService permissionService = getPermissionService();
130        for (Map<String, String> permissionDetails : permissionDetailList) {
131            if (permissionService.isAuthorizedByTemplate(principalId, KewApiConstants.KEW_NAMESPACE,
132                    KewApiConstants.SUPER_USER_APPROVE_DOCUMENT, permissionDetails, new HashMap<String, String>())) {
133                return true;
134            }
135        }
136        return false;
137    }
138
139    /**
140     * Implements {@link org.kuali.rice.kew.doctype.service.DocumentTypePermissionService#canSuperUserDisapproveDocument(String, org.kuali.rice.kew.doctype.bo.DocumentType, java.util.List, String)}
141     */
142    protected boolean canSuperUserDisapproveDocument(String principalId, DocumentType documentType,
143                                                     Collection<String> routeNodeNames,String routeStatusCode) {
144        validatePrincipalId(principalId);
145        validateDocumentType(documentType);
146
147        List<Map<String, String>> permissionDetailList = buildDocumentTypePermissionDetailsForNodes(documentType, routeNodeNames, routeStatusCode, null);
148        // loop over permission details, only one of them needs to be authorized
149        PermissionService permissionService = getPermissionService();
150        for (Map<String, String> permissionDetails : permissionDetailList) {
151            if (permissionService.isAuthorizedByTemplate(principalId, KewApiConstants.KEW_NAMESPACE,
152                    KewApiConstants.SUPER_USER_DISAPPROVE_DOCUMENT, permissionDetails, new HashMap<String, String>())) {
153                return true;
154            }
155        }
156        return false;
157    }
158
159    /**
160     * Implements {@link org.kuali.rice.kew.doctype.service.DocumentTypePermissionService#canCancel(String, org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue)}
161     */
162    public boolean canCancel(String principalId, DocumentRouteHeaderValue document) {
163        validatePrincipalId(principalId);
164        validateDocument(document);
165        String documentId = document.getDocumentId();
166        DocumentType documentType = document.getDocumentType();
167        String documentStatus = document.getDocRouteStatus();
168        String initiatorPrincipalId = document.getInitiatorWorkflowId();
169        List<String> routeNodeNames = document.getCurrentNodeNames();
170        validateDocumentType(documentType);
171        validateRouteNodeNames(routeNodeNames);
172        validateDocumentStatus(documentStatus);
173        validatePrincipalId(initiatorPrincipalId);
174
175        if (!documentType.isPolicyDefined(org.kuali.rice.kew.api.doctype.DocumentTypePolicy.INITIATOR_MUST_CANCEL)) {
176            List<Map<String, String>> permissionDetailList = buildDocumentTypePermissionDetailsForNodes(documentType, routeNodeNames, documentStatus, null);
177
178            boolean foundAtLeastOnePermission = false;
179            // loop over permission details, only one of them needs to be authorized
180            for (Map<String, String> permissionDetails : permissionDetailList) {
181                Map<String, String> roleQualifiers = buildDocumentRoleQualifiers(document, permissionDetails.get(KewApiConstants.ROUTE_NODE_NAME_DETAIL));
182                if (useKimPermission(KewApiConstants.KEW_NAMESPACE, KewApiConstants.CANCEL_PERMISSION, permissionDetails, true)) {
183                    foundAtLeastOnePermission = true;
184                    if (getPermissionService().isAuthorizedByTemplate(principalId, KewApiConstants.KEW_NAMESPACE,
185                            KewApiConstants.CANCEL_PERMISSION, permissionDetails, roleQualifiers)) {
186                        return true;
187                    }
188                }
189            }
190            // if we found defined KIM permissions, but not of them have authorized this user, return false
191            if (foundAtLeastOnePermission) {
192                return false;
193            }
194        }
195
196        if (documentType.getInitiatorMustCancelPolicy().getPolicyValue()) {
197            return executeInitiatorPolicyCheck(principalId, initiatorPrincipalId, documentStatus);
198        } else {
199            return true;
200        }
201    }
202
203    /**
204     * Implements {@link org.kuali.rice.kew.doctype.service.DocumentTypePermissionService#canRecall(String, org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue)}
205     */
206    public boolean canRecall(String principalId, DocumentRouteHeaderValue document) {
207        validatePrincipalId(principalId);
208        validateDocument(document);
209        String documentId = document.getDocumentId();
210        DocumentType documentType = document.getDocumentType();
211        String documentStatus = document.getDocRouteStatus();
212        String appDocStatus = document.getAppDocStatus();
213        String initiatorPrincipalId = document.getInitiatorWorkflowId();
214        List<String> routeNodeNames = document.getCurrentNodeNames();
215        validateDocumentType(documentType);
216        validateRouteNodeNames(routeNodeNames);
217        validateDocumentStatus(documentStatus);
218        // no need to validate appdocstatus, this is a free-form application defined value
219
220        // add appDocStatus to the details
221        List<Map<String, String>> permissionDetailList = buildDocumentTypePermissionDetailsForNodes(documentType, routeNodeNames, documentStatus, null);
222        if (!StringUtils.isBlank(appDocStatus)) {
223            for (Map<String, String> details: permissionDetailList) {
224                details.put(KewApiConstants.APP_DOC_STATUS_DETAIL, appDocStatus);
225            }
226        }
227
228        boolean foundAtLeastOnePermission = false;
229        boolean authorizedByPermission = false;
230        boolean principalIsInitiator = StringUtils.equals(initiatorPrincipalId, principalId);
231
232        // loop over permission details, only one of them needs to be authorized
233        for (Map<String, String> permissionDetails : permissionDetailList) {
234            Map<String, String> roleQualifiers = buildDocumentRoleQualifiers(document, permissionDetails.get(KewApiConstants.ROUTE_NODE_NAME_DETAIL));
235            if (useKimPermission(KewApiConstants.KEW_NAMESPACE, KewApiConstants.RECALL_PERMISSION, permissionDetails, false)) {
236                if (getPermissionService().isPermissionDefinedByTemplate(KewApiConstants.KEW_NAMESPACE, KewApiConstants.RECALL_PERMISSION, permissionDetails)) {
237                    foundAtLeastOnePermission = true;
238                    if (getPermissionService().isAuthorizedByTemplate(principalId, KewApiConstants.KEW_NAMESPACE,
239                            KewApiConstants.RECALL_PERMISSION, permissionDetails, roleQualifiers)) {
240                        return true;
241                    }
242                }
243            }
244        }
245        if (foundAtLeastOnePermission) {
246            return false;
247        }
248        // alternative could be to only authorize initiator if the permission is omitted
249        // (i.e. exclude initiator if the initiator does not have the recall permission)
250        return authorizedByPermission;
251    }
252
253    /**
254     * Implements {@link org.kuali.rice.kew.doctype.service.DocumentTypePermissionService#canBlanketApprove(String, org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue)}
255     */
256    public boolean canBlanketApprove(String principalId, DocumentRouteHeaderValue document) {
257        validatePrincipalId(principalId);
258        validateDocument(document);
259        DocumentType documentType = document.getDocumentType();
260        String initiatorPrincipalId = document.getInitiatorWorkflowId();
261        String documentStatus = document.getDocRouteStatus();
262        validateDocumentType(documentType);
263        validateDocumentStatus(documentStatus);
264        validatePrincipalId(initiatorPrincipalId);
265        final Boolean result;
266        if (documentType.isBlanketApproveGroupDefined()) {
267            boolean initiatorAuthorized = true;
268            if (documentType.getInitiatorMustBlanketApprovePolicy().getPolicyValue()) {
269                initiatorAuthorized = executeInitiatorPolicyCheck(principalId, initiatorPrincipalId, documentStatus);
270            }
271            result = initiatorAuthorized && documentType.isBlanketApprover(principalId);
272        } else {
273            Map<String, String> permissionDetails = buildDocumentTypePermissionDetails(documentType, documentStatus, null, null);
274            result = getPermissionService().isAuthorizedByTemplate(principalId, KewApiConstants.KEW_NAMESPACE,
275                    KewApiConstants.BLANKET_APPROVE_PERMISSION, permissionDetails, new HashMap<String, String>());
276        }
277        return result;
278    }
279
280    /**
281     * Implements {@link org.kuali.rice.kew.doctype.service.DocumentTypePermissionService#canSave(String, org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue)}
282     */
283    public boolean canSave(String principalId, DocumentRouteHeaderValue document) {
284        validatePrincipalId(principalId);
285        validateDocument(document);
286        String documentId = document.getDocumentId();
287        DocumentType documentType = document.getDocumentType();
288        String documentStatus = document.getDocRouteStatus();
289        String initiatorPrincipalId = document.getInitiatorWorkflowId();
290        List<String> routeNodeNames = document.getCurrentNodeNames();
291        validateDocumentType(documentType);
292        validateRouteNodeNames(routeNodeNames);
293        validateDocumentStatus(documentStatus);
294        validatePrincipalId(initiatorPrincipalId);
295
296        if (!documentType.isPolicyDefined(org.kuali.rice.kew.api.doctype.DocumentTypePolicy.INITIATOR_MUST_SAVE)) {
297            List<Map<String, String>> permissionDetailList = buildDocumentTypePermissionDetailsForNodes(documentType, routeNodeNames, documentStatus, null);
298
299            boolean foundAtLeastOnePermission = false;
300            // loop over permission details, only one of them needs to be authorized
301            for (Map<String, String> permissionDetails : permissionDetailList) {
302                Map<String, String> roleQualifiers = buildDocumentRoleQualifiers(document, permissionDetails.get(KewApiConstants.ROUTE_NODE_NAME_DETAIL));
303                if (useKimPermission(KewApiConstants.KEW_NAMESPACE, KewApiConstants.SAVE_PERMISSION, permissionDetails, true)) {
304                    foundAtLeastOnePermission = true;
305                    if (getPermissionService().isAuthorizedByTemplate(principalId, KewApiConstants.KEW_NAMESPACE,
306                            KewApiConstants.SAVE_PERMISSION, permissionDetails, roleQualifiers)) {
307                        return true;
308                    }
309                }
310            }
311            // if we found defined KIM permissions, but not of them have authorized this user, return false
312            if (foundAtLeastOnePermission) {
313                return false;
314            }
315        }
316
317        if (documentType.getInitiatorMustSavePolicy().getPolicyValue()) {
318            return executeInitiatorPolicyCheck(principalId, initiatorPrincipalId, documentStatus);
319        }
320        return true;
321    }
322
323    /**
324     * Generates permission details map for KIM permission checks.  Details are derived from document type, status, action request code (if non-null)
325     * and routeNode name (if non-null).  If the document status is not a routed state, "PreRoute" is used.
326     * Note that this has to match the required data defined in krim_typ_attr_t for the krim_typ_t with
327     * srvc_nm='documentTypeAndNodeOrStatePermissionTypeService'.
328     * TODO: See KULRICE-3490, make assembly of permission details dynamic based on db config
329     * @param documentType the KEW DocumentType
330     * @param documentStatus the document status
331     * @param actionRequestCode action request code if applicable
332     * @param routeNodeName routeNode name if applicable
333     * @return map of permission details for permission check
334     */
335    protected Map<String, String> buildDocumentTypePermissionDetails(DocumentType documentType, String documentStatus, String actionRequestCode, String routeNodeName) {
336        Map<String, String> details = new HashMap<String, String>();
337        if (documentType != null) {
338            details.put(KimConstants.AttributeConstants.DOCUMENT_TYPE_NAME, documentType.getName());
339        }
340        if (!StringUtils.isBlank(documentStatus)) {
341            details.put(KimConstants.AttributeConstants.ROUTE_STATUS_CODE, documentStatus);
342        }
343        if (KewApiConstants.ROUTE_HEADER_INITIATED_CD.equals(documentStatus) ||
344                KewApiConstants.ROUTE_HEADER_SAVED_CD.equals(documentStatus)) {
345            details.put(KewApiConstants.ROUTE_NODE_NAME_DETAIL, DocumentAuthorizerBase.PRE_ROUTING_ROUTE_NAME);
346        } else if (!StringUtils.isBlank(routeNodeName)) {
347            details.put(KewApiConstants.ROUTE_NODE_NAME_DETAIL, routeNodeName);
348        }
349        if (!StringUtils.isBlank(actionRequestCode)) {
350            details.put(KimConstants.AttributeConstants.ACTION_REQUEST_CD, actionRequestCode);
351        }
352        return details;
353    }
354
355    /**
356     * This method generates the permission details for the given document with current active route nodes.
357     * This method simply invokes {@link #buildDocumentTypePermissionDetails(org.kuali.rice.kew.doctype.bo.DocumentType, String, String, String)}
358     * for each node (or once if no node names are provided).
359     * @param documentType the DocumentType
360     * @param routeNodeNames active route nodes for which to generate permission details
361     * @param documentStatus document status
362     * @param actionRequestCode action request code if applicable
363     * @return list of permission details maps, one for each route node inspected
364     */
365    protected List<Map<String, String>> buildDocumentTypePermissionDetailsForNodes(DocumentType documentType,
366                                                                                   Collection<String> routeNodeNames, String documentStatus, String actionRequestCode) {
367        List<Map<String, String>> detailList = new ArrayList<Map<String, String>>();
368
369        if (!routeNodeNames.isEmpty()) {
370            for (String routeNodeName : routeNodeNames) {
371                detailList.add(buildDocumentTypePermissionDetails(documentType, documentStatus, actionRequestCode, routeNodeName));
372            }
373        } else {
374            detailList.add(buildDocumentTypePermissionDetails(documentType, documentStatus, actionRequestCode, null));
375        }
376        return detailList;
377    }
378
379    /**
380     * Generates role qualifiers for authorization check.  If the document status is a non-routed status, "PreRoute" is used.
381     * The namespaceCode attribute is derived from the KRAD DataDictionary if there is a mapping for the document type.
382     * @param document the document instance
383     * @param routeNodeName name of the applicable routenode
384     * @return map of role qualifiers
385     */
386    protected Map<String, String> buildDocumentRoleQualifiers(DocumentRouteHeaderValue document, String routeNodeName) {
387        Map<String, String> qualifiers = new HashMap<String, String>();
388        qualifiers.put(KimConstants.AttributeConstants.DOCUMENT_NUMBER, document.getDocumentId());
389        if (!StringUtils.isBlank(document.getDocRouteStatus())) {
390            qualifiers.put(KewApiConstants.DOCUMENT_STATUS_DETAIL, document.getDocRouteStatus());
391            if (KewApiConstants.ROUTE_HEADER_INITIATED_CD.equals(document.getDocRouteStatus()) || KewApiConstants.ROUTE_HEADER_SAVED_CD.equals(document.getDocRouteStatus())) {
392                qualifiers.put(KimConstants.AttributeConstants.ROUTE_NODE_NAME, DocumentAuthorizerBase.PRE_ROUTING_ROUTE_NAME);
393            }
394            else {
395                qualifiers.put(KimConstants.AttributeConstants.ROUTE_NODE_NAME, routeNodeName);
396            }
397        }
398        qualifiers.put(KewApiConstants.DOCUMENT_TYPE_NAME_DETAIL, document.getDocumentType().getName());
399
400        DocumentEntry documentEntry = KRADServiceLocatorWeb.getDataDictionaryService().getDataDictionary().getDocumentEntry(document.getDocumentType().getName());
401        if (documentEntry != null) {
402            Class<? extends Document> documentClass = documentEntry.getDocumentClass();
403            String namespaceCode;
404            if (MaintenanceDocument.class.isAssignableFrom(documentClass)) {
405                MaintenanceDocumentEntry maintenanceDocumentEntry = (MaintenanceDocumentEntry) documentEntry;
406                namespaceCode = KRADUtils.getNamespaceCode(maintenanceDocumentEntry.getDataObjectClass());
407            }
408            else {
409                namespaceCode = KRADUtils.getNamespaceCode(documentClass);
410            }
411            qualifiers.put(KimConstants.AttributeConstants.NAMESPACE_CODE, namespaceCode);
412        }
413
414        return qualifiers;
415    }
416
417    /**
418     * Returns whether to invoke KIM to perform permission checks.  First consults the {@link KewApiConstants#KIM_PRIORITY_ON_DOC_TYP_PERMS_IND} system parameter
419     * to determine whether we should check for permission existence.  If this parameter is unset or is true, we proceed to invoke
420     * {@link PermissionService#isPermissionDefinedByTemplate(String, String, java.util.Map)} to determine whether the given permission
421     * is defined anywhere in the system.
422     * @param namespace namespace of permission we are querying
423     * @param permissionTemplateName template name of permissions we are querying
424     * @param permissionDetails details of permissions we are querying
425     * @param checkKimPriorityInd whether to consult the {@link KewApiConstants#KIM_PRIORITY_ON_DOC_TYP_PERMS_IND} parameter to determine whether the check for
426     *                            permission definition
427     * @return whether there are any permissions defined for the given permission template, or false if we are checking the kim priority indicator and
428     *         the {@link KewApiConstants@KIM_PRIORITY_ON_DOC_TYP_PERMS_IND} system parameter is disabled.
429     */
430    protected boolean useKimPermission(String namespace, String permissionTemplateName, Map<String, String> permissionDetails, boolean checkKimPriorityInd) {
431        Boolean b = true;
432        if (checkKimPriorityInd) {
433            b =  CoreFrameworkServiceLocator.getParameterService().getParameterValueAsBoolean(KewApiConstants.KEW_NAMESPACE, KRADConstants.DetailTypes.ALL_DETAIL_TYPE, KewApiConstants.KIM_PRIORITY_ON_DOC_TYP_PERMS_IND);
434        }
435        if (b == null || b) {
436            return getPermissionService().isPermissionDefinedByTemplate(namespace, permissionTemplateName,
437                    permissionDetails);
438        }
439        return false;
440    }
441
442    private boolean executeInitiatorPolicyCheck(String principalId, String initiatorPrincipalId, String documentStatus) {
443        return principalId.equals(initiatorPrincipalId) || !(KewApiConstants.ROUTE_HEADER_SAVED_CD.equals(documentStatus) || KewApiConstants.ROUTE_HEADER_INITIATED_CD.equals(documentStatus));
444    }
445
446    /**
447     * Validates principal id parameter
448     * @param principalId the principal id
449     * @throw IllegalArgumentException if the principal is not valid (null or empty)
450     */
451    protected void validatePrincipalId(String principalId) {
452        if (StringUtils.isBlank(principalId)) {
453            throw new IllegalArgumentException("Invalid principal ID, value was empty");
454        }
455    }
456
457    /**
458     * Validates document parameter
459     * @param document the document
460     * @throw IllegalArgumentException if the document is null
461     */
462    protected void validateDocument(DocumentRouteHeaderValue document) {
463        if (document== null) {
464            throw new IllegalArgumentException("document cannot be null");
465        }
466    }
467
468    /**
469     * Validates documenttype parameter
470     * @param documentType the document type
471     * @throw IllegalArgumentException if the documenttype is null
472     */
473    protected void validateDocumentType(DocumentType documentType) {
474        if (documentType == null) {
475            throw new IllegalArgumentException("DocumentType cannot be null");
476        }
477    }
478
479    /**
480     * Validates routeNodeNames parameter
481     * @param routeNodeNames the routeNode names
482     * @throw IllegalArgumentException if any routeNode name is empty or null
483     */
484    protected void validateRouteNodeNames(List<String> routeNodeNames) {
485        if (routeNodeNames.isEmpty()) {
486            return;
487            //throw new IllegalArgumentException("List of route node names was empty.");
488        }
489        for (String routeNodeName : routeNodeNames) {
490            if (StringUtils.isBlank(routeNodeName)) {
491                throw new IllegalArgumentException("List of route node names contained an invalid route node name, value was empty");
492            }
493        }
494    }
495
496    /**
497     * Validates documentStatus parameter
498     * @param documentStatus the document status
499     * @throw IllegalArgumentException if document status is empty or null, or an invalid value
500     */
501    protected void validateDocumentStatus(String documentStatus) {
502        if (StringUtils.isBlank(documentStatus)) {
503            throw new IllegalArgumentException("Invalid document status, value was empty");
504        }
505        if (!KewApiConstants.DOCUMENT_STATUSES.containsKey(documentStatus)) {
506            throw new IllegalArgumentException("Invalid document status was given, value was: " + documentStatus);
507        }
508    }
509
510    // convenenience method to look up KIM PermissionService
511    protected PermissionService getPermissionService() {
512        return KimApiServiceLocator.getPermissionService();
513    }
514
515}