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}