From 4a0115c24f7eb72405ecdc2c2d4cc25af429e5e1 Mon Sep 17 00:00:00 2001 From: Tobias Holgers Date: Wed, 29 Apr 2009 00:48:35 +0000 Subject: Added @Derived(shouldCopy=true) to copy derived properties used as repository hints --- src/main/java/com/amazon/carbonado/Derived.java | 8 +++ .../amazon/carbonado/gen/StorableGenerator.java | 62 +++++++++++++++------- .../carbonado/info/StorableIntrospector.java | 11 ++++ .../amazon/carbonado/info/StorableProperty.java | 10 ++++ .../repo/jdbc/JDBCStorableIntrospector.java | 5 ++ 5 files changed, 77 insertions(+), 19 deletions(-) (limited to 'src') 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.*; * * * @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 { 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 { 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 { 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(); @@ -1969,6 +1972,27 @@ public final class StorableGenerator { b.ifZeroComparisonBranch(skipCopy, "=="); } + /** + * 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 extends Serializable, Appender { @@ -278,5 +279,14 @@ public interface StorableProperty 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 -- cgit v1.2.3