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.commons.configuration2.convert;
018
019import java.util.Collection;
020import java.util.List;
021
022/**
023 * <p>
024 * Definition of an interface that controls the handling of list delimiters in
025 * configuration properties.
026 * </p>
027 * <p>
028 * {@link org.apache.commons.configuration2.AbstractConfiguration
029 * AbstractConfiguration} supports list delimiters in property values. If such a
030 * delimiter is found, the value actually contains multiple values and has to be
031 * split. This is useful for instance for
032 * {@link org.apache.commons.configuration2.PropertiesConfiguration
033 * PropertiesConfiguration}: properties files that have to be compatible with
034 * the {@code java.util.Properties} class cannot have multiple occurrences of a
035 * single property key, therefore a different storage scheme for multi-valued
036 * properties is needed. A possible storage scheme could look as follows:
037 * </p>
038 *
039 * <pre>
040 * myProperty=value1,value2,value3
041 * </pre>
042 *
043 * <p>
044 * Here a comma is used as list delimiter. When parsing this property (and using
045 * a corresponding {@code ListDelimiterHandler} implementation) the string value
046 * is split, and three values are added for the property key.
047 * </p>
048 * <p>
049 * A {@code ListDelimiterHandler} knows how to parse and to escape property
050 * values. It is called by concrete {@code Configuration} implementations when
051 * they have to deal with properties with multiple values.
052 * </p>
053 *
054 * @version $Id: ListDelimiterHandler.java 1842194 2018-09-27 22:24:23Z ggregory $
055 * @since 2.0
056 */
057public interface ListDelimiterHandler
058{
059    /**
060     * A specialized {@code ValueTransformer} implementation which does no
061     * transformation. The {@code transformValue()} method just returns the
062     * passed in object without changes. This instance can be used by
063     * configurations which do not require additional encoding.
064     */
065    ValueTransformer NOOP_TRANSFORMER = new ValueTransformer()
066    {
067        @Override
068        public Object transformValue(final Object value)
069        {
070            return value;
071        }
072    };
073
074    /**
075     * Parses the specified value for list delimiters and splits it if
076     * necessary. The passed in object can be either a single value or a complex
077     * one, e.g. a collection, an array, or an {@code Iterable}. It is the
078     * responsibility of this method to return an {@code Iterable} which
079     * contains all extracted values.
080     *
081     * @param value the value to be parsed
082     * @return an {@code Iterable} allowing access to all extracted values
083     */
084    Iterable<?> parse(Object value);
085
086    /**
087     * Splits the specified string at the list delimiter and returns a
088     * collection with all extracted components. A concrete implementation also
089     * has to deal with escape characters which might mask a list delimiter
090     * character at certain positions. The boolean {@code trim} flag determines
091     * whether each extracted component should be trimmed. This typically makes
092     * sense as the list delimiter may be surrounded by whitespace. However,
093     * there may be specific use cases in which automatic trimming is not
094     * desired.
095     *
096     * @param s the string to be split
097     * @param trim a flag whether each component of the string is to be trimmed
098     * @return a collection with all components extracted from the string
099     */
100    Collection<String> split(String s, boolean trim);
101
102    /**
103     * Escapes the specified single value object. This method is called for
104     * properties containing only a single value. So this method can rely on the
105     * fact that the passed in object is not a list. An implementation has to
106     * check whether the value contains list delimiter characters and - if so -
107     * escape them accordingly.
108     *
109     * @param value the value to be escaped
110     * @param transformer a {@code ValueTransformer} for an additional encoding
111     *        (must not be <b>null</b>)
112     * @return the escaped value
113     */
114    Object escape(Object value, ValueTransformer transformer);
115
116    /**
117     * Escapes all values in the given list and concatenates them to a single
118     * string. This operation is required by configurations that have to
119     * represent properties with multiple values in a single line in their
120     * external configuration representation. This may require an advanced
121     * escaping in some cases.
122     *
123     * @param values the list with all the values to be converted to a single
124     *        value
125     * @param transformer a {@code ValueTransformer} for an additional encoding
126     *        (must not be <b>null</b>)
127     * @return the resulting escaped value
128     */
129    Object escapeList(List<?> values, ValueTransformer transformer);
130}