View Javadoc
1   /**
2    * Copyright 2004-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.kpme.core.util;
17  
18  import java.sql.Connection;
19  import java.sql.ResultSet;
20  import java.sql.SQLException;
21  import java.sql.Statement;
22  import java.util.ArrayList;
23  import java.util.HashMap;
24  import java.util.List;
25  import java.util.Map;
26  
27  import javax.sql.DataSource;
28  
29  import junit.framework.Assert;
30  
31  import org.apache.commons.lang.StringUtils;
32  import org.apache.log4j.Logger;
33  import org.enhydra.jdbc.pool.StandardXAPoolDataSource;
34  import org.kuali.kpme.core.service.HrServiceLocator;
35  import org.kuali.rice.core.api.config.property.ConfigContext;
36  import org.kuali.rice.core.api.lifecycle.BaseLifecycle;
37  import org.springframework.jdbc.core.ConnectionCallback;
38  import org.springframework.jdbc.core.JdbcTemplate;
39  import org.springframework.jdbc.core.StatementCallback;
40  import org.springframework.transaction.PlatformTransactionManager;
41  import org.springframework.transaction.TransactionStatus;
42  import org.springframework.transaction.support.TransactionCallback;
43  import org.springframework.transaction.support.TransactionTemplate;
44  
45  public class ClearDatabaseLifecycle extends BaseLifecycle {
46  
47  	protected static final Logger LOG = Logger.getLogger(ClearDatabaseLifecycle.class);
48      private List<String> alternativeTablesToClear = new ArrayList<String>();
49  
50  	private static List<String> TABLES_TO_CLEAR = new ArrayList<String>();
51  	static {
52  		TABLES_TO_CLEAR.add("HR_CALENDAR_T");
53  		TABLES_TO_CLEAR.add("HR_CALENDAR_ENTRIES_T");
54  		TABLES_TO_CLEAR.add("HR_DEPT_T");
55  		TABLES_TO_CLEAR.add("TK_ASSIGN_ACCT_T");
56  		TABLES_TO_CLEAR.add("TK_ASSIGNMENT_T");
57  		TABLES_TO_CLEAR.add("TK_CLOCK_LOCATION_RL_T");
58  		TABLES_TO_CLEAR.add("TK_CLOCK_LOG_T");
59  		TABLES_TO_CLEAR.add("TK_DAILY_OVERTIME_RL_T");
60  		TABLES_TO_CLEAR.add("HR_EARN_CODE_SECURITY_T");
61  		TABLES_TO_CLEAR.add("TK_DEPT_LUNCH_RL_T");
62  		TABLES_TO_CLEAR.add("HR_EARN_CODE_T");
63  		TABLES_TO_CLEAR.add("HR_EARN_CODE_GROUP_T");
64  		TABLES_TO_CLEAR.add("HR_EARN_CODE_GROUP_DEF_T");
65  		TABLES_TO_CLEAR.add("TK_GRACE_PERIOD_RL_T");
66  		TABLES_TO_CLEAR.add("TK_HOUR_DETAIL_HIST_T");
67  		TABLES_TO_CLEAR.add("TK_HOUR_DETAIL_T");
68  		TABLES_TO_CLEAR.add("HR_ROLES_T");
69  		TABLES_TO_CLEAR.add("HR_SAL_GROUP_T");
70  		TABLES_TO_CLEAR.add("TK_SHIFT_DIFFERENTIAL_RL_T");
71  		TABLES_TO_CLEAR.add("TK_SYSTEM_LUNCH_RL_T");
72  		TABLES_TO_CLEAR.add("TK_TASK_T");
73  		TABLES_TO_CLEAR.add("TK_TIME_BLOCK_HIST_T");
74  		TABLES_TO_CLEAR.add("TK_TIME_BLOCK_T");
75  		TABLES_TO_CLEAR.add("TK_TIME_COLLECTION_RL_T");
76  		TABLES_TO_CLEAR.add("TK_WEEKLY_OVERTIME_RL_T");
77  		TABLES_TO_CLEAR.add("TK_WORK_AREA_T");
78  		TABLES_TO_CLEAR.add("HR_JOB_T");
79  		TABLES_TO_CLEAR.add("HR_PAYTYPE_T");
80  //		TABLES_TO_CLEAR.add("HR_WORK_SCHEDULE_ENTRY_T");
81  //		TABLES_TO_CLEAR.add("HR_WORK_SCHEDULE_T");
82  		TABLES_TO_CLEAR.add("TK_DOCUMENT_HEADER_T");
83  		TABLES_TO_CLEAR.add("HR_POSITION_T");
84  	}
85  
86  	private static final Map<String,String> TABLE_TO_ID_MAP = new HashMap<String,String>();
87  	static{
88  		TABLE_TO_ID_MAP.put("TK_TIME_COLLECTION_RL_T", "TK_TIME_COLL_RULE_ID");
89  		TABLE_TO_ID_MAP.put("TK_SHIFT_DIFFERENTIAL_RL_T", "TK_SHIFT_DIFF_RL_ID");
90  		TABLE_TO_ID_MAP.put("TK_GRACE_PERIOD_RL_T", "TK_GRACE_PERIOD_RULE_ID");
91  		TABLE_TO_ID_MAP.put("TK_CLOCK_LOCATION_RL_T", "TK_CLOCK_LOC_RULE_ID");
92  		TABLE_TO_ID_MAP.put("HR_CALENDAR_ENTRIES_T", "HR_CALENDAR_ENTRY_ID");
93  		TABLE_TO_ID_MAP.put("TK_DOCUMENT_HEADER_T", "DOCUMENT_ID");
94          TABLE_TO_ID_MAP.put("KREW_RULE_T", "RULE_ID");
95          TABLE_TO_ID_MAP.put("KREW_RULE_RSP_T", "RULE_RSP_ID");
96          TABLE_TO_ID_MAP.put("KREW_DLGN_RSP_T", "DLGN_RULE_ID");
97          TABLE_TO_ID_MAP.put("KREW_RULE_ATTR_T", "RULE_ATTR_ID");
98          TABLE_TO_ID_MAP.put("KREW_RULE_TMPL_T", "RULE_TMPL_ID");
99          TABLE_TO_ID_MAP.put("KREW_DOC_TYP_T", "DOC_TYP_ID");
100 	}
101 
102     private static final Map<String,Integer> TABLE_START_CLEAR_ID = new HashMap<String,Integer>();
103     static{
104         TABLE_START_CLEAR_ID.put("KREW_DOC_TYP_T", new Integer(3000));
105     }
106 
107 	public static final String TEST_TABLE_NAME = "KR_UNITTEST_T";
108 
109 	public static final Integer START_CLEAR_ID = 1000;
110 
111 	public void start() throws Exception {
112 		if (new Boolean(ConfigContext.getCurrentContextConfig().getProperty("tk.use.clearDatabaseLifecycle"))) {
113 			final StandardXAPoolDataSource dataSource = (StandardXAPoolDataSource) HrServiceLocator.getBean("kpmeDataSource");
114 			final PlatformTransactionManager transactionManager = (PlatformTransactionManager) HrServiceLocator.getPlatformTransactionManager();
115 			final String schemaName = dataSource.getUser().toUpperCase();
116 			clearTables(transactionManager, dataSource, schemaName);
117 			super.start();
118 		}
119 	}
120 
121 	protected Boolean getTestTableInSchema(final DataSource dataSource) {
122 	Assert.assertNotNull("DataSource could not be located.", dataSource);
123 	return (Boolean) new JdbcTemplate(dataSource).execute(new ConnectionCallback() {
124 			public Object doInConnection(final Connection connection) throws SQLException {
125 				final ResultSet resultSet = connection.getMetaData().getTables(null, null, TEST_TABLE_NAME, null);
126 				return new Boolean(resultSet.next());
127 			}
128 		});
129 	}
130 
131 	protected void verifyTestEnvironment(final DataSource dataSource) {
132 		Assert.assertTrue("No table named '" + TEST_TABLE_NAME + "' was found in the configured database.  " + "You are attempting to run tests against a non-test database!!!",
133 		getTestTableInSchema(dataSource));
134 	}
135 
136 	protected void clearTables(final PlatformTransactionManager transactionManager, final DataSource dataSource, final String schemaName) {
137 		LOG.info("Clearing tables for schema " + schemaName);
138 		Assert.assertNotNull("DataSource could not be located.", dataSource);
139 
140 		if (schemaName == null || schemaName.equals("")) {
141 			Assert.fail("Empty schema name given");
142 		}
143 		new TransactionTemplate(transactionManager).execute(new TransactionCallback<Object>() {
144             public Object doInTransaction(final TransactionStatus status) {
145             	verifyTestEnvironment(dataSource);
146             	return new JdbcTemplate(dataSource).execute(new StatementCallback<Object>() {
147                 	public Object doInStatement(Statement statement) throws SQLException {
148                     		final List<String> reEnableConstraints = new ArrayList<String>();
149                             List<List<String>> tableLists = new ArrayList<List<String>>(2);
150                             tableLists.add(TABLES_TO_CLEAR);
151                             tableLists.add(alternativeTablesToClear);
152                             for (List<String> list : tableLists) {
153                                 for (String tableName : list) {
154                                     //if there is an id name that doesnt follow convention check and limit accordingly
155                                     String idName = TABLE_TO_ID_MAP.get(tableName);
156                                     String deleteStatement = null;
157                                     Integer clearId = TABLE_START_CLEAR_ID.get(tableName) != null ? TABLE_START_CLEAR_ID.get(tableName) : START_CLEAR_ID;
158                                     if(idName == null){
159                                         deleteStatement = "DELETE FROM " + tableName +" WHERE "+StringUtils.removeEnd(tableName,"_T")+"_ID"+ " >= "+clearId;
160                                     } else {
161                                         deleteStatement = "DELETE FROM " + tableName +" WHERE "+ idName + " >= "+clearId;
162                                     }
163 
164                                     LOG.debug("Clearing contents using statement ->" + deleteStatement + "<-");
165                                     statement.addBatch(deleteStatement);
166                                 }
167                             }
168 
169                             for (final String constraint : reEnableConstraints) {
170                             	LOG.debug("Enabling constraints using statement ->" + constraint + "<-");
171                             	statement.addBatch(constraint);
172                             }
173                             statement.executeBatch();
174                             return null;
175                       }
176                 });
177             }
178 		});
179 		LOG.info("Tables successfully cleared for schema " + schemaName);
180 	}
181 
182 	public List<String> getTablesToClear() {
183 	return TABLES_TO_CLEAR;
184 	}
185 
186     public List<String> getAlternativeTablesToClear() {
187         return this.alternativeTablesToClear;
188     }
189 
190 }
191