View Javadoc
1   /**
2    * Copyright 2005-2016 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.engine.node.dao.impl;
17  
18  import java.sql.Connection;
19  import java.sql.PreparedStatement;
20  import java.sql.ResultSet;
21  import java.sql.SQLException;
22  import java.util.ArrayList;
23  import java.util.Iterator;
24  import java.util.List;
25  
26  import javax.persistence.EntityManager;
27  import javax.persistence.PersistenceContext;
28  import javax.persistence.Query;
29  import javax.sql.DataSource;
30  
31  import org.kuali.rice.core.framework.persistence.jpa.OrmUtils;
32  import org.kuali.rice.kew.api.KEWPropertyConstants;
33  import org.kuali.rice.kew.engine.node.Branch;
34  import org.kuali.rice.kew.engine.node.NodeState;
35  import org.kuali.rice.kew.engine.node.RouteNode;
36  import org.kuali.rice.kew.engine.node.RouteNodeInstance;
37  import org.kuali.rice.kew.engine.node.dao.RouteNodeDAO;
38  import org.kuali.rice.kew.service.KEWServiceLocator;
39  import org.springframework.dao.DataAccessException;
40  import org.springframework.jdbc.core.JdbcTemplate;
41  import org.springframework.jdbc.core.PreparedStatementCallback;
42  import org.springframework.jdbc.core.PreparedStatementCreator;
43  
44  public class RouteNodeDAOJpaImpl implements RouteNodeDAO {
45  
46  	@PersistenceContext(unitName="kew-unit")
47  	EntityManager entityManager;
48  	
49      /**
50  	 * @return the entityManager
51  	 */
52  	public EntityManager getEntityManager() {
53  		return this.entityManager;
54  	}
55  
56  	/**
57  	 * @param entityManager the entityManager to set
58  	 */
59  	public void setEntityManager(EntityManager entityManager) {
60  		this.entityManager = entityManager;
61  	}
62  
63  	public void save(RouteNode node) {
64      	if (node.getRouteNodeId() == null){
65      		entityManager.persist(node);
66      	} else {
67      		OrmUtils.merge(entityManager, node);
68      	}
69      }
70  
71      public void save(RouteNodeInstance nodeInstance) {
72      	if (nodeInstance.getRouteNodeInstanceId() == null){
73      		entityManager.persist(nodeInstance);
74      	} else {
75      		OrmUtils.merge(entityManager, nodeInstance);
76      	}
77      }
78  
79      public void save(NodeState nodeState) {
80      	if (nodeState.getNodeStateId() == null){
81      		entityManager.persist(nodeState);
82      	} else {
83      		OrmUtils.merge(entityManager, nodeState);
84      	}
85      }
86  
87      public void save(Branch branch) {   	
88      	if (branch.getBranchId() == null){
89      		entityManager.persist(branch);
90      	} else {
91      		OrmUtils.merge(entityManager, branch);
92      	}
93      }
94  
95      public RouteNode findRouteNodeById(String nodeId) {
96      	Query query = entityManager.createNamedQuery("RouteNode.FindByRouteNodeId");
97      	query.setParameter(KEWPropertyConstants.ROUTE_NODE_ID, nodeId);
98      	return (RouteNode) query.getSingleResult();
99      }
100 
101     public RouteNodeInstance findRouteNodeInstanceById(String nodeInstanceId) {
102     	Query query = entityManager.createNamedQuery("RouteNodeInstance.FindByRouteNodeInstanceId");
103     	query.setParameter(KEWPropertyConstants.ROUTE_NODE_INSTANCE_ID, nodeInstanceId);
104 
105    	 	return (RouteNodeInstance) query.getSingleResult(); 		
106     }
107 
108     @SuppressWarnings("unchecked")
109     public List<RouteNodeInstance> getActiveNodeInstances(String documentId) {
110     	Query query = entityManager.createNamedQuery("RouteNodeInstance.FindActiveNodeInstances");
111     	query.setParameter(KEWPropertyConstants.DOCUMENT_ID, documentId);
112     	return (List<RouteNodeInstance>)query.getResultList();
113     }
114 
115     private static final String CURRENT_ROUTE_NODE_NAMES_SQL = "SELECT rn.nm" +
116                 " FROM krew_rte_node_t rn," +
117                 "      krew_rte_node_instn_t rni" +
118                 " LEFT JOIN krew_rte_node_instn_lnk_t rnl" +
119                 "   ON rnl.from_rte_node_instn_id = rni.rte_node_instn_id" +
120                 " WHERE rn.rte_node_id = rni.rte_node_id AND" +
121                 "       rni.doc_hdr_id = ? AND" +
122                 "       rnl.from_rte_node_instn_id IS NULL";
123 
124         @Override
125         public List<String> getCurrentRouteNodeNames(final String documentId) {
126             final DataSource dataSource = KEWServiceLocator.getDataSource();
127             JdbcTemplate template = new JdbcTemplate(dataSource);
128             List<String> names = template.execute(new PreparedStatementCreator() {
129                         public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
130                             return connection.prepareStatement(CURRENT_ROUTE_NODE_NAMES_SQL);
131                         }
132                     }, new PreparedStatementCallback<List<String>>() {
133                         public List<String> doInPreparedStatement(
134                                 PreparedStatement statement) throws SQLException, DataAccessException {
135                             List<String> routeNodeNames = new ArrayList<String>();
136                             statement.setString(1, documentId);
137                             ResultSet rs = statement.executeQuery();
138                             try {
139                                 while (rs.next()) {
140                                     String name = rs.getString("nm");
141                                     routeNodeNames.add(name);
142                                 }
143                             } finally {
144                                 if (rs != null) {
145                                     rs.close();
146                                 }
147                             }
148                             return routeNodeNames;
149                         }
150                     }
151             );
152             return names;
153         }
154     
155     @Override
156 	public List<String> getActiveRouteNodeNames(final String documentId) {
157     	final DataSource dataSource = KEWServiceLocator.getDataSource();
158     	JdbcTemplate template = new JdbcTemplate(dataSource);
159     	List<String> names = template.execute(
160 				new PreparedStatementCreator() {
161 					public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
162 						PreparedStatement statement = connection.prepareStatement(
163 								"SELECT rn.nm FROM krew_rte_node_t rn, krew_rte_node_instn_t rni WHERE rn.rte_node_id = rni.rte_node_id AND rni.doc_hdr_id = ? AND rni.actv_ind = ?");
164 						return statement;
165 					}
166 				},
167 				new PreparedStatementCallback<List<String>>() {
168 					public List<String> doInPreparedStatement(PreparedStatement statement) throws SQLException, DataAccessException {
169 						List<String> routeNodeNames = new ArrayList<String>();
170 						statement.setString(1, documentId);
171 						statement.setBoolean(2, Boolean.TRUE);
172 						ResultSet rs = statement.executeQuery();
173 						try {
174 							while(rs.next()) {
175 								String name = rs.getString("nm");
176 								routeNodeNames.add(name);
177 							}
178 						} finally {
179 							if(rs != null) {
180 								rs.close();
181 							}
182 						}
183 						return routeNodeNames;
184 					}
185 				});
186     	return names;
187 	}
188 
189     @SuppressWarnings("unchecked")
190     public List<RouteNodeInstance> getTerminalNodeInstances(String documentId) {
191     	Query query = entityManager.createNamedQuery("RouteNodeInstance.FindTerminalNodeInstances");
192     	query.setParameter(KEWPropertyConstants.DOCUMENT_ID, documentId);
193 		
194 		//FIXME: Can we do this better using just the JPQL query?  
195 		List<RouteNodeInstance> terminalNodes = new ArrayList<RouteNodeInstance>();
196 		List<RouteNodeInstance> routeNodeInstances = (List<RouteNodeInstance>) query.getResultList();
197 		for (RouteNodeInstance routeNodeInstance : routeNodeInstances) {
198 		    if (routeNodeInstance.getNextNodeInstances().isEmpty()) {
199 		    	terminalNodes.add(routeNodeInstance);
200 		    }
201 		}
202 		return terminalNodes;
203     }
204 
205     @Override
206     public List<String> getTerminalRouteNodeNames(final String documentId) {
207         final DataSource dataSource = KEWServiceLocator.getDataSource();
208         JdbcTemplate template = new JdbcTemplate(dataSource);
209         List<String> names = template.execute(new PreparedStatementCreator() {
210                     public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
211                         PreparedStatement statement = connection.prepareStatement("SELECT rn.nm" +
212                                 "  FROM krew_rte_node_t rn," +
213                                 "       krew_rte_node_instn_t rni" +
214                                 "  LEFT JOIN krew_rte_node_instn_lnk_t rnl" +
215                                 "    ON rnl.from_rte_node_instn_id = rni.rte_node_instn_id" +
216                                 "  WHERE rn.rte_node_id = rni.rte_node_id AND" +
217                                 "        rni.doc_hdr_id = ? AND" +
218                                 "        rni.actv_ind = ? AND" +
219                                 "        rni.cmplt_ind = ? AND" +
220                                 "        rnl.from_rte_node_instn_id IS NULL");
221                         return statement;
222                     }
223                 }, new PreparedStatementCallback<List<String>>() {
224                     public List<String> doInPreparedStatement(
225                             PreparedStatement statement) throws SQLException, DataAccessException {
226                         List<String> routeNodeNames = new ArrayList<String>();
227                         statement.setString(1, documentId);
228                         statement.setBoolean(2, Boolean.FALSE);
229                         statement.setBoolean(3, Boolean.TRUE);
230                         ResultSet rs = statement.executeQuery();
231                         try {
232                             while (rs.next()) {
233                                 String name = rs.getString("nm");
234                                 routeNodeNames.add(name);
235                             }
236                         } finally {
237                             if (rs != null) {
238                                 rs.close();
239                             }
240                         }
241                         return routeNodeNames;
242                     }
243                 }
244         );
245         return names;
246     }
247 
248     public List getInitialNodeInstances(String documentId) {
249     	//FIXME: Not sure this query is returning what it needs to     	                                              
250     	Query query = entityManager.createNamedQuery("RouteNodeInstance.FindInitialNodeInstances");
251     	query.setParameter(KEWPropertyConstants.DOCUMENT_ID, documentId);
252 		return (List)query.getResultList();
253     }
254 
255     public NodeState findNodeState(Long nodeInstanceId, String key) {
256     	Query query = entityManager.createNamedQuery("NodeState.FindNodeState");
257     	query.setParameter(KEWPropertyConstants.NODE_INSTANCE_ID, nodeInstanceId);
258     	query.setParameter(KEWPropertyConstants.KEY, key);
259 		return (NodeState) query.getSingleResult();
260     }
261 
262     public RouteNode findRouteNodeByName(String documentTypeId, String name) {
263     	Query query = entityManager.createNamedQuery("RouteNode.FindRouteNodeByName");
264     	query.setParameter(KEWPropertyConstants.DOCUMENT_TYPE_ID, documentTypeId);
265     	query.setParameter(KEWPropertyConstants.ROUTE_NODE_NAME, name);
266 		return (RouteNode)query.getSingleResult();    	
267     }
268 
269     public List<RouteNode> findFinalApprovalRouteNodes(String documentTypeId) {
270     	Query query = entityManager.createNamedQuery("RouteNode.FindApprovalRouteNodes");
271     	query.setParameter(KEWPropertyConstants.DOCUMENT_TYPE_ID, documentTypeId);
272     	query.setParameter(KEWPropertyConstants.FINAL_APPROVAL, Boolean.TRUE);
273     	return new ArrayList<RouteNode>(query.getResultList());
274     }
275 
276     public List findProcessNodeInstances(RouteNodeInstance process) {
277     	Query query = entityManager.createNamedQuery("RouteNodeInstance.FindProcessNodeInstances");
278     	query.setParameter(KEWPropertyConstants.PROCESS_ID, process.getRouteNodeInstanceId());
279     	return (List) query.getResultList();
280     }
281 
282     public List findRouteNodeInstances(String documentId) {
283     	Query query = entityManager.createNamedQuery("RouteNodeInstance.FindRouteNodeInstances");
284     	query.setParameter(KEWPropertyConstants.DOCUMENT_ID, documentId);
285     	return (List) query.getResultList();
286     }
287 
288     public void deleteLinksToPreNodeInstances(RouteNodeInstance routeNodeInstance) {
289 		List<RouteNodeInstance> preNodeInstances = routeNodeInstance.getPreviousNodeInstances();
290 		for (Iterator<RouteNodeInstance> preNodeInstanceIter = preNodeInstances.iterator(); preNodeInstanceIter.hasNext();) {
291 		    RouteNodeInstance preNodeInstance = (RouteNodeInstance) preNodeInstanceIter.next();
292 		    List<RouteNodeInstance> nextInstances = preNodeInstance.getNextNodeInstances();
293 		    nextInstances.remove(routeNodeInstance);
294 		    entityManager.merge(preNodeInstance);
295 		}
296     }
297 
298     public void deleteRouteNodeInstancesHereAfter(RouteNodeInstance routeNodeInstance) {
299     	RouteNodeInstance rnInstance = findRouteNodeInstanceById(routeNodeInstance.getRouteNodeInstanceId());
300     	entityManager.remove(rnInstance);
301     }
302 
303     public void deleteNodeStateById(Long nodeStateId) {
304     	Query query = entityManager.createNamedQuery("RouteNode.FindNodeStateById");
305     	query.setParameter(KEWPropertyConstants.ROUTE_NODE_STATE_ID, nodeStateId);
306     	NodeState nodeState = (NodeState) query.getSingleResult();
307     	entityManager.remove(nodeState);
308     }
309 
310     public void deleteNodeStates(List statesToBeDeleted) {
311 		for (Iterator stateToBeDeletedIter = statesToBeDeleted.iterator(); stateToBeDeletedIter.hasNext();) {
312 		    Long stateId = (Long) stateToBeDeletedIter.next();
313 		    deleteNodeStateById(stateId);
314 		}
315     }
316 
317 }