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.routeheader.service.impl;
017
018import java.math.BigDecimal;
019import java.sql.Timestamp;
020import java.util.ArrayList;
021import java.util.Collection;
022import java.util.HashMap;
023import java.util.HashSet;
024import java.util.List;
025import java.util.Map;
026import java.util.Set;
027
028import org.apache.commons.lang.StringUtils;
029import org.kuali.rice.kew.api.KewApiConstants;
030import org.kuali.rice.kew.api.action.ActionItem;
031import org.kuali.rice.kew.docsearch.SearchableAttributeValue;
032import org.kuali.rice.kew.docsearch.dao.SearchableAttributeDAO;
033import org.kuali.rice.kew.doctype.bo.DocumentType;
034import org.kuali.rice.kew.exception.WorkflowServiceErrorException;
035import org.kuali.rice.kew.exception.WorkflowServiceErrorImpl;
036import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
037import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValueContent;
038import org.kuali.rice.kew.routeheader.dao.DocumentRouteHeaderDAO;
039import org.kuali.rice.kew.routeheader.service.RouteHeaderService;
040import org.kuali.rice.kew.service.KEWServiceLocator;
041import org.kuali.rice.kim.api.identity.principal.Principal;
042import org.kuali.rice.kim.api.services.KimApiServiceLocator;
043
044
045
046public class RouteHeaderServiceImpl implements RouteHeaderService {
047
048    private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(RouteHeaderServiceImpl.class);
049
050    private DocumentRouteHeaderDAO routeHeaderDAO;
051    private SearchableAttributeDAO searchableAttributeDAO;
052
053    public DocumentRouteHeaderValue getRouteHeader(String documentId) {
054        return getRouteHeaderDAO().findRouteHeader(documentId);
055    }
056
057    public DocumentRouteHeaderValue getRouteHeader(String documentId, boolean clearCache) {
058        return getRouteHeaderDAO().findRouteHeader(documentId, clearCache);
059    }
060
061    public Collection<DocumentRouteHeaderValue> getRouteHeaders(Collection<String> documentIds) {
062        return getRouteHeaderDAO().findRouteHeaders(documentIds);
063    }
064    
065    public Collection<DocumentRouteHeaderValue> getRouteHeaders(Collection<String> documentIds, boolean clearCache) {
066        return getRouteHeaderDAO().findRouteHeaders(documentIds, clearCache);
067    }
068    
069    public Map<String,DocumentRouteHeaderValue> getRouteHeadersForActionItems(Collection<ActionItem> actionItems) {
070        Map<String,DocumentRouteHeaderValue> routeHeaders = new HashMap<String,DocumentRouteHeaderValue>();
071        List<String> documentIds = new ArrayList<String>(actionItems.size());
072        for (ActionItem actionItem : actionItems) {
073                documentIds.add(actionItem.getDocumentId());
074        }
075        Collection<DocumentRouteHeaderValue> actionItemRouteHeaders = getRouteHeaders(documentIds);
076        if (actionItemRouteHeaders != null) {
077                for (DocumentRouteHeaderValue routeHeader : actionItemRouteHeaders) {
078                        routeHeaders.put(routeHeader.getDocumentId(), routeHeader);
079                }
080        }
081        return routeHeaders;
082    }
083    
084    public void lockRouteHeader(String documentId, boolean wait) {
085        getRouteHeaderDAO().lockRouteHeader(documentId, wait);
086        LOG.debug("Successfully locked document [docId=" + documentId + "]");
087    }
088
089    public void saveRouteHeader(DocumentRouteHeaderValue routeHeader) {
090        this.getRouteHeaderDAO().saveRouteHeader(routeHeader);
091    }
092
093    public void deleteRouteHeader(DocumentRouteHeaderValue routeHeader) {
094        getRouteHeaderDAO().deleteRouteHeader(routeHeader);
095    }
096
097    public String getNextDocumentId() {
098        return getRouteHeaderDAO().getNextDocumentId();
099    }
100
101    public Collection findPendingByResponsibilityIds(Set responsibilityIds) {
102        return getRouteHeaderDAO().findPendingByResponsibilityIds(responsibilityIds);
103    }
104
105    public void clearRouteHeaderSearchValues(String documentId) {
106        getRouteHeaderDAO().clearRouteHeaderSearchValues(documentId);
107    }
108
109    public void updateRouteHeaderSearchValues(String documentId, List<SearchableAttributeValue> searchAttributes) {
110        getRouteHeaderDAO().clearRouteHeaderSearchValues(documentId);
111        HashSet<String> uniqueAttributes = new HashSet<String>();
112        //"de-dupe" for value,key,and doc header id
113        for (SearchableAttributeValue searchAttribute : searchAttributes) {
114            if(searchAttribute != null) {
115                String fakeKey = searchAttribute.getSearchableAttributeKey() + "-" + searchAttribute.getSearchableAttributeValue();
116                if(!uniqueAttributes.contains(fakeKey)){
117                    getRouteHeaderDAO().save(searchAttribute);
118                    uniqueAttributes.add(fakeKey);
119                }
120            }
121        }
122        LOG.info("Deduplication adjusted incoming SearchableAttributeValue list from original: " + searchAttributes.size() + " entries into : "  + (searchAttributes.size() - uniqueAttributes.size()) + " entries.");
123    }
124
125    public void validateRouteHeader(DocumentRouteHeaderValue routeHeader){
126        LOG.debug("Enter validateRouteHeader(..)");
127        List errors = new ArrayList();
128
129        if (routeHeader.getDocRouteStatus() == null || routeHeader.getDocRouteStatus().trim().equals("")) {
130            errors.add(new WorkflowServiceErrorImpl("RouteHeader route status null.", "routeheader.routestatus.empty"));
131        } else if (!KewApiConstants.DOCUMENT_STATUSES.containsKey(routeHeader.getDocRouteStatus())){
132            errors.add(new WorkflowServiceErrorImpl("RouteHeader route status invalid.", "routeheader.routestatus.invalid"));
133        }
134
135        if(routeHeader.getDocRouteLevel() == null || routeHeader.getDocRouteLevel().intValue() < 0){
136            errors.add(new WorkflowServiceErrorImpl("RouteHeader route level invalid.", "routeheader.routelevel.invalid"));
137        }
138
139        if(routeHeader.getDateLastModified() == null){
140            errors.add(new WorkflowServiceErrorImpl("RouteHeader status modification date empty.", "routeheader.statusmoddate.empty"));
141        }
142
143        if(routeHeader.getCreateDate() == null){
144            errors.add(new WorkflowServiceErrorImpl("RouteHeader status create date empty.", "routeheader.createdate.empty"));
145        }
146        if(routeHeader.getDocVersion() == null || routeHeader.getDocVersion().intValue() < 0){
147            errors.add(new WorkflowServiceErrorImpl("RouteHeader doc version invalid.", "routeheader.docversion.invalid"));
148        }
149
150        if (routeHeader.getInitiatorWorkflowId () == null || routeHeader.getInitiatorWorkflowId().trim().equals("")) {
151            errors.add(new WorkflowServiceErrorImpl("RouteHeader initiator null.", "routeheader.initiator.empty"));
152        }
153        else
154        {
155                Principal principal = KimApiServiceLocator.getIdentityService().getPrincipal(routeHeader.getInitiatorWorkflowId());
156            if(principal == null)
157            {
158                errors.add(new WorkflowServiceErrorImpl("RouteHeader initiator id invalid.", "routeheader.initiator.invalid"));
159            }
160        }
161
162        if(!StringUtils.isBlank(routeHeader.getDocumentTypeId())){
163            DocumentType docType = KEWServiceLocator.getDocumentTypeService().findById(routeHeader.getDocumentTypeId());
164            if(docType == null){
165                errors.add(new WorkflowServiceErrorImpl("RouteHeader document type id invalid.", "routeheader.doctypeid.invalid"));
166            }
167        }
168
169        LOG.debug("Exit validateRouteHeader(..) ");
170        if (!errors.isEmpty()) {
171            throw new WorkflowServiceErrorException("RouteHeader Validation Error", errors);
172        }
173    }
174
175    public String getApplicationIdByDocumentId(String documentId) {
176        return getRouteHeaderDAO().getApplicationIdByDocumentId(documentId);
177    }
178
179    public DocumentRouteHeaderValueContent getContent(String documentId) {
180        if (documentId == null) {
181                return new DocumentRouteHeaderValueContent();
182        }
183        DocumentRouteHeaderValueContent content = getRouteHeaderDAO().getContent(documentId);
184        if (content == null) {
185                content = new DocumentRouteHeaderValueContent(documentId);
186        }
187        return content;
188    }
189
190    public boolean hasSearchableAttributeValue(String documentId, String searchableAttributeKey, String searchableAttributeValue) {
191        return getRouteHeaderDAO().hasSearchableAttributeValue(documentId, searchableAttributeKey, searchableAttributeValue);
192    }
193
194    public String getDocumentStatus(String documentId) {
195        return getRouteHeaderDAO().getDocumentStatus(documentId);
196    }
197    
198    public String getAppDocId(String documentId) {
199                if (documentId == null) {
200                        return null;
201                }
202                return getRouteHeaderDAO().getAppDocId(documentId);
203    }
204
205    public String getAppDocStatus(String documentId) {
206        if (documentId == null) {
207            return null;
208        }
209        return getRouteHeaderDAO().getAppDocStatus(documentId);
210    }
211
212    public DocumentRouteHeaderDAO getRouteHeaderDAO() {
213        return routeHeaderDAO;
214    }
215
216    public void setRouteHeaderDAO(DocumentRouteHeaderDAO routeHeaderDAO) {
217        this.routeHeaderDAO = routeHeaderDAO;
218    }
219
220        public List<Timestamp> getSearchableAttributeDateTimeValuesByKey(
221                        String documentId, String key) {
222                return getSearchableAttributeDAO().getSearchableAttributeDateTimeValuesByKey(documentId, key);
223        }
224
225        public List<BigDecimal> getSearchableAttributeFloatValuesByKey(
226                        String documentId, String key) {
227                return getSearchableAttributeDAO().getSearchableAttributeFloatValuesByKey(documentId, key);
228        }
229
230        public List<Long> getSearchableAttributeLongValuesByKey(String documentId,
231                        String key) {
232                return getSearchableAttributeDAO().getSearchableAttributeLongValuesByKey(documentId, key);
233        }
234
235        public List<String> getSearchableAttributeStringValuesByKey(
236                        String documentId, String key) {
237
238                return getSearchableAttributeDAO().getSearchableAttributeStringValuesByKey(documentId, key);
239        }
240
241        public void setSearchableAttributeDAO(SearchableAttributeDAO searchableAttributeDAO) {
242                this.searchableAttributeDAO = searchableAttributeDAO;
243        }
244
245        public SearchableAttributeDAO getSearchableAttributeDAO() {
246                return searchableAttributeDAO;
247        }
248
249        public Collection findByDocTypeAndAppId(String documentTypeName,
250                        String appId) {
251                return getRouteHeaderDAO().findByDocTypeAndAppId(documentTypeName, appId);
252        }
253}