package org.gbif.checklistbank.service.mybatis.postgres; import java.sql.Array; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Set; import com.google.common.base.Strings; import com.google.common.collect.Sets; import org.apache.commons.lang3.StringUtils; import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.JdbcType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A mybatis type handler that translates from typed java.util.Set<T> to typed postgres arrays. */ public abstract class ArraySetTypeHandler<T> extends BaseTypeHandler<Set<T>> { private static final Logger LOG = LoggerFactory.getLogger(ArraySetTypeHandler.class); private final String baseType; /** * @param baseType postgres base type of the postgres array */ public ArraySetTypeHandler(String baseType) { this.baseType = baseType; } @Override public void setNonNullParameter(PreparedStatement ps, int i, Set<T> parameter, JdbcType jdbcType) throws SQLException { Array array = ps.getConnection().createArrayOf(baseType, parameter.toArray()); ps.setArray(i, array); } @Override public Set<T> getNullableResult(ResultSet rs, String columnName) throws SQLException { return fromString(rs.getString(columnName)); } @Override public Set<T> getNullableResult(ResultSet rs, int columnIndex) throws SQLException { return fromString(rs.getString(columnIndex)); } @Override public Set<T> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { return fromString(cs.getString(columnIndex)); } private Set<T> fromString(String array) { Set<T> set = Sets.newHashSet(); if (!Strings.isNullOrEmpty(array)) { String n = array.substring(1, array.length()-1); if (!Strings.isNullOrEmpty(n)) { for (String x : n.split(",")) { // remove potential quotes. These might even exist for non text datatypes // see https://github.com/pgjdbc/pgjdbc/issues/517#issuecomment-185647055 try { T val = convert(StringUtils.strip(x, "\"")); if (val != null) { set.add(val); } } catch (IllegalArgumentException e) { LOG.warn("Ignore invalid array element value {}. {}", x, e.getMessage()); } } } } return set; } protected abstract T convert(String x) throws IllegalArgumentException; }