summaryrefslogtreecommitdiff
path: root/src/main/java/com/amazon/carbonado/gen
diff options
context:
space:
mode:
authorBrian S. O'Neill <bronee@gmail.com>2008-07-22 09:19:51 +0000
committerBrian S. O'Neill <bronee@gmail.com>2008-07-22 09:19:51 +0000
commitfec4f593ccac17493f0014bd8fabdedc278135c8 (patch)
treec435dcbe45e420f3bf2b91dc70e0e296fdc7687b /src/main/java/com/amazon/carbonado/gen
parent005101b7b1e7579b899c8a379f4516309e164c09 (diff)
Added advanced conversion capability when setting query filter properties. This is used to ensure that BigDecimal values are properly normalized.
Diffstat (limited to 'src/main/java/com/amazon/carbonado/gen')
-rw-r--r--src/main/java/com/amazon/carbonado/gen/MasterFeature.java3
-rw-r--r--src/main/java/com/amazon/carbonado/gen/MasterStorableGenerator.java137
-rw-r--r--src/main/java/com/amazon/carbonado/gen/StorableGenerator.java4
3 files changed, 134 insertions, 10 deletions
diff --git a/src/main/java/com/amazon/carbonado/gen/MasterFeature.java b/src/main/java/com/amazon/carbonado/gen/MasterFeature.java
index a1bb278..f433ce6 100644
--- a/src/main/java/com/amazon/carbonado/gen/MasterFeature.java
+++ b/src/main/java/com/amazon/carbonado/gen/MasterFeature.java
@@ -28,6 +28,9 @@ public enum MasterFeature {
/** Insert and update operations implement record versioning, if version property exists */
VERSIONING,
+ /** Insert and update operations normalize property types such as BigDecimal */
+ NORMALIZE,
+
/** Update operations load clean copy first, to prevent destructive update */
UPDATE_FULL,
diff --git a/src/main/java/com/amazon/carbonado/gen/MasterStorableGenerator.java b/src/main/java/com/amazon/carbonado/gen/MasterStorableGenerator.java
index d8d2901..092eea8 100644
--- a/src/main/java/com/amazon/carbonado/gen/MasterStorableGenerator.java
+++ b/src/main/java/com/amazon/carbonado/gen/MasterStorableGenerator.java
@@ -19,8 +19,13 @@
package com.amazon.carbonado.gen;
import java.lang.reflect.Method;
+
+import java.math.BigDecimal;
+
+import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import org.cojen.classfile.ClassFile;
@@ -489,9 +494,19 @@ public final class MasterStorableGenerator<S extends Storable> {
isInitialized.setLocation();
}
+ // Copy of properties before normalization.
+ List<PropertyCopy> unnormalized = null;
+ if (mFeatures.contains(MasterFeature.NORMALIZE)) {
+ unnormalized = addNormalization(b, false);
+ }
+
+ Label doTryStart = b.createLabel().setLocation();
+
b.loadThis();
b.invokeVirtual(DO_TRY_INSERT_MASTER_METHOD_NAME, TypeDesc.BOOLEAN, null);
+ addNormalizationRollback(b, doTryStart, unnormalized);
+
if (tryStart == null) {
b.returnValue(TypeDesc.BOOLEAN);
} else {
@@ -520,6 +535,7 @@ public final class MasterStorableGenerator<S extends Storable> {
CodeBuilder b = new CodeBuilder(mi);
if ((!mFeatures.contains(MasterFeature.VERSIONING)) &&
+ (!mFeatures.contains(MasterFeature.NORMALIZE)) &&
(!mFeatures.contains(MasterFeature.UPDATE_FULL)) &&
(!mFeatures.contains(MasterFeature.UPDATE_TXN)))
{
@@ -539,7 +555,22 @@ public final class MasterStorableGenerator<S extends Storable> {
Label tryLoadStart = null, tryLoadEnd = null;
- if (mFeatures.contains(MasterFeature.UPDATE_FULL)) {
+ // Copy of properties before normalization.
+ List<PropertyCopy> unnormalized = null;
+ if (mFeatures.contains(MasterFeature.NORMALIZE)) {
+ unnormalized = addNormalization(b, false);
+ }
+
+ Label doTryStart = b.createLabel().setLocation();
+
+ if (!mFeatures.contains(MasterFeature.UPDATE_FULL)) {
+ // if (!this.doTryUpdateMaster()) {
+ // goto failed;
+ // }
+ b.loadThis();
+ b.invokeVirtual(DO_TRY_UPDATE_MASTER_METHOD_NAME, TypeDesc.BOOLEAN, null);
+ b.ifZeroComparisonBranch(failed, "==");
+ } else {
// Storable saved = copy();
b.loadThis();
b.invokeVirtual(COPY_METHOD_NAME, storableType, null);
@@ -701,13 +732,6 @@ public final class MasterStorableGenerator<S extends Storable> {
b.loadThis();
b.invokeInterface
(storableType, COPY_UNEQUAL_PROPERTIES, null, new TypeDesc[] {storableType});
- } else {
- // if (!this.doTryUpdateMaster()) {
- // goto failed;
- // }
- b.loadThis();
- b.invokeVirtual(DO_TRY_UPDATE_MASTER_METHOD_NAME, TypeDesc.BOOLEAN, null);
- b.ifZeroComparisonBranch(failed, "==");
}
// txn.commit();
@@ -1023,4 +1047,101 @@ public final class MasterStorableGenerator<S extends Storable> {
b.invoke(versionProperty.getWriteMethod());
}
+
+ private List<PropertyCopy> addNormalization(CodeBuilder b, boolean forUpdate) {
+ List<PropertyCopy> unnormalized = null;
+
+ for (StorableProperty<S> property : mAllProperties.values()) {
+ if (property.isDerived()) {
+ continue;
+ }
+ if (!BigDecimal.class.isAssignableFrom(property.getType())) {
+ continue;
+ }
+
+ if (unnormalized == null) {
+ unnormalized = new ArrayList<PropertyCopy>();
+ }
+
+ PropertyCopy copy = new PropertyCopy<S>(b, property);
+ unnormalized.add(copy);
+
+ copy.makeCopy(b);
+
+ b.loadLocal(copy.copyVar);
+ Label skipNormalize = b.createLabel();
+ b.ifNullBranch(skipNormalize, true);
+
+ if (forUpdate) {
+ // FIXME: for update, also check if dirty
+ }
+
+ // Normalize by stripping trailing zeros.
+ // FIXME: Workaround BigDecimal.ZERO bug.
+ b.loadThis();
+ b.loadLocal(copy.copyVar);
+ TypeDesc propertyType = copy.copyVar.getType();
+ b.invokeVirtual(propertyType, "stripTrailingZeros", propertyType, null);
+ b.storeField(property.getName(), propertyType);
+
+ skipNormalize.setLocation();
+ }
+
+ return unnormalized;
+ }
+
+ /**
+ * Assumes a boolean is on the stack, as returned by doTryInsert or doTryUpdate.
+ */
+ private void addNormalizationRollback(CodeBuilder b, Label doTryStart,
+ List<PropertyCopy> unnormalized)
+ {
+ if (unnormalized != null) {
+ Label doTryEnd = b.createLabel().setLocation();
+
+ b.dup();
+ Label success = b.createLabel();
+ b.ifZeroComparisonBranch(success, "!=");
+
+ for (int i=0; i<2; i++) {
+ if (i == 0) {
+ } else {
+ b.exceptionHandler(doTryStart, doTryEnd, null);
+ }
+ // Rollback normalized properties.
+ for (PropertyCopy copy : unnormalized) {
+ copy.restore(b);
+ }
+ if (i == 0) {
+ b.branch(success);
+ } else {
+ b.throwObject();
+ }
+ }
+
+ success.setLocation();
+ }
+ }
+
+ private static class PropertyCopy<S extends Storable> {
+ final StorableProperty<S> property;
+ final LocalVariable copyVar;
+
+ PropertyCopy(CodeBuilder b, StorableProperty<S> property) {
+ this.property = property;
+ copyVar = b.createLocalVariable(null, TypeDesc.forClass(property.getType()));
+ }
+
+ void makeCopy(CodeBuilder b) {
+ b.loadThis();
+ b.loadField(property.getName(), copyVar.getType());
+ b.storeLocal(copyVar);
+ }
+
+ void restore(CodeBuilder b) {
+ b.loadThis();
+ b.loadLocal(copyVar);
+ b.storeField(property.getName(), copyVar.getType());
+ }
+ }
}
diff --git a/src/main/java/com/amazon/carbonado/gen/StorableGenerator.java b/src/main/java/com/amazon/carbonado/gen/StorableGenerator.java
index 0eee3de..e88ba39 100644
--- a/src/main/java/com/amazon/carbonado/gen/StorableGenerator.java
+++ b/src/main/java/com/amazon/carbonado/gen/StorableGenerator.java
@@ -2732,7 +2732,7 @@ public final class StorableGenerator<S extends Storable> {
LocalVariable encodedVar;
try {
- encodedVar = encoder.buildSerialEncoding(b, null, null);
+ encodedVar = encoder.buildSerialEncoding(b, null);
} catch (SupportException e) {
CodeBuilderUtil.throwException(b, SupportException.class, e.getMessage());
return;
@@ -2780,7 +2780,7 @@ public final class StorableGenerator<S extends Storable> {
GenericEncodingStrategy<S> encoder = new GenericEncodingStrategy<S>(mStorableType, null);
try {
- encoder.buildSerialDecoding(b, null, null, encodedVar);
+ encoder.buildSerialDecoding(b, null, encodedVar);
} catch (SupportException e) {
CodeBuilderUtil.throwException(b, SupportException.class, e.getMessage());
return;