package org.molgenis.data.postgresql;
import org.apache.commons.lang3.time.DateUtils;
import org.molgenis.data.Entity;
import org.molgenis.data.MolgenisDataException;
import org.molgenis.data.meta.AttributeType;
import org.molgenis.data.meta.model.Attribute;
import org.molgenis.file.model.FileMeta;
import java.time.ZoneId;
import java.util.Date;
import static java.lang.String.format;
import static java.util.stream.Collectors.toList;
import static java.util.stream.StreamSupport.stream;
/**
* PostgreSQL utilities such as entity value to PostgreSQL value conversion.
*/
class PostgreSqlUtils
{
private PostgreSqlUtils()
{
}
/**
* Returns the PostgreSQL value for the given entity attribute
*
* @param entity entity
* @param attr attribute
* @return PostgreSQL value
*/
static Object getPostgreSqlValue(Entity entity, Attribute attr)
{
String attrName = attr.getName();
AttributeType attrType = attr.getDataType();
switch (attrType)
{
case BOOL:
return entity.getBoolean(attrName);
case CATEGORICAL:
case XREF:
Entity xrefEntity = entity.getEntity(attrName);
return xrefEntity != null ? getPostgreSqlValue(xrefEntity,
xrefEntity.getEntityType().getIdAttribute()) : null;
case CATEGORICAL_MREF:
case MREF:
case ONE_TO_MANY:
Iterable<Entity> entities = entity.getEntities(attrName);
return stream(entities.spliterator(), false).map(mrefEntity -> getPostgreSqlValue(mrefEntity,
mrefEntity.getEntityType().getIdAttribute())).collect(toList());
case DATE:
Date date = entity.getUtilDate(attrName);
// http://stackoverflow.com/questions/21242110/convert-java-util-date-to-java-time-localdate
return date != null ? date.toInstant().atZone(ZoneId.of("UTC")).toLocalDate() : null;
case DATE_TIME:
Date dateTime = entity.getUtilDate(attrName);
return dateTime != null ? new java.sql.Timestamp(
(dateTime.getTime() / DateUtils.MILLIS_PER_SECOND) * DateUtils.MILLIS_PER_SECOND) : null;
case DECIMAL:
return entity.getDouble(attrName);
case EMAIL:
case ENUM:
case HTML:
case HYPERLINK:
case SCRIPT:
case STRING:
case TEXT:
return entity.getString(attrName);
case FILE:
FileMeta fileEntity = entity.getEntity(attrName, FileMeta.class);
return fileEntity != null ? getPostgreSqlValue(fileEntity,
fileEntity.getEntityType().getIdAttribute()) : null;
case INT:
return entity.getInt(attrName);
case LONG:
return entity.getLong(attrName);
case COMPOUND:
throw new RuntimeException(format("Illegal attribute type [%s]", attrType.toString()));
default:
throw new RuntimeException(format("Unknown attribute type [%s]", attrType.toString()));
}
}
/**
* Returns the PostgreSQL query value for the given entity attribute. For query operators requiring a list of
* values (e.g. IN or RANGE) this method must be called for each individual query value.
*
* @param queryValue value of the type that matches the attribute type
* @param attr attribute
* @return PostgreSQL value
*/
static Object getPostgreSqlQueryValue(Object queryValue, Attribute attr)
{
while (true)
{
String attrName = attr.getName();
AttributeType attrType = attr.getDataType();
switch (attrType)
{
case BOOL:
if (queryValue != null && !(queryValue instanceof Boolean))
{
throw new MolgenisDataException(
format("Attribute [%s] query value is of type [%s] instead of [%s]", attrName,
queryValue.getClass().getSimpleName(), Boolean.class.getSimpleName()));
}
return queryValue;
case CATEGORICAL:
case CATEGORICAL_MREF: // one query value
case FILE:
case MREF: // one query value
case XREF:
case ONE_TO_MANY:
// queries values referencing an entity can either be the entity itself or the entity id
if (queryValue != null)
{
if (queryValue instanceof Entity)
{
queryValue = ((Entity) queryValue).getIdValue();
}
attr = attr.getRefEntity().getIdAttribute();
continue;
}
else
{
return null;
}
case DATE:
if (queryValue != null && !(queryValue instanceof Date))
{
throw new MolgenisDataException(
format("Attribute [%s] query value is of type [%s] instead of [%s]", attrName,
queryValue.getClass().getSimpleName(), Date.class.getSimpleName()));
}
Date date = (Date) queryValue;
return date != null ? new java.sql.Date(date.getTime()) : null;
case DATE_TIME:
if (queryValue != null && !(queryValue instanceof Date))
{
throw new MolgenisDataException(
format("Attribute [%s] query value is of type [%s] instead of [%s]", attrName,
queryValue.getClass().getSimpleName(), Date.class.getSimpleName()));
}
Date dateTime = (Date) queryValue;
return dateTime != null ? new java.sql.Timestamp(dateTime.getTime()) : null;
case DECIMAL:
if (queryValue != null && !(queryValue instanceof Double))
{
throw new MolgenisDataException(
format("Attribute [%s] query value is of type [%s] instead of [%s]", attrName,
queryValue.getClass().getSimpleName(), Double.class.getSimpleName()));
}
return queryValue;
case ENUM:
// enum query values can be an enum or enum string
if (queryValue != null)
{
if (queryValue instanceof String)
{
return queryValue;
}
else if (queryValue instanceof Enum<?>)
{
return queryValue.toString();
}
else
{
throw new MolgenisDataException(
format("Attribute [%s] query value is of type [%s] instead of [%s] or [%s]",
attrName, queryValue.getClass().getSimpleName(),
String.class.getSimpleName(), Enum.class.getSimpleName()));
}
}
else
{
return null;
}
case EMAIL:
case HTML:
case HYPERLINK:
case SCRIPT:
case STRING:
case TEXT:
if (queryValue != null && !(queryValue instanceof String))
{
throw new MolgenisDataException(
format("Attribute [%s] query value is of type [%s] instead of [%s]", attrName,
queryValue.getClass().getSimpleName(), String.class.getSimpleName()));
}
return queryValue;
case INT:
if (queryValue != null && !(queryValue instanceof Integer))
{
throw new MolgenisDataException(
format("Attribute [%s] query value is of type [%s] instead of [%s]", attrName,
queryValue.getClass().getSimpleName(), Integer.class.getSimpleName()));
}
return queryValue;
case LONG:
if (queryValue != null && !(queryValue instanceof Long))
{
throw new MolgenisDataException(
format("Attribute [%s] query value is of type [%s] instead of [%s]", attrName,
queryValue.getClass().getSimpleName(), Long.class.getSimpleName()));
}
return queryValue;
case COMPOUND:
throw new RuntimeException(format("Illegal attribute type [%s]", attrType.toString()));
default:
throw new RuntimeException(format("Unknown attribute type [%s]", attrType.toString()));
}
}
}
}