Package io.permazen

Interface PermazenObject

All Known Implementing Classes:
UntypedPermazenObject

public interface PermazenObject
Interface implemented by Permazen Java model objects.

All Permazen database objects are instances of runtime-generated sub-classes of user-provided Java model types. These generated subclasses will always implement this interface, providing convenient access to database operations. Therefore, it is convenient to declare Java model classes abstract and implements PermazenObject. However, this is not strictly necessary; all of the methods declared here ultimately delegate to one of the PermazenTransaction support methods.

Object Identity and State

Every PermazenObject has a unique 64-bit object identifier, represented as an ObjId. All PermazenObject instances are permanently associated with a specific transaction, and are the unique representatives for their corresponding ObjId in that transaction. All field state derives from the associated transaction.

There are two types of transactions: normal transactions reflecting an open transaction on the underlying key/value database, and detached transactions, which are in-memory containers of object data. Detached transactions are fully functional, supporting index queries, object versioning, etc.

Copying Objects

This interface provides methods for copying a graph of objects between transactions, for example, from an open key/value database transaction into an in-memory detached transaction ("copy out"), or vice-versa ("copy in"). A graph of objects can be copied by specifying a starting object and a list of reference cascades. (see @PermazenField). Object ID's can be remapped during the copy if necessary, e.g., to ensure existing objects are not overwritten (see CopyState).

See Also:
  • Method Summary

    Modifier and Type
    Method
    Description
    default ObjIdSet
    cascade(int recursionLimit, String... cascades)
    Find all objects reachable through the specified reference cascade(s).
    copyIn(String... cascades)
    Copy this instance, and other instances reachable through the specified reference cascades (if any), into the transaction associated with the current thread.
    copyOut(String... cascades)
    Copy this instance, and other instances reachable through the specified reference cascades (if any), into the in-memory, detached transaction associated with this instance's transaction.
    copyTo(PermazenTransaction dest, int recursionLimit, CopyState copyState, String... cascades)
    Copy this instance, and other instances it references through the specified reference cascades, into the specified destination transaction.
    default boolean
    Delete this instance, if it exists, in this instance's associated transaction.
    default boolean
    Determine whether this instance still exists in its associated transaction.
    Get the original Java model class of which this PermazenObject is an instance.
    Get this instance's unique Permazen object identifier.
    default PermazenClass<?>
    Get the PermazenClass of which this PermazenObject is an instance.
    default SchemaId
    Get the SchemaId that identifies this instance's current schema.
    Get this instance's associated PermazenTransaction.
    default boolean
    Determine whether this instance is a normal instance or is a detached instance associated with a DetachedPermazenTransaction.
    default boolean
    Migrate the schema of this instance, if necessary, so that it matches the schema of its associated transaction.
    default boolean
    Recreate a deleted instance, if it does not exist, in its associated transaction.
    void
    Reset cached simple field values.
    default void
    revalidate(Class<?>... groups)
    Add this instance to the validation queue for validation in its associated transaction.
  • Method Details

    • getObjId

      ObjId getObjId()
      Get this instance's unique Permazen object identifier.

      This method always succeeds, even if the object does not exist.

      Returns:
      unique database identifier for this instance
    • getTransaction

      PermazenTransaction getTransaction()
      Get this instance's associated PermazenTransaction.
      Returns:
      the PermazenTransaction that contains this instance's field state
    • getSchemaId

      default SchemaId getSchemaId()
      Get the SchemaId that identifies this instance's current schema.
      Returns:
      the ID of this instance's current schema
      Throws:
      DeletedObjectException - if this object does not exist in the PermazenTransaction associated with this instance
      StaleTransactionException - if the transaction associated with this instance is no longer usable
    • delete

      default boolean delete()
      Delete this instance, if it exists, in this instance's associated transaction.

      See Transaction.delete() for details on secondary deletions from DeleteAction.DELETE and PermazenField.forwardDelete().

      Returns:
      true if instance was deleted, false if it did not exist
      Throws:
      StaleTransactionException - if the transaction associated with the current thread is no longer usable
      ReferencedObjectException - if the object is referenced by some other object through a reference field configured for DeleteAction.EXCEPTION
    • exists

      default boolean exists()
      Determine whether this instance still exists in its associated transaction.
      Returns:
      true if instance exists, otherwise false
      Throws:
      StaleTransactionException - if the transaction associated with this instance is no longer usable
    • isDetached

      default boolean isDetached()
      Determine whether this instance is a normal instance or is a detached instance associated with a DetachedPermazenTransaction.

      Equivalent to getTransaction().isDetached().

      Returns:
      true if instance lives in a detached transaction
    • recreate

      default boolean recreate()
      Recreate a deleted instance, if it does not exist, in its associated transaction. The fields of a recreated object are set to their initial values. If the object already exists, nothing changes.
      Returns:
      true if instance was recreated, false if it already existed
      Throws:
      StaleTransactionException - if the transaction associated with this instance is no longer usable
    • revalidate

      default void revalidate(Class<?>... groups)
      Add this instance to the validation queue for validation in its associated transaction.

      The actual validation will occur either during PermazenTransaction.commit() or at the next invocation of PermazenTransaction.validate(), whichever occurs first. The specified validation groups, if any, will be used.

      If the associated transaction was opened with ValidationMode.DISABLED, no validation will be performed.

      Parameters:
      groups - validation group(s) to use for validation; if empty, Default is assumed
      Throws:
      DeletedObjectException - if this object does not exist in the PermazenTransaction associated with this instance
      IllegalStateException - if transaction commit is already in progress
      StaleTransactionException - if the transaction associated with this instance is no longer usable
      IllegalArgumentException - if groups is or any group in groups null
    • migrateSchema

      default boolean migrateSchema()
      Migrate the schema of this instance, if necessary, so that it matches the schema of its associated transaction.

      If a schema change occurs, @OnSchemaChange methods will be invoked prior to this method returning.

      Returns:
      true if the object's schema changed, false if it was already migrated
      Throws:
      DeletedObjectException - if this object does not exist in the PermazenTransaction associated with this instance
      StaleTransactionException - if the transaction associated with this instance is no longer usable
    • cascade

      default ObjIdSet cascade(int recursionLimit, String... cascades)
      Find all objects reachable through the specified reference cascade(s).

      This method finds all objects reachable from this instance through reference field cascades having the specified name(s). In other words, a reference field is traversed in the forward or inverse direction if one of the cascades is specified in the corresponding @PermazenField annotation property.

      All objects found will be automatically migrated to this object's associated transaction's schema.

      The recursionLimit parameter can be used to limit the maximum distance of any reachable object, measured in the number of reference field "hops" from the given starting object.

      Parameters:
      cascades - zero or more reference cascades that identify additional objects to copy
      recursionLimit - the maximum number of reference fields to hop through, or -1 for infinity
      Returns:
      the object ID's of the objects reachable from this object (including this object itself)
      Throws:
      DeletedObjectException - if any object containing a traversed reference field does not actually exist
      IllegalArgumentException - if recursionLimit is less that -1
      IllegalArgumentException - if cascades or any element therein is null
      See Also:
    • copyOut

      default PermazenObject copyOut(String... cascades)
      Copy this instance, and other instances reachable through the specified reference cascades (if any), into the in-memory, detached transaction associated with this instance's transaction.

      This method should only be invoked on regular database PermazenObjects. The returned object will always live in a DetachedPermazenTransaction.

      This is a convenience method, and is equivalent to invoking:

       this.copyTo(this.getTransaction().getDetachedTransaction(), -1, new CopyState(), cascades);
       
      Parameters:
      cascades - zero or more reference cascades that identify additional objects to copy
      Returns:
      the detached PermazenObject copy of this instance
      Throws:
      SchemaMismatchException - if the schema corresponding to this object's version is not identical in both transactions
      IllegalArgumentException - if this instance is itself a detached instance
      IllegalArgumentException - if cascades or any element therein is null
      See Also:
    • copyIn

      default PermazenObject copyIn(String... cascades)
      Copy this instance, and other instances reachable through the specified reference cascades (if any), into the transaction associated with the current thread.

      Normally this method would only be invoked on detached database objects. The returned object will be a PermazenObject in the open transaction associated with the current thread.

      This is a convenience method, and is equivalent to invoking:

       this.copyTo(PermazenTransaction.getCurrent(), -1, new CopyState(), cascades)
       
      Parameters:
      cascades - zero or more reference cascades that identify additional objects to copy
      Returns:
      the regular database copy of this instance
      Throws:
      DeletedObjectException - if any copied object ends up with a reference to an object that does not exist in dest through a reference field configured to disallow deleted assignment
      SchemaMismatchException - if the schema corresponding to this object's version is not identical in both transactions
      IllegalArgumentException - if cascades or any element therein is null
      See Also:
    • copyTo

      default PermazenObject copyTo(PermazenTransaction dest, int recursionLimit, CopyState copyState, String... cascades)
      Copy this instance, and other instances it references through the specified reference cascades, into the specified destination transaction.

      This is a more general method; see copyIn() and copyOut() for more common and specific use cases.

      If a target object does not exist, it will be created, otherwise its schema will be migrated to match the source object if necessary (with resulting @OnSchemaChange notifications). If CopyState.isSuppressNotifications() returns false, @OnCreate and @OnChange notifications will also be delivered.

      The copyState tracks which objects have already been copied. For a "fresh" copy operation, pass a newly created CopyState; for a copy operation that is a continuation of a previous copy, reuse the previous CopyState. The CopyState may also be configured to remap object ID's.

      This object's transaction and dest must be compatible in that for any schemas encountered, those schemas must be identical in both.

      If dest is not a DetachedPermazenTransaction and any copied objects contain reference fields configured with PermazenField.allowDeleted()= false, then any objects referenced by those fields must also be copied, or else must already exist in dest. Otherwise, a DeletedObjectException is thrown and it is indeterminate which objects were copied.

      The recursionLimit parameter can be used to limit the maximum distance of any reachable object, measured in the number of reference field "hops" from the given starting object.

      Note: if two threads attempt to copy objects between the same two transactions at the same time but in opposite directions, deadlock could result.

      Parameters:
      dest - destination transaction for copies
      copyState - tracks which objects have already been copied
      recursionLimit - the maximum number of reference fields to hop through, or -1 for infinity
      cascades - zero or more reference cascades that identify additional objects to copy
      Returns:
      the copied version of this instance in dest
      Throws:
      DeletedObjectException - if any object to be copied does not actually exist
      DeletedObjectException - if any copied object ends up with a reference to an object that does not exist in dest through a reference field configured to disallow deleted assignment
      SchemaMismatchException - if the schema corresponding to any copied object is not identical in both the transaction associated with this instance and dest
      IllegalArgumentException - if any parameter is null
      IllegalArgumentException - if any element in cascades is null
      See Also:
    • resetCachedFieldValues

      void resetCachedFieldValues()
      Reset cached simple field values.

      PermazenObjects instances may cache simple field values after they have been read from the underlying key/value store for efficiency. This method causes any such cached values to be forgotten, so they will be re-read from the underlying key/value store on the next read of the field.

      Normally this method does not need to be used. It may be needed to maintain consistency in exotic situations, for example, where the underlying key/value store is being modified directly.

    • getPermazenClass

      default PermazenClass<?> getPermazenClass()
      Get the PermazenClass of which this PermazenObject is an instance.
      Returns:
      associated PermazenClass
      Throws:
      TypeNotInSchemaException - if this instance is an UntypedPermazenObject
    • getModelClass

      Class<?> getModelClass()
      Get the original Java model class of which this PermazenObject is an instance.
      Returns:
      Java model class