View Javadoc
1   /**
2    * Copyright 2005-2014 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 org.kuali.rice.core.api.criteria.QueryByCriteria;
19  import org.kuali.rice.kew.api.KEWPropertyConstants;
20  import org.kuali.rice.kew.engine.node.NodeState;
21  import org.kuali.rice.kew.engine.node.RouteNode;
22  import org.kuali.rice.kew.engine.node.RouteNodeInstance;
23  import org.kuali.rice.kew.engine.node.dao.RouteNodeDAO;
24  import org.kuali.rice.kew.service.KEWServiceLocator;
25  import org.kuali.rice.krad.data.DataObjectService;
26  import org.springframework.beans.factory.annotation.Required;
27  import org.springframework.dao.DataAccessException;
28  import org.springframework.jdbc.core.JdbcTemplate;
29  import org.springframework.jdbc.core.PreparedStatementCallback;
30  import org.springframework.jdbc.core.PreparedStatementCreator;
31  
32  import javax.persistence.EntityManager;
33  import javax.persistence.Query;
34  import javax.sql.DataSource;
35  import java.sql.Connection;
36  import java.sql.PreparedStatement;
37  import java.sql.ResultSet;
38  import java.sql.SQLException;
39  import java.util.ArrayList;
40  import java.util.Iterator;
41  import java.util.List;
42  
43  import static org.kuali.rice.core.api.criteria.PredicateFactory.equal;
44  
45  public class RouteNodeDAOJpa implements RouteNodeDAO {
46  
47  	private EntityManager entityManager;
48      private DataObjectService dataObjectService;
49  
50      public static final String FIND_INITIAL_NODE_INSTANCES_NAME = "RouteNodeInstance.FindInitialNodeInstances";
51      public static final String FIND_INITIAL_NODE_INSTANCES_QUERY = "select d.initialRouteNodeInstances from "
52              + "DocumentRouteHeaderValue d where d.documentId = :documentId";
53  
54      /**
55  	 * @return the entityManager
56  	 */
57  	public EntityManager getEntityManager() {
58  		return this.entityManager;
59  	}
60  
61  	/**
62  	 * @param entityManager the entityManager to set
63  	 */
64  	public void setEntityManager(EntityManager entityManager) {
65  		this.entityManager = entityManager;
66  	}
67  
68      public RouteNodeInstance findRouteNodeInstanceById(String nodeInstanceId) {
69          QueryByCriteria.Builder queryByCriteria = QueryByCriteria.Builder.create().setPredicates(
70                  equal(KEWPropertyConstants.ROUTE_NODE_INSTANCE_ID,nodeInstanceId)
71          );
72  
73          List<RouteNodeInstance> routeNodeInstances = getDataObjectService().findMatching(
74                  RouteNodeInstance.class,queryByCriteria.build()).getResults();
75          if(routeNodeInstances != null && routeNodeInstances.size() > 0){
76              return routeNodeInstances.get(0);
77          }
78          return null;
79      }
80  
81      @SuppressWarnings("unchecked")
82      public List<RouteNodeInstance> getActiveNodeInstances(String documentId) {
83          QueryByCriteria.Builder queryByCriteria = QueryByCriteria.Builder.create().setPredicates(
84                  equal(KEWPropertyConstants.DOCUMENT_ID,documentId),
85                  equal(KEWPropertyConstants.ACTIVE,true)
86          );
87          return getDataObjectService().findMatching(RouteNodeInstance.class,
88                      queryByCriteria.build()).getResults();
89      }
90  
91      private static final String CURRENT_ROUTE_NODE_NAMES_SQL = "SELECT rn.nm" +
92                  " FROM krew_rte_node_t rn," +
93                  "      krew_rte_node_instn_t rni" +
94                  " LEFT JOIN krew_rte_node_instn_lnk_t rnl" +
95                  "   ON rnl.from_rte_node_instn_id = rni.rte_node_instn_id" +
96                  " WHERE rn.rte_node_id = rni.rte_node_id AND" +
97                  "       rni.doc_hdr_id = ? AND" +
98                  "       rnl.from_rte_node_instn_id IS NULL";
99  
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 }