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 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.sql.DataSource;
27  
28  import org.apache.ojb.broker.query.Criteria;
29  import org.apache.ojb.broker.query.QueryByCriteria;
30  import org.apache.ojb.broker.query.QueryFactory;
31  import org.apache.ojb.broker.query.ReportQueryByCriteria;
32  import org.kuali.rice.kew.engine.node.Branch;
33  import org.kuali.rice.kew.engine.node.NodeState;
34  import org.kuali.rice.kew.engine.node.RouteNode;
35  import org.kuali.rice.kew.engine.node.RouteNodeInstance;
36  import org.kuali.rice.kew.engine.node.dao.RouteNodeDAO;
37  import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
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  import org.springmodules.orm.ojb.support.PersistenceBrokerDaoSupport;
44  
45  
46  public class RouteNodeDAOOjbImpl extends PersistenceBrokerDaoSupport implements RouteNodeDAO {
47  
48      private static final String ROUTE_NODE_ID = "routeNodeId";
49      private static final String ROUTE_NODE_INSTANCE_ID = "routeNodeInstanceId";
50      private static final String NODE_INSTANCE_ID = "nodeInstanceId";
51      private static final String DOCUMENT_ID = "documentId";
52      private static final String ROUTE_NODE_NAME = "routeNodeName";
53      private static final String DOCUMENT_TYPE_ID = "documentTypeId";
54      private static final String PROCESS_ID = "processId";
55      private static final String ACTIVE = "active";
56      private static final String COMPLETE = "complete";
57      private static final String FINAL_APPROVAL = "finalApprovalInd";
58      private static final String KEY = "key";
59      private static final String Route_Node_State_ID = "nodeStateId";
60  
61      public void save(RouteNode node) {
62  	getPersistenceBrokerTemplate().store(node);
63      }
64  
65      public void save(RouteNodeInstance nodeInstance) {
66      	// this is because the branch table relates to the node instance table - both through their keys - and
67      	// ojb can't automatically do this bi-directional relationship
68      	getPersistenceBrokerTemplate().store(nodeInstance.getBranch());
69      	getPersistenceBrokerTemplate().store(nodeInstance);
70      }
71  
72      public void save(NodeState nodeState) {
73  	getPersistenceBrokerTemplate().store(nodeState);
74      }
75  
76      public void save(Branch branch) {
77  	getPersistenceBrokerTemplate().store(branch);
78      }
79  
80      public RouteNode findRouteNodeById(String nodeId) {
81  	Criteria criteria = new Criteria();
82  	criteria.addEqualTo(ROUTE_NODE_ID, nodeId);
83  	return (RouteNode) getPersistenceBrokerTemplate().getObjectByQuery(new QueryByCriteria(RouteNode.class, criteria));
84      }
85  
86      public RouteNodeInstance findRouteNodeInstanceById(String nodeInstanceId) {
87  	Criteria criteria = new Criteria();
88  	criteria.addEqualTo(ROUTE_NODE_INSTANCE_ID, nodeInstanceId);
89  	return (RouteNodeInstance) getPersistenceBrokerTemplate().getObjectByQuery(
90  		new QueryByCriteria(RouteNodeInstance.class, criteria));
91      }
92  
93      @SuppressWarnings(value = "unchecked")
94      public List<RouteNodeInstance> getActiveNodeInstances(String documentId) {
95  	Criteria criteria = new Criteria();
96  	criteria.addEqualTo(DOCUMENT_ID, documentId);
97  	criteria.addEqualTo(ACTIVE, Boolean.TRUE);
98  	return (List<RouteNodeInstance>) getPersistenceBrokerTemplate().getCollectionByQuery(
99  		new QueryByCriteria(RouteNodeInstance.class, criteria));
100     }
101 
102     private static final String CURRENT_ROUTE_NODE_NAMES_SQL = "SELECT rn.nm" +
103             " FROM krew_rte_node_t rn," +
104             "      krew_rte_node_instn_t rni" +
105             " LEFT JOIN krew_rte_node_instn_lnk_t rnl" +
106             "   ON rnl.from_rte_node_instn_id = rni.rte_node_instn_id" +
107             " WHERE rn.rte_node_id = rni.rte_node_id AND" +
108             "       rni.doc_hdr_id = ? AND" +
109             "       rnl.from_rte_node_instn_id IS NULL";
110 
111     @Override
112     public List<String> getCurrentRouteNodeNames(final String documentId) {
113         final DataSource dataSource = KEWServiceLocator.getDataSource();
114         JdbcTemplate template = new JdbcTemplate(dataSource);
115         List<String> names = template.execute(new PreparedStatementCreator() {
116                     public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
117                         return connection.prepareStatement(CURRENT_ROUTE_NODE_NAMES_SQL);
118                     }
119                 }, new PreparedStatementCallback<List<String>>() {
120                     public List<String> doInPreparedStatement(
121                             PreparedStatement statement) throws SQLException, DataAccessException {
122                         List<String> routeNodeNames = new ArrayList<String>();
123                         statement.setString(1, documentId);
124                         ResultSet rs = statement.executeQuery();
125                         try {
126                             while (rs.next()) {
127                                 String name = rs.getString("nm");
128                                 routeNodeNames.add(name);
129                             }
130                         } finally {
131                             if (rs != null) {
132                                 rs.close();
133                             }
134                         }
135                         return routeNodeNames;
136                     }
137                 }
138         );
139         return names;
140     }
141 
142     @Override
143 	public List<String> getActiveRouteNodeNames(final String documentId) {
144     	final DataSource dataSource = KEWServiceLocator.getDataSource();
145     	JdbcTemplate template = new JdbcTemplate(dataSource);
146     	List<String> names = template.execute(
147 				new PreparedStatementCreator() {
148 					public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
149 						PreparedStatement statement = connection.prepareStatement(
150 								"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 = ?");
151 						return statement;
152 					}
153 				},
154 				new PreparedStatementCallback<List<String>>() {
155 					public List<String> doInPreparedStatement(PreparedStatement statement) throws SQLException, DataAccessException {
156 						List<String> routeNodeNames = new ArrayList<String>();
157 						statement.setString(1, documentId);
158 						statement.setBoolean(2, Boolean.TRUE);
159 						ResultSet rs = statement.executeQuery();
160 						try {
161 							while(rs.next()) {
162 								String name = rs.getString("nm");
163 								routeNodeNames.add(name);
164 							}
165 						} finally {
166 							if(rs != null) {
167 								rs.close();
168 							}
169 						}
170 						return routeNodeNames;
171 					}
172 				});
173     	return names;
174 	}
175 
176     @Override
177 	public List<String> getTerminalRouteNodeNames(final String documentId) {
178 		final DataSource dataSource = KEWServiceLocator.getDataSource();
179     	JdbcTemplate template = new JdbcTemplate(dataSource);
180     	List<String> names = template.execute(
181 				new PreparedStatementCreator() {
182 					public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
183 						PreparedStatement statement = connection.prepareStatement(
184 								"SELECT rn.nm" +
185 								"  FROM krew_rte_node_t rn," +
186 								"       krew_rte_node_instn_t rni" +
187 								"  LEFT JOIN krew_rte_node_instn_lnk_t rnl" +
188 								"    ON rnl.from_rte_node_instn_id = rni.rte_node_instn_id" +
189 								"  WHERE rn.rte_node_id = rni.rte_node_id AND" +
190 								"        rni.doc_hdr_id = ? AND" +
191 								"        rni.actv_ind = ? AND" +
192 								"        rni.cmplt_ind = ? AND" +
193 								"        rnl.from_rte_node_instn_id IS NULL");
194 						return statement;
195 					}
196 				},
197 				new PreparedStatementCallback<List<String>>() {
198 					public List<String> doInPreparedStatement(PreparedStatement statement) throws SQLException, DataAccessException {
199 						List<String> routeNodeNames = new ArrayList<String>();
200 						statement.setString(1, documentId);
201 						statement.setBoolean(2, Boolean.FALSE);
202 						statement.setBoolean(3, Boolean.TRUE);
203 						ResultSet rs = statement.executeQuery();
204 						try {
205 							while(rs.next()) {
206 								String name = rs.getString("nm");
207 								routeNodeNames.add(name);
208 							}
209 						} finally {
210 							if(rs != null) {
211 								rs.close();
212 							}
213 						}
214 						return routeNodeNames;
215 					}
216 				});
217     	return names;
218 	}
219 
220     @SuppressWarnings("unchecked")
221     public List<RouteNodeInstance> getTerminalNodeInstances(String documentId) {
222 	Criteria criteria = new Criteria();
223 	criteria.addEqualTo(DOCUMENT_ID, documentId);
224 	criteria.addEqualTo(ACTIVE, Boolean.FALSE);
225 	criteria.addEqualTo(COMPLETE, Boolean.TRUE);
226 //	criteria.addIsNull("nextNodeInstances.routeNodeInstanceId");
227 //	QueryByCriteria query = new QueryByCriteria(RouteNodeInstance.class, criteria);
228 //	// we need to outer join here because we are looking for nodes with no nextNodeInstances
229 //	query.setPathOuterJoin("nextNodeInstances");
230 //	return (List) getPersistenceBrokerTemplate().getCollectionByQuery(query);
231 	
232 	//forced to do this programmatically, for some reason the above code stopped working 
233 	List<RouteNodeInstance> terminalNodes = new ArrayList<RouteNodeInstance>();
234 	List<RouteNodeInstance> routeNodeInstances = (List<RouteNodeInstance>) getPersistenceBrokerTemplate().getCollectionByQuery(new QueryByCriteria(RouteNodeInstance.class, criteria));
235 	for (RouteNodeInstance routeNodeInstance : routeNodeInstances) {
236 	    if (routeNodeInstance.getNextNodeInstances().isEmpty()) {
237 		terminalNodes.add(routeNodeInstance);
238 	    }
239 	}
240 	return terminalNodes;
241     }
242 
243     public List getInitialNodeInstances(String documentId) {
244         Criteria criteria = new Criteria();
245         criteria.addEqualTo("initialDocumentRouteHeaderValues." + DOCUMENT_ID, documentId);
246         return (List) getPersistenceBrokerTemplate().getCollectionByQuery(
247                 new QueryByCriteria(RouteNodeInstance.class, criteria));
248     }
249 
250     public NodeState findNodeState(Long nodeInstanceId, String key) {
251 	Criteria criteria = new Criteria();
252 	criteria.addEqualTo(NODE_INSTANCE_ID, nodeInstanceId);
253 	criteria.addEqualTo(KEY, key);
254 	return (NodeState) getPersistenceBrokerTemplate().getObjectByQuery(new QueryByCriteria(NodeState.class, criteria));
255     }
256 
257     public RouteNode findRouteNodeByName(String documentTypeId, String name) {
258 	Criteria criteria = new Criteria();
259 	criteria.addEqualTo(ROUTE_NODE_NAME, name);
260 	criteria.addEqualTo(DOCUMENT_TYPE_ID, documentTypeId);
261 	return (RouteNode) getPersistenceBrokerTemplate().getObjectByQuery(new QueryByCriteria(RouteNode.class, criteria));
262     }
263 
264     public List<RouteNode> findFinalApprovalRouteNodes(String documentTypeId) {
265 	Criteria criteria = new Criteria();
266 	criteria.addEqualTo(DOCUMENT_TYPE_ID, documentTypeId);
267 	criteria.addEqualTo(FINAL_APPROVAL, Boolean.TRUE);
268 	return new ArrayList<RouteNode>(getPersistenceBrokerTemplate().getCollectionByQuery(new QueryByCriteria(RouteNode.class, criteria)));
269     }
270 
271     public List findProcessNodeInstances(RouteNodeInstance process) {
272 	Criteria crit = new Criteria();
273 	crit.addEqualTo(PROCESS_ID, process.getRouteNodeInstanceId());
274 	return (List) getPersistenceBrokerTemplate()
275 		.getCollectionByQuery(new QueryByCriteria(RouteNodeInstance.class, crit));
276     }
277 
278     public List findRouteNodeInstances(String documentId) {
279 	Criteria criteria = new Criteria();
280 	criteria.addEqualTo(DOCUMENT_ID, documentId);
281 	return (List) getPersistenceBrokerTemplate().getCollectionByQuery(
282 		new QueryByCriteria(RouteNodeInstance.class, criteria));
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 	    save(preNodeInstance);
292 	}
293     }
294 
295     public void deleteRouteNodeInstancesHereAfter(RouteNodeInstance routeNodeInstance) {
296 	this.getPersistenceBrokerTemplate().delete(routeNodeInstance);
297     }
298 
299     public void deleteNodeStateById(Long nodeStateId) {
300 	Criteria criteria = new Criteria();
301 	criteria.addEqualTo(Route_Node_State_ID, nodeStateId);
302 	NodeState nodeState = (NodeState) getPersistenceBrokerTemplate().getObjectByQuery(
303 		new QueryByCriteria(NodeState.class, criteria));
304 	getPersistenceBrokerTemplate().delete(nodeState);
305     }
306 
307     public void deleteNodeStates(List statesToBeDeleted) {
308 	for (Iterator stateToBeDeletedIter = statesToBeDeleted.iterator(); stateToBeDeletedIter.hasNext();) {
309 	    Long stateId = (Long) stateToBeDeletedIter.next();
310 	    deleteNodeStateById(stateId);
311 	}
312     }
313 
314 }