All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.helidon.config.spi.ConfigParser Maven / Gradle / Ivy

There is a newer version: 4.1.1
Show newest version
/*
 * Copyright (c) 2017, 2023 Oracle and/or its affiliates.
 *
 * 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
 *
 *     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 io.helidon.config.spi;

import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;

import io.helidon.common.media.type.MediaType;
import io.helidon.config.spi.ConfigNode.ObjectNode;

/**
 * Transforms config {@link io.helidon.config.spi.ConfigParser.Content} into a {@link ConfigNode.ObjectNode} that
 * represents the original structure and values from the content.
 * 

* The application can register parsers on a {@code Builder} using the * {@link io.helidon.config.Config.Builder#addParser(ConfigParser)} method. The * config system also locates parsers using the Java * {@link java.util.ServiceLoader} mechanism and automatically adds them to * every {@code Builder} unless the application disables this feature for a * given {@code Builder} by invoking * {@link io.helidon.config.Config.Builder#disableParserServices()}. *

* A parser can specify a {@link io.helidon.common.Weight}. If no weight is * explicitly assigned, the value of {@value io.helidon.common.Weighted#DEFAULT_WEIGHT} is assumed. *

* Parser is used by the config system and a config source provides data as an input stream. * * @see io.helidon.config.Config.Builder#addParser(ConfigParser) * @see io.helidon.config.spi.ParsableSource * @see io.helidon.config.ConfigParsers ConfigParsers - access built-in implementations. */ public interface ConfigParser { /** * Returns set of supported media types by the parser. *

* Set of supported media types is used when config system looks for appropriate parser based on media type * of content. *

* {@link io.helidon.config.spi.ParsableSource} implementations can use {@link io.helidon.common.media.type.MediaTypes} * to probe for media type of content to provide it to config system through * {@link io.helidon.config.spi.ConfigParser.Content.Builder#mediaType(io.helidon.common.media.type.MediaType)}. * * @return supported media types by the parser */ Set supportedMediaTypes(); /** * Parses a specified {@link ConfigContent} into a {@link ObjectNode hierarchical configuration representation}. *

* Never returns {@code null}. * * @param content a content to be parsed * @return parsed hierarchical configuration representation * @throws ConfigParserException in case of problem to parse configuration from the source * @deprecated use {@link #parse(io.helidon.config.spi.ConfigParser.Content, java.util.function.Function)} instead */ @Deprecated ObjectNode parse(Content content) throws ConfigParserException; /** * Parses a specified {@link ConfigContent} into a {@link ObjectNode hierarchical configuration representation}. *

* Never returns {@code null}. * * @param content a content to be parsed * @param relativeResolver function to resolve relative resources to this resource (if supported by the source) * @return parsed hierarchical configuration representation * @throws ConfigParserException in case of problem to parse configuration from the source */ default ObjectNode parse(Content content, Function> relativeResolver) { return parse(content); } /** * Config parser can define supported file suffixes. If such are defined, Helidon will * use these to discover default configuration sources. * For example if there is a {@code ConfigParser} that returns {@code xml}, config would look for * {@code meta-config.xml} to discover meta configuration, and for {@code application.xml} on file * system and on classpath to discover configuration files. *

* Note that the suffixes must resolve into a media type supported by a config parser * (see {@link io.helidon.common.media.type.MediaTypes#detectExtensionType(String)}). * * @return a set of file suffixes supported by this config parser. */ default List supportedSuffixes() { return List.of(); } /** * Config content to be parsed by a {@link ConfigParser}. */ interface Content extends ConfigContent { /** * Media type of the content. This method is only called if * there is no parser configured. * * @return content media type if known, {@code empty} otherwise */ Optional mediaType(); /** * Data of this config source. * * @return the data of the underlying source to be parsed by a {@link ConfigParser} */ InputStream data(); /** * Charset configured by the config source or {@code UTF-8} if none configured. * * @return charset to use when reading {@link #data()} if needed by the parser */ Charset charset(); /** * A fluent API builder for {@link io.helidon.config.spi.ConfigParser.Content}. * * @return a new builder instance */ static Builder builder() { return new Builder(); } /** * Create content from data, media type and a stamp. * If not all are available, construct content using {@link #builder()} * * @param data input stream to underlying data * @param mediaType content media type * @param stamp stamp of the content * @return content built from provided information */ static Content create(InputStream data, MediaType mediaType, Object stamp) { return builder().data(data) .mediaType(mediaType) .stamp(stamp) .build(); } /** * Fluent API builder for {@link Content}. */ class Builder extends ConfigContent.Builder implements io.helidon.common.Builder { private InputStream data; private MediaType mediaType; private Charset charset = StandardCharsets.UTF_8; private Builder() { } /** * Data of the config source as loaded from underlying storage. * * @param data to be parsed * @return updated builder instance */ public Builder data(InputStream data) { Objects.requireNonNull(data, "Parsable input stream must be provided"); this.data = data; return this; } /** * Media type of the content if known by the config source. * Media type is configured on content, as sometimes you need the actual file to exist to be able to * "guess" its media type, and this is the place we are sure it exists. * * @param mediaType media type of the content as understood by the config source * @return updated builder instance */ public Builder mediaType(MediaType mediaType) { Objects.requireNonNull(mediaType, "Media type must be provided, or this method should not be called"); this.mediaType = mediaType; return this; } /** * A shortcut method to invoke with result of {@link io.helidon.common.media.type.MediaTypes#detectType(String)} * and similar methods. Only sets media type if the parameter is present. * * @param mediaType optional of media type * @return updated builder instance */ public Builder mediaType(Optional mediaType) { mediaType.ifPresent(this::mediaType); return this; } /** * Configure charset if known by the config source. * * @param charset charset to use if the content should be read using a reader * @return updated builder instance */ public Builder charset(Charset charset) { Objects.requireNonNull(charset, "Charset must be provided, or this method should not be called"); this.charset = charset; return this; } InputStream data() { return data; } MediaType mediaType() { return mediaType; } Charset charset() { return charset; } @Override public Content build() { if (null == data) { throw new ConfigParserException("Parsable content exists, yet input stream was not configured."); } return new ContentImpl.ParsableContentImpl(this); } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy