001package com.typesafe.config.parser;
002
003import com.typesafe.config.ConfigValue;
004
005/**
006 * Represents an individual HOCON or JSON file, preserving all
007 * formatting and syntax details.  This can be used to replace
008 * individual values and exactly render the original text of the
009 * input.
010 *
011 * <p>
012 * Because this object is immutable, it is safe to use from multiple threads and
013 * there's no need for "defensive copies."
014 *
015 * <p>
016 * <em>Do not implement interface {@code ConfigDocument}</em>; it should only be
017 * implemented by the config library. Arbitrary implementations will not work
018 * because the library internals assume a specific concrete implementation.
019 * Also, this interface is likely to grow new methods over time, so third-party
020 * implementations will break.
021 */
022public interface ConfigDocument {
023    /**
024     * Returns a new ConfigDocument that is a copy of the current ConfigDocument,
025     * but with the desired value set at the desired path. If the path exists, it will
026     * remove all duplicates before the final occurrence of the path, and replace the value
027     * at the final occurrence of the path. If the path does not exist, it will be added. If
028     * the document has an array as the root value, an exception will be thrown.
029     *
030     * @param path the path at which to set the desired value
031     * @param newValue the value to set at the desired path, represented as a string. This
032     *                 string will be parsed into a ConfigNode using the same options used to
033     *                 parse the entire document, and the text will be inserted
034     *                 as-is into the document. Leading and trailing comments, whitespace, or
035     *                 newlines are not allowed, and if present an exception will be thrown.
036     *                 If a concatenation is passed in for newValue but the document was parsed
037     *                 with JSON, the first value in the concatenation will be parsed and inserted
038     *                 into the ConfigDocument.
039     * @return a copy of the ConfigDocument with the desired value at the desired path
040     */
041    ConfigDocument withValueText(String path, String newValue);
042
043    /**
044     * Returns a new ConfigDocument that is a copy of the current
045     * ConfigDocument, but with the desired value set at the
046     * desired path. Works like {@link #withValueText(String, String)},
047     * but takes a ConfigValue instead of a string.
048     *
049     * @param path the path at which to set the desired value
050     * @param newValue the value to set at the desired path, represented as a ConfigValue.
051     *                 The rendered text of the ConfigValue will be inserted into the
052     *                 ConfigDocument.
053     * @return a copy of the ConfigDocument with the desired value at the desired path
054     */
055    ConfigDocument withValue(String path, ConfigValue newValue);
056
057    /**
058     * Returns a new ConfigDocument that is a copy of the current ConfigDocument, but with
059     * all values at the desired path removed. If the path does not exist in the document,
060     * a copy of the current document will be returned. If there is an array at the root, an exception
061     * will be thrown.
062     *
063     * @param path the path to remove from the document
064     * @return a copy of the ConfigDocument with the desired value removed from the document.
065     */
066    ConfigDocument withoutPath(String path);
067
068    /**
069     * Returns a boolean indicating whether or not a ConfigDocument has a value at the desired path.
070     * null counts as a value for purposes of this check.
071     * @param path the path to check
072     * @return true if the path exists in the document, otherwise false
073     */
074    boolean hasPath(String path);
075
076    /**
077     * The original text of the input, modified if necessary with
078     * any replaced or added values.
079     * @return the modified original text
080     */
081    String render();
082}