001 /**
002 * Copyright 2005-2011 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 */
016 package org.kuali.rice.kew.routeheader.dao.impl;
017
018 import org.apache.commons.lang.StringUtils;
019 import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
020 import org.kuali.rice.core.api.util.RiceConstants;
021 import org.kuali.rice.core.framework.persistence.jpa.OrmUtils;
022 import org.kuali.rice.core.framework.persistence.jpa.criteria.Criteria;
023 import org.kuali.rice.core.framework.persistence.jpa.criteria.QueryByCriteria;
024 import org.kuali.rice.core.framework.persistence.platform.DatabasePlatform;
025 import org.kuali.rice.kew.actionitem.ActionItem;
026 import org.kuali.rice.kew.actionlist.service.ActionListService;
027 import org.kuali.rice.kew.api.WorkflowRuntimeException;
028 import org.kuali.rice.kew.api.action.ActionRequestStatus;
029 import org.kuali.rice.kew.docsearch.SearchableAttributeValue;
030 import org.kuali.rice.kew.api.exception.LockingException;
031 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
032 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValueContent;
033 import org.kuali.rice.kew.routeheader.dao.DocumentRouteHeaderDAO;
034 import org.kuali.rice.kew.service.KEWServiceLocator;
035
036 import javax.persistence.EntityManager;
037 import javax.persistence.EntityNotFoundException;
038 import javax.persistence.PersistenceContext;
039 import javax.persistence.Query;
040 import java.math.BigDecimal;
041 import java.util.ArrayList;
042 import java.util.Collection;
043 import java.util.Iterator;
044 import java.util.List;
045 import java.util.Set;
046
047
048 public class DocumentRouteHeaderDAOJpaImpl implements DocumentRouteHeaderDAO {
049
050 @PersistenceContext(unitName="kew-unit")
051 private EntityManager entityManager;
052 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DocumentRouteHeaderDAOJpaImpl.class);
053
054
055 /**
056 * @return the entityManager
057 */
058 public EntityManager getEntityManager() {
059 return this.entityManager;
060 }
061
062 /**
063 * @param entityManager the entityManager to set
064 */
065 public void setEntityManager(EntityManager entityManager) {
066 this.entityManager = entityManager;
067 }
068
069 public void saveRouteHeader(DocumentRouteHeaderValue routeHeader) {
070 DocumentRouteHeaderValueContent documentContent = routeHeader.getDocumentContent();
071 // List<SearchableAttributeValue> searchableAttributes = routeHeader.getSearchableAttributeValues();
072
073 if (routeHeader.getDocumentId() == null){
074 entityManager.persist(routeHeader);
075 } else {
076 OrmUtils.merge(entityManager, routeHeader);
077 }
078
079 //Save document content (document content retrieved via a service call)
080 documentContent.setDocumentId(routeHeader.getDocumentId());
081 entityManager.merge(documentContent);
082
083 /*
084 //Save searchable attributes
085 for (SearchableAttributeValue searchableAttributeValue:searchableAttributes){
086 searchableAttributeValue.setDocumentId(routeHeader.getDocumentId());
087 if (searchableAttributeValue.getSearchableAttributeValueId() == null){
088 entityManager.persist(searchableAttributeValue);
089 } else {
090 entityManager.merge(searchableAttributeValue);
091 }
092 }
093 */
094 }
095
096 public DocumentRouteHeaderValueContent getContent(String documentId) {
097 Query query = entityManager.createNamedQuery("DocumentRouteHeaderValueContent.FindByDocumentId");
098 query.setParameter("documentId", documentId);
099 return (DocumentRouteHeaderValueContent)query.getSingleResult();
100 }
101
102 public void clearRouteHeaderSearchValues(String documentId) {
103 List<SearchableAttributeValue> searchableAttributeValues = findSearchableAttributeValues(documentId);
104 for (SearchableAttributeValue searchableAttributeValue:searchableAttributeValues){
105 entityManager.remove(searchableAttributeValue);
106 }
107 }
108
109 private List<SearchableAttributeValue> findSearchableAttributeValues(String documentId){
110 List<SearchableAttributeValue> searchableAttributeValues = new ArrayList<SearchableAttributeValue>();
111
112 for (int i=1;i<=4; i++){
113 String namedQuery = "";
114 switch (i) {
115 case 1: namedQuery = "SearchableAttributeFloatValue.FindByDocumentId"; break;
116 case 2: namedQuery = "SearchableAttributeDateTimeValue.FindByDocumentId"; break;
117 case 3: namedQuery = "SearchableAttributeLongValue.FindByDocumentId";break;
118 case 4: namedQuery = "SearchableAttributeStringValue.FindByDocumentId"; break;
119 }
120 Query query = entityManager.createNamedQuery(namedQuery);
121 query.setParameter("documentId", documentId);
122 searchableAttributeValues.addAll(query.getResultList());
123 }
124
125 return searchableAttributeValues;
126 }
127
128 public void lockRouteHeader(final String documentId, final boolean wait) {
129 String sql = getPlatform().getLockRouteHeaderQuerySQL(documentId, wait);
130 try{
131 Query query = entityManager.createNativeQuery(sql);
132 query.setParameter(1, documentId);
133 query.getSingleResult();
134 } catch (Exception e){
135 //FIXME: Should this check for hibernate LockAcquisitionException
136 throw new LockingException("Could not aquire lock on document, documentId=" + documentId, e);
137 }
138 }
139
140 public DocumentRouteHeaderValue findRouteHeader(String documentId) {
141 return findRouteHeader(documentId, false);
142 }
143
144 public DocumentRouteHeaderValue findRouteHeader(String documentId, boolean clearCache) {
145 Query query = entityManager.createNamedQuery("DocumentRouteHeaderValue.FindByDocumentId");
146 query.setParameter("documentId", documentId);
147
148 //TODO: What cache do we clear when using JPA
149 if (clearCache) {
150 //this.getPersistenceBrokerTemplate().clearCache();
151 }
152
153 DocumentRouteHeaderValue routeHeader = (DocumentRouteHeaderValue) query.getSingleResult();
154 // routeHeader.setSearchableAttributeValues(findSearchableAttributeValues(documentId));
155 return routeHeader;
156 }
157
158 public Collection<DocumentRouteHeaderValue> findRouteHeaders(Collection<String> documentIds) {
159 return findRouteHeaders(documentIds, false);
160 }
161
162 public Collection<DocumentRouteHeaderValue> findRouteHeaders(Collection<String> documentIds, boolean clearCache) {
163 if (documentIds == null || documentIds.isEmpty()) {
164 return null;
165 }
166 Criteria crit = new Criteria(DocumentRouteHeaderValue.class.getName());
167 crit.in("documentId", documentIds);
168
169 //TODO: What cache do we clear when using JPA
170 if (clearCache) {
171 //this.getPersistenceBrokerTemplate().clearCache();
172 }
173
174 return new QueryByCriteria(entityManager, crit).toQuery().getResultList();
175 }
176
177 public void deleteRouteHeader(DocumentRouteHeaderValue routeHeader) {
178 // need to clear action list cache for users who have this item in their action list
179 ActionListService actionListSrv = KEWServiceLocator.getActionListService();
180 Collection actionItems = actionListSrv.findByDocumentId(routeHeader.getDocumentId());
181 for (Iterator iter = actionItems.iterator(); iter.hasNext();) {
182 ActionItem actionItem = (ActionItem) iter.next();
183 try {
184 KEWServiceLocator.getUserOptionsService().saveRefreshUserOption(actionItem.getPrincipalId());
185 } catch (Exception e) {
186 LOG.error("error saving refreshUserOption", e);
187 }
188 }
189
190 DocumentRouteHeaderValue attachedRouteHeader = findRouteHeader(routeHeader.getDocumentId());
191 entityManager.remove(attachedRouteHeader);
192 }
193
194 public String getNextDocumentId() {
195 Long nextDocumentId = getPlatform().getNextValSQL("KREW_DOC_HDR_S", entityManager);
196 return nextDocumentId.toString();
197 }
198
199 protected DatabasePlatform getPlatform() {
200 return (DatabasePlatform) GlobalResourceLoader.getService(RiceConstants.DB_PLATFORM);
201 }
202
203 @Override
204 public Collection<String> findPendingByResponsibilityIds(Set<String> responsibilityIds) {
205
206 if (responsibilityIds.isEmpty()) {
207 return new ArrayList();
208 }
209
210 String respIds = "(";
211 int index = 0;
212 for (String responsibilityId : responsibilityIds) {
213 respIds += responsibilityId + (index == responsibilityIds.size()-1 ? "" : ",");
214 }
215 respIds += ")";
216
217 String query = "SELECT DISTINCT(doc_hdr_id) FROM KREW_ACTN_RQST_T "+
218 "WHERE (STAT_CD='" +
219 ActionRequestStatus.INITIALIZED.getCode()+
220 "' OR STAT_CD='"+
221 ActionRequestStatus.ACTIVATED.getCode()+
222 "') AND RSP_ID IN "+respIds;
223
224 LOG.debug("Query to find pending documents for requeue: " + query);
225
226 List<String> idList = new ArrayList<String>();
227 for (Object tempId : entityManager.createNativeQuery(query).getResultList()) {
228 idList.add(((String) tempId));
229 }
230
231 return idList; //(List<Long>)entityManager.createNativeQuery(query).getResultList();
232 }
233
234 public boolean hasSearchableAttributeValue(String documentId, String searchableAttributeKey, String searchableAttributeValue) {
235 return hasSearchableAttributeValue(documentId, searchableAttributeKey, searchableAttributeValue, "SearchableAttributeDateTimeValue.FindByKey")
236 || hasSearchableAttributeValue(documentId, searchableAttributeKey, searchableAttributeValue, "SearchableAttributeStringValue.FindByKey")
237 || hasSearchableAttributeValue(documentId, searchableAttributeKey, searchableAttributeValue, "SearchableAttributeLongValue.FindByKey")
238 || hasSearchableAttributeValue(documentId, searchableAttributeKey, searchableAttributeValue, "SearchableAttributeFloatValue.FindByKey");
239 }
240
241 private boolean hasSearchableAttributeValue(String documentId, String searchableAttributeKey, String searchableAttributeValue, String namedQuery) {
242 Query query = entityManager.createNamedQuery(namedQuery);
243 query.setParameter("documentId", documentId);
244 query.setParameter("searchableAttributeKey", searchableAttributeKey);
245 Collection results = query.getResultList();
246 if (!results.isEmpty()) {
247 for (Iterator iterator = results.iterator(); iterator.hasNext();) {
248 SearchableAttributeValue attribute = (SearchableAttributeValue) iterator.next();
249 if (StringUtils.equals(attribute.getSearchableAttributeDisplayValue(), searchableAttributeValue)) {
250 return true;
251 }
252 }
253 }
254 return false;
255 }
256
257 public String getApplicationIdByDocumentId(String documentId) {
258 if (documentId == null) {
259 throw new IllegalArgumentException("Encountered a null document ID.");
260 }
261
262 String applicationId = null;
263
264 try {
265 String sql = "SELECT DT.APPL_ID FROM KREW_DOC_TYP_T DT, KREW_DOC_HDR_T DH "+
266 "WHERE DH.DOC_TYP_ID=DT.DOC_TYP_ID AND "+
267 "DH.DOC_HDR_ID=?";
268
269 Query query = entityManager.createNativeQuery(sql);
270 query.setParameter(1, documentId);
271
272 applicationId = (String)query.getSingleResult();
273 } catch (EntityNotFoundException enfe) {
274 throw new WorkflowRuntimeException(enfe.getMessage());
275 }
276
277 return applicationId;
278 }
279
280 public String getDocumentStatus(String documentId) {
281 DocumentRouteHeaderValue document = findRouteHeader(documentId);
282
283 return document.getDocRouteStatus();
284 }
285
286 public String getAppDocId(String documentId) {
287 Query query = entityManager.createNamedQuery("DocumentRouteHeaderValue.GetAppDocId");
288 query.setParameter("documentId", documentId);
289 return (String) query.getSingleResult();
290 }
291
292 public void save(SearchableAttributeValue searchableAttributeValue) {
293 if (searchableAttributeValue.getSearchableAttributeValueId() == null){
294 entityManager.persist(searchableAttributeValue);
295 } else {
296 entityManager.merge(searchableAttributeValue);
297 }
298 }
299
300 public Collection findByDocTypeAndAppId(String documentTypeName,
301 String appId) {
302 try {
303 String sql =
304 "SELECT DISTINCT " +
305 " (docHdr.doc_hdr_id) " +
306 "FROM " +
307 " KREW_DOC_HDR_T docHdr, " +
308 " KREW_DOC_TYP_T docTyp " +
309 "WHERE " +
310 " docHdr.APP_DOC_ID = ? " +
311 " AND docHdr.DOC_TYP_ID = docTyp.DOC_TYP_ID " +
312 " AND docTyp.DOC_TYP_NM = ?";
313
314 Query query = entityManager.createNativeQuery(sql);
315 query.setParameter(1, appId);
316 query.setParameter(2, documentTypeName);
317 Collection<Long> idCollection = new ArrayList<Long>();
318 for (Object tempId : query.getResultList()) {
319 idCollection.add(((BigDecimal)tempId).longValueExact());
320 }
321 return idCollection;
322 } catch (EntityNotFoundException enfe) {
323 throw new WorkflowRuntimeException(enfe.getMessage());
324 }
325 }
326
327
328 }