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