001/** 002 * Copyright 2005-2017 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.impl.doctype; 017 018import org.apache.commons.collections.CollectionUtils; 019import org.apache.commons.lang.StringUtils; 020import org.apache.log4j.Logger; 021import org.kuali.rice.core.api.exception.RiceIllegalArgumentException; 022import org.kuali.rice.kew.api.doctype.DocumentType; 023import org.kuali.rice.kew.api.doctype.DocumentTypeService; 024import org.kuali.rice.kew.api.doctype.ProcessDefinition; 025import org.kuali.rice.kew.api.doctype.RoutePath; 026import org.kuali.rice.kew.api.document.node.RouteNodeInstance; 027import org.kuali.rice.kew.doctype.dao.DocumentTypeDAO; 028import org.kuali.rice.kew.engine.node.ProcessDefinitionBo; 029import org.kuali.rice.kew.engine.node.RouteNode; 030import org.kuali.rice.kew.service.KEWServiceLocator; 031import org.kuali.rice.krad.data.DataObjectService; 032import org.springframework.beans.factory.annotation.Required; 033 034import java.util.ArrayList; 035import java.util.Collections; 036import java.util.List; 037 038/** 039 * Reference implementation of the {@link DocumentTypeService}. 040 * 041 * @author Kuali Rice Team (rice.collab@kuali.org) 042 * 043 */ 044public class DocumentTypeServiceImpl implements DocumentTypeService { 045 046 private static final Logger LOG = Logger.getLogger(DocumentTypeServiceImpl.class); 047 048 private DocumentTypeDAO documentTypeDao; 049 050 private DataObjectService dataObjectService; 051 052 @Override 053 public String getIdByName(String documentTypeName) { 054 if (StringUtils.isBlank(documentTypeName)) { 055 throw new RiceIllegalArgumentException("documentTypeName was null or blank"); 056 } 057 return documentTypeDao.findDocumentTypeIdByName(documentTypeName); 058 } 059 060 @Override 061 public String getNameById(String documentTypeId) { 062 if (StringUtils.isBlank(documentTypeId)) { 063 throw new RiceIllegalArgumentException("documentTypeId was null or blank"); 064 } 065 return documentTypeDao.findDocumentTypeNameById(documentTypeId); 066 } 067 068 @Override 069 public DocumentType getDocumentTypeById(String documentTypeId) { 070 if (StringUtils.isBlank(documentTypeId)) { 071 throw new RiceIllegalArgumentException("documentTypeId was null or blank"); 072 } 073 org.kuali.rice.kew.doctype.bo.DocumentType documentTypeBo = getDataObjectService(). 074 find(org.kuali.rice.kew.doctype.bo.DocumentType.class,documentTypeId); 075 return org.kuali.rice.kew.doctype.bo.DocumentType.to(documentTypeBo); 076 } 077 078 @Override 079 public org.kuali.rice.kew.api.doctype.DocumentType getDocumentTypeByName(String documentTypeName) { 080 if (StringUtils.isBlank(documentTypeName)) { 081 throw new RiceIllegalArgumentException("documentTypeName was null or blank"); 082 } 083 org.kuali.rice.kew.doctype.bo.DocumentType documentTypeBo = documentTypeDao.findByName(documentTypeName); 084 return org.kuali.rice.kew.doctype.bo.DocumentType.to(documentTypeBo); 085 } 086 087 @Override 088 public List<org.kuali.rice.kew.api.doctype.DocumentType> findAllDocumentTypes() { 089 List<org.kuali.rice.kew.doctype.bo.DocumentType> documentTypeBos = documentTypeDao.findAllCurrent(); 090 List<org.kuali.rice.kew.api.doctype.DocumentType> currentDocTypes = new ArrayList<org.kuali.rice.kew.api.doctype.DocumentType>(); 091 for (org.kuali.rice.kew.doctype.bo.DocumentType dt : documentTypeBos) { 092 currentDocTypes.add(org.kuali.rice.kew.doctype.bo.DocumentType.to(dt)); 093 } 094 return Collections.unmodifiableList(currentDocTypes); 095 } 096 097 @Override 098 public boolean isSuperUserForDocumentTypeId(String principalId, String documentTypeId) { 099 if (LOG.isDebugEnabled()) { 100 LOG.debug("Determining super user status [principalId=" + principalId + ", documentTypeId=" 101 + documentTypeId + "]"); 102 } 103 if (StringUtils.isBlank(principalId)) { 104 throw new RiceIllegalArgumentException("principalId was null or blank"); 105 } 106 if (StringUtils.isBlank(documentTypeId)) { 107 throw new RiceIllegalArgumentException("documentTypeId was null or blank"); 108 } 109 org.kuali.rice.kew.doctype.bo.DocumentType documentType = KEWServiceLocator.getDocumentTypeService().findById(documentTypeId); 110 boolean isSuperUser = KEWServiceLocator.getDocumentTypePermissionService().canAdministerRouting(principalId, 111 documentType); 112 if (LOG.isDebugEnabled()) { 113 LOG.debug("Super user status is " + isSuperUser + "."); 114 } 115 return isSuperUser; 116 117 } 118 119 @Override 120 public boolean isSuperUserForDocumentTypeName(String principalId, String documentTypeName) { 121 if (LOG.isDebugEnabled()) { 122 LOG.debug("Determining super user status [principalId=" + principalId + ", documentTypeName=" 123 + documentTypeName + "]"); 124 } 125 if (StringUtils.isBlank(principalId)) { 126 throw new RiceIllegalArgumentException("principalId was null or blank"); 127 } 128 if (StringUtils.isBlank(documentTypeName)) { 129 throw new RiceIllegalArgumentException("documentTypeId was null or blank"); 130 } 131 org.kuali.rice.kew.doctype.bo.DocumentType documentType = KEWServiceLocator.getDocumentTypeService().findByName(documentTypeName); 132 boolean isSuperUser = KEWServiceLocator.getDocumentTypePermissionService().canAdministerRouting(principalId, 133 documentType); 134 if (LOG.isDebugEnabled()) { 135 LOG.debug("Super user status is " + isSuperUser + "."); 136 } 137 return isSuperUser; 138 139 } 140 141 @Override 142 public boolean canSuperUserApproveSingleActionRequest( String principalId, String documentTypeName, List<RouteNodeInstance> routeNodeInstances, String routeStatusCode ) { 143 144 checkSuperUserInput( principalId, documentTypeName ); 145 146 org.kuali.rice.kew.doctype.bo.DocumentType documentType = KEWServiceLocator.getDocumentTypeService().findByName(documentTypeName); 147 List<org.kuali.rice.kew.engine.node.RouteNodeInstance> currentNodeInstances = null; 148 if (routeNodeInstances != null && !routeNodeInstances.isEmpty()) { 149 currentNodeInstances = KEWServiceLocator.getRouteNodeService().getCurrentNodeInstances(routeNodeInstances.get(0).getDocumentId()); 150 } 151 152 boolean isSuperUser = KEWServiceLocator.getDocumentTypePermissionService().canSuperUserApproveSingleActionRequest( principalId, documentType, 153 currentNodeInstances, routeStatusCode); 154 if (LOG.isDebugEnabled()) { 155 LOG.debug("Super user approve single action request status is " + isSuperUser + "."); 156 } 157 return isSuperUser; 158 } 159 160 @Override 161 public boolean canSuperUserApproveDocument( String principalId, String documentTypeName, List<RouteNodeInstance> routeNodeInstances, String routeStatusCode ) { 162 checkSuperUserInput( principalId, documentTypeName ); 163 164 org.kuali.rice.kew.doctype.bo.DocumentType documentType = KEWServiceLocator.getDocumentTypeService().findByName(documentTypeName); 165 List<org.kuali.rice.kew.engine.node.RouteNodeInstance> currentNodeInstances = null; 166 if (routeNodeInstances != null && !routeNodeInstances.isEmpty()) { 167 currentNodeInstances = KEWServiceLocator.getRouteNodeService().getCurrentNodeInstances(routeNodeInstances.get(0).getDocumentId()); 168 } 169 170 boolean isSuperUser = KEWServiceLocator.getDocumentTypePermissionService().canSuperUserApproveDocument( 171 principalId, documentType, currentNodeInstances, routeStatusCode); 172 if (LOG.isDebugEnabled()) { 173 LOG.debug("Super user approve document status is " + isSuperUser + "."); 174 } 175 return isSuperUser; 176 } 177 178 @Override 179 public boolean canSuperUserDisapproveDocument( String principalId, String documentTypeName, List<RouteNodeInstance> routeNodeInstances, String routeStatusCode ) { 180 checkSuperUserInput( principalId, documentTypeName ); 181 182 org.kuali.rice.kew.doctype.bo.DocumentType documentType = KEWServiceLocator.getDocumentTypeService().findByName(documentTypeName); 183 184 List<org.kuali.rice.kew.engine.node.RouteNodeInstance> currentNodeInstances = null; 185 if (routeNodeInstances != null && !routeNodeInstances.isEmpty()) { 186 currentNodeInstances = KEWServiceLocator.getRouteNodeService().getCurrentNodeInstances(routeNodeInstances.get(0).getDocumentId()); 187 } 188 189 boolean isSuperUser = KEWServiceLocator.getDocumentTypePermissionService().canSuperUserDisapproveDocument( principalId, documentType, 190 currentNodeInstances, routeStatusCode); 191 if (LOG.isDebugEnabled()) { 192 LOG.debug("Super user disapprove document status is " + isSuperUser + "."); 193 } 194 return isSuperUser; 195 } 196 197 private void checkSuperUserInput( String principalId, String documentTypeName ) { 198 if (LOG.isDebugEnabled()) { 199 LOG.debug("Determining super user status [principalId=" + principalId + ", documentTypeName=" 200 + documentTypeName + "]"); 201 } 202 if (StringUtils.isBlank(principalId)) { 203 throw new RiceIllegalArgumentException("principalId was null or blank"); 204 } 205 if (StringUtils.isBlank(documentTypeName)) { 206 throw new RiceIllegalArgumentException("documentTypeId was null or blank"); 207 } 208 } 209 210 @Override 211 public boolean hasRouteNodeForDocumentTypeName(String routeNodeName, String documentTypeName) 212 throws RiceIllegalArgumentException { 213 if (StringUtils.isBlank(routeNodeName)) { 214 throw new RiceIllegalArgumentException("routeNodeName was null or blank"); 215 } 216 if (StringUtils.isBlank(documentTypeName)) { 217 throw new RiceIllegalArgumentException("documentTypeName was null or blank"); 218 } 219 220 DocumentType documentType = getDocumentTypeByName(documentTypeName); 221 if (documentType == null) { 222 throw new RiceIllegalArgumentException("Failed to locate a document type for the given name: " + documentTypeName); 223 } 224 RouteNode routeNode = KEWServiceLocator.getRouteNodeService().findRouteNodeByName(documentType.getId(), routeNodeName); 225 226 if (routeNode == null) { 227 if (documentType.getParentId() == null) { 228 return false; 229 } else { 230 return hasRouteNodeForDocumentTypeId(routeNodeName, documentType.getParentId()); 231 } 232 } else { 233 return true; 234 } 235 } 236 237 @Override 238 public boolean hasRouteNodeForDocumentTypeId(String routeNodeName, String documentTypeId) 239 throws RiceIllegalArgumentException { 240 if (StringUtils.isBlank(routeNodeName)) { 241 throw new RiceIllegalArgumentException("routeNodeName was null or blank"); 242 } 243 if (StringUtils.isBlank(documentTypeId)) { 244 throw new RiceIllegalArgumentException("documentTypeId was null or blank"); 245 } 246 247 DocumentType documentType = getDocumentTypeById(documentTypeId); 248 if (documentType == null) { 249 throw new RiceIllegalArgumentException("Failed to locate a document type for the given id: " + documentTypeId); 250 } 251 RouteNode routeNode = KEWServiceLocator.getRouteNodeService().findRouteNodeByName(documentType.getId(), routeNodeName); 252 253 if (routeNode == null) { 254 if (documentType.getParentId() == null) { 255 return false; 256 } else { 257 return hasRouteNodeForDocumentTypeId(routeNodeName, documentType.getParentId()); 258 } 259 } else { 260 return true; 261 } 262 } 263 264 @Override 265 public boolean isActiveById(String documentTypeId) { 266 if (StringUtils.isBlank(documentTypeId)) { 267 throw new RiceIllegalArgumentException("documentTypeId was null or blank"); 268 } 269 org.kuali.rice.kew.doctype.bo.DocumentType docType = KEWServiceLocator.getDocumentTypeService().findById(documentTypeId); 270 return docType != null && docType.isActive(); 271 } 272 273 @Override 274 public boolean isActiveByName(String documentTypeName) { 275 if (StringUtils.isBlank(documentTypeName)) { 276 throw new RiceIllegalArgumentException("documentTypeName was null or blank"); 277 } 278 org.kuali.rice.kew.doctype.bo.DocumentType docType = KEWServiceLocator.getDocumentTypeService().findByName(documentTypeName); 279 return docType != null && docType.isActive(); 280 } 281 282 @Override 283 public RoutePath getRoutePathForDocumentTypeId(String documentTypeId) { 284 if (StringUtils.isBlank(documentTypeId)) { 285 throw new RiceIllegalArgumentException("documentTypeId was null or blank"); 286 } 287 org.kuali.rice.kew.doctype.bo.DocumentType docType = KEWServiceLocator.getDocumentTypeService().findById(documentTypeId); 288 if (docType == null) { 289 return null; 290 } 291 RoutePath.Builder builder = RoutePath.Builder.create(); 292 List<ProcessDefinitionBo> processes = docType.getProcesses(); 293 for (ProcessDefinitionBo process : processes) { 294 builder.getProcessDefinitions().add(ProcessDefinition.Builder.create(process)); 295 } 296 return builder.build(); 297 } 298 299 @Override 300 public RoutePath getRoutePathForDocumentTypeName(String documentTypeName) { 301 if (StringUtils.isBlank(documentTypeName)) { 302 throw new RiceIllegalArgumentException("documentTypeName was null or blank"); 303 } 304 org.kuali.rice.kew.doctype.bo.DocumentType docType = KEWServiceLocator.getDocumentTypeService().findByName(documentTypeName); 305 if (docType == null) { 306 return null; 307 } 308 RoutePath.Builder builder = RoutePath.Builder.create(); 309 List<ProcessDefinitionBo> processes = docType.getProcesses(); 310 for (ProcessDefinitionBo process : processes) { 311 builder.getProcessDefinitions().add(ProcessDefinition.Builder.create(process)); 312 } 313 return builder.build(); 314 315 } 316 317 public void setDocumentTypeDao(DocumentTypeDAO documentTypeDao) { 318 this.documentTypeDao = documentTypeDao; 319 } 320 321 322 public DataObjectService getDataObjectService() { 323 return dataObjectService; 324 } 325 326 @Required 327 public void setDataObjectService(DataObjectService dataObjectService) { 328 this.dataObjectService = dataObjectService; 329 } 330 331}