001    /**
002     * Copyright 2004-2013 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     */
016    package org.kuali.hr.time.util;
017    
018    import java.sql.Connection;
019    import java.sql.ResultSet;
020    import java.sql.SQLException;
021    import java.sql.Statement;
022    import java.util.ArrayList;
023    import java.util.HashMap;
024    import java.util.List;
025    import java.util.Map;
026    
027    import javax.sql.DataSource;
028    
029    import junit.framework.Assert;
030    
031    import org.apache.commons.lang.StringUtils;
032    import org.apache.log4j.Logger;
033    import org.enhydra.jdbc.pool.StandardXAPoolDataSource;
034    import org.kuali.hr.time.service.base.TkServiceLocator;
035    import org.kuali.rice.core.api.config.property.ConfigContext;
036    import org.kuali.rice.core.api.lifecycle.BaseLifecycle;
037    import org.springframework.jdbc.core.ConnectionCallback;
038    import org.springframework.jdbc.core.JdbcTemplate;
039    import org.springframework.jdbc.core.StatementCallback;
040    import org.springframework.transaction.PlatformTransactionManager;
041    import org.springframework.transaction.TransactionStatus;
042    import org.springframework.transaction.support.TransactionCallback;
043    import org.springframework.transaction.support.TransactionTemplate;
044    
045    public class ClearDatabaseLifecycle extends BaseLifecycle {
046    
047            protected static final Logger LOG = Logger.getLogger(ClearDatabaseLifecycle.class);
048        private List<String> alternativeTablesToClear = new ArrayList<String>();
049    
050            private static List<String> TABLES_TO_CLEAR = new ArrayList<String>();
051            static {
052                    TABLES_TO_CLEAR.add("HR_CALENDAR_T");
053                    TABLES_TO_CLEAR.add("HR_CALENDAR_ENTRIES_T");
054                    TABLES_TO_CLEAR.add("HR_DEPT_T");
055                    TABLES_TO_CLEAR.add("TK_ASSIGN_ACCT_T");
056                    TABLES_TO_CLEAR.add("TK_ASSIGNMENT_T");
057                    TABLES_TO_CLEAR.add("TK_CLOCK_LOCATION_RL_T");
058                    TABLES_TO_CLEAR.add("TK_CLOCK_LOG_T");
059                    TABLES_TO_CLEAR.add("TK_DAILY_OVERTIME_RL_T");
060                    TABLES_TO_CLEAR.add("HR_EARN_CODE_SECURITY_T");
061                    TABLES_TO_CLEAR.add("TK_DEPT_LUNCH_RL_T");
062                    TABLES_TO_CLEAR.add("HR_EARN_CODE_T");
063                    TABLES_TO_CLEAR.add("HR_EARN_CODE_GROUP_T");
064                    TABLES_TO_CLEAR.add("HR_EARN_CODE_GROUP_DEF_T");
065                    TABLES_TO_CLEAR.add("TK_GRACE_PERIOD_RL_T");
066                    TABLES_TO_CLEAR.add("TK_HOUR_DETAIL_HIST_T");
067                    TABLES_TO_CLEAR.add("TK_HOUR_DETAIL_T");
068                    TABLES_TO_CLEAR.add("HR_ROLES_T");
069                    TABLES_TO_CLEAR.add("HR_SAL_GROUP_T");
070                    TABLES_TO_CLEAR.add("TK_SHIFT_DIFFERENTIAL_RL_T");
071                    TABLES_TO_CLEAR.add("TK_SYSTEM_LUNCH_RL_T");
072                    TABLES_TO_CLEAR.add("TK_TASK_T");
073                    TABLES_TO_CLEAR.add("TK_TIME_BLOCK_HIST_T");
074                    TABLES_TO_CLEAR.add("TK_TIME_BLOCK_T");
075                    TABLES_TO_CLEAR.add("TK_TIME_COLLECTION_RL_T");
076                    TABLES_TO_CLEAR.add("TK_WEEKLY_OVERTIME_RL_T");
077                    TABLES_TO_CLEAR.add("TK_WORK_AREA_T");
078                    TABLES_TO_CLEAR.add("HR_JOB_T");
079                    TABLES_TO_CLEAR.add("HR_PAYTYPE_T");
080    //              TABLES_TO_CLEAR.add("HR_WORK_SCHEDULE_ENTRY_T");
081    //              TABLES_TO_CLEAR.add("HR_WORK_SCHEDULE_T");
082                    TABLES_TO_CLEAR.add("TK_DOCUMENT_HEADER_T");
083                    TABLES_TO_CLEAR.add("HR_POSITION_T");
084            }
085    
086            private static final Map<String,String> TABLE_TO_ID_MAP = new HashMap<String,String>();
087            static{
088                    TABLE_TO_ID_MAP.put("TK_TIME_COLLECTION_RL_T", "TK_TIME_COLL_RULE_ID");
089                    TABLE_TO_ID_MAP.put("TK_SHIFT_DIFFERENTIAL_RL_T", "TK_SHIFT_DIFF_RL_ID");
090                    TABLE_TO_ID_MAP.put("TK_GRACE_PERIOD_RL_T", "TK_GRACE_PERIOD_RULE_ID");
091                    TABLE_TO_ID_MAP.put("TK_CLOCK_LOCATION_RL_T", "TK_CLOCK_LOC_RULE_ID");
092                    TABLE_TO_ID_MAP.put("HR_CALENDAR_ENTRIES_T", "HR_CALENDAR_ENTRY_ID");
093                    TABLE_TO_ID_MAP.put("TK_DOCUMENT_HEADER_T", "DOCUMENT_ID");
094            TABLE_TO_ID_MAP.put("KREW_RULE_T", "RULE_ID");
095            TABLE_TO_ID_MAP.put("KREW_RULE_RSP_T", "RULE_RSP_ID");
096            TABLE_TO_ID_MAP.put("KREW_DLGN_RSP_T", "DLGN_RULE_ID");
097            TABLE_TO_ID_MAP.put("KREW_RULE_ATTR_T", "RULE_ATTR_ID");
098            TABLE_TO_ID_MAP.put("KREW_RULE_TMPL_T", "RULE_TMPL_ID");
099            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) TkServiceLocator.getBean("kpmeDataSource");
114                            final PlatformTransactionManager transactionManager = (PlatformTransactionManager) TkServiceLocator.getPlatformTransactionManager();
115                            final String schemaName = dataSource.getUser().toUpperCase();
116                            clearTables(transactionManager, dataSource, schemaName);
117                            super.start();
118                    }
119            }
120    
121            protected Boolean isTestTableInSchema(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                    isTestTableInSchema(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