/*
 * Copyright 2017-2020 original authors
 *
 * Licensed 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
 *
 * https://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 io.micronaut.core.value;

import io.micronaut.core.convert.ArgumentConversionContext;
import io.micronaut.core.convert.ConversionContext;
import io.micronaut.core.naming.conventions.StringConvention;
import io.micronaut.core.type.Argument;

import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;

import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;

A property resolver is capable of resolving properties from an underlying property source.
Author:Graeme Rocher
Since:1.0
/** * A property resolver is capable of resolving properties from an underlying property source. * * @author Graeme Rocher * @since 1.0 */
public interface PropertyResolver extends ValueResolver<String> {

Whether the given property is contained within this resolver.

Note that this method will return false for nested properties. In other words given a key of foo.bar this method will return false for: resolver.containsProperty("foo")

To check for nested properties using containsProperties(String) instead.

Params:
  • name – The name of the property
Returns:True if it is
/** * <p>Whether the given property is contained within this resolver.</p> * <p> * <p>Note that this method will return false for nested properties. In other words given a key of <tt>foo.bar</tt> this method will * return <tt>false</tt> for: <code>resolver.containsProperty("foo")</code></p> * <p> * <p>To check for nested properties using {@link #containsProperties(String)} instead.</p> * * @param name The name of the property * @return True if it is */
boolean containsProperty(@NonNull String name);
Whether the given property or any nested properties exist for the key given key within this resolver.
Params:
  • name – The name of the property
Returns:True if it is
/** * Whether the given property or any nested properties exist for the key given key within this resolver. * * @param name The name of the property * @return True if it is */
boolean containsProperties(@NonNull String name);

Resolve the given property for the given name, type and generic type arguments.

Implementers can choose to implement more intelligent type conversion by analyzing the typeArgument.

Params:
  • name – The name
  • conversionContext – The conversion context
Type parameters:
  • <T> – The concrete type
Returns:An optional containing the property value if it exists
/** * <p>Resolve the given property for the given name, type and generic type arguments.</p> * <p> * <p>Implementers can choose to implement more intelligent type conversion by analyzing the typeArgument.</p> * * @param name The name * @param conversionContext The conversion context * @param <T> The concrete type * @return An optional containing the property value if it exists */
@NonNull <T> Optional<T> getProperty(@NonNull String name, @NonNull ArgumentConversionContext<T> conversionContext);
Returns a collection of properties entries under the given key. For example given the following keys:
datasource.default.url=localhost
datasource.another.url=someother
Calling getPropertyEntries(String) with a value of datasource will result in a collection containing default and other.
Params:
  • name – The name to resolve
Returns:The property entries.
/** * Returns a collection of properties entries under the given key. For example given the following keys: * * <pre> * * <code>datasource.default.url=localhost * datasource.another.url=someother</code> * </pre> * * Calling {@code getPropertyEntries(String)} with a value of {@code datasource} will result in a collection * containing {@code default} and {@code other}. * * @param name The name to resolve * @return The property entries. */
default @NonNull Collection<String> getPropertyEntries(@NonNull String name) { return Collections.emptySet(); }

Resolve the given property for the given name, type and generic type arguments.

Implementers can choose to implement more intelligent type conversion by analyzing the typeArgument.

Params:
  • name – The name
  • argument – The required type
Type parameters:
  • <T> – The concrete type
Returns:An optional containing the property value if it exists
/** * <p>Resolve the given property for the given name, type and generic type arguments.</p> * <p> * <p>Implementers can choose to implement more intelligent type conversion by analyzing the typeArgument.</p> * * @param name The name * @param argument The required type * @param <T> The concrete type * @return An optional containing the property value if it exists */
default @NonNull <T> Optional<T> getProperty(@NonNull String name, @NonNull Argument<T> argument) { return getProperty(name, ConversionContext.of(argument)); }
Return all the properties under the given key.
Params:
  • name – The name
Returns:The properties
/** * Return all the properties under the given key. * * @param name The name * @return The properties */
default @NonNull Map<String, Object> getProperties(@NonNull String name) { return getProperties(name, null); }
Return all the properties under the given key. By default Micronaut stores keys in keb-case, such that normalized lookups are more efficient. You can obtain the raw key values by passing in StringConvention.RAW.
Params:
  • name – The name
  • keyFormat – The key format to use for the keys. Default is kebab-case.
Returns:The properties
/** * Return all the properties under the given key. By default Micronaut stores keys in keb-case, such that normalized lookups * are more efficient. You can obtain the raw key values by passing in {@link StringConvention#RAW}. * * @param name The name * @param keyFormat The key format to use for the keys. Default is kebab-case. * @return The properties */
default @NonNull Map<String, Object> getProperties(@Nullable String name, @Nullable StringConvention keyFormat) { return Collections.emptyMap(); }

Resolve the given property for the given name, type and generic type arguments.

Implementers can choose to implement more intelligent type conversion by analyzing the typeArgument.

Params:
  • name – The name
  • requiredType – The required type
  • context – The ConversionContext to apply to any conversion
Type parameters:
  • <T> – The concrete type
Returns:An optional containing the property value if it exists
/** * <p>Resolve the given property for the given name, type and generic type arguments.</p> * <p> * <p>Implementers can choose to implement more intelligent type conversion by analyzing the typeArgument.</p> * * @param name The name * @param requiredType The required type * @param context The {@link ConversionContext} to apply to any conversion * @param <T> The concrete type * @return An optional containing the property value if it exists */
default @NonNull <T> Optional<T> getProperty(@NonNull String name, @NonNull Class<T> requiredType, @NonNull ConversionContext context) { return getProperty(name, context.with(Argument.of(requiredType))); } @Override default @NonNull <T> Optional<T> get(@NonNull String name, @NonNull ArgumentConversionContext<T> conversionContext) { return getProperty(name, conversionContext); }
Resolve the given property for the given name.
Params:
  • name – The name
  • requiredType – The required type
Type parameters:
  • <T> – The concrete type
Returns:An optional containing the property value if it exists
/** * Resolve the given property for the given name. * * @param name The name * @param requiredType The required type * @param <T> The concrete type * @return An optional containing the property value if it exists */
default @NonNull <T> Optional<T> getProperty(@NonNull String name, @NonNull Class<T> requiredType) { return getProperty(name, requiredType, ConversionContext.DEFAULT); }
Resolve the given property for the given name.
Params:
  • name – The name
  • requiredType – The required type
  • defaultValue – The default value
Type parameters:
  • <T> – The concrete type
Returns:An optional containing the property value if it exists
/** * Resolve the given property for the given name. * * @param name The name * @param requiredType The required type * @param defaultValue The default value * @param <T> The concrete type * @return An optional containing the property value if it exists */
default @Nullable <T> T getProperty(@NonNull String name, @NonNull Class<T> requiredType, @Nullable T defaultValue) { return getProperty(name, requiredType).orElse(defaultValue); }
Resolve the given property for the given name.
Params:
  • name – The name of the property
  • requiredType – The required type
Type parameters:
  • <T> – The concrete type
Throws:
Returns:The value of the property
/** * Resolve the given property for the given name. * * @param name The name of the property * @param requiredType The required type * @param <T> The concrete type * @return The value of the property * @throws PropertyNotFoundException exception when property does not exist */
default @NonNull <T> T getRequiredProperty(@NonNull String name, @NonNull Class<T> requiredType) throws PropertyNotFoundException { return getProperty(name, requiredType).orElseThrow(() -> new PropertyNotFoundException(name, requiredType) ); }
Builds a property name for the given property path.
Params:
  • path – The path
Returns:The property name
/** * Builds a property name for the given property path. * * @param path The path * @return The property name */
static String nameOf(String... path) { return String.join(".", path); } }