Java tutorial
/* * Copyright 2014. Vadim Baranov * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.vader.apm.dao.util; import org.apache.commons.lang3.Validate; import org.springframework.jdbc.core.RowCallbackHandler; import org.springframework.jdbc.core.RowMapper; import org.vader.apm.domain.ApmDbObject; import java.sql.ResultSet; import java.sql.SQLException; import java.util.HashMap; import java.util.Map; /** * @author Vadim Baranov * @param <K> key type * @param <V> value type */ public class MapExtractor<K, V> implements RowCallbackHandler { private final RowMapper<K> keyMapper; private final RowMapper<V> valueMapper; private int rowNum; private Map<Long, K> loadedKeys = new HashMap<>(); private Map<Long, V> loadedValues = new HashMap<>(); private final Map<K, V> result = new HashMap<>(); /** * Constructor. * * @param keyMapper key mapper * @param valueMapper value mapper */ public MapExtractor(RowMapper<K> keyMapper, RowMapper<V> valueMapper) { Validate.notNull(keyMapper, "key mapper must be not null"); Validate.notNull(valueMapper, "value mapper must be not null"); this.keyMapper = keyMapper; this.valueMapper = valueMapper; } /** * Constructor. * * @param keyColumn key column name * @param keyClazz key type * @param valueMapper value mapper */ public MapExtractor(String keyColumn, Class<K> keyClazz, RowMapper<V> valueMapper) { Validate.notBlank(keyColumn, "key column name must be not blank"); Validate.notNull(keyClazz, "key class must be not null"); Validate.notNull(valueMapper, "value mapper must be not null"); this.keyMapper = new PrimitiveRowMapper<>(keyColumn, keyClazz); this.valueMapper = valueMapper; } /** * Constructor. * * @param keyColumn key column name * @param keyClazz key type * @param valueColumn value column name * @param valueClazz value type */ public MapExtractor(String keyColumn, Class<K> keyClazz, String valueColumn, Class<V> valueClazz) { Validate.notBlank(keyColumn, "key column name must be not blank"); Validate.notNull(keyClazz, "key class must be not null"); Validate.notBlank(valueColumn, "value column name must be not blank"); Validate.notNull(valueClazz, "value class must be not null"); this.keyMapper = new PrimitiveRowMapper<>(keyColumn, keyClazz); this.valueMapper = new PrimitiveRowMapper<>(valueColumn, valueClazz); } /** * Constructor. * * @param keyMapper key mapper * @param valueColumn value column name * @param valueClazz value type */ public MapExtractor(RowMapper<K> keyMapper, String valueColumn, Class<V> valueClazz) { Validate.notNull(keyMapper, "key mapper must be not null"); Validate.notBlank(valueColumn, "value column name must be not blank"); Validate.notNull(valueClazz, "value class must be not null"); this.keyMapper = keyMapper; this.valueMapper = new PrimitiveRowMapper<>(valueColumn, valueClazz); } @Override public void processRow(ResultSet rs) throws SQLException { K key = keyMapper.mapRow(rs, rowNum); if (key instanceof ApmDbObject) { final ApmDbObject dbObject = (ApmDbObject) key; if (loadedKeys.containsKey(dbObject.getId())) { key = loadedKeys.get(dbObject.getId()); } else { loadedKeys.put(dbObject.getId(), key); } } V value = valueMapper.mapRow(rs, rowNum++); if (value instanceof ApmDbObject) { final ApmDbObject dbObject = (ApmDbObject) value; if (loadedValues.containsKey(dbObject.getId())) { value = loadedValues.get(dbObject.getId()); } else { loadedValues.put(dbObject.getId(), value); } } result.put(key, value); } public Map<K, V> getResult() { return result; } /** * Primitive row mapper. */ private static class PrimitiveRowMapper<T> implements RowMapper<T> { private final String column; private final Class<T> clazz; /** * Constructor. * * @param column column name * @param clazz column type */ private PrimitiveRowMapper(String column, Class<T> clazz) { this.column = column; this.clazz = clazz; } @Override public T mapRow(ResultSet rs, int rowNum) throws SQLException { return clazz.cast(rs.getObject(column)); } } }