001/** 002 * Copyright 2005-2016 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 */ 016package org.kuali.rice.kew.engine.node.dao.impl; 017 018import org.kuali.rice.core.api.criteria.QueryByCriteria; 019import org.kuali.rice.kew.api.KEWPropertyConstants; 020import org.kuali.rice.kew.engine.node.NodeState; 021import org.kuali.rice.kew.engine.node.RouteNode; 022import org.kuali.rice.kew.engine.node.RouteNodeInstance; 023import org.kuali.rice.kew.engine.node.dao.RouteNodeDAO; 024import org.kuali.rice.kew.service.KEWServiceLocator; 025import org.kuali.rice.krad.data.DataObjectService; 026import org.springframework.beans.factory.annotation.Required; 027import org.springframework.dao.DataAccessException; 028import org.springframework.jdbc.core.JdbcTemplate; 029import org.springframework.jdbc.core.PreparedStatementCallback; 030import org.springframework.jdbc.core.PreparedStatementCreator; 031 032import javax.persistence.EntityManager; 033import javax.persistence.Query; 034import javax.sql.DataSource; 035import java.sql.Connection; 036import java.sql.PreparedStatement; 037import java.sql.ResultSet; 038import java.sql.SQLException; 039import java.util.ArrayList; 040import java.util.Iterator; 041import java.util.List; 042 043import static org.kuali.rice.core.api.criteria.PredicateFactory.equal; 044 045public class RouteNodeDAOJpa implements RouteNodeDAO { 046 047 private EntityManager entityManager; 048 private DataObjectService dataObjectService; 049 050 public static final String FIND_INITIAL_NODE_INSTANCES_NAME = "RouteNodeInstance.FindInitialNodeInstances"; 051 public static final String FIND_INITIAL_NODE_INSTANCES_QUERY = "select d.initialRouteNodeInstances from " 052 + "DocumentRouteHeaderValue d where d.documentId = :documentId"; 053 054 /** 055 * @return the entityManager 056 */ 057 public EntityManager getEntityManager() { 058 return this.entityManager; 059 } 060 061 /** 062 * @param entityManager the entityManager to set 063 */ 064 public void setEntityManager(EntityManager entityManager) { 065 this.entityManager = entityManager; 066 } 067 068 public RouteNodeInstance findRouteNodeInstanceById(String nodeInstanceId) { 069 QueryByCriteria.Builder queryByCriteria = QueryByCriteria.Builder.create().setPredicates( 070 equal(KEWPropertyConstants.ROUTE_NODE_INSTANCE_ID,nodeInstanceId) 071 ); 072 073 List<RouteNodeInstance> routeNodeInstances = getDataObjectService().findMatching( 074 RouteNodeInstance.class,queryByCriteria.build()).getResults(); 075 if(routeNodeInstances != null && routeNodeInstances.size() > 0){ 076 return routeNodeInstances.get(0); 077 } 078 return null; 079 } 080 081 @SuppressWarnings("unchecked") 082 public List<RouteNodeInstance> getActiveNodeInstances(String documentId) { 083 QueryByCriteria.Builder queryByCriteria = QueryByCriteria.Builder.create().setPredicates( 084 equal(KEWPropertyConstants.DOCUMENT_ID,documentId), 085 equal(KEWPropertyConstants.ACTIVE,true) 086 ); 087 return getDataObjectService().findMatching(RouteNodeInstance.class, 088 queryByCriteria.build()).getResults(); 089 } 090 091 private static final String CURRENT_ROUTE_NODE_NAMES_SQL = "SELECT rn.nm" + 092 " FROM krew_rte_node_t rn," + 093 " krew_rte_node_instn_t rni" + 094 " LEFT JOIN krew_rte_node_instn_lnk_t rnl" + 095 " ON rnl.from_rte_node_instn_id = rni.rte_node_instn_id" + 096 " WHERE rn.rte_node_id = rni.rte_node_id AND" + 097 " rni.doc_hdr_id = ? AND" + 098 " rnl.from_rte_node_instn_id IS NULL"; 099 100 @Override 101 public List<String> getCurrentRouteNodeNames(final String documentId) { 102 final DataSource dataSource = KEWServiceLocator.getDataSource(); 103 JdbcTemplate template = new JdbcTemplate(dataSource); 104 List<String> names = template.execute(new PreparedStatementCreator() { 105 public PreparedStatement createPreparedStatement(Connection connection) throws SQLException { 106 return connection.prepareStatement(CURRENT_ROUTE_NODE_NAMES_SQL); 107 } 108 }, new PreparedStatementCallback<List<String>>() { 109 public List<String> doInPreparedStatement( 110 PreparedStatement statement) throws SQLException, DataAccessException { 111 List<String> routeNodeNames = new ArrayList<String>(); 112 statement.setString(1, documentId); 113 ResultSet rs = statement.executeQuery(); 114 try { 115 while (rs.next()) { 116 String name = rs.getString("nm"); 117 routeNodeNames.add(name); 118 } 119 } finally { 120 if (rs != null) { 121 rs.close(); 122 } 123 } 124 return routeNodeNames; 125 } 126 } 127 ); 128 return names; 129 } 130 131 @Override 132 public List<String> getActiveRouteNodeNames(final String documentId) { 133 final DataSource dataSource = KEWServiceLocator.getDataSource(); 134 JdbcTemplate template = new JdbcTemplate(dataSource); 135 List<String> names = template.execute( 136 new PreparedStatementCreator() { 137 public PreparedStatement createPreparedStatement(Connection connection) throws SQLException { 138 PreparedStatement statement = connection.prepareStatement( 139 "SELECT rn.nm FROM krew_rte_node_t rn, krew_rte_node_instn_t rni WHERE rn.rte_node_id " 140 + "= rni.rte_node_id AND rni.doc_hdr_id = ? AND rni.actv_ind = ?"); 141 return statement; 142 } 143 }, 144 new PreparedStatementCallback<List<String>>() { 145 public List<String> doInPreparedStatement(PreparedStatement statement) throws SQLException, DataAccessException { 146 List<String> routeNodeNames = new ArrayList<String>(); 147 statement.setString(1, documentId); 148 statement.setBoolean(2, Boolean.TRUE); 149 ResultSet rs = statement.executeQuery(); 150 try { 151 while(rs.next()) { 152 String name = rs.getString("nm"); 153 routeNodeNames.add(name); 154 } 155 } finally { 156 if(rs != null) { 157 rs.close(); 158 } 159 } 160 return routeNodeNames; 161 } 162 }); 163 return names; 164 } 165 166 @SuppressWarnings("unchecked") 167 public List<RouteNodeInstance> getTerminalNodeInstances(String documentId) { 168 QueryByCriteria.Builder queryByCriteria = QueryByCriteria.Builder.create().setPredicates( 169 equal(KEWPropertyConstants.DOCUMENT_ID,documentId), 170 equal(KEWPropertyConstants.ACTIVE,false), 171 equal(KEWPropertyConstants.COMPLETE,true) 172 ); 173 174 //FIXME: Can we do this better using just the JPQL query? 175 List<RouteNodeInstance> terminalNodes = new ArrayList<RouteNodeInstance>(); 176 List<RouteNodeInstance> routeNodeInstances = getDataObjectService(). 177 findMatching(RouteNodeInstance.class,queryByCriteria.build()).getResults(); 178 for (RouteNodeInstance routeNodeInstance : routeNodeInstances) { 179 if (routeNodeInstance.getNextNodeInstances().isEmpty()) { 180 terminalNodes.add(routeNodeInstance); 181 } 182 } 183 return terminalNodes; 184 } 185 186 @Override 187 public List<String> getTerminalRouteNodeNames(final String documentId) { 188 final DataSource dataSource = KEWServiceLocator.getDataSource(); 189 JdbcTemplate template = new JdbcTemplate(dataSource); 190 List<String> names = template.execute(new PreparedStatementCreator() { 191 public PreparedStatement createPreparedStatement(Connection connection) throws SQLException { 192 PreparedStatement statement = connection.prepareStatement("SELECT rn.nm" + 193 " FROM krew_rte_node_t rn," + 194 " krew_rte_node_instn_t rni" + 195 " LEFT JOIN krew_rte_node_instn_lnk_t rnl" + 196 " ON rnl.from_rte_node_instn_id = rni.rte_node_instn_id" + 197 " WHERE rn.rte_node_id = rni.rte_node_id AND" + 198 " rni.doc_hdr_id = ? AND" + 199 " rni.actv_ind = ? AND" + 200 " rni.cmplt_ind = ? AND" + 201 " rnl.from_rte_node_instn_id IS NULL"); 202 return statement; 203 } 204 }, new PreparedStatementCallback<List<String>>() { 205 public List<String> doInPreparedStatement( 206 PreparedStatement statement) throws SQLException, DataAccessException { 207 List<String> routeNodeNames = new ArrayList<String>(); 208 statement.setString(1, documentId); 209 statement.setBoolean(2, Boolean.FALSE); 210 statement.setBoolean(3, Boolean.TRUE); 211 ResultSet rs = statement.executeQuery(); 212 try { 213 while (rs.next()) { 214 String name = rs.getString("nm"); 215 routeNodeNames.add(name); 216 } 217 } finally { 218 if (rs != null) { 219 rs.close(); 220 } 221 } 222 return routeNodeNames; 223 } 224 } 225 ); 226 return names; 227 } 228 229 public List getInitialNodeInstances(String documentId) { 230 //FIXME: Not sure this query is returning what it needs to 231 Query query = entityManager.createNamedQuery(FIND_INITIAL_NODE_INSTANCES_NAME); 232 query.setParameter(KEWPropertyConstants.DOCUMENT_ID, documentId); 233 return (List)query.getResultList(); 234 } 235 236 public NodeState findNodeState(Long nodeInstanceId, String key) { 237 QueryByCriteria.Builder queryByCriteria = QueryByCriteria.Builder.create().setPredicates( 238 equal(KEWPropertyConstants.ROUTE_NODE_INSTANCE_ID,nodeInstanceId.toString()), 239 equal(KEWPropertyConstants.KEY,key) 240 ); 241 242 List<NodeState> nodeStates = getDataObjectService().findMatching( 243 NodeState.class,queryByCriteria.build()).getResults(); 244 if(nodeStates != null && nodeStates.size() > 0){ 245 return nodeStates.get(0); 246 } 247 return null; 248 } 249 250 public RouteNode findRouteNodeByName(String documentTypeId, String name) { 251 QueryByCriteria.Builder queryByCriteria = QueryByCriteria.Builder.create().setPredicates( 252 equal(KEWPropertyConstants.DOCUMENT_TYPE_ID,documentTypeId), 253 equal(KEWPropertyConstants.ROUTE_NODE_NAME,name) 254 ); 255 List<RouteNode> routeNodes = getDataObjectService().findMatching( 256 RouteNode.class,queryByCriteria.build()).getResults(); 257 if(routeNodes != null && routeNodes.size() > 0){ 258 return routeNodes.get(0); 259 } 260 return null; 261 } 262 263 public List<RouteNode> findFinalApprovalRouteNodes(String documentTypeId) { 264 QueryByCriteria.Builder queryByCriteria = QueryByCriteria.Builder.create().setPredicates( 265 equal(KEWPropertyConstants.DOCUMENT_TYPE_ID,documentTypeId), 266 equal(KEWPropertyConstants.FINAL_APPROVAL,Boolean.TRUE) 267 ); 268 return getDataObjectService().findMatching(RouteNode.class,queryByCriteria.build()).getResults(); 269 } 270 271 public List findProcessNodeInstances(RouteNodeInstance process) { 272 QueryByCriteria.Builder queryByCriteria = QueryByCriteria.Builder.create().setPredicates( 273 equal(KEWPropertyConstants.PROCESS_ID,process.getRouteNodeInstanceId()) 274 ); 275 return getDataObjectService().findMatching(RouteNodeInstance.class,queryByCriteria.build()).getResults(); 276 } 277 278 public List findRouteNodeInstances(String documentId) { 279 QueryByCriteria.Builder queryByCriteria = QueryByCriteria.Builder.create().setPredicates( 280 equal(KEWPropertyConstants.DOCUMENT_ID,documentId) 281 ); 282 return getDataObjectService().findMatching(RouteNodeInstance.class,queryByCriteria.build()).getResults(); 283 } 284 285 public void deleteLinksToPreNodeInstances(RouteNodeInstance routeNodeInstance) { 286 List<RouteNodeInstance> preNodeInstances = routeNodeInstance.getPreviousNodeInstances(); 287 for (Iterator<RouteNodeInstance> preNodeInstanceIter = preNodeInstances.iterator(); preNodeInstanceIter.hasNext();) { 288 RouteNodeInstance preNodeInstance = (RouteNodeInstance) preNodeInstanceIter.next(); 289 List<RouteNodeInstance> nextInstances = preNodeInstance.getNextNodeInstances(); 290 nextInstances.remove(routeNodeInstance); 291 getEntityManager().merge(preNodeInstance); 292 } 293 } 294 295 public void deleteRouteNodeInstancesHereAfter(RouteNodeInstance routeNodeInstance) { 296 RouteNodeInstance rnInstance = findRouteNodeInstanceById(routeNodeInstance.getRouteNodeInstanceId()); 297 entityManager.remove(rnInstance); 298 } 299 300 public void deleteNodeStateById(Long nodeStateId) { 301 QueryByCriteria.Builder queryByCriteria = QueryByCriteria.Builder.create().setPredicates( 302 equal(KEWPropertyConstants.ROUTE_NODE_STATE_ID,nodeStateId) 303 ); 304 List<NodeState> nodeStates = getDataObjectService().findMatching( 305 NodeState.class,queryByCriteria.build()).getResults(); 306 NodeState nodeState = null; 307 if(nodeStates != null && nodeStates.size() > 0){ 308 nodeState = nodeStates.get(0); 309 } 310 getDataObjectService().delete(nodeState); 311 } 312 313 public void deleteNodeStates(List statesToBeDeleted) { 314 for (Iterator stateToBeDeletedIter = statesToBeDeleted.iterator(); stateToBeDeletedIter.hasNext();) { 315 Long stateId = (Long) stateToBeDeletedIter.next(); 316 deleteNodeStateById(stateId); 317 } 318 } 319 320 321 public DataObjectService getDataObjectService() { 322 return dataObjectService; 323 } 324 325 @Required 326 public void setDataObjectService(DataObjectService dataObjectService) { 327 this.dataObjectService = dataObjectService; 328 } 329 330 331}