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