/* * PatientView * * Copyright (c) Worth Solutions Limited 2004-2013 * * This file is part of PatientView. * * PatientView is free software: you can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * PatientView is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License along with PatientView in a file * titled COPYING. If not, see <http://www.gnu.org/licenses/>. * * @package PatientView * @link http://www.patientview.org * @author PatientView <info@patientview.org> * @copyright Copyright (c) 2004-2013, Worth Solutions Limited * @license http://www.gnu.org/licenses/gpl-3.0.html The GNU General Public License V3.0 */ package org.patientview.radar.dao.impl; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import javax.sql.DataSource; import java.lang.reflect.Method; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; public abstract class BaseDaoImpl { private static final Logger LOGGER = LoggerFactory.getLogger(BaseDaoImpl.class); protected JdbcTemplate jdbcTemplate; protected NamedParameterJdbcTemplate namedParameterJdbcTemplate; public static <T> T getEnumValue(Class<T> enumClass, Integer id) { try { // Assume we've been supplied an enum with an ID field, so get the accessor method Method getId = enumClass.getMethod("getId"); // All enums have a static values method to get an array of the possible values Method method = enumClass.getMethod("values"); // Use the static method to get an array of all the possible values T[] values = (T[]) method.invoke(null); for (T t : values) { // Get the ID field value Integer thisId = (Integer) getId.invoke(t); if (thisId.equals(id)) { return t; } } // If we looped all the ID's and didn't find a value then return null LOGGER.debug("Could not find matching value for enum {} with ID {}", enumClass, id); return null; } catch (Exception e) { // This is pretty bad so lets throw a runtime exception LOGGER.error("Could not get values for enum {}", enumClass); throw new RuntimeException(e); } } public void setDataSource(DataSource dataSource) { jdbcTemplate = new JdbcTemplate(dataSource); namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource); } /** * GetXWithNullCheck methods added because ResultSet.getInt or ResultSet.getDouble will return * 0 if null in db but we want it to return null */ public Boolean getBooleanWithNullCheck(String column, ResultSet resultSet) throws SQLException { boolean value = resultSet.getBoolean(column); if (resultSet.wasNull()) { return null; } return value; } public Double getDoubleWithNullCheck(String column, ResultSet resultSet) throws SQLException { double value = resultSet.getDouble(column); if (resultSet.wasNull()) { return null; } return value; } public Integer getIntegerWithNullCheck(String column, ResultSet resultSet) throws SQLException { int value = resultSet.getInt(column); if (resultSet.wasNull()) { return null; } return value; } public Long getLongWithNullCheck(String column, ResultSet resultSet) throws SQLException { long value = resultSet.getLong(column); if (resultSet.wasNull()) { return null; } return value; } /** * Build an update query for a database record * @param tableName table to update * @param idFieldName the field in the table which is used as the identifier for the record to update * @param paramMap List of values to update on the table and the field they should update * @return String */ public String buildUpdateQuery(String tableName, String idFieldName, Map<String, Object> paramMap) { String updateSql = "UPDATE " + tableName + " SET "; // get the id value from the map Object idValue = paramMap.get(idFieldName); // remove the id temp so we can loop through it as we dont want that in the update part paramMap.remove(idFieldName); // loop through all params and add them in int count = 1; for (String field : paramMap.keySet()) { updateSql += " " + field + " = :" + field; if (count < paramMap.size()) { updateSql += ", "; } count++; } // add the where clause with the id updateSql += " WHERE " + idFieldName + " = :" + idFieldName; // add it back into map paramMap.put(idFieldName, idValue); return updateSql; } /** * Will build the order by statement on the specified field and what directon its to be returned in * @param sortField Database field name * @param reverse whether its ASC or DESC * @return String */ public String buildOrderQuery(String sortField, boolean reverse) { return "ORDER BY " + sortField + " " + (reverse ? "ASC" : "DESC"); } /** * Will simple take two values to start the record set from and end it * @param page Start record * @param numberPerPage Number of records to return * @param paramList List of params for current query * @return String */ public String buildLimitQuery(int page, int numberPerPage, List<Object> paramList) { if (page > 0 && numberPerPage > 0) { // work out the row to start from int start = ((page * numberPerPage) - numberPerPage); paramList.add(start); paramList.add(numberPerPage); return "LIMIT ?, ?"; } return ""; } /** * Build a list of values for use in an IN clause in SQL * * @param values * @return */ public String buildValueList(Collection<String> values) { StringBuilder result = new StringBuilder(); boolean firstValue = true; if (CollectionUtils.isNotEmpty(values)) { for (String s : values) { if (firstValue) { firstValue = false; } else { result.append(","); } result.append("'"); result.append(s); result.append("'"); } } return result.toString(); } public String buildWhereQuery(Map<String, String> searchMap, boolean and, List<Object> paramList) { return buildWhereQuery(true, searchMap, and, paramList); } /** * Will build a where query based on search values in a map * Key in the map is the database field name and the value is the text to search for * @param searchMap Map<String, String> fieldName, searchValue * @param and If the where clause should AND or OR the search values * @param paramList List of params for current query * @return String */ public String buildWhereQuery(boolean includeWhere, Map<String, String> searchMap, boolean and, List<Object> paramList) { if (searchMap != null && !searchMap.isEmpty()) { List<String> searchQueries = new ArrayList<String>(); // if there a search fields in the filter then create where clause // the start is optional as some statement may already have the where part and only require all the clauses if (includeWhere) { searchQueries.add("WHERE"); } // parse the search map as one key can be multiple fields in a table searchMap = parseSearchMap(searchMap); int count = 1; for (Map.Entry<String, String> entry : searchMap.entrySet()) { // converting the field values to uppercase so I dont have to faff around // probably bite me in the ass at some point searchQueries.add("UPPER(" + entry.getKey() + ") LIKE ?"); paramList.add("%" + entry.getValue().toUpperCase() + "%"); // if there are more than one field being search AND them if (count < searchMap.size()) { searchQueries.add((and ? "AND" : "OR")); } count++; } return StringUtils.join(searchQueries.toArray(), " "); } return ""; } /** * Will take a Map<String, String> and check to see if the key is a multi part value seperated by a , indicating * that the search value should be used across multiple database fields * If it is it will split and add in a key for each all using the same search value * @param searchMap Map<String, String> * @return Map<String, String> */ private Map<String, String> parseSearchMap(Map<String, String> searchMap) { Map<String, String> newSearchMap = new HashMap<String, String>(); for (Map.Entry<String, String> entry : searchMap.entrySet()) { String searchValue = entry.getValue().trim(); if (entry.getValue().length() > 0) { if (entry.getKey().indexOf(",") > -1) { String[] fields = entry.getKey().split(","); for (String s : fields) { newSearchMap.put(s.trim(), searchValue); } } else { newSearchMap.put(entry.getKey().trim(), searchValue); } } } return newSearchMap; } }