1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kew.routeheader.dao.impl;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.apache.commons.lang.exception.ExceptionUtils;
20 import org.apache.ojb.broker.OptimisticLockException;
21 import org.apache.ojb.broker.PersistenceBroker;
22 import org.apache.ojb.broker.accesslayer.LookupException;
23 import org.apache.ojb.broker.query.Criteria;
24 import org.apache.ojb.broker.query.QueryByCriteria;
25 import org.apache.ojb.broker.query.QueryFactory;
26 import org.apache.ojb.broker.query.ReportQueryByCriteria;
27 import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
28 import org.kuali.rice.core.api.util.RiceConstants;
29 import org.kuali.rice.core.framework.persistence.platform.DatabasePlatform;
30 import org.kuali.rice.kew.actionitem.ActionItem;
31 import org.kuali.rice.kew.actionlist.service.ActionListService;
32 import org.kuali.rice.kew.api.WorkflowRuntimeException;
33 import org.kuali.rice.kew.api.action.ActionRequestStatus;
34 import org.kuali.rice.kew.api.exception.LockingException;
35 import org.kuali.rice.kew.docsearch.SearchableAttributeValue;
36 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
37 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValueContent;
38 import org.kuali.rice.kew.routeheader.dao.DocumentRouteHeaderDAO;
39 import org.kuali.rice.kew.service.KEWServiceLocator;
40 import org.springframework.dao.CannotAcquireLockException;
41 import org.springmodules.orm.ojb.OjbFactoryUtils;
42 import org.springmodules.orm.ojb.PersistenceBrokerCallback;
43 import org.springmodules.orm.ojb.support.PersistenceBrokerDaoSupport;
44
45 import java.sql.Connection;
46 import java.sql.PreparedStatement;
47 import java.sql.ResultSet;
48 import java.sql.SQLException;
49 import java.sql.Statement;
50 import java.util.ArrayList;
51 import java.util.Collection;
52 import java.util.Iterator;
53 import java.util.Set;
54
55 public class DocumentRouteHeaderDAOOjbImpl extends PersistenceBrokerDaoSupport implements DocumentRouteHeaderDAO {
56
57 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DocumentRouteHeaderDAOOjbImpl.class);
58
59 public void saveRouteHeader(DocumentRouteHeaderValue routeHeader) {
60 if ( LOG.isDebugEnabled() ) {
61 LOG.debug( "About to Save the route Header: " + routeHeader.getDocumentId() + " / version=" + routeHeader.getVersionNumber() );
62 DocumentRouteHeaderValue currHeader = findRouteHeader(routeHeader.getDocumentId());
63 if ( currHeader != null ) {
64 LOG.debug( "Current Header Version: " + currHeader.getVersionNumber() );
65
66
67
68 } else {
69 LOG.debug( "Current Header: null" );
70 }
71 LOG.debug( ExceptionUtils.getStackTrace(new Throwable()) );
72 }
73 try {
74 getPersistenceBrokerTemplate().store(routeHeader);
75 routeHeader.getDocumentContent().setDocumentId(routeHeader.getDocumentId());
76 getPersistenceBrokerTemplate().store(routeHeader.getDocumentContent());
77 } catch ( RuntimeException ex ) {
78 if ( ex.getCause() instanceof OptimisticLockException ) {
79 LOG.error( "Optimistic Locking Exception saving document header or content. Offending object: " + ((OptimisticLockException)ex.getCause()).getSourceObject()
80 + "; DocumentId = " + routeHeader.getDocumentId() + " ; Version Number = " + routeHeader.getVersionNumber());
81 }
82 LOG.error( "Unable to save document header or content. Route Header: " + routeHeader, ex );
83 throw ex;
84 }
85 }
86
87 public DocumentRouteHeaderValueContent getContent(String documentId) {
88 Criteria crit = new Criteria();
89 crit.addEqualTo("documentId", documentId);
90 return (DocumentRouteHeaderValueContent)this.getPersistenceBrokerTemplate().getObjectByQuery(new QueryByCriteria(DocumentRouteHeaderValueContent.class, crit));
91 }
92
93 public void clearRouteHeaderSearchValues(String documentId) {
94 Criteria crit = new Criteria();
95 crit.addEqualTo("documentId", documentId);
96 QueryByCriteria query = new QueryByCriteria(SearchableAttributeValue.class, crit);
97 query.addOrderByAscending("searchableAttributeValueId");
98 Collection<SearchableAttributeValue> results = this.getPersistenceBrokerTemplate().getCollectionByQuery(query);
99 if (!results.isEmpty()) {
100 for (SearchableAttributeValue srchAttrVal: results) {
101 this.getPersistenceBrokerTemplate().delete(srchAttrVal);
102 }
103 }
104 }
105
106 public void lockRouteHeader(final String documentId, final boolean wait) {
107
108
109
110
111
112 this.getPersistenceBrokerTemplate().execute(new PersistenceBrokerCallback() {
113 public Object doInPersistenceBroker(PersistenceBroker broker) {
114 PreparedStatement statement = null;
115 try {
116 Connection connection = broker.serviceConnectionManager().getConnection();
117 String sql = getPlatform().getLockRouteHeaderQuerySQL(documentId, wait);
118 statement = connection.prepareStatement(sql);
119 statement.setString(1, documentId);
120 statement.execute();
121 return null;
122 } catch (SQLException e) {
123 throw new LockingException("Could not aquire lock on document, documentId=" + documentId, e);
124 } catch (LookupException e) {
125 throw new LockingException("Could not aquire lock on document, documentId=" + documentId, e);
126 } catch (CannotAcquireLockException e) {
127 throw new LockingException("Could not aquire lock on document, documentId=" + documentId, e);
128 } finally {
129 if (statement != null) {
130 try {
131 statement.close();
132 } catch (SQLException e) {
133 }
134 }
135 }
136 }
137 });
138
139 }
140
141 public DocumentRouteHeaderValue findRouteHeader(String documentId) {
142 return findRouteHeader(documentId, false);
143 }
144
145 public DocumentRouteHeaderValue findRouteHeader(String documentId, boolean clearCache) {
146 Criteria crit = new Criteria();
147 crit.addEqualTo("documentId", documentId);
148 if (clearCache) {
149 this.getPersistenceBrokerTemplate().clearCache();
150 }
151 return (DocumentRouteHeaderValue) this.getPersistenceBrokerTemplate().getObjectByQuery(new QueryByCriteria(DocumentRouteHeaderValue.class, crit));
152 }
153
154 public Collection<DocumentRouteHeaderValue> findRouteHeaders(Collection<String> documentIds) {
155 return findRouteHeaders(documentIds, false);
156 }
157
158 public Collection<DocumentRouteHeaderValue> findRouteHeaders(Collection<String> documentIds, boolean clearCache) {
159 if (documentIds == null || documentIds.isEmpty()) {
160 return null;
161 }
162 Criteria crit = new Criteria();
163 crit.addIn("documentId", documentIds);
164 if (clearCache) {
165 this.getPersistenceBrokerTemplate().clearCache();
166 }
167 return (Collection<DocumentRouteHeaderValue>) this.getPersistenceBrokerTemplate().getCollectionByQuery(new QueryByCriteria(DocumentRouteHeaderValue.class, crit));
168 }
169
170 public void deleteRouteHeader(DocumentRouteHeaderValue routeHeader) {
171
172 ActionListService actionListSrv = KEWServiceLocator.getActionListService();
173 Collection actionItems = actionListSrv.findByDocumentId(routeHeader.getDocumentId());
174 for (Iterator iter = actionItems.iterator(); iter.hasNext();) {
175 ActionItem actionItem = (ActionItem) iter.next();
176 try {
177 KEWServiceLocator.getUserOptionsService().saveRefreshUserOption(actionItem.getPrincipalId());
178 } catch (Exception e) {
179 LOG.error("error saving refreshUserOption", e);
180 }
181 }
182 this.getPersistenceBrokerTemplate().delete(routeHeader);
183 }
184
185 public String getNextDocumentId() {
186 return (String)this.getPersistenceBrokerTemplate().execute(new PersistenceBrokerCallback() {
187 public Object doInPersistenceBroker(PersistenceBroker broker) {
188 return getPlatform().getNextValSQL("KREW_DOC_HDR_S", broker).toString();
189 }
190 });
191 }
192
193 protected DatabasePlatform getPlatform() {
194 return (DatabasePlatform)GlobalResourceLoader.getService(RiceConstants.DB_PLATFORM);
195 }
196
197 public Collection<String> findPendingByResponsibilityIds(Set<String> responsibilityIds) {
198 Collection<String> documentIds = new ArrayList();
199 if (responsibilityIds.isEmpty()) {
200 return documentIds;
201 }
202 PersistenceBroker broker = null;
203 Connection conn = null;
204 Statement statement = null;
205 ResultSet rs = null;
206 try {
207 broker = getPersistenceBroker(false);
208 conn = broker.serviceConnectionManager().getConnection();
209 String respIds = "(";
210 int index = 0;
211 for (String responsibilityId : responsibilityIds) {
212 respIds += responsibilityId + (index == responsibilityIds.size()-1 ? "" : ",");
213 index++;
214 }
215 respIds += ")";
216 String query = "SELECT DISTINCT(doc_hdr_id) FROM KREW_ACTN_RQST_T "+
217 "WHERE (STAT_CD='" +
218 ActionRequestStatus.INITIALIZED.getCode()+
219 "' OR STAT_CD='"+
220 ActionRequestStatus.ACTIVATED.getCode()+
221 "') AND RSP_ID IN "+respIds;
222 LOG.debug("Query to find pending documents for requeue: " + query);
223 statement = conn.createStatement();
224 rs = statement.executeQuery(query);
225 while (rs.next()) {
226 documentIds.add(rs.getString(1));
227 }
228 } catch (SQLException sqle) {
229 LOG.error("SQLException: " + sqle.getMessage(), sqle);
230 throw new WorkflowRuntimeException(sqle);
231 } catch (LookupException le) {
232 LOG.error("LookupException: " + le.getMessage(), le);
233 throw new WorkflowRuntimeException(le);
234 } finally {
235 if (rs != null) {
236 try {
237 rs.close();
238 } catch (SQLException e) {
239 LOG.warn("Could not close result set.");
240 }
241 }
242 if (statement != null) {
243 try {
244 statement.close();
245 } catch (SQLException e) {
246 LOG.warn("Could not close statement.");
247 }
248 }
249 try {
250 if (broker != null) {
251 OjbFactoryUtils.releasePersistenceBroker(broker, this.getPersistenceBrokerTemplate().getPbKey());
252 }
253 } catch (Exception e) {
254 LOG.error("Failed closing connection: " + e.getMessage(), e);
255 }
256 }
257 return documentIds;
258 }
259
260 public boolean hasSearchableAttributeValue(String documentId, String searchableAttributeKey, String searchableAttributeValue) {
261 Criteria crit = new Criteria();
262 crit.addEqualTo("documentId", documentId);
263 crit.addEqualTo("searchableAttributeKey", searchableAttributeKey);
264 Collection results = getPersistenceBrokerTemplate().getCollectionByQuery(new QueryByCriteria(SearchableAttributeValue.class, crit));
265 if (!results.isEmpty()) {
266 for (Iterator iterator = results.iterator(); iterator.hasNext();) {
267 SearchableAttributeValue attribute = (SearchableAttributeValue) iterator.next();
268 if (StringUtils.equals(attribute.getSearchableAttributeDisplayValue(), searchableAttributeValue)) {
269 return true;
270 }
271 }
272 }
273 return false;
274 }
275
276 public String getApplicationIdByDocumentId(String documentId) {
277 if (documentId == null) {
278 throw new IllegalArgumentException("Encountered a null document ID.");
279 }
280 String applicationId = null;
281 PersistenceBroker broker = null;
282 Connection conn = null;
283 PreparedStatement statement = null;
284 ResultSet rs = null;
285 try {
286 broker = this.getPersistenceBroker(false);
287 conn = broker.serviceConnectionManager().getConnection();
288 String query = "SELECT DT.APPL_ID FROM KREW_DOC_TYP_T DT, KREW_DOC_HDR_T DH "+
289 "WHERE DH.DOC_TYP_ID=DT.DOC_TYP_ID AND "+
290 "DH.DOC_HDR_ID=?";
291 statement = conn.prepareStatement(query);
292 statement.setString(1, documentId);
293 rs = statement.executeQuery();
294 if (rs.next()) {
295 applicationId = rs.getString(1);
296 if (rs.wasNull()) {
297 applicationId = null;
298 }
299 }
300 } catch (SQLException sqle) {
301 LOG.error("SQLException: " + sqle.getMessage(), sqle);
302 throw new WorkflowRuntimeException(sqle);
303 } catch (LookupException le) {
304 LOG.error("LookupException: " + le.getMessage(), le);
305 throw new WorkflowRuntimeException(le);
306 } finally {
307 if (rs != null) {
308 try {
309 rs.close();
310 } catch (SQLException e) {
311 LOG.warn("Could not close result set.");
312 }
313 }
314 if (statement != null) {
315 try {
316 statement.close();
317 } catch (SQLException e) {
318 LOG.warn("Could not close statement.");
319 }
320 }
321 try {
322 if (broker != null) {
323 OjbFactoryUtils.releasePersistenceBroker(broker, this.getPersistenceBrokerTemplate().getPbKey());
324 }
325 } catch (Exception e) {
326 LOG.error("Failed closing connection: " + e.getMessage(), e);
327 }
328 }
329 return applicationId;
330 }
331
332 public String getDocumentStatus(String documentId) {
333 Criteria crit = new Criteria();
334 crit.addEqualTo("documentId", documentId);
335 ReportQueryByCriteria query = QueryFactory.newReportQuery(DocumentRouteHeaderValue.class, crit);
336 query.setAttributes(new String[] { "docRouteStatus" });
337 String status = null;
338 Iterator iter = getPersistenceBrokerTemplate().getReportQueryIteratorByQuery(query);
339 while (iter.hasNext()) {
340 Object[] row = (Object[]) iter.next();
341 status = (String)row[0];
342 }
343 return status;
344 }
345
346 public String getAppDocId(String documentId) {
347 Criteria crit = new Criteria();
348 crit.addEqualTo("documentId", documentId);
349 ReportQueryByCriteria query = QueryFactory.newReportQuery(DocumentRouteHeaderValue.class, crit);
350 query.setAttributes(new String[] { "appDocId" });
351 String appDocId = null;
352 Iterator iter = getPersistenceBrokerTemplate().getReportQueryIteratorByQuery(query);
353 while (iter.hasNext()) {
354 Object[] row = (Object[]) iter.next();
355 appDocId = (String)row[0];
356 }
357 return appDocId;
358 }
359
360 public void save(SearchableAttributeValue searchableAttributeValue) {
361 getPersistenceBrokerTemplate().store(searchableAttributeValue);
362 }
363
364 public Collection findByDocTypeAndAppId(String documentTypeName,
365 String appId) {
366 Collection documentIds = new ArrayList();
367
368 PersistenceBroker broker = null;
369 Connection conn = null;
370 ResultSet rs = null;
371 try {
372 broker = getPersistenceBroker(false);
373 conn = broker.serviceConnectionManager().getConnection();
374
375 String query =
376 "SELECT DISTINCT " +
377 " (docHdr.doc_hdr_id) " +
378 "FROM " +
379 " KREW_DOC_HDR_T docHdr, " +
380 " KREW_DOC_TYP_T docTyp " +
381 "WHERE " +
382 " docHdr.APP_DOC_ID = ? " +
383 " AND docHdr.DOC_TYP_ID = docTyp.DOC_TYP_ID " +
384 " AND docTyp.DOC_TYP_NM = ?";
385
386 LOG.debug("Query to find documents by app id: " + query);
387
388 PreparedStatement stmt = conn.prepareStatement(query);
389 stmt.setString(1, appId);
390 stmt.setString(2, documentTypeName);
391 rs = stmt.executeQuery();
392
393 while (rs.next()) {
394 documentIds.add(new String(rs.getString(1)));
395 }
396 rs.close();
397 } catch (SQLException sqle) {
398 LOG.error("SQLException: " + sqle.getMessage(), sqle);
399 throw new WorkflowRuntimeException(sqle);
400 } catch (LookupException le) {
401 LOG.error("LookupException: " + le.getMessage(), le);
402 throw new WorkflowRuntimeException(le);
403 } finally {
404 try {
405 if (broker != null) {
406 OjbFactoryUtils.releasePersistenceBroker(broker, this.getPersistenceBrokerTemplate().getPbKey());
407 }
408 } catch (Exception e) {
409 LOG.error("Failed closing connection: " + e.getMessage(), e);
410 }
411 }
412 return documentIds;
413 }
414
415 }