io.permazen.annotation.ReferencePath Maven / Gradle / Ivy
Show all versions of permazen-main Show documentation
/*
* 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;
import java.util.NavigableSet;
import java.util.Optional;
/**
* Annotates Java instance methods that should return all objects found at the far end of a reference path,
* starting from the current instance.
*
*
*
*
*
*
* This annotation can be used as a convenience to let Permazen auto-generate {@link io.permazen.ReferencePath} 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 @ReferencePath("->some->path")} is equivalent to providing an implementation
* that returns all objects reachable via the {@linkplain io.permazen.ReferencePath reference path} {@code "->some->path"} when
* starting at the current instance. References can be traversed in either the forward or inverse directions; see
* {@link io.permazen.ReferencePath} for details on reference paths.
*
*
* For example:
*
* @PermazenType
* public interface TreeNode extends PermazenObject {
*
* /**
* * 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.
* */
* @ReferencePath("<-TreeNode.parent")
* NavigableSet<TreeNode> getChildren();
*
* /**
* * Get this node's grandparent, if any.
* */
* @ReferencePath("->parent->parent")
* Optional<TreeNode> getGrandparent();
* }
*
* In the example above, the generated {@code getChildren()} implementation will be functionally equivalent to
* (and slightly more efficient than) this one:
*
* /**
* * Get the children of this node.
* */
* NavigableSet<TreeNode> getChildren() {
* final PermazenTransaction jtx = this.getTransaction();
* final ReferencePath path = jtx.getPermazen().parseReferencePath(this.getClass(), "<-TreeNode.parent");
* return jtx.followReferencePath(path, Collections.singleton(this));
* }
* }
*
*
* Method Return Type
*
*
* The annotated method must be an instance method and return either {@link NavigableSet NavigableSet<T>}
* or {@link Optional}{@code }, where {@code T} is any super-type of the target object type(s) at the end
* of the reference path.
*
*
* If the reference path {@link io.permazen.ReferencePath#isSingular isSingular()} (i.e., contains only forward traversals
* of simple reference fields), then only one object can be returned and the return type must be {@link Optional}{@code }.
*
*
* Otherwise, either return type is valid, and you can use {@link Optional}{@code } if you only care to
* retrieve at most a single instance.
*
*
* More examples:
*
* @PermazenType
* public interface TreeNode extends PermazenObject {
*
* /**
* * 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.
* */
* @ReferencePath("<-TreeNode.parent")
* NavigableSet<TreeNode> getChildren();
*
* /**
* * Get the siblings of this node (including this node).
* */
* @ReferencePath("->parent<-TreeNode.parent")
* NavigableSet<TreeNode> getSiblings();
*
* /**
* * Get second cousins once removed (and parents), but only the first.
* */
* @ReferencePath("->parent->parent->parent<-TreeNode.parent<-TreeNode.parent")
* Optional<TreeNode> getSecondCousinOnceRemoved();
* }
*
*
* Meta-Annotations
*
*
* This annotation may be configured indirectly as a Spring
* meta-annotation
* when {@code spring-core} is on the classpath.
*
* @see io.permazen.ReferencePath
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })
@Documented
public @interface ReferencePath {
/**
* The reference path to follow.
*
*
* The starting type for the reference path is the class containing the annotated method.
*
* @return the reference path to traverse
* @see io.permazen.ReferencePath
*/
String value() default "";
}