WIP Java8 types - ScalarTypeDuration etc

This commit is contained in:
rbygrave
2014-11-17 00:05:20 +13:00
parent 4a882b537c
commit 7f30dc7b1e
59 changed files with 1857 additions and 558 deletions
@@ -0,0 +1,29 @@
package com.avaje.ebean.config;
/**
* Configuration for JSON features.
*/
public abstract class JsonConfig {
/**
* Defined the format used for DateTime types.
*/
public enum DateTime {
/**
* Format as epoch millis.
*/
MILLIS,
/**
* Format as epoch with nanos.
*/
NANOS,
/**
* Format as ISO-8601 date format.
*/
ISO8601
}
}
@@ -121,6 +121,11 @@ public class ServerConfig {
*/
private AutofetchConfig autofetchConfig = new AutofetchConfig();
/**
* The JSON format used for DateTime types. Default to millis.
*/
private JsonConfig.DateTime jsonDateTime = JsonConfig.DateTime.MILLIS;
/**
* The database platform name. Used to imply a DatabasePlatform to use.
*/
@@ -270,6 +275,20 @@ public class ServerConfig {
this.jsonFactory = jsonFactory;
}
/**
* Return the JSON format used for DateTime types.
*/
public JsonConfig.DateTime getJsonDateTime() {
return jsonDateTime;
}
/**
* Set the JSON format to use for DateTime types.
*/
public void setJsonDateTime(JsonConfig.DateTime jsonDateTime) {
this.jsonDateTime = jsonDateTime;
}
/**
* Return the name of the EbeanServer.
*/
@@ -1368,6 +1387,13 @@ public class ServerConfig {
lazyLoadBatchSize = p.getInt("lazyLoadBatchSize", 1);
queryBatchSize = p.getInt("queryBatchSize", DEFAULT_QUERY_BATCH_SIZE);
String jsonDateTimeFormat = p.get("jsonDateTime", null);
if (jsonDateTimeFormat != null) {
jsonDateTime = JsonConfig.DateTime.valueOf(jsonDateTimeFormat);
} else {
jsonDateTime = JsonConfig.DateTime.MILLIS;
}
ddlGenerate = p.getBoolean("ddl.generate", false);
ddlRun = p.getBoolean("ddl.run", false);
@@ -41,29 +41,6 @@ import com.fasterxml.jackson.core.JsonToken;
*/
public class BeanProperty implements ElPropertyValue {
/**
* Advanced bean deployment. To exclude this property from update where
* clause.
*/
public static final String EXCLUDE_FROM_UPDATE_WHERE = "EXCLUDE_FROM_UPDATE_WHERE";
/**
* Advanced bean deployment. To exclude this property from delete where
* clause.
*/
public static final String EXCLUDE_FROM_DELETE_WHERE = "EXCLUDE_FROM_DELETE_WHERE";
/**
* Advanced bean deployment. To exclude this property from insert.
*/
public static final String EXCLUDE_FROM_INSERT = "EXCLUDE_FROM_INSERT";
/**
* Advanced bean deployment. To exclude this property from update set
* clause.
*/
public static final String EXCLUDE_FROM_UPDATE = "EXCLUDE_FROM_UPDATE";
/**
* Flag to mark this at part of the unique id.
*/
@@ -488,15 +465,7 @@ public class BeanProperty implements ElPropertyValue {
* Return true if the underlying type is mutable.
*/
public boolean isMutableScalarType() {
if (scalarType == null) {
return false;
}
return scalarType.isMutable();
}
public void copyProperty(EntityBean sourceBean, EntityBean destBean) {
Object value = getValue(sourceBean);
setValue(destBean, value);
return scalarType != null && scalarType.isMutable();
}
/**
@@ -506,10 +475,6 @@ public class BeanProperty implements ElPropertyValue {
return descriptor.getEncryptKey(this);
}
public String getDecryptProperty() {
return dbEncryptFunction.getDecryptSql(this.getName());
}
public String getDecryptProperty(String propertyName) {
return dbEncryptFunction.getDecryptSql(propertyName);
}
@@ -575,24 +540,6 @@ public class BeanProperty implements ElPropertyValue {
return owningType.isAssignableFrom(type);
}
public Object readSetOwning(DbReadContext ctx, EntityBean bean, Class<?> type) throws SQLException {
try {
Object value = scalarType.read(ctx.getDataReader());
if (value == null || bean == null) {
// not setting the value...
} else {
if (owningType.equals(type)) {
setValue(bean, value);
}
}
return value;
} catch (Exception e) {
String msg = "Error readSet on " + descriptor + "." + name;
throw new PersistenceException(msg, e);
}
}
public void loadIgnore(DbReadContext ctx) {
scalarType.loadIgnore(ctx.getDataReader());
}
@@ -616,16 +563,13 @@ public class BeanProperty implements ElPropertyValue {
public Object readSet(DbReadContext ctx, EntityBean bean, Class<?> type) throws SQLException {
try {
Object value = scalarType.read(ctx.getDataReader());
if (bean == null || (type != null && !owningType.isAssignableFrom(type))) {
// not setting the value...
} else {
setValue(bean, value);
}
return value;
Object value = scalarType.read(ctx.getDataReader());
if (bean != null && ((type == null || owningType.isAssignableFrom(type)))) {
setValue(bean, value);
}
return value;
} catch (Exception e) {
String msg = "Error readSet on " + descriptor + "." + name;
throw new PersistenceException(msg, e);
throw new PersistenceException("Error readSet on " + descriptor + "." + name, e);
}
}
@@ -653,21 +597,6 @@ public class BeanProperty implements ElPropertyValue {
return scalarType.readData(dataInput);
}
public boolean isCascadeValidate() {
return cascadeValidate;
}
/**
* Checks to see if a bean is a reference (will be lazy loaded) or a
* BeanCollection that has not yet been populated.
* <p>
* For base types this returns true.
* </p>
*/
public boolean isValueLoaded(Object value) {
return true;
}
public BeanProperty getBeanProperty() {
return this;
}
@@ -737,11 +666,9 @@ public class BeanProperty implements ElPropertyValue {
}
}
private static Object[] NO_ARGS = new Object[0];
public Object getCacheDataValue(EntityBean bean) {
return getValue(bean);
}
}
public void setCacheDataValue(EntityBean bean, Object cacheData) {
setValue(bean, cacheData);
@@ -759,19 +686,6 @@ public class BeanProperty implements ElPropertyValue {
throw new RuntimeException(msg, ex);
}
}
/**
* Explicitly use reflection to get value.
*/
public Object getValueViaReflection(Object bean) {
try {
return readMethod.invoke(bean, NO_ARGS);
} catch (Exception ex) {
String beanType = bean == null ? "null" : bean.getClass().getName();
String msg = "get " + name + " on [" + descriptor + "] type[" + beanType + "] threw error.";
throw new RuntimeException(msg, ex);
}
}
public Object getValueIntercept(EntityBean bean) {
try {
@@ -826,13 +740,6 @@ public class BeanProperty implements ElPropertyValue {
return name;
}
/**
* This is a full ElGetValue.
*/
public boolean isDeployOnly() {
return false;
}
@Override
public boolean containsFormulaWithJoin() {
return formula && sqlFormulaJoin != null;
@@ -902,7 +809,7 @@ public class BeanProperty implements ElPropertyValue {
/**
* Return the scalarType.
*/
public ScalarType<?> getScalarType() {
public ScalarType<Object> getScalarType() {
return scalarType;
}
@@ -923,7 +830,7 @@ public class BeanProperty implements ElPropertyValue {
}
public Object parseDateTime(long systemTimeMillis) {
return scalarType.parseDateTime(systemTimeMillis);
return scalarType.convertFromMillis(systemTimeMillis);
}
/**
@@ -1031,10 +938,6 @@ public class BeanProperty implements ElPropertyValue {
return version;
}
public String getDeployProperty() {
return dbColumn;
}
/**
* The database column name this is mapped to.
*/
@@ -1168,13 +1071,6 @@ public class BeanProperty implements ElPropertyValue {
return embedded;
}
/**
* Return an extra attribute set on this property.
*/
public String getExtraAttribute(String key) {
return extraAttributeMap.get(key);
}
/**
* Return the default value.
*/
@@ -385,12 +385,6 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
return null;
}
@Override
public boolean isValueLoaded(Object value) {
return !(value instanceof BeanCollection<?>) || ((BeanCollection<?>) value).isPopulated();
}
public void add(BeanCollection<?> collection, EntityBean bean) {
help.add(collection, bean);
}
@@ -265,14 +265,6 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
}
}
@Override
public boolean isValueLoaded(Object value) {
if (value instanceof EntityBean) {
return ((EntityBean) value)._ebean_getIntercept().isLoaded();
}
return true;
}
/**
* Return meta data for the deployment of the embedded bean specific to this
* property.
@@ -215,7 +215,7 @@ public class ElPropertyChain implements ElPropertyValue {
}
public Object parseDateTime(long systemTimeMillis) {
return scalarType.parseDateTime(systemTimeMillis);
return scalarType.convertFromMillis(systemTimeMillis);
}
public StringParser getStringParser() {
@@ -3,6 +3,7 @@ package com.avaje.ebeaninternal.server.type;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
public class DateTimeJsonParser {
@@ -31,4 +32,7 @@ public class DateTimeJsonParser {
}
}
public String format(Date value) {
return dtFormat().format(value);
}
}
@@ -0,0 +1,89 @@
package com.avaje.ebeaninternal.server.type;
/*
* Copyright 2013 FasterXML.com
*
* 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.
*/
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.Duration;
import java.time.Instant;
/**
* Utilities to aid in the translation of decimal types to/from multiple parts.
*
* @author Nick Williams
* @since 2.2.0
*/
public final class DecimalUtils {
private static final char[] ZEROES = new char[]{'0', '0', '0', '0', '0', '0', '0', '0', '0'};
private static final BigDecimal ONE_BILLION = new BigDecimal(1000000000L);
private DecimalUtils() {
throw new RuntimeException("DecimalUtils cannot be instantiated.");
}
public static Duration toDuration(BigDecimal value) {
long seconds = value.longValue();
int nanoseconds = extractNanosecondDecimal(value, seconds);
return Duration.ofSeconds(seconds, nanoseconds);
}
public static BigDecimal toDecimal(Duration instant) {
return new BigDecimal(toDecimal(instant.getSeconds(), instant.getNano()));
}
public static Timestamp toTimestamp(BigDecimal value) {
long seconds = value.longValue();
int nanoseconds = extractNanosecondDecimal(value, seconds);
Timestamp ts = new Timestamp(seconds * 1000);
ts.setNanos(nanoseconds);
return ts;
}
public static BigDecimal toDecimal(Timestamp instant) {
long millis = instant.getTime();
long secs = millis/1000;
return new BigDecimal(toDecimal(secs, instant.getNanos()));
}
public static Instant toInstant(BigDecimal value) {
long seconds = value.longValue();
int nanoseconds = DecimalUtils.extractNanosecondDecimal(value, seconds);
return Instant.ofEpochSecond(seconds, nanoseconds);
}
public static BigDecimal toDecimal(Instant instant) {
return new BigDecimal(toDecimal(instant.getEpochSecond(), instant.getNano()));
}
public static String toDecimal(long seconds, int nanoseconds) {
StringBuilder string = new StringBuilder(Integer.toString(nanoseconds));
if (string.length() < 9)
string.insert(0, ZEROES, 0, 9 - string.length());
return seconds + "." + string;
}
public static int extractNanosecondDecimal(BigDecimal value, long integer) {
return value.subtract(new BigDecimal(integer)).multiply(ONE_BILLION).intValue();
}
}
@@ -4,6 +4,7 @@ import java.math.BigInteger;
import java.sql.Types;
import java.util.Calendar;
import com.avaje.ebean.config.JsonConfig;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
@@ -80,27 +81,27 @@ public class DefaultTypeFactory {
/**
* Create the default ScalarType for java.util.Date.
*/
public ScalarType<java.util.Date> createUtilDate() {
public ScalarType<java.util.Date> createUtilDate(JsonConfig.DateTime mode) {
// by default map anonymous java.util.Date to java.sql.Timestamp.
// String mapType =
// properties.getProperty("type.mapping.java.util.Date","timestamp");
int utilDateType = getTemporalMapType("timestamp");
return createUtilDate(utilDateType);
return createUtilDate(mode, utilDateType);
}
/**
* Create a ScalarType for java.util.Date explicitly specifying the type to
* map to.
*/
public ScalarType<java.util.Date> createUtilDate(int utilDateType) {
public ScalarType<java.util.Date> createUtilDate(JsonConfig.DateTime mode, int utilDateType) {
switch (utilDateType) {
case Types.DATE:
return new ScalarTypeUtilDate.DateType();
case Types.TIMESTAMP:
return new ScalarTypeUtilDate.TimestampType();
return new ScalarTypeUtilDate.TimestampType(mode);
default:
throw new RuntimeException("Invalid type " + utilDateType);
@@ -110,23 +111,19 @@ public class DefaultTypeFactory {
/**
* Create the default ScalarType for java.util.Calendar.
*/
public ScalarType<Calendar> createCalendar() {
// by default map anonymous java.util.Calendar to java.sql.Timestamp.
// String mapType =
// properties.getProperty("type.mapping.java.util.Calendar",
// "timestamp");
int jdbcType = getTemporalMapType("timestamp");
public ScalarType<Calendar> createCalendar(JsonConfig.DateTime mode) {
return createCalendar(jdbcType);
int jdbcType = getTemporalMapType("timestamp");
return createCalendar(mode, jdbcType);
}
/**
* Create a ScalarType for java.util.Calendar explicitly specifying the type
* to map to.
*/
public ScalarType<Calendar> createCalendar(int jdbcType) {
public ScalarType<Calendar> createCalendar(JsonConfig.DateTime mode, int jdbcType) {
return new ScalarTypeCalendar(jdbcType);
return new ScalarTypeCalendar(mode, jdbcType);
}
private int getTemporalMapType(String mapType) {
@@ -23,6 +23,7 @@ import java.util.TimeZone;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import com.avaje.ebean.config.*;
import org.joda.time.DateMidnight;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
@@ -33,10 +34,6 @@ import org.slf4j.LoggerFactory;
import com.avaje.ebean.annotation.EnumMapping;
import com.avaje.ebean.annotation.EnumValue;
import com.avaje.ebean.config.CompoundType;
import com.avaje.ebean.config.CompoundTypeProperty;
import com.avaje.ebean.config.ScalarTypeConverter;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebeaninternal.api.ClassUtil;
import com.avaje.ebeaninternal.server.core.BootupClasses;
import com.avaje.ebeaninternal.server.lib.util.StringHelper;
@@ -103,8 +100,6 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable {
private final ScalarType<?> dateType = new ScalarTypeDate();
private final ScalarType<?> timestampType = new ScalarTypeTimestamp();
private final ScalarType<?> inetAddressType = new ScalarTypeInetAddress();
private final ScalarType<?> urlType = new ScalarTypeURL();
private final ScalarType<?> uriType = new ScalarTypeURI();
@@ -116,7 +111,6 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable {
private final ScalarType<?> classType = new ScalarTypeClass();
private final ScalarTypeLongToTimestamp longToTimestamp = new ScalarTypeLongToTimestamp();
private final List<ScalarType<?>> customScalarTypes = new ArrayList<ScalarType<?>>();
@@ -126,6 +120,8 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable {
private final ReflectionBasedTypeBuilder reflectScalarBuilder;
private final JsonConfig.DateTime jsonDateTime;
/**
* Create the DefaultTypeManager.
*/
@@ -134,6 +130,7 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable {
int clobType = config == null ? Types.CLOB : config.getDatabasePlatform().getClobDbType();
int blobType = config == null ? Types.BLOB : config.getDatabasePlatform().getBlobDbType();
this.jsonDateTime = config.getJsonDateTime();
this.checkImmutable = new CheckImmutable(this);
this.reflectScalarBuilder = new ReflectionBasedTypeBuilder(this);
@@ -146,12 +143,12 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable {
this.extraTypeFactory = new DefaultTypeFactory(config);
initialiseStandard(clobType, blobType, config.isUuidStoreAsBinary());
initialiseJavaTimeTypes();
initialiseJodaTypes();
initialiseStandard(jsonDateTime, clobType, blobType, config.isUuidStoreAsBinary());
initialiseJavaTimeTypes(jsonDateTime);
initialiseJodaTypes(jsonDateTime);
if (bootupClasses != null) {
initialiseCustomScalarTypes(bootupClasses);
initialiseCustomScalarTypes(jsonDateTime, bootupClasses);
initialiseScalarConverters(bootupClasses);
initialiseCompoundTypes(bootupClasses);
}
@@ -313,19 +310,15 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable {
if (jdbcType == 0 || scalarType.getJdbcType() == jdbcType) {
// matching type
return (ScalarType<T>) scalarType;
} else {
// sometime like java.util.Date or java.util.Calendar
// that that does not map to the same jdbc type as the
// server wide settings.
}
}
// a util Date with jdbcType not matching server wide settings
if (type.equals(java.util.Date.class)) {
return (ScalarType<T>) extraTypeFactory.createUtilDate(jdbcType);
return (ScalarType<T>) extraTypeFactory.createUtilDate(jsonDateTime, jdbcType);
}
// a Calendar with jdbcType not matching server wide settings
if (type.equals(java.util.Calendar.class)) {
return (ScalarType<T>) extraTypeFactory.createCalendar(jdbcType);
return (ScalarType<T>) extraTypeFactory.createCalendar(jsonDateTime, jdbcType);
}
String msg = "Unmatched ScalarType for " + type + " jdbcType:" + jdbcType;
@@ -417,7 +410,7 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable {
public ScalarType<?> createEnumScalarType(Class<?> enumType) {
// get the mapping information from EnumMapping
EnumMapping enumMapping = (EnumMapping) enumType.getAnnotation(EnumMapping.class);
EnumMapping enumMapping = enumType.getAnnotation(EnumMapping.class);
if (enumMapping == null) {
// look for EnumValue annotations instead
return createEnumScalarType2(enumType);
@@ -468,7 +461,9 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable {
* interface and register it with this TypeManager.
* </p>
*/
protected void initialiseCustomScalarTypes(BootupClasses bootupClasses) {
protected void initialiseCustomScalarTypes(JsonConfig.DateTime mode, BootupClasses bootupClasses) {
ScalarTypeLongToTimestamp longToTimestamp = new ScalarTypeLongToTimestamp(mode);
customScalarTypes.add(longToTimestamp);
@@ -604,12 +599,12 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable {
return propParamTypes[1];
}
protected void initialiseJavaTimeTypes() {
protected void initialiseJavaTimeTypes(JsonConfig.DateTime mode) {
if (ClassUtil.isPresent("java.time.LocalDate", this.getClass())) {
logger.debug("Registering java.time data types");
typeMap.put(java.time.LocalDate.class, new ScalarTypeLocalDate());
typeMap.put(java.time.LocalDateTime.class, new ScalarTypeLocalDateTime());
typeMap.put(OffsetDateTime.class, new ScalarTypeOffsetDateTime());
typeMap.put(java.time.LocalDateTime.class, new ScalarTypeLocalDateTime(mode));
typeMap.put(OffsetDateTime.class, new ScalarTypeOffsetDateTime(mode));
}
}
@@ -617,16 +612,16 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable {
* Detect if Joda classes are in the classpath and if so register the Joda
* data types.
*/
protected void initialiseJodaTypes() {
protected void initialiseJodaTypes(JsonConfig.DateTime mode) {
// detect if Joda classes are in the classpath
if (ClassUtil.isPresent("org.joda.time.LocalDateTime", this.getClass())) {
// Joda classes are in the classpath so register the types
logger.debug("Registering Joda data types");
typeMap.put(LocalDateTime.class, new ScalarTypeJodaLocalDateTime());
typeMap.put(LocalDateTime.class, new ScalarTypeJodaLocalDateTime(mode));
typeMap.put(DateTime.class, new ScalarTypeJodaDateTime(mode));
typeMap.put(LocalDate.class, new ScalarTypeJodaLocalDate());
typeMap.put(LocalTime.class, new ScalarTypeJodaLocalTime());
typeMap.put(DateTime.class, new ScalarTypeJodaDateTime());
typeMap.put(DateMidnight.class, new ScalarTypeJodaDateMidnight());
}
}
@@ -635,12 +630,12 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable {
* Register all the standard types supported. This is the standard JDBC types
* plus some other common types such as java.util.Date and java.util.Calendar.
*/
protected void initialiseStandard(int platformClobType, int platformBlobType, boolean binaryUUID) {
protected void initialiseStandard(JsonConfig.DateTime mode, int platformClobType, int platformBlobType, boolean binaryUUID) {
ScalarType<?> utilDateType = extraTypeFactory.createUtilDate();
ScalarType<?> utilDateType = extraTypeFactory.createUtilDate(mode);
typeMap.put(java.util.Date.class, utilDateType);
ScalarType<?> calType = extraTypeFactory.createCalendar();
ScalarType<?> calType = extraTypeFactory.createCalendar(mode);
typeMap.put(Calendar.class, calType);
ScalarType<?> mathBigIntType = extraTypeFactory.createMathBigInteger();
@@ -655,8 +650,6 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable {
if (booleanType.getJdbcType() == Types.BIT) {
// for MapBeans ... BIT types are assumed to be booleans
nativeMap.put(Types.BIT, booleanType);
} else {
// boolean mapping to Types.Integer, Types.VARCHAR or Types.Boolean
}
// Store UUID as binary(16) or varchar(40)
@@ -744,6 +737,9 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable {
nativeMap.put(Types.TIME, timeType);
typeMap.put(Date.class, dateType);
nativeMap.put(Types.DATE, dateType);
ScalarType<?> timestampType = new ScalarTypeTimestamp(mode);
typeMap.put(Timestamp.class, timestampType);
nativeMap.put(Types.TIMESTAMP, timestampType);
@@ -162,19 +162,11 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
*/
public T parse(String value);
/**
* Convert the systemTimeMillis into the appropriate java object.
* <p>
* For non dateTime types this will throw an exception.
* </p>
*/
public T parseDateTime(long dateTime);
/**
* Return true if the type can accept long systemTimeMillis input.
* <p>
* This is used to determine if is is sensible to use the
* {@link #parseDateTime(long)} method.
* {@link #convertFromMillis(long)} method.
* </p>
* <p>
* This includes the Date, Calendar, sql Date, Time, Timestamp, JODA types
@@ -184,24 +176,32 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
*/
public boolean isDateTimeCapable();
/**
/**
* Convert the systemTimeMillis into the appropriate java object.
* <p>
* For non dateTime types this will throw an exception.
* </p>
*/
public T convertFromMillis(long dateTime);
/**
* Read the value from binary input.
*/
public Object readData(DataInput dataInput) throws IOException;
public T readData(DataInput dataInput) throws IOException;
/**
* Write the value to binary output.
*/
public void writeData(DataOutput dataOutput, Object v) throws IOException;
public void writeData(DataOutput dataOutput, T v) throws IOException;
/**
* Read the value from JsonParser.
*/
public Object jsonRead(JsonParser ctx, JsonToken event) throws IOException;
public T jsonRead(JsonParser ctx, JsonToken event) throws IOException;
/**
* Write the value to the JsonGenerator.
*/
public void jsonWrite(JsonGenerator ctx, String name, Object value) throws IOException;
public void jsonWrite(JsonGenerator ctx, String name, T value) throws IOException;
}
@@ -64,7 +64,7 @@ public abstract class ScalarTypeBaseDate<T> extends ScalarTypeBase<T> {
return convertFromDate(date);
}
public T parseDateTime(long systemTimeMillis) {
public T convertFromMillis(long systemTimeMillis) {
Date ts = new Date(systemTimeMillis);
return convertFromDate(ts);
}
@@ -74,20 +74,20 @@ public abstract class ScalarTypeBaseDate<T> extends ScalarTypeBase<T> {
}
@Override
public Object jsonRead(JsonParser ctx, JsonToken event) throws IOException {
public T jsonRead(JsonParser ctx, JsonToken event) throws IOException {
if (JsonToken.VALUE_NUMBER_INT == event) {
return parseDateTime(ctx.getLongValue());
return convertFromMillis(ctx.getLongValue());
} else {
return convertFromDate(Date.valueOf(ctx.getText()));
}
}
public void jsonWrite(JsonGenerator ctx, String name, Object value) throws IOException {
public void jsonWrite(JsonGenerator ctx, String name, T value) throws IOException {
long millis = convertToMillis(value);
ctx.writeNumberField(name, millis);
}
public Object readData(DataInput dataInput) throws IOException {
public T readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
return null;
} else {
@@ -98,9 +98,8 @@ public abstract class ScalarTypeBaseDate<T> extends ScalarTypeBase<T> {
}
@SuppressWarnings("unchecked")
public void writeData(DataOutput dataOutput, Object v) throws IOException {
public void writeData(DataOutput dataOutput, T value) throws IOException {
T value = (T) v;
if (value == null) {
dataOutput.writeBoolean(false);
} else {
@@ -1,39 +1,69 @@
package com.avaje.ebeaninternal.server.type;
import com.avaje.ebean.config.JsonConfig;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import java.time.Instant;
/**
* Base type for DateTime types.
*/
public abstract class ScalarTypeBaseDateTime<T> extends ScalarTypeBase<T> {
protected DateTimeJsonParser dateTimeParser = new DateTimeJsonParser();
public ScalarTypeBaseDateTime(Class<T> type, boolean jdbcNative, int jdbcType) {
protected final DateTimeJsonParser dateTimeParser = new DateTimeJsonParser();
protected final JsonConfig.DateTime mode;
public ScalarTypeBaseDateTime(JsonConfig.DateTime mode, Class<T> type, boolean jdbcNative, int jdbcType) {
super(type, jdbcNative, jdbcType);
this.mode = mode;
}
public abstract long convertToMillis(Object value);
/**
* Convert the value to a Timestamp.
*/
public abstract Timestamp convertToTimestamp(T t);
/**
* Convert to the value from a Timestamp.
*/
public abstract T convertFromTimestamp(Timestamp ts);
/**
* Convert from epoch millis to the value.
*/
public abstract T convertFromMillis(long systemTimeMillis);
/**
* Convert from the value to epoch millis.
*/
public abstract long convertToMillis(T value);
/**
* Convert the value to time with nanos format.
*/
protected abstract String toJsonNanos(T value);
/**
* Convert the value to ISO8601 format.
*/
protected abstract String toJsonISO8601(T value);
public void bind(DataBind b, T value) throws SQLException {
if (value == null) {
b.setNull(Types.TIMESTAMP);
} else {
Timestamp ts = convertToTimestamp(value);
b.setTimestamp(ts);
b.setTimestamp(convertToTimestamp(value));
}
}
@@ -47,23 +77,49 @@ public abstract class ScalarTypeBaseDateTime<T> extends ScalarTypeBase<T> {
}
}
/**
* Helper method that given epoch seconds and nanos return a JSON nanos formatted string.
*/
protected String toJsonNanos(long epochSecs, int nanos) {
return DecimalUtils.toDecimal(epochSecs, nanos);
}
@Override
public Object jsonRead(JsonParser ctx, JsonToken event) throws IOException {
public T jsonRead(JsonParser ctx, JsonToken event) throws IOException {
if (JsonToken.VALUE_NUMBER_INT == event) {
long millis = ctx.getLongValue();
return parseDateTime(millis);
} else {
String jsonDateTime = ctx.getText();
return convertFromTimestamp(dateTimeParser.parse(jsonDateTime));
switch (event) {
case VALUE_NUMBER_INT: {
return convertFromMillis(ctx.getLongValue());
}
case VALUE_NUMBER_FLOAT: {
BigDecimal value = ctx.getDecimalValue();
//Instant instant = DecimalUtils.toInstant(value);
Timestamp timestamp = DecimalUtils.toTimestamp(value);
convertFromTimestamp(timestamp);//Timestamp.from(instant));
}
default: {
String jsonDateTime = ctx.getText();
return convertFromTimestamp(dateTimeParser.parse(jsonDateTime));
}
}
}
@Override
public void jsonWrite(JsonGenerator ctx, String name, Object value) throws IOException {
long millis = convertToMillis(value);
ctx.writeNumberField(name, millis);
public void jsonWrite(JsonGenerator generator, String name, T value) throws IOException {
switch (mode) {
case ISO8601: {
generator.writeNumber(toJsonISO8601(value));
break;
}
case NANOS: {
generator.writeNumber(toJsonNanos(value));
break;
}
default: {
generator.writeNumberField(name, convertToMillis(value));
}
}
}
public String formatValue(T t) {
@@ -76,16 +132,12 @@ public abstract class ScalarTypeBaseDateTime<T> extends ScalarTypeBase<T> {
return convertFromTimestamp(ts);
}
public T parseDateTime(long systemTimeMillis) {
Timestamp ts = new Timestamp(systemTimeMillis);
return convertFromTimestamp(ts);
}
public boolean isDateTimeCapable() {
return true;
}
public Object readData(DataInput dataInput) throws IOException {
public T readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
return null;
} else {
@@ -95,10 +147,8 @@ public abstract class ScalarTypeBaseDateTime<T> extends ScalarTypeBase<T> {
}
}
@SuppressWarnings("unchecked")
public void writeData(DataOutput dataOutput, Object v) throws IOException {
public void writeData(DataOutput dataOutput, T value) throws IOException {
T value = (T) v;
if (value == null) {
dataOutput.writeBoolean(false);
} else {
@@ -86,7 +86,7 @@ public abstract class ScalarTypeBaseVarchar<T> extends ScalarTypeBase<T> {
}
@Override
public T parseDateTime(long systemTimeMillis) {
public T convertFromMillis(long systemTimeMillis) {
throw new TextException("Not Supported");
}
@@ -102,7 +102,7 @@ public abstract class ScalarTypeBaseVarchar<T> extends ScalarTypeBase<T> {
}
@Override
public Object readData(DataInput dataInput) throws IOException {
public T readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
return null;
} else {
@@ -111,10 +111,8 @@ public abstract class ScalarTypeBaseVarchar<T> extends ScalarTypeBase<T> {
}
}
@SuppressWarnings("unchecked")
public void writeData(DataOutput dataOutput, Object v) throws IOException {
public void writeData(DataOutput dataOutput, T value) throws IOException {
T value = (T) v;
if (value == null) {
dataOutput.writeBoolean(false);
} else {
@@ -125,12 +123,12 @@ public abstract class ScalarTypeBaseVarchar<T> extends ScalarTypeBase<T> {
}
@Override
public Object jsonRead(JsonParser ctx, JsonToken event) throws IOException {
public T jsonRead(JsonParser ctx, JsonToken event) throws IOException {
return parse(ctx.getValueAsString());
}
@Override
public void jsonWrite(JsonGenerator ctx, String name, Object value) throws IOException {
public void jsonWrite(JsonGenerator ctx, String name, T value) throws IOException {
ctx.writeStringField(name, format(value));
}
}
@@ -17,75 +17,73 @@ import com.fasterxml.jackson.core.JsonToken;
*/
public class ScalarTypeBigDecimal extends ScalarTypeBase<BigDecimal> {
public ScalarTypeBigDecimal() {
super(BigDecimal.class, true, Types.DECIMAL);
}
public Object readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
return null;
} else {
double val = dataInput.readDouble();
return new BigDecimal(val);
}
public ScalarTypeBigDecimal() {
super(BigDecimal.class, true, Types.DECIMAL);
}
public BigDecimal readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
return null;
} else {
double val = dataInput.readDouble();
return new BigDecimal(val);
}
}
public void writeData(DataOutput dataOutput, Object v) throws IOException {
BigDecimal b = (BigDecimal)v;
if (b == null){
dataOutput.writeBoolean(false);
} else {
dataOutput.writeBoolean(true);
dataOutput.writeDouble(b.doubleValue());
}
public void writeData(DataOutput dataOutput, BigDecimal b) throws IOException {
if (b == null) {
dataOutput.writeBoolean(false);
} else {
dataOutput.writeBoolean(true);
dataOutput.writeDouble(b.doubleValue());
}
public void bind(DataBind b, BigDecimal value) throws SQLException {
if (value == null){
b.setNull(Types.DECIMAL);
} else {
b.setBigDecimal(value);
}
}
}
public BigDecimal read(DataReader dataReader) throws SQLException {
return dataReader.getBigDecimal();
}
public Object toJdbcType(Object value) {
return BasicTypeConverter.toBigDecimal(value);
}
public BigDecimal toBeanType(Object value) {
return BasicTypeConverter.toBigDecimal(value);
}
public String formatValue(BigDecimal t) {
return t.toPlainString();
public void bind(DataBind b, BigDecimal value) throws SQLException {
if (value == null) {
b.setNull(Types.DECIMAL);
} else {
b.setBigDecimal(value);
}
}
public BigDecimal parse(String value) {
return new BigDecimal(value);
}
public BigDecimal read(DataReader dataReader) throws SQLException {
public BigDecimal parseDateTime(long systemTimeMillis) {
return BigDecimal.valueOf(systemTimeMillis);
}
return dataReader.getBigDecimal();
}
public boolean isDateTimeCapable() {
return true;
}
public Object toJdbcType(Object value) {
return BasicTypeConverter.toBigDecimal(value);
}
public BigDecimal toBeanType(Object value) {
return BasicTypeConverter.toBigDecimal(value);
}
public String formatValue(BigDecimal t) {
return t.toPlainString();
}
public BigDecimal parse(String value) {
return new BigDecimal(value);
}
public BigDecimal convertFromMillis(long systemTimeMillis) {
return BigDecimal.valueOf(systemTimeMillis);
}
public boolean isDateTimeCapable() {
return true;
}
@Override
public Object jsonRead(JsonParser ctx, JsonToken event) throws IOException {
public BigDecimal jsonRead(JsonParser ctx, JsonToken event) throws IOException {
return ctx.getDecimalValue();
}
public void jsonWrite(JsonGenerator ctx, String name, Object value) throws IOException {
ctx.writeNumberField(name, (BigDecimal)value);
public void jsonWrite(JsonGenerator ctx, String name, BigDecimal value) throws IOException {
ctx.writeNumberField(name, (BigDecimal) value);
}
}
@@ -261,7 +261,7 @@ public class ScalarTypeBoolean {
return Boolean.valueOf(value);
}
public Boolean parseDateTime(long systemTimeMillis) {
public Boolean convertFromMillis(long systemTimeMillis) {
throw new TextException("Not Supported");
}
@@ -269,32 +269,30 @@ public class ScalarTypeBoolean {
return false;
}
public Object readData(DataInput dataInput) throws IOException {
public Boolean readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
return null;
} else {
boolean val = dataInput.readBoolean();
return Boolean.valueOf(val);
return dataInput.readBoolean();
}
}
public void writeData(DataOutput dataOutput, Object v) throws IOException {
public void writeData(DataOutput dataOutput, Boolean val) throws IOException {
Boolean val = (Boolean) v;
if (val == null) {
dataOutput.writeBoolean(false);
} else {
dataOutput.writeBoolean(true);
dataOutput.writeBoolean(val.booleanValue());
dataOutput.writeBoolean(val);
}
}
@Override
public Object jsonRead(JsonParser ctx, JsonToken event) {
public Boolean jsonRead(JsonParser ctx, JsonToken event) {
return JsonToken.VALUE_TRUE == event ? Boolean.TRUE : Boolean.FALSE;
}
public void jsonWrite(JsonGenerator ctx, String name, Object value) throws IOException {
public void jsonWrite(JsonGenerator ctx, String name, Boolean value) throws IOException {
ctx.writeBooleanField(name, (Boolean) value);
}
}
@@ -42,12 +42,12 @@ public class ScalarTypeByte extends ScalarTypeBase<Byte> {
}
@Override
public void jsonWrite(JsonGenerator ctx, String name, Object value) throws IOException {
public void jsonWrite(JsonGenerator ctx, String name, Byte value) throws IOException {
throw new IOException("Not supported");
}
@Override
public Object jsonRead(JsonParser ctx, JsonToken event) throws IOException {
public Byte jsonRead(JsonParser ctx, JsonToken event) throws IOException {
throw new IOException("Not supported");
}
@@ -59,7 +59,7 @@ public class ScalarTypeByte extends ScalarTypeBase<Byte> {
throw new TextException("Not supported");
}
public Byte parseDateTime(long systemTimeMillis) {
public Byte convertFromMillis(long systemTimeMillis) {
throw new TextException("Not Supported");
}
@@ -67,18 +67,16 @@ public class ScalarTypeByte extends ScalarTypeBase<Byte> {
return false;
}
public Object readData(DataInput dataInput) throws IOException {
public Byte readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
return null;
} else {
byte val = dataInput.readByte();
return Byte.valueOf(val);
return dataInput.readByte();
}
}
public void writeData(DataOutput dataOutput, Object v) throws IOException {
public void writeData(DataOutput dataOutput, Byte val) throws IOException {
Byte val = (Byte) v;
if (val == null) {
dataOutput.writeBoolean(false);
} else {
@@ -45,12 +45,12 @@ public abstract class ScalarTypeBytesBase extends ScalarTypeBase<byte[]> {
}
@Override
public void jsonWrite(JsonGenerator ctx, String name, Object value) throws IOException {
public void jsonWrite(JsonGenerator ctx, String name, byte[] value) throws IOException {
ctx.writeBinaryField(name, (byte[]) value);
}
@Override
public Object jsonRead(JsonParser ctx, JsonToken event) throws IOException {
public byte[] jsonRead(JsonParser ctx, JsonToken event) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream(500);
ctx.readBinaryValue(out);
return out.toByteArray();
@@ -64,7 +64,7 @@ public abstract class ScalarTypeBytesBase extends ScalarTypeBase<byte[]> {
throw new TextException("Not supported");
}
public byte[] parseDateTime(long systemTimeMillis) {
public byte[] convertFromMillis(long systemTimeMillis) {
throw new TextException("Not supported");
}
@@ -72,7 +72,7 @@ public abstract class ScalarTypeBytesBase extends ScalarTypeBase<byte[]> {
return false;
}
public Object readData(DataInput dataInput) throws IOException {
public byte[] readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
return null;
} else {
@@ -83,10 +83,11 @@ public abstract class ScalarTypeBytesBase extends ScalarTypeBase<byte[]> {
}
}
public void writeData(DataOutput dataOutput, Object v) throws IOException {
public void writeData(DataOutput dataOutput, byte[] v) throws IOException {
if (v == null) {
dataOutput.writeBoolean(false);
} else {
dataOutput.writeBoolean(true);
byte[] bytes = convertToBytes(v);
dataOutput.writeInt(bytes.length);
dataOutput.write(bytes);
@@ -67,12 +67,12 @@ public class ScalarTypeBytesEncrypted implements ScalarType<byte[]> {
}
@Override
public void jsonWrite(JsonGenerator ctx, String name, Object value) throws IOException {
public void jsonWrite(JsonGenerator ctx, String name, byte[] value) throws IOException {
ctx.writeBinaryField(name, (byte[]) value);
}
@Override
public Object jsonRead(JsonParser ctx, JsonToken event) throws IOException {
public byte[] jsonRead(JsonParser ctx, JsonToken event) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream(500);
ctx.readBinaryValue(out);
return out.toByteArray();
@@ -90,8 +90,8 @@ public class ScalarTypeBytesEncrypted implements ScalarType<byte[]> {
return baseType.parse(value);
}
public byte[] parseDateTime(long systemTimeMillis) {
return baseType.parseDateTime(systemTimeMillis);
public byte[] convertFromMillis(long systemTimeMillis) {
return baseType.convertFromMillis(systemTimeMillis);
}
public byte[] read(DataReader dataReader) throws SQLException {
@@ -113,17 +113,26 @@ public class ScalarTypeBytesEncrypted implements ScalarType<byte[]> {
baseType.accumulateScalarTypes(propName, list);
}
public Object readData(DataInput dataInput) throws IOException {
int len = dataInput.readInt();
byte[] value = new byte[len];
dataInput.readFully(value);
return value;
public byte[] readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
return null;
} else {
int len = dataInput.readInt();
byte[] value = new byte[len];
dataInput.readFully(value);
return value;
}
}
public void writeData(DataOutput dataOutput, Object v) throws IOException {
byte[] value = (byte[]) v;
dataOutput.writeInt(value.length);
dataOutput.write(value);
public void writeData(DataOutput dataOutput, byte[] value) throws IOException {
if (value == null) {
dataOutput.writeBoolean(false);
} else {
dataOutput.writeBoolean(true);
dataOutput.writeInt(value.length);
dataOutput.write(value);
}
}
}
@@ -6,6 +6,7 @@ import java.sql.Timestamp;
import java.sql.Types;
import java.util.Calendar;
import com.avaje.ebean.config.JsonConfig;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
/**
@@ -13,25 +14,32 @@ import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
*/
public class ScalarTypeCalendar extends ScalarTypeBaseDateTime<Calendar> {
public ScalarTypeCalendar(int jdbcType) {
super(Calendar.class, false, jdbcType);
public ScalarTypeCalendar(JsonConfig.DateTime mode, int jdbcType) {
super(mode, Calendar.class, false, jdbcType);
}
public void bind(DataBind b, Calendar value) throws SQLException {
if (value == null) {
b.setNull(Types.TIMESTAMP);
} else {
Calendar date = (Calendar) value;
if (jdbcType == Types.TIMESTAMP) {
Timestamp timestamp = new Timestamp(date.getTimeInMillis());
Timestamp timestamp = new Timestamp(value.getTimeInMillis());
b.setTimestamp(timestamp);
} else {
Date d = new Date(date.getTimeInMillis());
Date d = new Date(value.getTimeInMillis());
b.setDate(d);
}
}
}
@Override
public Calendar convertFromMillis(long systemTimeMillis) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(systemTimeMillis);
return calendar;
}
@Override
public Calendar convertFromTimestamp(Timestamp ts) {
Calendar calendar = Calendar.getInstance();
@@ -40,8 +48,18 @@ public class ScalarTypeCalendar extends ScalarTypeBaseDateTime<Calendar> {
}
@Override
public long convertToMillis(Object value) {
return ((Calendar) value).getTimeInMillis();
protected String toJsonNanos(Calendar value) {
return String.valueOf(value.getTime());
}
@Override
protected String toJsonISO8601(Calendar value) {
return dateTimeParser.format(value.getTime());
}
@Override
public long convertToMillis(Calendar value) {
return value.getTimeInMillis();
}
@Override
@@ -49,10 +67,12 @@ public class ScalarTypeCalendar extends ScalarTypeBaseDateTime<Calendar> {
return new Timestamp(t.getTimeInMillis());
}
@Override
public Object toJdbcType(Object value) {
return BasicTypeConverter.convert(value, jdbcType);
}
@Override
public Calendar toBeanType(Object value) {
return BasicTypeConverter.toCalendar(value);
}
@@ -64,11 +64,11 @@ public class ScalarTypeCharArray extends ScalarTypeBaseVarchar<char[]> {
}
@Override
public Object jsonRead(JsonParser ctx, JsonToken event) throws IOException {
public char[] jsonRead(JsonParser ctx, JsonToken event) throws IOException {
return ctx.getValueAsString().toCharArray();
}
public void jsonWrite(JsonGenerator ctx, String name, Object value) throws IOException {
public void jsonWrite(JsonGenerator ctx, String name, char[] value) throws IOException {
ctx.writeStringField(name, String.valueOf(value));
}
}
@@ -55,7 +55,7 @@ public class ScalarTypeDouble extends ScalarTypeBase<Double> {
}
@Override
public Double parseDateTime(long systemTimeMillis) {
public Double convertFromMillis(long systemTimeMillis) {
return Double.valueOf(systemTimeMillis);
}
@@ -65,34 +65,32 @@ public class ScalarTypeDouble extends ScalarTypeBase<Double> {
}
@Override
public Object readData(DataInput dataInput) throws IOException {
public Double readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
return null;
} else {
double val = dataInput.readDouble();
return Double.valueOf(val);
return dataInput.readDouble();
}
}
@Override
public void writeData(DataOutput dataOutput, Object v) throws IOException {
public void writeData(DataOutput dataOutput, Double value) throws IOException {
Double value = (Double) v;
if (value == null) {
dataOutput.writeBoolean(false);
} else {
dataOutput.writeBoolean(true);
dataOutput.writeDouble(value.doubleValue());
dataOutput.writeDouble(value);
}
}
@Override
public Object jsonRead(JsonParser ctx, JsonToken event) throws IOException {
public Double jsonRead(JsonParser ctx, JsonToken event) throws IOException {
return ctx.getDoubleValue();
}
@Override
public void jsonWrite(JsonGenerator ctx, String name, Object value) throws IOException {
ctx.writeNumberField(name, (Double) value);
public void jsonWrite(JsonGenerator ctx, String name, Double value) throws IOException {
ctx.writeNumberField(name, value);
}
}
@@ -0,0 +1,104 @@
package com.avaje.ebeaninternal.server.type;
import com.avaje.ebean.text.TextException;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.sql.SQLException;
import java.sql.Types;
import java.time.Duration;
import java.time.LocalTime;
/**
* ScalarType for java.time.Duration
*/
public class ScalarTypeDuration extends ScalarTypeBase<Duration> {
public ScalarTypeDuration() {
super(Duration.class, false, Types.BIGINT);
}
protected ScalarTypeDuration(int jdbcType) {
super(Duration.class, false, jdbcType);
}
@Override
public void bind(DataBind bind, Duration value) throws SQLException {
if (value == null) {
bind.setNull(Types.BIGINT);
} else {
bind.setLong(value.getSeconds());
}
}
@Override
public Duration read(DataReader dataReader) throws SQLException {
return Duration.ofSeconds(dataReader.getLong());
}
@Override
public Duration readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
return null;
} else {
return Duration.ofSeconds(dataInput.readLong());
}
}
@Override
public void writeData(DataOutput dataOutput, Duration value) throws IOException {
if (value == null) {
dataOutput.writeBoolean(false);
} else {
dataOutput.writeBoolean(true);
dataOutput.writeLong(value.getSeconds());
}
}
@Override
public Object toJdbcType(Object value) {
if (value instanceof Long) return value;
return ((Duration)value).getSeconds();
}
@Override
public Duration toBeanType(Object value) {
if (value instanceof Duration) return (Duration) value;
return Duration.ofSeconds(BasicTypeConverter.toLong(value));
}
@Override
public String formatValue(Duration v) {
return v.toString();
}
@Override
public Duration parse(String value) {
return Duration.parse(value);
}
@Override
public boolean isDateTimeCapable() {
return false;
}
@Override
public Duration convertFromMillis(long systemTimeMillis) {
throw new TextException("Not Supported");
}
@Override
public Duration jsonRead(JsonParser ctx, JsonToken event) throws IOException {
return Duration.parse(ctx.getValueAsString());
}
@Override
public void jsonWrite(JsonGenerator ctx, String name, Duration value) throws IOException {
ctx.writeStringField(name, value.toString());
}
}
@@ -0,0 +1,82 @@
package com.avaje.ebeaninternal.server.type;
import com.avaje.ebean.text.TextException;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.sql.Types;
import java.time.Duration;
/**
* ScalarType for java.time.Duration with Nanos precision.
* <p>
* Stored in the DB as DECIMAL value.
* </p>
*/
public class ScalarTypeDurationWithNanos extends ScalarTypeDuration {
public ScalarTypeDurationWithNanos() {
super(Types.DECIMAL);
}
public BigDecimal convertToBigDecimal(Duration value) {
return DecimalUtils.toDecimal(value);
}
public Duration convertFromBigDecimal(BigDecimal value) {
return DecimalUtils.toDuration(value);
}
@Override
public void bind(DataBind bind, Duration value) throws SQLException {
if (value == null) {
bind.setNull(Types.DECIMAL);
} else {
bind.setBigDecimal(convertToBigDecimal(value));
}
}
@Override
public Duration read(DataReader dataReader) throws SQLException {
return convertFromBigDecimal(dataReader.getBigDecimal());
}
@Override
public Duration readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
return null;
} else {
return convertFromBigDecimal(new BigDecimal(dataInput.readUTF()));
}
}
@Override
public void writeData(DataOutput dataOutput, Duration value) throws IOException {
if (value == null) {
dataOutput.writeBoolean(false);
} else {
dataOutput.writeBoolean(true);
dataOutput.writeUTF(convertToBigDecimal(value).toString());
}
}
@Override
public Object toJdbcType(Object value) {
if (value instanceof BigDecimal) return value;
return convertToBigDecimal((Duration)value);
}
@Override
public Duration toBeanType(Object value) {
if (value instanceof Duration) return (Duration) value;
return convertFromBigDecimal(BasicTypeConverter.toBigDecimal(value));
}
}
@@ -34,12 +34,12 @@ public class ScalarTypeEncryptedWrapper<T> implements ScalarType<T> {
}
@Override
public Object readData(DataInput dataInput) throws IOException {
public T readData(DataInput dataInput) throws IOException {
return wrapped.readData(dataInput);
}
@Override
public void writeData(DataOutput dataOutput, Object v) throws IOException {
public void writeData(DataOutput dataOutput, T v) throws IOException {
wrapped.writeData(dataOutput, v);
}
@@ -113,8 +113,8 @@ public class ScalarTypeEncryptedWrapper<T> implements ScalarType<T> {
}
@Override
public T parseDateTime(long systemTimeMillis) {
return wrapped.parseDateTime(systemTimeMillis);
public T convertFromMillis(long systemTimeMillis) {
return wrapped.convertFromMillis(systemTimeMillis);
}
@Override
@@ -133,12 +133,12 @@ public class ScalarTypeEncryptedWrapper<T> implements ScalarType<T> {
}
@Override
public Object jsonRead(JsonParser ctx, JsonToken event) throws IOException {
public T jsonRead(JsonParser ctx, JsonToken event) throws IOException {
return wrapped.jsonRead(ctx, event);
}
@Override
public void jsonWrite(JsonGenerator ctx, String name, Object value) throws IOException {
public void jsonWrite(JsonGenerator ctx, String name, T value) throws IOException {
wrapped.jsonWrite(ctx, name, value);
}
}
@@ -222,7 +222,7 @@ public class ScalarTypeEnumStandard {
}
@Override
public Object parseDateTime(long systemTimeMillis) {
public Object convertFromMillis(long systemTimeMillis) {
throw new TextException("Not Supported");
}
@@ -55,7 +55,7 @@ public class ScalarTypeFloat extends ScalarTypeBase<Float> {
}
@Override
public Float parseDateTime(long systemTimeMillis) {
public Float convertFromMillis(long systemTimeMillis) {
return Float.valueOf(systemTimeMillis);
}
@@ -65,7 +65,7 @@ public class ScalarTypeFloat extends ScalarTypeBase<Float> {
}
@Override
public Object readData(DataInput dataInput) throws IOException {
public Float readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
return null;
} else {
@@ -75,24 +75,23 @@ public class ScalarTypeFloat extends ScalarTypeBase<Float> {
}
@Override
public void writeData(DataOutput dataOutput, Object v) throws IOException {
public void writeData(DataOutput dataOutput, Float value) throws IOException {
Float value = (Float) v;
if (value == null) {
dataOutput.writeBoolean(false);
} else {
dataOutput.writeBoolean(true);
dataOutput.writeFloat(value.floatValue());
dataOutput.writeFloat(value);
}
}
@Override
public Object jsonRead(JsonParser ctx, JsonToken event) throws IOException {
public Float jsonRead(JsonParser ctx, JsonToken event) throws IOException {
return ctx.getFloatValue();
}
@Override
public void jsonWrite(JsonGenerator ctx, String name, Object value) throws IOException {
public void jsonWrite(JsonGenerator ctx, String name, Float value) throws IOException {
ctx.writeNumberField(name, (Float) value);
}
}
@@ -0,0 +1,59 @@
package com.avaje.ebeaninternal.server.type;
import com.avaje.ebean.config.JsonConfig;
import java.sql.Timestamp;
import java.sql.Types;
import java.time.Instant;
/**
* ScalarType for java.sql.Timestamp.
*/
public class ScalarTypeInstant extends ScalarTypeBaseDateTime<Instant> {
public ScalarTypeInstant(JsonConfig.DateTime mode) {
super(mode, Instant.class, true, Types.TIMESTAMP);
}
@Override
protected String toJsonNanos(Instant value) {
return toJsonNanos(value.getEpochSecond(), value.getNano());
}
@Override
protected String toJsonISO8601(Instant value) {
return value.toString();
}
@Override
public long convertToMillis(Instant value) {
return value.toEpochMilli();
}
@Override
public Instant convertFromMillis(long systemTimeMillis) {
return Instant.ofEpochMilli(systemTimeMillis);
}
@Override
public Instant convertFromTimestamp(Timestamp ts) {
return ts.toInstant();
}
@Override
public Timestamp convertToTimestamp(Instant t) {
return Timestamp.from(t);
}
@Override
public Object toJdbcType(Object value) {
if (value instanceof Timestamp) return value;
return convertToTimestamp((Instant) value);
}
@Override
public Instant toBeanType(Object value) {
if (value instanceof Instant) return (Instant) value;
return convertFromTimestamp((Timestamp) value);
}
}
@@ -36,13 +36,22 @@ public class ScalarTypeInteger extends ScalarTypeBase<Integer> {
}
@Override
public Object readData(DataInput dataInput) throws IOException {
return Integer.valueOf(dataInput.readInt());
public Integer readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
return null;
} else {
return Integer.valueOf(dataInput.readInt());
}
}
@Override
public void writeData(DataOutput dataOutput, Object v) throws IOException {
dataOutput.writeInt((Integer) v);
public void writeData(DataOutput dataOutput, Integer value) throws IOException {
if (value == null) {
dataOutput.writeBoolean(false);
} else {
dataOutput.writeBoolean(true);
dataOutput.writeInt(value);
}
}
@Override
@@ -66,7 +75,7 @@ public class ScalarTypeInteger extends ScalarTypeBase<Integer> {
}
@Override
public Integer parseDateTime(long systemTimeMillis) {
public Integer convertFromMillis(long systemTimeMillis) {
throw new TextException("Not Supported");
}
@@ -76,12 +85,12 @@ public class ScalarTypeInteger extends ScalarTypeBase<Integer> {
}
@Override
public Object jsonRead(JsonParser ctx, JsonToken event) throws IOException {
public Integer jsonRead(JsonParser ctx, JsonToken event) throws IOException {
return ctx.getIntValue();
}
@Override
public void jsonWrite(JsonGenerator ctx, String name, Object value) throws IOException {
ctx.writeNumberField(name, (Integer) value);
public void jsonWrite(JsonGenerator ctx, String name, Integer value) throws IOException {
ctx.writeNumberField(name, value);
}
}
@@ -3,22 +3,39 @@ package com.avaje.ebeaninternal.server.type;
import java.sql.Timestamp;
import java.sql.Types;
import com.avaje.ebean.config.JsonConfig;
import org.joda.time.DateTime;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
import org.joda.time.LocalDateTime;
/**
* ScalarType for Joda DateTime. This maps to a JDBC Timestamp.
*/
public class ScalarTypeJodaDateTime extends ScalarTypeBaseDateTime<DateTime> {
public ScalarTypeJodaDateTime() {
super(DateTime.class, false, Types.TIMESTAMP);
public ScalarTypeJodaDateTime(JsonConfig.DateTime mode) {
super(mode, DateTime.class, false, Types.TIMESTAMP);
}
@Override
public long convertToMillis(Object value) {
return ((DateTime) value).getMillis();
public long convertToMillis(DateTime value) {
return value.getMillis();
}
@Override
protected String toJsonNanos(DateTime value) {
return String.valueOf(value.toDateTime().getMillis());
}
@Override
protected String toJsonISO8601(DateTime value) {
return value.toString();
}
@Override
public DateTime convertFromMillis(long systemTimeMillis) {
return new DateTime(systemTimeMillis);
}
@Override
@@ -48,7 +48,7 @@ public class ScalarTypeJodaLocalDate extends ScalarTypeBaseDate<LocalDate> {
}
@Override
public LocalDate parseDateTime(long systemTimeMillis) {
public LocalDate convertFromMillis(long systemTimeMillis) {
return new LocalDate(systemTimeMillis);
}
@@ -2,7 +2,9 @@ package com.avaje.ebeaninternal.server.type;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.Date;
import com.avaje.ebean.config.JsonConfig;
import org.joda.time.LocalDateTime;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
@@ -12,13 +14,29 @@ import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
*/
public class ScalarTypeJodaLocalDateTime extends ScalarTypeBaseDateTime<LocalDateTime> {
public ScalarTypeJodaLocalDateTime() {
super(LocalDateTime.class, false, Types.TIMESTAMP);
public ScalarTypeJodaLocalDateTime(JsonConfig.DateTime mode) {
super(mode, LocalDateTime.class, false, Types.TIMESTAMP);
}
@Override
public long convertToMillis(Object value) {
return ((LocalDateTime) value).toDateTime().getMillis();
protected String toJsonNanos(LocalDateTime value) {
return String.valueOf(value.toDateTime().getMillis());
}
@Override
protected String toJsonISO8601(LocalDateTime value) {
return value.toString();
}
@Override
public long convertToMillis(LocalDateTime value) {
return value.toDateTime().getMillis();
}
@Override
public LocalDateTime convertFromMillis(long systemTimeMillis) {
return new LocalDateTime(systemTimeMillis);
}
@Override
@@ -47,9 +65,4 @@ public class ScalarTypeJodaLocalDateTime extends ScalarTypeBaseDateTime<LocalDat
return (LocalDateTime) value;
}
@Override
public LocalDateTime parseDateTime(long systemTimeMillis) {
return new LocalDateTime(systemTimeMillis);
}
}
@@ -72,15 +72,15 @@ public class ScalarTypeJodaLocalTime extends ScalarTypeBase<LocalTime> {
}
@Override
public void jsonWrite(JsonGenerator ctx, String name, Object value) throws IOException {
public void jsonWrite(JsonGenerator ctx, String name, LocalTime value) throws IOException {
ctx.writeStringField(name, value.toString());
}
@Override
public Object jsonRead(JsonParser ctx, JsonToken event) throws IOException {
public LocalTime jsonRead(JsonParser ctx, JsonToken event) throws IOException {
if (JsonToken.VALUE_NUMBER_INT == event) {
long millis = ctx.getLongValue();
return parseDateTime(millis);
return convertFromMillis(millis);
} else {
String string = ctx.getValueAsString();
throw new RuntimeException("convert " + string);
@@ -88,7 +88,7 @@ public class ScalarTypeJodaLocalTime extends ScalarTypeBase<LocalTime> {
}
@Override
public LocalTime parseDateTime(long systemTimeMillis) {
public LocalTime convertFromMillis(long systemTimeMillis) {
return new LocalTime(systemTimeMillis);
}
@@ -98,7 +98,7 @@ public class ScalarTypeJodaLocalTime extends ScalarTypeBase<LocalTime> {
}
@Override
public Object readData(DataInput dataInput) throws IOException {
public LocalTime readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
return null;
} else {
@@ -108,9 +108,8 @@ public class ScalarTypeJodaLocalTime extends ScalarTypeBase<LocalTime> {
}
@Override
public void writeData(DataOutput dataOutput, Object v) throws IOException {
public void writeData(DataOutput dataOutput, LocalTime value) throws IOException {
Time value = (Time) v;
if (value == null) {
dataOutput.writeBoolean(false);
} else {
@@ -52,7 +52,7 @@ public class ScalarTypeLocalDate extends ScalarTypeBaseDate<LocalDate> {
}
@Override
public LocalDate parseDateTime(long systemTimeMillis) {
public LocalDate convertFromMillis(long systemTimeMillis) {
return new Timestamp(systemTimeMillis).toLocalDateTime().toLocalDate();
}
@@ -1,21 +1,40 @@
package com.avaje.ebeaninternal.server.type;
import com.avaje.ebean.config.JsonConfig;
import java.sql.Timestamp;
import java.sql.Types;
import java.time.*;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
/**
* ScalarType for java.sql.Timestamp.
*/
public class ScalarTypeLocalDateTime extends ScalarTypeBaseDateTime<LocalDateTime> {
public ScalarTypeLocalDateTime() {
super(LocalDateTime.class, true, Types.TIMESTAMP);
public ScalarTypeLocalDateTime(JsonConfig.DateTime mode) {
super(mode, LocalDateTime.class, true, Types.TIMESTAMP);
}
@Override
public long convertToMillis(Object value) {
return ((LocalDateTime) value).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
public LocalDateTime convertFromMillis(long systemTimeMillis) {
return new Timestamp(systemTimeMillis).toLocalDateTime();
}
@Override
public long convertToMillis(LocalDateTime value) {
return value.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
}
@Override
protected String toJsonNanos(LocalDateTime value) {
return String.valueOf(convertToMillis(value));
}
@Override
protected String toJsonISO8601(LocalDateTime value) {
return value.toString();
}
@Override
@@ -0,0 +1,100 @@
package com.avaje.ebeaninternal.server.type;
import com.avaje.ebean.text.TextException;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.sql.SQLException;
import java.sql.Types;
import java.time.LocalTime;
import java.time.Year;
/**
* ScalarType for java.time.Year
*/
public class ScalarTypeLocalTime extends ScalarTypeBase<LocalTime> {
public ScalarTypeLocalTime() {
super(LocalTime.class, true, Types.BIGINT);
}
@Override
public void bind(DataBind bind, LocalTime value) throws SQLException {
if (value == null) {
bind.setNull(Types.BIGINT);
} else {
bind.setLong(value.toNanoOfDay());
}
}
@Override
public LocalTime read(DataReader dataReader) throws SQLException {
return LocalTime.ofNanoOfDay(dataReader.getLong());
}
@Override
public LocalTime readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
return null;
} else {
return LocalTime.ofNanoOfDay(dataInput.readLong());
}
}
@Override
public void writeData(DataOutput dataOutput, LocalTime value) throws IOException {
if (value == null) {
dataOutput.writeBoolean(false);
} else {
dataOutput.writeBoolean(true);
dataOutput.writeLong(value.toNanoOfDay());
}
}
@Override
public Object toJdbcType(Object value) {
if (value instanceof Long) return value;
return ((LocalTime)value).toNanoOfDay();
}
@Override
public LocalTime toBeanType(Object value) {
if (value instanceof LocalTime) return (LocalTime) value;
return LocalTime.ofNanoOfDay(BasicTypeConverter.toLong(value));
}
@Override
public String formatValue(LocalTime v) {
return v.toString();
}
@Override
public LocalTime parse(String value) {
return LocalTime.parse(value);
}
@Override
public boolean isDateTimeCapable() {
return false;
}
@Override
public LocalTime convertFromMillis(long systemTimeMillis) {
throw new TextException("Not Supported");
}
@Override
public LocalTime jsonRead(JsonParser ctx, JsonToken event) throws IOException {
return LocalTime.parse(ctx.getValueAsString());
}
@Override
public void jsonWrite(JsonGenerator ctx, String name, LocalTime value) throws IOException {
ctx.writeStringField(name, value.toString());
}
}
@@ -55,8 +55,8 @@ public class ScalarTypeLong extends ScalarTypeBase<Long> {
}
@Override
public Long parseDateTime(long systemTimeMillis) {
return Long.valueOf(systemTimeMillis);
public Long convertFromMillis(long systemTimeMillis) {
return systemTimeMillis;
}
@Override
@@ -65,34 +65,32 @@ public class ScalarTypeLong extends ScalarTypeBase<Long> {
}
@Override
public Object readData(DataInput dataInput) throws IOException {
public Long readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
return null;
} else {
long val = dataInput.readLong();
return Long.valueOf(val);
return dataInput.readLong();
}
}
@Override
public void writeData(DataOutput dataOutput, Object v) throws IOException {
public void writeData(DataOutput dataOutput, Long value) throws IOException {
Long value = (Long) v;
if (value == null) {
dataOutput.writeBoolean(false);
} else {
dataOutput.writeBoolean(true);
dataOutput.writeLong(value.longValue());
dataOutput.writeLong(value);
}
}
@Override
public Object jsonRead(JsonParser ctx, JsonToken event) throws IOException {
public Long jsonRead(JsonParser ctx, JsonToken event) throws IOException {
return ctx.getLongValue();
}
@Override
public void jsonWrite(JsonGenerator ctx, String name, Object value) throws IOException {
public void jsonWrite(JsonGenerator ctx, String name, Long value) throws IOException {
ctx.writeNumberField(name, (Long) value);
}
}
@@ -1,10 +1,12 @@
package com.avaje.ebeaninternal.server.type;
import com.avaje.ebean.config.JsonConfig;
import java.sql.Timestamp;
public class ScalarTypeLongToTimestamp extends ScalarTypeWrapper<Long, Timestamp> {
public ScalarTypeLongToTimestamp() {
super(Long.class, new ScalarTypeTimestamp(), new LongToTimestampConverter());
public ScalarTypeLongToTimestamp(JsonConfig.DateTime mode) {
super(Long.class, new ScalarTypeTimestamp(mode), new LongToTimestampConverter());
}
}
@@ -3,9 +3,11 @@ package com.avaje.ebeaninternal.server.type;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.SQLException;
import java.sql.Types;
import java.time.Instant;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
import com.fasterxml.jackson.core.JsonGenerator;
@@ -61,7 +63,7 @@ public class ScalarTypeMathBigInteger extends ScalarTypeBase<BigInteger> {
}
@Override
public BigInteger parseDateTime(long systemTimeMillis) {
public BigInteger convertFromMillis(long systemTimeMillis) {
return BigInteger.valueOf(systemTimeMillis);
}
@@ -71,19 +73,18 @@ public class ScalarTypeMathBigInteger extends ScalarTypeBase<BigInteger> {
}
@Override
public Object readData(DataInput dataInput) throws IOException {
public BigInteger readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
return null;
} else {
long val = dataInput.readLong();
return Long.valueOf(val);
return BigInteger.valueOf(val);
}
}
@Override
public void writeData(DataOutput dataOutput, Object v) throws IOException {
public void writeData(DataOutput dataOutput, BigInteger value) throws IOException {
Long value = (Long) v;
if (value == null) {
dataOutput.writeBoolean(false);
} else {
@@ -93,12 +94,12 @@ public class ScalarTypeMathBigInteger extends ScalarTypeBase<BigInteger> {
}
@Override
public Object jsonRead(JsonParser ctx, JsonToken event) throws IOException {
public BigInteger jsonRead(JsonParser ctx, JsonToken event) throws IOException {
return ctx.getDecimalValue().toBigInteger();
}
@Override
public void jsonWrite(JsonGenerator ctx, String name, Object value) throws IOException {
public void jsonWrite(JsonGenerator ctx, String name, BigInteger value) throws IOException {
ctx.writeNumberField(name, ((BigInteger) value).longValue());
}
@@ -1,7 +1,10 @@
package com.avaje.ebeaninternal.server.type;
import com.avaje.ebean.config.JsonConfig;
import java.sql.Timestamp;
import java.sql.Types;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneId;
@@ -10,13 +13,28 @@ import java.time.ZoneId;
*/
public class ScalarTypeOffsetDateTime extends ScalarTypeBaseDateTime<OffsetDateTime> {
public ScalarTypeOffsetDateTime() {
super(OffsetDateTime.class, true, Types.TIMESTAMP);
public ScalarTypeOffsetDateTime(JsonConfig.DateTime mode) {
super(mode, OffsetDateTime.class, true, Types.TIMESTAMP);
}
@Override
public long convertToMillis(Object value) {
return ((OffsetDateTime) value).toInstant().toEpochMilli();
protected String toJsonNanos(OffsetDateTime value) {
return toJsonNanos(value.toEpochSecond(), value.getNano());
}
@Override
protected String toJsonISO8601(OffsetDateTime value) {
return value.toString();
}
@Override
public long convertToMillis(OffsetDateTime value) {
return value.toInstant().toEpochMilli();
}
@Override
public OffsetDateTime convertFromMillis(long systemTimeMillis) {
return OffsetDateTime.ofInstant(Instant.ofEpochMilli(systemTimeMillis), ZoneId.systemDefault());
}
@Override
@@ -88,7 +88,7 @@ public class ScalarTypePostgresHstore extends ScalarTypeBase<Map> {
}
@Override
public Map parseDateTime(long dateTime) {
public Map convertFromMillis(long dateTime) {
throw new RuntimeException("Should never be called");
}
@@ -98,19 +98,28 @@ public class ScalarTypePostgresHstore extends ScalarTypeBase<Map> {
}
@Override
public Object readData(DataInput dataInput) throws IOException {
String json = dataInput.readUTF();
return parse(json);
public Map readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
return null;
} else {
String json = dataInput.readUTF();
return parse(json);
}
}
@Override
public void writeData(DataOutput dataOutput, Object v) throws IOException {
String json = format(v);
dataOutput.writeUTF(json);
public void writeData(DataOutput dataOutput, Map v) throws IOException {
if (v == null) {
dataOutput.writeBoolean(false);
} else {
dataOutput.writeBoolean(true);
String json = format(v);
dataOutput.writeUTF(json);
}
}
@Override
public void jsonWrite(JsonGenerator ctx, String name, Object value) throws IOException {
public void jsonWrite(JsonGenerator ctx, String name, Map value) throws IOException {
// write the field name followed by the Map/JSON Object
if (value == null) {
ctx.writeNullField(name);
@@ -121,7 +130,7 @@ public class ScalarTypePostgresHstore extends ScalarTypeBase<Map> {
}
@Override
public Object jsonRead(JsonParser ctx, JsonToken event) throws IOException {
public Map jsonRead(JsonParser ctx, JsonToken event) throws IOException {
// at this point the BeanProperty has read the START_OBJECT token
// to check for a null value. Pass the START_OBJECT token through to
// the EJson parsing so that it knows the first token has been read
@@ -56,7 +56,7 @@ public class ScalarTypeShort extends ScalarTypeBase<Short> {
}
@Override
public Short parseDateTime(long systemTimeMillis) {
public Short convertFromMillis(long systemTimeMillis) {
throw new TextException("Not Supported");
}
@@ -66,34 +66,32 @@ public class ScalarTypeShort extends ScalarTypeBase<Short> {
}
@Override
public Object readData(DataInput dataInput) throws IOException {
public Short readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
return null;
} else {
short val = dataInput.readShort();
return Short.valueOf(val);
return dataInput.readShort();
}
}
@Override
public void writeData(DataOutput dataOutput, Object v) throws IOException {
public void writeData(DataOutput dataOutput, Short value) throws IOException {
Short value = (Short) v;
if (value == null) {
dataOutput.writeBoolean(false);
} else {
dataOutput.writeBoolean(true);
dataOutput.writeShort(value.shortValue());
dataOutput.writeShort(value);
}
}
@Override
public Object jsonRead(JsonParser ctx, JsonToken event) throws IOException {
public Short jsonRead(JsonParser ctx, JsonToken event) throws IOException {
return ctx.getShortValue();
}
@Override
public void jsonWrite(JsonGenerator ctx, String name, Object value) throws IOException {
public void jsonWrite(JsonGenerator ctx, String name, Short value) throws IOException {
ctx.writeNumberField(name, (Short) value);
}
}
@@ -55,7 +55,7 @@ public class ScalarTypeString extends ScalarTypeBase<String> {
}
@Override
public String parseDateTime(long systemTimeMillis) {
public String convertFromMillis(long systemTimeMillis) {
return String.valueOf(systemTimeMillis);
}
@@ -65,7 +65,7 @@ public class ScalarTypeString extends ScalarTypeBase<String> {
}
@Override
public Object readData(DataInput dataInput) throws IOException {
public String readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
return null;
} else {
@@ -74,9 +74,8 @@ public class ScalarTypeString extends ScalarTypeBase<String> {
}
@Override
public void writeData(DataOutput dataOutput, Object v) throws IOException {
public void writeData(DataOutput dataOutput, String value) throws IOException {
String value = (String) v;
if (value == null) {
dataOutput.writeBoolean(false);
} else {
@@ -86,12 +85,12 @@ public class ScalarTypeString extends ScalarTypeBase<String> {
}
@Override
public Object jsonRead(JsonParser ctx, JsonToken event) throws IOException {
public String jsonRead(JsonParser ctx, JsonToken event) throws IOException {
return ctx.getValueAsString();
}
@Override
public void jsonWrite(JsonGenerator ctx, String name, Object value) throws IOException {
public void jsonWrite(JsonGenerator ctx, String name, String value) throws IOException {
ctx.writeStringField(name, (String) value);
}
}
@@ -56,7 +56,7 @@ public class ScalarTypeTime extends ScalarTypeBase<Time> {
}
@Override
public Time parseDateTime(long systemTimeMillis) {
public Time convertFromMillis(long systemTimeMillis) {
return new Time(systemTimeMillis);
}
@@ -66,7 +66,7 @@ public class ScalarTypeTime extends ScalarTypeBase<Time> {
}
@Override
public Object readData(DataInput dataInput) throws IOException {
public Time readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
return null;
} else {
@@ -76,9 +76,8 @@ public class ScalarTypeTime extends ScalarTypeBase<Time> {
}
@Override
public void writeData(DataOutput dataOutput, Object v) throws IOException {
public void writeData(DataOutput dataOutput, Time value) throws IOException {
Time value = (Time) v;
if (value == null) {
dataOutput.writeBoolean(false);
} else {
@@ -88,12 +87,12 @@ public class ScalarTypeTime extends ScalarTypeBase<Time> {
}
@Override
public Object jsonRead(JsonParser ctx, JsonToken event) throws IOException {
public Time jsonRead(JsonParser ctx, JsonToken event) throws IOException {
return parse(ctx.getValueAsString());
}
@Override
public void jsonWrite(JsonGenerator ctx, String name, Object value) throws IOException {
public void jsonWrite(JsonGenerator ctx, String name, Time value) throws IOException {
ctx.writeStringField(name, format(value));
}
@@ -3,7 +3,9 @@ package com.avaje.ebeaninternal.server.type;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.time.OffsetDateTime;
import com.avaje.ebean.config.JsonConfig;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
/**
@@ -11,13 +13,28 @@ import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
*/
public class ScalarTypeTimestamp extends ScalarTypeBaseDateTime<Timestamp> {
public ScalarTypeTimestamp() {
super(Timestamp.class, true, Types.TIMESTAMP);
public ScalarTypeTimestamp(JsonConfig.DateTime mode) {
super(mode, Timestamp.class, true, Types.TIMESTAMP);
}
@Override
public long convertToMillis(Object value) {
return ((Timestamp) value).getTime();
protected String toJsonNanos(Timestamp value) {
return String.valueOf(value.getTime());
}
@Override
protected String toJsonISO8601(Timestamp value) {
return dateTimeParser.format(value);
}
@Override
public long convertToMillis(Timestamp value) {
return value.getTime();
}
@Override
public Timestamp convertFromMillis(long systemTimeMillis) {
return new Timestamp(systemTimeMillis);
}
@Override
@@ -30,6 +47,8 @@ public class ScalarTypeTimestamp extends ScalarTypeBaseDateTime<Timestamp> {
return t;
}
@Override
public void bind(DataBind b, Timestamp value) throws SQLException {
if (value == null) {
@@ -47,7 +47,7 @@ public class ScalarTypeUUIDBinary extends ScalarTypeBase<UUID> {
}
@Override
public UUID parseDateTime(long dateTime) {
public UUID convertFromMillis(long dateTime) {
throw new IllegalStateException("Never called");
}
@@ -124,33 +124,32 @@ public class ScalarTypeUUIDBinary extends ScalarTypeBase<UUID> {
}
@Override
public Object readData(DataInput dataInput) throws IOException {
public UUID readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
return null;
} else {
return dataInput.readUTF();
return parse(dataInput.readUTF());
}
}
@Override
public void writeData(DataOutput dataOutput, Object v) throws IOException {
public void writeData(DataOutput dataOutput, UUID value) throws IOException {
String value = (String) v;
if (value == null) {
dataOutput.writeBoolean(false);
} else {
dataOutput.writeBoolean(true);
dataOutput.writeUTF(format(v));
dataOutput.writeUTF(format(value));
}
}
@Override
public Object jsonRead(JsonParser ctx, JsonToken event) throws IOException {
public UUID jsonRead(JsonParser ctx, JsonToken event) throws IOException {
return UUID.fromString(ctx.getValueAsString());
}
@Override
public void jsonWrite(JsonGenerator ctx, String name, Object value) throws IOException {
public void jsonWrite(JsonGenerator ctx, String name, UUID value) throws IOException {
ctx.writeStringField(name, value.toString());
}
@@ -5,6 +5,7 @@ import java.sql.Timestamp;
import java.sql.Types;
import java.util.Date;
import com.avaje.ebean.config.JsonConfig;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
/**
@@ -12,92 +13,108 @@ import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
*/
public class ScalarTypeUtilDate {
public static class TimestampType extends ScalarTypeBaseDateTime<java.util.Date> {
public static class TimestampType extends ScalarTypeBaseDateTime<java.util.Date> {
public TimestampType(JsonConfig.DateTime mode) {
super(mode, java.util.Date.class, false, Types.TIMESTAMP);
}
@Override
protected String toJsonNanos(Date value) {
return String.valueOf(value.getTime());
}
@Override
protected String toJsonISO8601(Date value) {
return dateTimeParser.format(value);
}
@Override
public long convertToMillis(Date value) {
return value.getTime();
}
@Override
public java.util.Date read(DataReader dataReader) throws SQLException {
Timestamp timestamp = dataReader.getTimestamp();
if (timestamp == null) {
return null;
} else {
return new java.util.Date(timestamp.getTime());
}
}
@Override
public void bind(DataBind b, java.util.Date value)
throws SQLException {
if (value == null) {
b.setNull(Types.TIMESTAMP);
} else {
Timestamp timestamp = new Timestamp(value.getTime());
b.setTimestamp(timestamp);
}
}
@Override
public Object toJdbcType(Object value) {
return BasicTypeConverter.toTimestamp(value);
}
@Override
public java.util.Date toBeanType(Object value) {
return BasicTypeConverter.toUtilDate(value);
}
@Override
public Date convertFromTimestamp(Timestamp ts) {
return new java.util.Date(ts.getTime());
}
@Override
public Timestamp convertToTimestamp(Date t) {
return new Timestamp(t.getTime());
}
@Override
public java.util.Date convertFromMillis(long systemTimeMillis) {
return new java.util.Date(systemTimeMillis);
}
}
public static class DateType extends ScalarTypeBaseDate<java.util.Date> {
public DateType() {
super(Date.class, false, Types.DATE);
}
public TimestampType() {
super(java.util.Date.class, false, Types.TIMESTAMP);
}
@Override
public long convertToMillis(Object value) {
return BasicTypeConverter.toTimestamp(value).getTime();
}
public java.util.Date read(DataReader dataReader) throws SQLException {
Timestamp timestamp = dataReader.getTimestamp();
if (timestamp == null) {
return null;
} else {
return new java.util.Date(timestamp.getTime());
}
}
public void bind(DataBind b, java.util.Date value)
throws SQLException {
if (value == null) {
b.setNull(Types.TIMESTAMP);
} else {
Timestamp timestamp = new Timestamp(value.getTime());
b.setTimestamp(timestamp);
}
}
public Object toJdbcType(Object value) {
return BasicTypeConverter.toTimestamp(value);
}
public java.util.Date toBeanType(Object value) {
return BasicTypeConverter.toUtilDate(value);
}
@Override
public Date convertFromTimestamp(Timestamp ts) {
return new java.util.Date(ts.getTime());
}
@Override
public Timestamp convertToTimestamp(Date t) {
return new Timestamp(t.getTime());
}
public java.util.Date parseDateTime(long systemTimeMillis) {
return new java.util.Date(systemTimeMillis);
}
}
public static class DateType extends ScalarTypeBaseDate<java.util.Date> {
public DateType() {
super(Date.class, false, Types.DATE);
}
@Override
public long convertToMillis(Object value) {
java.sql.Date date = BasicTypeConverter.toDate(value);
java.sql.Date date = BasicTypeConverter.toDate(value);
return date.getTime();
}
@Override
public Date convertFromDate(java.sql.Date ts) {
return new java.util.Date(ts.getTime());
}
public Date convertFromDate(java.sql.Date ts) {
return new java.util.Date(ts.getTime());
}
@Override
public java.sql.Date convertToDate(Date t) {
return new java.sql.Date(t.getTime());
}
@Override
public java.sql.Date convertToDate(Date t) {
return new java.sql.Date(t.getTime());
}
public Object toJdbcType(Object value) {
return BasicTypeConverter.toDate(value);
}
@Override
public Object toJdbcType(Object value) {
return BasicTypeConverter.toDate(value);
}
public java.util.Date toBeanType(Object value) {
return BasicTypeConverter.toUtilDate(value);
}
}
@Override
public java.util.Date toBeanType(Object value) {
return BasicTypeConverter.toUtilDate(value);
}
}
}
@@ -57,16 +57,16 @@ public class ScalarTypeWrapper<B, S> implements ScalarType<B> {
@Override
@SuppressWarnings("unchecked")
public Object readData(DataInput dataInput) throws IOException {
Object v = scalarType.readData(dataInput);
return converter.wrapValue((S) v);
public B readData(DataInput dataInput) throws IOException {
S unwrapValue = scalarType.readData(dataInput);
return converter.wrapValue(unwrapValue);
}
@Override
@SuppressWarnings("unchecked")
public void writeData(DataOutput dataOutput, Object v) throws IOException {
S sv = converter.unwrapValue((B) v);
scalarType.writeData(dataOutput, sv);
public void writeData(DataOutput dataOutput, B value) throws IOException {
S unwrapValue = converter.unwrapValue(value);
scalarType.writeData(dataOutput, unwrapValue);
}
@Override
@@ -126,8 +126,8 @@ public class ScalarTypeWrapper<B, S> implements ScalarType<B> {
}
@Override
public B parseDateTime(long systemTimeMillis) {
S sv = scalarType.parseDateTime(systemTimeMillis);
public B convertFromMillis(long systemTimeMillis) {
S sv = scalarType.convertFromMillis(systemTimeMillis);
if (sv == null) {
return nullValue;
}
@@ -185,17 +185,15 @@ public class ScalarTypeWrapper<B, S> implements ScalarType<B> {
return this;
}
@SuppressWarnings("unchecked")
@Override
public Object jsonRead(JsonParser ctx, JsonToken event) throws IOException {
Object object = scalarType.jsonRead(ctx, event);
return converter.wrapValue((S) object);
public B jsonRead(JsonParser ctx, JsonToken event) throws IOException {
S object = scalarType.jsonRead(ctx, event);
return converter.wrapValue(object);
}
@Override
public void jsonWrite(JsonGenerator ctx, String name, Object beanValue) throws IOException {
@SuppressWarnings("unchecked")
S unwrapValue = converter.unwrapValue((B) beanValue);
public void jsonWrite(JsonGenerator ctx, String name, B beanValue) throws IOException {
S unwrapValue = converter.unwrapValue(beanValue);
scalarType.jsonWrite(ctx, name, unwrapValue);
}
@@ -0,0 +1,99 @@
package com.avaje.ebeaninternal.server.type;
import com.avaje.ebean.text.TextException;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.sql.SQLException;
import java.sql.Types;
import java.time.Year;
/**
* ScalarType for java.time.Year
*/
public class ScalarTypeYear extends ScalarTypeBase<Year> {
public ScalarTypeYear() {
super(Year.class, true, Types.INTEGER);
}
@Override
public void bind(DataBind bind, Year value) throws SQLException {
if (value == null) {
bind.setNull(Types.INTEGER);
} else {
bind.setInt(value.getValue());
}
}
@Override
public Year read(DataReader dataReader) throws SQLException {
return Year.of(dataReader.getInt());
}
@Override
public Year readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
return null;
} else {
return Year.of(dataInput.readInt());
}
}
@Override
public void writeData(DataOutput dataOutput, Year value) throws IOException {
if (value == null) {
dataOutput.writeBoolean(false);
} else {
dataOutput.writeBoolean(true);
dataOutput.writeInt(value.getValue());
}
}
@Override
public Object toJdbcType(Object value) {
if (value instanceof Year) return ((Year)value).getValue();
return BasicTypeConverter.toInteger(value);
}
@Override
public Year toBeanType(Object value) {
if (value instanceof Year) return (Year) value;
return Year.of(BasicTypeConverter.toInteger(value));
}
@Override
public String formatValue(Year v) {
return v.toString();
}
@Override
public Year parse(String value) {
return Year.parse(value);
}
@Override
public boolean isDateTimeCapable() {
return false;
}
@Override
public Year convertFromMillis(long systemTimeMillis) {
throw new TextException("Not Supported");
}
@Override
public Year jsonRead(JsonParser ctx, JsonToken event) throws IOException {
return Year.of(ctx.getIntValue());
}
@Override
public void jsonWrite(JsonGenerator ctx, String name, Year value) throws IOException {
ctx.writeNumberField(name, value.getValue());
}
}