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}