summaryrefslogtreecommitdiff
path: root/src/main/java/com/amazon/carbonado/Storable.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/amazon/carbonado/Storable.java')
-rw-r--r--src/main/java/com/amazon/carbonado/Storable.java424
1 files changed, 424 insertions, 0 deletions
diff --git a/src/main/java/com/amazon/carbonado/Storable.java b/src/main/java/com/amazon/carbonado/Storable.java
new file mode 100644
index 0000000..f5c2248
--- /dev/null
+++ b/src/main/java/com/amazon/carbonado/Storable.java
@@ -0,0 +1,424 @@
+/*
+ * Copyright 2006 Amazon Technologies, Inc. or its affiliates.
+ * Amazon, Amazon.com and Carbonado are trademarks or registered trademarks
+ * of Amazon Technologies, Inc. or its affiliates. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.amazon.carbonado;
+
+/**
+ * A data access object in a {@link Repository}. User defined storables must
+ * either extend or implement this interface via an interface or abstract
+ * class. Bean properties defined in the storable are persisted into the
+ * repository. At least one property must be annotated as the {@link
+ * PrimaryKey}. At most one property may be annotated as being the {@link
+ * Version} property.
+ *
+ * <p>Storable instances are mutable, but they must be thread-safe. Although
+ * there may be race conditions if multiple threads are mutating the Storable,
+ * the Storable instance will not get into a corrupt state.
+ *
+ * @author Brian S O'Neill
+ * @author Don Schneider
+ *
+ * @see com.amazon.carbonado.Alias
+ * @see com.amazon.carbonado.Indexes
+ * @see com.amazon.carbonado.Join
+ * @see com.amazon.carbonado.Nullable
+ * @see com.amazon.carbonado.PrimaryKey
+ * @see com.amazon.carbonado.Version
+ */
+public interface Storable<S extends Storable<S>> {
+ /**
+ * Loads or reloads this object from the storage layer by its primary
+ * key. This object's primary key itself is never modified by calling
+ * load. If load is successful, altering the primary key is no longer
+ * allowed unless the object is deleted. Attempting to alter the primary
+ * key in this state results in an {@link IllegalStateException}.
+ *
+ * <p>Note: This method differs from {@link #tryLoad} only in that it
+ * throws an exception if no matching record was found instead of returning
+ * false. This may indicate that the underlying record was deleted between
+ * a load and reload. When a FetchNoneException is thrown, this object's
+ * state will be the same as if the delete method was called on it.
+ *
+ * @throws FetchNoneException if no matching record found
+ * @throws FetchException if storage layer throws an exception
+ * @throws IllegalStateException if the state of this instance suggests
+ * that any primary keys are unspecified
+ */
+ void load() throws FetchNoneException, FetchException;
+
+ /**
+ * Loads or reloads this object from the storage layer by its primary
+ * key. This object's primary key itself is never modified by calling
+ * load. If load is successful, altering the primary key is no longer
+ * allowed unless the object is deleted. Attempting to alter the primary
+ * key in this state results in an {@link IllegalStateException}.
+ *
+ * <p>Note: This method differs from {@link #load} only in that it returns
+ * false if no matching record was found instead of throwing an exception.
+ * This may indicate that the underlying record was deleted between a load
+ * and reload. When false is returned, this object's state will be the same
+ * as if the delete method was called on it.
+ *
+ * @return true if found and loaded, false otherwise
+ * @throws FetchException if storage layer throws an exception
+ * @throws IllegalStateException if the state of this instance suggests
+ * that any primary keys are unspecified
+ */
+ boolean tryLoad() throws FetchException;
+
+ /**
+ * Inserts a new persistent value for this object. If successful, altering
+ * the primary key is no longer allowed unless the object is deleted.
+ * Attempting to alter the primary key in this state results in an
+ * {@link IllegalStateException}.
+ *
+ * <p>Insert requires that all primary key properties be specified. If not,
+ * an {@link IllegalStateException} is thrown. Also, repository
+ * implementations usually require that properties which are not {@link
+ * Nullable} also be specified. Otherwise, a {@link ConstraintException}
+ * may be thrown.
+ *
+ * <p>Note: This method differs from {@link #tryInsert} only in that it may
+ * throw a UniqueConstraintException instead of returning false.
+ *
+ * @throws UniqueConstraintException if it is absolutely known that a key
+ * of inserted object matches an existing one
+ * @throws ConstraintException if any required properties are unspecified
+ * @throws PersistException if storage layer throws an exception
+ * @throws IllegalStateException if the state of this instance suggests
+ * that any primary keys are unspecified
+ */
+ void insert() throws PersistException;
+
+ /**
+ * Inserts a new persistent value for this object. If successful, altering
+ * the primary key is no longer allowed unless the object is deleted.
+ * Attempting to alter the primary key in this state results in an
+ * {@link IllegalStateException}.
+ *
+ * <p>Insert requires that all primary key properties be specified. If not,
+ * an {@link IllegalStateException} is thrown. Also, repository
+ * implementations usually require that properties which are not {@link
+ * Nullable} also be specified. Otherwise, a {@link ConstraintException}
+ * may be thrown.
+ *
+ * <p>Note: This method differs from {@link #insert} only in that it
+ * returns false instead of throwing a UniqueConstraintException.
+ *
+ * @return false if it is absolutely known that a key of inserted object
+ * matches an existing one
+ * @throws ConstraintException if any required properties are unspecified
+ * @throws PersistException if storage layer throws an exception
+ * @throws IllegalStateException if the state of this instance suggests
+ * that any primary keys are unspecified
+ */
+ boolean tryInsert() throws PersistException;
+
+ /**
+ * Updates the persistent value of this object, regardless of whether this
+ * object has actually been loaded or not. If successful, altering the
+ * primary key is no longer allowed unless the object is deleted.
+ * Attempting to alter the primary key in this state results in an
+ * {@link IllegalStateException}.
+ *
+ * <p>If this object has a {@link Version version} property defined, then
+ * the update logic is a bit more strict. Updates of any storable require
+ * that the primary keys be specified; if a version is present, the version
+ * must be specified as well. If any of the primary key or version
+ * properties are unspecified, an {@link IllegalStateException} will be
+ * thrown; if they are fully specified and the version doesn't match the
+ * current record, an {@link OptimisticLockException} is thrown.
+ *
+ * <p>Not all properties need to be set on this object when calling
+ * update. Setting a subset results in a partial update. After a successful
+ * update, all properties are set to the actual values in the storage
+ * layer. Put another way, the object is automatically reloaded after a
+ * successful update.
+ *
+ * <p>If PersistNoneException is thrown, this indicates that the underlying
+ * record was deleted. When this happens, this object's state will be the
+ * same as if the delete method was called on it.
+ *
+ * @throws PersistNoneException if record is missing and no update occurred
+ * @throws PersistException if storage layer throws an exception
+ * @throws OptimisticLockException if a version property exists and the
+ * optimistic lock failed
+ * @throws IllegalStateException if the state of this instance suggests
+ * that any primary keys are unspecified, or if a version property is unspecified
+ */
+ void update() throws PersistException;
+
+ /**
+ * Updates the persistent value of this object, regardless of whether this
+ * object has actually been loaded or not. If successful, altering the
+ * primary key is no longer allowed unless the object is deleted.
+ * Attempting to alter the primary key in this state results in an
+ * {@link IllegalStateException}.
+ *
+ * <p>If this object has a {@link Version version} property defined, then
+ * the update logic is a bit more strict. Updates of any storable require
+ * that the primary keys be specified; if a version is present, the version
+ * must be specified as well. If any of the primary key or version
+ * properties are unspecified, an {@link IllegalStateException} will be
+ * thrown; if they are fully specified and the version doesn't match the
+ * current record, an {@link OptimisticLockException} is thrown.
+ *
+ * <p>Not all properties need to be set on this object when calling
+ * update. Setting a subset results in a partial update. After a successful
+ * update, all properties are set to the actual values in the storage
+ * layer. Put another way, the object is automatically reloaded after a
+ * successful update.
+ *
+ * <p>A return value of false indicates that the underlying record was
+ * deleted. When this happens, this object's state will be the same as if
+ * the delete method was called on it.
+ *
+ * @return true if record likely exists and was updated, or false if record
+ * absolutely no longer exists and no update occurred
+ * @throws PersistException if storage layer throws an exception
+ * @throws OptimisticLockException if a version property exists and the
+ * optimistic lock failed
+ * @throws IllegalStateException if the state of this instance suggests
+ * that any primary keys are unspecified, or if a version property is unspecified
+ */
+ boolean tryUpdate() throws PersistException;
+
+ /**
+ * Deletes this object from the storage layer by its primary key,
+ * regardless of whether this object has actually been loaded or not.
+ * Calling delete does not prevent this object from being used again. All
+ * property values are still valid, including the primary key. Once
+ * deleted, the insert operation is permitted again.
+ *
+ * <p>Note: This method differs from {@link #tryDelete} only in that it may
+ * throw a PersistNoneException instead of returning false.
+ *
+ * @throws PersistNoneException if record is missing and nothing was
+ * deleted
+ * @throws PersistException if storage layer throws an exception
+ * @throws IllegalStateException if the state of this instance suggests
+ * that any primary keys are unspecified
+ */
+ void delete() throws PersistException;
+
+ /**
+ * Deletes this object from the storage layer by its primary key,
+ * regardless of whether this object has actually been loaded or not.
+ * Calling delete does not prevent this object from being used again. All
+ * property values are still valid, including the primary key. Once
+ * deleted, the insert operation is permitted again.
+ *
+ * <p>Note: This method differs from {@link #delete} only in that it
+ * returns false instead of throwing a PersistNoneException.
+ *
+ * @return true if record likely existed and was deleted, or false if record
+ * absolutely no longer exists and no delete was necessary
+ * @throws PersistException if storage layer throws an exception
+ * @throws IllegalStateException if the state of this instance suggests
+ * that any primary keys are unspecified
+ */
+ boolean tryDelete() throws PersistException;
+
+ /**
+ * Returns the class or interface from which this storable was
+ * generated. This represents the data class for the storable.
+ *
+ * <p><i>Design note: the name "getStorableType" is avoided, so as not to
+ * conflict with a user defined property of "storableType"</i>
+ */
+ Class<S> storableType();
+
+ /**
+ * Copies all supported properties, skipping any that are uninitialized.
+ * Specifically, calls "target.set&lt;property&gt;" for all supported
+ * properties in this storable, passing the value of the property from this
+ * object. Unsupported {@link Independent independent} properties in this
+ * or the target are not copied.
+ *
+ * @param target storable on which to call set&lt;property&gt; methods
+ * @throws IllegalStateException if any primary key properties of target
+ * cannot be altered
+ */
+ void copyAllProperties(S target);
+
+ /**
+ * Copies all supported primary key properties, skipping any that are
+ * uninitialized. Specifically, calls "target.set&lt;property&gt;" for all
+ * supported properties which participate in the primary key, passing the
+ * value of the property from this object. Unsupported {@link Independent
+ * independent} properties in this or the target are not copied.
+ *
+ * @param target storable on which to call set&lt;property&gt; methods
+ * @throws IllegalStateException if any primary key properties of target
+ * cannot be altered
+ */
+ void copyPrimaryKeyProperties(S target);
+
+ /**
+ * Copies the optional version property, unless it is uninitialized.
+ * Specifically, calls "target.set&lt;property&gt;" for the version
+ * property (if supported), passing the value of the property from this
+ * object. If no version property is defined, then this method does
+ * nothing. Unsupported {@link Independent independent} properties in this
+ * or the target are not copied.
+ *
+ * @param target storable on which to call set&lt;property&gt; method
+ */
+ void copyVersionProperty(S target);
+
+ /**
+ * Copies all supported non-primary key properties which are unequal,
+ * skipping any that are uninitialized. Specifically, calls
+ * "target.get&lt;property&gt;", and if the value thus retrieved differs
+ * from the local value, "target.set&lt;property&gt;" is called for that
+ * property. Unsupported {@link Independent independent} properties in this
+ * or the target are not copied.
+ *
+ * @param target storable on which to call set&lt;property&gt; methods
+ */
+ void copyUnequalProperties(S target);
+
+ /**
+ * Copies all supported non-primary key properties which are
+ * dirty. Specifically, calls "target.set&lt;property&gt;" for any
+ * non-primary key property which is dirty, passing the value of the
+ * property from this object. A property is considered dirty when set
+ * before a load or persist operation is called. Unsupported {@link
+ * Independent independent} properties in this or the target are not
+ * copied.
+ *
+ * @param target storable on which to call set&lt;property&gt; methods
+ */
+ void copyDirtyProperties(S target);
+
+ /**
+ * Returns true if any non-primary key properties in this object are
+ * dirty. A property is considered dirty when set before a load or persist
+ * operation is called. A property becomes clean after a successful load,
+ * insert, or update operation.
+ */
+ boolean hasDirtyProperties();
+
+ /**
+ * Marks all dirty properties as clean. Uninitialized properties remain so.
+ * As a side-effect, initialized primary keys may no longer be altered.
+ */
+ void markPropertiesClean();
+
+ /**
+ * Marks all properties as clean, including uninitialized properties.
+ * As a side-effect, primary keys may no longer be altered.
+ */
+ void markAllPropertiesClean();
+
+ /**
+ * Marks all clean properties as dirty. Uninitialized properties remain so.
+ * As a side-effect, primary keys can be altered.
+ */
+ void markPropertiesDirty();
+
+ /**
+ * Marks all properties as dirty, including uninitialized properties.
+ * As a side-effect, primary keys can be altered.
+ */
+ void markAllPropertiesDirty();
+
+ /**
+ * Returns true if the given property of this Storable has never been
+ * loaded or set.
+ *
+ * @param propertyName name of property to interrogate
+ * @throws IllegalArgumentException if property is unknown or is a join
+ */
+ boolean isPropertyUninitialized(String propertyName);
+
+ /**
+ * Returns true if the given property of this Storable has been set, but no
+ * load or store operation has been performed yet.
+ *
+ * @param propertyName name of property to interrogate
+ * @throws IllegalArgumentException if property is unknown or is a join
+ */
+ boolean isPropertyDirty(String propertyName);
+
+ /**
+ * Returns true if the given property of this Storable is clean. All
+ * properties are clean after a successful load or store operation.
+ *
+ * @param propertyName name of property to interrogate
+ * @throws IllegalArgumentException if property is unknown or is a join
+ */
+ boolean isPropertyClean(String propertyName);
+
+ /**
+ * Returns true if the given property exists and is supported. If a
+ * Storable has an {@link Independent} property which is not supported by
+ * the repository, then this method returns false.
+ *
+ * @param propertyName name of property to check
+ */
+ boolean isPropertySupported(String propertyName);
+
+ /**
+ * Returns an exact shallow copy of this object, including the state.
+ */
+ S copy();
+
+ int hashCode();
+
+ /**
+ * True if all properties and fields are equal, but ignoring the state.
+ *
+ * @param obj object to compare to for equality
+ */
+ boolean equals(Object obj);
+
+ /**
+ * True if the supported properties which participate in the primary key
+ * are equal. This is useful to cheaply investigate if two storables refer
+ * to the same entity, regardless of the state of object (specifically the
+ * non-key properties). Unsupported {@link Independent independent}
+ * properties in this or the target are not compared.
+ *
+ * @param obj object to compare to for equality
+ */
+ boolean equalPrimaryKeys(Object obj);
+
+ /**
+ * True if all supported properties for this object are equal. Unsupported
+ * {@link Independent independent} properties in this or the target are not
+ * compared.
+ *
+ * @param obj object to compare to for equality
+ */
+ boolean equalProperties(Object obj);
+
+ /**
+ * Returns a string for debugging purposes that contains all supported
+ * property names and values for this object. Unsupported {@link
+ * Independent independent} properties are not included.
+ */
+ String toString();
+
+ /**
+ * Returns a string for debugging purposes that contains only supported
+ * primary key property names and values for this object. Unsupported
+ * {@link Independent independent} properties are not included.
+ */
+ String toStringKeyOnly();
+}