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 /**
41 * A builder class for creating instances of {@code DefaultExpressionEngineSymbols}.
42 */
43 public static class Builder {
44
45 /** Stores the property delimiter. */
46 private String propertyDelimiter;
47
48 /** Stores the escaped property delimiter. */
49 private String escapedDelimiter;
50
51 /** Stores the attribute start marker. */
52 private String attributeStart;
53
54 /** Stores the attribute end marker. */
55 private String attributeEnd;
56
57 /** Stores the index start marker. */
58 private String indexStart;
59
60 /** Stores the index end marker. */
61 private String indexEnd;
62
63 /**
64 * Creates a new, uninitialized instance of {@code Builder}. All symbols are undefined.
65 */
66 public Builder() {
67 }
68
69 /**
70 * Creates a new instance of {@code Builder} whose properties are initialized from the passed in
71 * {@code DefaultExpressionEngineSymbols} object. This is useful if symbols are to be created which are similar to the
72 * passed in instance.
73 *
74 * @param c the {@code DefaultExpressionEngineSymbols} object serving as starting point for this builder
75 */
76 public Builder(final DefaultExpressionEngineSymbols c) {
77 propertyDelimiter = c.getPropertyDelimiter();
78 escapedDelimiter = c.getEscapedDelimiter();
79 indexStart = c.getIndexStart();
80 indexEnd = c.getIndexEnd();
81 attributeStart = c.getAttributeStart();
82 attributeEnd = c.getAttributeEnd();
83 }
84
85 /**
86 * Creates the {@code DefaultExpressionEngineSymbols} instance based on the properties set for this builder object. This
87 * method does not change the state of this builder. So it is possible to change properties and create another
88 * {@code DefaultExpressionEngineSymbols} instance.
89 *
90 * @return the newly created {@code DefaultExpressionEngineSymbols} instance
91 */
92 public DefaultExpressionEngineSymbols create() {
93 return new DefaultExpressionEngineSymbols(this);
94 }
95
96 /**
97 * Sets the string representing the end marker of an attribute in a property key.
98 *
99 * @param attributeEnd the attribute end marker
100 * @return a reference to this object for method chaining
101 */
102 public Builder setAttributeEnd(final String attributeEnd) {
103 this.attributeEnd = attributeEnd;
104 return this;
105 }
106
107 /**
108 * Sets the string representing the start marker of an attribute in a property key. Attribute start and end marker are
109 * used together to detect attributes in a property key.
110 *
111 * @param attributeStart the attribute start marker
112 * @return a reference to this object for method chaining
113 */
114 public Builder setAttributeStart(final String attributeStart) {
115 this.attributeStart = attributeStart;
116 return this;
117 }
118
119 /**
120 * Sets the string representing an escaped property delimiter. With this string a delimiter that belongs to the key of a
121 * property can be escaped. If for instance "." is used as property delimiter, you can set the escaped
122 * delimiter to "\." and can then escape the delimiter with a back slash.
123 *
124 * @param escapedDelimiter the escaped property delimiter
125 * @return a reference to this object for method chaining
126 */
127 public Builder setEscapedDelimiter(final String escapedDelimiter) {
128 this.escapedDelimiter = escapedDelimiter;
129 return this;
130 }
131
132 /**
133 * Sets the string representing the end of an index in a property key.
134 *
135 * @param indexEnd the index end
136 * @return a reference to this object for method chaining
137 */
138 public Builder setIndexEnd(final String indexEnd) {
139 this.indexEnd = indexEnd;
140 return this;
141 }
142
143 /**
144 * Sets the string representing the start of an index in a property key. Index start and end marker are used together to
145 * detect indices in a property key.
146 *
147 * @param is the index start
148 * @return a reference to this object for method chaining
149 */
150 public Builder setIndexStart(final String is) {
151 this.indexStart = is;
152 return this;
153 }
154
155 /**
156 * Sets the string representing a delimiter for properties.
157 *
158 * @param propertyDelimiter the property delimiter
159 * @return a reference to this object for method chaining
160 */
161 public Builder setPropertyDelimiter(final String propertyDelimiter) {
162 this.propertyDelimiter = propertyDelimiter;
163 return this;
164 }
165 }
166
167 /** Constant for the default property delimiter. */
168 public static final String DEFAULT_PROPERTY_DELIMITER = ".";
169
170 /** Constant for the default escaped property delimiter. */
171 public static final String DEFAULT_ESCAPED_DELIMITER = DEFAULT_PROPERTY_DELIMITER + DEFAULT_PROPERTY_DELIMITER;
172
173 /** Constant for the default attribute start marker. */
174 public static final String DEFAULT_ATTRIBUTE_START = "[@";
175
176 /** Constant for the default attribute end marker. */
177 public static final String DEFAULT_ATTRIBUTE_END = "]";
178
179 /** Constant for the default index start marker. */
180 public static final String DEFAULT_INDEX_START = "(";
181
182 /** Constant for the default index end marker. */
183 public static final String DEFAULT_INDEX_END = ")";
184
185 /**
186 * An instance with default symbols. This instance is used by the default instance of {@code DefaultExpressionEngine}.
187 */
188 public static final DefaultExpressionEngineSymbols DEFAULT_SYMBOLS = createDefaultSmybols();
189
190 /**
191 * Creates the {@code DefaultExpressionEngineSymbols} object with default symbols.
192 *
193 * @return the default symbols instance
194 */
195 private static DefaultExpressionEngineSymbols createDefaultSmybols() {
196 return new Builder().setPropertyDelimiter(DEFAULT_PROPERTY_DELIMITER).setEscapedDelimiter(DEFAULT_ESCAPED_DELIMITER).setIndexStart(DEFAULT_INDEX_START)
197 .setIndexEnd(DEFAULT_INDEX_END).setAttributeStart(DEFAULT_ATTRIBUTE_START).setAttributeEnd(DEFAULT_ATTRIBUTE_END).create();
198 }
199
200 /** Stores the property delimiter. */
201 private final String propertyDelimiter;
202
203 /** Stores the escaped property delimiter. */
204 private final String escapedDelimiter;
205
206 /** Stores the attribute start marker. */
207 private final String attributeStart;
208
209 /** Stores the attribute end marker. */
210 private final String attributeEnd;
211
212 /** Stores the index start marker. */
213 private final String indexStart;
214
215 /** Stores the index end marker. */
216 private final String indexEnd;
217
218 /**
219 * Creates a new instance of {@code DefaultExpressionEngineSymbols}.
220 *
221 * @param b the builder for defining the properties of this instance
222 */
223 private DefaultExpressionEngineSymbols(final Builder b) {
224 propertyDelimiter = b.propertyDelimiter;
225 escapedDelimiter = b.escapedDelimiter;
226 indexStart = b.indexStart;
227 indexEnd = b.indexEnd;
228 attributeStart = b.attributeStart;
229 attributeEnd = b.attributeEnd;
230 }
231
232 /**
233 * Compares this object with another one. Two instances of {@code DefaultExpressionEngineSymbols} are considered equal
234 * if all of their properties are equal.
235 *
236 * @param obj the object to compare to
237 * @return a flag whether these objects are equal
238 */
239 @Override
240 public boolean equals(final Object obj) {
241 if (this == obj) {
242 return true;
243 }
244 if (!(obj instanceof DefaultExpressionEngineSymbols)) {
245 return false;
246 }
247
248 final DefaultExpressionEngineSymbols c = (DefaultExpressionEngineSymbols) obj;
249 return new EqualsBuilder().append(getPropertyDelimiter(), c.getPropertyDelimiter()).append(getEscapedDelimiter(), c.getEscapedDelimiter())
250 .append(getIndexStart(), c.getIndexStart()).append(getIndexEnd(), c.getIndexEnd()).append(getAttributeStart(), c.getAttributeStart())
251 .append(getAttributeEnd(), c.getAttributeEnd()).isEquals();
252 }
253
254 /**
255 * Gets the string representing an attribute end marker.
256 *
257 * @return the attribute end marker
258 */
259 public String getAttributeEnd() {
260 return attributeEnd;
261 }
262
263 /**
264 * Gets the string representing an attribute start marker.
265 *
266 * @return the attribute start marker
267 */
268 public String getAttributeStart() {
269 return attributeStart;
270 }
271
272 /**
273 * Gets the string representing an escaped property delimiter.
274 *
275 * @return the escaped property delimiter
276 */
277 public String getEscapedDelimiter() {
278 return escapedDelimiter;
279 }
280
281 /**
282 * Gets the string representing the end of an index in a property key.
283 *
284 * @return the index end marker
285 */
286 public String getIndexEnd() {
287 return indexEnd;
288 }
289
290 /**
291 * Gets the string representing the start of an index in a property key.
292 *
293 * @return the index start marker
294 */
295 public String getIndexStart() {
296 return indexStart;
297 }
298
299 /**
300 * Gets the string used as delimiter in property keys.
301 *
302 * @return the property delimiter
303 */
304 public String getPropertyDelimiter() {
305 return propertyDelimiter;
306 }
307
308 /**
309 * Returns a hash code for this object.
310 *
311 * @return a hash code
312 */
313 @Override
314 public int hashCode() {
315 return new HashCodeBuilder().append(getPropertyDelimiter()).append(getEscapedDelimiter()).append(getIndexStart()).append(getIndexEnd())
316 .append(getAttributeStart()).append(getAttributeEnd()).toHashCode();
317 }
318
319 /**
320 * Returns a string representation for this object. This string contains the values of all properties.
321 *
322 * @return a string for this object
323 */
324 @Override
325 public String toString() {
326 return new ToStringBuilder(this).append("propertyDelimiter", getPropertyDelimiter()).append("escapedDelimiter", getEscapedDelimiter())
327 .append("indexStart", getIndexStart()).append("indexEnd", getIndexEnd()).append("attributeStart", getAttributeStart())
328 .append("attributeEnd", getAttributeEnd()).toString();
329 }
330 }