All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.permazen.annotation.OnDelete Maven / Gradle / Ivy

The newest version!

/*
 * Copyright (C) 2015 Archie L. Cobbs. All rights reserved.
 */

package io.permazen.annotation;

import io.permazen.DetachedPermazenTransaction;
import io.permazen.ReferencePath;
import io.permazen.core.Transaction;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Annotates Permazen model class methods that are to be invoked whenever an object is about to be deleted.
 *
 * 
 * 
 * 
 *
 * 

Overview

* *

* When a matching object is deleted, annotated methods are invoked just prior to actual deletion. * *

* Methods must return void and normally take one parameter. A matching object is one whose type is compatible * with the method parameter and which is found at the end of the {@linkplain ReferencePath reference path} * specified by {@link #path}, starting from the object to be notified. See {@link ReferencePath} for more * information about reference paths. * *

* In the case of an instance method where {@link #path} is empty (the default), the method is allowed to take * zero parameters; in this case, the object monitors itself. * *

* For static methods, {@link #path} must be empty and every object whose type is compatible with the method's parameter * is a matching object and can produce notifications. * *

* The annotated method may may have any level of access, including {@code private}. * *

* A class may have multiple {@link OnDelete @OnDelete} methods, each with a specific purpose. * *

Examples

* *

* This example shows various ways an annotated method can be matched: * *


 *   @PermazenType
 *   public abstract class User implements PermazenObject {
 *
 *       public abstract Account getAccount();
 *       public abstract void setAccount(Account account);
 *
 *       @OnDelete(path = "->account")
 *       private void handleDeletion1(Account account) {
 *           // Invoked when MY Account is deleted
 *       }
 *   }
 *
 *   @PermazenType
 *   public abstract class Feature implements PermazenObject {
 *
 *       public abstract Account getAccount();
 *       public abstract void setAccount(Account account);
 *
 *       @OnDelete(path = "->account<-User.account")
 *       private void handleDeletion1(User user) {
 *           // Invoked when ANY User associated with MY Account is deleted
 *       }
 *   }
 *
 *   @PermazenType
 *   public abstract class Account implements PermazenObject {
 *
 *       @NotNull
 *       public abstract String getName();
 *       public abstract void setName(String name);
 *
 *   // Non-static @OnDelete methods
 *
 *       @OnDelete
 *       private void handleDeletion1() {
 *           // Invoked when THIS Account is deleted
 *       }
 *
 *       @OnDelete
 *       private void handleDeletion2(SpecialAccount self) {
 *           // Invoked when THIS Account is deleted IF it's also a SpecialAccount
 *       }
 *
 *       @OnDelete(path = "<-User.account")
 *       private void handleDeletion3(User user) {
 *           // Invoked when ANY User associated with THIS Account is deleted
 *       }
 *
 *       @OnDelete(path = "<-User.account")
 *       private void handleDeletion4(Object obj) {
 *           // Invoked when ANY User OR Feature associated with THIS Account is deleted
 *       }
 *
 *       @OnDelete(path = "<-Feature.account->account<-User.account")
 *       private void handleDeletion5(User user) {
 *           // Invoked when ANY User associated with the same Account
 *           // as ANY Feature associated with THIS Account is deleted
 *       }
 *
 *  // Static @OnDelete methods
 *
 *       @OnDelete
 *       private static void handleDeletion5(Object obj) {
 *           // Invoked when ANY object is deleted
 *       }
 *
 *       @OnDelete
 *       private static void handleDeletion6(Account account) {
 *           // Invoked when ANY Account is deleted
 *       }
 *   }
 * 
* *

Instance vs. Static Methods

* *

* An instance method will be invoked on each object for which the deleted object is found at the end * of the specified reference path, starting from that object. For example, if there are three child {@code Node}'s * pointing to the same parent {@code Node}, and the {@code Node} class has an instance method annotated with * {@link OnDelete @OnDelete}{@code (path = "parent")}, then all three child {@code Node}'s will be notified * when the parent is deleted. * *

* A static method is invoked once for any matching object; the {@link path} is ignored and must be empty. * *

Notification Delivery

* *

* Notifications are delivered in the same thread that deletes the object, before the deletion actually occurs. * At most one delete notification will ever be delivered for any object deletion event. In particular, if an * annotated method attempts to re-entrantly delete the same object again, no new notification is delivered. * *

* Some notifications may need to be ignored by objects in {@linkplain DetachedPermazenTransaction detached} transactions; * you can use {@code this.isDetached()} to detect that situation. * *

* Actions that have effects visible to the outside world should be made contingent on successful transaction commit, * for example, via {@link Transaction#addCallback Transaction.addCallback()}. * *

Meta-Annotations

* *

* This annotation may be configured indirectly as a Spring * meta-annotation * when {@code spring-core} is on the classpath. * * @see OnCreate */ @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) @Documented public @interface OnDelete { /** * Specify the reference path to the target object(s) that should be monitored for deletion. * See {@link ReferencePath} for information on reference paths and their proper syntax. * *

* The default empty path means the monitored object and the notified object are the same. In that case, * the type of the parameter (if any) restricts notifications to compatible subclasses. * *

* When annotating static methods, this property is unused and must be left unset. * * @return reference path leading to monitored objects * @see ReferencePath */ String path() default ""; }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy