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.stuck; 017 018import org.kuali.rice.core.api.config.property.RuntimeConfig; 019import org.slf4j.Logger; 020import org.slf4j.LoggerFactory; 021import org.springframework.beans.factory.annotation.Required; 022 023import java.sql.Timestamp; 024import java.util.ArrayList; 025import java.util.Collections; 026import java.util.List; 027import java.util.stream.Collectors; 028 029import static com.google.common.base.Preconditions.checkNotNull; 030 031/** 032 * @author Eric Westfall 033 */ 034public class StuckDocumentServiceImpl implements StuckDocumentService { 035 036 private StuckDocumentDao stuckDocumentDao; 037 private StuckDocumentNotifier notifier; 038 private RuntimeConfig failureNotificationEnabled; 039 040 @Override 041 public List<String> findAllStuckDocumentIds() { 042 return getStuckDocumentDao().findAllStuckDocumentIds(); 043 } 044 045 @Override 046 public List<StuckDocument> findAllStuckDocuments() { 047 return getStuckDocumentDao().findAllStuckDocuments(); 048 } 049 050 @Override 051 public StuckDocumentIncident findIncident(String stuckDocumentIncidentId) { 052 checkNotNull(stuckDocumentIncidentId); 053 return getStuckDocumentDao().findIncident(stuckDocumentIncidentId); 054 } 055 056 @Override 057 public List<StuckDocumentIncident> findIncidents(List<String> stuckDocumentIncidentIds) { 058 checkNotNull(stuckDocumentIncidentIds); 059 List<StuckDocumentIncident> incidents = new ArrayList<>(stuckDocumentIncidentIds.size()); 060 for (String stuckDocumentIncidentId : stuckDocumentIncidentIds) { 061 StuckDocumentIncident incident = findIncident(stuckDocumentIncidentId); 062 if (incident != null) { 063 incidents.add(incident); 064 } 065 } 066 return incidents; 067 } 068 069 @Override 070 public List<StuckDocumentIncident> findAllIncidents(int maxIncidents) { 071 return getStuckDocumentDao().findAllIncidents(maxIncidents); 072 } 073 074 @Override 075 public List<StuckDocumentIncident> findIncidentsByStatus(int maxIncidents, StuckDocumentIncident.Status status) { 076 return getStuckDocumentDao().findIncidentsByStatus(maxIncidents, status); 077 } 078 079 @Override 080 public List<StuckDocumentIncident> recordNewStuckDocumentIncidents() { 081 List<String> newStuckDocuments = getStuckDocumentDao().identifyNewStuckDocuments(); 082 return newStuckDocuments.stream().map(documentId -> getStuckDocumentDao().saveIncident(StuckDocumentIncident.startNewIncident(documentId))).collect(Collectors.toList()); 083 } 084 085 @Override 086 public StuckDocumentFixAttempt recordNewIncidentFixAttempt(StuckDocumentIncident stuckDocumentIncident) { 087 checkNotNull(stuckDocumentIncident); 088 StuckDocumentFixAttempt auditEntry = new StuckDocumentFixAttempt(); 089 auditEntry.setStuckDocumentIncidentId(stuckDocumentIncident.getStuckDocumentIncidentId()); 090 auditEntry.setTimestamp(new Timestamp(System.currentTimeMillis())); 091 return getStuckDocumentDao().saveFixAttempt(auditEntry); 092 } 093 094 @Override 095 public List<StuckDocumentFixAttempt> findAllFixAttempts(String stuckDocumentIncidentId) { 096 return getStuckDocumentDao().findAllFixAttempts(stuckDocumentIncidentId); 097 } 098 099 @Override 100 public List<StuckDocumentIncident> resolveIncidentsIfPossible(List<String> stuckDocumentIncidentIds) { 101 checkNotNull(stuckDocumentIncidentIds); 102 List<StuckDocumentIncident> stuckIncidents = getStuckDocumentDao().identifyStillStuckDocuments(stuckDocumentIncidentIds); 103 List<String> stuckIncidentIds = stuckIncidents.stream().map(StuckDocumentIncident::getStuckDocumentIncidentId).collect(Collectors.toList()); 104 // let's find the ones that aren't stuck so that we can resolve them 105 List<String> notStuckIncidentIds = new ArrayList<>(stuckDocumentIncidentIds); 106 notStuckIncidentIds.removeAll(stuckIncidentIds); 107 if (!notStuckIncidentIds.isEmpty()) { 108 List<StuckDocumentIncident> notStuckIncidents = findIncidents(notStuckIncidentIds); 109 notStuckIncidents.forEach(this::resolve); 110 } 111 return stuckIncidents; 112 } 113 114 protected StuckDocumentIncident resolve(StuckDocumentIncident stuckDocumentIncident) { 115 checkNotNull(stuckDocumentIncident); 116 if (stuckDocumentIncident.getStatus().equals(StuckDocumentIncident.Status.PENDING)) { 117 // if it was pending that means we just went through the quiet period and the document unstuck itself, 118 // let's get rid of it's incident since it's just noise 119 getStuckDocumentDao().deleteIncident(stuckDocumentIncident); 120 return stuckDocumentIncident; 121 } else { 122 stuckDocumentIncident.setStatus(StuckDocumentIncident.Status.FIXED); 123 stuckDocumentIncident.setEndDate(new Timestamp(System.currentTimeMillis())); 124 return getStuckDocumentDao().saveIncident(stuckDocumentIncident); 125 } 126 } 127 128 @Override 129 public StuckDocumentIncident startFixingIncident(StuckDocumentIncident stuckDocumentIncident) { 130 checkNotNull(stuckDocumentIncident); 131 stuckDocumentIncident.setStatus(StuckDocumentIncident.Status.FIXING); 132 return getStuckDocumentDao().saveIncident(stuckDocumentIncident); 133 } 134 135 @Override 136 public StuckDocumentIncident recordIncidentFailure(StuckDocumentIncident stuckDocumentIncident) { 137 checkNotNull(stuckDocumentIncident); 138 stuckDocumentIncident.setStatus(StuckDocumentIncident.Status.FAILED); 139 stuckDocumentIncident.setEndDate(new Timestamp(System.currentTimeMillis())); 140 stuckDocumentIncident = getStuckDocumentDao().saveIncident(stuckDocumentIncident); 141 notifyIncidentFailure(stuckDocumentIncident); 142 return stuckDocumentIncident; 143 } 144 145 protected void notifyIncidentFailure(StuckDocumentIncident stuckDocumentIncident) { 146 if (getFailureNotificationEnabled().getValueAsBoolean()) { 147 List<StuckDocumentFixAttempt> attempts = getStuckDocumentDao().findAllFixAttempts(stuckDocumentIncident.getStuckDocumentIncidentId()); 148 notifier.notifyIncidentFailure(stuckDocumentIncident, attempts); 149 } 150 } 151 152 protected StuckDocumentDao getStuckDocumentDao() { 153 return stuckDocumentDao; 154 } 155 156 @Required 157 public void setStuckDocumentDao(StuckDocumentDao stuckDocumentDao) { 158 this.stuckDocumentDao = stuckDocumentDao; 159 } 160 161 protected StuckDocumentNotifier getNotifier() { 162 return notifier; 163 } 164 165 @Required 166 public void setNotifier(StuckDocumentNotifier notifier) { 167 this.notifier = notifier; 168 } 169 170 protected RuntimeConfig getFailureNotificationEnabled() { 171 return failureNotificationEnabled; 172 } 173 174 @Required 175 public void setFailureNotificationEnabled(RuntimeConfig failureNotificationEnabled) { 176 this.failureNotificationEnabled = failureNotificationEnabled; 177 } 178}