package com.qcadoo.mes.basic; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.stereotype.Service; import com.google.common.base.Preconditions; @Service public class LookupUtils { @Autowired private NamedParameterJdbcTemplate jdbcTemplate; public <R> GridResponse<R> getGridResponse(String query, String sidx, String sord, Integer page, int perPage, R recordExample) { return getGridResponse(query, sidx, sord, page, perPage, recordExample, new HashMap<>()); } public <R> GridResponse<R> getGridResponse(String query, String sidx, String sord, Integer page, int perPage, R recordExample, Map<String, Object> parameters) { sidx = sidx != null ? sidx.toLowerCase() : ""; sord = sord != null ? sord.toLowerCase() : ""; Preconditions.checkState(Arrays.asList("asc", "desc", "").contains(sord)); Preconditions.checkState(Arrays.asList(recordExample.getClass().getDeclaredFields()).stream().map(Field::getName).map(String::toLowerCase).collect(Collectors.toList()).contains(sidx)); query += addQueryWhereForObject(recordExample); parameters.putAll(getParametersForObject(recordExample)); String queryCount = String.format(query, "COUNT(*)", ""); String queryRecords = String.format(query, "*", "ORDER BY " + sidx + " " + sord) + String.format(" LIMIT %d OFFSET %d", perPage, perPage * (page - 1)); Integer countRecords = jdbcTemplate.queryForObject(queryCount, parameters, Long.class).intValue(); List<R> records = jdbcTemplate.query(queryRecords, parameters, new BeanPropertyRowMapper(recordExample.getClass())); return new GridResponse<>(page, Double.valueOf(Math.ceil((1.0 * countRecords) / perPage)).intValue(), countRecords, records); } private String addQueryWhereForObject(Object object) { List<String> items = new ArrayList<>(); if (object != null) { for (Field field : object.getClass().getDeclaredFields()) { try { field.setAccessible(true); Object value = field.get(object); if (value != null) { if (value instanceof Number) { items.add(String.format("%s = :%s", field.getName(), field.getName())); } else if (value instanceof Date) { items.add(String.format("%s = :%s", field.getName(), field.getName())); } else if (value instanceof Boolean) { items.add(String.format("%s = :%s", field.getName(), field.getName())); } else if (value instanceof String) { SearchAttribute.SEARCH_TYPE searchType = field.isAnnotationPresent(SearchAttribute.class) ? field.getAnnotation(SearchAttribute.class).searchType() : SearchAttribute.SEARCH_TYPE.LIKE; if (searchType == SearchAttribute.SEARCH_TYPE.EXACT_MATCH) { items.add(String.format("lower(%s) = lower(:%s)", field.getName(), field.getName())); } else { items.add(String.format("lower(%s) like lower(:%s)", field.getName(), field.getName())); } } } } catch (IllegalArgumentException | IllegalAccessException ex) { throw new RuntimeException(ex); } } } String where = ""; if (!items.isEmpty()) { where = " WHERE " + items.stream().collect(Collectors.joining(" AND ")); } return where; } private Map<String, Object> getParametersForObject(Object object) { Map<String, Object> parameters = new HashMap<>(); if (object != null) { for (Field field : object.getClass().getDeclaredFields()) { try { field.setAccessible(true); Object value = field.get(object); if (value != null) { if (value instanceof String) { SearchAttribute.SEARCH_TYPE searchType = field.isAnnotationPresent(SearchAttribute.class) ? field.getAnnotation(SearchAttribute.class).searchType() : SearchAttribute.SEARCH_TYPE.LIKE; if (searchType == SearchAttribute.SEARCH_TYPE.EXACT_MATCH) { parameters.put(field.getName(), value); } else { parameters.put(field.getName(), "%" + value + "%"); } } else { parameters.put(field.getName(), value); } } } catch (IllegalArgumentException | IllegalAccessException ex) { throw new RuntimeException(ex); } } } return parameters; } }