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}