Refactor rename MutableHash to MutableValueInfo (and subsequent rename on methods etc)

This commit is contained in:
rbygrave committed 2021-07-29 13:20:30 +12:00
1 parent 5ad8e7ead4
commit 2bc5d3d325
8 files changed
+107 -74

No files matched your search

@@ -97,9 +97,9 @@ public final class EntityBeanIntercept implements Serializable {
private int sortOrder; private int sortOrder;
/** /**
* Holds MD5 hash of json loaded jackson beans. * Holds information of json loaded jackson beans (e.g. the original json or checksum).
*/ */
private MutableHash[] mutableHash; private MutableValueInfo[] mutableInfo;
/** /**
* Holds json content determined at point of dirty check. * Holds json content determined at point of dirty check.
@@ -247,9 +247,9 @@ public final class EntityBeanIntercept implements Serializable {
if (dirty) { if (dirty) {
return true; return true;
} }
if (mutableHash != null) { if (mutableInfo != null) {
for (int i = 0; i < mutableHash.length; i++) { for (int i = 0; i < mutableInfo.length; i++) {
if (mutableHash[i] != null && !mutableHash[i].isEqualToObject(owner._ebean_getField(i))) { if (mutableInfo[i] != null && !mutableInfo[i].isEqualToObject(owner._ebean_getField(i))) {
dirty = true; dirty = true;
break; break;
} }
@@ -472,7 +472,7 @@ public final class EntityBeanIntercept implements Serializable {
public Object getOrigValue(int propertyIndex) { public Object getOrigValue(int propertyIndex) {
if ((flags[propertyIndex] & (FLAG_ORIG_VALUE_SET | FLAG_MUTABLE_HASH_SET)) == FLAG_MUTABLE_HASH_SET) { if ((flags[propertyIndex] & (FLAG_ORIG_VALUE_SET | FLAG_MUTABLE_HASH_SET)) == FLAG_MUTABLE_HASH_SET) {
// mutable hash set, but not ORIG_VALUE // mutable hash set, but not ORIG_VALUE
setOriginalValue(propertyIndex, mutableHash[propertyIndex].get()); setOriginalValue(propertyIndex, mutableInfo[propertyIndex].get());
} }
if (origValues == null) { if (origValues == null) {
return null; return null;
@@ -1174,7 +1174,7 @@ public final class EntityBeanIntercept implements Serializable {
private boolean isChangedProp(int i) { private boolean isChangedProp(int i) {
if ((flags[i] & FLAG_CHANGED_PROP) != 0) { if ((flags[i] & FLAG_CHANGED_PROP) != 0) {
return true; return true;
} else if (mutableHash == null || mutableHash[i] == null || mutableHash[i].isEqualToObject(owner._ebean_getField(i))) { } else if (mutableInfo == null || mutableInfo[i] == null || mutableInfo[i].isEqualToObject(owner._ebean_getField(i))) {
return false; return false;
} else { } else {
// mark for change // mark for change
@@ -1184,22 +1184,38 @@ public final class EntityBeanIntercept implements Serializable {
} }
} }
public MutableHash mutableHash(int propertyIndex) { /**
return mutableHash == null ? null : mutableHash[propertyIndex]; * Return the MutableValueInfo for the given property or null.
*/
public MutableValueInfo mutableInfo(int propertyIndex) {
return mutableInfo == null ? null : mutableInfo[propertyIndex];
} }
public void mutableHash(int propertyIndex, MutableHash content) { /**
if (mutableHash == null) { * Set the MutableValueInfo for the given property.
mutableHash = new MutableHash[flags.length]; */
public void mutableInfo(int propertyIndex, MutableValueInfo info) {
if (mutableInfo == null) {
mutableInfo = new MutableValueInfo[flags.length];
} }
flags[propertyIndex] |= FLAG_MUTABLE_HASH_SET; flags[propertyIndex] |= FLAG_MUTABLE_HASH_SET;
mutableHash[propertyIndex] = content; mutableInfo[propertyIndex] = info;
} }
/**
* Return the [json] content of a mutable value.
*/
public String mutableContent(int propertyIndex) { public String mutableContent(int propertyIndex) {
return mutableContent == null ? null : mutableContent[propertyIndex]; return mutableContent == null ? null : mutableContent[propertyIndex];
} }
/**
* Set the [json] content of a mutable property.
* <p>
* Set here as the mutable property dirty detection is based on json content comparison.
* We only want to perform the json serialisation once so storing it here as part of
* dirty detection so that we can get it back to bind in insert or update etc.
*/
public void mutableContent(int propertyIndex, String content) { public void mutableContent(int propertyIndex, String content) {
if (mutableContent == null) { if (mutableContent == null) {
mutableContent = new String[flags.length]; mutableContent = new String[flags.length];
@@ -1,29 +0,0 @@
package io.ebean.bean;
/**
* Interface to for mutable information in EntityBeanIntercept.
*/
public interface MutableHash {
/**
* Compares the given json to an internal value. Can be a MD5 hash or a plain JSON string.
*
* @return true if the value matches the hash.
*/
boolean isEqualToJson(String json);
/**
* Compares the given object to an internal value. Required for proper changelog/beanState support.
* The implementation can serialize the object and compare it against the original json.
*/
boolean isEqualToObject(Object obj);
/**
* Creates a new instance from the internal json string.
* <p>
* This is used to provide an original/old value for change logging / persist listeners.
*/
default Object get() {
return null;
}
}
@@ -0,0 +1,39 @@
package io.ebean.bean;
/**
* Holds information on mutable values (like plain beans stored as json).
* <p>
* Used internally in EntityBeanIntercept for dirty detection on mutable values.
* Typically dirty detection is based on a hash/checksum of json content or the
* original json content itself.
* <p>
* Refer to the mapping options {@code @DbJson(dirtyDetection)} and {@code @DbJson(keepSource)}.
*/
public interface MutableValueInfo {
/**
* Compares the given json to an internal value. Can be a hash/checksum comparison
* or a plain JSON string comparison (based on {@code @DbJson(keepSource)}).
*
* @return true if the value is considered unchanged (when comparing in json form).
*/
boolean isEqualToJson(String json);
/**
* Compares the given object to an internal value.
* <p>
* This is used to support changelog/beanState. The implementation can serialize the
* object into json form and compare it against the original json.
*/
boolean isEqualToObject(Object obj);
/**
* Creates a new instance from the internal json string.
* <p>
* This is used to provide an original/old value for change logging / persist listeners.
* This is only available for properties that have {@code @DbJson(keepSource=true)}.
*/
default Object get() {
return null;
}
}
@@ -3,7 +3,6 @@ package io.ebean.core.type;
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonParser;
import io.ebean.bean.MutableHash;
import io.ebean.text.StringFormatter; import io.ebean.text.StringFormatter;
import io.ebean.text.StringParser; import io.ebean.text.StringParser;
@@ -4,7 +4,7 @@ import com.fasterxml.jackson.core.JsonToken;
import io.ebean.ValuePair; import io.ebean.ValuePair;
import io.ebean.bean.EntityBean; import io.ebean.bean.EntityBean;
import io.ebean.bean.EntityBeanIntercept; import io.ebean.bean.EntityBeanIntercept;
import io.ebean.bean.MutableHash; import io.ebean.bean.MutableValueInfo;
import io.ebean.bean.PersistenceContext; import io.ebean.bean.PersistenceContext;
import io.ebean.config.EncryptKey; import io.ebean.config.EncryptKey;
import io.ebean.config.dbplatform.DbEncryptFunction; import io.ebean.config.dbplatform.DbEncryptFunction;
@@ -823,7 +823,7 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
/** /**
* creates a mutableHash for the given JSON value. * creates a mutableHash for the given JSON value.
*/ */
public MutableHash createMutableHash(String json) { public MutableValueInfo createMutableInfo(String json) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@@ -2,7 +2,7 @@ package io.ebeaninternal.server.deploy;
import io.ebean.bean.EntityBean; import io.ebean.bean.EntityBean;
import io.ebean.bean.EntityBeanIntercept; import io.ebean.bean.EntityBeanIntercept;
import io.ebean.bean.MutableHash; import io.ebean.bean.MutableValueInfo;
import io.ebean.core.type.DataReader; import io.ebean.core.type.DataReader;
import io.ebean.core.type.ScalarType; import io.ebean.core.type.ScalarType;
import io.ebean.text.TextException; import io.ebean.text.TextException;
@@ -26,11 +26,11 @@ public class BeanPropertyJsonMapper extends BeanProperty {
} }
@Override @Override
public MutableHash createMutableHash(String json) { public MutableValueInfo createMutableInfo(String json) {
if (keepSource) { if (keepSource) {
return new JsonMutableHash(scalarType, json); return new SourceMutableValue(scalarType, json);
} else if (dirtyDetection) { } else if (dirtyDetection) {
return new Md5MutableHash(scalarType, json); return new ChecksumMutableValue(scalarType, json);
} else { } else {
return NO_DIRTY_DETECTION; return NO_DIRTY_DETECTION;
} }
@@ -42,9 +42,9 @@ public class BeanPropertyJsonMapper extends BeanProperty {
*/ */
@Override @Override
boolean isDirtyValue(Object value, EntityBeanIntercept ebi) { boolean isDirtyValue(Object value, EntityBeanIntercept ebi) {
// dirty detection based on md5 hash of json content // dirty detection based on json content or checksum of json content
final String json = scalarType.format(value); final String json = scalarType.format(value);
final MutableHash oldHash = ebi.mutableHash(propertyIndex); final MutableValueInfo oldHash = ebi.mutableInfo(propertyIndex);
if (oldHash == null || !oldHash.isEqualToJson(json)) { if (oldHash == null || !oldHash.isEqualToJson(json)) {
ebi.mutableContent(propertyIndex, json); // so we only convert to json once ebi.mutableContent(propertyIndex, json); // so we only convert to json once
return true; return true;
@@ -60,8 +60,8 @@ public class BeanPropertyJsonMapper extends BeanProperty {
setValue(bean, value); setValue(bean, value);
String json = reader.popJson(); String json = reader.popJson();
if (json != null) { if (json != null) {
final MutableHash hash = createMutableHash(json); final MutableValueInfo hash = createMutableInfo(json);
bean._ebean_getIntercept().mutableHash(propertyIndex, hash); bean._ebean_getIntercept().mutableInfo(propertyIndex, hash);
} }
} }
return value; return value;
@@ -72,18 +72,24 @@ public class BeanPropertyJsonMapper extends BeanProperty {
} }
} }
private static class Md5MutableHash implements MutableHash { /**
* Hold checksum of json source content.
* <p>
* Dirty detection based on checksum difference on json form.
* Does not support rebuilding 'oldValue' as no original json content.
*/
private static class ChecksumMutableValue implements MutableValueInfo {
private final String hash;
private final ScalarType<?> parent; private final ScalarType<?> parent;
private final long checksum;
Md5MutableHash(ScalarType<?> parent, String json) { ChecksumMutableValue(ScalarType<?> parent, String json) {
this.parent = parent; this.parent = parent;
this.hash = hash(json); this.checksum = checksum(json);
} }
private String hash(String json) { private long checksum(String json) {
return String.valueOf(Checksum.checksum(json)); return Checksum.checksum(json);
} }
@Override @Override
@@ -93,22 +99,24 @@ public class BeanPropertyJsonMapper extends BeanProperty {
@Override @Override
public boolean isEqualToJson(String json) { public boolean isEqualToJson(String json) {
return hash(json).equals(hash); return checksum(json) == checksum;
} }
@Override @Override
public Object get() { public Object get() {
return null; // cannot create object from json return null; // cannot create object from json
} }
} }
private static class JsonMutableHash implements MutableHash { /**
* Hold original json source content. This supports rebuilding the 'oldValue'.
*/
private static class SourceMutableValue implements MutableValueInfo {
private final String originalJson; private final String originalJson;
private final ScalarType<?> parent; private final ScalarType<?> parent;
JsonMutableHash(ScalarType<?> parent, String json) { SourceMutableValue(ScalarType<?> parent, String json) {
this.parent = parent; this.parent = parent;
this.originalJson = json; this.originalJson = json;
} }
@@ -125,24 +133,24 @@ public class BeanPropertyJsonMapper extends BeanProperty {
@Override @Override
public Object get() { public Object get() {
// rebuild the 'oldValue' for change log etc
return parent.parse(originalJson); return parent.parse(originalJson);
} }
} }
/** /**
* No dirty detection on JSON content. * No dirty detection on json content.
*/ */
private static class NoDirtyDetection implements MutableHash { private static class NoDirtyDetection implements MutableValueInfo {
@Override @Override
public boolean isEqualToJson(String json) { public boolean isEqualToJson(String json) {
return true; return true; // treat as not dirty
} }
@Override @Override
public boolean isEqualToObject(Object obj) { public boolean isEqualToObject(Object obj) {
return true; return true; // treat as not dirty
} }
} }
} }
@@ -1,7 +1,7 @@
package io.ebeaninternal.server.persist.dmlbind; package io.ebeaninternal.server.persist.dmlbind;
import io.ebean.bean.EntityBean; import io.ebean.bean.EntityBean;
import io.ebean.bean.MutableHash; import io.ebean.bean.MutableValueInfo;
import io.ebeaninternal.server.deploy.BeanProperty; import io.ebeaninternal.server.deploy.BeanProperty;
import java.sql.SQLException; import java.sql.SQLException;
@@ -32,8 +32,8 @@ class BindablePropertyJsonInsert extends BindableProperty {
} else { } else {
// on insert store hash and push json // on insert store hash and push json
final String json = prop.format(value); final String json = prop.format(value);
final MutableHash hash = prop.createMutableHash(json); final MutableValueInfo hash = prop.createMutableInfo(json);
bean._ebean_getIntercept().mutableHash(propertyIndex, hash); bean._ebean_getIntercept().mutableInfo(propertyIndex, hash);
request.pushJson(json); request.pushJson(json);
request.bind(value, prop); request.bind(value, prop);
} }
@@ -1,7 +1,7 @@
package io.ebeaninternal.server.persist.dmlbind; package io.ebeaninternal.server.persist.dmlbind;
import io.ebean.bean.EntityBean; import io.ebean.bean.EntityBean;
import io.ebean.bean.MutableHash; import io.ebean.bean.MutableValueInfo;
import io.ebeaninternal.server.deploy.BeanProperty; import io.ebeaninternal.server.deploy.BeanProperty;
import java.sql.SQLException; import java.sql.SQLException;
@@ -28,8 +28,8 @@ class BindablePropertyJsonUpdate extends BindableProperty {
} else { } else {
// on update store hash and push json // on update store hash and push json
final String json = bean._ebean_getIntercept().mutableContent(propertyIndex); final String json = bean._ebean_getIntercept().mutableContent(propertyIndex);
final MutableHash hash = prop.createMutableHash(json); final MutableValueInfo hash = prop.createMutableInfo(json);
bean._ebean_getIntercept().mutableHash(propertyIndex, hash); bean._ebean_getIntercept().mutableInfo(propertyIndex, hash);
request.pushJson(json); request.pushJson(json);
final Object value = prop.getValue(bean); final Object value = prop.getValue(bean);
request.bind(value, prop); request.bind(value, prop);