summaryrefslogtreecommitdiff
path: root/src/main/java/com/amazon/carbonado
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/amazon/carbonado')
-rw-r--r--src/main/java/com/amazon/carbonado/Derived.java8
-rw-r--r--src/main/java/com/amazon/carbonado/gen/StorableGenerator.java62
-rw-r--r--src/main/java/com/amazon/carbonado/info/StorableIntrospector.java11
-rw-r--r--src/main/java/com/amazon/carbonado/info/StorableProperty.java10
-rw-r--r--src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorableIntrospector.java5
5 files changed, 77 insertions, 19 deletions
diff --git a/src/main/java/com/amazon/carbonado/Derived.java b/src/main/java/com/amazon/carbonado/Derived.java
index 901a583..9e51600 100644
--- a/src/main/java/com/amazon/carbonado/Derived.java
+++ b/src/main/java/com/amazon/carbonado/Derived.java
@@ -50,6 +50,7 @@ import java.lang.annotation.*;
* </pre>
*
* @author Brian S O'Neill
+ * @author Tobias Holgers
* @since 1.2
*/
@Documented
@@ -60,4 +61,11 @@ public @interface Derived {
* List of properties that this property is derived from.
*/
String[] from() default {};
+
+ /**
+ * Returns whether this property should be included when copying a
+ * storable. Copying of a derived property uses the "get" and "set" methods
+ * and requires the "set" method to be defined. Default false.
+ */
+ boolean shouldCopy() default false;
}
diff --git a/src/main/java/com/amazon/carbonado/gen/StorableGenerator.java b/src/main/java/com/amazon/carbonado/gen/StorableGenerator.java
index 3b2287a..4ea40e2 100644
--- a/src/main/java/com/amazon/carbonado/gen/StorableGenerator.java
+++ b/src/main/java/com/amazon/carbonado/gen/StorableGenerator.java
@@ -82,6 +82,7 @@ import static com.amazon.carbonado.gen.CommonMethodNames.*;
*
* @author Brian S O'Neill
* @author Don Schneider
+ * @author Tobias Holgers
* @see MasterStorableGenerator
* @see DelegateStorableGenerator
* @since 1.2
@@ -1874,7 +1875,9 @@ public final class StorableGenerator<S extends Storable> {
for (StorableProperty property : mAllProperties.values()) {
// Decide if property should be part of the copy.
- boolean shouldCopy = !property.isDerived() && !property.isJoin() &&
+ boolean shouldCopy =
+ (!property.isDerived() || property.shouldCopyDerived()) &&
+ !property.isJoin() &&
(property.isPrimaryKeyMember() && pkProperties ||
property.isVersion() && versionProperty ||
!property.isPrimaryKeyMember() && dataProperties);
@@ -1882,7 +1885,7 @@ public final class StorableGenerator<S extends Storable> {
if (shouldCopy) {
int ordinal = property.getNumber();
- if (stateBits == null) {
+ if (stateBits == null && !property.isDerived()) {
// Load state bits into local for quick retrieval.
stateBits = b.createLocalVariable(null, TypeDesc.INT);
String stateFieldName =
@@ -1899,36 +1902,36 @@ public final class StorableGenerator<S extends Storable> {
addSkipIndependent(b, target, property, skipCopy);
}
- // Skip property if uninitialized.
- b.loadLocal(stateBits);
- b.loadConstant(mask);
- b.math(Opcode.IAND);
- b.ifZeroComparisonBranch(skipCopy, "==");
-
- if (dirtyOnly) {
- // Add code to find out if property has been dirty.
+ if (stateBits != null) {
+ // Skip property if uninitialized.
b.loadLocal(stateBits);
b.loadConstant(mask);
b.math(Opcode.IAND);
- b.loadConstant(PROPERTY_STATE_DIRTY << ((ordinal & 0xf) * 2));
- b.ifComparisonBranch(skipCopy, "!=");
+ b.ifZeroComparisonBranch(skipCopy, "==");
+
+ if (dirtyOnly) {
+ // Add code to find out if property has been dirty.
+ b.loadLocal(stateBits);
+ b.loadConstant(mask);
+ b.math(Opcode.IAND);
+ b.loadConstant(PROPERTY_STATE_DIRTY << ((ordinal & 0xf) * 2));
+ b.ifComparisonBranch(skipCopy, "!=");
+ }
}
TypeDesc type = TypeDesc.forClass(property.getType());
if (unequalOnly) {
// Add code to find out if they're equal.
- b.loadThis();
- b.loadField(property.getName(), type); // [this.propValue
- b.loadLocal(target); // [this.propValue, target
- b.invoke(property.getReadMethod()); // [this.propValue, target.propValue
+ loadThisProperty(b, property, type); // [this.propValue
+ b.loadLocal(target); // [this.propValue, target
+ b.invoke(property.getReadMethod()); // [this.propValue, target.propValue
CodeBuilderUtil.addValuesEqualCall
(b, TypeDesc.forClass(property.getType()), true, skipCopy, true);
}
- b.loadLocal(target); // [target
- b.loadThis(); // [target, this
- b.loadField(property.getName(), type); // [target, this.propValue
+ b.loadLocal(target); // [target
+ loadThisProperty(b, property, type); // [target, this.propValue
mutateProperty(b, property, type);
skipCopy.setLocation();
@@ -1970,6 +1973,27 @@ public final class StorableGenerator<S extends Storable> {
}
/**
+ * Loads the property value of the current storable onto the stack. If the
+ * property is derived the read method is used, otherwise it just loads the
+ * value from the appropriate field.
+ *
+ * entry stack: [
+ * exit stack: [value
+ *
+ * @param b - {@link CodeBuilder} to which to add the load code
+ * @param property - property to load
+ * @param type - type of the property
+ */
+ private void loadThisProperty(CodeBuilder b, StorableProperty property, TypeDesc type) {
+ b.loadThis();
+ if (property.isDerived()) {
+ b.invoke(property.getReadMethod());
+ } else {
+ b.loadField(property.getName(), type);
+ }
+ }
+
+ /**
* Puts the value on the stack into the specified storable. If a write method is defined
* uses it, otherwise just shoves the value into the appropriate field.
*
diff --git a/src/main/java/com/amazon/carbonado/info/StorableIntrospector.java b/src/main/java/com/amazon/carbonado/info/StorableIntrospector.java
index 835741b..06218a4 100644
--- a/src/main/java/com/amazon/carbonado/info/StorableIntrospector.java
+++ b/src/main/java/com/amazon/carbonado/info/StorableIntrospector.java
@@ -85,6 +85,7 @@ import com.amazon.carbonado.util.ThrowUnchecked;
*
* @author Brian S O'Neill
* @author Fang Chen
+ * @author Tobias Holgers
*/
public class StorableIntrospector {
// Weakly maps Class objects to softly referenced StorableInfo objects.
@@ -1038,6 +1039,10 @@ public class StorableIntrospector {
errorMessages.add("Derived properties cannot be abstract: " +
propertyName);
}
+ if (writeMethod == null && derived.shouldCopy()) {
+ errorMessages.add("Derived properties which should be copied " +
+ "must have a write method: " + propertyName);
+ }
if (pk) {
errorMessages.add("Derived properties cannot be a member of primary key: " +
propertyName);
@@ -1782,6 +1787,7 @@ public class StorableIntrospector {
private final boolean mIndependent;
private final boolean mAutomatic;
private final boolean mIsDerived;
+ private final boolean mShouldCopyDerived;
private final String mName;
private final String mBeanName;
@@ -1824,6 +1830,7 @@ public class StorableIntrospector {
mIndependent = independent;
mAutomatic = automatic;
mIsDerived = derived != null;
+ mShouldCopyDerived = (mIsDerived ? derived.shouldCopy() : false);
mDerived = derived;
mBeanName = mBeanProperty.getName();
mName = name == null ? mBeanName : name;
@@ -1962,6 +1969,10 @@ public class StorableIntrospector {
return mDerivedTo.clone();
}
+ public final boolean shouldCopyDerived() {
+ return mShouldCopyDerived;
+ }
+
public boolean isJoin() {
return false;
}
diff --git a/src/main/java/com/amazon/carbonado/info/StorableProperty.java b/src/main/java/com/amazon/carbonado/info/StorableProperty.java
index 36491f8..aadc623 100644
--- a/src/main/java/com/amazon/carbonado/info/StorableProperty.java
+++ b/src/main/java/com/amazon/carbonado/info/StorableProperty.java
@@ -27,6 +27,7 @@ import com.amazon.carbonado.util.Appender;
* Contains all the metadata describing a property of a specific {@link Storable} type.
*
* @author Brian S O'Neill
+ * @author Tobias Holgers
* @see StorableIntrospector
*/
public interface StorableProperty<S extends Storable> extends Serializable, Appender {
@@ -278,5 +279,14 @@ public interface StorableProperty<S extends Storable> extends Serializable, Appe
*/
ChainedProperty<?>[] getDerivedToProperties();
+ /**
+ * Returns true if this derived property should be included when copying a
+ * storable. Copying of a derived property uses the "get" and "set" methods
+ * and requires the "set" method to be defined.
+ *
+ * @since 1.2
+ */
+ boolean shouldCopyDerived();
+
String toString();
}
diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorableIntrospector.java b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorableIntrospector.java
index 0f8ab95..cecd7a9 100644
--- a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorableIntrospector.java
+++ b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorableIntrospector.java
@@ -73,6 +73,7 @@ import com.amazon.carbonado.info.StorablePropertyConstraint;
*
* @author Brian S O'Neill
* @author Adam D Bradley
+ * @author Tobias Holgers
*/
public class JDBCStorableIntrospector extends StorableIntrospector {
// Maps compound keys to softly referenced JDBCStorableInfo objects.
@@ -1377,6 +1378,10 @@ public class JDBCStorableIntrospector extends StorableIntrospector {
return mMainProperty.getDerivedToProperties();
}
+ public boolean shouldCopyDerived() {
+ return mMainProperty.shouldCopyDerived();
+ }
+
public boolean isSupported() {
if (isJoin()) {
// TODO: Check if joined type is supported