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 }