WIP on JSON refactor

This commit is contained in:
Rob Bygrave
2014-06-28 03:09:10 +12:00
parent 7966d74eb3
commit 0ceda6406e
52 changed files with 1583 additions and 174 deletions
@@ -0,0 +1,44 @@
package com.avaje.ebean.json;
import java.io.Reader;
import java.io.Writer;
import java.util.List;
import java.util.Map;
import javax.json.stream.JsonGenerator;
import javax.json.stream.JsonParser;
public class EJson {
public static String write(Object object) {
return EJsonWriter.write(object);
}
public static void write(Object object, Writer writer) {
EJsonWriter.write(object, writer);
}
public static void write(Object object, JsonGenerator jsonGenerator) {
EJsonWriter.write(object, jsonGenerator);
}
public static Map<String,Object> parseObject(String json) {
return EJsonReader.parseObject(json);
}
public static List<Object> parseList(String json) {
return EJsonReader.parseList(json);
}
public static Object parse(String json) {
return EJsonReader.parse(json);
}
public static Object parse(Reader reader) {
return EJsonReader.parse(reader);
}
public static Object parse(JsonParser parser) {
return EJsonReader.parse(parser);
}
}
@@ -0,0 +1,271 @@
package com.avaje.ebean.json;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import javax.json.Json;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
public class EJsonReader {
@SuppressWarnings("unchecked")
public static Map<String, Object> parseObject(String json) {
return (Map<String, Object>) parse(json);
}
@SuppressWarnings("unchecked")
public static List<Object> parseList(String json) {
return (List<Object>) parse(json);
}
public static Object parse(String json) {
return parse(new StringReader(json));
}
public static Object parse(Reader reader) {
return parse(Json.createParser(reader));
}
public static Object parse(JsonParser parser) {
return new EJsonReader(parser).parseJson();
}
private final JsonParser parser;
private Stack stack;
private Context currentContext;
EJsonReader(JsonParser parser) {
this.parser = parser;
}
private void startArray() {
stack.push(currentContext);
currentContext = new ArrayContext();
}
private void startObject() {
stack.push(currentContext);
currentContext = new ObjectContext();
}
private void endArray() {
end();
}
private void endObject() {
end();
}
private void end() {
if (!stack.isEmpty()) {
currentContext = stack.pop();
}
}
private void setValue(Object value) {
currentContext.setValue(value);
}
private void setValueNull() {
currentContext.setValueNull();
}
private Object parseJson() {
if (!parser.hasNext()) {
return null;
}
Event event = parser.next();
if (Event.VALUE_NULL == event) {
// it is just a null value
return null;
}
Object simpleValue = getSimpleValue(event);
if (simpleValue != null) {
// it is a simple string, number or boolean
return simpleValue;
}
stack = new Stack();
// it is a object or array, process the first event
processEvent(event);
// process the rest of the object or array
while (parser.hasNext()) {
processEvent(parser.next());
}
return currentContext.getValue();
}
/**
* See if the event is a value rather than object or array.
* <p>
* If just a value then return that value else return null.
*/
private Object getSimpleValue(Event event) {
switch (event) {
case VALUE_STRING:
return parser.getString();
case VALUE_NUMBER:
if (parser.isIntegralNumber()) {
return parser.getLong();
} else {
return parser.getBigDecimal();
}
case VALUE_TRUE:
return Boolean.TRUE;
case VALUE_FALSE:
return Boolean.FALSE;
default:
return false;
}
}
/**
* Process the event for objects and arrays.
*/
private void processEvent(Event event) {
switch (event) {
case START_ARRAY:
startArray();
break;
case START_OBJECT:
startObject();
break;
case KEY_NAME:
currentContext.setKey(parser.getString());
break;
case VALUE_STRING:
setValue(parser.getString());
break;
case VALUE_NUMBER:
if (parser.isIntegralNumber()) {
setValue(parser.getLong());
} else {
setValue(parser.getBigDecimal());
}
break;
case VALUE_TRUE:
setValue(Boolean.TRUE);
break;
case VALUE_FALSE:
setValue(Boolean.FALSE);
break;
case VALUE_NULL:
setValueNull();
break;
case END_OBJECT:
endObject();
break;
case END_ARRAY:
endArray();
break;
default:
break;
}
}
private static final class Stack {
private Context head;
private void push(Context context) {
if (context != null) {
context.next = head;
head = context;
}
}
private Context pop() {
if (head == null) {
throw new NoSuchElementException();
}
Context temp = head;
head = head.next;
return temp;
}
private boolean isEmpty() {
return head == null;
}
}
private static abstract class Context {
Context next;
abstract Object getValue();
abstract void setKey(String key);
abstract void setValue(Object value);
abstract void setValueNull();
}
private static class ObjectContext extends Context {
private final Map<String, Object> map = new LinkedHashMap<String, Object>();
private String key;
Object getValue() {
return map;
}
void setKey(String key) {
this.key = key;
}
void setValue(Object value) {
map.put(key, value);
}
void setValueNull() {
map.put(key, null);
}
}
private static class ArrayContext extends Context {
private final List<Object> values = new ArrayList<Object>();
Object getValue() {
return values;
}
void setValue(Object value) {
values.add(value);
}
void setValueNull() {
// ignore
}
void setKey(String key) {
// not expected
}
}
}
@@ -0,0 +1,201 @@
package com.avaje.ebean.json;
import java.io.StringWriter;
import java.io.Writer;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.json.Json;
import javax.json.stream.JsonGenerator;
class EJsonWriter {
public static String write(Object object) {
StringWriter writer = new StringWriter(200);
write(object, writer);
return writer.toString();
}
public static void write(Object object, Writer writer) {
JsonGenerator generator = Json.createGenerator(writer);
write(object, generator);
generator.close();
}
public static void write(Object object, JsonGenerator jsonGenerator) {
new EJsonWriter(jsonGenerator).writeJson(object);
}
private final JsonGenerator jsonGenerator;
private EJsonWriter(JsonGenerator jsonGenerator) {
this.jsonGenerator = jsonGenerator;
}
private void writeJson(Object object) {
writeJson(null, object);
}
@SuppressWarnings("unchecked")
private void writeJson(String name, Object object) {
if (object == null) {
writeNull(name);
} else if (object instanceof Map) {
writeMap(name, (Map<Object, Object>) object);
} else if (object instanceof Collection) {
writeCollection(name, (Collection<Object>) object);
} else if (object instanceof Boolean) {
writeBoolean(name, (Boolean) object);
} else if (object instanceof Number) {
writeNumber(name, (Number) object);
} else if (object instanceof Date) {
writeDate(name, (Date) object);
} else if (object instanceof String) {
writeString(name, (String) object);
} else {
writeString(name, object.toString());
}
}
private void writeBoolean(String name, Boolean object) {
if (name == null) {
jsonGenerator.write(object);
} else {
jsonGenerator.write(name, object);
}
}
private void writeDate(String name, Date object) {
if (name == null) {
jsonGenerator.write(object.getTime());
} else {
jsonGenerator.write(name, object.getTime());
}
}
private void writeNumber(String name, Number object) {
if (object instanceof Long) {
writeLong(name, object);
} else if (object instanceof Integer) {
writeInteger(name, object);
} else if (object instanceof Double) {
writeDouble(name, object);
} else if (object instanceof BigDecimal) {
writeBigDecimal(name, object);
} else if (object instanceof BigInteger) {
writeBigInteger(name, object);
} else {
writeGeneralNumber(name, object);
}
}
private void writeGeneralNumber(String name, Number object) {
if (name == null) {
jsonGenerator.write(new BigDecimal(object.toString()));
} else {
jsonGenerator.write(name, new BigDecimal(object.toString()));
}
}
private void writeBigDecimal(String name, Number object) {
if (name == null) {
jsonGenerator.write((BigDecimal) object);
} else {
jsonGenerator.write(name, (BigDecimal) object);
}
}
private void writeBigInteger(String name, Number object) {
if (name == null) {
jsonGenerator.write((BigInteger) object);
} else {
jsonGenerator.write(name, (BigInteger) object);
}
}
private void writeDouble(String name, Number object) {
if (name == null) {
jsonGenerator.write((Double) object);
} else {
jsonGenerator.write(name, (Double) object);
}
}
private void writeLong(String name, Number object) {
if (name == null) {
jsonGenerator.write((Long) object);
} else {
jsonGenerator.write(name, (Long) object);
}
}
private void writeInteger(String name, Number object) {
if (name == null) {
jsonGenerator.write((Integer) object);
} else {
jsonGenerator.write(name, (Integer) object);
}
}
private void writeNull(String name) {
if (name == null) {
jsonGenerator.writeNull();
} else {
jsonGenerator.writeNull(name);
}
}
private void writeString(String name, String object) {
if (name == null) {
jsonGenerator.write(object);
} else {
jsonGenerator.write(name, object);
}
}
private void writeCollection(String name, Collection<Object> collection) {
if (name == null) {
jsonGenerator.writeStartObject();
} else {
jsonGenerator.writeStartArray(name);
}
for (Object object : collection) {
writeJson(null, object);
}
jsonGenerator.writeEnd();
}
private void writeMap(String name, Map<Object, Object> map) {
if (name == null) {
jsonGenerator.writeStartObject();
} else {
jsonGenerator.writeStartObject(name);
}
Set<Entry<Object, Object>> entrySet = map.entrySet();
for (Entry<Object, Object> entry : entrySet) {
writeJson(entry.getKey().toString(), entry.getValue());
}
jsonGenerator.writeEnd();
}
}
@@ -13,6 +13,7 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import javax.json.stream.JsonParser;
import javax.persistence.PersistenceException;
import org.slf4j.Logger;
@@ -195,12 +196,12 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
/**
* Inheritance information. Server side only.
*/
private final InheritInfo inheritInfo;
protected final InheritInfo inheritInfo;
/**
* Derived list of properties that make up the unique id.
*/
private final BeanProperty idProperty;
protected final BeanProperty idProperty;
private final int idPropertyIndex;
/**
@@ -327,7 +328,8 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
private final boolean cacheSharableBeans;
private final BeanDescriptorCacheHelp<T> cacheHelp;
private final BeanDescriptorJsonHelp<T> jsonHelp;
private final String defaultSelectClause;
private final Set<String> defaultSelectClauseSet;
@@ -422,7 +424,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
this.cacheSharableBeans = noRelationships && deploy.getCacheOptions().isReadOnly();
this.cacheHelp = new BeanDescriptorCacheHelp<T>(this, owner.getCacheManager(), deploy.getCacheOptions(), cacheSharableBeans, propertiesOneImported);
this.jsonHelp = new BeanDescriptorJsonHelp<T>(this);
// Check if there are no cascade save associated beans ( subject to change
// in initialiseOther()). Note that if we are in an inheritance hierarchy
@@ -2198,88 +2200,12 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
beanVisitor.visit((T) bean, ctx);
}
}
@SuppressWarnings("unchecked")
public T jsonReadBean(ReadJsonContext ctx, String path) {
ReadBeanState beanState = jsonRead(ctx, path);
if (beanState == null) {
return null;
} else {
return (T) beanState.getBean();
}
}
public ReadBeanState jsonRead(ReadJsonContext ctx, String path) {
if (!ctx.readObjectBegin()) {
// the object is null
return null;
}
if (inheritInfo == null) {
return jsonReadObject(ctx, path);
} else {
// check for the discriminator value to determine the correct sub type
String discColumn = inheritInfo.getRoot().getDiscriminatorColumn();
if (!ctx.readKeyNext()) {
String msg = "Error reading inheritance discriminator - expected [" + discColumn + "] but no json key?";
throw new TextException(msg);
}
String propName = ctx.getTokenKey();
String discValue;
if (propName.equalsIgnoreCase(discColumn)) {
discValue = ctx.readScalarValue();
if (!ctx.readValueNext()) {
// Expected to read a comma to setup for reading the real properties of the bean
String msg = "Error reading inheritance discriminator [" + discColumn + "]. Expected more json name values?";
throw new TextException(msg);
}
} else {
// Assume that the we are just reading using this bean type
// Push the token key back so that it is re-read as it is one
// of the real properties of the bean itself
ctx.pushTokenKey();
discValue = inheritInfo.getDiscriminatorStringValue();
}
// determine the sub type for this particular json object
InheritInfo localInheritInfo = inheritInfo.readType(discValue);
BeanDescriptor<?> localDescriptor = localInheritInfo.getBeanDescriptor();
return localDescriptor.jsonReadObject(ctx, path);
}
public T jsonRead(JsonParser parser, String path) {
return jsonHelp.jsonRead(parser, path);
}
private ReadBeanState jsonReadObject(ReadJsonContext ctx, String path) {
EntityBean bean = createEntityBean();
ctx.pushBean(bean, path, this);
do {
if (!ctx.readKeyNext()) {
break;
} else {
// we read a property key ...
String propName = ctx.getTokenKey();
BeanProperty p = getBeanProperty(propName);
if (p != null) {
p.jsonRead(ctx, bean);
ctx.setProperty(propName);
} else {
// unknown property key ...
ctx.readUnmappedJson(propName);
}
if (!ctx.readValueNext()) {
break;
}
}
} while (true);
return ctx.popBeanState();
protected T jsonReadObject(JsonParser parser, String path) {
return jsonHelp.jsonReadObject(parser, path);
}
}
@@ -0,0 +1,190 @@
package com.avaje.ebeaninternal.server.deploy;
import java.util.Set;
import javax.json.stream.JsonGenerator;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebean.json.EJson;
import com.avaje.ebean.text.TextException;
import com.avaje.ebean.text.json.JsonWriteBeanVisitor;
import com.avaje.ebeaninternal.server.text.json.WriteJsonContext;
import com.avaje.ebeaninternal.server.text.json.WriteJsonContext.WriteBeanState;
public class BeanDescriptorJsonHelp<T> {
private final BeanDescriptor<T> desc;
private final InheritInfo inheritInfo;
public BeanDescriptorJsonHelp(BeanDescriptor<T> desc) {
this.desc = desc;
this.inheritInfo = desc.inheritInfo;
}
public void jsonWrite(JsonGenerator ctx, EntityBean bean) {
if (bean != null) {
ctx.writeStartObject();
//WriteBeanState prevState = ctx.pushBeanState(bean);
if (inheritInfo != null) {
InheritInfo localInheritInfo = inheritInfo.readType(bean.getClass());
String discValue = localInheritInfo.getDiscriminatorStringValue();
String discColumn = localInheritInfo.getDiscriminatorColumn();
ctx.write(discColumn, discValue);
//ctx.appendDiscriminator(discColumn, discValue);
BeanDescriptor<?> localDescriptor = localInheritInfo.getBeanDescriptor();
localDescriptor.jsonWriteProperties(ctx, bean);
} else {
jsonWriteProperties(ctx, bean);
}
//ctx.pushPreviousState(prevState);
//ctx.appendObjectEnd();
ctx.writeEnd();
}
}
@SuppressWarnings("unchecked")
private void jsonWriteProperties(JsonGenerator ctx, EntityBean bean) {
//JsonWriteBeanVisitor<T> beanVisitor = (JsonWriteBeanVisitor<T>) ctx.getBeanVisitor();
Set<String> props = ctx.getIncludeProperties();
boolean explicitAllProps;
if (props == null) {
explicitAllProps = false;
} else {
explicitAllProps = props.contains("*");
if (explicitAllProps || props.isEmpty()) {
props = null;
}
}
if (desc.idProperty != null) {
Object idValue = desc.idProperty.getValue(bean);
if (idValue != null) {
if (props == null || props.contains(idProperty.getName())) {
idProperty.jsonWrite(ctx, bean);
}
}
}
if (!explicitAllProps && props == null) {
// just render the loaded properties
props = ((EntityBean)bean)._ebean_getIntercept().getLoadedPropertyNames();
}
if (props != null) {
// render only the appropriate properties (when not all properties)
for (String prop : props) {
BeanProperty p = getBeanProperty(prop);
if (p != null && !p.isId()) {
p.jsonWrite(ctx, bean);
}
}
} else {
if (explicitAllProps || !isReference(bean._ebean_getIntercept())) {
// render all the properties and invoke lazy loading if required
for (int j = 0; j < propertiesNonTransient.length; j++) {
propertiesNonTransient[j].jsonWrite(ctx, bean);
}
for (int j = 0; j < propertiesTransient.length; j++) {
propertiesTransient[j].jsonWrite(ctx, bean);
}
}
}
if (beanVisitor != null) {
beanVisitor.visit((T) bean, ctx);
}
}
@SuppressWarnings("unchecked")
public T jsonRead(JsonParser parser, String path) {
if (!parser.hasNext()) {
return null;
}
Event event = parser.next();
if (Event.VALUE_NULL == event || Event.END_ARRAY == event) {
return null;
}
if (Event.START_OBJECT != event) {
throw new RuntimeException("Unexpected token "+event+" - expecting start_object at: "+parser.getLocation());
}
if (desc.inheritInfo == null) {
return jsonReadObject(parser, path);
}
// check for the discriminator value to determine the correct sub type
String discColumn = inheritInfo.getRoot().getDiscriminatorColumn();
if (!parser.hasNext() || ((event = parser.next()) != Event.KEY_NAME)) {
String msg = "Error reading inheritance discriminator - expected [" + discColumn + "] but no json key?";
throw new TextException(msg);
}
String propName = parser.getString();
if (!propName.equalsIgnoreCase(discColumn)) {
String msg = "Error reading inheritance discriminator, expected property ["+discColumn+"] but got [" + propName + "] ?";
throw new TextException(msg);
}
if (!parser.hasNext() || ((event = parser.next()) != Event.VALUE_STRING)) {
String msg = "Error reading inheritance discriminator - expected value_string token but got [" + event + "] at ["+parser.getLocation()+"]?";
throw new TextException(msg);
}
String discValue = parser.getString();
// determine the sub type for this particular json object
InheritInfo localInheritInfo = inheritInfo.readType(discValue);
BeanDescriptor<?> localDescriptor = localInheritInfo.getBeanDescriptor();
return (T) localDescriptor.jsonReadObject(parser, path);
}
@SuppressWarnings("unchecked")
protected T jsonReadObject(JsonParser parser, String path) {
EntityBean bean = desc.createEntityBean();
//ctx.pushBean(bean, path, this);
do {
if (parser.hasNext()) {
Event event = parser.next();
if (Event.KEY_NAME == event) {
String key = parser.getString();
BeanProperty p = desc.getBeanProperty(key);
if (p != null) {
p.jsonRead(parser, bean);
} else {
Object rawValue = EJson.parse(parser);
// unknown property key ...
//ctx.readUnmappedJson(propName);
}
} else if (Event.END_OBJECT == event) {
break;
} else {
throw new RuntimeException("Unexpected token "+event+" - expecting key or end_object at: "+parser.getLocation());
}
}
} while (true);
return (T)bean;
}
}
@@ -10,6 +10,9 @@ import java.sql.Types;
import java.util.List;
import java.util.Map;
import javax.json.stream.JsonGenerator;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import javax.persistence.PersistenceException;
import com.avaje.ebean.bean.EntityBean;
@@ -18,7 +21,6 @@ import com.avaje.ebean.config.dbplatform.DbEncryptFunction;
import com.avaje.ebean.config.dbplatform.DbType;
import com.avaje.ebean.text.StringFormatter;
import com.avaje.ebean.text.StringParser;
import com.avaje.ebean.text.TextException;
import com.avaje.ebeaninternal.server.core.InternString;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor.EntityType;
import com.avaje.ebeaninternal.server.deploy.generatedproperty.GeneratedProperty;
@@ -30,7 +32,6 @@ 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.text.json.ReadJsonContext;
import com.avaje.ebeaninternal.server.text.json.WriteJsonContext;
import com.avaje.ebeaninternal.server.type.DataBind;
import com.avaje.ebeaninternal.server.type.ScalarType;
@@ -1173,6 +1174,22 @@ public class BeanProperty implements ElPropertyValue {
return name;
}
@SuppressWarnings("unchecked")
public void jsonWrite(JsonGenerator ctx, EntityBean bean) {
if(!jsonSerialize){
return;
}
Object value = getValueIntercept(bean);
if (value == null) {
ctx.writeNull(name);
} else {
scalarType.jsonWrite(ctx, name, value);
//ctx.appendNameValue(name, scalarType, value);
}
}
@SuppressWarnings("unchecked")
public void jsonWrite(WriteJsonContext ctx, EntityBean bean) {
if(!jsonSerialize){
@@ -1186,22 +1203,39 @@ public class BeanProperty implements ElPropertyValue {
}
}
public void jsonRead(ReadJsonContext ctx, EntityBean bean) {
if(!jsonDeserialize){
return;
}
String jsonValue;
try {
jsonValue = ctx.readScalarValue();
} catch (TextException e){
throw new TextException("Error reading property "+getFullBeanName(), e);
}
Object objValue;
if (jsonValue == null) {
objValue = null;
} else {
objValue = scalarType.jsonFromString(jsonValue, ctx.getValueAdapter());
}
setValue(bean, objValue);
// public void jsonRead(ReadJsonContext ctx, EntityBean bean) {
// if(!jsonDeserialize){
// return;
// }
// String jsonValue;
// try {
// jsonValue = ctx.readScalarValue();
// } catch (TextException e){
// throw new TextException("Error reading property "+getFullBeanName(), e);
// }
// Object objValue;
// if (jsonValue == null) {
// objValue = null;
// } else {
// objValue = scalarType.jsonFromString(jsonValue, ctx.getValueAdapter());
// }
// setValue(bean, objValue);
// }
public void jsonRead(JsonParser ctx, EntityBean bean) {
if (!jsonDeserialize) {
return;
}
if (!ctx.hasNext()) {
throw new RuntimeException(ctx.getLocation().toString());
}
Event event = ctx.next();
if (Event.VALUE_NULL == event) {
setValue(bean, null);
} else {
Object objValue = scalarType.jsonRead(ctx, event);
setValue(bean, objValue);
}
}
}
@@ -6,6 +6,7 @@ import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import javax.json.stream.JsonParser;
import javax.persistence.PersistenceException;
import org.slf4j.Logger;
@@ -40,6 +41,8 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
private static final Logger logger = LoggerFactory.getLogger(BeanPropertyAssocMany.class);
private final BeanPropertyAssocManyJsonHelp jsonHelp;
/**
* Join for manyToMany intersection table.
*/
@@ -91,7 +94,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
/**
* Property on the 'child' bean that links back to the 'master'.
*/
private BeanPropertyAssocOne<?> childMasterProperty;
protected BeanPropertyAssocOne<?> childMasterProperty;
private boolean embeddedExportedProperties;
@@ -116,6 +119,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
this.intersectionJoin = deploy.createIntersectionTableJoin();
this.inverseJoin = deploy.createInverseTableJoin();
this.modifyListenMode = deploy.getModifyListenMode();
this.jsonHelp = new BeanPropertyAssocManyJsonHelp(this);
}
public void initialise() {
@@ -900,37 +904,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
}
}
public void jsonRead(ReadJsonContext ctx, EntityBean bean){
if(!this.jsonDeserialize){
return;
}
if (!ctx.readArrayBegin()) {
// the array is null
return;
}
Object collection = help.createEmpty(false);
BeanCollectionAdd add = getBeanCollectionAdd(collection, null);
do {
ReadBeanState detailBeanState = targetDescriptor.jsonRead(ctx, name);
if (detailBeanState == null){
// probably empty array
break;
}
EntityBean detailBean = (EntityBean)detailBeanState.getBean();
add.addBean(detailBean);
if (bean != null && childMasterProperty != null){
// bind detail bean back to master via mappedBy property
childMasterProperty.setValue(detailBean, bean);
detailBeanState.setLoaded(childMasterProperty.getName());
}
if (!ctx.readArrayNext()){
break;
}
} while(true);
setValue(bean, collection);
public void jsonRead(JsonParser parser, EntityBean parentBean) {
jsonHelp.jsonRead(parser, parentBean);
}
}
@@ -0,0 +1,49 @@
package com.avaje.ebeaninternal.server.deploy;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.avaje.ebean.bean.BeanCollectionAdd;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebean.text.TextException;
public class BeanPropertyAssocManyJsonHelp {
private final BeanPropertyAssocMany<?> many;
public BeanPropertyAssocManyJsonHelp(BeanPropertyAssocMany<?> many) {
this.many = many;
}
public void jsonRead(JsonParser parser, EntityBean parentBean) {
if (!this.many.jsonDeserialize || !parser.hasNext()) {
return;
}
Event event = parser.next();
if (Event.VALUE_NULL == event) {
return;
}
if (Event.START_ARRAY != event) {
throw new TextException("Unexpected token "+event+" - expecting start_array at: "+parser.getLocation());
}
Object collection = many.createEmpty(false);
BeanCollectionAdd add = many.getBeanCollectionAdd(collection, null);
do {
EntityBean detailBean = (EntityBean)many.targetDescriptor.jsonRead(parser, many.name);
if (detailBean == null) {
// read the entire array
break;
}
add.addBean(detailBean);
if (parentBean != null && many.childMasterProperty != null) {
// bind detail bean back to master via mappedBy property
many.childMasterProperty.setValue(detailBean, parentBean);
}
} while (true);
many.setValue(parentBean, collection);
}
}
@@ -5,6 +5,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.json.stream.JsonParser;
import javax.persistence.PersistenceException;
import com.avaje.ebean.EbeanServer;
@@ -854,13 +855,13 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
}
}
}
@Override
public void jsonRead(ReadJsonContext ctx, EntityBean bean){
if (targetDescriptor != null) {
T assocBean = targetDescriptor.jsonReadBean(ctx, name);
setValue(bean, assocBean);
}
public void jsonRead(JsonParser parser, EntityBean bean) {
if (targetDescriptor != null) {
T assocBean = targetDescriptor.jsonRead(parser, name);
setValue(bean, assocBean);
}
}
public boolean isReference(Object detailBean) {
@@ -0,0 +1,215 @@
package com.avaje.ebeaninternal.server.deploy;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import javax.json.Json;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
public class EJsonReader {
@SuppressWarnings("unchecked")
public static Map<String, Object> parseObject(String json) {
return (Map<String, Object>) parse(json);
}
@SuppressWarnings("unchecked")
public static List<Object> parseList(String json) {
return (List<Object>) parse(json);
}
public static Object parse(String json) {
return parse(new StringReader(json));
}
public static Object parse(Reader reader) {
return parse(Json.createParser(reader));
}
public static Object parse(JsonParser parser) {
return new EJsonReader(parser).parseJson();
}
private final JsonParser parser;
private final Stack stack = new Stack();
private Context currentContext;
EJsonReader(JsonParser parser) {
this.parser = parser;
}
private void startArray() {
stack.push(currentContext);
currentContext = new ArrayContext();
}
private void startObject() {
stack.push(currentContext);
currentContext = new ObjectContext();
}
private void endArray() {
end();
}
private void endObject() {
end();
}
private void end() {
if (!stack.isEmpty()) {
currentContext = stack.pop();
}
}
private void setValue(Object value) {
currentContext.setValue(value);
}
private void setValueNull() {
currentContext.setValueNull();
}
private Object parseJson() {
while (parser.hasNext()) {
Event event = parser.next();
switch (event) {
case START_ARRAY:
startArray();
break;
case START_OBJECT:
startObject();
break;
case KEY_NAME:
currentContext.setKey(parser.getString());
break;
case VALUE_STRING:
setValue(parser.getString());
break;
case VALUE_NUMBER:
if (parser.isIntegralNumber()) {
setValue(parser.getLong());
} else {
setValue(parser.getBigDecimal());
}
break;
case VALUE_TRUE:
setValue(Boolean.TRUE);
break;
case VALUE_FALSE:
setValue(Boolean.FALSE);
break;
case VALUE_NULL:
setValueNull();
break;
case END_OBJECT:
endObject();
break;
case END_ARRAY:
endArray();
break;
default:
break;
}
}
return currentContext.getValue();
}
private static final class Stack {
private Context head;
private void push(Context context) {
if (context != null) {
context.next = head;
head = context;
}
}
private Context pop() {
if (head == null) {
throw new NoSuchElementException();
}
Context temp = head;
head = head.next;
return temp;
}
private boolean isEmpty() {
return head == null;
}
}
private static abstract class Context {
Context next;
abstract Object getValue();
abstract void setKey(String key);
abstract void setValue(Object value);
abstract void setValueNull();
}
private static class ObjectContext extends Context {
private String key;
Map<String, Object> map = new LinkedHashMap<String,Object>();
Object getValue() {
return map;
}
public void setKey(String key) {
this.key = key;
}
void setValue(Object value) {
map.put(key, value);
}
void setValueNull() {
map.put(key, null);
}
}
private static class ArrayContext extends Context {
List<Object> values = new ArrayList<Object>();
Object getValue() {
return values;
}
void setValue(Object value) {
values.add(value);
}
void setValueNull() {
}
void setKey(String key) {
}
}
}
@@ -0,0 +1,9 @@
package com.avaje.ebeaninternal.server.deploy;
import javax.json.stream.JsonParser;
public class ReadJson {
JsonParser parser;
}
@@ -1,6 +1,7 @@
package com.avaje.ebeaninternal.server.text.json;
import java.io.Reader;
import java.io.StringReader;
import java.io.Writer;
import java.lang.reflect.Type;
import java.util.ArrayList;
@@ -11,6 +12,10 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.json.Json;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebean.text.TextException;
import com.avaje.ebean.text.json.JsonContext;
@@ -48,12 +53,13 @@ public class DJsonContext implements JsonContext {
return server.isSupportedType(genericType);
}
private ReadJsonSource createReader(Reader jsonReader) {
return new ReadJsonSourceReader(jsonReader, 256, 512);
private JsonParser createReader(Reader jsonReader) {
return Json.createParser(jsonReader);
//return new ReadJsonSourceReader(jsonReader, 256, 512);
}
public <T> T toBean(Class<T> cls, String json){
return toBean(cls, new ReadJsonSourceString(json), null);
return toBean(cls, new StringReader(json), null);
}
public <T> T toBean(Class<T> cls, Reader jsonReader) {
@@ -61,26 +67,33 @@ public class DJsonContext implements JsonContext {
}
public <T> T toBean(Class<T> cls, String json, JsonReadOptions options){
return toBean(cls, new ReadJsonSourceString(json), options);
return toBean(cls, new StringReader(json), options);
}
public <T> T toBean(Class<T> cls, Reader jsonReader, JsonReadOptions options) {
return toBean(cls, createReader(jsonReader), options);
}
private <T> T toBean(Class<T> cls, ReadJsonSource src, JsonReadOptions options){
// private <T> T toBean(Class<T> cls, ReadJsonSource src, JsonReadOptions options){
//
// BeanDescriptor<T> d = getDecriptor(cls);
// ReadJsonContext ctx = new ReadJsonContext(src, dfltValueAdapter, options);
// return d.jsonReadBean(ctx, null);
// }
BeanDescriptor<T> d = getDecriptor(cls);
ReadJsonContext ctx = new ReadJsonContext(src, dfltValueAdapter, options);
return d.jsonReadBean(ctx, null);
private <T> T toBean(Class<T> cls, JsonParser parser, JsonReadOptions options) {
BeanDescriptor<T> d = getDecriptor(cls);
// ReadJsonContext ctx = new ReadJsonContext(src, dfltValueAdapter, options);
return d.jsonRead(parser, null);
}
public <T> List<T> toList(Class<T> cls, String json){
return toList(cls, new ReadJsonSourceString(json), null);
return toList(cls, new StringReader(json), null);
}
public <T> List<T> toList(Class<T> cls, String json, JsonReadOptions options){
return toList(cls, new ReadJsonSourceString(json), options);
return toList(cls, new StringReader(json), options);
}
public <T> List<T> toList(Class<T> cls, Reader jsonReader){
@@ -91,26 +104,36 @@ public class DJsonContext implements JsonContext {
return toList(cls, createReader(jsonReader), options);
}
private <T> List<T> toList(Class<T> cls, ReadJsonSource src, JsonReadOptions options){
private <T> List<T> toList(Class<T> cls, JsonParser src, JsonReadOptions options){
try {
BeanDescriptor<T> d = getDecriptor(cls);
List<T> list = new ArrayList<T>();
ReadJsonContext ctx = new ReadJsonContext(src, dfltValueAdapter, options);
ctx.readArrayBegin();
//ReadJsonContext ctx = new ReadJsonContext(src, dfltValueAdapter, options);
if (!src.hasNext()) {
return list;
}
Event event = src.next();
if (event != Event.START_ARRAY) {
throw new TextException("Expecting start_array event but got ["+event+"] at ["+src.getLocation()+"]");
}
//ctx.readArrayBegin();
do {
T bean = d.jsonReadBean(ctx, null);
if (bean != null){
T bean = d.jsonRead(src, null);
if (bean == null){
break;
} else {
list.add(bean);
}
if (!ctx.readArrayNext()){
break;
}
// if (!ctx.readArrayNext()){
// break;
// }
} while(true);
return list;
} catch (RuntimeException e){
throw new TextException("Error parsing "+src, e);
}
@@ -5,6 +5,10 @@ import java.io.DataOutput;
import java.io.IOException;
import java.sql.SQLException;
import javax.json.stream.JsonGenerator;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.avaje.ebean.text.StringFormatter;
import com.avaje.ebean.text.StringParser;
import com.avaje.ebean.text.json.JsonValueAdapter;
@@ -192,5 +196,9 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
public Object readData(DataInput dataInput) throws IOException;
public void writeData(DataOutput dataOutput, Object v) throws IOException;
public Object jsonRead(JsonParser ctx, Event event);
public void jsonWrite(JsonGenerator ctx, String name, Object value);
}
@@ -7,6 +7,10 @@ import java.sql.Date;
import java.sql.SQLException;
import java.sql.Types;
import javax.json.stream.JsonGenerator;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.avaje.ebean.text.json.JsonValueAdapter;
import com.avaje.ebeaninternal.server.text.json.WriteJsonBuffer;
@@ -61,6 +65,24 @@ public abstract class ScalarTypeBaseDate<T> extends ScalarTypeBase<T> {
return true;
}
@Override
public Object jsonRead(JsonParser ctx, Event event) {
if (ctx.isIntegralNumber()) {
long millis = ctx.getLong();
return parseDateTime(millis);
} else {
String string = ctx.getString();
throw new RuntimeException("convert "+string);
}
}
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
long millis = convertToMillis(value);
ctx.write(name, millis);
}
public abstract long convertToMillis(Object value);
@Override
public String jsonToString(T value, JsonValueAdapter ctx) {
Date date = convertToDate(value);
@@ -7,6 +7,10 @@ import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import javax.json.stream.JsonGenerator;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.avaje.ebean.text.json.JsonValueAdapter;
import com.avaje.ebeaninternal.server.text.json.WriteJsonBuffer;
@@ -19,6 +23,8 @@ public abstract class ScalarTypeBaseDateTime<T> extends ScalarTypeBase<T> {
super(type, jdbcNative, jdbcType);
}
public abstract long convertToMillis(Object value);
public abstract Timestamp convertToTimestamp(T t);
public abstract T convertFromTimestamp(Timestamp ts);
@@ -42,6 +48,23 @@ public abstract class ScalarTypeBaseDateTime<T> extends ScalarTypeBase<T> {
}
}
@Override
public Object jsonRead(JsonParser ctx, Event event) {
if (ctx.isIntegralNumber()) {
long millis = ctx.getLong();
return parseDateTime(millis);
} else {
String string = ctx.getString();
throw new RuntimeException("convert "+string);
}
}
@Override
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
long millis = convertToMillis(value);
ctx.write(name, millis);
}
public String formatValue(T t) {
Timestamp ts = convertToTimestamp(t);
return ts.toString();
@@ -6,6 +6,10 @@ import java.io.IOException;
import java.sql.SQLException;
import java.sql.Types;
import javax.json.stream.JsonGenerator;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.avaje.ebean.text.TextException;
import com.avaje.ebean.text.json.JsonValueAdapter;
import com.avaje.ebeaninternal.server.text.json.WriteJsonBuffer;
@@ -115,4 +119,13 @@ public abstract class ScalarTypeBaseVarchar<T> extends ScalarTypeBase<T> {
dataOutput.writeUTF(s);
}
}
@Override
public Object jsonRead(JsonParser ctx, Event event) {
return parse(ctx.getString());
}
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
ctx.write(name, format(value));
}
}
@@ -4,9 +4,14 @@ 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 javax.json.stream.JsonGenerator;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
/**
@@ -74,5 +79,15 @@ public class ScalarTypeBigDecimal extends ScalarTypeBase<BigDecimal> {
public boolean isDateTimeCapable() {
return true;
}
@Override
public Object jsonRead(JsonParser ctx, Event event) {
return ctx.getBigDecimal();
}
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
ctx.write(name, (BigDecimal)value);
}
}
@@ -3,9 +3,14 @@ package com.avaje.ebeaninternal.server.type;
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 javax.json.stream.JsonGenerator;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.avaje.ebean.text.TextException;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
@@ -286,6 +291,15 @@ public class ScalarTypeBoolean {
dataOutput.writeBoolean(val.booleanValue());
}
}
@Override
public Object jsonRead(JsonParser ctx, Event event) {
return Event.VALUE_TRUE == event ? Boolean.TRUE : Boolean.FALSE;
}
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
ctx.write(name, (Boolean)value);
}
}
}
@@ -6,6 +6,9 @@ import java.io.IOException;
import java.sql.SQLException;
import java.sql.Types;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.avaje.ebean.text.TextException;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
@@ -39,7 +42,13 @@ public class ScalarTypeByte extends ScalarTypeBase<Byte> {
}
public String formatValue(Byte t) {
@Override
public Object jsonRead(JsonParser ctx, Event event) {
throw new TextException("Not supported");
}
public String formatValue(Byte t) {
return t.toString();
}
@@ -5,6 +5,9 @@ import java.io.DataOutput;
import java.io.IOException;
import java.sql.SQLException;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.avaje.ebean.text.TextException;
/**
@@ -41,7 +44,12 @@ public abstract class ScalarTypeBytesBase extends ScalarTypeBase<byte[]> {
}
public String formatValue(byte[] t) {
@Override
public Object jsonRead(JsonParser ctx, Event event) {
throw new TextException("Not supported");
}
public String formatValue(byte[] t) {
throw new TextException("Not supported");
}
@@ -5,6 +5,10 @@ import java.io.DataOutput;
import java.io.IOException;
import java.sql.SQLException;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.avaje.ebean.text.TextException;
import com.avaje.ebean.text.json.JsonValueAdapter;
import com.avaje.ebeaninternal.server.text.json.WriteJsonBuffer;
@@ -65,6 +69,11 @@ public class ScalarTypeBytesEncrypted implements ScalarType<byte[]> {
baseType.loadIgnore(dataReader);
}
@Override
public Object jsonRead(JsonParser ctx, Event event) {
throw new TextException("Not supported");
}
public String format(Object v) {
throw new RuntimeException("Not used");
}
@@ -39,6 +39,11 @@ public class ScalarTypeCalendar extends ScalarTypeBaseDateTime<Calendar> {
return calendar;
}
@Override
public long convertToMillis(Object value) {
return ((Calendar) value).getTimeInMillis();
}
@Override
public Timestamp convertToTimestamp(Calendar t) {
return new Timestamp(t.getTimeInMillis());
@@ -3,6 +3,9 @@ package com.avaje.ebeaninternal.server.type;
import java.sql.SQLException;
import java.sql.Types;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.avaje.ebean.text.json.JsonValueAdapter;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
@@ -70,4 +73,10 @@ public class ScalarTypeChar extends ScalarTypeBaseVarchar<Character> {
return EscapeJson.escapeQuote(value.toString());
}
@Override
public Object jsonRead(JsonParser ctx, Event event) {
return ctx.getString();
}
}
@@ -1,8 +1,13 @@
package com.avaje.ebeaninternal.server.type;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.sql.Types;
import javax.json.stream.JsonGenerator;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.avaje.ebean.text.json.JsonValueAdapter;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
@@ -70,4 +75,12 @@ public class ScalarTypeCharArray extends ScalarTypeBaseVarchar<char[]>{
return EscapeJson.escapeQuote(String.valueOf(value));
}
@Override
public Object jsonRead(JsonParser ctx, Event event) {
return ctx.getString().toCharArray();
}
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
ctx.write(name, String.valueOf(value));
}
}
@@ -1,5 +1,6 @@
package com.avaje.ebeaninternal.server.type;
import javax.json.stream.JsonGenerator;
import javax.persistence.PersistenceException;
/**
@@ -42,6 +43,10 @@ public class ScalarTypeClass extends ScalarTypeBaseVarchar<Class> {
throw new PersistenceException(msg, e);
}
}
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
ctx.write(name, formatValue((Class<?>)value));
}
}
@@ -2,6 +2,10 @@ package com.avaje.ebeaninternal.server.type;
import java.util.Currency;
import javax.json.stream.JsonGenerator;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
/**
* ScalarType for java.util.Currency which converts to and from a VARCHAR database column.
*/
@@ -33,5 +37,13 @@ public class ScalarTypeCurrency extends ScalarTypeBaseVarchar<Currency> {
public Currency parse(String value) {
return Currency.getInstance(value);
}
@Override
public Object jsonRead(JsonParser ctx, Event event) {
return parse(ctx.getString());
}
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
ctx.write(name, formatValue((Currency)value));
}
}
@@ -14,8 +14,13 @@ public class ScalarTypeDate extends ScalarTypeBaseDate<java.sql.Date> {
public ScalarTypeDate() {
super(Date.class, true, Types.DATE);
}
@Override
public long convertToMillis(Object value) {
return ((Date)value).getTime();
}
@Override
public Date convertFromDate(Date date) {
return date;
}
@@ -5,6 +5,11 @@ import java.io.DataOutput;
import java.io.IOException;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Currency;
import javax.json.stream.JsonGenerator;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
@@ -82,4 +87,13 @@ public class ScalarTypeDouble extends ScalarTypeBase<Double> {
dataOutput.writeDouble(value.doubleValue());
}
}
@Override
public Object jsonRead(JsonParser ctx, Event event) {
return ctx.getBigDecimal().doubleValue();
}
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
ctx.write(name, (Double)value);
}
}
@@ -5,6 +5,10 @@ import java.io.DataOutput;
import java.io.IOException;
import java.sql.SQLException;
import javax.json.stream.JsonGenerator;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.avaje.ebean.text.json.JsonValueAdapter;
import com.avaje.ebeaninternal.server.text.json.WriteJsonBuffer;
@@ -31,7 +35,12 @@ public class ScalarTypeEncryptedWrapper<T> implements ScalarType<T> {
public boolean isDirty(Object value) {
return wrapped.isDirty(value);
}
@Override
public Object jsonRead(JsonParser ctx, Event event) {
return wrapped.jsonRead(ctx, event);
}
public Object readData(DataInput dataInput) throws IOException {
return wrapped.readData(dataInput);
}
@@ -126,4 +135,7 @@ public class ScalarTypeEncryptedWrapper<T> implements ScalarType<T> {
return wrapped.jsonFromString(value, ctx);
}
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
wrapped.jsonWrite(ctx, name, value);
}
}
@@ -7,6 +7,10 @@ import java.sql.SQLException;
import java.sql.Types;
import java.util.EnumSet;
import javax.json.stream.JsonGenerator;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.avaje.ebean.text.TextException;
import com.avaje.ebean.text.json.JsonValueAdapter;
@@ -225,6 +229,17 @@ public class ScalarTypeEnumStandard {
public boolean isDateTimeCapable() {
return false;
}
@Override
public Object jsonRead(JsonParser ctx, Event event) {
String val = ctx.getString();
return parse(val);
}
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
ctx.write(name, formatValue(value));
}
@Override
public Object jsonFromString(String value, JsonValueAdapter ctx) {
@@ -6,6 +6,10 @@ import java.io.IOException;
import java.sql.SQLException;
import java.sql.Types;
import javax.json.stream.JsonGenerator;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
/**
@@ -81,4 +85,13 @@ public class ScalarTypeFloat extends ScalarTypeBase<Float> {
dataOutput.writeFloat(value.floatValue());
}
}
@Override
public Object jsonRead(JsonParser ctx, Event event) {
return ctx.getBigDecimal().floatValue();
}
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
ctx.write(name, (Float)value);
}
}
@@ -6,6 +6,10 @@ import java.io.IOException;
import java.sql.SQLException;
import java.sql.Types;
import javax.json.stream.JsonGenerator;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.avaje.ebean.text.TextException;
import com.avaje.ebean.text.json.JsonValueAdapter;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
@@ -71,4 +75,14 @@ public class ScalarTypeInteger extends ScalarTypeBase<Integer> {
public Integer jsonFromString(String value, JsonValueAdapter ctx) {
return Integer.valueOf(value);
}
@Override
public Object jsonRead(JsonParser ctx, Event event) {
return Integer.valueOf(ctx.getInt());
}
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
ctx.write(name, (Integer)value);
}
}
@@ -4,6 +4,7 @@ import java.sql.Date;
import java.sql.Types;
import org.joda.time.DateMidnight;
import org.joda.time.DateTime;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
@@ -19,6 +20,11 @@ public class ScalarTypeJodaDateMidnight extends ScalarTypeBaseDate<DateMidnight>
super(DateMidnight.class, false, Types.DATE);
}
@Override
public long convertToMillis(Object value) {
return ((DateMidnight) value).getMillis();
}
@Override
public DateMidnight convertFromDate(Date ts) {
return new DateMidnight(ts.getTime());
@@ -4,6 +4,7 @@ import java.sql.Timestamp;
import java.sql.Types;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
@@ -16,6 +17,11 @@ public class ScalarTypeJodaDateTime extends ScalarTypeBaseDateTime<DateTime> {
super(DateTime.class, false, Types.TIMESTAMP);
}
@Override
public long convertToMillis(Object value) {
return ((DateTime) value).getMillis();
}
@Override
public DateTime convertFromTimestamp(Timestamp ts) {
return new DateTime(ts.getTime());
@@ -17,6 +17,11 @@ public class ScalarTypeJodaLocalDate extends ScalarTypeBaseDate<LocalDate> {
}
@Override
public long convertToMillis(Object value) {
return ((LocalDate)value).toDateMidnight().getMillis();
}
@Override
public LocalDate convertFromDate(Date ts) {
return new LocalDate(((java.util.Date)ts).getTime());
}
@@ -16,7 +16,14 @@ public class ScalarTypeJodaLocalDateTime extends ScalarTypeBaseDateTime<LocalDat
super(LocalDateTime.class, false, Types.TIMESTAMP);
}
@Override
public long convertToMillis(Object value) {
return ((LocalDateTime)value).toDateTime().getMillis();
}
@Override
public LocalDateTime convertFromTimestamp(Timestamp ts) {
return new LocalDateTime(ts.getTime());
}
@@ -7,6 +7,10 @@ import java.sql.SQLException;
import java.sql.Time;
import java.sql.Types;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import org.joda.time.DateMidnight;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalTime;
@@ -20,7 +24,7 @@ public class ScalarTypeJodaLocalTime extends ScalarTypeBase<LocalTime> {
public ScalarTypeJodaLocalTime() {
super(LocalTime.class, false, Types.TIME);
}
public void bind(DataBind b, LocalTime value) throws SQLException {
if (value == null){
b.setNull(Types.TIME);
@@ -61,8 +65,21 @@ public class ScalarTypeJodaLocalTime extends ScalarTypeBase<LocalTime> {
public LocalTime parse(String value) {
return new LocalTime(value);
}
public LocalTime parseDateTime(long systemTimeMillis) {
@Override
public Object jsonRead(JsonParser ctx, Event event) {
if (ctx.isIntegralNumber()) {
long millis = ctx.getLong();
return parseDateTime(millis);
} else {
String string = ctx.getString();
throw new RuntimeException("convert "+string);
}
}
public LocalTime parseDateTime(long systemTimeMillis) {
return new LocalTime(systemTimeMillis);
}
@@ -6,6 +6,10 @@ import java.io.IOException;
import java.sql.SQLException;
import java.sql.Types;
import javax.json.stream.JsonGenerator;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
/**
@@ -73,4 +77,13 @@ public class ScalarTypeLong extends ScalarTypeBase<Long> {
dataOutput.writeLong(value.longValue());
}
}
@Override
public Object jsonRead(JsonParser ctx, Event event) {
return ctx.getLong();
}
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
ctx.write(name, (Long)value);
}
}
@@ -7,6 +7,10 @@ import java.math.BigInteger;
import java.sql.SQLException;
import java.sql.Types;
import javax.json.stream.JsonGenerator;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
/**
@@ -80,4 +84,13 @@ public class ScalarTypeMathBigInteger extends ScalarTypeBase<BigInteger> {
}
}
@Override
public Object jsonRead(JsonParser ctx, Event event) {
return ctx.getBigDecimal().toBigInteger();
}
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
ctx.write(name, (BigInteger)value);
}
}
@@ -6,6 +6,9 @@ import java.io.IOException;
import java.sql.SQLException;
import java.util.Map;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.avaje.ebean.config.dbplatform.PostgresPlatform;
/**
@@ -63,6 +66,12 @@ public class ScalarTypePostgresHstore extends ScalarTypeBase<Map> {
public Map toBeanType(Object value) {
return (Map)value;
}
@Override
public Object jsonRead(JsonParser ctx, Event event) {
// TODO Auto-generated method stub
return null;
}
@Override
public String formatValue(Map v) {
@@ -6,6 +6,10 @@ import java.io.IOException;
import java.sql.SQLException;
import java.sql.Types;
import javax.json.stream.JsonGenerator;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.avaje.ebean.text.TextException;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
@@ -74,4 +78,13 @@ public class ScalarTypeShort extends ScalarTypeBase<Short> {
dataOutput.writeShort(value.shortValue());
}
}
@Override
public Object jsonRead(JsonParser ctx, Event event) {
return (short)ctx.getInt();
}
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
ctx.write(name, (Short)value);
}
}
@@ -6,6 +6,10 @@ import java.io.IOException;
import java.sql.SQLException;
import java.sql.Types;
import javax.json.stream.JsonGenerator;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.avaje.ebean.text.json.JsonValueAdapter;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
import com.avaje.ebeaninternal.server.text.json.WriteJsonBuffer;
@@ -92,5 +96,12 @@ public class ScalarTypeString extends ScalarTypeBase<String> {
}
}
@Override
public Object jsonRead(JsonParser ctx, Event event) {
return ctx.getString();
}
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
ctx.write(name, (String)value);
}
}
@@ -7,6 +7,10 @@ import java.sql.SQLException;
import java.sql.Time;
import java.sql.Types;
import javax.json.stream.JsonGenerator;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
/**
@@ -75,5 +79,15 @@ public class ScalarTypeTime extends ScalarTypeBase<Time> {
dataOutput.writeUTF(format(value));
}
}
@Override
public Object jsonRead(JsonParser ctx, Event event) {
return parse(ctx.getString());
}
@Override
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
ctx.write(name, value.toString());
}
}
@@ -1,5 +1,6 @@
package com.avaje.ebeaninternal.server.type;
import java.sql.Date;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
@@ -15,6 +16,11 @@ public class ScalarTypeTimestamp extends ScalarTypeBaseDateTime<Timestamp> {
super(Timestamp.class, true, Types.TIMESTAMP);
}
@Override
public long convertToMillis(Object value) {
return ((Timestamp)value).getTime();
}
@Override
public Timestamp convertFromTimestamp(Timestamp ts) {
return ts;
@@ -3,6 +3,9 @@ package com.avaje.ebeaninternal.server.type;
import java.net.MalformedURLException;
import java.net.URL;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.avaje.ebean.text.TextException;
/**
@@ -40,4 +43,10 @@ public class ScalarTypeURL extends ScalarTypeBaseVarchar<URL> {
throw new TextException(e);
}
}
@Override
public Object jsonRead(JsonParser ctx, Event event) {
return parse(ctx.getString());
}
}
@@ -11,6 +11,10 @@ import java.sql.SQLException;
import java.sql.Types;
import java.util.UUID;
import javax.json.stream.JsonGenerator;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
public class ScalarTypeUUIDBinary extends ScalarTypeBase<UUID> {
protected ScalarTypeUUIDBinary() {
@@ -138,4 +142,14 @@ public class ScalarTypeUUIDBinary extends ScalarTypeBase<UUID> {
}
}
@Override
public Object jsonRead(JsonParser ctx, Event event) {
return UUID.fromString(ctx.getString());
}
@Override
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
ctx.write(name, value.toString());
}
}
@@ -2,6 +2,9 @@ package com.avaje.ebeaninternal.server.type;
import java.util.UUID;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
/**
@@ -44,4 +47,9 @@ public class ScalarTypeUUIDVarchar extends ScalarTypeBaseVarchar<UUID> {
return UUID.fromString(value);
}
@Override
public Object jsonRead(JsonParser ctx, Event event) {
return UUID.fromString(ctx.getString());
}
}
@@ -17,7 +17,12 @@ public class ScalarTypeUtilDate {
public TimestampType() {
super(java.util.Date.class, false, Types.TIMESTAMP);
}
@Override
public long convertToMillis(Object value) {
return BasicTypeConverter.toTimestamp(value).getTime();
}
public java.util.Date read(DataReader dataReader) throws SQLException {
Timestamp timestamp = dataReader.getTimestamp();
if (timestamp == null) {
@@ -69,7 +74,15 @@ public class ScalarTypeUtilDate {
super(Date.class, false, Types.DATE);
}
@Override
public long convertToMillis(Object value) {
java.sql.Date date = BasicTypeConverter.toDate(value);
return date.getTime();
}
@Override
public Date convertFromDate(java.sql.Date ts) {
return new java.util.Date(ts.getTime());
}
@@ -5,6 +5,10 @@ import java.io.DataOutput;
import java.io.IOException;
import java.sql.SQLException;
import javax.json.stream.JsonGenerator;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.avaje.ebean.config.ScalarTypeConverter;
import com.avaje.ebean.text.json.JsonValueAdapter;
import com.avaje.ebeaninternal.server.text.json.WriteJsonBuffer;
@@ -180,5 +184,20 @@ public class ScalarTypeWrapper<B, S> implements ScalarType<B> {
S s = scalarType.jsonFromString(value, ctx);
return converter.wrapValue(s);
}
@SuppressWarnings("unchecked")
@Override
public Object jsonRead(JsonParser ctx, Event event) {
Object object = scalarType.jsonRead(ctx, event);
return converter.wrapValue((S)object);
}
@Override
public void jsonWrite(JsonGenerator ctx, String name, Object beanValue) {
S unwrapValue = converter.unwrapValue((B)beanValue);
scalarType.jsonWrite(ctx, name, unwrapValue);
}
}