1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.configuration2.tree;
18
19 import org.apache.commons.lang3.builder.EqualsBuilder;
20 import org.apache.commons.lang3.builder.HashCodeBuilder;
21 import org.apache.commons.lang3.builder.ToStringBuilder;
22
23 /**
24 * <p>
25 * A class representing the various symbols that are supported in keys recognized by {@link DefaultExpressionEngine}.
26 * </p>
27 * <p>
28 * An instance of this class is associated with each instance of {@code DefaultExpressionEngine}. It determines which
29 * concrete symbols are used to define elements like separators, attributes, etc. within a configuration key.
30 * </p>
31 * <p>
32 * Instances are created using the nested {@code Builder} class. They are immutable and can be shared between arbitrary
33 * components.
34 * </p>
35 *
36 * @since 2.0
37 */
38 public final class DefaultExpressionEngineSymbols {
39 /**
40 * A builder class for creating instances of {@code DefaultExpressionEngineSymbols}.
41 */
42 public static class Builder {
43 /** Stores the property delimiter. */
44 private String propertyDelimiter;
45
46 /** Stores the escaped property delimiter. */
47 private String escapedDelimiter;
48
49 /** Stores the attribute start marker. */
50 private String attributeStart;
51
52 /** Stores the attribute end marker. */
53 private String attributeEnd;
54
55 /** Stores the index start marker. */
56 private String indexStart;
57
58 /** Stores the index end marker. */
59 private String indexEnd;
60
61 /**
62 * Creates a new, uninitialized instance of {@code Builder}. All symbols are undefined.
63 */
64 public Builder() {
65 }
66
67 /**
68 * Creates a new instance of {@code Builder} whose properties are initialized from the passed in
69 * {@code DefaultExpressionEngineSymbols} object. This is useful if symbols are to be created which are similar to the
70 * passed in instance.
71 *
72 * @param c the {@code DefaultExpressionEngineSymbols} object serving as starting point for this builder
73 */
74 public Builder(final DefaultExpressionEngineSymbols c) {
75 propertyDelimiter = c.getPropertyDelimiter();
76 escapedDelimiter = c.getEscapedDelimiter();
77 indexStart = c.getIndexStart();
78 indexEnd = c.getIndexEnd();
79 attributeStart = c.getAttributeStart();
80 attributeEnd = c.getAttributeEnd();
81 }
82
83 /**
84 * Creates the {@code DefaultExpressionEngineSymbols} instance based on the properties set for this builder object. This
85 * method does not change the state of this builder. So it is possible to change properties and create another
86 * {@code DefaultExpressionEngineSymbols} instance.
87 *
88 * @return the newly created {@code DefaultExpressionEngineSymbols} instance
89 */
90 public DefaultExpressionEngineSymbols create() {
91 return new DefaultExpressionEngineSymbols(this);
92 }
93
94 /**
95 * Sets the string representing the end marker of an attribute in a property key.
96 *
97 * @param attributeEnd the attribute end marker
98 * @return a reference to this object for method chaining
99 */
100 public Builder setAttributeEnd(final String attributeEnd) {
101 this.attributeEnd = attributeEnd;
102 return this;
103 }
104
105 /**
106 * Sets the string representing the start marker of an attribute in a property key. Attribute start and end marker are
107 * used together to detect attributes in a property key.
108 *
109 * @param attributeStart the attribute start marker
110 * @return a reference to this object for method chaining
111 */
112 public Builder setAttributeStart(final String attributeStart) {
113 this.attributeStart = attributeStart;
114 return this;
115 }
116
117 /**
118 * Sets the string representing an escaped property delimiter. With this string a delimiter that belongs to the key of a
119 * property can be escaped. If for instance "." is used as property delimiter, you can set the escaped
120 * delimiter to "\." and can then escape the delimiter with a back slash.
121 *
122 * @param escapedDelimiter the escaped property delimiter
123 * @return a reference to this object for method chaining
124 */
125 public Builder setEscapedDelimiter(final String escapedDelimiter) {
126 this.escapedDelimiter = escapedDelimiter;
127 return this;
128 }
129
130 /**
131 * Sets the string representing the end of an index in a property key.
132 *
133 * @param indexEnd the index end
134 * @return a reference to this object for method chaining
135 */
136 public Builder setIndexEnd(final String indexEnd) {
137 this.indexEnd = indexEnd;
138 return this;
139 }
140
141 /**
142 * Sets the string representing the start of an index in a property key. Index start and end marker are used together to
143 * detect indices in a property key.
144 *
145 * @param is the index start
146 * @return a reference to this object for method chaining
147 */
148 public Builder setIndexStart(final String is) {
149 this.indexStart = is;
150 return this;
151 }
152
153 /**
154 * Sets the string representing a delimiter for properties.
155 *
156 * @param propertyDelimiter the property delimiter
157 * @return a reference to this object for method chaining
158 */
159 public Builder setPropertyDelimiter(final String propertyDelimiter) {
160 this.propertyDelimiter = propertyDelimiter;
161 return this;
162 }
163 }
164
165 /** Constant for the default property delimiter. */
166 public static final String DEFAULT_PROPERTY_DELIMITER = ".";
167
168 /** Constant for the default escaped property delimiter. */
169 public static final String DEFAULT_ESCAPED_DELIMITER = DEFAULT_PROPERTY_DELIMITER + DEFAULT_PROPERTY_DELIMITER;
170
171 /** Constant for the default attribute start marker. */
172 public static final String DEFAULT_ATTRIBUTE_START = "[@";
173
174 /** Constant for the default attribute end marker. */
175 public static final String DEFAULT_ATTRIBUTE_END = "]";
176
177 /** Constant for the default index start marker. */
178 public static final String DEFAULT_INDEX_START = "(";
179
180 /** Constant for the default index end marker. */
181 public static final String DEFAULT_INDEX_END = ")";
182
183 /**
184 * An instance with default symbols. This instance is used by the default instance of {@code DefaultExpressionEngine}.
185 */
186 public static final DefaultExpressionEngineSymbols DEFAULT_SYMBOLS = createDefaultSmybols();
187
188 /**
189 * Creates the {@code DefaultExpressionEngineSymbols} object with default symbols.
190 *
191 * @return the default symbols instance
192 */
193 private static DefaultExpressionEngineSymbols createDefaultSmybols() {
194 return new Builder().setPropertyDelimiter(DEFAULT_PROPERTY_DELIMITER).setEscapedDelimiter(DEFAULT_ESCAPED_DELIMITER).setIndexStart(DEFAULT_INDEX_START)
195 .setIndexEnd(DEFAULT_INDEX_END).setAttributeStart(DEFAULT_ATTRIBUTE_START).setAttributeEnd(DEFAULT_ATTRIBUTE_END).create();
196 }
197
198 /** Stores the property delimiter. */
199 private final String propertyDelimiter;
200
201 /** Stores the escaped property delimiter. */
202 private final String escapedDelimiter;
203
204 /** Stores the attribute start marker. */
205 private final String attributeStart;
206
207 /** Stores the attribute end marker. */
208 private final String attributeEnd;
209
210 /** Stores the index start marker. */
211 private final String indexStart;
212
213 /** Stores the index end marker. */
214 private final String indexEnd;
215
216 /**
217 * Creates a new instance of {@code DefaultExpressionEngineSymbols}.
218 *
219 * @param b the builder for defining the properties of this instance
220 */
221 private DefaultExpressionEngineSymbols(final Builder b) {
222 propertyDelimiter = b.propertyDelimiter;
223 escapedDelimiter = b.escapedDelimiter;
224 indexStart = b.indexStart;
225 indexEnd = b.indexEnd;
226 attributeStart = b.attributeStart;
227 attributeEnd = b.attributeEnd;
228 }
229
230 /**
231 * Compares this object with another one. Two instances of {@code DefaultExpressionEngineSymbols} are considered equal
232 * if all of their properties are equal.
233 *
234 * @param obj the object to compare to
235 * @return a flag whether these objects are equal
236 */
237 @Override
238 public boolean equals(final Object obj) {
239 if (this == obj) {
240 return true;
241 }
242 if (!(obj instanceof DefaultExpressionEngineSymbols)) {
243 return false;
244 }
245
246 final DefaultExpressionEngineSymbols c = (DefaultExpressionEngineSymbols) obj;
247 return new EqualsBuilder().append(getPropertyDelimiter(), c.getPropertyDelimiter()).append(getEscapedDelimiter(), c.getEscapedDelimiter())
248 .append(getIndexStart(), c.getIndexStart()).append(getIndexEnd(), c.getIndexEnd()).append(getAttributeStart(), c.getAttributeStart())
249 .append(getAttributeEnd(), c.getAttributeEnd()).isEquals();
250 }
251
252 /**
253 * Gets the string representing an attribute end marker.
254 *
255 * @return the attribute end marker
256 */
257 public String getAttributeEnd() {
258 return attributeEnd;
259 }
260
261 /**
262 * Gets the string representing an attribute start marker.
263 *
264 * @return the attribute start marker
265 */
266 public String getAttributeStart() {
267 return attributeStart;
268 }
269
270 /**
271 * Gets the string representing an escaped property delimiter.
272 *
273 * @return the escaped property delimiter
274 */
275 public String getEscapedDelimiter() {
276 return escapedDelimiter;
277 }
278
279 /**
280 * Gets the string representing the end of an index in a property key.
281 *
282 * @return the index end marker
283 */
284 public String getIndexEnd() {
285 return indexEnd;
286 }
287
288 /**
289 * Gets the string representing the start of an index in a property key.
290 *
291 * @return the index start marker
292 */
293 public String getIndexStart() {
294 return indexStart;
295 }
296
297 /**
298 * Gets the string used as delimiter in property keys.
299 *
300 * @return the property delimiter
301 */
302 public String getPropertyDelimiter() {
303 return propertyDelimiter;
304 }
305
306 /**
307 * Returns a hash code for this object.
308 *
309 * @return a hash code
310 */
311 @Override
312 public int hashCode() {
313 return new HashCodeBuilder().append(getPropertyDelimiter()).append(getEscapedDelimiter()).append(getIndexStart()).append(getIndexEnd())
314 .append(getAttributeStart()).append(getAttributeEnd()).toHashCode();
315 }
316
317 /**
318 * Returns a string representation for this object. This string contains the values of all properties.
319 *
320 * @return a string for this object
321 */
322 @Override
323 public String toString() {
324 return new ToStringBuilder(this).append("propertyDelimiter", getPropertyDelimiter()).append("escapedDelimiter", getEscapedDelimiter())
325 .append("indexStart", getIndexStart()).append("indexEnd", getIndexEnd()).append("attributeStart", getAttributeStart())
326 .append("attributeEnd", getAttributeEnd()).toString();
327 }
328 }