From 0ceda6406e6d1434b989aabd21bdaf709b68e6fb Mon Sep 17 00:00:00 2001 From: Rob Bygrave Date: Sat, 28 Jun 2014 03:09:10 +1200 Subject: [PATCH] WIP on JSON refactor --- pom.xml | 6 + src/main/java/com/avaje/ebean/json/EJson.java | 44 +++ .../com/avaje/ebean/json/EJsonReader.java | 271 ++++++++++++++++++ .../com/avaje/ebean/json/EJsonWriter.java | 201 +++++++++++++ .../server/deploy/BeanDescriptor.java | 96 +------ .../server/deploy/BeanDescriptorJsonHelp.java | 190 ++++++++++++ .../server/deploy/BeanProperty.java | 72 +++-- .../server/deploy/BeanPropertyAssocMany.java | 40 +-- .../deploy/BeanPropertyAssocManyJsonHelp.java | 49 ++++ .../server/deploy/BeanPropertyAssocOne.java | 13 +- .../server/deploy/EJsonReader.java | 215 ++++++++++++++ .../ebeaninternal/server/deploy/ReadJson.java | 9 + .../server/text/json/DJsonContext.java | 61 ++-- .../ebeaninternal/server/type/ScalarType.java | 8 + .../server/type/ScalarTypeBaseDate.java | 22 ++ .../server/type/ScalarTypeBaseDateTime.java | 23 ++ .../server/type/ScalarTypeBaseVarchar.java | 13 + .../server/type/ScalarTypeBigDecimal.java | 15 + .../server/type/ScalarTypeBoolean.java | 14 + .../server/type/ScalarTypeByte.java | 11 +- .../server/type/ScalarTypeBytesBase.java | 10 +- .../server/type/ScalarTypeBytesEncrypted.java | 9 + .../server/type/ScalarTypeCalendar.java | 5 + .../server/type/ScalarTypeChar.java | 9 + .../server/type/ScalarTypeCharArray.java | 13 + .../server/type/ScalarTypeClass.java | 5 + .../server/type/ScalarTypeCurrency.java | 14 +- .../server/type/ScalarTypeDate.java | 7 +- .../server/type/ScalarTypeDouble.java | 14 + .../type/ScalarTypeEncryptedWrapper.java | 14 +- .../server/type/ScalarTypeEnumStandard.java | 15 + .../server/type/ScalarTypeFloat.java | 13 + .../server/type/ScalarTypeInteger.java | 14 + .../type/ScalarTypeJodaDateMidnight.java | 6 + .../server/type/ScalarTypeJodaDateTime.java | 6 + .../server/type/ScalarTypeJodaLocalDate.java | 5 + .../type/ScalarTypeJodaLocalDateTime.java | 7 + .../server/type/ScalarTypeJodaLocalTime.java | 23 +- .../server/type/ScalarTypeLong.java | 13 + .../server/type/ScalarTypeMathBigInteger.java | 13 + .../server/type/ScalarTypePostgresHstore.java | 9 + .../server/type/ScalarTypeShort.java | 13 + .../server/type/ScalarTypeString.java | 11 + .../server/type/ScalarTypeTime.java | 16 +- .../server/type/ScalarTypeTimestamp.java | 6 + .../server/type/ScalarTypeURL.java | 9 + .../server/type/ScalarTypeUUIDBinary.java | 14 + .../server/type/ScalarTypeUUIDVarchar.java | 8 + .../server/type/ScalarTypeUtilDate.java | 15 +- .../server/type/ScalarTypeWrapper.java | 19 ++ .../json/TestJsonBeanDescriptorParse.java | 45 +++ .../tests/text/json/TestTextJsonSimple.java | 4 +- 52 files changed, 1583 insertions(+), 174 deletions(-) create mode 100644 src/main/java/com/avaje/ebean/json/EJson.java create mode 100644 src/main/java/com/avaje/ebean/json/EJsonReader.java create mode 100644 src/main/java/com/avaje/ebean/json/EJsonWriter.java create mode 100644 src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorJsonHelp.java create mode 100644 src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocManyJsonHelp.java create mode 100644 src/main/java/com/avaje/ebeaninternal/server/deploy/EJsonReader.java create mode 100644 src/main/java/com/avaje/ebeaninternal/server/deploy/ReadJson.java create mode 100644 src/test/java/com/avaje/tests/text/json/TestJsonBeanDescriptorParse.java diff --git a/pom.xml b/pom.xml index 12d29b0c5..5af102284 100644 --- a/pom.xml +++ b/pom.xml @@ -63,6 +63,12 @@ provided + + org.glassfish + javax.json + 1.0.4 + + javax.servlet servlet-api diff --git a/src/main/java/com/avaje/ebean/json/EJson.java b/src/main/java/com/avaje/ebean/json/EJson.java new file mode 100644 index 000000000..2f9da3541 --- /dev/null +++ b/src/main/java/com/avaje/ebean/json/EJson.java @@ -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 parseObject(String json) { + return EJsonReader.parseObject(json); + } + + public static List 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); + } +} diff --git a/src/main/java/com/avaje/ebean/json/EJsonReader.java b/src/main/java/com/avaje/ebean/json/EJsonReader.java new file mode 100644 index 000000000..1f37ed821 --- /dev/null +++ b/src/main/java/com/avaje/ebean/json/EJsonReader.java @@ -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 parseObject(String json) { + return (Map) parse(json); + } + + @SuppressWarnings("unchecked") + public static List parseList(String json) { + return (List) 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. + *

+ * 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 map = new LinkedHashMap(); + + 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 values = new ArrayList(); + + Object getValue() { + return values; + } + + void setValue(Object value) { + values.add(value); + } + + void setValueNull() { + // ignore + } + void setKey(String key) { + // not expected + } + } + +} diff --git a/src/main/java/com/avaje/ebean/json/EJsonWriter.java b/src/main/java/com/avaje/ebean/json/EJsonWriter.java new file mode 100644 index 000000000..2f98c04b9 --- /dev/null +++ b/src/main/java/com/avaje/ebean/json/EJsonWriter.java @@ -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); + + } else if (object instanceof Collection) { + writeCollection(name, (Collection) 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 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 map) { + + if (name == null) { + jsonGenerator.writeStartObject(); + } else { + jsonGenerator.writeStartObject(name); + } + Set> entrySet = map.entrySet(); + for (Entry entry : entrySet) { + writeJson(entry.getKey().toString(), entry.getValue()); + } + jsonGenerator.writeEnd(); + } + +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java index 28b2b621c..437269d41 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java @@ -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 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 implements MetaBeanInfo { private final boolean cacheSharableBeans; private final BeanDescriptorCacheHelp cacheHelp; - + private final BeanDescriptorJsonHelp jsonHelp; + private final String defaultSelectClause; private final Set defaultSelectClauseSet; @@ -422,7 +424,7 @@ public class BeanDescriptor implements MetaBeanInfo { this.cacheSharableBeans = noRelationships && deploy.getCacheOptions().isReadOnly(); this.cacheHelp = new BeanDescriptorCacheHelp(this, owner.getCacheManager(), deploy.getCacheOptions(), cacheSharableBeans, propertiesOneImported); - + this.jsonHelp = new BeanDescriptorJsonHelp(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 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); } - } diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorJsonHelp.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorJsonHelp.java new file mode 100644 index 000000000..8d93b3937 --- /dev/null +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorJsonHelp.java @@ -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 { + + private final BeanDescriptor desc; + private final InheritInfo inheritInfo; + + public BeanDescriptorJsonHelp(BeanDescriptor 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 beanVisitor = (JsonWriteBeanVisitor) ctx.getBeanVisitor(); + + Set 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; + } + +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanProperty.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanProperty.java index 7eff03cb3..6c3813db7 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanProperty.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanProperty.java @@ -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); + } + + } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocMany.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocMany.java index 156b3a1b2..5f8da9623 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocMany.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocMany.java @@ -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 extends BeanPropertyAssoc { 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 extends BeanPropertyAssoc { /** * 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 extends BeanPropertyAssoc { 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 extends BeanPropertyAssoc { } } - 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); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocManyJsonHelp.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocManyJsonHelp.java new file mode 100644 index 000000000..9c923f52d --- /dev/null +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocManyJsonHelp.java @@ -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); + } +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocOne.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocOne.java index 7d9b620bc..b6ac0d47d 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocOne.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocOne.java @@ -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 extends BeanPropertyAssoc { } } } - + @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) { diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/EJsonReader.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/EJsonReader.java new file mode 100644 index 000000000..71f4e790e --- /dev/null +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/EJsonReader.java @@ -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 parseObject(String json) { + return (Map) parse(json); + } + + @SuppressWarnings("unchecked") + public static List parseList(String json) { + return (List) 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 map = new LinkedHashMap(); + + 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 values = new ArrayList(); + + Object getValue() { + return values; + } + + void setValue(Object value) { + values.add(value); + } + + void setValueNull() { + } + void setKey(String key) { + } + } + +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/ReadJson.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/ReadJson.java new file mode 100644 index 000000000..871517f40 --- /dev/null +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/ReadJson.java @@ -0,0 +1,9 @@ +package com.avaje.ebeaninternal.server.deploy; + +import javax.json.stream.JsonParser; + +public class ReadJson { + + JsonParser parser; + +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/text/json/DJsonContext.java b/src/main/java/com/avaje/ebeaninternal/server/text/json/DJsonContext.java index a176731bb..582c72ac7 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/text/json/DJsonContext.java +++ b/src/main/java/com/avaje/ebeaninternal/server/text/json/DJsonContext.java @@ -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 toBean(Class cls, String json){ - return toBean(cls, new ReadJsonSourceString(json), null); + return toBean(cls, new StringReader(json), null); } public T toBean(Class cls, Reader jsonReader) { @@ -61,26 +67,33 @@ public class DJsonContext implements JsonContext { } public T toBean(Class cls, String json, JsonReadOptions options){ - return toBean(cls, new ReadJsonSourceString(json), options); + return toBean(cls, new StringReader(json), options); } public T toBean(Class cls, Reader jsonReader, JsonReadOptions options) { return toBean(cls, createReader(jsonReader), options); } - private T toBean(Class cls, ReadJsonSource src, JsonReadOptions options){ +// private T toBean(Class cls, ReadJsonSource src, JsonReadOptions options){ +// +// BeanDescriptor d = getDecriptor(cls); +// ReadJsonContext ctx = new ReadJsonContext(src, dfltValueAdapter, options); +// return d.jsonReadBean(ctx, null); +// } - BeanDescriptor d = getDecriptor(cls); - ReadJsonContext ctx = new ReadJsonContext(src, dfltValueAdapter, options); - return d.jsonReadBean(ctx, null); + private T toBean(Class cls, JsonParser parser, JsonReadOptions options) { + + BeanDescriptor d = getDecriptor(cls); + // ReadJsonContext ctx = new ReadJsonContext(src, dfltValueAdapter, options); + return d.jsonRead(parser, null); } - + public List toList(Class cls, String json){ - return toList(cls, new ReadJsonSourceString(json), null); + return toList(cls, new StringReader(json), null); } public List toList(Class cls, String json, JsonReadOptions options){ - return toList(cls, new ReadJsonSourceString(json), options); + return toList(cls, new StringReader(json), options); } public List toList(Class cls, Reader jsonReader){ @@ -91,26 +104,36 @@ public class DJsonContext implements JsonContext { return toList(cls, createReader(jsonReader), options); } - private List toList(Class cls, ReadJsonSource src, JsonReadOptions options){ + private List toList(Class cls, JsonParser src, JsonReadOptions options){ try { BeanDescriptor d = getDecriptor(cls); List list = new ArrayList(); - 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); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarType.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarType.java index 693a46a3d..9f7db04de 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarType.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarType.java @@ -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 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); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBaseDate.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBaseDate.java index b11c01c2c..b0d4e4c79 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBaseDate.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBaseDate.java @@ -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 extends ScalarTypeBase { 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); diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBaseDateTime.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBaseDateTime.java index 9c6d3f0e2..216b2e9f8 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBaseDateTime.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBaseDateTime.java @@ -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 extends ScalarTypeBase { 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 extends ScalarTypeBase { } } + @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(); diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBaseVarchar.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBaseVarchar.java index e54a325ce..41c81456b 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBaseVarchar.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBaseVarchar.java @@ -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 extends ScalarTypeBase { 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)); + } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBigDecimal.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBigDecimal.java index bc3e1e25a..91f363fe5 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBigDecimal.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBigDecimal.java @@ -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 { 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); + } + } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBoolean.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBoolean.java index f26d43e21..44608da90 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBoolean.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBoolean.java @@ -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); + } } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeByte.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeByte.java index 502e37b10..1cc744142 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeByte.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeByte.java @@ -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 { } - 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(); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBytesBase.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBytesBase.java index 34992b06c..479b69132 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBytesBase.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBytesBase.java @@ -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 { } - 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"); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBytesEncrypted.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBytesEncrypted.java index 843977369..abad19df5 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBytesEncrypted.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeBytesEncrypted.java @@ -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 { 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"); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeCalendar.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeCalendar.java index 4655f4d93..c21e95600 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeCalendar.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeCalendar.java @@ -39,6 +39,11 @@ public class ScalarTypeCalendar extends ScalarTypeBaseDateTime { return calendar; } + @Override + public long convertToMillis(Object value) { + return ((Calendar) value).getTimeInMillis(); + } + @Override public Timestamp convertToTimestamp(Calendar t) { return new Timestamp(t.getTimeInMillis()); diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeChar.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeChar.java index c69474b47..88d6bc063 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeChar.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeChar.java @@ -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 { return EscapeJson.escapeQuote(value.toString()); } + @Override + public Object jsonRead(JsonParser ctx, Event event) { + return ctx.getString(); + } + + } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeCharArray.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeCharArray.java index 83cea2c8c..52e3ca1c4 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeCharArray.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeCharArray.java @@ -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{ 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)); + } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeClass.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeClass.java index 22f0450ae..e2a1f110d 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeClass.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeClass.java @@ -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 { throw new PersistenceException(msg, e); } } + + public void jsonWrite(JsonGenerator ctx, String name, Object value) { + ctx.write(name, formatValue((Class)value)); + } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeCurrency.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeCurrency.java index d952a9fe3..eb58f0d7c 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeCurrency.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeCurrency.java @@ -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 { 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)); + } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeDate.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeDate.java index 0da8b8e44..f74774c1d 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeDate.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeDate.java @@ -14,8 +14,13 @@ public class ScalarTypeDate extends ScalarTypeBaseDate { 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; } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeDouble.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeDouble.java index 751a84405..65be80b09 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeDouble.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeDouble.java @@ -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 { 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); + } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeEncryptedWrapper.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeEncryptedWrapper.java index 222e74b1b..e8dc2c874 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeEncryptedWrapper.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeEncryptedWrapper.java @@ -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 implements ScalarType { 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 implements ScalarType { return wrapped.jsonFromString(value, ctx); } + public void jsonWrite(JsonGenerator ctx, String name, Object value) { + wrapped.jsonWrite(ctx, name, value); + } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeEnumStandard.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeEnumStandard.java index 86bacbe31..3dc1e6a22 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeEnumStandard.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeEnumStandard.java @@ -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) { diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeFloat.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeFloat.java index 516c1bd43..973cc752b 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeFloat.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeFloat.java @@ -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 { 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); + } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeInteger.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeInteger.java index 6c67ff1c6..c18d27fcd 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeInteger.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeInteger.java @@ -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 { 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); + } + } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeJodaDateMidnight.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeJodaDateMidnight.java index ba6c8cc81..464255cc9 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeJodaDateMidnight.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeJodaDateMidnight.java @@ -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 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()); diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeJodaDateTime.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeJodaDateTime.java index 8ddb187a4..485007afc 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeJodaDateTime.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeJodaDateTime.java @@ -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 { 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()); diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeJodaLocalDate.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeJodaLocalDate.java index 3ad217090..703905fd9 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeJodaLocalDate.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeJodaLocalDate.java @@ -17,6 +17,11 @@ public class ScalarTypeJodaLocalDate extends ScalarTypeBaseDate { } @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()); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeJodaLocalDateTime.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeJodaLocalDateTime.java index 848c7a4e8..755f6ae51 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeJodaLocalDateTime.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeJodaLocalDateTime.java @@ -16,7 +16,14 @@ public class ScalarTypeJodaLocalDateTime extends ScalarTypeBaseDateTime { 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 { 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); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeLong.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeLong.java index 1b586b714..5127d7f90 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeLong.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeLong.java @@ -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 { 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); + } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeMathBigInteger.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeMathBigInteger.java index e97b50222..c81303163 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeMathBigInteger.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeMathBigInteger.java @@ -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 { } } + @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); + } + } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypePostgresHstore.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypePostgresHstore.java index 1563f9c5e..bb0f5fb1d 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypePostgresHstore.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypePostgresHstore.java @@ -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 { 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) { diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeShort.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeShort.java index 40f9a3940..0556411fc 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeShort.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeShort.java @@ -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 { 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); + } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeString.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeString.java index 254cd12fa..2e81b917b 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeString.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeString.java @@ -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 { } } + @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); + } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeTime.java b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeTime.java index 01a245a08..55ada137a 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeTime.java +++ b/src/main/java/com/avaje/ebeaninternal/server/type/ScalarTypeTime.java @@ -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