blob: d7fbd2515eda049923b68e781e590bf00099d500 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.tamaya.inject.api;
import javax.enterprise.util.Nonbinding;
import javax.inject.Qualifier;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* Annotation to define injection of a configured property or define the configuration data
* backing a configuration template method. Hereby this annotation can be used in multiple
* ways and combined with other annotations such as {@link WithConfigOperator}, {@link WithPropertyConverter}.
*
* <h1>Simplest variant</h1>
* Below the most simple variant of a configured class is given:
* <pre>
* package a.b;
*
* public class ConfiguredItem {
* &amp;Config
* private String aValue;
* }
* </pre>
* Configuration resolution is implemented as follows:
* <ul>
* <li>The current valid Configuration is evaluated by calling {@code Configuration cfg = Configuration.current();}</li>
* <li>The current possible property keys are evaluated by calling {@link org.apache.tamaya.inject.spi.InjectionUtils#getKeys(Field)}
* or {@link org.apache.tamaya.inject.spi.InjectionUtils#getKeys(Method)} . Hereby the key resolution is delegated
* to an instance of {@link KeyResolver}, which can be defined on the configured class with the {@link ConfigSection}
* or (overriding) on the configured field/method with the {@link Config} annotation. The default key resolver
* is {@link org.apache.tamaya.inject.spi.AutoKeyResolver}.</li>
* <li>Each key evaluated is looked up in the configuration, until a configuration value has been found.</li>
* <li>if not successful, {@link Config#defaultValue()} is used, if present.</li>
* <li>If no value could be evaluated a ({@link org.apache.tamaya.ConfigException} is thrown, unless {@link Config#required()}
* is setPropertyValue to {@code true} (default is {@code false}).</li>
* <li>If necessary, the final <i>raw</i> value is converted into the required type to be injected, using a
* {@link org.apache.tamaya.spi.PropertyConverter}, then the value is injected.</li>
* </ul>
*
* <h3>Explicit annotations</h3>
* In the next example we explicitly define the configuration keys to be used:
* <pre>
* &amp;ConfigSection("section1")
* public class ConfiguredItem {
*
* &amp;Config(key = {"b"}, alternateKeys={"[a.b.deprecated.keys]", "a"}, defaultValue = "myDefaultValue")
* private String aValue;
* }
* </pre>
*
* Within this example we evaluate multiple possible keys: {@code section1.b, a.b.deprecated.keys, section1.a}.
* Evaluation is aborted if a key is resolved successfully. Hereby the ordering of the annotation values
* define the ordering of resolution. If no value can be found, the configured default {@code myDefaultValue} is
* injected.
*
* <h3>Using explicit field annotation only</h3>
* In the last example we explicitly define the configuration keys but omit the section part, letting the default
* section names to be taken:
* <pre>
* package a.b;
*
* public class ConfiguredItem {
*
* &amp;Config(key = {"b"}, alternateKeys={"[a.b.deprecated.keys]", "a"}, defaultValue = "myDefaultValue")
* private String aValue;
* }
* </pre>
*
* Key resolution is similar to above, but now the default section resolution allies, resulting in the keys
* {@code ConfiguredItem.b, a.b.deprecated.keys, ConfiguredItem.a} being looked up.
*/
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target(value = { ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
public @interface Config {
/** Value that is setCurrent by default as default, so it is possible to use empty Strings as default values. */
String UNCONFIGURED_VALUE = "org.apache.tamaya.config.configproperty.unconfigureddvalue";
/**
* Defines the main configuration property key to be used. The final target property is evaluated based on
* the {@link #keyResolver()} strategy, by default {@link org.apache.tamaya.inject.spi.AutoKeyResolver}.
*
* @return the main property key, not null. If empty, the field or property name (of a setter method) being injected
* is used by default.
*/
@Nonbinding
String key() default "";
/**
* Allows to customize the key resolution strategy how the {@link #key()} and {@link #alternateKeys()}values
* should be used to evaluate the final main target configuration keys. Hereby the default resolution
* works as follows:
* <ol>
* <li>The containing class <b>does not</b> have a {@link ConfigSection} annotation and the field/method does not have
* a {@link Config} annotation: the main key equals to
* {@code Owning.class.getSimpleName() + '.' + propertyKey}.</li>
* <li>The containing class <b>does not</b> have a {@link ConfigSection} annotation: the main key equals to
* {@code propertyKey}.</li>
* <li>The containing class <b>does</b> have a {@link ConfigSection} annotation: the main key equals to
* {@code areaAnnotation.getValue() + '.' + propertyKey}.</li>
* </ol>
*
* Note that on field or method injection without any {@link Config} annotation multiple main keys are generated, e.g.:
* <ul>
* <li>a field named {@code a_b_property} evaluates to {@code a_b_property, a.b.property}}</li>
* <li>a field named {@code aProperty} evaluates to {@code aProperty, a.property}}</li>
* </ul>
*
* @return the key resolution strategy, never null.
*/
@Nonbinding
Class<? extends KeyResolver> keyResolver() default KeyResolver.class;
/**
* Defines the alternate configuration property keys to be used, if no value could be evaluated using the main
* {@link #key()}.
*
* @return the property keys, not null.
*/
@Nonbinding
String[] alternateKeys() default {};
/**
* The default createValue to be injected, if none of the configuration keys could be resolved. If no key has been
* resolved and no default createValue is defined, it is, by default, handled as a deployment error. Depending on the
* extension loaded default values can be fixed Strings or even themselves resolvable. For typed configuration of
* type T entries that are not Strings the default createValue must be a valid input to a corresponding
* {@link org.apache.tamaya.spi.PropertyConverter}.
*
* @return default createValue used in case resolution fails.
*/
@Nonbinding
String defaultValue() default UNCONFIGURED_VALUE;
/**
* Flag that defines if a configuration property is required. If a required
* property is missing, a {@link org.apache.tamaya.ConfigException} is raised.
* Default is {@code true}.
* @return the flag createValue.
*/
@Nonbinding
boolean required() default true;
}