package io.ebeaninternal.server.type;


import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.DocPropertyType;
import io.ebean.core.type.ScalarType;
import io.ebean.text.TextException;
import io.ebean.text.json.EJson;
import io.ebeaninternal.json.ModifyAwareList;

import javax.persistence.PersistenceException;
import java.io.IOException;
import java.lang.reflect.Type;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.locks.ReentrantLock;

import static java.util.Collections.EMPTY_LIST;

Type mapped for DB ARRAY type (Postgres only effectively).
/** * Type mapped for DB ARRAY type (Postgres only effectively). */
@SuppressWarnings("rawtypes") public class ScalarTypeArrayList extends ScalarTypeArrayBase<List> implements ScalarTypeArray { static PlatformArrayTypeFactory factory() { return new Factory(); } static class Factory implements PlatformArrayTypeFactory { private final ReentrantLock lock = new ReentrantLock(); private final Map<String, ScalarTypeArrayList> cache = new HashMap<>();
Return the ScalarType to use based on the List's generic parameter type.
/** * Return the ScalarType to use based on the List's generic parameter type. */
@Override public ScalarTypeArrayList typeFor(Type valueType, boolean nullable) { lock.lock(); try { String key = valueType + ":" + nullable; if (valueType.equals(UUID.class)) { return cache.computeIfAbsent(key, s -> new ScalarTypeArrayList(nullable, "uuid", DocPropertyType.UUID, ArrayElementConverter.UUID)); } if (valueType.equals(Long.class)) { return cache.computeIfAbsent(key, s -> new ScalarTypeArrayList(nullable, "bigint", DocPropertyType.LONG, ArrayElementConverter.LONG)); } if (valueType.equals(Integer.class)) { return cache.computeIfAbsent(key, s -> new ScalarTypeArrayList(nullable, "integer", DocPropertyType.INTEGER, ArrayElementConverter.INTEGER)); } if (valueType.equals(Double.class)) { return cache.computeIfAbsent(key, s -> new ScalarTypeArrayList(nullable, "float", DocPropertyType.DOUBLE, ArrayElementConverter.DOUBLE)); } if (valueType.equals(String.class)) { return cache.computeIfAbsent(key, s -> new ScalarTypeArrayList(nullable, "varchar", DocPropertyType.TEXT, ArrayElementConverter.STRING)); } throw new IllegalArgumentException("Type [" + valueType + "] not supported for @DbArray mapping"); } finally { lock.unlock(); } } @Override public ScalarTypeArrayList typeForEnum(ScalarType<?> scalarType, boolean nullable) { return new ScalarTypeArrayList(nullable, arrayTypeFor(scalarType), scalarType.getDocType(), new ArrayElementConverter.EnumConverter(scalarType)); } } private final String arrayType; private final ArrayElementConverter converter; public ScalarTypeArrayList(boolean nullable, String arrayType, DocPropertyType docPropertyType, ArrayElementConverter converter) { super(List.class, Types.ARRAY, docPropertyType, nullable); this.arrayType = arrayType; this.converter = converter; } @Override public DocPropertyType getDocType() { return docPropertyType; }
Return the DB column definition for DDL generation.
/** * Return the DB column definition for DDL generation. */
@Override public String getDbColumnDefn() { return arrayType + "[]"; } @SuppressWarnings("unchecked") @Override protected List fromArray(Object[] array1) { List list = new ArrayList(array1.length); for (Object element : array1) { if (element == null) { list.add(null); } else { list.add(converter.toElement(element)); } } return new ModifyAwareList(list); } protected Object[] toArray(List value) { return converter.toDbArray(value.toArray()); } @Override public void bind(DataBinder binder, List value) throws SQLException { if (value == null) { bindNull(binder); } else { binder.setArray(arrayType, toArray(value)); } } @Override protected void bindNull(DataBinder binder) throws SQLException { if (nullable) { binder.setNull(Types.ARRAY); } else { binder.setArray(arrayType, toArray(EMPTY_LIST)); } } @Override public String formatValue(List value) { try { return EJson.write(value); } catch (IOException e) { throw new PersistenceException("Failed to format List into JSON content", e); } } @Override public List parse(String value) { try { return EJson.parseList(value, false); } catch (IOException e) { throw new TextException("Failed to parse JSON [{}] as List", value, e); } } @Override public List jsonRead(JsonParser parser) throws IOException { return EJson.parseList(parser, parser.getCurrentToken()); } @Override public void jsonWrite(JsonGenerator writer, List value) throws IOException { EJson.write(value, writer); } }