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.commons.inject;
018
019import static java.lang.annotation.ElementType.*;
020import static java.lang.annotation.RetentionPolicy.*;
021
022import java.lang.annotation.*;
023
024/**
025 * Declares a class as a prefix-scoped, whole-object config binding target — Juneau's analog of
026 * Spring's {@code @ConfigurationProperties}.
027 *
028 * <p>
029 * When a {@code @ConfigProperties}-annotated class is materialized through {@link BeanInstantiator},
030 * its fields are populated from the {@link org.apache.juneau.commons.settings.Settings Settings} chain
031 * under {@link #prefix()} via {@link ConfigPropertiesBinder}, and the bound instance is auto-registered
032 * into the current {@link BeanStore}.
033 *
034 * <h5 class='section'>Binding order and lifecycle</h5>
035 * <p>
036 * The whole-object config bind runs <b>after</b> {@code @Value}/{@code @Inject} field-and-method injection and
037 * <b>before</b> any {@link PostConstruct @PostConstruct} method — so a
038 * {@code @PostConstruct} method observes the fully-bound config fields. Fields that are themselves annotated with
039 * {@code @Value} or {@code @Inject} are left to the injection engine and are never overwritten by config binding,
040 * even when a matching {@code prefix.fieldName} key exists.
041 *
042 * <h5 class='section'>Caller-scoped sources</h5>
043 * <p>
044 * The bind consults any {@link org.apache.juneau.commons.settings.PropertySource PropertySource}-typed beans in the
045 * active {@link BeanStore} <b>ahead of</b> the global {@link org.apache.juneau.commons.settings.Settings Settings}
046 * chain, so a caller can layer overriding or supplementary sources without mutating the shared
047 * {@code Settings.get()} singleton.
048 *
049 * <h5 class='section'>Not inherited</h5>
050 * <p>
051 * This annotation is <b>not</b> {@link java.lang.annotation.Inherited @Inherited}: the {@link BeanInstantiator}
052 * trigger fires only when the <i>exact declared type</i> being instantiated carries the annotation — a subclass or
053 * interface implementor of an annotated type does not itself trigger binding or auto-registration.
054 *
055 * <p>
056 * This is distinct from the {@link ConfigPropertiesBinder} <b>nested-field</b> detection, which <i>is</i>
057 * inheritance-aware: a field whose <i>declared type</i> is a subclass of an {@code @ConfigProperties}-annotated
058 * type still triggers nested binding under the enclosing type's prefix, since the annotation lookup there walks the
059 * declared field type's class hierarchy rather than requiring an exact-type match.
060 *
061 * <h5 class='section'>Example:</h5>
062 * <p class='bjava'>
063 *    <ja>@ConfigProperties</ja>(prefix = <js>"MyService"</js>)
064 *    <jk>public class</jk> MyServiceProperties {
065 *       <jk>public</jk> String <jv>host</jv> = <js>"localhost"</js>;
066 *       <jk>public int</jk> <jv>port</jv> = 8080;
067 *    }
068 * </p>
069 *
070 * <p>
071 * {@code @ConfigProperties} and {@link Value @Value} coexist: {@code @Value}
072 * resolves a single value; {@code @ConfigProperties} resolves a whole object. A class can use
073 * {@code @Value} fields internally and separately be the target of another class's nested
074 * {@code @ConfigProperties} bind.
075 *
076 * <h5 class='section'>See Also:</h5><ul>
077 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/ConfigProperties">@ConfigProperties Annotation Basics</a>
078 * </ul>
079 *
080 * @since 10.0.0
081 */
082@Documented
083@Target(TYPE)
084@Retention(RUNTIME)
085public @interface ConfigProperties {
086
087   /**
088    * The property-key prefix (no trailing dot).
089    *
090    * <p>
091    * Ignored when the annotated type appears as a nested field of another {@code @ConfigProperties} type — the
092    * enclosing type's prefix (extended with the field name) wins for the nested bind.
093    *
094    * @return The prefix.
095    */
096   String prefix();
097
098   /**
099    * Whether relaxed (camelCase / kebab-case / dotted / {@code SCREAMING_SNAKE_CASE}) key matching is enabled.
100    *
101    * <p>
102    * Ignored when the annotated type appears as a nested field of another {@code @ConfigProperties} type — the
103    * enclosing type's {@code relaxed} flag wins for the nested bind.
104    *
105    * @return <jk>true</jk> if relaxed matching is enabled. Defaults to <jk>true</jk>.
106    */
107   boolean relaxed() default true;
108}