001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.marshall;
018
019import static java.lang.annotation.ElementType.*;
020import static java.lang.annotation.RetentionPolicy.*;
021
022import java.lang.annotation.*;
023
024/**
025 * Identifies a setter method or field for adding a parent reference to a child object.
026 *
027 * <p>
028 * This annotation is used by parsers to automatically establish parent-child relationships when parsing
029 * nested objects. When a child object is created within a parent object (e.g., in a list or as a property),
030 * the parser automatically sets the parent reference on the child.
031 *
032 * <h5 class='section'>Requirements:</h5>
033 * <ul class='spaced-list'>
034 *    <li>Must be an <strong>instance</strong> method or field (not static)
035 *    <li>For methods: Must accept exactly one parameter (the parent object type)
036 *    <li>For fields: Can be any type (typically the parent object type)
037 *    <li>The method or field does not need to be public (will be made accessible automatically)
038 * </ul>
039 *
040 * <p>
041 * Can be used in the following locations:
042 * <ul>
043 *    <li>Bean setter methods or fields
044 *    <li><ja>@Rest</ja>-annotated classes and <ja>@RestOp</ja>-annotated methods when used with {@link ParentPropertyApply @ParentPropertyApply}
045 * </ul>
046 *
047 * <h5 class='section'>Example:</h5>
048 * <p class='bjava'>
049 *    <jk>public class</jk> AddressBook {
050 *       <jk>public</jk> List&lt;Person&gt; people;
051 *    }
052 *
053 *    <jk>public class</jk> Person {
054 *       <ja>@ParentProperty</ja>
055 *       <jk>public</jk> AddressBook addressBook;  <jc>// Automatically set to the enclosing AddressBook (the intervening List is skipped).</jc>
056 *
057 *       <jk>public</jk> String name;
058 *       <jk>public</jk> <jk>char</jk> sex;
059 *    }
060 *
061 *    <jc>// Or using a setter method:</jc>
062 *    <jk>public class</jk> Person {
063 *       <jk>private</jk> AddressBook parent;
064 *
065 *       <ja>@ParentProperty</ja>
066 *       <jk>protected void</jk> setParent(AddressBook <jv>parent</jv>) {
067 *          <jk>this</jk>.parent = <jv>parent</jv>;
068 *       }
069 *
070 *       <jk>public</jk> String name;
071 *       <jk>public</jk> <jk>char</jk> sex;
072 *    }
073 * </p>
074 *
075 * <h5 class='section'>When It's Called:</h5>
076 * <ul class='spaced-list'>
077 *    <li>During parsing when a child object is created within a parent object
078 *    <li>The parser automatically calls the setter or sets the field with a reference to the parent object
079 *    <li>This allows child objects to navigate back to their parent if needed
080 * </ul>
081 *
082 * <h5 class='section'>Parent resolution through collections and maps:</h5>
083 * <ul class='spaced-list'>
084 *    <li>A collection/map element's <ja>@ParentProperty</ja> is set to the nearest enclosing bean, skipping any
085 *       intervening collections, maps, or arrays.  In the example above, each <c>Person</c> lives inside a
086 *       <c>List&lt;Person&gt;</c>, yet its <c>addressBook</c> back-reference receives the enclosing <c>AddressBook</c>
087 *       bean, not the <c>List</c>.  The same holds through arbitrarily deep nesting
088 *       (e.g. <c>List&lt;List&lt;Person&gt;&gt;</c>, <c>Map&lt;String,List&lt;Person&gt;&gt;</c>).
089 *    <li>A bean at the document root (or directly inside a top-level collection) has no enclosing bean, so its
090 *       <ja>@ParentProperty</ja> is left <jk>null</jk>.
091 * </ul>
092 *
093 * <h5 class='section'>Cyclic graphs and serialization:</h5>
094 * <ul class='spaced-list'>
095 *    <li>When a <ja>@ParentProperty</ja> back-reference is also a normally-visible bean property (e.g. a <jk>public</jk>
096 *       field or getter, as in the example above), it forms a parent-to-child/child-to-parent <b>cycle</b>.  Unlike
097 *       Jackson's <c>@JsonBackReference</c>, Juneau does <b>not</b> auto-omit the <ja>@ParentProperty</ja> member on the
098 *       write (serialize) side — the annotation is a parse-time convenience only.  This is intentional.
099 *    <li>Under the <b>default</b> serializer configuration (<c>detectRecursions=<jk>false</jk></c>,
100 *       <c>ignoreRecursions=<jk>false</jk></c>), serializing such a cyclic graph produces <b>finite but
101 *       semantically-incomplete</b> output: the traversal is silently truncated at
102 *       {@link MarshallingTraverseContext.Builder#maxDepth(int) maxDepth} (default <c>100</c>).  No exception is thrown —
103 *       <c>maxDepth</c> is a size guard, not a cycle detector.
104 *    <li>To fail-fast on cycles with a clear error, enable
105 *       {@link MarshallingTraverseContext.Builder#detectRecursions() detectRecursions} — a
106 *       {@link MarshallingRecursionException} (surfaced as a serialize exception) is thrown.
107 *    <li>To omit the back-reference and round-trip cleanly, enable
108 *       {@link MarshallingTraverseContext.Builder#ignoreRecursions() ignoreRecursions} — the repeated node is emitted as
109 *       <jk>null</jk>, and parsing re-injects the parent via this annotation.
110 * </ul>
111 *
112 * <p>
113 * Putting it together, the <c>AddressBook</c>/<c>List&lt;Person&gt;</c> graph above round-trips cleanly when the
114 * back-reference is omitted on serialize and re-injected on parse:
115 * <p class='bjava'>
116 *    Serializer <jv>serializer</jv> = JsonSerializer.<jsm>create</jsm>().ignoreRecursions().build();
117 *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jv>addressBook</jv>);
118 *    AddressBook <jv>parsed</jv> = JsonParser.<jsf>DEFAULT</jsf>.parse(<jv>json</jv>, AddressBook.<jk>class</jk>);
119 *    Person <jv>person</jv> = <jv>parsed</jv>.people.get(0);
120 *    <jsm>assertTrue</jsm>(<jv>person</jv>.addressBook == <jv>parsed</jv>);  <jc>// Parent re-injected through the List.</jc>
121 * </p>
122 *
123 * <h5 class='section'>See Also:</h5><ul>
124 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/ParentPropertyAnnotation">@ParentProperty Annotation</a>
125
126 * </ul>
127 */
128@Target({ METHOD, FIELD })
129@Retention(RUNTIME)
130@Inherited
131public @interface ParentProperty {
132
133   /**
134    * Optional description for the exposed API.
135    *
136    * @return The annotation value.
137    * @since 9.2.0
138    */
139   String[] description() default {};
140
141}