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

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

There is a newer version: 5.1.0
Show newest version

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

package io.permazen.annotation;

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;

/**
 * Java annotation for declaring methods that should return objects found by traversing a {@link io.permazen.ReferencePath}.
 *
 * 

* This annotation can be used as a convenience to let Permazen auto-generate reference path traversal code. * A common use case is inverting references, e.g., from a parent back to a child in a one-to-many relationship. * *

* Annotating an abstract method with {@code @FollowPath("some.path")} is just short-hand for providing an implementation * that creates and traverses the {@linkplain io.permazen.ReferencePath reference path} {@code "some.path"}. * See {@link io.permazen.ReferencePath} for details on reference paths. The specified reference path is assumed to not * have any {@linkplain io.permazen.ReferencePath#getTargetField target field}. * *

* For example, the following declaration: *

 *      @FollowPath("^TreeNode:parent^")
 *      public abstract NavigableSet<TreeNode> getChildren();
 * 
* is functionally equivalent to, and slightly more efficient than: *
 *
 *      public NavigableSet<TreeNode> getChildren() {
 *          final Permazen jdb = /* the Permazen instance associated with this instance */
 *          final ReferencePath path = jdb.parseReferencePath(this.getClass(), "^TreeNode:parent^", false);
 *          return jdb.followReferencePath(path, Collections.singleton(this));
 *      }
 * 
* *

Method Return Type

* *

* The annotated method should return {@link java.util.NavigableSet NavigableSet<T>}, where {@code T} is any super-type of * the type(s) at the other end of the reference path. * *

* However, if {@code firstOnly} is true then the method returns only the first object found (if any), and the method's * return type should instead be {@link java.util.Optional}{@code }; this is always appropriate when the reference path * contains only forward traversals of many-to-one relationships. * *

* For example: *

 *  @PermazenType
 *  public interface TreeNode extends JObject {
 *
 *      /**
 *       * Get the parent of this node, or null if node is a root.
 *       */
 *      TreeNode getParent();
 *      void setParent(TreeNode parent);
 *
 *      /**
 *       * Get the children of this node.
 *       */
 *      @FollowPath("^TreeNode:parent^")
 *      NavigableSet<TreeNode> getChildren();
 *
 *      /**
 *       * Get the siblings of this node (including this node).
 *       */
 *      @FollowPath("parent.^TreeNode:parent^")
 *      NavigableSet<TreeNode> getSiblings();
 *
 *      /**
 *       * Get the grandparent of this node.
 *       */
 *      @FollowPath(value = "parent.parent", firstOnly = true)
 *      Optional<TreeNode> getGrandparent();
 *  }
 * 
* *

Inverse Paths

* *

* Inverse paths may be specified using the combination of {@link #inverseOf} and {@link #startingFrom} properties. * So the following two declarations are functionally equivalent: *

 *      /**
 *       * Get the children of this node.
 *       */
 *      @FollowPath("^TreeNode:parent^")
 *      NavigableSet<TreeNode> getChildren();
 *
 *      /**
 *       * Get the children of this node.
 *       */
 *      @FollowPath(inverseOf = "parent", startingFrom = TreeNode.class)
 *      NavigableSet<TreeNode> getChildren();
 * 
* *

Meta-Annotations

* *

* This annotation may be configured indirectly as a Spring * meta-annotation * when {@code spring-core} is on the classpath. */ @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) @Documented public @interface FollowPath { /** * The reference path to follow in the forward direction. * *

* The starting type for the reference path is the class containing the annotated method. * *

* If this property is used, both of {@link #inverseOf} and {@link #startingFrom} must be left unset. * * @return the reference path to traverse in the forward direction */ String value() default ""; /** * The reference path to follow in the inverse direction. * *

* If this property is used, {@link #startingFrom} must also be specified and {@link #value} must be left unset. * * @return the reference path to traverse in the inverse direction */ String inverseOf() default ""; /** * The starting model type for the reference path to follow in the inverse direction. * *

* When an inverse reference path is specified, the starting type for the reference path is not implied, because * the path starts from the "remote end", instead of from the class containing the annotated method. * Therefore, it must be explicitly specified via this property. * *

* If this property is used, {@link #inverseOf} must also be specified and {@link #value} must be left unset. * * @return the starting model type for the inverted reference path */ Class startingFrom() default void.class; /** * Whether only the first, if any, of the set of objects should be returned, or the entire set. * *

* If this property is true, then the annotated method's return type must be {@code java.util.Optional}{@code }, * or if false, it must be {@link java.util.NavigableSet}{@code }, where {@code T} is some super-type of the type(s) * at the remote end of the reference path. * * @return whether to return only the first object */ boolean firstOnly() default false; }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy