001    /*
002     * Copyright 2011 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.kfs.sys.batch.dataaccess.impl;
017    
018    import java.sql.PreparedStatement;
019    import java.sql.ResultSet;
020    import java.sql.SQLException;
021    import java.util.HashMap;
022    import java.util.Map;
023    
024    import org.kuali.kfs.sys.batch.dataaccess.PreparedStatementCachingDao;
025    import org.kuali.rice.kns.dao.jdbc.PlatformAwareDaoBaseJdbc;
026    import org.kuali.rice.kns.service.DateTimeService;
027    
028    public abstract class AbstractPreparedStatementCachingDaoJdbc extends PlatformAwareDaoBaseJdbc implements PreparedStatementCachingDao {
029        protected static final String RETRIEVE_PREFIX = "retrieve-";
030        protected static final String INSERT_PREFIX = "insert-";
031        protected static final String UPDATE_PREFIX = "update-";
032    
033        protected abstract class JdbcWrapper<T> {
034            protected abstract void populateStatement(PreparedStatement preparedStatement) throws SQLException;
035    
036            void update(Class<T> type, PreparedStatement preparedStatement) {
037                try {
038                    populateStatement(preparedStatement);
039                    preparedStatement.executeUpdate();
040                }
041                catch (SQLException e) {
042                    throw new RuntimeException("AbstractUpdatingPreparedStatementCachingDaoJdbc.UpdatingJdbcWrapper encountered exception during getObject method for type: " + type, e);
043                }
044            }
045        }
046    
047        protected abstract class RetrievingJdbcWrapper<T> extends JdbcWrapper {
048            protected abstract T extractResult(ResultSet resultSet) throws SQLException;
049    
050            public T get(Class<T> type) {
051                T value = null;
052                PreparedStatement statement = preparedStatementCache.get(RETRIEVE_PREFIX + type);
053                try {
054                    populateStatement(statement);
055                    ResultSet resultSet = statement.executeQuery();
056                    if (resultSet.next()) {
057                        value = extractResult(resultSet);
058                        if (resultSet.next()) {
059                            throw new RuntimeException("More that one row returned when selecting by primary key in AbstractRetrievingPreparedStatementCachingDaoJdbc.RetrievingJdbcWrapper for: " + type);
060                        }
061                    }
062                    resultSet.close();
063                }
064                catch (SQLException e) {
065                    throw new RuntimeException("AbstractRetrievingPreparedStatementCachingDaoJdbc.RetrievingJdbcWrapper encountered exception during getObject method for type: " + type, e);
066                }
067                return (T) value;
068            }
069        }
070    
071        protected abstract class InsertingJdbcWrapper<T> extends JdbcWrapper {
072            public void execute(Class<T> type) {
073                update(type, preparedStatementCache.get(INSERT_PREFIX + type));
074            }
075        }
076    
077        protected abstract class UpdatingJdbcWrapper<T> extends JdbcWrapper {
078            public void execute(Class<T> type) {
079                update(type, preparedStatementCache.get(UPDATE_PREFIX + type));
080            }
081        }
082    
083        protected Map<String, PreparedStatement> preparedStatementCache;
084        protected DateTimeService dateTimeService;
085    
086        protected abstract Map<String, String> getSql();
087    
088        public void initialize() {
089            preparedStatementCache = new HashMap<String, PreparedStatement>();
090            try {
091                for (String statementKey : getSql().keySet()) {
092                    preparedStatementCache.put(statementKey, getConnection().prepareStatement(getSql().get(statementKey)));
093                }
094            }
095            catch (SQLException e) {
096                throw new RuntimeException("Caught exception preparing statements in CachingDaoJdbc initialize method", e);
097            }
098        }
099    
100        public void destroy() {
101            try {
102                for (PreparedStatement preparedStatement : preparedStatementCache.values()) {
103                    preparedStatement.close();
104                }
105                preparedStatementCache = null;
106            }
107            catch (SQLException e) {
108                throw new RuntimeException("Caught exception closing statements in CachingDaoJdbc destroy method", e);
109            }
110        }
111    
112        public void setDateTimeService(DateTimeService dateTimeService) {
113            this.dateTimeService = dateTimeService;
114        }
115    }