View Javadoc

1   /**
2    * Copyright 2005-2013 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
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.List;
54  import java.util.Set;
55  
56  public class DocumentRouteHeaderDAOOjbImpl extends PersistenceBrokerDaoSupport implements DocumentRouteHeaderDAO {
57  
58      private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DocumentRouteHeaderDAOOjbImpl.class);
59  
60      public void saveRouteHeader(DocumentRouteHeaderValue routeHeader) {
61          if ( LOG.isDebugEnabled() ) {
62              LOG.debug( "About to Save the route Header: " + routeHeader.getDocumentId() + " / version=" + routeHeader.getVersionNumber() );
63              DocumentRouteHeaderValue currHeader = findRouteHeader(routeHeader.getDocumentId());
64              if ( currHeader != null ) {
65                  LOG.debug( "Current Header Version: " + currHeader.getVersionNumber() );
66  //                for ( SearchableAttributeValue s : currHeader.get() ) {
67  //                    LOG.debug( "SA: " + s.getSearchableAttributeValueId() + " / version=" + s.get )
68  //                }
69              } else {
70                  LOG.debug( "Current Header: null" );
71              }
72              LOG.debug( ExceptionUtils.getStackTrace(new Throwable()) );
73          }
74          try {
75              getPersistenceBrokerTemplate().store(routeHeader);
76              routeHeader.getDocumentContent().setDocumentId(routeHeader.getDocumentId());
77              getPersistenceBrokerTemplate().store(routeHeader.getDocumentContent());
78          } catch ( RuntimeException ex ) {
79              if ( ex.getCause() instanceof OptimisticLockException ) {
80                   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              LOG.error( "Unable to save document header or content. Route Header: " + routeHeader, ex );
84              throw ex;
85          }
86      }
87  
88      public DocumentRouteHeaderValueContent getContent(String documentId) {
89      	Criteria crit = new Criteria();
90          crit.addEqualTo("documentId", documentId);
91          return (DocumentRouteHeaderValueContent)this.getPersistenceBrokerTemplate().getObjectByQuery(new QueryByCriteria(DocumentRouteHeaderValueContent.class, crit));
92      }
93  
94      public void clearRouteHeaderSearchValues(String documentId) {
95          Criteria crit = new Criteria();
96          crit.addEqualTo("documentId", documentId);
97          QueryByCriteria query = new QueryByCriteria(SearchableAttributeValue.class, crit);
98          query.addOrderByAscending("searchableAttributeValueId");
99          Collection<SearchableAttributeValue> results = this.getPersistenceBrokerTemplate().getCollectionByQuery(query);
100         if (!results.isEmpty()) {
101             for (SearchableAttributeValue srchAttrVal: results) {
102                 this.getPersistenceBrokerTemplate().delete(srchAttrVal);
103             }
104         }
105     }
106 
107     public Collection<SearchableAttributeValue> findSearchableAttributeValues(String documentId) {
108         Criteria crit = new Criteria();
109         crit.addEqualTo("documentId", documentId);
110         QueryByCriteria query = new QueryByCriteria(SearchableAttributeValue.class, crit);
111         query.addOrderByAscending("searchableAttributeValueId");
112         return this.getPersistenceBrokerTemplate().getCollectionByQuery(query);
113     }
114 
115     public void lockRouteHeader(final String documentId, final boolean wait) {
116 
117         /*
118          * String sql = (wait ? LOCK_SQL_WAIT : LOCK_SQL_NOWAIT); try { getJdbcTemplate().update(sql, new Object[] { documentId }); } catch (CannotAcquireLockException e) { throw new LockingException("Could not aquire lock on document, documentId=" + documentId, e); }
119          */
120 
121     	this.getPersistenceBrokerTemplate().execute(new PersistenceBrokerCallback() {
122             public Object doInPersistenceBroker(PersistenceBroker broker) {
123                 PreparedStatement statement = null;
124                 try {
125                     Connection connection = broker.serviceConnectionManager().getConnection();
126                     String sql = getPlatform().getLockRouteHeaderQuerySQL(documentId, wait);
127                     statement = connection.prepareStatement(sql);
128                     statement.setString(1, documentId);
129                     statement.execute();
130                     return null;
131                 } catch (SQLException e) {
132                     throw new LockingException("Could not aquire lock on document, documentId=" + documentId, e);
133                 } catch (LookupException e) {
134                     throw new LockingException("Could not aquire lock on document, documentId=" + documentId, e);
135                 } catch (CannotAcquireLockException e) {
136                     throw new LockingException("Could not aquire lock on document, documentId=" + documentId, e);
137                 } finally {
138                     if (statement != null) {
139                         try {
140                             statement.close();
141                         } catch (SQLException e) {
142                         }
143                     }
144                 }
145             }
146         });
147 
148     }
149 
150     public DocumentRouteHeaderValue findRouteHeader(String documentId) {
151     	return findRouteHeader(documentId, false);
152     }
153 
154     public DocumentRouteHeaderValue findRouteHeader(String documentId, boolean clearCache) {
155         Criteria crit = new Criteria();
156         crit.addEqualTo("documentId", documentId);
157         if (clearCache) {
158         	this.getPersistenceBrokerTemplate().clearCache();
159         }
160         return (DocumentRouteHeaderValue) this.getPersistenceBrokerTemplate().getObjectByQuery(new QueryByCriteria(DocumentRouteHeaderValue.class, crit));
161     }
162 
163     public Collection<DocumentRouteHeaderValue> findRouteHeaders(Collection<String> documentIds) {
164     	return findRouteHeaders(documentIds, false);
165     }
166     
167     public Collection<DocumentRouteHeaderValue> findRouteHeaders(Collection<String> documentIds, boolean clearCache) {
168     	if (documentIds == null || documentIds.isEmpty()) {
169     		return null;
170     	}
171     	Criteria crit = new Criteria();
172     	crit.addIn("documentId", documentIds);
173     	if (clearCache) {
174         	this.getPersistenceBrokerTemplate().clearCache();
175         }
176     	return (Collection<DocumentRouteHeaderValue>) this.getPersistenceBrokerTemplate().getCollectionByQuery(new QueryByCriteria(DocumentRouteHeaderValue.class, crit));
177     }
178 
179     public void deleteRouteHeader(DocumentRouteHeaderValue routeHeader) {
180     	this.getPersistenceBrokerTemplate().delete(routeHeader);
181     }
182 
183     public String getNextDocumentId() {
184         return (String)this.getPersistenceBrokerTemplate().execute(new PersistenceBrokerCallback() {
185             public Object doInPersistenceBroker(PersistenceBroker broker) {
186             	return getPlatform().getNextValSQL("KREW_DOC_HDR_S", broker).toString();
187                     }
188         });
189     }
190 
191     protected DatabasePlatform getPlatform() {
192     	return (DatabasePlatform)GlobalResourceLoader.getService(RiceConstants.DB_PLATFORM);
193     }
194 
195     public Collection<String> findPendingByResponsibilityIds(Set<String> responsibilityIds) {
196         Collection<String> documentIds = new ArrayList();
197         if (responsibilityIds.isEmpty()) {
198             return documentIds;
199         }
200         PersistenceBroker broker = null;
201         Connection conn = null;
202         Statement statement = null;
203         ResultSet rs = null;
204         try {
205             broker = getPersistenceBroker(false);
206             conn = broker.serviceConnectionManager().getConnection();
207             String respIds = "('";
208             int index = 0;
209             for (String responsibilityId : responsibilityIds) {
210                 respIds += responsibilityId + (index == responsibilityIds.size()-1 ? "" : "','");
211                 index++;
212             }
213             respIds += "')";
214             String query = "SELECT DISTINCT(doc_hdr_id) FROM KREW_ACTN_RQST_T "+
215             	"WHERE (STAT_CD='" +
216             	ActionRequestStatus.INITIALIZED.getCode()+
217             	"' OR STAT_CD='"+
218             	ActionRequestStatus.ACTIVATED.getCode()+
219             	"') AND RSP_ID IN "+respIds;
220             LOG.debug("Query to find pending documents for requeue: " + query);
221             statement = conn.createStatement();
222             rs = statement.executeQuery(query);
223             while (rs.next()) {
224             	documentIds.add(rs.getString(1));
225             }
226         } catch (SQLException sqle) {
227             LOG.error("SQLException: " + sqle.getMessage(), sqle);
228             throw new WorkflowRuntimeException(sqle);
229         } catch (LookupException le) {
230             LOG.error("LookupException: " + le.getMessage(), le);
231             throw new WorkflowRuntimeException(le);
232         } finally {
233         	if (rs != null) {
234                 try {
235                     rs.close();
236                 } catch (SQLException e) {
237                     LOG.warn("Could not close result set.");
238                 }
239             }
240             if (statement != null) {
241                 try {
242                     statement.close();
243                 } catch (SQLException e) {
244                     LOG.warn("Could not close statement.");
245                 }
246             }
247             try {
248                 if (broker != null) {
249                     OjbFactoryUtils.releasePersistenceBroker(broker, this.getPersistenceBrokerTemplate().getPbKey());
250                 }
251             } catch (Exception e) {
252                 LOG.error("Failed closing connection: " + e.getMessage(), e);
253             }
254         }
255         return documentIds;
256     }
257 
258     public boolean hasSearchableAttributeValue(String documentId, String searchableAttributeKey, String searchableAttributeValue) {
259     	Criteria crit = new Criteria();
260         crit.addEqualTo("documentId", documentId);
261         crit.addEqualTo("searchableAttributeKey", searchableAttributeKey);
262         Collection results = getPersistenceBrokerTemplate().getCollectionByQuery(new QueryByCriteria(SearchableAttributeValue.class, crit));
263         if (!results.isEmpty()) {
264             for (Iterator iterator = results.iterator(); iterator.hasNext();) {
265                 SearchableAttributeValue attribute = (SearchableAttributeValue) iterator.next();
266                 if (StringUtils.equals(attribute.getSearchableAttributeDisplayValue(), searchableAttributeValue)) {
267                     return true;
268                 }
269             }
270         }
271         return false;
272     }
273 
274     public String getApplicationIdByDocumentId(String documentId) {
275     	if (documentId == null) {
276     		throw new IllegalArgumentException("Encountered a null document ID.");
277     	}
278     	String applicationId = null;
279         PersistenceBroker broker = null;
280         Connection conn = null;
281         PreparedStatement statement = null;
282         ResultSet rs = null;
283         try {
284             broker = this.getPersistenceBroker(false);
285             conn = broker.serviceConnectionManager().getConnection();
286             String query = "SELECT DT.APPL_ID FROM KREW_DOC_TYP_T DT, KREW_DOC_HDR_T DH "+
287             	"WHERE DH.DOC_TYP_ID=DT.DOC_TYP_ID AND "+
288             	"DH.DOC_HDR_ID=?";
289             statement = conn.prepareStatement(query);
290             statement.setString(1, documentId);
291             rs = statement.executeQuery();
292             if (rs.next()) {
293             	applicationId = rs.getString(1);
294                 if (rs.wasNull()) {
295                 	applicationId = null;
296                 }
297             }
298         } catch (SQLException sqle) {
299             LOG.error("SQLException: " + sqle.getMessage(), sqle);
300             throw new WorkflowRuntimeException(sqle);
301         } catch (LookupException le) {
302             LOG.error("LookupException: " + le.getMessage(), le);
303             throw new WorkflowRuntimeException(le);
304         } finally {
305         	if (rs != null) {
306                 try {
307                     rs.close();
308                 } catch (SQLException e) {
309                     LOG.warn("Could not close result set.");
310                 }
311             }
312             if (statement != null) {
313                 try {
314                     statement.close();
315                 } catch (SQLException e) {
316                     LOG.warn("Could not close statement.");
317                 }
318             }
319             try {
320                 if (broker != null) {
321                     OjbFactoryUtils.releasePersistenceBroker(broker, this.getPersistenceBrokerTemplate().getPbKey());
322                 }
323             } catch (Exception e) {
324                 LOG.error("Failed closing connection: " + e.getMessage(), e);
325             }
326         }
327         return applicationId;
328     }
329 
330     public String getDocumentStatus(String documentId) {
331 	Criteria crit = new Criteria();
332     	crit.addEqualTo("documentId", documentId);
333     	ReportQueryByCriteria query = QueryFactory.newReportQuery(DocumentRouteHeaderValue.class, crit);
334     	query.setAttributes(new String[] { "docRouteStatus" });
335     	String status = null;
336     	Iterator iter = getPersistenceBrokerTemplate().getReportQueryIteratorByQuery(query);
337     	while (iter.hasNext()) {
338     	    Object[] row = (Object[]) iter.next();
339     	    status = (String)row[0];
340     	}
341     	return status;
342     }
343     
344     public String getAppDocId(String documentId) {
345  	 	Criteria crit = new Criteria();
346  	 	crit.addEqualTo("documentId", documentId);
347  	 	ReportQueryByCriteria query = QueryFactory.newReportQuery(DocumentRouteHeaderValue.class, crit);
348  	 	query.setAttributes(new String[] { "appDocId" });
349  	 	String appDocId = null;
350  	 	Iterator iter = getPersistenceBrokerTemplate().getReportQueryIteratorByQuery(query);
351  	 	while (iter.hasNext()) {
352  	 		Object[] row = (Object[]) iter.next();
353  	 		appDocId = (String)row[0];
354  	 	}
355  	 	return appDocId;
356  	 }
357     
358     public void save(SearchableAttributeValue searchableAttributeValue) {
359     	getPersistenceBrokerTemplate().store(searchableAttributeValue);
360     }
361 
362 	public Collection findByDocTypeAndAppId(String documentTypeName,
363 			String appId) {
364         Collection documentIds = new ArrayList();
365 
366         PersistenceBroker broker = null;
367         Connection conn = null;
368         ResultSet rs = null;
369         try {
370             broker = getPersistenceBroker(false);
371             conn = broker.serviceConnectionManager().getConnection();
372 
373             String query = 
374             	 	"SELECT DISTINCT " +
375             		"    (docHdr.doc_hdr_id) " +
376             		"FROM " +
377             		"    KREW_DOC_HDR_T docHdr, " +
378             		"    KREW_DOC_TYP_T docTyp " +
379             		"WHERE " +
380             		"    docHdr.APP_DOC_ID     = ? " +
381             		"    AND docHdr.DOC_TYP_ID = docTyp.DOC_TYP_ID " +
382             		"    AND docTyp.DOC_TYP_NM = ?";
383             
384             LOG.debug("Query to find documents by app id: " + query);
385             
386             PreparedStatement stmt = conn.prepareStatement(query);
387             stmt.setString(1, appId);
388             stmt.setString(2, documentTypeName);
389             rs = stmt.executeQuery();
390             
391             while (rs.next()) {
392             	documentIds.add(new String(rs.getString(1)));
393             }
394             rs.close();
395         } catch (SQLException sqle) {
396             LOG.error("SQLException: " + sqle.getMessage(), sqle);
397             throw new WorkflowRuntimeException(sqle);
398         } catch (LookupException le) {
399             LOG.error("LookupException: " + le.getMessage(), le);
400             throw new WorkflowRuntimeException(le);
401         } finally {
402             try {
403                 if (broker != null) {
404                     OjbFactoryUtils.releasePersistenceBroker(broker, this.getPersistenceBrokerTemplate().getPbKey());
405                 }
406             } catch (Exception e) {
407                 LOG.error("Failed closing connection: " + e.getMessage(), e);
408             }
409         }
410         return documentIds;
411 	}
412 
413 }