    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.tree;
    018
    019import org.apache.commons.lang3.builder.EqualsBuilder;
    020import org.apache.commons.lang3.builder.HashCodeBuilder;
    021import org.apache.commons.lang3.builder.ToStringBuilder;
    022
    023/**
    024 * <p>
    025 * A class representing the various symbols that are supported in keys
    026 * recognized by {@link DefaultExpressionEngine}.
    027 * </p>
    028 * <p>
    029 * An instance of this class is associated with each instance of
    030 * {@code DefaultExpressionEngine}. It determines which concrete symbols are
    031 * used to define elements like separators, attributes, etc. within a
    032 * configuration key.
    033 * </p>
    034 * <p>
    035 * Instances are created using the nested {@code Builder} class. They are
    036 * immutable and can be shared between arbitrary components.
    037 * </p>
    038 *
    039 * @version $Id: DefaultExpressionEngineSymbols.java 1842194 2018-09-27 22:24:23Z ggregory $
    040 * @since 2.0
    041 */
    042public final class DefaultExpressionEngineSymbols
    043{
    044    /** Constant for the default property delimiter. */
    045    public static final String DEFAULT_PROPERTY_DELIMITER = ".";
    046
    047    /** Constant for the default escaped property delimiter. */
    048    public static final String DEFAULT_ESCAPED_DELIMITER = DEFAULT_PROPERTY_DELIMITER
    049            + DEFAULT_PROPERTY_DELIMITER;
    050
    051    /** Constant for the default attribute start marker. */
    052    public static final String DEFAULT_ATTRIBUTE_START = "[@";
    053
    054    /** Constant for the default attribute end marker. */
    055    public static final String DEFAULT_ATTRIBUTE_END = "]";
    056
    057    /** Constant for the default index start marker. */
    058    public static final String DEFAULT_INDEX_START = "(";
    059
    060    /** Constant for the default index end marker. */
    061    public static final String DEFAULT_INDEX_END = ")";
    062
    063    /**
    064     * An instance with default symbols. This instance is used by the default
    065     * instance of {@code DefaultExpressionEngine}.
    066     */
    067    public static final DefaultExpressionEngineSymbols DEFAULT_SYMBOLS =
    068            createDefaultSmybols();
    069
    070    /** Stores the property delimiter. */
    071    private final String propertyDelimiter;
    072
    073    /** Stores the escaped property delimiter. */
    074    private final String escapedDelimiter;
    075
    076    /** Stores the attribute start marker. */
    077    private final String attributeStart;
    078
    079    /** Stores the attribute end marker. */
    080    private final String attributeEnd;
    081
    082    /** Stores the index start marker. */
    083    private final String indexStart;
    084
    085    /** stores the index end marker. */
    086    private final String indexEnd;
    087
    088    /**
    089     * Creates a new instance of {@code DefaultExpressionEngineSymbols}.
    090     *
    091     * @param b the builder for defining the properties of this instance
    092     */
    093    private DefaultExpressionEngineSymbols(final Builder b)
    094    {
    095        propertyDelimiter = b.propertyDelimiter;
    096        escapedDelimiter = b.escapedDelimiter;
    097        indexStart = b.indexStart;
    098        indexEnd = b.indexEnd;
    099        attributeStart = b.attributeStart;
    100        attributeEnd = b.attributeEnd;
    101    }
    102
    103    /**
    104     * Returns the string used as delimiter in property keys.
    105     *
    106     * @return the property delimiter
    107     */
    108    public String getPropertyDelimiter()
    109    {
    110        return propertyDelimiter;
    111    }
    112
    113    /**
    114     * Returns the string representing an escaped property delimiter.
    115     *
    116     * @return the escaped property delimiter
    117     */
    118    public String getEscapedDelimiter()
    119    {
    120        return escapedDelimiter;
    121    }
    122
    123    /**
    124     * Returns the string representing an attribute start marker.
    125     *
    126     * @return the attribute start marker
    127     */
    128    public String getAttributeStart()
    129    {
    130        return attributeStart;
    131    }
    132
    133    /**
    134     * Returns the string representing an attribute end marker.
    135     *
    136     * @return the attribute end marker
    137     */
    138    public String getAttributeEnd()
    139    {
    140        return attributeEnd;
    141    }
    142
    143    /**
    144     * Returns the string representing the start of an index in a property key.
    145     *
    146     * @return the index start marker
    147     */
    148    public String getIndexStart()
    149    {
    150        return indexStart;
    151    }
    152
    153    /**
    154     * Returns the string representing the end of an index in a property key.
    155     *
    156     * @return the index end marker
    157     */
    158    public String getIndexEnd()
    159    {
    160        return indexEnd;
    161    }
    162
    163    /**
    164     * Returns a hash code for this object.
    165     *
    166     * @return a hash code
    167     */
    168    @Override
    169    public int hashCode()
    170    {
    171        return new HashCodeBuilder().append(getPropertyDelimiter())
    172                .append(getEscapedDelimiter()).append(getIndexStart())
    173                .append(getIndexEnd()).append(getAttributeStart())
    174                .append(getAttributeEnd()).toHashCode();
    175    }
    176
    177    /**
    178     * Compares this object with another one. Two instances of
    179     * {@code DefaultExpressionEngineSymbols} are considered equal if all of
    180     * their properties are equal.
    181     *
    182     * @param obj the object to compare to
    183     * @return a flag whether these objects are equal
    184     */
    185    @Override
    186    public boolean equals(final Object obj)
    187    {
    188        if (this == obj)
    189        {
    190            return true;
    191        }
    192        if (!(obj instanceof DefaultExpressionEngineSymbols))
    193        {
    194            return false;
    195        }
    196
    197        final DefaultExpressionEngineSymbols c = (DefaultExpressionEngineSymbols) obj;
    198        return new EqualsBuilder()
    199                .append(getPropertyDelimiter(), c.getPropertyDelimiter())
    200                .append(getEscapedDelimiter(), c.getEscapedDelimiter())
    201                .append(getIndexStart(), c.getIndexStart())
    202                .append(getIndexEnd(), c.getIndexEnd())
    203                .append(getAttributeStart(), c.getAttributeStart())
    204                .append(getAttributeEnd(), c.getAttributeEnd()).isEquals();
    205    }
    206
    207    /**
    208     * Returns a string representation for this object. This string contains the
    209     * values of all properties.
    210     *
    211     * @return a string for this object
    212     */
    213    @Override
    214    public String toString()
    215    {
    216        return new ToStringBuilder(this)
    217                .append("propertyDelimiter", getPropertyDelimiter())
    218                .append("escapedDelimiter", getEscapedDelimiter())
    219                .append("indexStart", getIndexStart())
    220                .append("indexEnd", getIndexEnd())
    221                .append("attributeStart", getAttributeStart())
    222                .append("attributeEnd", getAttributeEnd()).toString();
    223    }
    224
    225    /**
    226     * Creates the {@code DefaultExpressionEngineSymbols} object with default
    227     * symbols.
    228     *
    229     * @return the default symbols instance
    230     */
    231    private static DefaultExpressionEngineSymbols createDefaultSmybols()
    232    {
    233        return new Builder().setPropertyDelimiter(DEFAULT_PROPERTY_DELIMITER)
    234                .setEscapedDelimiter(DEFAULT_ESCAPED_DELIMITER)
    235                .setIndexStart(DEFAULT_INDEX_START)
    236                .setIndexEnd(DEFAULT_INDEX_END)
    237                .setAttributeStart(DEFAULT_ATTRIBUTE_START)
    238                .setAttributeEnd(DEFAULT_ATTRIBUTE_END).create();
    239    }
    240
    241    /**
    242     * A builder class for creating instances of
    243     * {@code DefaultExpressionEngineSymbols}.
    244     */
    245    public static class Builder
    246    {
    247        /** Stores the property delimiter. */
    248        private String propertyDelimiter;
    249
    250        /** Stores the escaped property delimiter. */
    251        private String escapedDelimiter;
    252
    253        /** Stores the attribute start marker. */
    254        private String attributeStart;
    255
    256        /** Stores the attribute end marker. */
    257        private String attributeEnd;
    258
    259        /** Stores the index start marker. */
    260        private String indexStart;
    261
    262        /** stores the index end marker. */
    263        private String indexEnd;
    264
    265        /**
    266         * Creates a new, uninitialized instance of {@code Builder}. All symbols
    267         * are undefined.
    268         */
    269        public Builder()
    270        {
    271        }
    272
    273        /**
    274         * Creates a new instance of {@code Builder} whose properties are
    275         * initialized from the passed in {@code DefaultExpressionEngineSymbols}
    276         * object. This is useful if symbols are to be created which are similar
    277         * to the passed in instance.
    278         *
    279         * @param c the {@code DefaultExpressionEngineSymbols} object serving as
    280         *        starting point for this builder
    281         */
    282        public Builder(final DefaultExpressionEngineSymbols c)
    283        {
    284            propertyDelimiter = c.getPropertyDelimiter();
    285            escapedDelimiter = c.getEscapedDelimiter();
    286            indexStart = c.getIndexStart();
    287            indexEnd = c.getIndexEnd();
    288            attributeStart = c.getAttributeStart();
    289            attributeEnd = c.getAttributeEnd();
    290        }
    291
    292        /**
    293         * Sets the string representing a delimiter for properties.
    294         *
    295         * @param d the property delimiter
    296         * @return a reference to this object for method chaining
    297         */
    298        public Builder setPropertyDelimiter(final String d)
    299        {
    300            propertyDelimiter = d;
    301            return this;
    302        }
    303
    304        /**
    305         * Sets the string representing an escaped property delimiter. With this
    306         * string a delimiter that belongs to the key of a property can be
    307         * escaped. If for instance &quot;.&quot; is used as property delimiter,
    308         * you can set the escaped delimiter to &quot;\.&quot; and can then
    309         * escape the delimiter with a back slash.
    310         *
    311         * @param ed the escaped property delimiter
    312         * @return a reference to this object for method chaining
    313         */
    314        public Builder setEscapedDelimiter(final String ed)
    315        {
    316            escapedDelimiter = ed;
    317            return this;
    318        }
    319
    320        /**
    321         * Sets the string representing the start of an index in a property key.
    322         * Index start and end marker are used together to detect indices in a
    323         * property key.
    324         *
    325         * @param is the index start
    326         * @return a reference to this object for method chaining
    327         */
    328        public Builder setIndexStart(final String is)
    329        {
    330            indexStart = is;
    331            return this;
    332        }
    333
    334        /**
    335         * Sets the string representing the end of an index in a property key.
    336         *
    337         * @param ie the index end
    338         * @return a reference to this object for method chaining
    339         */
    340        public Builder setIndexEnd(final String ie)
    341        {
    342            indexEnd = ie;
    343            return this;
    344        }
    345
    346        /**
    347         * Sets the string representing the start marker of an attribute in a
    348         * property key. Attribute start and end marker are used together to
    349         * detect attributes in a property key.
    350         *
    351         * @param as the attribute start marker
    352         * @return a reference to this object for method chaining
    353         */
    354        public Builder setAttributeStart(final String as)
    355        {
    356            attributeStart = as;
    357            return this;
    358        }
    359
    360        /**
    361         * Sets the string representing the end marker of an attribute in a
    362         * property key.
    363         *
    364         * @param ae the attribute end marker
    365         * @return a reference to this object for method chaining
    366         */
    367        public Builder setAttributeEnd(final String ae)
    368        {
    369            attributeEnd = ae;
    370            return this;
    371        }
    372
    373        /**
    374         * Creates the {@code DefaultExpressionEngineSymbols} instance based on
    375         * the properties set for this builder object. This method does not
    376         * change the state of this builder. So it is possible to change
    377         * properties and create another {@code DefaultExpressionEngineSymbols}
    378         * instance.
    379         *
    380         * @return the newly created {@code DefaultExpressionEngineSymbols}
    381         *         instance
    382         */
    383        public DefaultExpressionEngineSymbols create()
    384        {
    385            return new DefaultExpressionEngineSymbols(this);
    386        }
    387    }
    388}