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