mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Merge from JSON refactoring branch
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* Utility that converts between JSON content and java Maps/Lists.
|
||||
*/
|
||||
public class EJson {
|
||||
|
||||
/**
|
||||
* Write the nested Map/List as json.
|
||||
*/
|
||||
public static String write(Object object) {
|
||||
return EJsonWriter.write(object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the nested Map/List as json to the writer.
|
||||
*/
|
||||
public static void write(Object object, Writer writer) {
|
||||
EJsonWriter.write(object, writer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the nested Map/List as json to the jsonGenerator.
|
||||
*/
|
||||
public static void write(Object object, JsonGenerator jsonGenerator) {
|
||||
EJsonWriter.write(object, jsonGenerator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the json and return as a Map.
|
||||
*/
|
||||
public static Map<String,Object> parseObject(String json) {
|
||||
return EJsonReader.parseObject(json);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the json and return as a Map taking a reader.
|
||||
*/
|
||||
public static Map<String,Object> parseObject(Reader reader) {
|
||||
return EJsonReader.parseObject(reader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the json and return as a Map taking a JsonParser.
|
||||
*/
|
||||
public static Map<String,Object> parseObject(JsonParser parser) {
|
||||
return EJsonReader.parseObject(parser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the json and return as a List.
|
||||
*/
|
||||
public static List<Object> parseList(String json) {
|
||||
return EJsonReader.parseList(json);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the json and return as a List taking a Reader.
|
||||
*/
|
||||
public static List<Object> parseList(Reader reader) {
|
||||
return EJsonReader.parseList(reader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the json and return as a List taking a JsonParser.
|
||||
*/
|
||||
public static List<Object> parseList(JsonParser parser) {
|
||||
return EJsonReader.parseList(parser);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse the json and return as a List or Map.
|
||||
*/
|
||||
public static Object parse(String json) {
|
||||
return EJsonReader.parse(json);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the json and return as a List or Map.
|
||||
*/
|
||||
public static Object parse(Reader 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, 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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,319 @@
|
||||
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;
|
||||
|
||||
class EJsonReader {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static Map<String, Object> parseObject(String json) {
|
||||
return (Map<String, Object>) parse(json);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static Map<String, Object> parseObject(Reader reader) {
|
||||
return (Map<String, Object>) parse(reader, false);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static Map<String, Object> parseObject(JsonParser parser) {
|
||||
return (Map<String, Object>) parse(parser, false);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static List<Object> parseList(String json) {
|
||||
return (List<Object>) parse(json);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static List<Object> parseList(Reader reader) {
|
||||
return (List<Object>) parse(reader, false);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static List<Object> parseList(JsonParser parser) {
|
||||
return (List<Object>) parse(parser, false);
|
||||
}
|
||||
|
||||
static Object parse(String json) {
|
||||
return parse(new StringReader(json), false);
|
||||
}
|
||||
|
||||
static Object parse(Reader reader, boolean partial) {
|
||||
return parse(Json.createParser(reader), partial);
|
||||
}
|
||||
|
||||
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, 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();
|
||||
}
|
||||
|
||||
private void endArray() {
|
||||
end();
|
||||
}
|
||||
|
||||
private void endObject() {
|
||||
end();
|
||||
}
|
||||
|
||||
private void end() {
|
||||
depth--;
|
||||
if (!stack.isEmpty()) {
|
||||
|
||||
//if (currentContext != null) {
|
||||
// Object value = currentContext.getValue();
|
||||
//}
|
||||
currentContext = stack.pop(currentContext);
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
if (partial && depth == 0) {
|
||||
// completed the object/array
|
||||
return currentContext.getValue();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return currentContext.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* See if the event is a value rather than object or array.
|
||||
* <p>
|
||||
* If just a value then return that value else return null.
|
||||
*/
|
||||
private Object getSimpleValue(Event event) {
|
||||
|
||||
switch (event) {
|
||||
case VALUE_STRING:
|
||||
return parser.getString();
|
||||
|
||||
case VALUE_NUMBER:
|
||||
if (parser.isIntegralNumber()) {
|
||||
return parser.getLong();
|
||||
} else {
|
||||
return parser.getBigDecimal();
|
||||
}
|
||||
|
||||
case VALUE_TRUE:
|
||||
return Boolean.TRUE;
|
||||
|
||||
case VALUE_FALSE:
|
||||
return Boolean.FALSE;
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(Context endingContext) {
|
||||
if (head == null) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
Context temp = head;
|
||||
head = head.next;
|
||||
temp.popContext(endingContext);
|
||||
return temp;
|
||||
}
|
||||
|
||||
private boolean isEmpty() {
|
||||
return head == null;
|
||||
}
|
||||
}
|
||||
|
||||
private static abstract class Context {
|
||||
Context next;
|
||||
abstract void popContext(Context temp);
|
||||
abstract Object getValue();
|
||||
abstract void setKey(String key);
|
||||
abstract void setValue(Object value);
|
||||
abstract void setValueNull();
|
||||
}
|
||||
|
||||
private static class ObjectContext extends Context {
|
||||
|
||||
private final Map<String, Object> map = new LinkedHashMap<String, Object>();
|
||||
|
||||
private String key;
|
||||
|
||||
public void popContext(Context temp) {
|
||||
setValue(temp.getValue());
|
||||
}
|
||||
|
||||
Object getValue() {
|
||||
return map;
|
||||
}
|
||||
|
||||
void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
void setValue(Object value) {
|
||||
map.put(key, value);
|
||||
}
|
||||
|
||||
void setValueNull() {
|
||||
map.put(key, null);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ArrayContext extends Context {
|
||||
|
||||
private final List<Object> values = new ArrayList<Object>();
|
||||
|
||||
public void popContext(Context temp) {
|
||||
values.add(temp.getValue());
|
||||
}
|
||||
|
||||
Object getValue() {
|
||||
return values;
|
||||
}
|
||||
|
||||
void setValue(Object value) {
|
||||
values.add(value);
|
||||
}
|
||||
|
||||
void setValueNull() {
|
||||
// ignore
|
||||
}
|
||||
void setKey(String key) {
|
||||
// not expected
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
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 {
|
||||
|
||||
static String write(Object object) {
|
||||
StringWriter writer = new StringWriter(200);
|
||||
write(object, writer);
|
||||
return writer.toString();
|
||||
}
|
||||
|
||||
static void write(Object object, Writer writer) {
|
||||
JsonGenerator generator = Json.createGenerator(writer);
|
||||
write(object, generator);
|
||||
generator.close();
|
||||
}
|
||||
|
||||
static void write(Object object, JsonGenerator jsonGenerator) {
|
||||
new EJsonWriter(jsonGenerator).writeJson(object);
|
||||
}
|
||||
|
||||
private final JsonGenerator jsonGenerator;
|
||||
|
||||
private EJsonWriter(JsonGenerator jsonGenerator) {
|
||||
this.jsonGenerator = jsonGenerator;
|
||||
}
|
||||
|
||||
private void writeJson(Object object) {
|
||||
writeJson(null, object);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void writeJson(String name, Object object) {
|
||||
if (object == null) {
|
||||
writeNull(name);
|
||||
|
||||
} else if (object instanceof Map) {
|
||||
writeMap(name, (Map<Object, Object>) object);
|
||||
|
||||
} else if (object instanceof Collection) {
|
||||
writeCollection(name, (Collection<Object>) object);
|
||||
|
||||
} else if (object instanceof Boolean) {
|
||||
writeBoolean(name, (Boolean) object);
|
||||
|
||||
} else if (object instanceof Number) {
|
||||
writeNumber(name, (Number) object);
|
||||
|
||||
} else if (object instanceof Date) {
|
||||
writeDate(name, (Date) object);
|
||||
|
||||
} else if (object instanceof String) {
|
||||
writeString(name, (String) object);
|
||||
|
||||
} else if (object instanceof Map.Entry<?, ?>) {
|
||||
Map.Entry<?, ?> entry = (Map.Entry<?, ?>)object;
|
||||
writeJson(entry.getKey().toString(), entry.getValue());
|
||||
|
||||
} else {
|
||||
writeString(name, object.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void writeBoolean(String name, Boolean object) {
|
||||
if (name == null) {
|
||||
jsonGenerator.write(object);
|
||||
} else {
|
||||
jsonGenerator.write(name, object);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeDate(String name, Date object) {
|
||||
if (name == null) {
|
||||
jsonGenerator.write(object.getTime());
|
||||
} else {
|
||||
jsonGenerator.write(name, object.getTime());
|
||||
}
|
||||
}
|
||||
|
||||
private void writeNumber(String name, Number object) {
|
||||
|
||||
if (object instanceof Long) {
|
||||
writeLong(name, object);
|
||||
|
||||
} else if (object instanceof Integer) {
|
||||
writeInteger(name, object);
|
||||
|
||||
} else if (object instanceof Double) {
|
||||
writeDouble(name, object);
|
||||
|
||||
} else if (object instanceof BigDecimal) {
|
||||
writeBigDecimal(name, object);
|
||||
|
||||
} else if (object instanceof BigInteger) {
|
||||
writeBigInteger(name, object);
|
||||
|
||||
} else {
|
||||
writeGeneralNumber(name, object);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeGeneralNumber(String name, Number object) {
|
||||
if (name == null) {
|
||||
jsonGenerator.write(new BigDecimal(object.toString()));
|
||||
} else {
|
||||
jsonGenerator.write(name, new BigDecimal(object.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
private void writeBigDecimal(String name, Number object) {
|
||||
if (name == null) {
|
||||
jsonGenerator.write((BigDecimal) object);
|
||||
} else {
|
||||
jsonGenerator.write(name, (BigDecimal) object);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeBigInteger(String name, Number object) {
|
||||
if (name == null) {
|
||||
jsonGenerator.write((BigInteger) object);
|
||||
} else {
|
||||
jsonGenerator.write(name, (BigInteger) object);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeDouble(String name, Number object) {
|
||||
if (name == null) {
|
||||
jsonGenerator.write((Double) object);
|
||||
} else {
|
||||
jsonGenerator.write(name, (Double) object);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeLong(String name, Number object) {
|
||||
if (name == null) {
|
||||
jsonGenerator.write((Long) object);
|
||||
} else {
|
||||
jsonGenerator.write(name, (Long) object);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeInteger(String name, Number object) {
|
||||
if (name == null) {
|
||||
jsonGenerator.write((Integer) object);
|
||||
} else {
|
||||
jsonGenerator.write(name, (Integer) object);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeNull(String name) {
|
||||
if (name == null) {
|
||||
jsonGenerator.writeNull();
|
||||
} else {
|
||||
jsonGenerator.writeNull(name);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeString(String name, String object) {
|
||||
if (name == null) {
|
||||
jsonGenerator.write(object);
|
||||
} else {
|
||||
jsonGenerator.write(name, object);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeCollection(String name, Collection<Object> collection) {
|
||||
if (name == null) {
|
||||
jsonGenerator.writeStartArray();
|
||||
} else {
|
||||
jsonGenerator.writeStartArray(name);
|
||||
}
|
||||
for (Object object : collection) {
|
||||
writeJson(null, object);
|
||||
}
|
||||
jsonGenerator.writeEnd();
|
||||
}
|
||||
|
||||
private void writeMap(String name, Map<Object, Object> map) {
|
||||
|
||||
if (name == null) {
|
||||
jsonGenerator.writeStartObject();
|
||||
} else {
|
||||
jsonGenerator.writeStartObject(name);
|
||||
}
|
||||
Set<Entry<Object, Object>> entrySet = map.entrySet();
|
||||
for (Entry<Object, Object> entry : entrySet) {
|
||||
writeJson(entry.getKey().toString(), entry.getValue());
|
||||
}
|
||||
jsonGenerator.writeEnd();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -53,6 +53,9 @@ class PathPropertiesParser {
|
||||
case '(':
|
||||
return currentWord();
|
||||
default:
|
||||
if (pos == 1) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
} while (pos < eof);
|
||||
throw new RuntimeException("Hit EOF while reading sectionTitle from " + startPos);
|
||||
@@ -91,6 +94,10 @@ class PathPropertiesParser {
|
||||
}
|
||||
|
||||
} while (pos < eof);
|
||||
if (startPos < pos) {
|
||||
String currentWord = source.substring(startPos, pos);
|
||||
currentPathProps.addProperty(currentWord);
|
||||
}
|
||||
}
|
||||
|
||||
private void addSubpath() {
|
||||
|
||||
@@ -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;
|
||||
@@ -1963,10 +1962,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,8 +11,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;
|
||||
@@ -33,7 +31,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.AutoCommitTransactionManager;
|
||||
import com.avaje.ebeaninternal.server.transaction.DefaultTransactionScopeManager;
|
||||
import com.avaje.ebeaninternal.server.transaction.ExternalTransactionScopeManager;
|
||||
@@ -46,6 +43,8 @@ import com.avaje.ebeaninternal.server.type.TypeManager;
|
||||
/**
|
||||
* Used to extend the ServerConfig with additional objects used to configure and
|
||||
* construct an EbeanServer.
|
||||
*
|
||||
* @author rbygrave
|
||||
*/
|
||||
public class InternalConfiguration {
|
||||
|
||||
@@ -163,16 +162,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() {
|
||||
|
||||
@@ -0,0 +1,266 @@
|
||||
package com.avaje.ebeaninternal.server.core;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.avaje.ebean.ExpressionFactory;
|
||||
import com.avaje.ebean.cache.ServerCacheManager;
|
||||
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.ebeaninternal.api.SpiBackgroundExecutor;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import com.avaje.ebeaninternal.server.autofetch.AutoFetchManager;
|
||||
import com.avaje.ebeaninternal.server.autofetch.AutoFetchManagerFactory;
|
||||
import com.avaje.ebeaninternal.server.cluster.ClusterManager;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
|
||||
import com.avaje.ebeaninternal.server.deploy.DeployOrmXml;
|
||||
import com.avaje.ebeaninternal.server.deploy.parse.DeployCreateProperties;
|
||||
import com.avaje.ebeaninternal.server.deploy.parse.DeployInherit;
|
||||
import com.avaje.ebeaninternal.server.deploy.parse.DeployUtil;
|
||||
import com.avaje.ebeaninternal.server.expression.DefaultExpressionFactory;
|
||||
import com.avaje.ebeaninternal.server.lib.sql.DataSourcePool;
|
||||
import com.avaje.ebeaninternal.server.persist.Binder;
|
||||
import com.avaje.ebeaninternal.server.persist.DefaultPersister;
|
||||
import com.avaje.ebeaninternal.server.query.CQueryEngine;
|
||||
import com.avaje.ebeaninternal.server.query.DefaultOrmQueryEngine;
|
||||
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;
|
||||
<<<<<<< HEAD
|
||||
import com.avaje.ebeaninternal.server.text.json.DefaultJsonValueAdapter;
|
||||
import com.avaje.ebeaninternal.server.transaction.AutoCommitTransactionManager;
|
||||
=======
|
||||
>>>>>>> json-refactor
|
||||
import com.avaje.ebeaninternal.server.transaction.DefaultTransactionScopeManager;
|
||||
import com.avaje.ebeaninternal.server.transaction.ExternalTransactionScopeManager;
|
||||
import com.avaje.ebeaninternal.server.transaction.JtaTransactionManager;
|
||||
import com.avaje.ebeaninternal.server.transaction.TransactionManager;
|
||||
import com.avaje.ebeaninternal.server.transaction.TransactionScopeManager;
|
||||
import com.avaje.ebeaninternal.server.type.DefaultTypeManager;
|
||||
import com.avaje.ebeaninternal.server.type.TypeManager;
|
||||
|
||||
/**
|
||||
* Used to extend the ServerConfig with additional objects used to configure and
|
||||
* construct an EbeanServer.
|
||||
*/
|
||||
public class InternalConfiguration {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(InternalConfiguration.class);
|
||||
|
||||
private final ServerConfig serverConfig;
|
||||
|
||||
private final BootupClasses bootupClasses;
|
||||
|
||||
private final DeployInherit deployInherit;
|
||||
|
||||
private final ResourceManager resourceManager;
|
||||
|
||||
private final DeployOrmXml deployOrmXml;
|
||||
|
||||
private final TypeManager typeManager;
|
||||
|
||||
private final Binder binder;
|
||||
|
||||
private final DeployCreateProperties deployCreateProperties;
|
||||
|
||||
private final DeployUtil deployUtil;
|
||||
|
||||
private final BeanDescriptorManager beanDescriptorManager;
|
||||
|
||||
private final TransactionManager transactionManager;
|
||||
|
||||
private final TransactionScopeManager transactionScopeManager;
|
||||
|
||||
private final CQueryEngine cQueryEngine;
|
||||
|
||||
private final ClusterManager clusterManager;
|
||||
|
||||
private final ServerCacheManager cacheManager;
|
||||
|
||||
private final ExpressionFactory expressionFactory;
|
||||
|
||||
private final SpiBackgroundExecutor backgroundExecutor;
|
||||
|
||||
private final PstmtBatch pstmtBatch;
|
||||
|
||||
private final XmlConfig xmlConfig;
|
||||
|
||||
public InternalConfiguration(XmlConfig xmlConfig, ClusterManager clusterManager,
|
||||
ServerCacheManager cacheManager, SpiBackgroundExecutor backgroundExecutor,
|
||||
ServerConfig serverConfig, BootupClasses bootupClasses, PstmtBatch pstmtBatch) {
|
||||
|
||||
this.xmlConfig = xmlConfig;
|
||||
this.pstmtBatch = pstmtBatch;
|
||||
this.clusterManager = clusterManager;
|
||||
this.backgroundExecutor = backgroundExecutor;
|
||||
this.cacheManager = cacheManager;
|
||||
this.serverConfig = serverConfig;
|
||||
this.bootupClasses = bootupClasses;
|
||||
this.expressionFactory = new DefaultExpressionFactory();
|
||||
|
||||
this.typeManager = new DefaultTypeManager(serverConfig, bootupClasses);
|
||||
this.binder = new Binder(typeManager);
|
||||
|
||||
this.resourceManager = ResourceManagerFactory.createResourceManager(serverConfig);
|
||||
this.deployOrmXml = new DeployOrmXml(resourceManager.getResourceSource());
|
||||
this.deployInherit = new DeployInherit(bootupClasses);
|
||||
|
||||
this.deployCreateProperties = new DeployCreateProperties(typeManager);
|
||||
this.deployUtil = new DeployUtil(typeManager, serverConfig);
|
||||
|
||||
this.beanDescriptorManager = new BeanDescriptorManager(this);
|
||||
beanDescriptorManager.deploy();
|
||||
|
||||
this.transactionManager = createTransactionManager();
|
||||
|
||||
this.cQueryEngine = new CQueryEngine(serverConfig.getDatabasePlatform(), binder);
|
||||
|
||||
ExternalTransactionManager externalTransactionManager = serverConfig.getExternalTransactionManager();
|
||||
if (externalTransactionManager == null && serverConfig.isUseJtaTransactionManager()) {
|
||||
externalTransactionManager = new JtaTransactionManager();
|
||||
}
|
||||
if (externalTransactionManager != null) {
|
||||
externalTransactionManager.setTransactionManager(transactionManager);
|
||||
this.transactionScopeManager = new ExternalTransactionScopeManager(transactionManager, externalTransactionManager);
|
||||
logger.info("Using Transaction Manager [" + externalTransactionManager.getClass() + "]");
|
||||
} else {
|
||||
this.transactionScopeManager = new DefaultTransactionScopeManager(transactionManager);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the TransactionManager taking into account autoCommit mode.
|
||||
*/
|
||||
private TransactionManager createTransactionManager() {
|
||||
|
||||
if (isAutoCommitMode()) {
|
||||
return new AutoCommitTransactionManager(clusterManager, backgroundExecutor, serverConfig, beanDescriptorManager, this.getBootupClasses());
|
||||
}
|
||||
|
||||
return new TransactionManager(clusterManager, backgroundExecutor, serverConfig, beanDescriptorManager, this.getBootupClasses());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if autoCommit mode is on.
|
||||
*/
|
||||
private boolean isAutoCommitMode() {
|
||||
if (serverConfig.isAutoCommitMode()) {
|
||||
// explicitly set
|
||||
return true;
|
||||
}
|
||||
DataSource dataSource = serverConfig.getDataSource();
|
||||
if (dataSource instanceof DataSourcePool && ((DataSourcePool)dataSource).getAutoCommit()) {
|
||||
// We know the DataSourcePool is using autoCommit
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public JsonContext createJsonContext(SpiEbeanServer server) {
|
||||
|
||||
return new DJsonContext(server);
|
||||
}
|
||||
|
||||
public XmlConfig getXmlConfig() {
|
||||
return xmlConfig;
|
||||
}
|
||||
|
||||
public AutoFetchManager createAutoFetchManager(SpiEbeanServer server) {
|
||||
return AutoFetchManagerFactory.create(server, serverConfig, resourceManager);
|
||||
}
|
||||
|
||||
public RelationalQueryEngine createRelationalQueryEngine() {
|
||||
return new DefaultRelationalQueryEngine(binder, serverConfig.getDatabaseBooleanTrue());
|
||||
}
|
||||
|
||||
public OrmQueryEngine createOrmQueryEngine() {
|
||||
return new DefaultOrmQueryEngine(beanDescriptorManager, cQueryEngine);
|
||||
}
|
||||
|
||||
public Persister createPersister(SpiEbeanServer server) {
|
||||
return new DefaultPersister(server, binder, beanDescriptorManager, pstmtBatch);
|
||||
}
|
||||
|
||||
public PstmtBatch getPstmtBatch() {
|
||||
return pstmtBatch;
|
||||
}
|
||||
|
||||
public ServerCacheManager getCacheManager() {
|
||||
return cacheManager;
|
||||
}
|
||||
|
||||
public BootupClasses getBootupClasses() {
|
||||
return bootupClasses;
|
||||
}
|
||||
|
||||
public DatabasePlatform getDatabasePlatform() {
|
||||
return serverConfig.getDatabasePlatform();
|
||||
}
|
||||
|
||||
public ServerConfig getServerConfig() {
|
||||
return serverConfig;
|
||||
}
|
||||
|
||||
public ExpressionFactory getExpressionFactory() {
|
||||
return expressionFactory;
|
||||
}
|
||||
|
||||
public TypeManager getTypeManager() {
|
||||
return typeManager;
|
||||
}
|
||||
|
||||
public Binder getBinder() {
|
||||
return binder;
|
||||
}
|
||||
|
||||
public BeanDescriptorManager getBeanDescriptorManager() {
|
||||
return beanDescriptorManager;
|
||||
}
|
||||
|
||||
public DeployInherit getDeployInherit() {
|
||||
return deployInherit;
|
||||
}
|
||||
|
||||
public ResourceManager getResourceManager() {
|
||||
return resourceManager;
|
||||
}
|
||||
|
||||
public DeployOrmXml getDeployOrmXml() {
|
||||
return deployOrmXml;
|
||||
}
|
||||
|
||||
public DeployCreateProperties getDeployCreateProperties() {
|
||||
return deployCreateProperties;
|
||||
}
|
||||
|
||||
public DeployUtil getDeployUtil() {
|
||||
return deployUtil;
|
||||
}
|
||||
|
||||
public TransactionManager getTransactionManager() {
|
||||
return transactionManager;
|
||||
}
|
||||
|
||||
public TransactionScopeManager getTransactionScopeManager() {
|
||||
return transactionScopeManager;
|
||||
}
|
||||
|
||||
public CQueryEngine getCQueryEngine() {
|
||||
return cQueryEngine;
|
||||
}
|
||||
|
||||
public ClusterManager getClusterManager() {
|
||||
return clusterManager;
|
||||
}
|
||||
|
||||
public SpiBackgroundExecutor getBackgroundExecutor() {
|
||||
return backgroundExecutor;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import com.avaje.ebean.bean.BeanCollection;
|
||||
import com.avaje.ebean.bean.BeanCollectionAdd;
|
||||
import com.avaje.ebean.bean.BeanCollectionLoader;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJsonContext;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJson;
|
||||
|
||||
/**
|
||||
* Helper functions for performing tasks on Lists Sets or Maps.
|
||||
@@ -62,6 +62,6 @@ public interface BeanCollectionHelp<T> {
|
||||
/**
|
||||
* Write the collection out as json.
|
||||
*/
|
||||
public void jsonWrite(WriteJsonContext ctx, String name, Object collection, boolean explicitInclude);
|
||||
public void jsonWrite(WriteJson ctx, String name, Object collection, boolean explicitInclude);
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -34,8 +35,6 @@ import com.avaje.ebean.event.BeanPersistListener;
|
||||
import com.avaje.ebean.event.BeanQueryAdapter;
|
||||
import com.avaje.ebean.meta.MetaBeanInfo;
|
||||
import com.avaje.ebean.meta.MetaQueryPlanStatistic;
|
||||
import com.avaje.ebean.text.TextException;
|
||||
import com.avaje.ebean.text.json.JsonWriteBeanVisitor;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlan;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import com.avaje.ebeaninternal.api.SpiQuery;
|
||||
@@ -62,10 +61,7 @@ import com.avaje.ebeaninternal.server.query.CQueryPlan;
|
||||
import com.avaje.ebeaninternal.server.query.CQueryPlanStats.Snapshot;
|
||||
import com.avaje.ebeaninternal.server.query.SplitName;
|
||||
import com.avaje.ebeaninternal.server.querydefn.OrmQueryDetail;
|
||||
import com.avaje.ebeaninternal.server.text.json.ReadJsonContext;
|
||||
import com.avaje.ebeaninternal.server.text.json.ReadJsonContext.ReadBeanState;
|
||||
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;
|
||||
import com.avaje.ebeaninternal.server.type.DataBind;
|
||||
import com.avaje.ebeaninternal.server.type.TypeManager;
|
||||
import com.avaje.ebeaninternal.util.SortByClause;
|
||||
@@ -195,12 +191,12 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
/**
|
||||
* Inheritance information. Server side only.
|
||||
*/
|
||||
private final InheritInfo inheritInfo;
|
||||
protected final InheritInfo inheritInfo;
|
||||
|
||||
/**
|
||||
* Derived list of properties that make up the unique id.
|
||||
*/
|
||||
private final BeanProperty idProperty;
|
||||
protected final BeanProperty idProperty;
|
||||
private final int idPropertyIndex;
|
||||
|
||||
/**
|
||||
@@ -327,7 +323,8 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
private final boolean cacheSharableBeans;
|
||||
|
||||
private final BeanDescriptorCacheHelp<T> cacheHelp;
|
||||
|
||||
private final BeanDescriptorJsonHelp<T> jsonHelp;
|
||||
|
||||
private final String defaultSelectClause;
|
||||
private final Set<String> defaultSelectClauseSet;
|
||||
|
||||
@@ -422,7 +419,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
|
||||
this.cacheSharableBeans = noRelationships && deploy.getCacheOptions().isReadOnly();
|
||||
this.cacheHelp = new BeanDescriptorCacheHelp<T>(this, owner.getCacheManager(), deploy.getCacheOptions(), cacheSharableBeans, propertiesOneImported);
|
||||
|
||||
this.jsonHelp = new BeanDescriptorJsonHelp<T>(this);
|
||||
|
||||
// Check if there are no cascade save associated beans ( subject to change
|
||||
// in initialiseOther()). Note that if we are in an inheritance hierarchy
|
||||
@@ -2115,167 +2112,23 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
return propertiesLocal;
|
||||
}
|
||||
|
||||
public void jsonWrite(WriteJsonContext ctx, EntityBean bean) {
|
||||
|
||||
if (bean != null) {
|
||||
|
||||
ctx.appendObjectBegin();
|
||||
WriteBeanState prevState = ctx.pushBeanState(bean);
|
||||
|
||||
if (inheritInfo != null) {
|
||||
InheritInfo localInheritInfo = inheritInfo.readType(bean.getClass());
|
||||
String discValue = localInheritInfo.getDiscriminatorStringValue();
|
||||
String discColumn = localInheritInfo.getDiscriminatorColumn();
|
||||
ctx.appendDiscriminator(discColumn, discValue);
|
||||
|
||||
BeanDescriptor<?> localDescriptor = localInheritInfo.getBeanDescriptor();
|
||||
localDescriptor.jsonWriteProperties(ctx, bean);
|
||||
|
||||
} else {
|
||||
jsonWriteProperties(ctx, bean);
|
||||
}
|
||||
|
||||
ctx.pushPreviousState(prevState);
|
||||
ctx.appendObjectEnd();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void jsonWriteProperties(WriteJsonContext ctx, EntityBean bean) {
|
||||
|
||||
JsonWriteBeanVisitor<T> beanVisitor = (JsonWriteBeanVisitor<T>) ctx.getBeanVisitor();
|
||||
|
||||
Set<String> props = ctx.getIncludeProperties();
|
||||
|
||||
boolean explicitAllProps;
|
||||
if (props == null) {
|
||||
explicitAllProps = false;
|
||||
} else {
|
||||
explicitAllProps = props.contains("*");
|
||||
if (explicitAllProps || props.isEmpty()) {
|
||||
props = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (idProperty != null) {
|
||||
Object idValue = 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 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 void jsonWrite(WriteJson writeJson, EntityBean bean) {
|
||||
jsonHelp.jsonWrite(writeJson, bean, null);
|
||||
}
|
||||
|
||||
private ReadBeanState jsonReadObject(ReadJsonContext ctx, String path) {
|
||||
public void jsonWrite(WriteJson writeJson, EntityBean bean, String key) {
|
||||
jsonHelp.jsonWrite(writeJson, bean, key);
|
||||
}
|
||||
|
||||
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 void jsonWriteProperties(WriteJson writeJson, EntityBean bean) {
|
||||
jsonHelp.jsonWriteProperties(writeJson, bean);
|
||||
}
|
||||
|
||||
public T jsonRead(JsonParser parser, String path) {
|
||||
return jsonHelp.jsonRead(parser, path);
|
||||
}
|
||||
|
||||
protected T jsonReadObject(JsonParser parser, String path) {
|
||||
return jsonHelp.jsonReadObject(parser, path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
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.ebeaninternal.server.text.json.WriteJson;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJson.WriteBean;
|
||||
|
||||
public class BeanDescriptorJsonHelp<T> {
|
||||
|
||||
private final BeanDescriptor<T> desc;
|
||||
|
||||
private final InheritInfo inheritInfo;
|
||||
|
||||
public BeanDescriptorJsonHelp(BeanDescriptor<T> desc) {
|
||||
this.desc = desc;
|
||||
this.inheritInfo = desc.inheritInfo;
|
||||
}
|
||||
|
||||
public void jsonWrite(WriteJson writeJson, EntityBean bean, String key) {
|
||||
|
||||
// if (writeJson.hasBean()) {
|
||||
|
||||
writeJson.writeStartObject(key);
|
||||
//WriteBeanState prevState = ctx.pushBeanState(bean);
|
||||
|
||||
if (inheritInfo == null) {
|
||||
jsonWriteProperties(writeJson, bean);
|
||||
|
||||
} else {
|
||||
InheritInfo localInheritInfo = inheritInfo.readType(bean.getClass());
|
||||
String discValue = localInheritInfo.getDiscriminatorStringValue();
|
||||
String discColumn = localInheritInfo.getDiscriminatorColumn();
|
||||
writeJson.gen().write(discColumn, discValue);
|
||||
|
||||
BeanDescriptor<?> localDescriptor = localInheritInfo.getBeanDescriptor();
|
||||
localDescriptor.jsonWriteProperties(writeJson, bean);
|
||||
}
|
||||
|
||||
//ctx.pushPreviousState(prevState);
|
||||
writeJson.gen().writeEnd();
|
||||
}
|
||||
|
||||
protected void jsonWriteProperties(WriteJson writeJson, EntityBean bean) {
|
||||
|
||||
|
||||
WriteBean writeBean = writeJson.createWriteBean(desc, bean);
|
||||
writeBean.write(writeJson);
|
||||
}
|
||||
|
||||
|
||||
@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)) {
|
||||
// just try to assume this is the correct bean type in the inheritance
|
||||
BeanProperty property = desc.getBeanProperty(propName);
|
||||
if (property != null) {
|
||||
EntityBean bean = desc.createEntityBean();
|
||||
property.jsonRead(parser, bean);
|
||||
return jsonReadProperties(parser, bean);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
protected T jsonReadObject(JsonParser parser, String path) {
|
||||
|
||||
EntityBean bean = desc.createEntityBean();
|
||||
//ctx.pushBean(bean, path, this);
|
||||
|
||||
return jsonReadProperties(parser, bean);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected T jsonReadProperties(JsonParser parser, EntityBean bean) {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,7 +12,7 @@ import com.avaje.ebean.bean.BeanCollectionAdd;
|
||||
import com.avaje.ebean.bean.BeanCollectionLoader;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.common.BeanList;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJsonContext;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJson;
|
||||
|
||||
/**
|
||||
* Helper object for dealing with Lists.
|
||||
@@ -128,7 +128,7 @@ public final class BeanListHelp<T> implements BeanCollectionHelp<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public void jsonWrite(WriteJsonContext ctx, String name, Object collection, boolean explicitInclude) {
|
||||
public void jsonWrite(WriteJson ctx, String name, Object collection, boolean explicitInclude) {
|
||||
|
||||
List<?> list;
|
||||
if (collection instanceof BeanCollection<?>) {
|
||||
@@ -147,15 +147,11 @@ public final class BeanListHelp<T> implements BeanCollectionHelp<T> {
|
||||
list = (List<?>) collection;
|
||||
}
|
||||
|
||||
ctx.beginAssocMany(name);
|
||||
ctx.gen().writeStartArray(name);
|
||||
for (int j = 0; j < list.size(); j++) {
|
||||
if (j > 0) {
|
||||
ctx.appendComma();
|
||||
}
|
||||
Object detailBean = list.get(j);
|
||||
targetDescriptor.jsonWrite(ctx, (EntityBean)detailBean);
|
||||
targetDescriptor.jsonWrite(ctx, (EntityBean)list.get(j));
|
||||
}
|
||||
ctx.endAssocMany();
|
||||
ctx.gen().writeEnd();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import com.avaje.ebean.bean.BeanCollectionAdd;
|
||||
import com.avaje.ebean.bean.BeanCollectionLoader;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.common.BeanMap;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJsonContext;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJson;
|
||||
|
||||
/**
|
||||
* Helper specifically for dealing with Maps.
|
||||
@@ -156,7 +156,7 @@ public final class BeanMapHelp<T> implements BeanCollectionHelp<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public void jsonWrite(WriteJsonContext ctx, String name, Object collection, boolean explicitInclude) {
|
||||
public void jsonWrite(WriteJson ctx, String name, Object collection, boolean explicitInclude) {
|
||||
|
||||
Map<?,?> map;
|
||||
if (collection instanceof BeanCollection<?>){
|
||||
@@ -175,19 +175,14 @@ public final class BeanMapHelp<T> implements BeanCollectionHelp<T> {
|
||||
map = (Map<?,?>)collection;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
ctx.beginAssocMany(name);
|
||||
ctx.gen().writeStartArray(name);
|
||||
Iterator<?> it = map.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
Entry<?, ?> entry = (Entry<?, ?>)it.next();
|
||||
if (count++ > 0){
|
||||
ctx.appendComma();
|
||||
}
|
||||
//FIXME: json write map key ...
|
||||
Object detailBean = entry.getValue();
|
||||
targetDescriptor.jsonWrite(ctx, (EntityBean)detailBean);
|
||||
targetDescriptor.jsonWrite(ctx, (EntityBean) entry.getValue());
|
||||
}
|
||||
ctx.endAssocMany();
|
||||
ctx.gen().writeEnd();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ import java.sql.Types;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.json.stream.JsonParser;
|
||||
import javax.json.stream.JsonParser.Event;
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
@@ -18,7 +20,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,8 +31,7 @@ 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.text.json.WriteJson;
|
||||
import com.avaje.ebeaninternal.server.type.DataBind;
|
||||
import com.avaje.ebeaninternal.server.type.ScalarType;
|
||||
|
||||
@@ -78,7 +78,7 @@ public class BeanProperty implements ElPropertyValue {
|
||||
* Flag set if this maps to the inheritance discriminator column
|
||||
*/
|
||||
final boolean discriminator;
|
||||
|
||||
|
||||
/**
|
||||
* Flag to mark the property as embedded. This could be on
|
||||
* BeanPropertyAssocOne rather than here. Put it here for checking Id type
|
||||
@@ -92,7 +92,7 @@ public class BeanProperty implements ElPropertyValue {
|
||||
final boolean version;
|
||||
|
||||
final boolean naturalKey;
|
||||
|
||||
|
||||
/**
|
||||
* Set if this property is nullable.
|
||||
*/
|
||||
@@ -136,7 +136,7 @@ public class BeanProperty implements ElPropertyValue {
|
||||
* True if the property is a Clob, Blob LongVarchar or LongVarbinary.
|
||||
*/
|
||||
final boolean lob;
|
||||
|
||||
|
||||
final boolean fetchEager;
|
||||
|
||||
final boolean isTransient;
|
||||
@@ -147,7 +147,7 @@ public class BeanProperty implements ElPropertyValue {
|
||||
final String name;
|
||||
|
||||
final int propertyIndex;
|
||||
|
||||
|
||||
/**
|
||||
* The reflected field.
|
||||
*/
|
||||
@@ -265,7 +265,6 @@ public class BeanProperty implements ElPropertyValue {
|
||||
final boolean indexed;
|
||||
|
||||
final String indexName;
|
||||
|
||||
public BeanProperty(DeployBeanProperty deploy) {
|
||||
this(null, null, deploy);
|
||||
}
|
||||
@@ -275,10 +274,8 @@ public class BeanProperty implements ElPropertyValue {
|
||||
this.descriptor = descriptor;
|
||||
this.name = InternString.intern(deploy.getName());
|
||||
this.propertyIndex = deploy.getPropertyIndex();
|
||||
|
||||
this.indexed = deploy.isIndexed();
|
||||
this.indexName = deploy.getIndexName();
|
||||
|
||||
this.unidirectionalShadow = deploy.isUndirectionalShadow();
|
||||
this.discriminator = deploy.isDiscriminator();
|
||||
this.localEncrypted = deploy.isLocalEncrypted();
|
||||
@@ -333,7 +330,7 @@ public class BeanProperty implements ElPropertyValue {
|
||||
this.lob = isLobType(dbType);
|
||||
this.propertyType = deploy.getPropertyType();
|
||||
this.field = deploy.getField();
|
||||
|
||||
|
||||
EntityType et = descriptor == null ? null : descriptor.getEntityType();
|
||||
this.elPlaceHolder = tableAliasIntern(descriptor, deploy.getElPlaceHolder(et), false, null);
|
||||
this.elPlaceHolderEncrypted = tableAliasIntern(descriptor, deploy.getElPlaceHolder(et), dbEncrypted, dbColumn);
|
||||
@@ -371,7 +368,6 @@ public class BeanProperty implements ElPropertyValue {
|
||||
|
||||
this.indexed = source.isIndexed();
|
||||
this.indexName = source.getIndexName();
|
||||
|
||||
this.dbColumn = InternString.intern(override.getDbColumn());
|
||||
this.sqlFormulaJoin = InternString.intern(override.getSqlFormulaJoin());
|
||||
this.sqlFormulaSelect = InternString.intern(override.getSqlFormulaSelect());
|
||||
@@ -420,7 +416,7 @@ public class BeanProperty implements ElPropertyValue {
|
||||
this.lob = isLobType(dbType);
|
||||
this.propertyType = source.getPropertyType();
|
||||
this.field = source.getField();
|
||||
|
||||
|
||||
this.elPlaceHolder = override.replace(source.elPlaceHolder, source.dbColumn);
|
||||
this.elPlaceHolderEncrypted = override.replace(source.elPlaceHolderEncrypted, source.dbColumn);
|
||||
|
||||
@@ -487,7 +483,7 @@ public class BeanProperty implements ElPropertyValue {
|
||||
public boolean isDiscriminator() {
|
||||
return discriminator;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if the underlying type is mutable.
|
||||
*/
|
||||
@@ -675,6 +671,14 @@ public class BeanProperty implements ElPropertyValue {
|
||||
public BeanProperty getBeanProperty() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isIndexed() {
|
||||
return indexed;
|
||||
}
|
||||
|
||||
public String getIndexName() {
|
||||
return indexName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the getter method.
|
||||
@@ -737,12 +741,12 @@ public class BeanProperty implements ElPropertyValue {
|
||||
|
||||
public Object getCacheDataValue(EntityBean bean) {
|
||||
return getValue(bean);
|
||||
}
|
||||
}
|
||||
|
||||
public void setCacheDataValue(EntityBean bean, Object cacheData) {
|
||||
setValue(bean, cacheData);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the value of the property method.
|
||||
*/
|
||||
@@ -755,12 +759,12 @@ public class BeanProperty implements ElPropertyValue {
|
||||
throw new RuntimeException(msg, ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Explicitly use reflection to get value.
|
||||
*/
|
||||
public Object getValueViaReflection(Object bean) {
|
||||
try {
|
||||
try {
|
||||
return readMethod.invoke(bean, NO_ARGS);
|
||||
} catch (Exception ex) {
|
||||
String beanType = bean == null ? "null" : bean.getClass().getName();
|
||||
@@ -815,7 +819,7 @@ public class BeanProperty implements ElPropertyValue {
|
||||
* Return the position of this property in the enhanced bean.
|
||||
*/
|
||||
public int getPropertyIndex() {
|
||||
return propertyIndex;
|
||||
return propertyIndex;
|
||||
}
|
||||
|
||||
public String getElName() {
|
||||
@@ -829,7 +833,6 @@ public class BeanProperty implements ElPropertyValue {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean containsFormulaWithJoin() {
|
||||
return formula && sqlFormulaJoin != null;
|
||||
@@ -895,7 +898,7 @@ public class BeanProperty implements ElPropertyValue {
|
||||
public boolean isDirtyValue(Object value) {
|
||||
return scalarType.isDirty(value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the scalarType.
|
||||
*/
|
||||
@@ -914,7 +917,7 @@ public class BeanProperty implements ElPropertyValue {
|
||||
public boolean isDateTimeCapable() {
|
||||
return scalarType != null && scalarType.isDateTimeCapable();
|
||||
}
|
||||
|
||||
|
||||
public int getJdbcType() {
|
||||
return scalarType == null ? 0 : scalarType.getJdbcType();
|
||||
}
|
||||
@@ -1020,7 +1023,7 @@ public class BeanProperty implements ElPropertyValue {
|
||||
public boolean isLoadProperty() {
|
||||
return !isTransient || formula;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if this is a version column used for concurrency checking.
|
||||
*/
|
||||
@@ -1183,43 +1186,32 @@ public class BeanProperty implements ElPropertyValue {
|
||||
return name;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void jsonWrite(WriteJsonContext ctx, EntityBean bean) {
|
||||
if (!jsonSerialize) {
|
||||
return;
|
||||
}
|
||||
Object value = getValueIntercept(bean);
|
||||
if (value == null) {
|
||||
ctx.appendNull(name);
|
||||
} else {
|
||||
ctx.appendNameValue(name, scalarType, value);
|
||||
}
|
||||
public void jsonWrite(WriteJson writeJson, EntityBean bean) {
|
||||
if (!jsonSerialize) {
|
||||
return;
|
||||
}
|
||||
Object value = getValueIntercept(bean);
|
||||
if (value == null) {
|
||||
writeJson.gen().writeNull(name);
|
||||
} else {
|
||||
scalarType.jsonWrite(writeJson.gen(), name, value);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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 boolean isIndexed() {
|
||||
return indexed;
|
||||
}
|
||||
|
||||
public String getIndexName() {
|
||||
return indexName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,6 +5,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import javax.json.stream.JsonParser;
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@@ -28,9 +29,7 @@ import com.avaje.ebeaninternal.server.el.ElPropertyChainBuilder;
|
||||
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
|
||||
import com.avaje.ebeaninternal.server.lib.util.StringHelper;
|
||||
import com.avaje.ebeaninternal.server.query.SqlBeanLoad;
|
||||
import com.avaje.ebeaninternal.server.text.json.ReadJsonContext;
|
||||
import com.avaje.ebeaninternal.server.text.json.ReadJsonContext.ReadBeanState;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJsonContext;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJson;
|
||||
|
||||
/**
|
||||
* Property mapped to a List Set or Map.
|
||||
@@ -39,6 +38,8 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(BeanPropertyAssocMany.class);
|
||||
|
||||
private final BeanPropertyAssocManyJsonHelp jsonHelp;
|
||||
|
||||
/**
|
||||
* Join for manyToMany intersection table.
|
||||
*/
|
||||
@@ -90,7 +91,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
/**
|
||||
* Property on the 'child' bean that links back to the 'master'.
|
||||
*/
|
||||
private BeanPropertyAssocOne<?> childMasterProperty;
|
||||
protected BeanPropertyAssocOne<?> childMasterProperty;
|
||||
|
||||
private boolean embeddedExportedProperties;
|
||||
|
||||
@@ -115,6 +116,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
this.intersectionJoin = deploy.createIntersectionTableJoin();
|
||||
this.inverseJoin = deploy.createInverseTableJoin();
|
||||
this.modifyListenMode = deploy.getModifyListenMode();
|
||||
this.jsonHelp = new BeanPropertyAssocManyJsonHelp(this);
|
||||
}
|
||||
|
||||
public void initialise() {
|
||||
@@ -875,7 +877,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
return null != targetDescriptor.getId(otherBean);
|
||||
}
|
||||
|
||||
public void jsonWrite(WriteJsonContext ctx, EntityBean bean) {
|
||||
public void jsonWrite(WriteJson ctx, EntityBean bean) {
|
||||
if(!this.jsonSerialize){
|
||||
return;
|
||||
}
|
||||
@@ -896,37 +898,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public void jsonRead(ReadJsonContext ctx, EntityBean bean){
|
||||
if(!this.jsonDeserialize){
|
||||
return;
|
||||
}
|
||||
if (!ctx.readArrayBegin()) {
|
||||
// the array is null
|
||||
return;
|
||||
}
|
||||
|
||||
Object collection = help.createEmpty(false);
|
||||
BeanCollectionAdd add = getBeanCollectionAdd(collection, null);
|
||||
do {
|
||||
ReadBeanState detailBeanState = targetDescriptor.jsonRead(ctx, name);
|
||||
if (detailBeanState == null){
|
||||
// probably empty array
|
||||
break;
|
||||
}
|
||||
EntityBean detailBean = (EntityBean)detailBeanState.getBean();
|
||||
add.addBean(detailBean);
|
||||
|
||||
if (bean != null && childMasterProperty != null){
|
||||
// bind detail bean back to master via mappedBy property
|
||||
childMasterProperty.setValue(detailBean, bean);
|
||||
detailBeanState.setLoaded(childMasterProperty.getName());
|
||||
}
|
||||
|
||||
if (!ctx.readArrayNext()){
|
||||
break;
|
||||
}
|
||||
} while(true);
|
||||
|
||||
setValue(bean, collection);
|
||||
public void jsonRead(JsonParser parser, EntityBean parentBean) {
|
||||
jsonHelp.jsonRead(parser, parentBean);
|
||||
}
|
||||
}
|
||||
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import javax.json.stream.JsonParser;
|
||||
import javax.json.stream.JsonParser.Event;
|
||||
|
||||
import com.avaje.ebean.bean.BeanCollectionAdd;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.text.TextException;
|
||||
|
||||
public class BeanPropertyAssocManyJsonHelp {
|
||||
|
||||
private final BeanPropertyAssocMany<?> many;
|
||||
|
||||
public BeanPropertyAssocManyJsonHelp(BeanPropertyAssocMany<?> many) {
|
||||
this.many = many;
|
||||
}
|
||||
|
||||
public void jsonRead(JsonParser parser, EntityBean parentBean) {
|
||||
|
||||
if (!this.many.jsonDeserialize || !parser.hasNext()) {
|
||||
return;
|
||||
}
|
||||
Event event = parser.next();
|
||||
if (Event.VALUE_NULL == event) {
|
||||
return;
|
||||
}
|
||||
if (Event.START_ARRAY != event) {
|
||||
throw new TextException("Unexpected token "+event+" - expecting start_array at: "+parser.getLocation());
|
||||
}
|
||||
|
||||
Object collection = many.createEmpty(false);
|
||||
BeanCollectionAdd add = many.getBeanCollectionAdd(collection, null);
|
||||
do {
|
||||
EntityBean detailBean = (EntityBean)many.targetDescriptor.jsonRead(parser, many.name);
|
||||
if (detailBean == null) {
|
||||
// read the entire array
|
||||
break;
|
||||
}
|
||||
add.addBean(detailBean);
|
||||
|
||||
if (parentBean != null && many.childMasterProperty != null) {
|
||||
// bind detail bean back to master via mappedBy property
|
||||
many.childMasterProperty.setValue(detailBean, parentBean);
|
||||
}
|
||||
} while (true);
|
||||
|
||||
many.setValue(parentBean, collection);
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import javax.json.stream.JsonParser;
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import com.avaje.ebean.EbeanServer;
|
||||
@@ -24,8 +25,7 @@ import com.avaje.ebeaninternal.server.el.ElPropertyValue;
|
||||
import com.avaje.ebeaninternal.server.query.SplitName;
|
||||
import com.avaje.ebeaninternal.server.query.SqlBeanLoad;
|
||||
import com.avaje.ebeaninternal.server.query.SqlJoinType;
|
||||
import com.avaje.ebeaninternal.server.text.json.ReadJsonContext;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJsonContext;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJson;
|
||||
|
||||
/**
|
||||
* Property mapped to a joined bean.
|
||||
@@ -831,36 +831,34 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jsonWrite(WriteJsonContext ctx, EntityBean bean) {
|
||||
public void jsonWrite(WriteJson writeJson, EntityBean bean) {
|
||||
|
||||
Object value = getValueIntercept(bean);
|
||||
if (value == null){
|
||||
ctx.beginAssocOneIsNull(name);
|
||||
writeJson.gen().writeNull(name);
|
||||
|
||||
} else {
|
||||
if (ctx.isParentBean(value)){
|
||||
if (writeJson.isParentBean(value)){
|
||||
// bi-directional and already rendered parent
|
||||
|
||||
} else {
|
||||
// Hmmm, not writing complex non-entity bean
|
||||
if (value instanceof EntityBean) {
|
||||
ctx.pushParentBean(bean);
|
||||
ctx.beginAssocOne(name);
|
||||
writeJson.beginAssocOne(name, bean);
|
||||
BeanDescriptor<?> refDesc = descriptor.getBeanDescriptor(value.getClass());
|
||||
refDesc.jsonWrite(ctx, (EntityBean)value);
|
||||
ctx.endAssocOne();
|
||||
ctx.popParentBean();
|
||||
refDesc.jsonWrite(writeJson, (EntityBean)value, name);
|
||||
writeJson.endAssocOne();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@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) {
|
||||
|
||||
@@ -3,15 +3,18 @@ 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.WriteJsonContext;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJson;
|
||||
import com.avaje.ebeaninternal.server.type.CtCompoundProperty;
|
||||
import com.avaje.ebeaninternal.server.type.CtCompoundPropertyElAdapter;
|
||||
import com.avaje.ebeaninternal.server.type.CtCompoundType;
|
||||
@@ -177,15 +180,32 @@ public class BeanPropertyCompound extends BeanProperty {
|
||||
return bean;
|
||||
}
|
||||
|
||||
public void jsonWrite(WriteJsonContext ctx, EntityBean bean) {
|
||||
|
||||
Object valueObject = getValueIntercept(bean);
|
||||
compoundType.jsonWrite(ctx, valueObject, name);
|
||||
public void jsonWrite(WriteJson ctx, EntityBean bean) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import com.avaje.ebean.bean.BeanCollectionAdd;
|
||||
import com.avaje.ebean.bean.BeanCollectionLoader;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.common.BeanSet;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJsonContext;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJson;
|
||||
|
||||
/**
|
||||
* Helper specifically for dealing with Sets.
|
||||
@@ -129,7 +129,7 @@ public final class BeanSetHelp<T> implements BeanCollectionHelp<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public void jsonWrite(WriteJsonContext ctx, String name, Object collection, boolean explicitInclude) {
|
||||
public void jsonWrite(WriteJson ctx, String name, Object collection, boolean explicitInclude) {
|
||||
|
||||
Set<?> set;
|
||||
if (collection instanceof BeanCollection<?>){
|
||||
@@ -148,16 +148,11 @@ public final class BeanSetHelp<T> implements BeanCollectionHelp<T> {
|
||||
set = (Set<?>)collection;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
ctx.beginAssocMany(name);
|
||||
ctx.gen().writeStartArray(name);
|
||||
Iterator<?> it = set.iterator();
|
||||
while (it.hasNext()) {
|
||||
Object detailBean = it.next();
|
||||
if (count++ > 0){
|
||||
ctx.appendComma();
|
||||
}
|
||||
targetDescriptor.jsonWrite(ctx, (EntityBean)detailBean);
|
||||
targetDescriptor.jsonWrite(ctx, (EntityBean)it.next());
|
||||
}
|
||||
ctx.endAssocMany();
|
||||
ctx.gen().writeEnd();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import javax.json.Json;
|
||||
import javax.json.stream.JsonParser;
|
||||
import javax.json.stream.JsonParser.Event;
|
||||
|
||||
public class EJsonReader {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Map<String, Object> parseObject(String json) {
|
||||
return (Map<String, Object>) parse(json);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static List<Object> parseList(String json) {
|
||||
return (List<Object>) parse(json);
|
||||
}
|
||||
|
||||
public static Object parse(String json) {
|
||||
return parse(new StringReader(json));
|
||||
}
|
||||
|
||||
public static Object parse(Reader reader) {
|
||||
return parse(Json.createParser(reader));
|
||||
}
|
||||
|
||||
public static Object parse(JsonParser parser) {
|
||||
return new EJsonReader(parser).parseJson();
|
||||
}
|
||||
|
||||
private final JsonParser parser;
|
||||
|
||||
private final Stack stack = new Stack();
|
||||
|
||||
private Context currentContext;
|
||||
|
||||
|
||||
EJsonReader(JsonParser parser) {
|
||||
this.parser = parser;
|
||||
}
|
||||
|
||||
private void startArray() {
|
||||
stack.push(currentContext);
|
||||
currentContext = new ArrayContext();
|
||||
}
|
||||
|
||||
private void startObject() {
|
||||
stack.push(currentContext);
|
||||
currentContext = new ObjectContext();
|
||||
}
|
||||
|
||||
private void endArray() {
|
||||
end();
|
||||
}
|
||||
|
||||
private void endObject() {
|
||||
end();
|
||||
}
|
||||
|
||||
private void end() {
|
||||
|
||||
if (!stack.isEmpty()) {
|
||||
currentContext = stack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
private void setValue(Object value) {
|
||||
currentContext.setValue(value);
|
||||
}
|
||||
|
||||
private void setValueNull() {
|
||||
currentContext.setValueNull();
|
||||
}
|
||||
|
||||
private Object parseJson() {
|
||||
|
||||
while (parser.hasNext()) {
|
||||
Event event = parser.next();
|
||||
switch (event) {
|
||||
|
||||
case START_ARRAY:
|
||||
startArray();
|
||||
break;
|
||||
|
||||
case START_OBJECT:
|
||||
startObject();
|
||||
break;
|
||||
|
||||
case KEY_NAME:
|
||||
currentContext.setKey(parser.getString());
|
||||
break;
|
||||
|
||||
case VALUE_STRING:
|
||||
setValue(parser.getString());
|
||||
break;
|
||||
|
||||
case VALUE_NUMBER:
|
||||
if (parser.isIntegralNumber()) {
|
||||
setValue(parser.getLong());
|
||||
} else {
|
||||
setValue(parser.getBigDecimal());
|
||||
}
|
||||
break;
|
||||
|
||||
case VALUE_TRUE:
|
||||
setValue(Boolean.TRUE);
|
||||
break;
|
||||
|
||||
case VALUE_FALSE:
|
||||
setValue(Boolean.FALSE);
|
||||
break;
|
||||
|
||||
case VALUE_NULL:
|
||||
setValueNull();
|
||||
break;
|
||||
|
||||
case END_OBJECT:
|
||||
endObject();
|
||||
break;
|
||||
|
||||
case END_ARRAY:
|
||||
endArray();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return currentContext.getValue();
|
||||
}
|
||||
|
||||
private static final class Stack {
|
||||
|
||||
private Context head;
|
||||
|
||||
private void push(Context context) {
|
||||
if (context != null) {
|
||||
context.next = head;
|
||||
head = context;
|
||||
}
|
||||
}
|
||||
|
||||
private Context pop() {
|
||||
if (head == null) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
Context temp = head;
|
||||
head = head.next;
|
||||
return temp;
|
||||
}
|
||||
|
||||
private boolean isEmpty() {
|
||||
return head == null;
|
||||
}
|
||||
}
|
||||
|
||||
private static abstract class Context {
|
||||
Context next;
|
||||
abstract Object getValue();
|
||||
abstract void setKey(String key);
|
||||
abstract void setValue(Object value);
|
||||
abstract void setValueNull();
|
||||
}
|
||||
|
||||
private static class ObjectContext extends Context {
|
||||
|
||||
private String key;
|
||||
|
||||
Map<String, Object> map = new LinkedHashMap<String,Object>();
|
||||
|
||||
Object getValue() {
|
||||
return map;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
void setValue(Object value) {
|
||||
map.put(key, value);
|
||||
}
|
||||
|
||||
void setValueNull() {
|
||||
map.put(key, null);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ArrayContext extends Context {
|
||||
|
||||
List<Object> values = new ArrayList<Object>();
|
||||
|
||||
Object getValue() {
|
||||
return values;
|
||||
}
|
||||
|
||||
void setValue(Object value) {
|
||||
values.add(value);
|
||||
}
|
||||
|
||||
void setValueNull() {
|
||||
}
|
||||
void setKey(String key) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import javax.json.stream.JsonParser;
|
||||
|
||||
public class ReadJson {
|
||||
|
||||
JsonParser parser;
|
||||
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.avaje.ebeaninternal.server.text.json;
|
||||
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
@@ -11,16 +13,19 @@ import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.json.Json;
|
||||
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.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;
|
||||
import com.avaje.ebeaninternal.server.type.EscapeJson;
|
||||
import com.avaje.ebeaninternal.util.ParamTypeHelper;
|
||||
import com.avaje.ebeaninternal.util.ParamTypeHelper.ManyType;
|
||||
import com.avaje.ebeaninternal.util.ParamTypeHelper.TypeInfo;
|
||||
@@ -32,275 +37,215 @@ import com.avaje.ebeaninternal.util.ParamTypeHelper.TypeInfo;
|
||||
*/
|
||||
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){
|
||||
this.server = server;
|
||||
this.dfltValueAdapter = dfltValueAdapter;
|
||||
this.dfltPretty = dfltPretty;
|
||||
}
|
||||
private final SpiEbeanServer server;
|
||||
|
||||
public boolean isSupportedType(Type genericType) {
|
||||
return server.isSupportedType(genericType);
|
||||
}
|
||||
public DJsonContext(SpiEbeanServer server) {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
private ReadJsonSource createReader(Reader jsonReader) {
|
||||
return new ReadJsonSourceReader(jsonReader, 256, 512);
|
||||
}
|
||||
|
||||
public <T> T toBean(Class<T> cls, String json){
|
||||
return toBean(cls, new ReadJsonSourceString(json), null);
|
||||
}
|
||||
|
||||
public <T> T toBean(Class<T> cls, Reader jsonReader) {
|
||||
return toBean(cls, createReader(jsonReader), null);
|
||||
}
|
||||
|
||||
public <T> T toBean(Class<T> cls, String json, JsonReadOptions options){
|
||||
return toBean(cls, new ReadJsonSourceString(json), options);
|
||||
}
|
||||
public boolean isSupportedType(Type genericType) {
|
||||
return server.isSupportedType(genericType);
|
||||
}
|
||||
|
||||
public <T> T toBean(Class<T> cls, Reader jsonReader, JsonReadOptions options) {
|
||||
return toBean(cls, createReader(jsonReader), options);
|
||||
}
|
||||
private JsonParser createReader(Reader jsonReader) {
|
||||
return Json.createParser(jsonReader);
|
||||
}
|
||||
|
||||
private <T> T toBean(Class<T> cls, ReadJsonSource src, JsonReadOptions options){
|
||||
public <T> T toBean(Class<T> cls, String json) {
|
||||
return toBean(cls, new StringReader(json));
|
||||
}
|
||||
|
||||
BeanDescriptor<T> d = getDecriptor(cls);
|
||||
ReadJsonContext ctx = new ReadJsonContext(src, dfltValueAdapter, options);
|
||||
return d.jsonReadBean(ctx, null);
|
||||
}
|
||||
public <T> T toBean(Class<T> cls, Reader jsonReader) {
|
||||
return toBean(cls, createReader(jsonReader));
|
||||
}
|
||||
|
||||
public <T> List<T> toList(Class<T> cls, String json){
|
||||
return toList(cls, new ReadJsonSourceString(json), null);
|
||||
}
|
||||
private <T> T toBean(Class<T> cls, JsonParser parser) {
|
||||
|
||||
public <T> List<T> toList(Class<T> cls, String json, JsonReadOptions options){
|
||||
return toList(cls, new ReadJsonSourceString(json), options);
|
||||
}
|
||||
|
||||
public <T> List<T> toList(Class<T> cls, Reader jsonReader){
|
||||
return toList(cls, createReader(jsonReader), null);
|
||||
}
|
||||
BeanDescriptor<T> d = getDecriptor(cls);
|
||||
return d.jsonRead(parser, null);
|
||||
}
|
||||
|
||||
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, ReadJsonSource src, JsonReadOptions options){
|
||||
|
||||
try {
|
||||
BeanDescriptor<T> d = getDecriptor(cls);
|
||||
|
||||
List<T> list = new ArrayList<T>();
|
||||
|
||||
ReadJsonContext ctx = new ReadJsonContext(src, dfltValueAdapter, options);
|
||||
ctx.readArrayBegin();
|
||||
do {
|
||||
T bean = d.jsonReadBean(ctx, null);
|
||||
if (bean != null){
|
||||
list.add(bean);
|
||||
}
|
||||
if (!ctx.readArrayNext()){
|
||||
break;
|
||||
}
|
||||
} while(true);
|
||||
|
||||
return list;
|
||||
} catch (RuntimeException e){
|
||||
throw new TextException("Error parsing "+src, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Object toObject(Type genericType, String json, JsonReadOptions options) {
|
||||
|
||||
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);
|
||||
|
||||
case LIST:
|
||||
return toList(info.getBeanType(), json, options);
|
||||
|
||||
default:
|
||||
String msg = "ManyType "+manyType+" not supported yet";
|
||||
throw new TextException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
public Object toObject(Type genericType, Reader json, JsonReadOptions options) {
|
||||
|
||||
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);
|
||||
|
||||
case LIST:
|
||||
return toList(info.getBeanType(), json, options);
|
||||
|
||||
default:
|
||||
String msg = "ManyType "+manyType+" not supported yet";
|
||||
throw new TextException(msg);
|
||||
}
|
||||
}
|
||||
public <T> List<T> toList(Class<T> cls, String json) {
|
||||
return toList(cls, new StringReader(json));
|
||||
}
|
||||
|
||||
|
||||
public void toJsonWriter(Object o, Writer writer) {
|
||||
toJsonWriter(o, writer, dfltPretty, null, null);
|
||||
}
|
||||
public <T> List<T> toList(Class<T> cls, Reader jsonReader) {
|
||||
return toList(cls, createReader(jsonReader));
|
||||
}
|
||||
|
||||
public void toJsonWriter(Object o, Writer writer, boolean pretty) {
|
||||
toJsonWriter(o, writer, pretty, null, null);
|
||||
}
|
||||
private <T> List<T> toList(Class<T> cls, JsonParser src) {
|
||||
|
||||
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) {
|
||||
toJsonInternal(o, new WriteJsonBufferWriter(writer), pretty, options, callback);
|
||||
}
|
||||
try {
|
||||
BeanDescriptor<T> d = getDecriptor(cls);
|
||||
|
||||
public String toJsonString(Object o){
|
||||
return toJsonString(o, dfltPretty, null);
|
||||
}
|
||||
List<T> list = new ArrayList<T>();
|
||||
|
||||
public String toJsonString(Object o, boolean pretty){
|
||||
return toJsonString(o, pretty, null);
|
||||
}
|
||||
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() + "]");
|
||||
}
|
||||
|
||||
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){
|
||||
WriteJsonBufferString b = new WriteJsonBufferString();
|
||||
toJsonInternal(o, b, pretty, options, callback);
|
||||
return b.getBufferOutput();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void toJsonInternal(Object o, WriteJsonBuffer buffer, boolean pretty, JsonWriteOptions options, String requestCallback){
|
||||
|
||||
if (o == null){
|
||||
buffer.append("null");
|
||||
} else if (o instanceof Number) {
|
||||
buffer.append(o.toString());
|
||||
} else if (o instanceof Boolean) {
|
||||
buffer.append(o.toString());
|
||||
} else if (o instanceof String) {
|
||||
EscapeJson.escapeQuote(o.toString(), buffer);
|
||||
} else if (o instanceof JsonElement) {
|
||||
|
||||
} else if (o instanceof Map<?,?>){
|
||||
toJsonFromMap((Map<Object,Object>)o, buffer, pretty, options, requestCallback);
|
||||
|
||||
} else if (o instanceof Collection<?>){
|
||||
toJsonFromCollection((Collection<?>)o, buffer, pretty, options, requestCallback);
|
||||
|
||||
do {
|
||||
T bean = d.jsonRead(src, null);
|
||||
if (bean == null) {
|
||||
break;
|
||||
} else {
|
||||
BeanDescriptor<?> d = getDecriptor(o.getClass());
|
||||
WriteJsonContext ctx = new WriteJsonContext(buffer, pretty, dfltValueAdapter, options, requestCallback, server);
|
||||
d.jsonWrite(ctx, (EntityBean)o);
|
||||
ctx.end();
|
||||
list.add(bean);
|
||||
}
|
||||
} while (true);
|
||||
|
||||
return list;
|
||||
|
||||
} catch (RuntimeException e) {
|
||||
throw new TextException("Error parsing " + src, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private <T> void toJsonFromCollection(Collection<T> c, WriteJsonBuffer buffer, boolean pretty, JsonWriteOptions options, String requestCallback){
|
||||
|
||||
Iterator<T> it = c.iterator();
|
||||
if (!it.hasNext()){
|
||||
buffer.append("[]");
|
||||
return;
|
||||
}
|
||||
|
||||
WriteJsonContext ctx = new WriteJsonContext(buffer, pretty, dfltValueAdapter, options, requestCallback, server);
|
||||
public Object toObject(Type genericType, String json) {
|
||||
|
||||
Object o = it.next();
|
||||
BeanDescriptor<?> d = getDecriptor(o.getClass());
|
||||
TypeInfo info = ParamTypeHelper.getTypeInfo(genericType);
|
||||
ManyType manyType = info.getManyType();
|
||||
switch (manyType) {
|
||||
case NONE:
|
||||
return toBean(info.getBeanType(), json);
|
||||
|
||||
ctx.appendArrayBegin();
|
||||
d.jsonWrite(ctx, (EntityBean)o);
|
||||
while (it.hasNext()) {
|
||||
ctx.appendComma();
|
||||
T t = it.next();
|
||||
d.jsonWrite(ctx, (EntityBean)t);
|
||||
}
|
||||
ctx.appendArrayEnd();
|
||||
ctx.end();
|
||||
case LIST:
|
||||
return toList(info.getBeanType(), json);
|
||||
|
||||
default:
|
||||
throw new TextException("Type " + manyType + " not supported");
|
||||
}
|
||||
}
|
||||
|
||||
public Object toObject(Type genericType, Reader json) {
|
||||
|
||||
TypeInfo info = ParamTypeHelper.getTypeInfo(genericType);
|
||||
ManyType manyType = info.getManyType();
|
||||
switch (manyType) {
|
||||
case NONE:
|
||||
return toBean(info.getBeanType(), json);
|
||||
|
||||
case LIST:
|
||||
return toList(info.getBeanType(), json);
|
||||
|
||||
default:
|
||||
throw new TextException("Type " + manyType + " not supported");
|
||||
}
|
||||
}
|
||||
|
||||
public void toJsonWriter(Object o, Writer writer) {
|
||||
toJsonWriter(o, writer, null);
|
||||
}
|
||||
|
||||
|
||||
public void toJsonWriter(Object o, Writer writer, JsonWriteOptions options) {
|
||||
JsonGenerator generator = Json.createGenerator(writer);
|
||||
toJsonInternal(o, generator, options);
|
||||
generator.close();
|
||||
}
|
||||
|
||||
public String toJsonString(Object o) {
|
||||
return toJsonString(o, null);
|
||||
}
|
||||
|
||||
public String toJsonString(Object o, JsonWriteOptions options) {
|
||||
StringWriter writer = new StringWriter(500);
|
||||
JsonGenerator gen = Json.createGenerator(writer);
|
||||
toJsonInternal(o, gen, options);
|
||||
gen.close();
|
||||
return writer.toString();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void toJsonInternal(Object o, JsonGenerator gen, JsonWriteOptions options) {
|
||||
|
||||
if (o == null) {
|
||||
gen.writeNull();
|
||||
} else if (o instanceof Number) {
|
||||
gen.write(((Number) o).doubleValue());
|
||||
} else if (o instanceof Boolean) {
|
||||
gen.write(((Boolean) o).booleanValue());
|
||||
} else if (o instanceof String) {
|
||||
gen.write((String) o);
|
||||
|
||||
// } else if (o instanceof JsonElement) {
|
||||
|
||||
} else if (o instanceof Map<?, ?>) {
|
||||
toJsonFromMap((Map<Object, Object>) o, gen, options);
|
||||
|
||||
} else if (o instanceof Collection<?>) {
|
||||
toJsonFromCollection((Collection<?>) o, null, gen, options);
|
||||
|
||||
} else if (o instanceof EntityBean) {
|
||||
BeanDescriptor<?> d = getDecriptor(o.getClass());
|
||||
WriteJson writeJson = createWriteJson(gen, options);
|
||||
d.jsonWrite(writeJson, (EntityBean)o, null);
|
||||
}
|
||||
}
|
||||
|
||||
private WriteJson createWriteJson(JsonGenerator gen, JsonWriteOptions options) {
|
||||
PathProperties pathProps = (options == null) ? null : options.getPathProperties();
|
||||
return new WriteJson(server, gen, pathProps);
|
||||
}
|
||||
|
||||
private <T> void toJsonFromCollection(Collection<T> c, String key, JsonGenerator gen, JsonWriteOptions options) {
|
||||
|
||||
if (key == null) {
|
||||
gen.writeStartArray();
|
||||
} else {
|
||||
gen.writeStartArray(key);
|
||||
}
|
||||
|
||||
private void toJsonFromMap(Map<Object,Object> map, WriteJsonBuffer buffer, boolean pretty, JsonWriteOptions options, String requestCallback){
|
||||
|
||||
if (map.isEmpty()){
|
||||
buffer.append("{}");
|
||||
return;
|
||||
}
|
||||
|
||||
WriteJsonContext ctx = new WriteJsonContext(buffer, pretty, dfltValueAdapter, options, requestCallback, server);
|
||||
WriteJson writeJson = createWriteJson(gen, options);
|
||||
|
||||
Set<Entry<Object,Object>> entrySet = map.entrySet();
|
||||
Iterator<Entry<Object, Object>> it = entrySet.iterator();
|
||||
|
||||
Entry<Object, Object> entry = it.next();
|
||||
|
||||
ctx.appendObjectBegin();
|
||||
toJsonMapKey(buffer, false, entry.getKey());
|
||||
toJsonMapValue(buffer, pretty, options, requestCallback, entry.getValue());
|
||||
|
||||
while (it.hasNext()) {
|
||||
entry = it.next();
|
||||
ctx.appendComma();
|
||||
toJsonMapKey(buffer, pretty, entry.getKey());
|
||||
toJsonMapValue(buffer, pretty, options, requestCallback, entry.getValue());
|
||||
}
|
||||
ctx.appendObjectEnd();
|
||||
ctx.end();
|
||||
Iterator<T> it = c.iterator();
|
||||
while (it.hasNext()) {
|
||||
T t = it.next();
|
||||
BeanDescriptor<?> d = getDecriptor(t.getClass());
|
||||
d.jsonWrite(writeJson, (EntityBean)t, null);
|
||||
}
|
||||
gen.writeEnd();
|
||||
}
|
||||
|
||||
private void toJsonMapKey(WriteJsonBuffer buffer, boolean pretty, Object key) {
|
||||
if (pretty){
|
||||
buffer.append("\n");
|
||||
}
|
||||
buffer.append("\"");
|
||||
buffer.append(key.toString());
|
||||
buffer.append("\":");
|
||||
}
|
||||
|
||||
private void toJsonMapValue(WriteJsonBuffer buffer, boolean pretty, JsonWriteOptions options, String requestCallback,
|
||||
Object value) {
|
||||
|
||||
if (value == null){
|
||||
buffer.append("null");
|
||||
} else {
|
||||
toJsonInternal(value, buffer, pretty, options, 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();
|
||||
|
||||
WriteJson writeJson = createWriteJson(gen, options);
|
||||
gen.writeStartObject();
|
||||
|
||||
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);
|
||||
while (it.hasNext()) {
|
||||
Entry<Object, Object> entry = it.next();
|
||||
String key = entry.getKey().toString();
|
||||
Object value = entry.getValue();
|
||||
if (value == null) {
|
||||
gen.writeNull(key);
|
||||
} else {
|
||||
if (value instanceof Collection<?>) {
|
||||
toJsonFromCollection((Collection<?>) value, key, gen, options);
|
||||
|
||||
} else if (value instanceof EntityBean) {
|
||||
BeanDescriptor<?> d = getDecriptor(value.getClass());
|
||||
d.jsonWrite(writeJson,(EntityBean) value, key);
|
||||
|
||||
} else {
|
||||
EJson.write(entry, gen);
|
||||
}
|
||||
return d;
|
||||
}
|
||||
}
|
||||
gen.writeEnd();
|
||||
}
|
||||
|
||||
private <T> BeanDescriptor<T> getDecriptor(Class<T> cls) {
|
||||
BeanDescriptor<T> d = server.getBeanDescriptor(cls);
|
||||
if (d == null) {
|
||||
throw new RuntimeException("No BeanDescriptor found for " + cls);
|
||||
}
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,23 +4,23 @@ import com.avaje.ebeaninternal.server.util.ArrayStack;
|
||||
|
||||
public class PathStack extends ArrayStack<String> {
|
||||
|
||||
public String peekFullPath(String key){
|
||||
|
||||
String prefix = peekWithNull();
|
||||
if (prefix != null){
|
||||
return prefix+"."+key;
|
||||
} else {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
public void pushPathKey(String key) {
|
||||
public String peekFullPath(String key) {
|
||||
|
||||
String prefix = peekWithNull();
|
||||
if (prefix != null){
|
||||
key = prefix+"."+key;
|
||||
}
|
||||
push(key);
|
||||
String prefix = peekWithNull();
|
||||
if (prefix != null) {
|
||||
return prefix + "." + key;
|
||||
} else {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
public void pushPathKey(String key) {
|
||||
|
||||
String prefix = peekWithNull();
|
||||
if (prefix != null) {
|
||||
key = prefix + "." + key;
|
||||
}
|
||||
push(key);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
package com.avaje.ebeaninternal.server.text.json;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.json.stream.JsonGenerator;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.text.PathProperties;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
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();
|
||||
|
||||
private final ArrayStack<Object> parentBeans = new ArrayStack<Object>();
|
||||
|
||||
public WriteJson(SpiEbeanServer server, JsonGenerator generator, PathProperties pathProperties){
|
||||
this.server = server;
|
||||
this.generator = generator;
|
||||
this.pathProperties = pathProperties;
|
||||
}
|
||||
|
||||
public JsonGenerator gen() {
|
||||
return generator;
|
||||
}
|
||||
|
||||
public boolean isParentBean(Object bean) {
|
||||
if (parentBeans.isEmpty()) {
|
||||
return false;
|
||||
} else {
|
||||
return parentBeans.contains(bean);
|
||||
}
|
||||
}
|
||||
|
||||
public void pushParentBeanMany(Object parentBean) {
|
||||
parentBeans.push(parentBean);
|
||||
}
|
||||
|
||||
public void popParentBeanMany() {
|
||||
parentBeans.pop();
|
||||
}
|
||||
|
||||
public void beginAssocOne(String key, Object bean) {
|
||||
parentBeans.push(bean);
|
||||
pathStack.pushPathKey(key);
|
||||
}
|
||||
|
||||
public void endAssocOne() {
|
||||
parentBeans.pop();
|
||||
pathStack.pop();
|
||||
}
|
||||
|
||||
public Set<String> getIncludeProperties() {
|
||||
|
||||
if (pathProperties == null) {
|
||||
return null;
|
||||
} else {
|
||||
return pathProperties.get(pathStack.peekWithNull());
|
||||
}
|
||||
}
|
||||
|
||||
public WriteBean createWriteBean(BeanDescriptor<?> desc, EntityBean bean) {
|
||||
|
||||
if (pathProperties == null) {
|
||||
return new WriteBean(desc, bean);
|
||||
}
|
||||
|
||||
boolean explicitAllProps = false;
|
||||
Set<String> currentIncludeProps = pathProperties.get(pathStack.peekWithNull());
|
||||
if (currentIncludeProps != null) {
|
||||
explicitAllProps = currentIncludeProps.contains("*");
|
||||
if (explicitAllProps || currentIncludeProps.isEmpty()) {
|
||||
currentIncludeProps = null;
|
||||
}
|
||||
}
|
||||
return new WriteBean(desc, explicitAllProps, currentIncludeProps, bean);
|
||||
}
|
||||
|
||||
public class WriteBean {
|
||||
|
||||
final boolean explicitAllProps;
|
||||
final Set<String> currentIncludeProps;
|
||||
final BeanDescriptor<?> desc;
|
||||
final EntityBean currentBean;
|
||||
|
||||
WriteBean(BeanDescriptor<?> desc, EntityBean currentBean){
|
||||
this(desc, false, null, currentBean);
|
||||
}
|
||||
|
||||
WriteBean(BeanDescriptor<?> desc, boolean explicitAllProps, Set<String> currentIncludeProps, EntityBean currentBean) {
|
||||
super();
|
||||
this.desc = desc;
|
||||
this.currentBean = currentBean;
|
||||
this.explicitAllProps = explicitAllProps;
|
||||
this.currentIncludeProps = currentIncludeProps;
|
||||
}
|
||||
|
||||
private boolean isReferenceOnly() {
|
||||
return !explicitAllProps && currentIncludeProps == null && currentBean._ebean_getIntercept().isReference();
|
||||
}
|
||||
|
||||
private boolean isIncludeProperty(BeanProperty prop) {
|
||||
if (explicitAllProps)
|
||||
return true;
|
||||
if (currentIncludeProps != null) {
|
||||
// explicitly controlled by pathProperties
|
||||
return currentIncludeProps.contains(prop.getName());
|
||||
} else {
|
||||
// include only loaded properties
|
||||
return currentBean._ebean_getIntercept().isLoadedProperty(prop.getPropertyIndex());
|
||||
}
|
||||
}
|
||||
|
||||
public void write(WriteJson writeJson) {
|
||||
//EntityBean bean = writeJson.getBean();
|
||||
BeanProperty beanProp = desc.getIdProperty();
|
||||
if (beanProp != null) {
|
||||
if (isIncludeProperty(beanProp)) {
|
||||
beanProp.jsonWrite(writeJson, currentBean);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isReferenceOnly()) {
|
||||
// render all the properties and invoke lazy loading if required
|
||||
BeanProperty[] props = desc.propertiesNonTransient();
|
||||
for (int j = 0; j < props.length; j++) {
|
||||
System.out.println("bean "+ currentBean+" prop:"+props[j]);
|
||||
if (isIncludeProperty(props[j])) {
|
||||
props[j].jsonWrite(writeJson, currentBean);
|
||||
}
|
||||
}
|
||||
props = desc.propertiesTransient();
|
||||
for (int j = 0; j < props.length; j++) {
|
||||
if (isIncludeProperty(props[j])) {
|
||||
props[j].jsonWrite(writeJson, currentBean);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Boolean includeMany(String key) {
|
||||
if (pathProperties != null) {
|
||||
String fullPath = pathStack.peekFullPath(key);
|
||||
return pathProperties.hasPath(fullPath);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void toJson(String name, Collection<?> c) {
|
||||
|
||||
beginAssocMany(name);
|
||||
|
||||
Iterator<?> it = c.iterator();
|
||||
while (it.hasNext()) {
|
||||
EntityBean o = (EntityBean) it.next();
|
||||
BeanDescriptor<?> d = getDecriptor(o.getClass());
|
||||
d.jsonWrite(this, o, null);
|
||||
}
|
||||
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 beginAssocMany(String key) {
|
||||
pathStack.pushPathKey(key);
|
||||
generator.writeStartArray(key);
|
||||
}
|
||||
|
||||
public void endAssocMany() {
|
||||
pathStack.pop();
|
||||
generator.writeEnd();
|
||||
}
|
||||
|
||||
public void writeStartObject(String key) {
|
||||
if (key == null) {
|
||||
generator.writeStartObject();
|
||||
} else {
|
||||
generator.writeStartObject(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();
|
||||
}
|
||||
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);
|
||||
|
||||
@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();
|
||||
} 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).
|
||||
|
||||
@@ -5,10 +5,12 @@ 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;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJsonBuffer;
|
||||
|
||||
/**
|
||||
* Describes a scalar type.
|
||||
@@ -183,14 +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 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,8 +7,9 @@ import java.sql.Date;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import com.avaje.ebean.text.json.JsonValueAdapter;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJsonBuffer;
|
||||
import javax.json.stream.JsonGenerator;
|
||||
import javax.json.stream.JsonParser;
|
||||
import javax.json.stream.JsonParser.Event;
|
||||
|
||||
/**
|
||||
* Base class for Date types.
|
||||
@@ -62,22 +63,22 @@ public abstract class ScalarTypeBaseDate<T> extends ScalarTypeBase<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String jsonToString(T value, JsonValueAdapter ctx) {
|
||||
Date date = convertToDate(value);
|
||||
return ctx.jsonFromDate(date);
|
||||
public Object jsonRead(JsonParser ctx, Event event) {
|
||||
if (ctx.isIntegralNumber()) {
|
||||
return parseDateTime(ctx.getLong());
|
||||
} else {
|
||||
String string = ctx.getString();
|
||||
throw new RuntimeException("convert "+string);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jsonWrite(WriteJsonBuffer buffer, T value, JsonValueAdapter ctx) {
|
||||
String s = jsonToString(value, ctx);
|
||||
buffer.append(s);
|
||||
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 T jsonFromString(String value, JsonValueAdapter ctx) {
|
||||
Date ts = ctx.jsonToDate(value);
|
||||
return convertFromDate(ts);
|
||||
}
|
||||
|
||||
public Object readData(DataInput dataInput) throws IOException {
|
||||
if (!dataInput.readBoolean()) {
|
||||
|
||||
@@ -7,8 +7,9 @@ import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.sql.Types;
|
||||
|
||||
import com.avaje.ebean.text.json.JsonValueAdapter;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJsonBuffer;
|
||||
import javax.json.stream.JsonGenerator;
|
||||
import javax.json.stream.JsonParser;
|
||||
import javax.json.stream.JsonParser.Event;
|
||||
|
||||
/**
|
||||
* Base type for DateTime types.
|
||||
@@ -19,6 +20,8 @@ public abstract class ScalarTypeBaseDateTime<T> extends ScalarTypeBase<T> {
|
||||
super(type, jdbcNative, jdbcType);
|
||||
}
|
||||
|
||||
public abstract long convertToMillis(Object value);
|
||||
|
||||
public abstract Timestamp convertToTimestamp(T t);
|
||||
|
||||
public abstract T convertFromTimestamp(Timestamp ts);
|
||||
@@ -42,6 +45,23 @@ public abstract class ScalarTypeBaseDateTime<T> extends ScalarTypeBase<T> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object jsonRead(JsonParser ctx, Event event) {
|
||||
if (ctx.isIntegralNumber()) {
|
||||
long millis = ctx.getLong();
|
||||
return parseDateTime(millis);
|
||||
} else {
|
||||
String string = ctx.getString();
|
||||
throw new RuntimeException("convert "+string);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
|
||||
long millis = convertToMillis(value);
|
||||
ctx.write(name, millis);
|
||||
}
|
||||
|
||||
public String formatValue(T t) {
|
||||
Timestamp ts = convertToTimestamp(t);
|
||||
return ts.toString();
|
||||
@@ -60,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()) {
|
||||
|
||||
@@ -6,9 +6,11 @@ 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;
|
||||
|
||||
/**
|
||||
* Base ScalarType for types which converts to and from a VARCHAR database
|
||||
@@ -81,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;
|
||||
@@ -115,4 +104,13 @@ public abstract class ScalarTypeBaseVarchar<T> extends ScalarTypeBase<T> {
|
||||
dataOutput.writeUTF(s);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object jsonRead(JsonParser ctx, Event event) {
|
||||
return parse(ctx.getString());
|
||||
}
|
||||
|
||||
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
|
||||
ctx.write(name, format(value));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,14 @@ import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import javax.json.stream.JsonGenerator;
|
||||
import javax.json.stream.JsonParser;
|
||||
import javax.json.stream.JsonParser.Event;
|
||||
|
||||
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
|
||||
|
||||
/**
|
||||
@@ -74,5 +79,15 @@ public class ScalarTypeBigDecimal extends ScalarTypeBase<BigDecimal> {
|
||||
public boolean isDateTimeCapable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object jsonRead(JsonParser ctx, Event event) {
|
||||
return ctx.getBigDecimal();
|
||||
}
|
||||
|
||||
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
|
||||
ctx.write(name, (BigDecimal)value);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -3,9 +3,14 @@ package com.avaje.ebeaninternal.server.type;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import javax.json.stream.JsonGenerator;
|
||||
import javax.json.stream.JsonParser;
|
||||
import javax.json.stream.JsonParser.Event;
|
||||
|
||||
import com.avaje.ebean.text.TextException;
|
||||
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
|
||||
|
||||
@@ -286,6 +291,15 @@ public class ScalarTypeBoolean {
|
||||
dataOutput.writeBoolean(val.booleanValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object jsonRead(JsonParser ctx, Event event) {
|
||||
return Event.VALUE_TRUE == event ? Boolean.TRUE : Boolean.FALSE;
|
||||
}
|
||||
|
||||
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
|
||||
ctx.write(name, (Boolean)value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,6 +6,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;
|
||||
|
||||
@@ -37,9 +41,18 @@ public class ScalarTypeByte extends ScalarTypeBase<Byte> {
|
||||
public Byte toBeanType(Object value) {
|
||||
return BasicTypeConverter.toByte(value);
|
||||
}
|
||||
|
||||
|
||||
public String formatValue(Byte t) {
|
||||
@Override
|
||||
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
|
||||
throw new TextException("Not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object jsonRead(JsonParser ctx, Event event) {
|
||||
throw new TextException("Not supported");
|
||||
}
|
||||
|
||||
public String formatValue(Byte t) {
|
||||
return t.toString();
|
||||
}
|
||||
|
||||
|
||||
@@ -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.TextException;
|
||||
|
||||
/**
|
||||
@@ -41,7 +45,17 @@ public abstract class ScalarTypeBytesBase extends ScalarTypeBase<byte[]> {
|
||||
}
|
||||
|
||||
|
||||
public String formatValue(byte[] t) {
|
||||
@Override
|
||||
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
|
||||
throw new TextException("Not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object jsonRead(JsonParser ctx, Event event) {
|
||||
throw new TextException("Not supported");
|
||||
}
|
||||
|
||||
public String formatValue(byte[] t) {
|
||||
throw new TextException("Not supported");
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,11 @@ import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.avaje.ebean.text.json.JsonValueAdapter;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJsonBuffer;
|
||||
import javax.json.stream.JsonGenerator;
|
||||
import javax.json.stream.JsonParser;
|
||||
import javax.json.stream.JsonParser.Event;
|
||||
|
||||
import com.avaje.ebean.text.TextException;
|
||||
|
||||
/**
|
||||
* Encrypted ScalarType that wraps a byte[] types.
|
||||
@@ -65,6 +68,16 @@ public class ScalarTypeBytesEncrypted implements ScalarType<byte[]> {
|
||||
baseType.loadIgnore(dataReader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
|
||||
throw new TextException("Not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object jsonRead(JsonParser ctx, Event event) {
|
||||
throw new TextException("Not supported");
|
||||
}
|
||||
|
||||
public String format(Object v) {
|
||||
throw new RuntimeException("Not used");
|
||||
}
|
||||
@@ -100,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];
|
||||
|
||||
@@ -39,6 +39,11 @@ public class ScalarTypeCalendar extends ScalarTypeBaseDateTime<Calendar> {
|
||||
return calendar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long convertToMillis(Object value) {
|
||||
return ((Calendar) value).getTimeInMillis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Timestamp convertToTimestamp(Calendar t) {
|
||||
return new Timestamp(t.getTimeInMillis());
|
||||
|
||||
@@ -3,7 +3,9 @@ package com.avaje.ebeaninternal.server.type;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import com.avaje.ebean.text.json.JsonValueAdapter;
|
||||
import javax.json.stream.JsonParser;
|
||||
import javax.json.stream.JsonParser.Event;
|
||||
|
||||
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
|
||||
|
||||
/**
|
||||
@@ -59,15 +61,11 @@ 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);
|
||||
public Object jsonRead(JsonParser ctx, Event event) {
|
||||
return ctx.getString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String jsonToString(Character value, JsonValueAdapter ctx) {
|
||||
return EscapeJson.escapeQuote(value.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,7 +3,10 @@ package com.avaje.ebeaninternal.server.type;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import com.avaje.ebean.text.json.JsonValueAdapter;
|
||||
import javax.json.stream.JsonGenerator;
|
||||
import javax.json.stream.JsonParser;
|
||||
import javax.json.stream.JsonParser.Event;
|
||||
|
||||
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
|
||||
|
||||
/**
|
||||
@@ -59,15 +62,13 @@ 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));
|
||||
public Object jsonRead(JsonParser ctx, Event event) {
|
||||
return ctx.getString().toCharArray();
|
||||
}
|
||||
|
||||
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
|
||||
ctx.write(name, String.valueOf(value));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.type;
|
||||
|
||||
import javax.json.stream.JsonGenerator;
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
/**
|
||||
@@ -42,6 +43,10 @@ public class ScalarTypeClass extends ScalarTypeBaseVarchar<Class> {
|
||||
throw new PersistenceException(msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
|
||||
ctx.write(name, formatValue((Class<?>)value));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,10 @@ package com.avaje.ebeaninternal.server.type;
|
||||
|
||||
import java.util.Currency;
|
||||
|
||||
import javax.json.stream.JsonGenerator;
|
||||
import javax.json.stream.JsonParser;
|
||||
import javax.json.stream.JsonParser.Event;
|
||||
|
||||
/**
|
||||
* ScalarType for java.util.Currency which converts to and from a VARCHAR database column.
|
||||
*/
|
||||
@@ -33,5 +37,13 @@ public class ScalarTypeCurrency extends ScalarTypeBaseVarchar<Currency> {
|
||||
public Currency parse(String value) {
|
||||
return Currency.getInstance(value);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object jsonRead(JsonParser ctx, Event event) {
|
||||
return parse(ctx.getString());
|
||||
}
|
||||
|
||||
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
|
||||
ctx.write(name, formatValue((Currency)value));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,8 +14,13 @@ public class ScalarTypeDate extends ScalarTypeBaseDate<java.sql.Date> {
|
||||
public ScalarTypeDate() {
|
||||
super(Date.class, true, Types.DATE);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long convertToMillis(Object value) {
|
||||
return ((Date)value).getTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date convertFromDate(Date date) {
|
||||
return date;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,11 @@ import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.Currency;
|
||||
|
||||
import javax.json.stream.JsonGenerator;
|
||||
import javax.json.stream.JsonParser;
|
||||
import javax.json.stream.JsonParser.Event;
|
||||
|
||||
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
|
||||
|
||||
@@ -82,4 +87,13 @@ public class ScalarTypeDouble extends ScalarTypeBase<Double> {
|
||||
dataOutput.writeDouble(value.doubleValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object jsonRead(JsonParser ctx, Event event) {
|
||||
return ctx.getBigDecimal().doubleValue();
|
||||
}
|
||||
|
||||
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
|
||||
ctx.write(name, (Double)value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,9 @@ import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.avaje.ebean.text.json.JsonValueAdapter;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJsonBuffer;
|
||||
import javax.json.stream.JsonGenerator;
|
||||
import javax.json.stream.JsonParser;
|
||||
import javax.json.stream.JsonParser.Event;
|
||||
|
||||
public class ScalarTypeEncryptedWrapper<T> implements ScalarType<T> {
|
||||
|
||||
@@ -31,7 +32,12 @@ public class ScalarTypeEncryptedWrapper<T> implements ScalarType<T> {
|
||||
public boolean isDirty(Object value) {
|
||||
return wrapped.isDirty(value);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object jsonRead(JsonParser ctx, Event event) {
|
||||
return wrapped.jsonRead(ctx, event);
|
||||
}
|
||||
|
||||
public Object readData(DataInput dataInput) throws IOException {
|
||||
return wrapped.readData(dataInput);
|
||||
}
|
||||
@@ -113,17 +119,8 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,11 @@ 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,15 +228,16 @@ public class ScalarTypeEnumStandard {
|
||||
public boolean isDateTimeCapable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object jsonFromString(String value, JsonValueAdapter ctx) {
|
||||
return parse(value);
|
||||
public Object jsonRead(JsonParser ctx, Event event) {
|
||||
|
||||
String val = ctx.getString();
|
||||
return parse(val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String jsonToString(Object value, JsonValueAdapter ctx) {
|
||||
return EscapeJson.escapeQuote(format(value));
|
||||
|
||||
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
|
||||
ctx.write(name, formatValue(value));
|
||||
}
|
||||
|
||||
public Object readData(DataInput dataInput) throws IOException {
|
||||
|
||||
@@ -6,6 +6,10 @@ import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import javax.json.stream.JsonGenerator;
|
||||
import javax.json.stream.JsonParser;
|
||||
import javax.json.stream.JsonParser.Event;
|
||||
|
||||
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
|
||||
|
||||
/**
|
||||
@@ -81,4 +85,13 @@ public class ScalarTypeFloat extends ScalarTypeBase<Float> {
|
||||
dataOutput.writeFloat(value.floatValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object jsonRead(JsonParser ctx, Event event) {
|
||||
return ctx.getBigDecimal().floatValue();
|
||||
}
|
||||
|
||||
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
|
||||
ctx.write(name, (Float)value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,11 @@ 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;
|
||||
|
||||
/**
|
||||
@@ -63,12 +66,13 @@ public class ScalarTypeInteger extends ScalarTypeBase<Integer> {
|
||||
public boolean isDateTimeCapable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.sql.Date;
|
||||
import java.sql.Types;
|
||||
|
||||
import org.joda.time.DateMidnight;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
|
||||
|
||||
@@ -19,6 +20,11 @@ public class ScalarTypeJodaDateMidnight extends ScalarTypeBaseDate<DateMidnight>
|
||||
super(DateMidnight.class, false, Types.DATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long convertToMillis(Object value) {
|
||||
return ((DateMidnight) value).getMillis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DateMidnight convertFromDate(Date ts) {
|
||||
return new DateMidnight(ts.getTime());
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.sql.Timestamp;
|
||||
import java.sql.Types;
|
||||
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.LocalDate;
|
||||
|
||||
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
|
||||
|
||||
@@ -16,6 +17,11 @@ public class ScalarTypeJodaDateTime extends ScalarTypeBaseDateTime<DateTime> {
|
||||
super(DateTime.class, false, Types.TIMESTAMP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long convertToMillis(Object value) {
|
||||
return ((DateTime) value).getMillis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DateTime convertFromTimestamp(Timestamp ts) {
|
||||
return new DateTime(ts.getTime());
|
||||
|
||||
@@ -17,6 +17,11 @@ public class ScalarTypeJodaLocalDate extends ScalarTypeBaseDate<LocalDate> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public long convertToMillis(Object value) {
|
||||
return ((LocalDate)value).toDateMidnight().getMillis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDate convertFromDate(Date ts) {
|
||||
return new LocalDate(((java.util.Date)ts).getTime());
|
||||
}
|
||||
|
||||
@@ -16,7 +16,14 @@ public class ScalarTypeJodaLocalDateTime extends ScalarTypeBaseDateTime<LocalDat
|
||||
super(LocalDateTime.class, false, Types.TIMESTAMP);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long convertToMillis(Object value) {
|
||||
return ((LocalDateTime)value).toDateTime().getMillis();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public LocalDateTime convertFromTimestamp(Timestamp ts) {
|
||||
return new LocalDateTime(ts.getTime());
|
||||
}
|
||||
|
||||
@@ -7,6 +7,10 @@ import java.sql.SQLException;
|
||||
import java.sql.Time;
|
||||
import java.sql.Types;
|
||||
|
||||
import javax.json.stream.JsonGenerator;
|
||||
import javax.json.stream.JsonParser;
|
||||
import javax.json.stream.JsonParser.Event;
|
||||
|
||||
import org.joda.time.DateTimeZone;
|
||||
import org.joda.time.LocalTime;
|
||||
|
||||
@@ -20,7 +24,7 @@ public class ScalarTypeJodaLocalTime extends ScalarTypeBase<LocalTime> {
|
||||
public ScalarTypeJodaLocalTime() {
|
||||
super(LocalTime.class, false, Types.TIME);
|
||||
}
|
||||
|
||||
|
||||
public void bind(DataBind b, LocalTime value) throws SQLException {
|
||||
if (value == null){
|
||||
b.setNull(Types.TIME);
|
||||
@@ -61,8 +65,24 @@ public class ScalarTypeJodaLocalTime extends ScalarTypeBase<LocalTime> {
|
||||
public LocalTime parse(String value) {
|
||||
return new LocalTime(value);
|
||||
}
|
||||
|
||||
public LocalTime parseDateTime(long systemTimeMillis) {
|
||||
|
||||
@Override
|
||||
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
|
||||
ctx.write(value.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object jsonRead(JsonParser ctx, Event event) {
|
||||
if (ctx.isIntegralNumber()) {
|
||||
long millis = ctx.getLong();
|
||||
return parseDateTime(millis);
|
||||
} else {
|
||||
String string = ctx.getString();
|
||||
throw new RuntimeException("convert "+string);
|
||||
}
|
||||
}
|
||||
|
||||
public LocalTime parseDateTime(long systemTimeMillis) {
|
||||
return new LocalTime(systemTimeMillis);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,10 @@ import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import javax.json.stream.JsonGenerator;
|
||||
import javax.json.stream.JsonParser;
|
||||
import javax.json.stream.JsonParser.Event;
|
||||
|
||||
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
|
||||
|
||||
/**
|
||||
@@ -73,4 +77,13 @@ public class ScalarTypeLong extends ScalarTypeBase<Long> {
|
||||
dataOutput.writeLong(value.longValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object jsonRead(JsonParser ctx, Event event) {
|
||||
return ctx.getLong();
|
||||
}
|
||||
|
||||
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
|
||||
ctx.write(name, (Long)value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,10 @@ import java.math.BigInteger;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import javax.json.stream.JsonGenerator;
|
||||
import javax.json.stream.JsonParser;
|
||||
import javax.json.stream.JsonParser.Event;
|
||||
|
||||
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
|
||||
|
||||
/**
|
||||
@@ -80,4 +84,13 @@ public class ScalarTypeMathBigInteger extends ScalarTypeBase<BigInteger> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object jsonRead(JsonParser ctx, Event event) {
|
||||
return ctx.getBigDecimal().toBigInteger();
|
||||
}
|
||||
|
||||
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
|
||||
ctx.write(name, (BigInteger)value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,6 +6,10 @@ import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.json.stream.JsonGenerator;
|
||||
import javax.json.stream.JsonParser;
|
||||
import javax.json.stream.JsonParser.Event;
|
||||
|
||||
import com.avaje.ebean.config.dbplatform.PostgresPlatform;
|
||||
|
||||
/**
|
||||
@@ -63,6 +67,17 @@ public class ScalarTypePostgresHstore extends ScalarTypeBase<Map> {
|
||||
public Map toBeanType(Object value) {
|
||||
return (Map)value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object jsonRead(JsonParser ctx, Event event) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String formatValue(Map v) {
|
||||
|
||||
@@ -6,6 +6,10 @@ import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import javax.json.stream.JsonGenerator;
|
||||
import javax.json.stream.JsonParser;
|
||||
import javax.json.stream.JsonParser.Event;
|
||||
|
||||
import com.avaje.ebean.text.TextException;
|
||||
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
|
||||
|
||||
@@ -74,4 +78,13 @@ public class ScalarTypeShort extends ScalarTypeBase<Short> {
|
||||
dataOutput.writeShort(value.shortValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object jsonRead(JsonParser ctx, Event event) {
|
||||
return (short)ctx.getInt();
|
||||
}
|
||||
|
||||
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
|
||||
ctx.write(name, (Short)value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,11 @@ import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import com.avaje.ebean.text.json.JsonValueAdapter;
|
||||
import javax.json.stream.JsonGenerator;
|
||||
import javax.json.stream.JsonParser;
|
||||
import javax.json.stream.JsonParser.Event;
|
||||
|
||||
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJsonBuffer;
|
||||
|
||||
/**
|
||||
* ScalarType for String.
|
||||
@@ -56,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;
|
||||
@@ -92,5 +77,12 @@ public class ScalarTypeString extends ScalarTypeBase<String> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object jsonRead(JsonParser ctx, Event event) {
|
||||
return ctx.getString();
|
||||
}
|
||||
|
||||
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
|
||||
ctx.write(name, (String)value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,10 @@ import java.sql.SQLException;
|
||||
import java.sql.Time;
|
||||
import java.sql.Types;
|
||||
|
||||
import javax.json.stream.JsonGenerator;
|
||||
import javax.json.stream.JsonParser;
|
||||
import javax.json.stream.JsonParser.Event;
|
||||
|
||||
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
|
||||
|
||||
/**
|
||||
@@ -75,5 +79,15 @@ public class ScalarTypeTime extends ScalarTypeBase<Time> {
|
||||
dataOutput.writeUTF(format(value));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object jsonRead(JsonParser ctx, Event event) {
|
||||
return parse(ctx.getString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
|
||||
ctx.write(name, value.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,6 +15,11 @@ public class ScalarTypeTimestamp extends ScalarTypeBaseDateTime<Timestamp> {
|
||||
super(Timestamp.class, true, Types.TIMESTAMP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long convertToMillis(Object value) {
|
||||
return ((Timestamp)value).getTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Timestamp convertFromTimestamp(Timestamp ts) {
|
||||
return ts;
|
||||
|
||||
@@ -3,6 +3,9 @@ package com.avaje.ebeaninternal.server.type;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import javax.json.stream.JsonParser;
|
||||
import javax.json.stream.JsonParser.Event;
|
||||
|
||||
import com.avaje.ebean.text.TextException;
|
||||
|
||||
/**
|
||||
@@ -40,4 +43,10 @@ public class ScalarTypeURL extends ScalarTypeBaseVarchar<URL> {
|
||||
throw new TextException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object jsonRead(JsonParser ctx, Event event) {
|
||||
return parse(ctx.getString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,6 +11,10 @@ import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.json.stream.JsonGenerator;
|
||||
import javax.json.stream.JsonParser;
|
||||
import javax.json.stream.JsonParser.Event;
|
||||
|
||||
public class ScalarTypeUUIDBinary extends ScalarTypeBase<UUID> {
|
||||
|
||||
protected ScalarTypeUUIDBinary() {
|
||||
@@ -138,4 +142,14 @@ public class ScalarTypeUUIDBinary extends ScalarTypeBase<UUID> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object jsonRead(JsonParser ctx, Event event) {
|
||||
return UUID.fromString(ctx.getString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jsonWrite(JsonGenerator ctx, String name, Object value) {
|
||||
ctx.write(name, value.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@ package com.avaje.ebeaninternal.server.type;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.json.stream.JsonParser;
|
||||
import javax.json.stream.JsonParser.Event;
|
||||
|
||||
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
|
||||
|
||||
/**
|
||||
@@ -44,4 +47,9 @@ public class ScalarTypeUUIDVarchar extends ScalarTypeBaseVarchar<UUID> {
|
||||
return UUID.fromString(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object jsonRead(JsonParser ctx, Event event) {
|
||||
return UUID.fromString(ctx.getString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,7 +17,12 @@ public class ScalarTypeUtilDate {
|
||||
public TimestampType() {
|
||||
super(java.util.Date.class, false, Types.TIMESTAMP);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long convertToMillis(Object value) {
|
||||
return BasicTypeConverter.toTimestamp(value).getTime();
|
||||
}
|
||||
|
||||
public java.util.Date read(DataReader dataReader) throws SQLException {
|
||||
Timestamp timestamp = dataReader.getTimestamp();
|
||||
if (timestamp == null) {
|
||||
@@ -69,7 +74,15 @@ public class ScalarTypeUtilDate {
|
||||
super(Date.class, false, Types.DATE);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long convertToMillis(Object value) {
|
||||
java.sql.Date date = BasicTypeConverter.toDate(value);
|
||||
return date.getTime();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Date convertFromDate(java.sql.Date ts) {
|
||||
return new java.util.Date(ts.getTime());
|
||||
}
|
||||
|
||||
@@ -5,9 +5,11 @@ import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import javax.json.stream.JsonGenerator;
|
||||
import javax.json.stream.JsonParser;
|
||||
import javax.json.stream.JsonParser.Event;
|
||||
|
||||
import com.avaje.ebean.config.ScalarTypeConverter;
|
||||
import com.avaje.ebean.text.json.JsonValueAdapter;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJsonBuffer;
|
||||
|
||||
/**
|
||||
* A ScalarType that uses a ScalarTypeConverter to convert to and from another
|
||||
@@ -165,20 +167,19 @@ 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);
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Object jsonRead(JsonParser ctx, Event event) {
|
||||
Object object = scalarType.jsonRead(ctx, event);
|
||||
return converter.wrapValue((S)object);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jsonWrite(JsonGenerator ctx, String name, Object beanValue) {
|
||||
@SuppressWarnings("unchecked")
|
||||
S unwrapValue = converter.unwrapValue((B)beanValue);
|
||||
scalarType.jsonWrite(ctx, name, unwrapValue);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user