JSON Refactor - compound type support

This commit is contained in:
Rob Bygrave
2014-11-06 23:18:20 +13:00
parent b313809894
commit 58755a51a9
68 changed files with 334 additions and 2849 deletions
+20 -2
View File
@@ -88,13 +88,31 @@ public class EJson {
* Parse the json and return as a List or Map.
*/
public static Object parse(Reader reader) {
return EJsonReader.parse(reader);
return EJsonReader.parse(reader, false);
}
/**
* Parse the json and return as a List or Map.
*/
public static Object parse(JsonParser parser) {
return EJsonReader.parse(parser);
return EJsonReader.parse(parser, false);
}
/**
* Parse the json and return the next json value, List or Map.
* This will not consume all the reader content and return once the
* next json object, list or value is read.
*/
public static Object parsePartial(Reader reader) {
return EJsonReader.parse(reader, true);
}
/**
* Parse the json and return the next json value, List or Map.
* This will not consume all the reader content and return once the
* next json object, list or value is read.
*/
public static Object parsePartial(JsonParser parser) {
return EJsonReader.parse(parser, true);
}
}
@@ -21,12 +21,12 @@ class EJsonReader {
@SuppressWarnings("unchecked")
static Map<String, Object> parseObject(Reader reader) {
return (Map<String, Object>) parse(reader);
return (Map<String, Object>) parse(reader, false);
}
@SuppressWarnings("unchecked")
static Map<String, Object> parseObject(JsonParser parser) {
return (Map<String, Object>) parse(parser);
return (Map<String, Object>) parse(parser, false);
}
@SuppressWarnings("unchecked")
@@ -36,43 +36,50 @@ class EJsonReader {
@SuppressWarnings("unchecked")
static List<Object> parseList(Reader reader) {
return (List<Object>) parse(reader);
return (List<Object>) parse(reader, false);
}
@SuppressWarnings("unchecked")
static List<Object> parseList(JsonParser parser) {
return (List<Object>) parse(parser);
return (List<Object>) parse(parser, false);
}
static Object parse(String json) {
return parse(new StringReader(json));
return parse(new StringReader(json), false);
}
static Object parse(Reader reader) {
return parse(Json.createParser(reader));
static Object parse(Reader reader, boolean partial) {
return parse(Json.createParser(reader), partial);
}
static Object parse(JsonParser parser) {
return new EJsonReader(parser).parseJson();
static Object parse(JsonParser parser, boolean partial) {
return new EJsonReader(parser, partial).parseJson();
}
private final JsonParser parser;
private final boolean partial;
private int depth;
private Stack stack;
private Context currentContext;
EJsonReader(JsonParser parser) {
EJsonReader(JsonParser parser, boolean partial) {
this.parser = parser;
this.partial = partial;
}
private void startArray() {
depth++;
stack.push(currentContext);
currentContext = new ArrayContext();
}
private void startObject() {
depth++;
stack.push(currentContext);
currentContext = new ObjectContext();
}
@@ -86,6 +93,7 @@ class EJsonReader {
}
private void end() {
depth--;
if (!stack.isEmpty()) {
//if (currentContext != null) {
@@ -127,6 +135,12 @@ class EJsonReader {
// process the rest of the object or array
while (parser.hasNext()) {
processEvent(parser.next());
if (partial && depth == 0) {
// completed the object/array
return currentContext.getValue();
}
}
return currentContext.getValue();
@@ -219,7 +233,7 @@ class EJsonReader {
private static final class Stack {
private Context head;
private void push(Context context) {
if (context != null) {
context.next = head;
@@ -64,6 +64,10 @@ class EJsonWriter {
} else if (object instanceof String) {
writeString(name, (String) object);
} else if (object instanceof Map.Entry<?, ?>) {
Map.Entry<?, ?> entry = (Map.Entry<?, ?>)object;
writeJson(entry.getKey().toString(), entry.getValue());
} else {
writeString(name, object.toString());
}
@@ -22,49 +22,27 @@ public interface JsonContext {
*/
public <T> T toBean(Class<T> rootType, Reader json);
/**
* Convert json string input into a Bean of a specific type with options.
*/
public <T> T toBean(Class<T> rootType, String json, JsonReadOptions options);
/**
* Convert json reader input into a Bean of a specific type with options.
*/
public <T> T toBean(Class<T> rootType, Reader json, JsonReadOptions options);
/**
* Convert json string input into a list of beans of a specific type.
*/
public <T> List<T> toList(Class<T> rootType, String json);
/**
* Convert json string input into a list of beans of a specific type with
* options.
*/
public <T> List<T> toList(Class<T> rootType, String json, JsonReadOptions options);
/**
* Convert json reader input into a list of beans of a specific type.
*/
public <T> List<T> toList(Class<T> rootType, Reader json);
/**
* Convert json reader input into a list of beans of a specific type with
* options.
* Use the genericType to determine if this should be converted into a List or
* bean.
*/
public <T> List<T> toList(Class<T> rootType, Reader json, JsonReadOptions options);
public Object toObject(Type genericType, Reader json);
/**
* Use the genericType to determine if this should be converted into a List or
* bean.
*/
public Object toObject(Type genericType, Reader json, JsonReadOptions options);
/**
* Use the genericType to determine if this should be converted into a List or
* bean.
*/
public Object toObject(Type genericType, String json, JsonReadOptions options);
public Object toObject(Type genericType, String json);
/**
* Write the bean or collection in JSON format to the writer with default
@@ -77,11 +55,6 @@ public interface JsonContext {
*/
public void toJsonWriter(Object o, Writer writer);
/**
* With additional pretty output option.
*/
public void toJsonWriter(Object o, Writer writer, boolean pretty);
/**
* With additional options to specify JsonValueAdapter and
* JsonWriteBeanVisitor's.
@@ -93,13 +66,7 @@ public interface JsonContext {
* @param options
* additional options to control the JSON output
*/
public void toJsonWriter(Object o, Writer writer, boolean pretty, JsonWriteOptions options);
/**
* With additional JSONP callback function.
*/
public void toJsonWriter(Object o, Writer writer, boolean pretty, JsonWriteOptions options,
String callback);
public void toJsonWriter(Object o, Writer writer, JsonWriteOptions options);
/**
* Convert a bean or collection to json string using default options.
@@ -107,20 +74,9 @@ public interface JsonContext {
public String toJsonString(Object o);
/**
* Convert a bean or collection to json string with pretty format using
* default options.
* Convert a bean or collection to json string.
*/
public String toJsonString(Object o, boolean pretty);
/**
* Convert a bean or collection to json string using options.
*/
public String toJsonString(Object o, boolean pretty, JsonWriteOptions options);
/**
* Convert a bean or collection to json string using a JSONP callback.
*/
public String toJsonString(Object o, boolean pretty, JsonWriteOptions options, String callback);
public String toJsonString(Object o, JsonWriteOptions options);
/**
* Return true if the type is known as an Entity or Xml type or a List Set or
@@ -1,39 +0,0 @@
package com.avaje.ebean.text.json;
/**
* Marker interface for all the Raw JSON types.
* <p>
* You will only use the JsonElements when you register a JsonReadBeanVisitor.
* The JSON elements that are not mapped to a bean property are made available
* to the JsonReadBeanVisitor.
* </p>
*
* @see JsonReadBeanVisitor
*
* @author rbygrave
*/
public interface JsonElement {
/**
* Return true if this is a JSON primitive type (null, boolean, number or
* string).
*/
public boolean isPrimitive();
/**
* Return the string value of this primitive JSON element.
* <p>
* This can not be used for JsonElementObject or JsonElementArray.
* </p>
*/
public String toPrimitiveString();
public Object eval(String exp);
public int evalInt(String exp);
public String evalString(String exp);
public boolean evalBoolean(String exp);
}
@@ -1,112 +0,0 @@
package com.avaje.ebean.text.json;
import java.util.ArrayList;
import java.util.List;
/**
* JSON Array element.
* <p>
* You will only use the JsonElements when you register a JsonReadBeanVisitor.
* The JSON elements that are not mapped to a bean property are made available
* to the JsonReadBeanVisitor.
* </p>
*
* @see JsonReadBeanVisitor
*
* @author rbygrave
*/
public class JsonElementArray implements JsonElement {
private final List<JsonElement> values = new ArrayList<JsonElement>();
public List<JsonElement> getValues() {
return values;
}
public void add(JsonElement value) {
values.add(value);
}
public String toString() {
return values.toString();
}
public boolean isPrimitive() {
return false;
}
public String toPrimitiveString() {
return null;
}
private String[] split(String exp) {
int pos = exp.indexOf('.');
if (pos == -1) {
return new String[] { exp, null };
}
String exp0 = exp.substring(0, pos);
String exp1 = exp.substring(pos + 1);
return new String[] { exp0, exp1 };
}
public Object eval(String exp) {
String[] e = split(exp);
return eval(e[0], e[1]);
}
public int evalInt(String exp) {
String[] e = split(exp);
return evalInt(e[0], e[1]);
}
public String evalString(String exp) {
String[] e = split(exp);
return evalString(e[0], e[1]);
}
public boolean evalBoolean(String exp) {
// TODO Auto-generated method stub
return false;
}
private Object eval(String exp0, String exp1) {
if ("size".equals(exp0)) {
return values.size();
}
if ("isEmpty".equals(exp0)) {
return values.isEmpty();
}
int idx = Integer.parseInt(exp0);
JsonElement element = values.get(idx);
return element.eval(exp1);
}
private int evalInt(String exp0, String exp1) {
if ("size".equals(exp0)) {
return values.size();
}
if ("isEmpty".equals(exp0)) {
return values.isEmpty() ? 1 : 0;
}
int idx = Integer.parseInt(exp0);
JsonElement element = values.get(idx);
return element.evalInt(exp1);
}
private String evalString(String exp0, String exp1) {
if ("size".equals(exp0)) {
return String.valueOf(values.size());
}
if ("isEmpty".equals(exp0)) {
return String.valueOf(values.isEmpty());
}
int idx = Integer.parseInt(exp0);
JsonElement element = values.get(idx);
return element.evalString(exp1);
}
public String getString() {
return toString();
}
}
@@ -1,63 +0,0 @@
package com.avaje.ebean.text.json;
/**
* JSON boolean element.
* <p>
* You will only use the JsonElements when you register a JsonReadBeanVisitor.
* The JSON elements that are not mapped to a bean property are made available
* to the JsonReadBeanVisitor.
* </p>
*
* @see JsonReadBeanVisitor
*
* @author rbygrave
*/
public class JsonElementBoolean implements JsonElement {
public static final JsonElementBoolean TRUE = new JsonElementBoolean(true);
public static final JsonElementBoolean FALSE = new JsonElementBoolean(false);
private final Boolean value;
private JsonElementBoolean(Boolean value) {
this.value = value;
}
public Boolean getValue() {
return value;
}
public String toString() {
return Boolean.toString(value);
}
public boolean isPrimitive() {
return true;
}
public String toPrimitiveString() {
return value.toString();
}
public Object eval(String exp) {
if (exp != null) {
throw new IllegalArgumentException("expression [" + exp + "] not allowed on boolean");
}
return value;
}
public int evalInt(String exp) {
return value ? 1 : 0;
}
public String evalString(String exp) {
return toString();
}
public boolean evalBoolean(String exp) {
return value;
}
}
@@ -1,57 +0,0 @@
package com.avaje.ebean.text.json;
/**
* JSON null element.
* <p>
* You will only use the JsonElements when you register a JsonReadBeanVisitor.
* The JSON elements that are not mapped to a bean property are made available
* to the JsonReadBeanVisitor.
* </p>
*
* @see JsonReadBeanVisitor
*
* @author rbygrave
*/
public class JsonElementNull implements JsonElement {
public static final JsonElementNull NULL = new JsonElementNull();
private JsonElementNull() {
}
public String getValue() {
return "null";
}
public String toString() {
return "json null";
}
public boolean isPrimitive() {
return true;
}
public String toPrimitiveString() {
return null;
}
public Object eval(String exp) {
if (exp != null) {
throw new IllegalArgumentException("expression [" + exp + "] not allowed on null");
}
return null;
}
public int evalInt(String exp) {
return 0;
}
public String evalString(String exp) {
return null;
}
public boolean evalBoolean(String exp) {
return false;
}
}
@@ -1,67 +0,0 @@
package com.avaje.ebean.text.json;
/**
* JSON number element.
* <p>
* You will only use the JsonElements when you register a JsonReadBeanVisitor.
* The JSON elements that are not mapped to a bean property are made available
* to the JsonReadBeanVisitor.
* </p>
*
* @see JsonReadBeanVisitor
*
* @author rbygrave
*/
public class JsonElementNumber implements JsonElement {
private final String value;
public JsonElementNumber(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public String toString() {
return value;
}
public boolean isPrimitive() {
return true;
}
public String toPrimitiveString() {
return value;
}
public Object eval(String exp) {
if (exp != null) {
throw new IllegalArgumentException("expression [" + exp + "] not allowed on number");
}
return Double.parseDouble(value);
}
public int evalInt(String exp) {
if (exp != null) {
throw new IllegalArgumentException("expression [" + exp + "] not allowed on number");
}
return Integer.parseInt(value);
}
public String evalString(String exp) {
if (exp != null) {
throw new IllegalArgumentException("expression [" + exp + "] not allowed on number");
}
return value;
}
public boolean evalBoolean(String exp) {
if (exp != null) {
throw new IllegalArgumentException("expression [" + exp + "] not allowed on number");
}
return Boolean.parseBoolean(value);
}
}
@@ -1,108 +0,0 @@
package com.avaje.ebean.text.json;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
/**
* JSON Object element.
* <p>
* You will only use the JsonElements when you register a JsonReadBeanVisitor.
* The JSON elements that are not mapped to a bean property are made available
* to the JsonReadBeanVisitor.
* </p>
*
* @see JsonReadBeanVisitor
*
* @author rbygrave
*/
public class JsonElementObject implements JsonElement {
private final Map<String, JsonElement> map = new LinkedHashMap<String, JsonElement>();
public void put(String key, JsonElement value) {
map.put(key, value);
}
private String[] split(String exp) {
int pos = exp.indexOf('.');
if (pos == -1) {
return new String[] { exp, null };
}
String exp0 = exp.substring(0, pos);
String exp1 = exp.substring(pos + 1);
return new String[] { exp0, exp1 };
}
public Object eval(String exp) {
String[] e = split(exp);
return eval(e[0], e[1]);
}
public int evalInt(String exp) {
String[] e = split(exp);
return evalInt(e[0], e[1]);
}
public String evalString(String exp) {
if (exp == null) {
return map.toString();
}
String[] e = split(exp);
return evalString(e[0], e[1]);
}
public boolean evalBoolean(String exp) {
String[] e = split(exp);
return evalBoolean(e[0], e[1]);
}
private Object eval(String exp0, String exp1) {
JsonElement e = map.get(exp0);
return e == null ? null : e.eval(exp1);
}
private int evalInt(String exp0, String exp1) {
JsonElement e = map.get(exp0);
return e == null ? 0 : e.evalInt(exp1);
}
private String evalString(String exp0, String exp1) {
JsonElement e = map.get(exp0);
return e == null ? "" : e.evalString(exp1);
}
private boolean evalBoolean(String exp0, String exp1) {
JsonElement e = map.get(exp0);
return e == null ? false : e.evalBoolean(exp1);
}
public JsonElement get(String key) {
return map.get(key);
}
public JsonElement getValue(String key) {
return map.get(key);
}
public Set<String> keySet() {
return map.keySet();
}
public Set<Map.Entry<String, JsonElement>> entrySet() {
return map.entrySet();
}
public String toString() {
return map.toString();
}
public boolean isPrimitive() {
return false;
}
public String toPrimitiveString() {
return null;
}
}
@@ -1,71 +0,0 @@
package com.avaje.ebean.text.json;
/**
* JSON string element.
* <p>
* You will only use the JsonElements when you register a JsonReadBeanVisitor.
* The JSON elements that are not mapped to a bean property are made available
* to the JsonReadBeanVisitor.
* </p>
*
* @see JsonReadBeanVisitor
*
* @author rbygrave
*/
public class JsonElementString implements JsonElement {
private final String value;
public JsonElementString(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public String toString() {
return value;
}
public boolean isPrimitive() {
return true;
}
public String toPrimitiveString() {
return value;
}
public Object eval(String exp) {
if (exp != null) {
throw new IllegalArgumentException("expression [" + exp + "] not allowed on number");
}
return value;
}
public int evalInt(String exp) {
if (exp != null) {
throw new IllegalArgumentException("expression [" + exp + "] not allowed on number");
}
try {
return Integer.parseInt(value);
} catch (NumberFormatException e) {
return 0;
}
}
public String evalString(String exp) {
if (exp != null) {
throw new IllegalArgumentException("expression [" + exp + "] not allowed on number");
}
return value;
}
public boolean evalBoolean(String exp) {
if (exp != null) {
throw new IllegalArgumentException("expression [" + exp + "] not allowed on number");
}
return Boolean.parseBoolean(exp);
}
}
@@ -1,34 +0,0 @@
package com.avaje.ebean.text.json;
import java.util.Map;
/**
* Provides for some custom handling of json content as it is read.
* <p>
* This visit method is called after all the known properties of the bean have
* been processed. Any JSON elements that could not be mapped to known bean
* properties are available in the unmapped Map.
* </p>
*
* @author rbygrave
*
* @param <T>
* The type of entity bean
*/
public interface JsonReadBeanVisitor<T> {
/**
* Visit the bean that has just been processed.
* <p>
* This provides a method of customising the bean and processing any custom
* JSON content.
* </p>
*
* @param bean
* the bean being processed
* @param unmapped
* Map of any JSON elements that didn't map to known bean properties
*/
public void visit(T bean, Map<String, JsonElement> unmapped);
}
@@ -1,71 +0,0 @@
package com.avaje.ebean.text.json;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Provides the ability to customise the reading of JSON content.
* <p>
* You can optionally provide a custom JsonValueAdapter to handle specific
* formatting for Date and DateTime types.
* </p>
* <p>
* You can optionally register JsonReadBeanVisitors to customise the processing
* of the beans as they are processed and handle any custom JSON elements that
* could not be mapped to bean properties.
* </p>
*
* @author rbygrave
*
*/
public class JsonReadOptions {
protected JsonValueAdapter valueAdapter;
protected Map<String, JsonReadBeanVisitor<?>> visitorMap;
/**
* Default constructor.
*/
public JsonReadOptions() {
this.visitorMap = new LinkedHashMap<String, JsonReadBeanVisitor<?>>();
}
/**
* Return the JsonValueAdapter.
*/
public JsonValueAdapter getValueAdapter() {
return valueAdapter;
}
/**
* Return the map of JsonReadBeanVisitor's.
*/
public Map<String, JsonReadBeanVisitor<?>> getVisitorMap() {
return visitorMap;
}
/**
* Set a JsonValueAdapter for custom DateTime and Date formatting.
*/
public JsonReadOptions setValueAdapter(JsonValueAdapter valueAdapter) {
this.valueAdapter = valueAdapter;
return this;
}
/**
* Register a JsonReadBeanVisitor for the root level.
*/
public JsonReadOptions addRootVisitor(JsonReadBeanVisitor<?> visitor) {
return addVisitor(null, visitor);
}
/**
* Register a JsonReadBeanVisitor for a given path.
*/
public JsonReadOptions addVisitor(String path, JsonReadBeanVisitor<?> visitor) {
visitorMap.put(path, visitor);
return this;
}
}
@@ -1,61 +0,0 @@
/**
* Copyright (C) 2009 Authors
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebean.text.json;
import java.sql.Timestamp;
/**
* Allows you to customise the Date and Timestamp formats.
* <p>
* There is not a standard JSON format for Date or Timestamp types. By default
* Ebean uses ISO8601 "yyyy-MM-dd'T'HH:mm:ss.SSSZ" and "yyyy-MM-dd".
* </p>
* <p>
* Note that Ebean will convert Joda types to either of the Date or Timestamp
* types and back for you.
* </p>
*
* @see JsonReadOptions
*
* @author rbygrave
*/
public interface JsonValueAdapter {
/**
* Convert the Date to json string.
*/
public String jsonFromDate(java.sql.Date date);
/**
* Convert the DateTime to json string.
*/
public String jsonFromTimestamp(java.sql.Timestamp date);
/**
* Parse the JSON string into a Date.
*/
public java.sql.Date jsonToDate(String jsonDate);
/**
* Parse the JSON DateTime into a Timestamp.
*/
public Timestamp jsonToTimestamp(String jsonDateTime);
}
@@ -1,33 +0,0 @@
package com.avaje.ebean.text.json;
/**
* Allows for customising the JSON write processing.
* <p>
* You can use this to add raw JSON content via {@link JsonWriter}.
* </p>
* <p>
* You register a JsonWriteBeanVisitor with {@link JsonWriteOptions}.
* </p>
*
* @author rbygrave
*
* @param <T>
* the type of entity bean
*
* @see JsonWriteOptions
*/
public interface JsonWriteBeanVisitor<T> {
/**
* Visit the bean that has just been writing it's content to JSON. You can
* write your own additional JSON content to the JsonWriter if you wish.
*
* @param bean
* the bean that has been writing it's content
* @param jsonWriter
* the JsonWriter which you can append custom json content to if you
* wish.
*/
public void visit(T bean, JsonWriter jsonWriter);
}
@@ -1,8 +1,6 @@
package com.avaje.ebean.text.json;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import com.avaje.ebean.text.PathProperties;
@@ -69,10 +67,6 @@ public class JsonWriteOptions {
protected String callback;
protected JsonValueAdapter valueAdapter;
protected Map<String, JsonWriteBeanVisitor<?>> visitorMap;
protected PathProperties pathProperties;
/**
@@ -99,11 +93,7 @@ public class JsonWriteOptions {
public JsonWriteOptions copy() {
JsonWriteOptions copy = new JsonWriteOptions();
copy.callback = callback;
copy.valueAdapter = valueAdapter;
copy.pathProperties = pathProperties;
if (visitorMap != null) {
copy.visitorMap = new HashMap<String, JsonWriteBeanVisitor<?>>(visitorMap);
}
return copy;
}
@@ -122,39 +112,6 @@ public class JsonWriteOptions {
return this;
}
/**
* Return the JsonValueAdapter.
*/
public JsonValueAdapter getValueAdapter() {
return valueAdapter;
}
/**
* Set a JsonValueAdapter for custom DateTime and Date formatting.
*/
public JsonWriteOptions setValueAdapter(JsonValueAdapter valueAdapter) {
this.valueAdapter = valueAdapter;
return this;
}
/**
* Register a JsonWriteBeanVisitor for the root level.
*/
public JsonWriteOptions setRootPathVisitor(JsonWriteBeanVisitor<?> visitor) {
return setPathVisitor(null, visitor);
}
/**
* Register a JsonWriteBeanVisitor for the given path.
*/
public JsonWriteOptions setPathVisitor(String path, JsonWriteBeanVisitor<?> visitor) {
if (visitorMap == null) {
visitorMap = new HashMap<String, JsonWriteBeanVisitor<?>>();
}
visitorMap.put(path, visitor);
return this;
}
/**
* Set the properties to include in the JSON output for the given path.
*
@@ -213,13 +170,6 @@ public class JsonWriteOptions {
return props;
}
/**
* Return the Map of registered JsonWriteBeanVisitor's by path.
*/
public Map<String, JsonWriteBeanVisitor<?>> getVisitorMap() {
return visitorMap;
}
/**
* Set the Map of properties to include by path.
*/
@@ -1,28 +0,0 @@
package com.avaje.ebean.text.json;
/**
* The JSON Writer made available to JsonWriteBeanVisitor's so that you can
* append your own JSON content into the output.
*
* @see JsonWriteBeanVisitor
* @see JsonWriteOptions#setRootPathVisitor(JsonWriteBeanVisitor)
* @see JsonWriteOptions#setPathVisitor(String, JsonWriteBeanVisitor)
*
* @author rbygrave
*/
public interface JsonWriter {
/**
* Use this to append some custom content into the JSON output.
*
* @param key
* the json key
*
* @param rawJsonValue
* raw json value
*/
public void appendRawValue(String key, String rawJsonValue);
public void appendQuoteEscapeValue(String key, String rawJsonValue);
}
@@ -65,7 +65,6 @@ import com.avaje.ebean.meta.MetaBeanInfo;
import com.avaje.ebean.meta.MetaInfoManager;
import com.avaje.ebean.text.csv.CsvReader;
import com.avaje.ebean.text.json.JsonContext;
import com.avaje.ebean.text.json.JsonElement;
import com.avaje.ebeaninternal.api.LoadBeanRequest;
import com.avaje.ebeaninternal.api.LoadManyRequest;
import com.avaje.ebeaninternal.api.ScopeTrans;
@@ -1989,10 +1988,6 @@ public final class DefaultServer implements SpiEbeanServer {
if (typeInfo == null) {
return false;
}
Class<?> beanType = typeInfo.getBeanType();
if (JsonElement.class.isAssignableFrom(beanType)) {
return true;
}
return getBeanDescriptor(typeInfo.getBeanType()) != null;
}
@@ -9,8 +9,6 @@ import com.avaje.ebean.config.ExternalTransactionManager;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
import com.avaje.ebean.text.json.JsonContext;
import com.avaje.ebean.text.json.JsonValueAdapter;
import com.avaje.ebeaninternal.api.ClassUtil;
import com.avaje.ebeaninternal.api.SpiBackgroundExecutor;
import com.avaje.ebeaninternal.api.SpiEbeanServer;
import com.avaje.ebeaninternal.server.autofetch.AutoFetchManager;
@@ -30,7 +28,6 @@ import com.avaje.ebeaninternal.server.query.DefaultRelationalQueryEngine;
import com.avaje.ebeaninternal.server.resource.ResourceManager;
import com.avaje.ebeaninternal.server.resource.ResourceManagerFactory;
import com.avaje.ebeaninternal.server.text.json.DJsonContext;
import com.avaje.ebeaninternal.server.text.json.DefaultJsonValueAdapter;
import com.avaje.ebeaninternal.server.transaction.DefaultTransactionScopeManager;
import com.avaje.ebeaninternal.server.transaction.ExternalTransactionScopeManager;
import com.avaje.ebeaninternal.server.transaction.JtaTransactionManager;
@@ -133,17 +130,8 @@ public class InternalConfiguration {
}
public JsonContext createJsonContext(SpiEbeanServer server) {
String s = serverConfig.getProperty("json.pretty", "false");
boolean dfltPretty = "true".equalsIgnoreCase(s);
s = serverConfig.getProperty("json.jsonValueAdapter", null);
JsonValueAdapter va = new DefaultJsonValueAdapter();
if (s != null) {
va = (JsonValueAdapter) ClassUtil.newInstance(s, this.getClass());
}
return new DJsonContext(server, va, dfltPretty);
return new DJsonContext(server);
}
public XmlConfig getXmlConfig() {
@@ -3,14 +3,17 @@ package com.avaje.ebeaninternal.server.deploy;
import java.sql.SQLException;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.json.stream.JsonParser;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebean.config.ScalarTypeConverter;
import com.avaje.ebean.json.EJson;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyCompound;
import com.avaje.ebeaninternal.server.el.ElPropertyChainBuilder;
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
import com.avaje.ebeaninternal.server.query.SqlBeanLoad;
import com.avaje.ebeaninternal.server.text.json.ReadJsonContext;
import com.avaje.ebeaninternal.server.text.json.WriteJson;
import com.avaje.ebeaninternal.server.type.CtCompoundProperty;
import com.avaje.ebeaninternal.server.type.CtCompoundPropertyElAdapter;
@@ -178,14 +181,31 @@ public class BeanPropertyCompound extends BeanProperty {
}
public void jsonWrite(WriteJson ctx, EntityBean bean) {
Object valueObject = getValueIntercept(bean);
//FIXME: compoundType.jsonWrite(ctx, valueObject, name);
if (!jsonSerialize) {
return;
}
Object value = getValueIntercept(bean);
if (value == null) {
ctx.gen().writeNull(name);
} else {
compoundType.jsonWrite(ctx, value, name);
}
}
public void jsonRead(ReadJsonContext ctx, EntityBean bean){
Object objValue = compoundType.jsonRead(ctx);
public void jsonRead(JsonParser ctx, EntityBean bean) {
if (!jsonDeserialize) {
return;
}
Object value = EJson.parsePartial(ctx);
if (value == null) {
setValue(bean, null);
} else {
@SuppressWarnings("unchecked")
Map<String,Object> map = (Map<String,Object>)value;
Object objValue = compoundType.jsonConvert(map);
setValue(bean, objValue);
}
}
}
@@ -19,12 +19,10 @@ 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.PathProperties;
import com.avaje.ebean.text.TextException;
import com.avaje.ebean.text.json.JsonContext;
import com.avaje.ebean.text.json.JsonElement;
import com.avaje.ebean.text.json.JsonReadOptions;
import com.avaje.ebean.text.json.JsonValueAdapter;
import com.avaje.ebean.text.json.JsonWriteOptions;
import com.avaje.ebeaninternal.api.SpiEbeanServer;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
@@ -41,14 +39,8 @@ public class DJsonContext implements JsonContext {
private final SpiEbeanServer server;
//private final JsonValueAdapter dfltValueAdapter;
private final boolean dfltPretty;
public DJsonContext(SpiEbeanServer server, JsonValueAdapter dfltValueAdapter, boolean dfltPretty) {
public DJsonContext(SpiEbeanServer server) {
this.server = server;
//this.dfltValueAdapter = dfltValueAdapter;
this.dfltPretty = dfltPretty;
}
public boolean isSupportedType(Type genericType) {
@@ -60,44 +52,29 @@ public class DJsonContext implements JsonContext {
}
public <T> T toBean(Class<T> cls, String json) {
return toBean(cls, new StringReader(json), null);
return toBean(cls, new StringReader(json));
}
public <T> T toBean(Class<T> cls, Reader jsonReader) {
return toBean(cls, createReader(jsonReader), null);
return toBean(cls, createReader(jsonReader));
}
public <T> T toBean(Class<T> cls, String json, JsonReadOptions 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, JsonParser parser, JsonReadOptions options) {
private <T> T toBean(Class<T> cls, JsonParser parser) {
BeanDescriptor<T> d = getDecriptor(cls);
return d.jsonRead(parser, null);
}
public <T> List<T> toList(Class<T> cls, String json) {
return toList(cls, new StringReader(json), null);
return toList(cls, new StringReader(json));
}
public <T> List<T> toList(Class<T> cls, String json, JsonReadOptions options) {
return toList(cls, new StringReader(json), options);
}
public <T> List<T> toList(Class<T> cls, Reader jsonReader) {
return toList(cls, createReader(jsonReader), null);
return toList(cls, createReader(jsonReader));
}
public <T> List<T> toList(Class<T> cls, Reader jsonReader, JsonReadOptions options) {
return toList(cls, createReader(jsonReader), options);
}
private <T> List<T> toList(Class<T> cls, JsonParser src, JsonReadOptions options) {
private <T> List<T> toList(Class<T> cls, JsonParser src) {
try {
BeanDescriptor<T> d = getDecriptor(cls);
@@ -128,89 +105,63 @@ public class DJsonContext implements JsonContext {
}
}
public Object toObject(Type genericType, String json, JsonReadOptions options) {
public Object toObject(Type genericType, String json) {
TypeInfo info = ParamTypeHelper.getTypeInfo(genericType);
Class<?> beanType = info.getBeanType();
if (JsonElement.class.isAssignableFrom(beanType)) {
return InternalJsonParser.parse(json);
}
ManyType manyType = info.getManyType();
switch (manyType) {
case NONE:
return toBean(info.getBeanType(), json, options);
return toBean(info.getBeanType(), json);
case LIST:
return toList(info.getBeanType(), json, options);
return toList(info.getBeanType(), json);
default:
String msg = "ManyType " + manyType + " not supported yet";
throw new TextException(msg);
throw new TextException("Type " + manyType + " not supported");
}
}
public Object toObject(Type genericType, Reader json, JsonReadOptions options) {
public Object toObject(Type genericType, Reader json) {
TypeInfo info = ParamTypeHelper.getTypeInfo(genericType);
Class<?> beanType = info.getBeanType();
if (JsonElement.class.isAssignableFrom(beanType)) {
return InternalJsonParser.parse(json);
}
ManyType manyType = info.getManyType();
switch (manyType) {
case NONE:
return toBean(info.getBeanType(), json, options);
return toBean(info.getBeanType(), json);
case LIST:
return toList(info.getBeanType(), json, options);
return toList(info.getBeanType(), json);
default:
throw new TextException("ManyType " + manyType + " not supported");
throw new TextException("Type " + manyType + " not supported");
}
}
public void toJsonWriter(Object o, Writer writer) {
toJsonWriter(o, writer, dfltPretty, null, null);
toJsonWriter(o, writer, null);
}
public void toJsonWriter(Object o, Writer writer, boolean pretty) {
toJsonWriter(o, writer, pretty, null, null);
}
public void toJsonWriter(Object o, Writer writer, boolean pretty, JsonWriteOptions options) {
toJsonWriter(o, writer, pretty, null, null);
}
public void toJsonWriter(Object o, Writer writer, boolean pretty, JsonWriteOptions options, String callback) {
public void toJsonWriter(Object o, Writer writer, JsonWriteOptions options) {
JsonGenerator generator = Json.createGenerator(writer);
toJsonInternal(o, generator, pretty, options, callback);
toJsonInternal(o, generator, options);
generator.close();
}
public String toJsonString(Object o) {
return toJsonString(o, dfltPretty, null);
return toJsonString(o, null);
}
public String toJsonString(Object o, boolean pretty) {
return toJsonString(o, pretty, null);
}
public String toJsonString(Object o, boolean pretty, JsonWriteOptions options) {
return toJsonString(o, pretty, options, null);
}
public String toJsonString(Object o, boolean pretty, JsonWriteOptions options, String callback) {
public String toJsonString(Object o, JsonWriteOptions options) {
StringWriter writer = new StringWriter(500);
JsonGenerator gen = Json.createGenerator(writer);
toJsonInternal(o, gen, pretty, options, callback);
toJsonInternal(o, gen, options);
gen.close();
return writer.toString();
}
@SuppressWarnings("unchecked")
private void toJsonInternal(Object o, JsonGenerator gen, boolean pretty, JsonWriteOptions options, String requestCallback) {
private void toJsonInternal(Object o, JsonGenerator gen, JsonWriteOptions options) {
if (o == null) {
gen.writeNull();
@@ -224,10 +175,10 @@ public class DJsonContext implements JsonContext {
// } else if (o instanceof JsonElement) {
} else if (o instanceof Map<?, ?>) {
toJsonFromMap((Map<Object, Object>) o, gen, pretty, options, requestCallback);
toJsonFromMap((Map<Object, Object>) o, gen, options);
} else if (o instanceof Collection<?>) {
toJsonFromCollection((Collection<?>) o, null, gen, pretty, options, requestCallback);
toJsonFromCollection((Collection<?>) o, null, gen, options);
} else if (o instanceof EntityBean) {
BeanDescriptor<?> d = getDecriptor(o.getClass());
@@ -241,7 +192,7 @@ public class DJsonContext implements JsonContext {
return new WriteJson(server, gen, pathProps);
}
private <T> void toJsonFromCollection(Collection<T> c, String key, JsonGenerator gen, boolean pretty, JsonWriteOptions options, String requestCallback) {
private <T> void toJsonFromCollection(Collection<T> c, String key, JsonGenerator gen, JsonWriteOptions options) {
if (key == null) {
gen.writeStartArray();
@@ -255,13 +206,12 @@ public class DJsonContext implements JsonContext {
while (it.hasNext()) {
T t = it.next();
BeanDescriptor<?> d = getDecriptor(t.getClass());
//writeJson.setBean();
d.jsonWrite(writeJson, (EntityBean)t, null);
}
gen.writeEnd();
}
private void toJsonFromMap(Map<Object, Object> map, JsonGenerator gen, boolean pretty, JsonWriteOptions options, String requestCallback) {
private void toJsonFromMap(Map<Object, Object> map, JsonGenerator gen, JsonWriteOptions options) {
Set<Entry<Object, Object>> entrySet = map.entrySet();
Iterator<Entry<Object, Object>> it = entrySet.iterator();
@@ -277,14 +227,14 @@ public class DJsonContext implements JsonContext {
gen.writeNull(key);
} else {
if (value instanceof Collection<?>) {
toJsonFromCollection((Collection<?>) value, key, gen, pretty, options, requestCallback);
toJsonFromCollection((Collection<?>) value, key, gen, options);
} else if (value instanceof EntityBean) {
BeanDescriptor<?> d = getDecriptor(value.getClass());
d.jsonWrite(writeJson,(EntityBean) value, key);
} else {
throw new RuntimeException("TODO process primitive");
EJson.write(entry, gen);
}
}
}
@@ -5,9 +5,7 @@ import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
import com.avaje.ebean.text.json.JsonValueAdapter;
public class DefaultJsonValueAdapter implements JsonValueAdapter {
public class DefaultJsonValueAdapter {//implements JsonValueAdapter {
private final SimpleDateFormat dateTimeProto;
@@ -1,23 +0,0 @@
package com.avaje.ebeaninternal.server.text.json;
import java.io.Reader;
import com.avaje.ebean.text.json.JsonElement;
public class InternalJsonParser {
public static JsonElement parse(String s) {
ReadJsonSourceString src = new ReadJsonSourceString(s);
ReadBasicJsonContext b = new ReadBasicJsonContext(src);
return ReadJsonRawReader.readJsonElement(b);
}
public static JsonElement parse(Reader s) {
ReadJsonSourceReader src = new ReadJsonSourceReader(s, 512, 256);
ReadBasicJsonContext b = new ReadBasicJsonContext(src);
return ReadJsonRawReader.readJsonElement(b);
}
}
@@ -1,273 +0,0 @@
package com.avaje.ebeaninternal.server.text.json;
import com.avaje.ebean.text.TextException;
public class ReadBasicJsonContext implements ReadJsonInterface {
private final ReadJsonSource src;
private char tokenStart;
private String tokenKey;
private boolean pushedTokenKey;
public ReadBasicJsonContext(ReadJsonSource src) {
this.src = src;
}
/**
* Push the current token key back onto the 'stack'.
*/
public void pushTokenKey() {
pushedTokenKey = true;
}
public char getToken() {
return tokenStart;
}
public String getTokenKey() {
return tokenKey;
}
public boolean isTokenKey() {
return '\"' == tokenStart;
}
public boolean isTokenObjectEnd() {
return '}' == tokenStart;
}
public boolean readObjectBegin() {
readNextToken();
if ('{' == tokenStart){
return true;
} else if ('n' == tokenStart) {
return false;
} else if (']' == tokenStart) {
// an empty array
return false;
}
throw new RuntimeException("Expected object begin at "+src.getErrorHelp());
}
public boolean readKeyNext() {
readNextToken();
if ('\"' == tokenStart){
return true;
} else if ('}' == tokenStart) {
return false;
}
throw new RuntimeException("Expected '\"' or '}' at "+src.getErrorHelp());
}
public boolean readValueNext() {
readNextToken();
if (',' == tokenStart){
return true;
} else if ('}' == tokenStart) {
return false;
}
throw new RuntimeException("Expected ',' or '}' at "+src.getErrorHelp()+" but got "+tokenStart);
}
public boolean readArrayBegin() {
readNextToken();
if ('[' == tokenStart){
return true;
} else if ('n' == tokenStart) {
return false;
}
throw new RuntimeException("Expected array begin at "+src.getErrorHelp());
}
public boolean readArrayNext() {
readNextToken();
if (',' == tokenStart){
return true;
}
if (']' == tokenStart){
return false;
}
throw new RuntimeException("Expected ',' or ']' at "+src.getErrorHelp());
}
public void readNextToken() {
if (pushedTokenKey) {
// Do nothing
pushedTokenKey = false;
return;
}
ignoreWhiteSpace();
tokenStart = src.nextChar("EOF finding next token");
switch (tokenStart) {
case '"':
internalReadKey();
break;
case '{': break;
case '}': break;
case '[': break; // not expected
case ']': break; // not expected
case ',': break; // not expected
case ':': break; // not expected
case 'n':
internalReadNull();
break; // not expected
default:
throw new RuntimeException("Unexpected tokenStart["+tokenStart+"] "+src.getErrorHelp());
}
}
public String readQuotedValue() {
boolean escape = false;
StringBuilder sb = new StringBuilder();
do {
char ch = src.nextChar("EOF reading quoted value");
if (escape) {
// in escape mode so just append the character
escape = false;
switch (ch) {
case 'n':
sb.append('\n');
break;
case 'r':
sb.append('\r');
break;
case 't':
sb.append('\t');
break;
case 'f':
sb.append('\f');
break;
case 'b':
sb.append('\b');
break;
case '"':
sb.append('"');
break;
case 'u':
String msg = "EOF reading unicode value";
char c1 = src.nextChar(msg);
char c2 = src.nextChar(msg);
char c3 = src.nextChar(msg);
char c4 = src.nextChar(msg);
char u = (char) Integer.parseInt(""+c1+c2+c3+c4, 16);
sb.append(u);
break;
default:
sb.append('\\');
sb.append(ch);
break;
}
} else {
switch (ch) {
case '\\':
// put into 'escape' mode for next character
escape = true;
break;
case '"':
return sb.toString();
default:
sb.append(ch);
}
}
} while (true);
}
public String readUnquotedValue(char c) {
String v = readUnquotedValueRaw(c);
if ("null".equals(v)){
return null;
} else {
return v;
}
}
private String readUnquotedValueRaw(char c) {
StringBuilder sb = new StringBuilder();
sb.append(c);
do {
tokenStart = src.nextChar("EOF reading unquoted value");
switch (tokenStart) {
case ',':
src.back();
return sb.toString();
case '}':
src.back();
return sb.toString();
case ' ':
return sb.toString();
case '\t':
return sb.toString();
case '\r':
return sb.toString();
case '\n':
return sb.toString();
default:
sb.append(tokenStart);
}
} while (true);
}
private void internalReadNull() {
StringBuilder sb = new StringBuilder(4);
sb.append(tokenStart);
for (int i = 0; i < 3; i++) {
char c = src.nextChar("EOF reading null ");
sb.append(c);
}
if (!"null".equals(sb.toString())){
throw new TextException("Expected 'null' but got "+sb.toString()+" "+src.getErrorHelp());
}
}
private void internalReadKey() {
StringBuilder sb = new StringBuilder();
do {
char c = src.nextChar("EOF reading key");
if ('\"' == c){
tokenKey = sb.toString();
break;
} else {
sb.append(c);
}
} while (true);
ignoreWhiteSpace();
char c = src.nextChar("EOF reading ':'");
if (':' != c){
throw new TextException("Expected to find colon after key at "+(src.pos()-1)+" but found ["+c+"]"+src.getErrorHelp());
}
}
public void ignoreWhiteSpace() {
src.ignoreWhiteSpace();
}
public char nextChar() {
tokenStart = src.nextChar("EOF getting nextChar for raw json");
return tokenStart;
}
}
@@ -1,177 +0,0 @@
package com.avaje.ebeaninternal.server.text.json;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebean.bean.EntityBeanIntercept;
import com.avaje.ebean.text.json.JsonElement;
import com.avaje.ebean.text.json.JsonReadBeanVisitor;
import com.avaje.ebean.text.json.JsonReadOptions;
import com.avaje.ebean.text.json.JsonValueAdapter;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import com.avaje.ebeaninternal.server.util.ArrayStack;
public class ReadJsonContext extends ReadBasicJsonContext {
private final Map<String, JsonReadBeanVisitor<?>> visitorMap;
private final JsonValueAdapter valueAdapter;
private final PathStack pathStack;
private final ArrayStack<ReadBeanState> beanState;
private ReadBeanState currentState;
public ReadJsonContext(ReadJsonSource src, JsonValueAdapter dfltValueAdapter, JsonReadOptions options) {
super(src);
this.beanState = new ArrayStack<ReadBeanState>();
if (options == null){
this.valueAdapter = dfltValueAdapter;
this.visitorMap = null;
this.pathStack = null;
} else {
this.valueAdapter = getValueAdapter(dfltValueAdapter, options.getValueAdapter());
this.visitorMap = options.getVisitorMap();
this.pathStack = (visitorMap == null || visitorMap.isEmpty()) ? null : new PathStack();
}
}
private JsonValueAdapter getValueAdapter(JsonValueAdapter dfltValueAdapter, JsonValueAdapter valueAdapter) {
return valueAdapter == null ? dfltValueAdapter : valueAdapter;
}
public JsonValueAdapter getValueAdapter() {
return valueAdapter;
}
public String readScalarValue() {
ignoreWhiteSpace();
char prevChar = nextChar();//"EOF reading scalarValue?");
if ('"' == prevChar){
return readQuotedValue();
} else {
return readUnquotedValue(prevChar);
}
}
public void pushBean(Object bean, String path, BeanDescriptor<?> beanDescriptor){
currentState = new ReadBeanState(bean, beanDescriptor);
beanState.push(currentState);
if (pathStack != null){
pathStack.pushPathKey(path);
}
}
public ReadBeanState popBeanState() {
if (pathStack != null){
String path = pathStack.peekWithNull();
JsonReadBeanVisitor<?> beanVisitor = visitorMap.get(path);
if (beanVisitor != null){
currentState.visit(beanVisitor);
}
pathStack.pop();
}
// return the current ReadBeanState as we can't call setLoadedState()
// yet. We might bind master/detail beans together via mappedBy property
// so wait until after that before calling ReadBeanStatesetLoadedState();
ReadBeanState s = currentState;
beanState.pop();
currentState = beanState.peekWithNull();
return s;
}
public void setProperty(String propertyName){
currentState.setLoaded(propertyName);
}
/**
* Got a key that doesn't map to a known property so read the json value
* which could be json primitive, object or array.
* <p>
* Provide these values to a JsonReadBeanVisitor if registered.
* </p>
*/
public JsonElement readUnmappedJson(String key) {
JsonElement rawJsonValue = ReadJsonRawReader.readJsonElement(this);
if (visitorMap != null){
currentState.addUnmappedJson(key, rawJsonValue);
}
return rawJsonValue;
}
public static class ReadBeanState implements PropertyChangeListener {
private final Object bean;
private final BeanDescriptor<?> beanDescriptor;
private final EntityBeanIntercept ebi;
private final Set<String> loadedProps;
private Map<String,JsonElement> unmapped;
private ReadBeanState(Object bean, BeanDescriptor<?> beanDescriptor) {
this.bean = bean;
this.beanDescriptor = beanDescriptor;
if (bean instanceof EntityBean){
this.ebi = ((EntityBean)bean)._ebean_getIntercept();
this.loadedProps = new HashSet<String>();
} else {
this.ebi = null;
this.loadedProps = null;
}
}
public String toString(){
return bean.getClass().getSimpleName()+" loaded:"+loadedProps;
}
/**
* Add a loaded/set property to the set of loadedProps.
*/
public void setLoaded(String propertyName){
if (ebi != null){
loadedProps.add(propertyName);
}
}
private void addUnmappedJson(String key, JsonElement value){
if (unmapped == null){
unmapped = new LinkedHashMap<String, JsonElement>();
}
unmapped.put(key, value);
}
@SuppressWarnings("unchecked")
private <T> void visit(JsonReadBeanVisitor<T> beanVisitor) {
// listen for property change events so that
// we can update the loadedProps if necessary
if (ebi != null){
ebi.addPropertyChangeListener(this);
}
beanVisitor.visit((T)bean, unmapped);
if (ebi != null){
ebi.removePropertyChangeListener(this);
}
}
public void propertyChange(PropertyChangeEvent evt) {
String propName = evt.getPropertyName();
loadedProps.add(propName);
}
public Object getBean() {
return bean;
}
}
}
@@ -1,22 +0,0 @@
package com.avaje.ebeaninternal.server.text.json;
public interface ReadJsonInterface {
public void ignoreWhiteSpace();
public char nextChar();
public String getTokenKey();
public boolean readKeyNext();
public boolean readValueNext();
public boolean readArrayNext();
public String readQuotedValue();
public String readUnquotedValue(char c);
}
@@ -1,107 +0,0 @@
package com.avaje.ebeaninternal.server.text.json;
import com.avaje.ebean.text.json.JsonElement;
import com.avaje.ebean.text.json.JsonElementArray;
import com.avaje.ebean.text.json.JsonElementBoolean;
import com.avaje.ebean.text.json.JsonElementNull;
import com.avaje.ebean.text.json.JsonElementNumber;
import com.avaje.ebean.text.json.JsonElementObject;
import com.avaje.ebean.text.json.JsonElementString;
public class ReadJsonRawReader {
public static JsonElement readJsonElement(ReadJsonInterface ctx) {
return new ReadJsonRawReader(ctx).readJsonElement();
}
private final ReadJsonInterface ctx;
private ReadJsonRawReader(ReadJsonInterface ctx){
this.ctx = ctx;
}
private JsonElement readJsonElement() {
return readValue();
}
private JsonElement readValue() {
ctx.ignoreWhiteSpace();
char c = ctx.nextChar();
switch (c) {
case '{':
return readObject();
case '[':
return readArray();
case '"':
return readString();
default:
return readUnquoted(c);
}
}
private JsonElement readArray() {
JsonElementArray a = new JsonElementArray();
do {
JsonElement value = readValue();
a.add(value);
if (!ctx.readArrayNext()){
break;
}
} while(true);
return a;
}
private JsonElement readObject() {
JsonElementObject o = new JsonElementObject();
do {
if (!ctx.readKeyNext()){
break;
} else {
// we read a property key ...
String key = ctx.getTokenKey();
JsonElement value = readValue();
o.put(key, value);
if (!ctx.readValueNext()){
break;
}
}
} while(true);
return o;
}
private JsonElement readString() {
String s = ctx.readQuotedValue();
return new JsonElementString(s);
}
private JsonElement readUnquoted(char c) {
String s = ctx.readUnquotedValue(c);
if ("null".equals(s)){
return JsonElementNull.NULL;
} else if ("true".equals(s)){
return JsonElementBoolean.TRUE;
} else if ("false".equals(s)) {
return JsonElementBoolean.FALSE;
}
return new JsonElementNumber(s);
}
}
@@ -1,15 +0,0 @@
package com.avaje.ebeaninternal.server.text.json;
public interface ReadJsonSource {
public char nextChar(String eofMsg);
public void ignoreWhiteSpace();
public void back();
public int pos();
public String getErrorHelp();
}
@@ -1,83 +0,0 @@
package com.avaje.ebeaninternal.server.text.json;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import com.avaje.ebean.text.TextException;
public class ReadJsonSourceReader implements ReadJsonSource {
private final Reader reader;
private char[] localBuffer;
private int totalPos;
private int localPos;
private int localPosEnd;
public ReadJsonSourceReader(Reader reader, int localBufferSize, int bufferSize) {
this.reader = new BufferedReader(reader,bufferSize);
this.localBuffer = new char[localBufferSize];
}
public String toString() {
return String.valueOf(localBuffer);
}
public String getErrorHelp() {
int prev = localPos - 30;
if (prev < 0){
prev = 0;
}
String c = new String(localBuffer, prev, (localPos-prev));
return "pos:"+pos()+" preceding:"+c;
}
public int pos() {
return totalPos+localPos;
}
public void ignoreWhiteSpace() {
do {
char c = nextChar("EOF ignoring whitespace");
if (!Character.isWhitespace(c)){
--localPos;
break;
}
} while(true);
}
public void back() {
localPos--;
}
public char nextChar(String eofMsg) {
if (localPos >= localPosEnd){
if (!loadLocalBuffer()) {
throw new TextException(eofMsg+" at pos:"+(totalPos+localPos));
}
}
return localBuffer[localPos++];
}
private boolean loadLocalBuffer() {
try {
localPosEnd = reader.read(localBuffer);
if (localPosEnd > 0){
totalPos += localPos;
localPos = 0;
return true;
} else {
this.localBuffer = null;
return false;
}
} catch (IOException e){
throw new TextException(e);
}
}
}
@@ -1,54 +0,0 @@
package com.avaje.ebeaninternal.server.text.json;
import com.avaje.ebean.text.TextException;
public class ReadJsonSourceString implements ReadJsonSource {
private final String source;
private final int sourceLength;
private int pos;
public ReadJsonSourceString(String source){
this.source = source;
this.sourceLength = source.length();
}
public String getErrorHelp() {
int prev = pos - 50;
if (prev < 0){
prev = 0;
}
String c = source.substring(prev, pos);
return "pos:"+pos+" precedingcontent:"+c;
}
public String toString() {
return source;
}
public int pos() {
return pos;
}
public void back() {
pos--;
}
public char nextChar(String eofMsg) {
if (pos >= sourceLength){
throw new TextException(eofMsg+" at pos:"+pos);
}
return source.charAt(pos++);
}
public void ignoreWhiteSpace() {
do {
char c = source.charAt(pos);
if (Character.isWhitespace(c)){
++pos;
} else {
break;
}
} while(true);
}
}
@@ -16,7 +16,9 @@ import com.avaje.ebeaninternal.server.util.ArrayStack;
public class WriteJson {
private final SpiEbeanServer server;
private final JsonGenerator generator;
private final PathProperties pathProperties;
private final PathStack pathStack = new PathStack();
@@ -49,7 +51,7 @@ public class WriteJson {
parentBeans.pop();
}
public void beginAssocOne(String key, EntityBean bean) {
public void beginAssocOne(String key, Object bean) {
parentBeans.push(bean);
pathStack.pushPathKey(key);
}
@@ -1,8 +0,0 @@
package com.avaje.ebeaninternal.server.text.json;
public interface WriteJsonBuffer extends Appendable {
public WriteJsonBuffer append(String content);
}
@@ -1,40 +0,0 @@
package com.avaje.ebeaninternal.server.text.json;
import java.io.IOException;
public class WriteJsonBufferString implements WriteJsonBuffer {
private final StringBuilder buffer;
public WriteJsonBufferString(){
this.buffer = new StringBuilder(256);
}
public WriteJsonBufferString append(CharSequence csq) throws IOException {
buffer.append(csq);
return this;
}
public WriteJsonBufferString append(CharSequence csq, int start, int end) throws IOException {
buffer.append(csq, start, end);
return this;
}
public WriteJsonBufferString append(char c) throws IOException {
buffer.append(c);
return this;
}
public WriteJsonBufferString append(String content){
buffer.append(content);
return this;
}
public String getBufferOutput() {
return buffer.toString();
}
public String toString() {
return buffer.toString();
}
}
@@ -1,45 +0,0 @@
package com.avaje.ebeaninternal.server.text.json;
import java.io.IOException;
import java.io.Writer;
import com.avaje.ebean.text.TextException;
public class WriteJsonBufferWriter implements WriteJsonBuffer {
private final Writer buffer;
public WriteJsonBufferWriter(Writer buffer){
this.buffer = buffer;
}
public WriteJsonBufferWriter append(String content){
try {
buffer.write(content);
return this;
} catch (IOException e) {
throw new TextException(e);
}
}
public WriteJsonBufferWriter append(CharSequence csq) throws IOException {
return append(csq, 0, csq.length());
}
public WriteJsonBufferWriter append(CharSequence csq, int start, int end) throws IOException {
for (int i = start; i < end; i++) {
buffer.append(csq.charAt(i));
}
return this;
}
public WriteJsonBufferWriter append(char c) throws IOException {
try {
buffer.write(c);
return this;
} catch (IOException e) {
throw new TextException(e);
}
}
}
@@ -1,376 +0,0 @@
package com.avaje.ebeaninternal.server.text.json;
//import java.util.Collection;
//import java.util.Iterator;
//import java.util.Map;
//import java.util.Set;
//
//import com.avaje.ebean.bean.EntityBean;
//import com.avaje.ebean.bean.EntityBeanIntercept;
//import com.avaje.ebean.text.PathProperties;
//import com.avaje.ebean.text.json.JsonValueAdapter;
//import com.avaje.ebean.text.json.JsonWriteBeanVisitor;
//import com.avaje.ebean.text.json.JsonWriteOptions;
//import com.avaje.ebean.text.json.JsonWriter;
//import com.avaje.ebeaninternal.api.SpiEbeanServer;
//import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
//import com.avaje.ebeaninternal.server.type.EscapeJson;
//import com.avaje.ebeaninternal.server.type.ScalarType;
//import com.avaje.ebeaninternal.server.util.ArrayStack;
public class WriteJsonContext {//implements JsonWriter {
// private final SpiEbeanServer server;
//
// private final WriteJsonBuffer buffer;
//
// private final boolean pretty;
//
// private final JsonValueAdapter valueAdapter;
//
// private final ArrayStack<Object> parentBeans = new ArrayStack<Object>();
//
// private final PathProperties pathProperties;
//
// private final Map<String, JsonWriteBeanVisitor<?>> visitorMap;
//
// private final String callback;
//
// private final PathStack pathStack;
//
// private WriteBeanState beanState;
//
// private int depthOffset;
//
// boolean assocOne;
//
// public WriteJsonContext(WriteJsonBuffer buffer, boolean pretty, JsonValueAdapter dfltValueAdapter,
// JsonWriteOptions options, String requestCallback, SpiEbeanServer server){
//
// this.server = server;
// this.buffer = buffer;
// this.pretty = pretty;
// this.pathStack = new PathStack();
// this.callback = getCallback(requestCallback, options);
// if (options == null){
// this.valueAdapter = dfltValueAdapter;
// this.visitorMap = null;
// this.pathProperties = null;
//
// } else {
// this.valueAdapter = getValueAdapter(dfltValueAdapter, options.getValueAdapter());
// this.visitorMap = emptyToNull(options.getVisitorMap());
// this.pathProperties = emptyToNull(options.getPathProperties());
// }
//
// if (callback != null){
// buffer.append(requestCallback).append("(");
// }
// }
//
// public void toJson(String name, Collection<?> c) {
//
// beginAssocMany(name);
//
// Iterator<?> it = c.iterator();
// if (!it.hasNext()){
// endAssocMany();
// return;
// }
//
// EntityBean o = (EntityBean)it.next();
// BeanDescriptor<?> d = getDecriptor(o.getClass());
//
// d.jsonWrite(this, o);
// while (it.hasNext()) {
// appendComma();
// EntityBean t = (EntityBean)it.next();
// d.jsonWrite(this, t);
// }
// endAssocMany();
// }
//
// private <T> BeanDescriptor<T> getDecriptor(Class<T> cls) {
// BeanDescriptor<T> d = server.getBeanDescriptor(cls);
// if (d == null){
// String msg = "No BeanDescriptor found for "+cls;
// throw new RuntimeException(msg);
// }
// return d;
// }
//
// public void appendRawValue(String key, String rawJsonValue) {
// appendKeyWithComma(key, true);
// buffer.append(rawJsonValue);
// }
//
// public void appendQuoteEscapeValue(String key, String valueToEscape) {
// appendKeyWithComma(key, true);
// EscapeJson.escapeQuote(valueToEscape, buffer);
// }
//
// public void end() {
// if (callback != null){
// buffer.append(")");
// }
// }
//
// private <MK,MV> Map<MK,MV> emptyToNull(Map<MK,MV> m){
// if ( m == null || m.isEmpty()) {
// return null;
// } else {
// return m;
// }
// }
//
// private PathProperties emptyToNull(PathProperties m){
// if ( m == null || m.isEmpty()) {
// return null;
// } else {
// return m;
// }
// }
//
// private String getCallback(String requestCallback, JsonWriteOptions options) {
// if (requestCallback != null){
// return requestCallback;
// }
// if (options != null){
// return options.getCallback();
// }
// return null;
// }
//
// private JsonValueAdapter getValueAdapter(JsonValueAdapter dfltValueAdapter, JsonValueAdapter valueAdapter) {
// return valueAdapter == null ? dfltValueAdapter : valueAdapter;
// }
//
// /**
// * Return the set of properties to write to JSON. If null is returned then
// * the default will output the properties loaded for this bean.
// */
// public Set<String> getIncludeProperties() {
// if (pathProperties != null){
// String path = pathStack.peekWithNull();
// return pathProperties.get(path);
// }
// return null;
// }
//
// public JsonWriteBeanVisitor<?> getBeanVisitor() {
// if (visitorMap != null){
// String path = pathStack.peekWithNull();
// return visitorMap.get(path);
// }
// return null;
// }
//
// public String getJson() {
// return buffer.toString();
// }
//
// private void appendIndent(){
//
// buffer.append("\n");
// int depth = depthOffset + parentBeans.size();
// for (int i = 0; i < depth; i++) {
// buffer.append(" ");
// }
// }
//
// public void appendObjectBegin(){
// if (pretty && !assocOne){
// appendIndent();
// }
// buffer.append("{");
// }
// public void appendObjectEnd(){
// buffer.append("}");
// }
//
// public void appendArrayBegin(){
// if (pretty){
// appendIndent();
// }
// buffer.append("[");
// depthOffset++;
// }
//
// public void appendArrayEnd(){
// depthOffset--;
// if (pretty){
// appendIndent();
// }
// buffer.append("]");
// }
//
// public void appendComma(){
// buffer.append(",");
// }
//
// public void addDepthOffset(int offset){
// depthOffset += offset;
// }
//
// public void beginAssocOneIsNull(String key) {
// depthOffset++;
// internalAppendKeyBegin(key);
// appendNull();
// depthOffset--;
// }
//
// public void beginAssocOne(String key) {
// pathStack.pushPathKey(key);
//
// internalAppendKeyBegin(key);
// assocOne = true;
// }
//
// public void endAssocOne() {
//
// pathStack.pop();
// assocOne = false;
// }
//
// public Boolean includeMany(String key) {
// if (pathProperties != null){
// String fullPath = pathStack.peekFullPath(key);
// return pathProperties.hasPath(fullPath);
// }
// return null;
// }
//
// public void beginAssocMany(String key) {
//
// pathStack.pushPathKey(key);
//
// depthOffset--;
// internalAppendKeyBegin(key);
// depthOffset++;
// buffer.append("[");
// }
//
// public void endAssocMany(){
//
// pathStack.pop();
//
// if (pretty){
// depthOffset--;
// appendIndent();
// depthOffset++;
// }
// buffer.append("]");
// }
//
// private void internalAppendKeyBegin(String key) {
// if (!beanState.isFirstKey()){
// buffer.append(",");
// }
// if (pretty){
// appendIndent();
// }
// appendKeyWithComma(key, false);
// }
//
// public <T> void appendNameValue(String key, ScalarType<T> scalarType, T value) {
// appendKeyWithComma(key, true);
// scalarType.jsonWrite(buffer, value, getValueAdapter());
// }
//
// public void appendDiscriminator(String key, String discValue) {
// appendKeyWithComma(key, true);
// buffer.append("\"");
// buffer.append(discValue);
// buffer.append("\"");
// }
//
// private void appendKeyWithComma(String key, boolean withComma) {
// if (withComma){
// if (!beanState.isFirstKey()){
// buffer.append(",");
// }
// }
// buffer.append("\"");
// if(key == null) {
// buffer.append("null");
// } else {
// buffer.append(key);
// }
// buffer.append("\":");
// }
//
// public void appendNull(String key) {
// appendKeyWithComma(key, true);
// buffer.append("null");
// }
//
// public void appendNull() {
// buffer.append("null");
// }
//
// public JsonValueAdapter getValueAdapter() {
// return valueAdapter;
// }
//
// public String toString() {
// return buffer.toString();
// }
//
// public void popParentBean(){
// parentBeans.pop();
// }
//
// public void pushParentBean(Object parentBean){
// parentBeans.push(parentBean);
// }
//
// public void popParentBeanMany(){
// parentBeans.pop();
// depthOffset--;
// }
//
// public void pushParentBeanMany(Object parentBean){
// parentBeans.push(parentBean);
// depthOffset++;
// }
//
// public boolean isParentBean(Object bean){
// if (parentBeans.isEmpty()){
// return false;
// } else {
// return parentBeans.contains(bean);
// }
// }
//
// public WriteBeanState pushBeanState(Object bean) {
// WriteBeanState newState = new WriteBeanState();//bean);
// WriteBeanState prevState = beanState;
// beanState = newState;
// return prevState;
// }
//
// public void pushPreviousState(WriteBeanState previousState) {
// this.beanState = previousState;
// }
//
//
// public static class WriteBeanState {
//
// private boolean firstKeyOut;
//
// public WriteBeanState() {
//
// }
//
// public boolean isFirstKey() {
// if (!firstKeyOut){
// firstKeyOut = true;
// return true;
// } else {
// return false;
// }
// }
//
// }
}
@@ -6,17 +6,10 @@ import java.util.Map;
import com.avaje.ebean.config.CompoundType;
import com.avaje.ebean.config.CompoundTypeProperty;
import com.avaje.ebean.text.json.JsonElement;
import com.avaje.ebean.text.json.JsonElementObject;
import com.avaje.ebeaninternal.server.text.json.ReadJsonContext;
//import com.avaje.ebeaninternal.server.text.json.WriteJsonContext;
//import com.avaje.ebeaninternal.server.text.json.WriteJsonContext.WriteBeanState;
import com.avaje.ebeaninternal.server.text.json.WriteJson;
/**
* The internal representation of a Compound Type (Immutable Compound Value
* Object).
*
* @author rbygrave
* The internal representation of a Compound Type (Immutable Compound Value Object).
*
* @param <V>
* The Type of the "Immutable Compound Value Object".
@@ -168,47 +161,26 @@ public final class CtCompoundType<V> implements ScalarDataReader<V> {
return parent + "." + propName;
}
}
public Object jsonRead(ReadJsonContext ctx) {
if (!ctx.readObjectBegin()) {
// the object is null
return null;
}
JsonElementObject jsonObject = new JsonElementObject();
do {
if (!ctx.readKeyNext()){
break;
} else {
// we read a property key ...
String propName = ctx.getTokenKey();
JsonElement unmappedJson = ctx.readUnmappedJson(propName);
jsonObject.put(propName, unmappedJson);
if (!ctx.readValueNext()){
break;
}
}
} while(true);
return readJsonElementObject(ctx, jsonObject);
public Object jsonConvert(Map<String, Object> map) {
return readJsonElementObject(map);
}
private Object readJsonElementObject(ReadJsonContext ctx, JsonElementObject jsonObject){
@SuppressWarnings("unchecked")
private Object readJsonElementObject(Map<String,Object> jsonObject){
boolean nullValue = false;
Object[] values = new Object[propReaders.length];
for (int i = 0; i < propReaders.length; i++) {
String propName = properties[i].getName();
JsonElement jsonElement = jsonObject.get(propName);
Object jsonElement = jsonObject.get(propName);
if (propReaders[i] instanceof CtCompoundType<?>) {
values[i] = ((CtCompoundType<?>)propReaders[i]).readJsonElementObject(ctx, (JsonElementObject)jsonElement);
values[i] = ((CtCompoundType<?>)propReaders[i]).readJsonElementObject((Map<String,Object>)jsonElement);
} else {
values[i] = ((ScalarType<?>)propReaders[i]).jsonFromString(jsonElement.toPrimitiveString(), ctx.getValueAdapter());
//((ScalarType<?>)propReaders[i]).jsonFromString(jsonElement.toPrimitiveString(), ctx.getValueAdapter());
values[i] = ((ScalarType<?>)propReaders[i]).parse(jsonElement.toString());;
}
if (values[i] == null){
nullValue = true;
@@ -223,40 +195,35 @@ public final class CtCompoundType<V> implements ScalarDataReader<V> {
}
// public void jsonWrite(WriteJsonContext ctx, Object valueObject, String propertyName) {
//
// if (valueObject == null){
// ctx.beginAssocOneIsNull(propertyName);
//
// } else {
// ctx.pushParentBean(valueObject);
// ctx.beginAssocOne(propertyName);
// jsonWriteProps(ctx, valueObject, propertyName);
// ctx.endAssocOne();
// ctx.popParentBean();
// }
// }
//
//
// @SuppressWarnings({ "unchecked", "rawtypes" })
// private void jsonWriteProps(WriteJsonContext ctx, Object valueObject, String propertyName) {
//
// ctx.appendObjectBegin();
// WriteBeanState prevState = ctx.pushBeanState(valueObject);
//
// for (int i = 0; i < properties.length; i++) {
// String propName = properties[i].getName();
// Object value = properties[i].getValue((V)valueObject);
// if (propReaders[i] instanceof CtCompoundType<?>) {
// ((CtCompoundType)propReaders[i]).jsonWrite(ctx, value, propName);
//
// } else {
// ctx.appendNameValue(propName, (ScalarType)propReaders[i], value);
// }
// }
//
// ctx.pushPreviousState(prevState);
// ctx.appendObjectEnd();
// }
public void jsonWrite(WriteJson ctx, Object valueObject, String propertyName) {
ctx.beginAssocOne(propertyName, valueObject);
jsonWriteProps(ctx, valueObject, propertyName);
ctx.endAssocOne();
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private void jsonWriteProps(WriteJson ctx, Object valueObject, String propertyName) {
if (propertyName != null) {
ctx.gen().writeStartObject(propertyName);
} else {
ctx.gen().writeStartObject();
}
for (int i = 0; i < properties.length; i++) {
String propName = properties[i].getName();
Object value = properties[i].getValue((V) valueObject);
if (propReaders[i] instanceof CtCompoundType<?>) {
((CtCompoundType) propReaders[i]).jsonWrite(ctx, value, propName);
} else {
((ScalarType) propReaders[i]).jsonWrite(ctx.gen(), propName, value);
//ctx.appendNameValue(propName, (ScalarType) propReaders[i], value);
}
}
ctx.gen().writeEnd();
}
}
@@ -4,7 +4,6 @@ import java.io.IOException;
import com.avaje.ebean.text.TextException;
import com.avaje.ebean.util.StringHelper;
import com.avaje.ebeaninternal.server.text.json.WriteJsonBuffer;
public class EscapeJson {
@@ -45,24 +44,6 @@ public class EscapeJson {
}
public static void escape(String value, WriteJsonBuffer sb) {
if (value == null) {
sb.append("null");
} else {
escapeAppend(value, sb);
}
}
public static void escapeQuote(String value, WriteJsonBuffer sb) {
if (value == null) {
sb.append("null");
} else {
sb.append("\"");
escapeAppend(value, sb);
sb.append("\"");
}
}
/**
* Escape quotes, \, /, \r, \n, \b, \f, \t and characters (U+0000 through
* U+001F).
@@ -11,8 +11,6 @@ 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;
import com.avaje.ebeaninternal.server.text.json.WriteJsonBuffer;
/**
* Describes a scalar type.
@@ -187,18 +185,12 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
*/
public boolean isDateTimeCapable();
public void jsonWrite(WriteJsonBuffer buffer, T value, JsonValueAdapter ctx);
public String jsonToString(T value, JsonValueAdapter ctx);
public Object readData(DataInput dataInput) throws IOException;
public T jsonFromString(String value, JsonValueAdapter ctx);
public void writeData(DataOutput dataOutput, Object v) throws IOException;
public Object readData(DataInput dataInput) throws IOException;
public Object jsonRead(JsonParser ctx, Event event);
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);
public void jsonWrite(JsonGenerator ctx, String name, Object value);
}
@@ -1,7 +1,5 @@
package com.avaje.ebeaninternal.server.type;
import com.avaje.ebean.text.json.JsonValueAdapter;
import com.avaje.ebeaninternal.server.text.json.WriteJsonBuffer;
@@ -74,25 +72,12 @@ public abstract class ScalarTypeBase<T> implements ScalarType<T> {
return value;
}
public void loadIgnore(DataReader dataReader) {
dataReader.incrementPos(1);
}
public void accumulateScalarTypes(String propName, CtCompoundTypeScalarList list) {
list.addScalarType(propName, this);
}
public void loadIgnore(DataReader dataReader) {
dataReader.incrementPos(1);
}
public void jsonWrite(WriteJsonBuffer buffer, T value, JsonValueAdapter ctx) {
String v = jsonToString(value, ctx);
buffer.append(v);
}
public String jsonToString(T value, JsonValueAdapter ctx) {
return formatValue(value);
}
public T jsonFromString(String value, JsonValueAdapter ctx) {
return parse(value);
}
public void accumulateScalarTypes(String propName, CtCompoundTypeScalarList list) {
list.addScalarType(propName, this);
}
}
@@ -11,9 +11,6 @@ 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;
/**
* Base class for Date types.
*/
@@ -68,8 +65,7 @@ public abstract class ScalarTypeBaseDate<T> extends ScalarTypeBase<T> {
@Override
public Object jsonRead(JsonParser ctx, Event event) {
if (ctx.isIntegralNumber()) {
long millis = ctx.getLong();
return parseDateTime(millis);
return parseDateTime(ctx.getLong());
} else {
String string = ctx.getString();
throw new RuntimeException("convert "+string);
@@ -83,23 +79,6 @@ public abstract class ScalarTypeBaseDate<T> extends ScalarTypeBase<T> {
public abstract long convertToMillis(Object value);
@Override
public String jsonToString(T value, JsonValueAdapter ctx) {
Date date = convertToDate(value);
return ctx.jsonFromDate(date);
}
@Override
public void jsonWrite(WriteJsonBuffer buffer, T value, JsonValueAdapter ctx) {
String s = jsonToString(value, ctx);
buffer.append(s);
}
@Override
public T jsonFromString(String value, JsonValueAdapter ctx) {
Date ts = ctx.jsonToDate(value);
return convertFromDate(ts);
}
public Object readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
@@ -11,9 +11,6 @@ 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;
/**
* Base type for DateTime types.
*/
@@ -83,24 +80,6 @@ public abstract class ScalarTypeBaseDateTime<T> extends ScalarTypeBase<T> {
public boolean isDateTimeCapable() {
return true;
}
@Override
public void jsonWrite(WriteJsonBuffer buffer, T value, JsonValueAdapter ctx) {
String v = jsonToString(value, ctx);
buffer.append(v);
}
@Override
public String jsonToString(T value, JsonValueAdapter ctx) {
Timestamp ts = convertToTimestamp(value);
return ctx.jsonFromTimestamp(ts);
}
@Override
public T jsonFromString(String value, JsonValueAdapter ctx) {
Timestamp ts = ctx.jsonToTimestamp(value);
return convertFromTimestamp(ts);
}
public Object readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
@@ -11,8 +11,6 @@ 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;
/**
* Base ScalarType for types which converts to and from a VARCHAR database
@@ -85,19 +83,6 @@ public abstract class ScalarTypeBaseVarchar<T> extends ScalarTypeBase<T> {
return formatValue((T) v);
}
public T jsonFromString(String value, JsonValueAdapter ctx) {
return parse(EscapeJson.unescapeSlash(value));
}
public String toJsonString(Object value, JsonValueAdapter ctx) {
return EscapeJson.escapeQuote(format(value));
}
@Override
public void jsonWrite(WriteJsonBuffer buffer, T value, JsonValueAdapter ctx) {
EscapeJson.escapeQuote(format(value), buffer);
}
public Object readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
return null;
@@ -10,8 +10,6 @@ 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;
/**
* Encrypted ScalarType that wraps a byte[] types.
@@ -115,18 +113,6 @@ public class ScalarTypeBytesEncrypted implements ScalarType<byte[]> {
baseType.accumulateScalarTypes(propName, list);
}
public void jsonWrite(WriteJsonBuffer buffer, byte[] value, JsonValueAdapter ctx) {
baseType.jsonWrite(buffer, value, ctx);
}
public String jsonToString(byte[] value, JsonValueAdapter ctx) {
return baseType.jsonToString(value, ctx);
}
public byte[] jsonFromString(String value, JsonValueAdapter ctx) {
return baseType.jsonFromString(value, ctx);
}
public Object readData(DataInput dataInput) throws IOException {
int len = dataInput.readInt();
byte[] value = new byte[len];
@@ -6,7 +6,6 @@ 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;
/**
@@ -62,16 +61,6 @@ public class ScalarTypeChar extends ScalarTypeBaseVarchar<Character> {
public Character parse(String value) {
return value.charAt(0);
}
@Override
public Character jsonFromString(String value, JsonValueAdapter ctx) {
return value.charAt(0);
}
@Override
public String jsonToString(Character value, JsonValueAdapter ctx) {
return EscapeJson.escapeQuote(value.toString());
}
@Override
public Object jsonRead(JsonParser ctx, Event event) {
@@ -1,6 +1,5 @@
package com.avaje.ebeaninternal.server.type;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.sql.Types;
@@ -8,7 +7,6 @@ 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;
/**
@@ -64,16 +62,6 @@ public class ScalarTypeCharArray extends ScalarTypeBaseVarchar<char[]>{
public char[] parse(String value) {
return value.toCharArray();
}
@Override
public char[] jsonFromString(String value, JsonValueAdapter ctx) {
return value.toCharArray();
}
@Override
public String jsonToString(char[] value, JsonValueAdapter ctx) {
return EscapeJson.escapeQuote(String.valueOf(value));
}
@Override
public Object jsonRead(JsonParser ctx, Event event) {
@@ -3,7 +3,6 @@ package com.avaje.ebeaninternal.server.type;
import java.sql.SQLException;
import java.sql.Types;
import com.avaje.ebean.text.json.JsonValueAdapter;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
/**
@@ -11,66 +10,55 @@ import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
*/
public class ScalarTypeClob extends ScalarTypeBaseVarchar<String> {
static final int clobBufferSize = 512;
static final int stringInitialSize = 512;
protected ScalarTypeClob(boolean jdbcNative, int jdbcType) {
super(String.class, jdbcNative, jdbcType);
}
public ScalarTypeClob() {
super(String.class, true, Types.CLOB);
}
@Override
public String convertFromDbString(String dbValue) {
return dbValue;
static final int clobBufferSize = 512;
static final int stringInitialSize = 512;
protected ScalarTypeClob(boolean jdbcNative, int jdbcType) {
super(String.class, jdbcNative, jdbcType);
}
public ScalarTypeClob() {
super(String.class, true, Types.CLOB);
}
@Override
public String convertFromDbString(String dbValue) {
return dbValue;
}
@Override
public String convertToDbString(String beanValue) {
return beanValue;
}
public void bind(DataBind b, String value) throws SQLException {
if (value == null) {
b.setNull(Types.VARCHAR);
} else {
b.setString(value);
}
}
@Override
public String convertToDbString(String beanValue) {
return beanValue;
}
public String read(DataReader dataReader) throws SQLException {
public void bind(DataBind b, String value) throws SQLException {
if (value == null) {
b.setNull(Types.VARCHAR);
} else {
b.setString(value);
}
}
return dataReader.getStringClob();
}
public String read(DataReader dataReader) throws SQLException {
public Object toJdbcType(Object value) {
return BasicTypeConverter.toString(value);
}
return dataReader.getStringClob();
}
public String toBeanType(Object value) {
return BasicTypeConverter.toString(value);
}
public Object toJdbcType(Object value) {
return BasicTypeConverter.toString(value);
}
public String formatValue(String t) {
return t;
}
public String toBeanType(Object value) {
return BasicTypeConverter.toString(value);
}
public String parse(String value) {
return value;
}
public String formatValue(String t) {
return t;
}
public String parse(String value) {
return value;
}
@Override
public String jsonFromString(String value, JsonValueAdapter ctx) {
return value;
}
@Override
public String jsonToString(String value, JsonValueAdapter ctx) {
return EscapeJson.escapeQuote(value);
}
}
@@ -9,9 +9,6 @@ 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;
public class ScalarTypeEncryptedWrapper<T> implements ScalarType<T> {
private final ScalarType<T> wrapped;
@@ -122,18 +119,6 @@ public class ScalarTypeEncryptedWrapper<T> implements ScalarType<T> {
public void accumulateScalarTypes(String propName, CtCompoundTypeScalarList list) {
wrapped.accumulateScalarTypes(propName, list);
}
public String jsonToString(T value, JsonValueAdapter ctx) {
return wrapped.jsonToString(value, ctx);
}
public void jsonWrite(WriteJsonBuffer buffer, T value, JsonValueAdapter ctx) {
wrapped.jsonWrite(buffer, value, ctx);
}
public T jsonFromString(String value, JsonValueAdapter ctx) {
return wrapped.jsonFromString(value, ctx);
}
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
wrapped.jsonWrite(ctx, name, value);
@@ -12,7 +12,6 @@ import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import com.avaje.ebean.text.TextException;
import com.avaje.ebean.text.json.JsonValueAdapter;
/**
@@ -240,16 +239,6 @@ public class ScalarTypeEnumStandard {
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
ctx.write(name, formatValue(value));
}
@Override
public Object jsonFromString(String value, JsonValueAdapter ctx) {
return parse(value);
}
@Override
public String jsonToString(Object value, JsonValueAdapter ctx) {
return EscapeJson.escapeQuote(format(value));
}
public Object readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
@@ -11,7 +11,6 @@ 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;
/**
@@ -67,22 +66,13 @@ public class ScalarTypeInteger extends ScalarTypeBase<Integer> {
public boolean isDateTimeCapable() {
return false;
}
@Override
public Object jsonRead(JsonParser ctx, Event event) {
return Integer.valueOf(ctx.getInt());
}
public String jsonToString(Integer value, JsonValueAdapter ctx) {
return value.toString();
}
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);
}
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
ctx.write(name, (Integer) value);
}
}
@@ -10,9 +10,7 @@ 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;
/**
* ScalarType for String.
@@ -60,23 +58,6 @@ public class ScalarTypeString extends ScalarTypeBase<String> {
return true;
}
@Override
public void jsonWrite(WriteJsonBuffer buffer, String value, JsonValueAdapter ctx) {
String s = format(value);
EscapeJson.escapeQuote(s, buffer);
}
@Override
public String jsonFromString(String value, JsonValueAdapter ctx) {
return value;
}
@Override
public String jsonToString(String value, JsonValueAdapter ctx) {
return EscapeJson.escapeQuote(value);
}
public Object readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
return null;
@@ -1,6 +1,5 @@
package com.avaje.ebeaninternal.server.type;
import java.sql.Date;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
@@ -10,8 +10,6 @@ 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;
/**
* A ScalarType that uses a ScalarTypeConverter to convert to and from another
@@ -169,22 +167,6 @@ public class ScalarTypeWrapper<B, S> implements ScalarType<B> {
return this;
}
public String jsonToString(B value, JsonValueAdapter ctx) {
S sv = converter.unwrapValue(value);
return scalarType.jsonToString(sv, ctx);
}
public void jsonWrite(WriteJsonBuffer buffer, B value, JsonValueAdapter ctx) {
S sv = converter.unwrapValue(value);
scalarType.jsonWrite(buffer, sv, ctx);
}
public B jsonFromString(String value, JsonValueAdapter ctx) {
S s = scalarType.jsonFromString(value, ctx);
return converter.wrapValue(s);
}
@SuppressWarnings("unchecked")
@Override
public Object jsonRead(JsonParser ctx, Event event) {
@@ -194,9 +176,9 @@ public class ScalarTypeWrapper<B, S> implements ScalarType<B> {
@Override
public void jsonWrite(JsonGenerator ctx, String name, Object beanValue) {
@SuppressWarnings("unchecked")
S unwrapValue = converter.unwrapValue((B)beanValue);
scalarType.jsonWrite(ctx, name, unwrapValue);
}