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:
@@ -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;
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user