Merge pull request #202 from ebean-orm/java8

Add support for java.time types, tidy up ScalarTypes
This commit is contained in:
Rob Bygrave
2014-11-19 00:13:37 +13:00
129 changed files with 4548 additions and 1057 deletions
+1 -1
View File
@@ -182,7 +182,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<version>3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
@@ -457,6 +457,30 @@ public interface EbeanServer {
* Execute the query visiting the results. This is similar to findIterate in
* that not all the result beans need to be held in memory at the same time
* and as such is go for processing large queries.
*
* @see Query#findEach(QueryEachConsumer)
*/
public <T> void findEach(Query<T> query, QueryEachConsumer<T> consumer, Transaction transaction);
/**
* Execute the query visiting the results. This is similar to findIterate in
* that not all the result beans need to be held in memory at the same time
* and as such is go for processing large queries.
*
* @see Query#findEachWhile(QueryEachWhileConsumer)
*/
public <T> void findEachWhile(Query<T> query, QueryEachWhileConsumer<T> consumer, Transaction transaction);
/**
* Deprecated in favor of #findEachWhile which is functionally exactly the same
* but has a much better name.
* <p>
* Execute the query visiting the results. This is similar to findIterate in
* that not all the result beans need to be held in memory at the same time
* and as such is go for processing large queries.
* </p>
*
* @deprecated
*/
public <T> void findVisit(Query<T> query, QueryResultVisitor<T> visitor, Transaction transaction);
@@ -102,9 +102,25 @@ public interface ExpressionList<T> extends Serializable {
public QueryIterator<T> findIterate();
/**
* Execute the query visiting the results.
*
* @see Query#findVisit(QueryResultVisitor)
* Execute the query process the beans one at a time.
*
* @see Query#findEach(QueryEachConsumer)
*/
public void findEach(QueryEachConsumer<T> consumer);
/**
* Execute the query processing the beans one at a time with the ability to
* stop processing before reading all the beans.
*
* @see Query#findEachWhile(QueryEachWhileConsumer)
*/
public void findEachWhile(QueryEachWhileConsumer<T> consumer);
/**
* Deprecated in favor of #findEachWhile which is functionally exactly the same
* but has a much better name.
*
* @deprecated
*/
public void findVisit(QueryResultVisitor<T> visitor);
+31
View File
@@ -328,6 +328,37 @@ public abstract class Model {
return query().findIds();
}
/**
* Execute the query consuming each bean one at a time.
* <p>
* This is generally used to process large queries where unlike findList
* you do not want to hold all the results in memory at once but instead
* process them one at a time (requiring far less memory).
* </p>
* Equivalent to {@link Query#findEach(QueryEachConsumer)}
*/
public void findEach(QueryEachConsumer<T> consumer) {
query().findEach(consumer);
}
/**
* Execute the query consuming each bean one at a time.
* <p>
* This is similar to #findEach except that you return boolean
* true to continue processing beans and return false to stop
* processing early.
* </p>
* <p>
* This is generally used to process large queries where unlike findList
* you do not want to hold all the results in memory at once but instead
* process them one at a time (requiring far less memory).
* </p>
* Equivalent to {@link Query#findEachWhile(QueryEachWhileConsumer)}
*/
public void findEachWhile(QueryEachWhileConsumer<T> consumer) {
query().findEachWhile(consumer);
}
/**
* Retrieves all entities of the given type.
* <p>
+67 -15
View File
@@ -446,37 +446,89 @@ public interface Query<T> extends Serializable {
*/
public QueryIterator<T> findIterate();
/**
* This is deprecated in favor of #findEachWhile.
* <p>
* This is functionally exactly the same as #findEachWhile. It is
* replaced by findEachWhile because the method name is much better.
* </p>
*
* @param visitor
* the visitor used to process the queried beans.
*
* @deprecated
*/
public void findVisit(QueryResultVisitor<T> visitor);
/**
* Execute the query processing the beans one at a time.
* <p>
* This method is appropriate to process very large query results as the
* beans are consumed one at a time and do not need to be held in memory
* (unlike #findList #findSet etc)
* </p>
* <p>
* Compared with #findEachWhile this will always process all the beans where as
* #findEachWhile provides a way to stop processing the query result early before
* all the beans have been read.
* </p>
* <p>
* This method is functionally equivalent to findIterate() but instead of using an
* iterator uses the QueryEachConsumer (SAM) interface which is better suited to use
* with Java8 closures.
* </p>
*
* <pre class="code">
*
* Query&lt;Customer&gt; query = server.find(Customer.class)
* .where().gt(&quot;id&quot;, 0)
* .orderBy(&quot;id&quot;)
* .setMaxRows(2);
*
* query.findVisit((Customer customer) -> {
*
* // do something with customer
* System.out.println(&quot;-- visit &quot; + customer);
* });
* </pre>
*
* @param consumer
* the consumer used to process the queried beans.
*/
public void findEach(QueryEachConsumer<T> consumer);
/**
* Execute the query using callbacks to a visitor to process the resulting
* beans one at a time.
* <p>
* Similar to findIterate() this query method does not require all the result
* beans to be all held in memory at once and as such is useful for processing
* large queries.
* This method is functionally equivalent to findIterate() but instead of using an
* iterator uses the QueryEachWhileConsumer (SAM) interface which is better suited to use
* with Java8 closures.
* </p>
*
*
* <pre class="code">
*
*
* Query&lt;Customer&gt; query = server.find(Customer.class)
* .fetch(&quot;contacts&quot;, new FetchConfig().query(2))
* .where().gt(&quot;id&quot;, 0)
* .orderBy(&quot;id&quot;)
* .setMaxRows(2);
*
* query.findVisit(new QueryResultVisitor&lt;Customer&gt;() {
*
* public boolean accept(Customer customer) {
*
* query.findEachWhile((Customer customer) -> {
*
* // do something with customer
* System.out.println(&quot;-- visit &quot; + customer);
* return true;
* }
*
* // return true to continue processing or false to stop
* return (customer.getId() < 40);
* });
* </pre>
*
* @param visitor
* the visitor used to process the queried beans.
*
* @param consumer
* the consumer used to process the queried beans.
*/
public void findVisit(QueryResultVisitor<T> visitor);
public void findEachWhile(QueryEachWhileConsumer<T> consumer);
/**
* Execute the query returning the list of objects.
@@ -0,0 +1,41 @@
package com.avaje.ebean;
/**
* Used to process a query result one bean at a time via a callback to this
* visitor.
* <p>
* If you wish to stop further processing return false from the accept method.
* </p>
* <p>
* Unlike findList() and findSet() using a QueryResultVisitor does not require
* all the beans in the query result to be held in memory at once. This makes
* QueryResultVisitor useful for processing large queries.
* </p>
*
* <pre class="code">
*
* Query&lt;Customer&gt; query = server.find(Customer.class)
* .where().gt(&quot;id&quot;, 0)
* .orderBy(&quot;id&quot;)
* .setMaxRows(2);
*
* query.findVisit((Customer customer) -> {
*
* // do something with customer
* System.out.println(&quot;-- visit &quot; + customer);
* });
* </pre>
*
* @param <T>
* the type of entity bean being queried.
*/
public interface QueryEachConsumer<T> {
/**
* Process the bean.
*
* @param bean
* the entity bean to process
*/
public void accept(T bean);
}
@@ -0,0 +1,45 @@
package com.avaje.ebean;
/**
* Used to process a query result one bean at a time via a callback to this
* visitor.
* <p>
* If you wish to stop further processing return false from the accept method.
* </p>
* <p>
* Unlike findList() and findSet() using a QueryResultVisitor does not require
* all the beans in the query result to be held in memory at once. This makes
* QueryResultVisitor useful for processing large queries.
* </p>
* <p/>
* <pre class="code">
*
* Query&lt;Customer&gt; query = server.find(Customer.class)
* .fetch(&quot;contacts&quot;, new FetchConfig().query(2))
* .where().gt(&quot;id&quot;, 0)
* .orderBy(&quot;id&quot;)
* .setMaxRows(2);
*
* query.findEachWhile((Customer customer) -> {
*
* // do something with customer
* System.out.println(&quot;-- visit &quot; + customer);
*
* // return true to continue processing or false to stop
* return (customer.getId() < 40);
* });
* </pre>
*
* @param <T> the type of entity bean being queried.
*/
public interface QueryEachWhileConsumer<T> {
/**
* Process the bean and return true if you want to continue processing more
* beans. Return false if you want to stop processing further.
*
* @param bean the entity bean to process
* @return true to continue processing more beans or false to stop.
*/
public boolean accept(T bean);
}
@@ -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.
*/
@@ -217,7 +222,7 @@ public class ServerConfig {
* Setting to indicate if UUID should be stored as binary(16) or varchar(40).
*/
private boolean uuidStoreAsBinary;
private List<BeanPersistController> persistControllers = new ArrayList<BeanPersistController>();
private List<BeanPersistListener<?>> persistListeners = new ArrayList<BeanPersistListener<?>>();
@@ -241,9 +246,13 @@ public class ServerConfig {
private boolean collectQueryStatsByNode;
private boolean collectQueryOrigins;
private JsonFactory jsonFactory;
private boolean localTimeWithNanos;
private boolean durationWithNanos;
/**
* Construct a Server Configuration for programmatically creating an
* EbeanServer.
@@ -270,6 +279,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.
*/
@@ -859,6 +882,43 @@ public class ServerConfig {
this.uuidStoreAsBinary = uuidStoreAsBinary;
}
/**
* Return true if LocalTime should be persisted with nanos precision.
*/
public boolean isLocalTimeWithNanos() {
return localTimeWithNanos;
}
/**
* Set to true if LocalTime should be persisted with nanos precision.
* <p>
* Otherwise it is persisted using java.sql.Time which is seconds precision.
* </p>
*/
public void setLocalTimeWithNanos(boolean localTimeWithNanos) {
this.localTimeWithNanos = localTimeWithNanos;
}
/**
* Return true if Duration should be persisted with nanos precision (SQL DECIMAL).
* <p>
* Otherwise it is persisted with second precision (SQL INTEGER).
* </p>
*/
public boolean isDurationWithNanos() {
return durationWithNanos;
}
/**
* Set to true if Duration should be persisted with nanos precision (SQL DECIMAL).
* <p>
* Otherwise it is persisted with second precision (SQL INTEGER).
* </p>
*/
public void setDurationWithNanos(boolean durationWithNanos) {
this.durationWithNanos = durationWithNanos;
}
/**
* Set to true to run the DDL generation on startup.
*/
@@ -1364,10 +1424,18 @@ public class ServerConfig {
databaseBooleanFalse = p.get("databaseBooleanFalse", null);
databasePlatformName = p.get("databasePlatformName", null);
uuidStoreAsBinary = p.getBoolean("uuidStoreAsBinary", false);
localTimeWithNanos = p.getBoolean("localTimeWithNanos", false);
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);
@@ -17,36 +17,10 @@ import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.persistence.PersistenceException;
import com.avaje.ebean.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.avaje.ebean.AdminAutofetch;
import com.avaje.ebean.BackgroundExecutor;
import com.avaje.ebean.BeanState;
import com.avaje.ebean.CallableSql;
import com.avaje.ebean.Ebean;
import com.avaje.ebean.ExpressionFactory;
import com.avaje.ebean.Filter;
import com.avaje.ebean.FutureIds;
import com.avaje.ebean.FutureList;
import com.avaje.ebean.FutureRowCount;
import com.avaje.ebean.PagedList;
import com.avaje.ebean.PagingList;
import com.avaje.ebean.Query;
import com.avaje.ebean.QueryIterator;
import com.avaje.ebean.QueryResultVisitor;
import com.avaje.ebean.SqlFutureList;
import com.avaje.ebean.SqlQuery;
import com.avaje.ebean.SqlRow;
import com.avaje.ebean.SqlUpdate;
import com.avaje.ebean.Transaction;
import com.avaje.ebean.TxCallable;
import com.avaje.ebean.TxIsolation;
import com.avaje.ebean.TxRunnable;
import com.avaje.ebean.TxScope;
import com.avaje.ebean.TxType;
import com.avaje.ebean.Update;
import com.avaje.ebean.ValuePair;
import com.avaje.ebean.bean.BeanCollection;
import com.avaje.ebean.bean.CallStack;
import com.avaje.ebean.bean.EntityBean;
@@ -273,17 +247,14 @@ public final class DefaultServer implements SpiEbeanServer {
List<SpiEbeanPlugin> spiPlugins = new ArrayList<SpiEbeanPlugin>();
final Iterator<SpiEbeanPlugin> plugins = ServiceLoader.load(SpiEbeanPlugin.class).iterator();
while (plugins.hasNext()) {
SpiEbeanPlugin plugin = plugins.next();
for (SpiEbeanPlugin plugin : ServiceLoader.load(SpiEbeanPlugin.class)) {
spiPlugins.add(plugin);
plugin.setup(this, this.getDatabasePlatform(), config.getServerConfig());
if (plugin instanceof DdlGenerator) {
// backwards compatible
ddlGenerator = (DdlGenerator)plugin;
}
ddlGenerator = (DdlGenerator) plugin;
}
}
if (ddlGenerator == null) {
@@ -1413,12 +1384,27 @@ public final class DefaultServer implements SpiEbeanServer {
SpiOrmQueryRequest<T> request = createQueryRequest(Type.LIST, query, t);
try {
request.initTransIfRequired();
request.findVisit(visitor);
} finally {
// do nothing - findVisit garuntee's cleanup of the transaction if required
}
request.initTransIfRequired();
request.findVisit(visitor);
// no try finally - findVisit guarantee's cleanup of the transaction if required
}
public <T> void findEach(Query<T> query, QueryEachConsumer<T> consumer, Transaction t) {
SpiOrmQueryRequest<T> request = createQueryRequest(Type.LIST, query, t);
request.initTransIfRequired();
request.findEach(consumer);
// no try finally - findVisit guarantee's cleanup of the transaction if required
}
public <T> void findEachWhile(Query<T> query, QueryEachWhileConsumer<T> consumer, Transaction t) {
SpiOrmQueryRequest<T> request = createQueryRequest(Type.LIST, query, t);
request.initTransIfRequired();
request.findEachWhile(consumer);
// no try finally - findVisit guarantee's cleanup of the transaction if required
}
public <T> QueryIterator<T> findIterate(Query<T> query, Transaction t) {
@@ -1542,7 +1528,7 @@ public final class DefaultServer implements SpiEbeanServer {
@Override
public void markAsDirty(Object bean) {
if (bean instanceof EntityBean == false) {
if (!(bean instanceof EntityBean)) {
throw new IllegalArgumentException("This bean is not an EntityBean?");
}
// mark the bean as dirty (so that an update will not get skipped)
@@ -1650,7 +1636,7 @@ public final class DefaultServer implements SpiEbeanServer {
if (bean == null) {
throw new IllegalArgumentException(Message.msg("bean.isnull"));
}
if (bean instanceof EntityBean == false) {
if (!(bean instanceof EntityBean)) {
throw new IllegalArgumentException("Was expecting an EntityBean but got a "+bean.getClass());
}
return (EntityBean)bean;
@@ -1959,10 +1945,7 @@ public final class DefaultServer implements SpiEbeanServer {
public boolean isSupportedType(java.lang.reflect.Type genericType) {
TypeInfo typeInfo = ParamTypeHelper.getTypeInfo(genericType);
if (typeInfo == null) {
return false;
}
return getBeanDescriptor(typeInfo.getBeanType()) != null;
return typeInfo != null && getBeanDescriptor(typeInfo.getBeanType()) != null;
}
public Object getBeanId(Object bean) {
@@ -6,9 +6,7 @@ import java.util.Set;
import javax.persistence.PersistenceException;
import com.avaje.ebean.QueryIterator;
import com.avaje.ebean.QueryResultVisitor;
import com.avaje.ebean.RawSql;
import com.avaje.ebean.*;
import com.avaje.ebean.bean.BeanCollection;
import com.avaje.ebean.bean.PersistenceContext;
import com.avaje.ebean.event.BeanFinder;
@@ -234,6 +232,30 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
return idList.getIdList();
}
public void findEach(QueryEachConsumer<T> consumer) {
QueryIterator<T> it = queryEngine.findIterate(this);
try {
while (it.hasNext()) {
consumer.accept(it.next());
}
} finally {
it.close();
}
}
public void findEachWhile(QueryEachWhileConsumer<T> consumer) {
QueryIterator<T> it = queryEngine.findIterate(this);
try {
while (it.hasNext()) {
if (!consumer.accept(it.next())) {
break;
}
}
} finally {
it.close();
}
}
public void findVisit(QueryResultVisitor<T> visitor) {
QueryIterator<T> it = queryEngine.findIterate(this);
try {
@@ -4,6 +4,8 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import com.avaje.ebean.QueryEachConsumer;
import com.avaje.ebean.QueryEachWhileConsumer;
import com.avaje.ebean.QueryIterator;
import com.avaje.ebean.QueryResultVisitor;
import com.avaje.ebean.bean.BeanCollection;
@@ -65,7 +67,17 @@ public interface SpiOrmQueryRequest<T> {
*/
public void findVisit(QueryResultVisitor<T> visitor);
/**
/**
* Execute the find returning a QueryIterator and visitor pattern.
*/
public void findEach(QueryEachConsumer<T> consumer);
/**
* Execute the find returning a QueryIterator and visitor pattern.
*/
public void findEachWhile(QueryEachWhileConsumer<T> consumer);
/**
* Execute the find returning a QueryIterator.
*/
public QueryIterator<T> findIterate();
@@ -62,10 +62,10 @@ import com.avaje.ebeaninternal.server.deploy.parse.ReadAnnotations;
import com.avaje.ebeaninternal.server.deploy.parse.TransientProperties;
import com.avaje.ebeaninternal.server.idgen.UuidIdGenerator;
import com.avaje.ebeaninternal.server.lib.util.Dnode;
import com.avaje.ebeaninternal.server.reflect.BeanReflect;
import com.avaje.ebeaninternal.server.reflect.BeanReflectFactory;
import com.avaje.ebeaninternal.server.reflect.BeanReflectProperties;
import com.avaje.ebeaninternal.server.reflect.EnhanceBeanReflectFactory;
import com.avaje.ebeaninternal.server.properties.BeanPropertyInfo;
import com.avaje.ebeaninternal.server.properties.BeanPropertyInfoFactory;
import com.avaje.ebeaninternal.server.properties.BeanPropertiesReader;
import com.avaje.ebeaninternal.server.properties.EnhanceBeanPropertyInfoFactory;
import com.avaje.ebeaninternal.server.type.TypeManager;
/**
@@ -86,7 +86,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
*/
private final DeployInherit deplyInherit;
private final BeanReflectFactory reflectFactory;
private final BeanPropertyInfoFactory reflectFactory;
private final DeployUtil deployUtil;
@@ -1274,9 +1274,9 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
}
}
private BeanReflectFactory createReflectionFactory() {
private BeanPropertyInfoFactory createReflectionFactory() {
return new EnhanceBeanReflectFactory();
return new EnhanceBeanPropertyInfoFactory();
}
/**
@@ -1295,9 +1295,9 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
Class<?> beanType = desc.getBeanType();
BeanReflectProperties reflectProps = new BeanReflectProperties(beanType);
BeanPropertiesReader reflectProps = new BeanPropertiesReader(beanType);
BeanReflect beanReflect = reflectFactory.create(beanType);
BeanPropertyInfo beanReflect = reflectFactory.create(beanType);
desc.setBeanReflect(beanReflect);
desc.setProperties(reflectProps.getProperties());
@@ -27,8 +27,8 @@ import com.avaje.ebeaninternal.server.el.ElPropertyValue;
import com.avaje.ebeaninternal.server.lib.util.StringHelper;
import com.avaje.ebeaninternal.server.query.SqlBeanLoad;
import com.avaje.ebeaninternal.server.query.SqlJoinType;
import com.avaje.ebeaninternal.server.reflect.BeanReflectGetter;
import com.avaje.ebeaninternal.server.reflect.BeanReflectSetter;
import com.avaje.ebeaninternal.server.properties.BeanPropertyGetter;
import com.avaje.ebeaninternal.server.properties.BeanPropertySetter;
import com.avaje.ebeaninternal.server.text.json.WriteJson;
import com.avaje.ebeaninternal.server.type.DataBind;
import com.avaje.ebeaninternal.server.type.ScalarType;
@@ -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.
*/
@@ -219,9 +196,9 @@ public class BeanProperty implements ElPropertyValue {
*/
final GeneratedProperty generatedProperty;
final BeanReflectGetter getter;
final BeanPropertyGetter getter;
final BeanReflectSetter setter;
final BeanPropertySetter setter;
final BeanDescriptor<?> descriptor;
@@ -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,16 +666,21 @@ 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);
}
/**
* Get the property value from a compound value type.
*/
public Object getValueObject(Object bean) {
throw new RuntimeException("Expected to be called only on BeanPropertyCompoundScalar");
}
/**
* Return the value of the property method.
*/
@@ -759,19 +693,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 +747,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 +816,7 @@ public class BeanProperty implements ElPropertyValue {
/**
* Return the scalarType.
*/
public ScalarType<?> getScalarType() {
public ScalarType<Object> getScalarType() {
return scalarType;
}
@@ -923,7 +837,7 @@ public class BeanProperty implements ElPropertyValue {
}
public Object parseDateTime(long systemTimeMillis) {
return scalarType.parseDateTime(systemTimeMillis);
return scalarType.convertFromMillis(systemTimeMillis);
}
/**
@@ -1031,10 +945,6 @@ public class BeanProperty implements ElPropertyValue {
return version;
}
public String getDeployProperty() {
return dbColumn;
}
/**
* The database column name this is mapped to.
*/
@@ -1168,13 +1078,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.
@@ -89,19 +89,6 @@ public class BeanPropertyCompound extends BeanProperty {
}
}
/**
* Get the underlying compound type.
*/
@SuppressWarnings("unchecked")
public Object getValueUnderlying(EntityBean bean) {
Object value = getValue(bean);
if (typeConverter != null){
value = typeConverter.unwrapValue(value);
}
return value;
}
public ElPropertyValue buildElPropertyValue(String propName, String remainder, ElPropertyChainBuilder chain, boolean propertyDeploy) {
if (chain == null) {
@@ -7,7 +7,7 @@ import java.util.List;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.reflect.BeanReflectSetter;
import com.avaje.ebeaninternal.server.properties.BeanPropertySetter;
import com.avaje.ebeaninternal.server.type.CtCompoundProperty;
/**
@@ -22,7 +22,7 @@ import com.avaje.ebeaninternal.server.type.CtCompoundProperty;
*/
public class BeanPropertyCompoundRoot {
private final BeanReflectSetter setter;
private final BeanPropertySetter setter;
/**
* The method used to write the property.
@@ -6,93 +6,100 @@ import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.type.CtCompoundProperty;
/**
* A BeanProperty owned by a Compound value object that maps to
* A BeanProperty owned by a Compound value object that maps to
* a real scalar type.
*
* @author rbygrave
*/
public class BeanPropertyCompoundScalar extends BeanProperty {
private final BeanPropertyCompoundRoot rootProperty;
private final CtCompoundProperty ctProperty;
@SuppressWarnings("rawtypes")
private final ScalarTypeConverter typeConverter;
public BeanPropertyCompoundScalar(BeanPropertyCompoundRoot rootProperty, DeployBeanProperty scalarDeploy,
CtCompoundProperty ctProperty, ScalarTypeConverter<?, ?> typeConverter) {
super(scalarDeploy);
this.rootProperty = rootProperty;
this.ctProperty = ctProperty;
this.typeConverter = typeConverter;
}
private final BeanPropertyCompoundRoot rootProperty;
@SuppressWarnings("unchecked")
@Override
public Object getValue(EntityBean valueObject) {
Object val = valueObject;
if (typeConverter != null){
val = typeConverter.unwrapValue(val);
}
return ctProperty.getValue(val);
}
private final CtCompoundProperty ctProperty;
@Override
public void setValue(EntityBean bean, Object value) {
setValueInCompound(bean, value, false);
}
@SuppressWarnings("unchecked")
public void setValueInCompound(EntityBean bean, Object value, boolean intercept) {
Object compoundValue = ctProperty.setValue(bean, value);
if (compoundValue != null){
if (typeConverter != null){
compoundValue = typeConverter.wrapValue(compoundValue);
}
// we are at the top level and we have a compound value
// that we can set using the root property
if (intercept){
rootProperty.setRootValueIntercept(bean, compoundValue);
} else {
rootProperty.setRootValue(bean, compoundValue);
}
}
}
@SuppressWarnings("rawtypes")
private final ScalarTypeConverter typeConverter;
/**
* No interception on embedded scalar values inside a CVO.
*/
@Override
public void setValueIntercept(EntityBean bean, Object value) {
setValueInCompound(bean, value, true);
}
public BeanPropertyCompoundScalar(BeanPropertyCompoundRoot rootProperty, DeployBeanProperty scalarDeploy,
CtCompoundProperty ctProperty, ScalarTypeConverter<?, ?> typeConverter) {
/**
* No interception on embedded scalar values inside a CVO.
*/
@Override
public Object getValueIntercept(EntityBean bean) {
return getValue(bean);
}
super(scalarDeploy);
this.rootProperty = rootProperty;
this.ctProperty = ctProperty;
this.typeConverter = typeConverter;
}
@Override
public Object elGetReference(EntityBean bean) {
return getValue(bean);
/**
* Return one of the scalar values from a compound type.
*/
public Object getValueObject(Object compoundValue) {
if (typeConverter != null) {
compoundValue = typeConverter.unwrapValue(compoundValue);
}
return ctProperty.getValue(compoundValue);
}
@Override
public Object elGetValue(EntityBean bean) {
return getValue(bean);
@SuppressWarnings("unchecked")
@Override
public Object getValue(EntityBean valueObject) {
Object val = valueObject;
if (typeConverter != null) {
val = typeConverter.unwrapValue(val);
}
return ctProperty.getValue(val);
}
@Override
public void elSetValue(EntityBean bean, Object value, boolean populate) {//, boolean reference) {
super.elSetValue(bean, value, populate);
@Override
public void setValue(EntityBean bean, Object value) {
setValueInCompound(bean, value, false);
}
@SuppressWarnings("unchecked")
public void setValueInCompound(EntityBean bean, Object value, boolean intercept) {
Object compoundValue = ctProperty.setValue(bean, value);
if (compoundValue != null) {
if (typeConverter != null) {
compoundValue = typeConverter.wrapValue(compoundValue);
}
// we are at the top level and we have a compound value
// that we can set using the root property
if (intercept) {
rootProperty.setRootValueIntercept(bean, compoundValue);
} else {
rootProperty.setRootValue(bean, compoundValue);
}
}
}
/**
* No interception on embedded scalar values inside a CVO.
*/
@Override
public void setValueIntercept(EntityBean bean, Object value) {
setValueInCompound(bean, value, true);
}
/**
* No interception on embedded scalar values inside a CVO.
*/
@Override
public Object getValueIntercept(EntityBean bean) {
return getValue(bean);
}
@Override
public Object elGetReference(EntityBean bean) {
return getValue(bean);
}
@Override
public Object elGetValue(EntityBean bean) {
return getValue(bean);
}
@Override
public void elSetValue(EntityBean bean, Object value, boolean populate) {//, boolean reference) {
super.elSetValue(bean, value, populate);
}
}
@@ -36,7 +36,7 @@ import com.avaje.ebeaninternal.server.deploy.DRawSqlMeta;
import com.avaje.ebeaninternal.server.deploy.DeployNamedQuery;
import com.avaje.ebeaninternal.server.deploy.DeployNamedUpdate;
import com.avaje.ebeaninternal.server.deploy.InheritInfo;
import com.avaje.ebeaninternal.server.reflect.BeanReflect;
import com.avaje.ebeaninternal.server.properties.BeanPropertyInfo;
/**
* Describes Beans including their deployment information.
@@ -127,7 +127,7 @@ public class DeployBeanDescriptor<T> {
* Used to provide mechanism to new EntityBean instances. Generated code
* faster than reflection at this stage.
*/
private BeanReflect beanReflect;
private BeanPropertyInfo beanReflect;
private String[] properties;
/**
@@ -302,7 +302,7 @@ public class DeployBeanDescriptor<T> {
this.properties = props;
}
public BeanReflect getBeanReflect() {
public BeanPropertyInfo getBeanReflect() {
return beanReflect;
}
@@ -317,7 +317,7 @@ public class DeployBeanDescriptor<T> {
* Set the BeanReflect used to create new instances of an EntityBean. This
* could use reflection or code generation to do this.
*/
public void setBeanReflect(BeanReflect beanReflect) {
public void setBeanReflect(BeanPropertyInfo beanReflect) {
this.beanReflect = beanReflect;
}
@@ -20,8 +20,8 @@ import com.avaje.ebeaninternal.server.core.InternString;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor.EntityType;
import com.avaje.ebeaninternal.server.deploy.generatedproperty.GeneratedProperty;
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
import com.avaje.ebeaninternal.server.reflect.BeanReflectGetter;
import com.avaje.ebeaninternal.server.reflect.BeanReflectSetter;
import com.avaje.ebeaninternal.server.properties.BeanPropertyGetter;
import com.avaje.ebeaninternal.server.properties.BeanPropertySetter;
import com.avaje.ebeaninternal.server.type.ScalarType;
import com.avaje.ebeaninternal.server.type.ScalarTypeEnum;
import com.avaje.ebeaninternal.server.type.ScalarTypeWrapper;
@@ -202,9 +202,9 @@ public class DeployBeanProperty {
private int propertyIndex;
private BeanReflectGetter getter;
private BeanPropertyGetter getter;
private BeanReflectSetter setter;
private BeanPropertySetter setter;
/**
* Generator for insert or update timestamp etc.
@@ -414,7 +414,7 @@ public class DeployBeanProperty {
ScalarTypeEnum etype = (ScalarTypeEnum) scalarType;
// check dbColName IN ('A', 'I', 'D')
return "check (" + dbColumn + " in " + etype.getContraintInValues() + ")";
return "check (" + dbColumn + " in " + etype.getConstraintInValues() + ")";
}
return null;
}
@@ -439,11 +439,11 @@ public class DeployBeanProperty {
this.propertyIndex = propertyIndex;
}
public BeanReflectGetter getGetter() {
public BeanPropertyGetter getGetter() {
return getter;
}
public BeanReflectSetter getSetter() {
public BeanPropertySetter getSetter() {
return setter;
}
@@ -482,14 +482,14 @@ public class DeployBeanProperty {
/**
* Set the getter used to read the property value from a bean.
*/
public void setGetter(BeanReflectGetter getter) {
public void setGetter(BeanPropertyGetter getter) {
this.getter = getter;
}
/**
* Set the setter used to set the property value to a bean.
*/
public void setSetter(BeanReflectSetter setter) {
public void setSetter(BeanPropertySetter setter) {
this.setter = setter;
}
@@ -21,99 +21,99 @@ import com.avaje.ebeaninternal.server.type.ScalarType;
*/
public class DeployBeanPropertyCompound extends DeployBeanProperty {
final CtCompoundType<?> compoundType;
final CtCompoundType<?> compoundType;
final ScalarTypeConverter<?, ?> typeConverter;
final ScalarTypeConverter<?, ?> typeConverter;
DeployBeanEmbedded deployEmbedded;
/**
* Create the property.
*/
public DeployBeanPropertyCompound(DeployBeanDescriptor<?> desc, Class<?> targetType,
CtCompoundType<?> compoundType, ScalarTypeConverter<?, ?> typeConverter) {
super(desc, targetType, null, null);
this.compoundType = compoundType;
this.typeConverter = typeConverter;
}
DeployBeanEmbedded deployEmbedded;
public BeanPropertyCompoundRoot getFlatProperties(BeanDescriptorMap owner, BeanDescriptor<?> descriptor) {
// get a 'flat' list of all the scalar types, their relative property names
// and also set their matching dbColumn
// represents the root property
BeanPropertyCompoundRoot rootProperty = new BeanPropertyCompoundRoot(this);
// Walk the tree of a compound type collecting the
// scalar types and non-scalar properties
CtCompoundTypeScalarList ctMeta = new CtCompoundTypeScalarList();
compoundType.accumulateScalarTypes(null, ctMeta);
List<BeanProperty> beanPropertyList = new ArrayList<BeanProperty>();
// for each of the scalar types inside a compound value object
// build a BeanPropertyCompoundScalar with appropriate deployment
// information.
for (Entry<String, ScalarType<?>> entry : ctMeta.entries()) {
/**
* Create the property.
*/
public DeployBeanPropertyCompound(DeployBeanDescriptor<?> desc, Class<?> targetType,
CtCompoundType<?> compoundType, ScalarTypeConverter<?, ?> typeConverter) {
String relativePropertyName = entry.getKey();
ScalarType<?> scalarType = entry.getValue();
CtCompoundProperty ctProp = ctMeta.getCompoundType(relativePropertyName);
String dbColumn = relativePropertyName.replace(".", "_");
dbColumn = getDbColumn(relativePropertyName, dbColumn);
DeployBeanProperty deploy = new DeployBeanProperty(null, scalarType.getType(), scalarType, null);
deploy.setScalarType(scalarType);
deploy.setDbColumn(dbColumn);
deploy.setName(relativePropertyName);
deploy.setDbInsertable(true);
deploy.setDbUpdateable(true);
deploy.setDbRead(true);
BeanPropertyCompoundScalar bp = new BeanPropertyCompoundScalar(rootProperty, deploy, ctProp, typeConverter);
beanPropertyList.add(bp);
rootProperty.register(bp);
}
rootProperty.setNonScalarProperties(ctMeta.getNonScalarProperties());
return rootProperty;
}
private String getDbColumn(String propName, String defaultDbColumn){
if (deployEmbedded == null){
return defaultDbColumn;
}
String dbColumn = deployEmbedded.getPropertyColumnMap().get(propName);
return dbColumn == null ? defaultDbColumn : dbColumn;
}
/**
* Return the deploy information specifically for the deployment
* of Embedded beans.
*/
public DeployBeanEmbedded getDeployEmbedded() {
// deployment should be single threaded
if (deployEmbedded == null){
deployEmbedded = new DeployBeanEmbedded();
}
return deployEmbedded;
}
super(desc, targetType, null, null);
this.compoundType = compoundType;
this.typeConverter = typeConverter;
}
public ScalarTypeConverter<?, ?> getTypeConverter() {
return typeConverter;
public BeanPropertyCompoundRoot getFlatProperties(BeanDescriptorMap owner, BeanDescriptor<?> descriptor) {
// get a 'flat' list of all the scalar types, their relative property names
// and also set their matching dbColumn
// represents the root property
BeanPropertyCompoundRoot rootProperty = new BeanPropertyCompoundRoot(this);
// Walk the tree of a compound type collecting the
// scalar types and non-scalar properties
CtCompoundTypeScalarList ctMeta = new CtCompoundTypeScalarList();
compoundType.accumulateScalarTypes(null, ctMeta);
List<BeanProperty> beanPropertyList = new ArrayList<BeanProperty>();
// for each of the scalar types inside a compound value object
// build a BeanPropertyCompoundScalar with appropriate deployment
// information.
for (Entry<String, ScalarType<?>> entry : ctMeta.entries()) {
String relativePropertyName = entry.getKey();
ScalarType<?> scalarType = entry.getValue();
CtCompoundProperty ctProp = ctMeta.getCompoundType(relativePropertyName);
String dbColumn = (getName() + "." + relativePropertyName).replace(".", "_");
dbColumn = getDbColumn(relativePropertyName, dbColumn);
DeployBeanProperty deploy = new DeployBeanProperty(null, scalarType.getType(), scalarType, null);
deploy.setScalarType(scalarType);
deploy.setDbColumn(dbColumn);
deploy.setName(relativePropertyName);
deploy.setDbInsertable(true);
deploy.setDbUpdateable(true);
deploy.setDbRead(true);
BeanPropertyCompoundScalar bp = new BeanPropertyCompoundScalar(rootProperty, deploy, ctProp, typeConverter);
beanPropertyList.add(bp);
rootProperty.register(bp);
}
public CtCompoundType<?> getCompoundType() {
return compoundType;
rootProperty.setNonScalarProperties(ctMeta.getNonScalarProperties());
return rootProperty;
}
private String getDbColumn(String propName, String defaultDbColumn) {
if (deployEmbedded == null) {
return defaultDbColumn;
}
String dbColumn = deployEmbedded.getPropertyColumnMap().get(propName);
return dbColumn == null ? defaultDbColumn : dbColumn;
}
/**
* Return the deploy information specifically for the deployment
* of Embedded beans.
*/
public DeployBeanEmbedded getDeployEmbedded() {
// deployment should be single threaded
if (deployEmbedded == null) {
deployEmbedded = new DeployBeanEmbedded();
}
return deployEmbedded;
}
public ScalarTypeConverter<?, ?> getTypeConverter() {
return typeConverter;
}
public CtCompoundType<?> getCompoundType() {
return compoundType;
}
}
@@ -93,7 +93,7 @@ public class DeployCreateProperties {
}
/**
* reflect the bean properties from Class. Some of these properties may not map to database
* properties the bean properties from Class. Some of these properties may not map to database
* columns.
*/
private void createProperties(DeployBeanDescriptor<?> desc, Class<?> beanType, int level) {
@@ -125,7 +125,7 @@ public class DeployCreateProperties {
Method getter = findGetter(field, initFieldName, declaredMethods, scalaObject);
Method setter = findSetter(field, initFieldName, declaredMethods, scalaObject);
DeployBeanProperty prop = createProp(level, desc, field, beanType, getter, setter);
DeployBeanProperty prop = createProp(desc, field, beanType, getter, setter);
if (prop == null) {
// transient annotation on unsupported type
@@ -152,7 +152,7 @@ public class DeployCreateProperties {
Class<?> superClass = beanType.getSuperclass();
if (!superClass.equals(Object.class)) {
// recursively add any properties in the inheritance heirarchy
// recursively add any properties in the inheritance hierarchy
// up to the Object.class level...
createProperties(desc, superClass, level + 1);
}
@@ -361,7 +361,7 @@ public class DeployCreateProperties {
if (field.getAnnotation(ColumnHstore.class) != null) {
return ScalarTypePostgresHstore.KEY;
};
}
return null;
}
@@ -372,7 +372,7 @@ public class DeployCreateProperties {
return (t != null);
}
private DeployBeanProperty createProp(int level, DeployBeanDescriptor<?> desc, Field field, Class<?> beanType,
private DeployBeanProperty createProp(DeployBeanDescriptor<?> desc, Field field, Class<?> beanType,
Method getter, Method setter) {
DeployBeanProperty prop = createProp(desc, field);
@@ -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() {
@@ -218,6 +218,16 @@ abstract class JunctionExpression<T> implements Junction<T>, SpiExpression, Expr
return exprList.findIds();
}
@Override
public void findEach(QueryEachConsumer<T> consumer) {
exprList.findEach(consumer);
}
@Override
public void findEachWhile(QueryEachWhileConsumer<T> consumer) {
exprList.findEachWhile(consumer);
}
public void findVisit(QueryResultVisitor<T> visitor) {
exprList.findVisit(visitor);
}
@@ -14,40 +14,41 @@ import com.avaje.ebeaninternal.server.persist.dml.GenerateDmlRequest;
*/
public class BindableCompound implements Bindable {
private final Bindable[] items;
private final BindableProperty[] items;
private final BeanPropertyCompound compound;
private final BeanPropertyCompound compound;
public BindableCompound(BeanPropertyCompound embProp, List<Bindable> list) {
this.compound = embProp;
this.items = list.toArray(new Bindable[list.size()]);
public BindableCompound(BeanPropertyCompound embProp, List<BindableProperty> list) {
this.compound = embProp;
this.items = list.toArray(new BindableProperty[list.size()]);
}
public String toString() {
return "BindableCompound " + compound + " items:" + Arrays.toString(items);
}
public void dmlAppend(GenerateDmlRequest request) {
for (int i = 0; i < items.length; i++) {
items[i].dmlAppend(request);
}
}
public String toString() {
return "BindableCompound " + compound + " items:" + Arrays.toString(items);
public void addToUpdate(PersistRequestBean<?> request, List<Bindable> list) {
if (request.isAddToUpdate(compound)) {
list.add(this);
}
}
public void dmlAppend(GenerateDmlRequest request) {
public void dmlBind(BindableRequest bindRequest, EntityBean bean) throws SQLException {
for (int i = 0; i < items.length; i++) {
items[i].dmlAppend(request);
}
}
// get the compound type value
Object valueObject = compound.getValue(bean);
public void addToUpdate(PersistRequestBean<?> request, List<Bindable> list) {
if (request.isAddToUpdate(compound)) {
list.add(this);
}
}
public void dmlBind(BindableRequest bindRequest, EntityBean bean) throws SQLException {
throw new RuntimeException("This is broken, need to break out the scalar values!!");
//Object valueObject = compound.getValue(bean);
//for (int i = 0; i < items.length; i++) {
// items[i].dmlBind(bindRequest, valueObject);
//}
// bind each of the underlying scalar values for this compound type
for (int i = 0; i < items.length; i++) {
items[i].dmlBindObject(bindRequest, valueObject);
}
}
}
@@ -13,33 +13,47 @@ import com.avaje.ebeaninternal.server.persist.dml.GenerateDmlRequest;
*/
public class BindableProperty implements Bindable {
protected final BeanProperty prop;
protected final BeanProperty prop;
public BindableProperty(BeanProperty prop) {
this.prop = prop;
public BindableProperty(BeanProperty prop) {
this.prop = prop;
}
public String toString() {
return prop.toString();
}
public void addToUpdate(PersistRequestBean<?> request, List<Bindable> list) {
if (request.isAddToUpdate(prop)) {
list.add(this);
}
}
public String toString() {
return prop.toString();
public void dmlAppend(GenerateDmlRequest request) {
request.appendColumn(prop.getDbColumn());
}
/**
* Normal binding of a property value from the bean.
*/
public void dmlBind(BindableRequest request, EntityBean bean) throws SQLException {
Object value = null;
if (bean != null) {
value = prop.getValue(bean);
}
request.bind(value, prop, prop.getName());
}
public void addToUpdate(PersistRequestBean<?> request, List<Bindable> list) {
if (request.isAddToUpdate(prop)) {
list.add(this);
}
}
/**
* For compound types bind one of the underlying scalar values for a compound type.
*/
public void dmlBindObject(BindableRequest request, Object bean) throws SQLException {
public void dmlAppend(GenerateDmlRequest request) {
request.appendColumn(prop.getDbColumn());
}
public void dmlBind(BindableRequest request, EntityBean bean) throws SQLException {
Object value = null;
if (bean != null) {
value = prop.getValue(bean);
}
// value = prop.getDefaultValue();
request.bind(value, prop, prop.getName());
Object value = null;
if (bean != null) {
value = prop.getValueObject(bean);
}
request.bind(value, prop, prop.getName());
}
}
@@ -16,49 +16,52 @@ import com.avaje.ebeaninternal.server.persist.dml.DmlMode;
*/
public class FactoryBaseProperties {
private final FactoryProperty factoryProperty;
public FactoryBaseProperties(boolean bindEncryptDataFirst) {
factoryProperty = new FactoryProperty(bindEncryptDataFirst);
}
private final FactoryProperty factoryProperty;
/**
* Add Bindable for the base properties to the list.
*/
public void create(List<Bindable> list, BeanDescriptor<?> desc, DmlMode mode, boolean withLobs) {
add(desc.propertiesBaseScalar(), list, desc, mode, withLobs);
public FactoryBaseProperties(boolean bindEncryptDataFirst) {
factoryProperty = new FactoryProperty(bindEncryptDataFirst);
}
BeanPropertyCompound[] compoundProps = desc.propertiesBaseCompound();
for (int i = 0; i < compoundProps.length; i++) {
BeanProperty[] props = compoundProps[i].getScalarProperties();
/**
* Add Bindable for the base properties to the list.
*/
public void create(List<Bindable> list, BeanDescriptor<?> desc, DmlMode mode, boolean withLobs) {
ArrayList<Bindable> newList = new ArrayList<Bindable>(props.length);
add(props, newList, desc, mode, withLobs);
BindableCompound compoundBindable = new BindableCompound(compoundProps[i], newList);
add(desc.propertiesBaseScalar(), list, desc, mode, withLobs);
list.add(compoundBindable);
}
}
BeanPropertyCompound[] compoundProps = desc.propertiesBaseCompound();
for (int i = 0; i < compoundProps.length; i++) {
BeanProperty[] props = compoundProps[i].getScalarProperties();
private void add(BeanProperty[] props, List<Bindable> list, BeanDescriptor<?> desc, DmlMode mode, boolean withLobs) {
List<BindableProperty> newList = new ArrayList<BindableProperty>(props.length);
addCompound(props, newList, desc, mode, withLobs);
for (int i = 0; i < props.length; i++) {
BindableCompound compoundBindable = new BindableCompound(compoundProps[i], newList);
// if(DmlMode.WHERE.equals(mode) && !withLobs && !props[i].isDbUpdatable()) {
// // skip non-updatable column from where clause
// } else {
Bindable item = factoryProperty.create(props[i], mode, withLobs);
if (item != null) {
list.add(item);
} else {
// null where readOnly (Secondary tables) or Lob exclusion
}
// }
}
list.add(compoundBindable);
}
}
private void add(BeanProperty[] props, List<Bindable> list, BeanDescriptor<?> desc, DmlMode mode, boolean withLobs) {
for (int i = 0; i < props.length; i++) {
Bindable item = factoryProperty.create(props[i], mode, withLobs);
if (item != null) {
list.add(item);
}
}
}
private void addCompound(BeanProperty[] props, List<BindableProperty> list, BeanDescriptor<?> desc, DmlMode mode, boolean withLobs) {
for (int i = 0; i < props.length; i++) {
BindableProperty item = (BindableProperty) factoryProperty.create(props[i], mode, withLobs);
if (item != null) {
list.add(item);
}
}
}
}
@@ -1,17 +1,20 @@
package com.avaje.ebeaninternal.server.reflect;
package com.avaje.ebeaninternal.server.properties;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class BeanReflectProperties {
/**
* Determines the properties on a given bean.
*/
public class BeanPropertiesReader {
private final Map<String,Integer> propertyIndexMap = new HashMap<String,Integer>();
private final String[] props;
public BeanReflectProperties(Class<?> clazz) {
public BeanPropertiesReader(Class<?> clazz) {
this.props = getProperties(clazz);
for (int i=0; i<props.length; i++) {
propertyIndexMap.put(props[i], Integer.valueOf(i));
@@ -1,11 +1,11 @@
package com.avaje.ebeaninternal.server.reflect;
package com.avaje.ebeaninternal.server.properties;
import com.avaje.ebean.bean.EntityBean;
/**
* The getter implementation for a given bean property.
*/
public interface BeanReflectGetter {
public interface BeanPropertyGetter {
/**
* Return the value of a given bean property.
@@ -1,4 +1,4 @@
package com.avaje.ebeaninternal.server.reflect;
package com.avaje.ebeaninternal.server.properties;
/**
* Provides getter setter and construction methods for beans.
@@ -7,7 +7,7 @@ package com.avaje.ebeaninternal.server.reflect;
* code generation.
* </p>
*/
public interface BeanReflect {
public interface BeanPropertyInfo {
/**
* Create an EntityBean for this type.
@@ -17,10 +17,10 @@ public interface BeanReflect {
/**
* Return the getter for a given bean property.
*/
public BeanReflectGetter getGetter(String name, int position);
public BeanPropertyGetter getGetter(String name, int position);
/**
* Return the setter for a given bean property.
*/
public BeanReflectSetter getSetter(String name, int position);
public BeanPropertySetter getSetter(String name, int position);
}
@@ -1,14 +1,14 @@
package com.avaje.ebeaninternal.server.reflect;
package com.avaje.ebeaninternal.server.properties;
/**
* Creates BeanReflect object used to provide getter setter and construction
* for the beans.
*/
public interface BeanReflectFactory {
public interface BeanPropertyInfoFactory {
/**
* Create the BeanReflect for the given plain bean and its EntityBean equivalent.
*/
public BeanReflect create(Class<?> entityBeanType);
public BeanPropertyInfo create(Class<?> entityBeanType);
}
@@ -1,11 +1,11 @@
package com.avaje.ebeaninternal.server.reflect;
package com.avaje.ebeaninternal.server.properties;
import com.avaje.ebean.bean.EntityBean;
/**
* The setter for a given bean property.
*/
public interface BeanReflectSetter {
public interface BeanPropertySetter {
/**
* Set the property value of a bean.
@@ -1,4 +1,4 @@
package com.avaje.ebeaninternal.server.reflect;
package com.avaje.ebeaninternal.server.properties;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
@@ -11,13 +11,13 @@ import com.avaje.ebean.bean.EntityBean;
* A BeanReflect implementation based on the enhancement that creates EntityBean
* implementations.
*/
public final class EnhanceBeanReflect implements BeanReflect {
public final class EnhanceBeanPropertyInfo implements BeanPropertyInfo {
private static final Object[] constuctorArgs = new Object[0];
private final Constructor<?> constructor;
public EnhanceBeanReflect(Class<?> clazz) {
public EnhanceBeanPropertyInfo(Class<?> clazz) {
try {
if (Modifier.isAbstract(clazz.getModifiers())) {
this.constructor = null;
@@ -47,15 +47,15 @@ public final class EnhanceBeanReflect implements BeanReflect {
}
}
public BeanReflectGetter getGetter(String name, int position) {
public BeanPropertyGetter getGetter(String name, int position) {
return new Getter(position);
}
public BeanReflectSetter getSetter(String name, int position) {
public BeanPropertySetter getSetter(String name, int position) {
return new Setter(position);
}
static final class Getter implements BeanReflectGetter {
static final class Getter implements BeanPropertyGetter {
private final int fieldIndex;
@@ -72,7 +72,7 @@ public final class EnhanceBeanReflect implements BeanReflect {
}
}
static final class Setter implements BeanReflectSetter {
static final class Setter implements BeanPropertySetter {
private final int fieldIndex;
@@ -0,0 +1,13 @@
package com.avaje.ebeaninternal.server.properties;
/**
* Creates a BeanReflectFactory based on the enhancement that
* creates EntityBean implementations.
*/
public final class EnhanceBeanPropertyInfoFactory implements BeanPropertyInfoFactory {
public BeanPropertyInfo create(Class<?> entityBeanType) {
return new EnhanceBeanPropertyInfo(entityBeanType);
}
}
@@ -8,22 +8,8 @@ import java.util.Set;
import javax.persistence.PersistenceException;
import com.avaje.ebean.EbeanServer;
import com.avaje.ebean.Expression;
import com.avaje.ebean.ExpressionFactory;
import com.avaje.ebean.ExpressionList;
import com.avaje.ebean.FetchConfig;
import com.avaje.ebean.FutureIds;
import com.avaje.ebean.FutureList;
import com.avaje.ebean.FutureRowCount;
import com.avaje.ebean.OrderBy;
import com.avaje.ebean.*;
import com.avaje.ebean.OrderBy.Property;
import com.avaje.ebean.PagedList;
import com.avaje.ebean.PagingList;
import com.avaje.ebean.Query;
import com.avaje.ebean.QueryIterator;
import com.avaje.ebean.QueryResultVisitor;
import com.avaje.ebean.RawSql;
import com.avaje.ebean.bean.BeanCollectionTouched;
import com.avaje.ebean.bean.CallStack;
import com.avaje.ebean.bean.EntityBean;
@@ -911,6 +897,16 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
server.findVisit(this, visitor, null);
}
@Override
public void findEachWhile(QueryEachWhileConsumer<T> consumer) {
server.findEachWhile(this, consumer, null);
}
@Override
public void findEach(QueryEachConsumer<T> consumer) {
server.findEach(this, consumer, null);
}
public QueryIterator<T> findIterate() {
return server.findIterate(this, null);
}
@@ -1,13 +0,0 @@
package com.avaje.ebeaninternal.server.reflect;
/**
* Creates a BeanReflectFactory based on the enhancement that
* creates EntityBean implementations.
*/
public final class EnhanceBeanReflectFactory implements BeanReflectFactory {
public BeanReflect create(Class<?> entityBeanType) {
return new EnhanceBeanReflect(entityBeanType);
}
}
@@ -0,0 +1,81 @@
package com.avaje.ebeaninternal.server.type;
import com.avaje.ebean.config.CompoundType;
import com.avaje.ebean.config.CompoundTypeProperty;
import java.time.Period;
/**
* Compound type for Period value type.
* <p>
* Persists the Period into 3 separate integer columns for years, months and days.
* </p>
*/
public class CompoundTypePeriod implements CompoundType<Period> {
CompoundTypeProperty[] properties = new CompoundTypeProperty[3];
public CompoundTypePeriod() {
properties[0] = new CTPeriodYear();
properties[1] = new CTPeriodMonth();
properties[2] = new CTPeriodDay();
}
@Override
public Period create(Object[] propertyValues) {
return Period.of((Integer)propertyValues[0], (Integer)propertyValues[1], (Integer)propertyValues[2]);
}
@Override
public CompoundTypeProperty<Period, ?>[] getProperties() {
return properties;
}
static class CTPeriodYear implements CompoundTypeProperty<Period, Integer> {
public String getName() {
return "years";
}
public Integer getValue(Period valueObject) {
return valueObject.getYears();
}
public int getDbType() {
return 0;
}
}
static class CTPeriodMonth implements CompoundTypeProperty<Period, Integer> {
public String getName() {
return "months";
}
public Integer getValue(Period valueObject) {
return valueObject.getMonths();
}
public int getDbType() {
return 0;
}
}
static class CTPeriodDay implements CompoundTypeProperty<Period, Integer> {
public String getName() {
return "days";
}
public Integer getValue(Period valueObject) {
return valueObject.getDays();
}
public int getDbType() {
return 0;
}
}
}
@@ -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 = 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) {
@@ -10,6 +10,7 @@ import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.time.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
@@ -22,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;
@@ -32,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;
@@ -102,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();
@@ -115,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<?>>();
@@ -125,6 +120,8 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable {
private final ReflectionBasedTypeBuilder reflectScalarBuilder;
private final JsonConfig.DateTime jsonDateTime;
/**
* Create the DefaultTypeManager.
*/
@@ -133,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);
@@ -145,11 +143,12 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable {
this.extraTypeFactory = new DefaultTypeFactory(config);
initialiseStandard(clobType, blobType, config.isUuidStoreAsBinary());
initialiseJodaTypes();
initialiseStandard(jsonDateTime, clobType, blobType, config.isUuidStoreAsBinary());
initialiseJavaTimeTypes(jsonDateTime, config);
initialiseJodaTypes(jsonDateTime);
if (bootupClasses != null) {
initialiseCustomScalarTypes(bootupClasses);
initialiseCustomScalarTypes(jsonDateTime, bootupClasses);
initialiseScalarConverters(bootupClasses);
initialiseCompoundTypes(bootupClasses);
}
@@ -311,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;
@@ -415,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);
@@ -466,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);
@@ -602,20 +599,48 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable {
return propParamTypes[1];
}
protected void initialiseJavaTimeTypes(JsonConfig.DateTime mode, ServerConfig config) {
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(mode));
typeMap.put(OffsetDateTime.class, new ScalarTypeOffsetDateTime(mode));
typeMap.put(ZonedDateTime.class, new ScalarTypeZonedDateTime(mode));
typeMap.put(Instant.class, new ScalarTypeInstant(mode));
typeMap.put(DayOfWeek.class, new ScalarTypeDayOfWeek());
typeMap.put(Month.class, new ScalarTypeMonth());
typeMap.put(Year.class, new ScalarTypeYear());
typeMap.put(YearMonth.class, new ScalarTypeYearMonthDate());
typeMap.put(MonthDay.class, new ScalarTypeMonthDay());
typeMap.put(OffsetTime.class, new ScalarTypeOffsetTime());
typeMap.put(ZoneId.class, new ScalarTypeZoneId());
typeMap.put(ZoneOffset.class, new ScalarTypeZoneOffset());
createCompoundScalarDataReader(Period.class, new CompoundTypePeriod(), "");
boolean localTimeNanos = config.isLocalTimeWithNanos();
typeMap.put(java.time.LocalTime.class, (localTimeNanos)? new ScalarTypeLocalTimeWithNanos() : new ScalarTypeLocalTime());
boolean durationNanos = config.isDurationWithNanos();
typeMap.put(Duration.class, (durationNanos)? new ScalarTypeDurationWithNanos() : new ScalarTypeDuration());
}
}
/**
* 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());
}
}
@@ -624,12 +649,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();
@@ -644,8 +669,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)
@@ -733,6 +756,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);
@@ -15,7 +15,12 @@ public class EnumToDbIntegerMap extends EnumToDbValueMap<Integer> {
return Types.INTEGER;
}
@Override
public EnumToDbIntegerMap add(Object beanValue, Integer dbValue) {
addInternal(beanValue, dbValue);
return this;
}
@Override
public EnumToDbIntegerMap add(Object beanValue, String stringDbValue) {
try {
@@ -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;
}
@@ -57,20 +57,6 @@ public abstract class ScalarTypeBase<T> implements ScalarType<T> {
return formatValue((T) v);
}
/**
* Return true if the value is null.
*/
public boolean isDbNull(Object value) {
return value == null;
}
/**
* Returns the value that was passed in.
*/
public Object getDbNullValue(Object value) {
return value;
}
public void loadIgnore(DataReader dataReader) {
dataReader.incrementPos(1);
}
@@ -23,7 +23,7 @@ public abstract class ScalarTypeBaseDate<T> extends ScalarTypeBase<T> {
/**
* Convert the target value to millis.
*/
public abstract long convertToMillis(Object value);
public abstract long convertToMillis(T value);
/**
* Convert to java.sql.Date from the target Date type.
@@ -39,19 +39,14 @@ public abstract class ScalarTypeBaseDate<T> extends ScalarTypeBase<T> {
if (value == null) {
b.setNull(Types.DATE);
} else {
Date date = convertToDate(value);
b.setDate(date);
b.setDate(convertToDate(value));
}
}
public T read(DataReader dataReader) throws SQLException {
Date ts = dataReader.getDate();
if (ts == null) {
return null;
} else {
return convertFromDate(ts);
}
return ts == null ? null : convertFromDate(ts);
}
public String formatValue(T t) {
@@ -64,7 +59,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 +69,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 +93,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,50 @@ 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();
Timestamp timestamp = DecimalUtils.toTimestamp(value);
return convertFromTimestamp(timestamp);
}
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.writeFieldName(name);
generator.writeString(toJsonISO8601(value));
break;
}
case NANOS: {
generator.writeFieldName(name);
generator.writeNumber(toJsonNanos(value));
break;
}
default: {
generator.writeNumberField(name, convertToMillis(value));
}
}
}
public String formatValue(T t) {
@@ -76,16 +133,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 +148,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));
}
}
@@ -16,8 +16,8 @@ public class ScalarTypeDate extends ScalarTypeBaseDate<java.sql.Date> {
}
@Override
public long convertToMillis(Object value) {
return ((Date) value).getTime();
public long convertToMillis(Date value) {
return value.getTime();
}
@Override
@@ -0,0 +1,51 @@
package com.avaje.ebeaninternal.server.type;
import java.sql.SQLException;
import java.sql.Types;
import java.time.DayOfWeek;
/**
* ScalarType mapping for Month enum.
*/
public class ScalarTypeDayOfWeek extends ScalarTypeEnumWithMapping {
static final EnumToDbIntegerMap beanDbMap = new EnumToDbIntegerMap();
static {
DayOfWeek[] values = DayOfWeek.values();
for (DayOfWeek value : values) {
beanDbMap.add(value, value.getValue());
}
}
public ScalarTypeDayOfWeek() {
super(beanDbMap, DayOfWeek.class, 1);
}
/**
* Bind DayOfWeek enum using getValue().
*/
@Override
public void bind(DataBind b, Object value) throws SQLException {
if (value == null) {
b.setNull(Types.INTEGER);
} else {
// avoiding the map lookup
b.setInt(((DayOfWeek)value).getValue());
}
}
/**
* Read DayOfWeek using int value.
*/
@Override
public Object read(DataReader dataReader) throws SQLException {
Integer i = dataReader.getInt();
if (i == null) {
return null;
} else {
// avoiding the map lookup
return DayOfWeek.of(i);
}
}
}
@@ -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,113 @@
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 seconds precision).
*/
public class ScalarTypeDuration extends ScalarTypeBase<Duration> {
public ScalarTypeDuration() {
super(Duration.class, false, Types.BIGINT);
}
protected ScalarTypeDuration(int jdbcType) {
super(Duration.class, false, jdbcType);
}
public BigDecimal convertToBigDecimal(Duration value) {
return (value == null) ? null : DecimalUtils.toDecimal(value);
}
public Duration convertFromBigDecimal(BigDecimal value) {
return (value == null) ? null : DecimalUtils.toDuration(value);
}
@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 {
Long value = dataReader.getLong();
return (value == null) ? null : Duration.ofSeconds(value);
}
@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 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 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,55 @@
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);
}
@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 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);
}
}
@@ -8,6 +8,6 @@ public interface ScalarTypeEnum {
/**
* Return the IN values for DB constraint construction.
*/
public String getContraintInValues();
public String getConstraintInValues();
}
@@ -41,7 +41,7 @@ public class ScalarTypeEnumStandard {
/**
* Return the IN values for DB constraint construction.
*/
public String getContraintInValues() {
public String getConstraintInValues() {
StringBuilder sb = new StringBuilder();
@@ -101,7 +101,7 @@ public class ScalarTypeEnumStandard {
if (beanValue == null) {
return null;
}
return ((Enum<?>) beanValue).toString();
return beanValue.toString();
}
public Object toBeanType(Object dbValue) {
@@ -129,7 +129,7 @@ public class ScalarTypeEnumStandard {
/**
* Return the IN values for DB constraint construction.
*/
public String getContraintInValues() {
public String getConstraintInValues() {
StringBuilder sb = new StringBuilder();
@@ -186,7 +186,7 @@ public class ScalarTypeEnumStandard {
return dbValue;
}
int ordinal = ((Integer) dbValue).intValue();
int ordinal = (Integer) dbValue;
if (ordinal < 0 || ordinal >= enumArray.length) {
String m = "Unexpected ordinal [" + ordinal + "] out of range [" + enumArray.length + "]";
throw new IllegalStateException(m);
@@ -222,7 +222,7 @@ public class ScalarTypeEnumStandard {
}
@Override
public Object parseDateTime(long systemTimeMillis) {
public Object convertFromMillis(long systemTimeMillis) {
throw new TextException("Not Supported");
}
@@ -25,7 +25,7 @@ public class ScalarTypeEnumWithMapping extends ScalarTypeEnumStandard.EnumBase i
/**
* Return the IN values for DB constraint construction.
*/
public String getContraintInValues() {
public String getConstraintInValues() {
StringBuilder sb = new StringBuilder();
@@ -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);
}
}
@@ -20,8 +20,8 @@ public class ScalarTypeJodaDateMidnight extends ScalarTypeBaseDate<DateMidnight>
}
@Override
public long convertToMillis(Object value) {
return ((DateMidnight) value).getMillis();
public long convertToMillis(DateMidnight value) {
return value.getMillis();
}
@Override
@@ -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
@@ -17,8 +17,8 @@ public class ScalarTypeJodaLocalDate extends ScalarTypeBaseDate<LocalDate> {
}
@Override
public long convertToMillis(Object value) {
return ((LocalDate) value).toDateMidnight().getMillis();
public long convertToMillis(LocalDate value) {
return value.toDateMidnight().getMillis();
}
@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 {
@@ -0,0 +1,59 @@
package com.avaje.ebeaninternal.server.type;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
import java.sql.Date;
import java.sql.Timestamp;
import java.sql.Types;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
/**
* ScalarType for java.time.LocalDate. This maps to a JDBC Date.
*/
public class ScalarTypeLocalDate extends ScalarTypeBaseDate<LocalDate> {
public ScalarTypeLocalDate() {
super(LocalDate.class, false, Types.DATE);
}
@Override
public long convertToMillis(LocalDate value) {
ZonedDateTime zonedDateTime = value.atStartOfDay(ZoneId.systemDefault());
return zonedDateTime.toInstant().toEpochMilli();
}
@Override
public LocalDate convertFromDate(Date ts) {
return ts.toLocalDate();
}
@Override
public Date convertToDate(LocalDate t) {
return Date.valueOf(t);
}
@Override
public Object toJdbcType(Object value) {
if (value instanceof LocalDate) {
return Date.valueOf((LocalDate) value);
}
return BasicTypeConverter.toDate(value);
}
@Override
public LocalDate toBeanType(Object value) {
if (value instanceof java.sql.Date) {
return ((java.sql.Date) value).toLocalDate();
}
return (LocalDate) value;
}
@Override
public LocalDate convertFromMillis(long systemTimeMillis) {
return new Timestamp(systemTimeMillis).toLocalDateTime().toLocalDate();
}
}
@@ -0,0 +1,64 @@
package com.avaje.ebeaninternal.server.type;
import com.avaje.ebean.config.JsonConfig;
import java.sql.Timestamp;
import java.sql.Types;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
/**
* ScalarType for java.sql.Timestamp.
*/
public class ScalarTypeLocalDateTime extends ScalarTypeBaseDateTime<LocalDateTime> {
public ScalarTypeLocalDateTime(JsonConfig.DateTime mode) {
super(mode, LocalDateTime.class, true, Types.TIMESTAMP);
}
@Override
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.atZone(ZoneId.systemDefault()).toInstant().toString();
}
@Override
public LocalDateTime convertFromTimestamp(Timestamp ts) {
return ts.toLocalDateTime();
}
@Override
public Timestamp convertToTimestamp(LocalDateTime t) {
ZonedDateTime zonedDateTime = t.atZone(ZoneId.systemDefault());
return Timestamp.from(zonedDateTime.toInstant());
}
@Override
public Object toJdbcType(Object value) {
if (value instanceof Timestamp) return value;
return convertToTimestamp((LocalDateTime)value);
}
@Override
public LocalDateTime toBeanType(Object value) {
if (value instanceof LocalDateTime) return (LocalDateTime)value;
return convertFromTimestamp((Timestamp)value);
}
}
@@ -0,0 +1,105 @@
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.Time;
import java.sql.Types;
import java.time.LocalTime;
/**
* ScalarType for java.time.LocalTime stored as JDBC Time.
*/
public class ScalarTypeLocalTime extends ScalarTypeBase<LocalTime> {
public ScalarTypeLocalTime() {
super(LocalTime.class, false, Types.TIME);
}
protected ScalarTypeLocalTime(int jdbcTtype) {
super(LocalTime.class, false, jdbcTtype);
}
@Override
public void bind(DataBind bind, LocalTime value) throws SQLException {
if (value == null) {
bind.setNull(Types.TIME);
} else {
bind.setTime(Time.valueOf(value));
}
}
@Override
public LocalTime read(DataReader dataReader) throws SQLException {
Time time = dataReader.getTime();
return (time == null) ? null : time.toLocalTime();
}
@Override
public Object toJdbcType(Object value) {
if (value instanceof Time) return value;
return Time.valueOf((LocalTime)value);
}
@Override
public LocalTime toBeanType(Object value) {
if (value instanceof LocalTime) return (LocalTime) value;
return BasicTypeConverter.toTime(value).toLocalTime();
}
@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 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());
}
}
@@ -0,0 +1,45 @@
package com.avaje.ebeaninternal.server.type;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
import java.sql.SQLException;
import java.sql.Types;
import java.time.LocalTime;
/**
* ScalarType for java.time.LocalTime stored with Nanos as DB BIGINT type.
*/
public class ScalarTypeLocalTimeWithNanos extends ScalarTypeLocalTime {
public ScalarTypeLocalTimeWithNanos() {
super(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 {
Long value = dataReader.getLong();
return (value == null) ? null : LocalTime.ofNanoOfDay(value);
}
@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));
}
}
@@ -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());
}
@@ -0,0 +1,51 @@
package com.avaje.ebeaninternal.server.type;
import java.sql.SQLException;
import java.sql.Types;
import java.time.Month;
/**
* ScalarType mapping for Month enum.
*/
public class ScalarTypeMonth extends ScalarTypeEnumWithMapping {
static final EnumToDbIntegerMap beanDbMap = new EnumToDbIntegerMap();
static {
Month[] values = Month.values();
for (Month value : values) {
beanDbMap.add(value, value.getValue());
}
}
public ScalarTypeMonth() {
super(beanDbMap, Month.class, 1);
}
/**
* Bind Month enum value.
*/
@Override
public void bind(DataBind b, Object value) throws SQLException {
if (value == null) {
b.setNull(Types.INTEGER);
} else {
// avoiding the map lookup
b.setInt(((Month)value).getValue());
}
}
/**
* Read Month enum from integer.
*/
@Override
public Object read(DataReader dataReader) throws SQLException {
Integer i = dataReader.getInt();
if (i == null) {
return null;
} else {
// avoiding the map lookup
return Month.of(i);
}
}
}
@@ -0,0 +1,132 @@
package com.avaje.ebeaninternal.server.type;
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.Date;
import java.sql.SQLException;
import java.sql.Types;
import java.time.LocalDate;
import java.time.MonthDay;
/**
* ScalarType for MonthDay stored as a SQL Date using a fixed year.
* <p>
* Note that the year used should be a leap year.
* </p>
*/
public class ScalarTypeMonthDay extends ScalarTypeBase<MonthDay> {
protected int year;
/**
* Construct with a year of 2000 (which is a leap year).
*/
public ScalarTypeMonthDay() {
this(2000); // Year 2000 is a leap year
}
/**
* Construct with a base year. The year should be a leap year to
* allow the 29th Feb value.
*/
public ScalarTypeMonthDay(int year) {
super(MonthDay.class, false, Types.DATE);
this.year = year;
}
private MonthDay convertFromDate(Date ts) {
LocalDate localDate = ts.toLocalDate();
return MonthDay.of(localDate.getMonthValue(), localDate.getDayOfMonth());
}
private Date convertToDate(MonthDay value) {
return Date.valueOf(LocalDate.of(2000, value.getMonthValue(), value.getDayOfMonth()));
}
@Override
public MonthDay read(DataReader dataReader) throws SQLException {
Date ts = dataReader.getDate();
return ts == null ? null : convertFromDate(ts);
}
@Override
public void bind(DataBind b, MonthDay value) throws SQLException {
if (value == null) {
b.setNull(Types.DATE);
} else {
b.setDate(convertToDate(value));
}
}
@Override
public Object toJdbcType(Object value) {
if (value instanceof Date) return value;
return convertToDate((MonthDay) value);
}
@Override
public MonthDay toBeanType(Object value) {
if (value instanceof MonthDay) return (MonthDay) value;
return convertFromDate((Date) value);
}
@Override
public String formatValue(MonthDay value) {
return value.toString();
}
@Override
public MonthDay parse(String value) {
return MonthDay.parse(value);
}
@Override
public boolean isDateTimeCapable() {
return false;
}
@Override
public MonthDay convertFromMillis(long dateTime) {
throw new RuntimeException("Not supported on this type");
}
@Override
public MonthDay readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
return null;
} else {
int month = dataInput.readInt();
int day = dataInput.readInt();
return MonthDay.of(month, day);
}
}
@Override
public void writeData(DataOutput dataOutput, MonthDay value) throws IOException {
if (value == null) {
dataOutput.writeBoolean(false);
} else {
dataOutput.writeBoolean(true);
dataOutput.write(value.getMonthValue());
dataOutput.write(value.getDayOfMonth());
}
}
@Override
public MonthDay jsonRead(JsonParser ctx, JsonToken event) throws IOException {
return parse(ctx.getValueAsString());
}
@Override
public void jsonWrite(JsonGenerator ctx, String name, MonthDay value) throws IOException {
ctx.writeStringField(name, format(value));
}
}
@@ -0,0 +1,61 @@
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;
/**
* ScalarType for java.sql.Timestamp.
*/
public class ScalarTypeOffsetDateTime extends ScalarTypeBaseDateTime<OffsetDateTime> {
public ScalarTypeOffsetDateTime(JsonConfig.DateTime mode) {
super(mode, OffsetDateTime.class, true, Types.TIMESTAMP);
}
@Override
protected String toJsonNanos(OffsetDateTime value) {
return toJsonNanos(value.toEpochSecond(), value.getNano());
}
@Override
protected String toJsonISO8601(OffsetDateTime value) {
return value.toInstant().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
public OffsetDateTime convertFromTimestamp(Timestamp ts) {
return OffsetDateTime.ofInstant(ts.toInstant(), ZoneId.systemDefault());
}
@Override
public Timestamp convertToTimestamp(OffsetDateTime t) {
return Timestamp.from(t.toInstant());
}
@Override
public Object toJdbcType(Object value) {
if (value instanceof Timestamp) return value;
return convertToTimestamp((OffsetDateTime)value);
}
@Override
public OffsetDateTime toBeanType(Object value) {
if (value instanceof OffsetDateTime) return (OffsetDateTime) value;
return convertFromTimestamp((Timestamp)value);
}
}
@@ -0,0 +1,39 @@
package com.avaje.ebeaninternal.server.type;
import java.time.OffsetTime;
/**
* ScalarType for java.time.OffsetTime stored as DB VARCHAR
*/
public class ScalarTypeOffsetTime extends ScalarTypeBaseVarchar<OffsetTime> {
public ScalarTypeOffsetTime() {
super(OffsetTime.class);
}
@Override
public int getLength() {
return 25;
}
@Override
public String formatValue(OffsetTime v) {
return v.toString();
}
@Override
public OffsetTime parse(String value) {
return OffsetTime.parse(value);
}
@Override
public OffsetTime convertFromDbString(String dbValue) {
return OffsetTime.parse(dbValue);
}
@Override
public String convertToDbString(OffsetTime beanValue) {
return beanValue.toString();
}
}
@@ -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,106 @@ 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() {
super(java.util.Date.class, false, Types.TIMESTAMP);
}
@Override
public long convertToMillis(Object value) {
return BasicTypeConverter.toTimestamp(value).getTime();
public TimestampType(JsonConfig.DateTime mode) {
super(mode, java.util.Date.class, false, Types.TIMESTAMP);
}
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 {
@Override
protected String toJsonNanos(Date value) {
return String.valueOf(value.getTime());
}
Timestamp timestamp = new Timestamp(value.getTime());
b.setTimestamp(timestamp);
}
}
@Override
protected String toJsonISO8601(Date value) {
return dateTimeParser.format(value);
}
public Object toJdbcType(Object value) {
return BasicTypeConverter.toTimestamp(value);
}
@Override
public long convertToMillis(Date value) {
return value.getTime();
}
public java.util.Date toBeanType(Object value) {
return BasicTypeConverter.toUtilDate(value);
}
@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 Date convertFromTimestamp(Timestamp ts) {
return new java.util.Date(ts.getTime());
}
@Override
public void bind(DataBind b, java.util.Date value)
throws SQLException {
if (value == null) {
b.setNull(Types.TIMESTAMP);
} else {
@Override
public Timestamp convertToTimestamp(Date t) {
return new Timestamp(t.getTime());
}
Timestamp timestamp = new Timestamp(value.getTime());
b.setTimestamp(timestamp);
}
}
public java.util.Date parseDateTime(long systemTimeMillis) {
return new java.util.Date(systemTimeMillis);
}
}
@Override
public Object toJdbcType(Object value) {
return BasicTypeConverter.toTimestamp(value);
}
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);
return date.getTime();
@Override
public java.util.Date toBeanType(Object value) {
return BasicTypeConverter.toUtilDate(value);
}
@Override
public Date convertFromDate(java.sql.Date ts) {
return new java.util.Date(ts.getTime());
}
public Date convertFromTimestamp(Timestamp 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 Timestamp convertToTimestamp(Date t) {
return new Timestamp(t.getTime());
}
public Object toJdbcType(Object value) {
return BasicTypeConverter.toDate(value);
}
@Override
public java.util.Date convertFromMillis(long systemTimeMillis) {
return new java.util.Date(systemTimeMillis);
}
}
public java.util.Date toBeanType(Object value) {
return BasicTypeConverter.toUtilDate(value);
}
}
public static class DateType extends ScalarTypeBaseDate<java.util.Date> {
public DateType() {
super(Date.class, false, Types.DATE);
}
@Override
public long convertToMillis(java.util.Date value) {
return value.getTime();
}
@Override
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 Object toJdbcType(Object value) {
return BasicTypeConverter.toDate(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,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.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 {
Integer value = dataReader.getInt();
return (value == null) ? null : Year.of(value);
}
@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());
}
}
@@ -0,0 +1,67 @@
package com.avaje.ebeaninternal.server.type;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
import java.sql.Date;
import java.sql.Timestamp;
import java.sql.Types;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.ZoneId;
import java.time.ZonedDateTime;
/**
* ScalarType for java.time.LocalDate. This maps to a JDBC Date.
*/
public class ScalarTypeYearMonthDate extends ScalarTypeBaseDate<YearMonth> {
public ScalarTypeYearMonthDate() {
super(YearMonth.class, false, Types.DATE);
}
protected LocalDate toLocalDate(YearMonth yearMonth) {
return LocalDate.of(yearMonth.getYear(), yearMonth.getMonth(), 1);
}
protected YearMonth fromLocalDate(LocalDate localDate) {
return YearMonth.of(localDate.getYear(), localDate.getMonth());
}
@Override
public YearMonth convertFromMillis(long systemTimeMillis) {
return fromLocalDate(new Timestamp(systemTimeMillis).toLocalDateTime().toLocalDate());
}
@Override
public long convertToMillis(YearMonth value) {
LocalDate localDate = toLocalDate(value);
ZonedDateTime zonedDateTime = localDate.atStartOfDay(ZoneId.systemDefault());
return zonedDateTime.toInstant().toEpochMilli();
}
@Override
public YearMonth convertFromDate(Date ts) {
return fromLocalDate(ts.toLocalDate());
}
@Override
public Date convertToDate(YearMonth t) {
return Date.valueOf(toLocalDate(t));
}
@Override
public Object toJdbcType(Object value) {
if (value instanceof Date) return value;
if (value instanceof YearMonth) return Date.valueOf(toLocalDate((YearMonth) value));
if (value instanceof LocalDate) return Date.valueOf((LocalDate)value);
return BasicTypeConverter.toDate(value);
}
@Override
public YearMonth toBeanType(Object value) {
if (value instanceof YearMonth) return (YearMonth) value;
if (value instanceof LocalDate) return fromLocalDate((LocalDate) value);
return fromLocalDate(BasicTypeConverter.toDate(value).toLocalDate());
}
}
@@ -0,0 +1,40 @@
package com.avaje.ebeaninternal.server.type;
import java.time.OffsetTime;
import java.time.ZoneId;
/**
* ScalarType for java.time.OffsetTime stored as DB VARCHAR
*/
public class ScalarTypeZoneId extends ScalarTypeBaseVarchar<ZoneId> {
public ScalarTypeZoneId() {
super(ZoneId.class);
}
@Override
public int getLength() {
return 60;
}
@Override
public String formatValue(ZoneId v) {
return v.toString();
}
@Override
public ZoneId parse(String value) {
return ZoneId.of(value);
}
@Override
public ZoneId convertFromDbString(String dbValue) {
return ZoneId.of(dbValue);
}
@Override
public String convertToDbString(ZoneId beanValue) {
return beanValue.toString();
}
}
@@ -0,0 +1,39 @@
package com.avaje.ebeaninternal.server.type;
import java.time.ZoneOffset;
/**
* ScalarType for java.time.OffsetTime stored as DB VARCHAR
*/
public class ScalarTypeZoneOffset extends ScalarTypeBaseVarchar<ZoneOffset> {
public ScalarTypeZoneOffset() {
super(ZoneOffset.class);
}
@Override
public int getLength() {
return 60;
}
@Override
public String formatValue(ZoneOffset v) {
return v.toString();
}
@Override
public ZoneOffset parse(String value) {
return ZoneOffset.of(value);
}
@Override
public ZoneOffset convertFromDbString(String dbValue) {
return ZoneOffset.of(dbValue);
}
@Override
public String convertToDbString(ZoneOffset beanValue) {
return beanValue.toString();
}
}
@@ -0,0 +1,62 @@
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;
import java.time.ZonedDateTime;
/**
* ScalarType for ZonedDateTime.
*/
public class ScalarTypeZonedDateTime extends ScalarTypeBaseDateTime<ZonedDateTime> {
public ScalarTypeZonedDateTime(JsonConfig.DateTime mode) {
super(mode, ZonedDateTime.class, true, Types.TIMESTAMP);
}
@Override
protected String toJsonNanos(ZonedDateTime value) {
return toJsonNanos(value.toEpochSecond(), value.getNano());
}
@Override
protected String toJsonISO8601(ZonedDateTime value) {
return value.toInstant().toString();
}
@Override
public long convertToMillis(ZonedDateTime value) {
return value.toInstant().toEpochMilli();
}
@Override
public ZonedDateTime convertFromMillis(long systemTimeMillis) {
return ZonedDateTime.ofInstant(Instant.ofEpochMilli(systemTimeMillis), ZoneId.systemDefault());
}
@Override
public ZonedDateTime convertFromTimestamp(Timestamp ts) {
return ZonedDateTime.ofInstant(ts.toInstant(), ZoneId.systemDefault());
}
@Override
public Timestamp convertToTimestamp(ZonedDateTime t) {
return Timestamp.from(t.toInstant());
}
@Override
public Object toJdbcType(Object value) {
if (value instanceof Timestamp) return value;
return convertToTimestamp((ZonedDateTime)value);
}
@Override
public ZonedDateTime toBeanType(Object value) {
if (value instanceof ZonedDateTime) return (ZonedDateTime) value;
return convertFromTimestamp((Timestamp)value);
}
}
@@ -6,19 +6,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import com.avaje.ebean.Expression;
import com.avaje.ebean.ExpressionFactory;
import com.avaje.ebean.ExpressionList;
import com.avaje.ebean.FutureIds;
import com.avaje.ebean.FutureList;
import com.avaje.ebean.FutureRowCount;
import com.avaje.ebean.Junction;
import com.avaje.ebean.OrderBy;
import com.avaje.ebean.PagedList;
import com.avaje.ebean.PagingList;
import com.avaje.ebean.Query;
import com.avaje.ebean.QueryIterator;
import com.avaje.ebean.QueryResultVisitor;
import com.avaje.ebean.*;
import com.avaje.ebean.event.BeanQueryRequest;
import com.avaje.ebean.text.PathProperties;
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
@@ -172,6 +160,16 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
return query.findIds();
}
@Override
public void findEach(QueryEachConsumer<T> consumer) {
query.findEach(consumer);
}
@Override
public void findEachWhile(QueryEachWhileConsumer<T> consumer) {
query.findEachWhile(consumer);
}
public void findVisit(QueryResultVisitor<T> visitor) {
query.findVisit(visitor);
}
+1 -1
View File
@@ -49,7 +49,7 @@ Export-Package: com.avaje.ebean,
com.avaje.ebeaninternal.server.persist.dmlbind,
com.avaje.ebeaninternal.server.query,
com.avaje.ebeaninternal.server.querydefn,
com.avaje.ebeaninternal.server.reflect,
com.avaje.ebeaninternal.server.properties,
com.avaje.ebeaninternal.server.resource,
com.avaje.ebeaninternal.server.text.csv,
com.avaje.ebeaninternal.server.text.json,
@@ -19,11 +19,7 @@ public class ConvertInetAddressTest {
String uriAddr6 = ConvertInetAddresses.toUriString(addr6);
Assert.assertEquals("["+ip6addr+"]", uriAddr6);
Assert.assertEquals(ip6addr, addr6.getHostAddress());
}
@Test
public void toUriString() {

Some files were not shown because too many files have changed in this diff Show More