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     */
017    package org.apache.commons.configuration.tree;
018    
019    import static org.junit.Assert.assertEquals;
020    import static org.junit.Assert.assertFalse;
021    import static org.junit.Assert.assertNull;
022    import static org.junit.Assert.assertTrue;
023    import static org.junit.Assert.fail;
024    
025    import java.util.NoSuchElementException;
026    
027    import org.junit.Before;
028    import org.junit.Test;
029    
030    /**
031     * Test class for DefaultConfigurationKey.
032     *
033     * @author Oliver Heger
034     * @version $Id: TestDefaultConfigurationKey.java 1225914 2011-12-30 20:26:36Z oheger $
035     */
036    public class TestDefaultConfigurationKey
037    {
038        /** Constant for a test key. */
039        private static final String TESTPROPS = "tables.table(0).fields.field(1)";
040    
041        /** Constant for a test attribute key. */
042        private static final String TESTATTR = "[@dataType]";
043    
044        /** Constant for a complex attribute key. */
045        private static final String TESTKEY = TESTPROPS + TESTATTR;
046    
047        /** Stores the expression engine of the key to test. */
048        DefaultExpressionEngine expressionEngine;
049    
050        /** Stores the object to be tested. */
051        DefaultConfigurationKey key;
052    
053        @Before
054        public void setUp() throws Exception
055        {
056            expressionEngine = new DefaultExpressionEngine();
057            key = new DefaultConfigurationKey(expressionEngine);
058        }
059    
060        /**
061         * Tests setting the expression engine to null. This should not be allowed.
062         */
063        @Test(expected = IllegalArgumentException.class)
064        public void testSetNullExpressionEngine()
065        {
066            key.setExpressionEngine(null);
067        }
068    
069        /**
070         * Tests the isAttributeKey() method with several keys.
071         */
072        @Test
073        public void testIsAttributeKey()
074        {
075            assertTrue("Attribute key not detected", key.isAttributeKey(TESTATTR));
076            assertFalse("Property key considered as attribute", key
077                    .isAttributeKey(TESTPROPS));
078            assertFalse("Null key considered as attribute", key
079                    .isAttributeKey(null));
080        }
081    
082        /**
083         * Tests if attribute keys are correctly detected if no end markers are set.
084         * (In this test case we use the same delimiter for attributes as for simple
085         * properties.)
086         */
087        @Test
088        public void testIsAttributeKeyWithoutEndMarkers()
089        {
090            expressionEngine.setAttributeEnd(null);
091            expressionEngine
092                    .setAttributeStart(DefaultExpressionEngine.DEFAULT_PROPERTY_DELIMITER);
093            assertTrue(
094                    "Attribute key not detected",
095                    key
096                            .isAttributeKey(DefaultExpressionEngine.DEFAULT_PROPERTY_DELIMITER
097                                    + "test"));
098            assertFalse("Property key considered as attribute key", key
099                    .isAttributeKey(TESTATTR));
100        }
101    
102        /**
103         * Tests removing leading delimiters.
104         */
105        @Test
106        public void testTrimLeft()
107        {
108            assertEquals("Key was not left trimmed", "test.", key
109                    .trimLeft(".test."));
110            assertEquals("Too much left trimming", "..test.", key
111                    .trimLeft("..test."));
112        }
113    
114        /**
115         * Tests removing trailing delimiters.
116         */
117        @Test
118        public void testTrimRight()
119        {
120            assertEquals("Key was not right trimmed", ".test", key
121                    .trimRight(".test."));
122            assertEquals("Too much right trimming", ".test..", key
123                    .trimRight(".test.."));
124        }
125    
126        /**
127         * Tests removing delimiters.
128         */
129        @Test
130        public void testTrim()
131        {
132            assertEquals("Key was not trimmed", "test", key.trim(".test."));
133            assertEquals("Null key could not be processed", "", key.trim(null));
134            assertEquals("Delimiter could not be processed", "", key
135                    .trim(DefaultExpressionEngine.DEFAULT_PROPERTY_DELIMITER));
136        }
137    
138        /**
139         * Tests appending keys.
140         */
141        @Test
142        public void testAppend()
143        {
144            key.append("tables").append("table(0).");
145            key.append("fields.").append("field(1)");
146            key.append(null).append(TESTATTR);
147            assertEquals("Wrong key", TESTKEY, key.toString());
148        }
149    
150        /**
151         * Tests appending keys that contain delimiters.
152         */
153        @Test
154        public void testAppendDelimiters()
155        {
156            key.append("key..").append("test").append(".");
157            key.append(".more").append("..tests");
158            assertEquals("Wrong key", "key...test.more...tests", key.toString());
159        }
160    
161        /**
162         * Tests appending keys that contain delimiters when no escpaped delimiter
163         * is defined.
164         */
165        @Test
166        public void testAppendDelimitersWithoutEscaping()
167        {
168            expressionEngine.setEscapedDelimiter(null);
169            key.append("key.......").append("test").append(".");
170            key.append(".more").append("..tests");
171            assertEquals("Wrong constructed key", "key.test.more.tests", key
172                    .toString());
173        }
174    
175        /**
176         * Tests calling append with the escape flag.
177         */
178        @Test
179        public void testAppendWithEscapeFlag()
180        {
181            key.append(".key.test.", true);
182            key.append(".more").append(".tests", true);
183            assertEquals("Wrong constructed key", "..key..test...more...tests", key
184                    .toString());
185        }
186    
187        /**
188         * Tests constructing keys for attributes.
189         */
190        @Test
191        public void testConstructAttributeKey()
192        {
193            assertEquals("Wrong attribute key", TESTATTR, key
194                    .constructAttributeKey("dataType"));
195            assertEquals("Attribute key was incorrectly converted", TESTATTR, key
196                    .constructAttributeKey(TESTATTR));
197            assertEquals("Null key could not be processed", "", key
198                    .constructAttributeKey(null));
199        }
200    
201        /**
202         * Tests constructing attribute keys when no end markers are defined. In
203         * this test case we use the property delimiter as attribute prefix.
204         */
205        @Test
206        public void testConstructAttributeKeyWithoutEndMarkers()
207        {
208            expressionEngine.setAttributeEnd(null);
209            expressionEngine.setAttributeStart(expressionEngine
210                    .getPropertyDelimiter());
211            assertEquals("Wrong attribute key", ".test", key
212                    .constructAttributeKey("test"));
213            assertEquals("Attribute key was incorrectly converted", ".test", key
214                    .constructAttributeKey(".test"));
215        }
216    
217        /**
218         * Tests appending attribute keys.
219         */
220        @Test
221        public void testAppendAttribute()
222        {
223            key.appendAttribute("dataType");
224            assertEquals("Attribute key not correctly appended", TESTATTR, key
225                    .toString());
226        }
227    
228        /**
229         * Tests appending an attribute key that is already decorated-
230         */
231        @Test
232        public void testAppendDecoratedAttributeKey()
233        {
234            key.appendAttribute(TESTATTR);
235            assertEquals("Decorated attribute key not correctly appended",
236                    TESTATTR, key.toString());
237        }
238    
239        /**
240         * Tests appending a null attribute key.
241         */
242        @Test
243        public void testAppendNullAttributeKey()
244        {
245            key.appendAttribute(null);
246            assertEquals("Null attribute key not correctly appended", "", key
247                    .toString());
248        }
249    
250        /**
251         * Tests appending an index to a key.
252         */
253        @Test
254        public void testAppendIndex()
255        {
256            key.append("test").appendIndex(42);
257            assertEquals("Index was not correctly appended", "test(42)", key
258                    .toString());
259        }
260    
261        /**
262         * Tests constructing a complex key by chaining multiple append operations.
263         */
264        @Test
265        public void testAppendComplexKey()
266        {
267            key.append("tables").append("table.").appendIndex(0);
268            key.append("fields.").append("field").appendIndex(1);
269            key.appendAttribute("dataType");
270            assertEquals("Wrong complex key", TESTKEY, key.toString());
271        }
272    
273        /**
274         * Tests getting and setting the key's length.
275         */
276        @Test
277        public void testLength()
278        {
279            key.append(TESTPROPS);
280            assertEquals("Wrong length", TESTPROPS.length(), key.length());
281            key.appendAttribute("dataType");
282            assertEquals("Wrong length", TESTKEY.length(), key.length());
283            key.setLength(TESTPROPS.length());
284            assertEquals("Wrong length after shortening", TESTPROPS.length(), key
285                    .length());
286            assertEquals("Wrong resulting key", TESTPROPS, key.toString());
287        }
288    
289        /**
290         * Tests comparing configuration keys.
291         */
292        @Test
293        public void testEquals()
294        {
295            DefaultConfigurationKey k1 = new DefaultConfigurationKey(
296                    expressionEngine, TESTKEY);
297            DefaultConfigurationKey k2 = new DefaultConfigurationKey(
298                    expressionEngine, TESTKEY);
299            assertTrue("Keys are not equal", k1.equals(k2));
300            assertTrue("Not reflexiv", k2.equals(k1));
301            assertEquals("Hash codes not equal", k1.hashCode(), k2.hashCode());
302            k2.append("anotherPart");
303            assertFalse("Keys considered equal", k1.equals(k2));
304            assertFalse("Keys considered equal", k2.equals(k1));
305            assertFalse("Key equals null key", k1.equals(null));
306            assertTrue("Faild comparison with string", k1.equals(TESTKEY));
307        }
308    
309        /**
310         * Tests determining an attribute key's name.
311         */
312        @Test
313        public void testAttributeName()
314        {
315            assertEquals("Plain key not detected", "test", key
316                    .attributeName("test"));
317            assertEquals("Attribute markers not stripped", "dataType", key
318                    .attributeName(TESTATTR));
319            assertNull("Null key not processed", key.attributeName(null));
320        }
321    
322        /**
323         * Tests to iterate over a simple key.
324         */
325        @Test
326        public void testIterate()
327        {
328            key.append(TESTKEY);
329            DefaultConfigurationKey.KeyIterator it = key.iterator();
330            assertTrue("No key parts", it.hasNext());
331            assertEquals("Wrong key part", "tables", it.nextKey());
332            assertEquals("Wrong key part", "table", it.nextKey());
333            assertTrue("No index found", it.hasIndex());
334            assertEquals("Wrong index", 0, it.getIndex());
335            assertEquals("Wrong key part", "fields", it.nextKey());
336            assertFalse("Found an index", it.hasIndex());
337            assertEquals("Wrong key part", "field", it.nextKey(true));
338            assertEquals("Wrong index", 1, it.getIndex());
339            assertFalse("Found an attribute", it.isAttribute());
340            assertEquals("Wrong current key", "field", it.currentKey(true));
341            assertEquals("Wrong key part", "dataType", it.nextKey());
342            assertEquals("Wrong decorated key part", "[@dataType]", it
343                    .currentKey(true));
344            assertTrue("Attribute not found", it.isAttribute());
345            assertFalse("Too many key parts", it.hasNext());
346            try
347            {
348                it.next();
349                fail("Could iterate over the iteration's end!");
350            }
351            catch (NoSuchElementException nex)
352            {
353                // ok
354            }
355        }
356    
357        /**
358         * Tests an iteration where the remove() method is called. This is not
359         * supported.
360         */
361        @Test(expected = UnsupportedOperationException.class)
362        public void testIterateWithRemove()
363        {
364            assertFalse(key.iterator().hasNext());
365            key.append("simple");
366            DefaultConfigurationKey.KeyIterator it = key.iterator();
367            assertTrue(it.hasNext());
368            assertEquals("simple", it.next());
369            it.remove();
370        }
371    
372        /**
373         * Tests iterating over some funny keys.
374         */
375        @Test
376        public void testIterateStrangeKeys()
377        {
378            key = new DefaultConfigurationKey(expressionEngine, "key.");
379            DefaultConfigurationKey.KeyIterator it = key.iterator();
380            assertTrue("Too few key parts", it.hasNext());
381            assertEquals("Wrong key part", "key", it.next());
382            assertFalse("Too many key parts", it.hasNext());
383    
384            key = new DefaultConfigurationKey(expressionEngine, ".");
385            it = key.iterator();
386            assertFalse("Simple delimiter key has more parts", it.hasNext());
387    
388            key = new DefaultConfigurationKey(expressionEngine,
389                    "key().index()undefined(0).test");
390            it = key.iterator();
391            assertEquals("Wrong first part", "key()", it.next());
392            assertFalse("Index detected in first part", it.hasIndex());
393            assertEquals("Wrong second part", "index()undefined", it.nextKey(false));
394            assertTrue("No index detected in second part", it.hasIndex());
395            assertEquals("Wrong index value", 0, it.getIndex());
396        }
397    
398        /**
399         * Tests iterating over keys with escaped delimiters.
400         */
401        @Test
402        public void testIterateEscapedDelimiters()
403        {
404            key.append("my..elem");
405            key.append("trailing..dot..");
406            key.append(".strange");
407            assertEquals("my..elem.trailing..dot...strange", key.toString());
408            DefaultConfigurationKey.KeyIterator kit = key.iterator();
409            assertEquals("Wrong first part", "my.elem", kit.nextKey());
410            assertEquals("Wrong second part", "trailing.dot.", kit.nextKey());
411            assertEquals("Wrong third part", "strange", kit.nextKey());
412            assertFalse("Too many parts", kit.hasNext());
413        }
414    
415        /**
416         * Tests iterating over keys when a different escaped delimiter is used.
417         */
418        @Test
419        public void testIterateAlternativeEscapeDelimiter()
420        {
421            expressionEngine.setEscapedDelimiter("\\.");
422            key.append("\\.my\\.elem");
423            key.append("trailing\\.dot\\.");
424            key.append(".strange");
425            assertEquals("\\.my\\.elem.trailing\\.dot\\..strange", key.toString());
426            DefaultConfigurationKey.KeyIterator kit = key.iterator();
427            assertEquals("Wrong first part", ".my.elem", kit.nextKey());
428            assertEquals("Wrong second part", "trailing.dot.", kit.nextKey());
429            assertEquals("Wrong third part", "strange", kit.nextKey());
430            assertFalse("Too many parts", kit.hasNext());
431        }
432    
433        /**
434         * Tests iterating when no escape delimiter is defined.
435         */
436        @Test
437        public void testIterateWithoutEscapeDelimiter()
438        {
439            expressionEngine.setEscapedDelimiter(null);
440            key.append("..my..elem.trailing..dot...strange");
441            assertEquals("Wrong key", "my..elem.trailing..dot...strange", key
442                    .toString());
443            DefaultConfigurationKey.KeyIterator kit = key.iterator();
444            final String[] parts =
445            { "my", "elem", "trailing", "dot", "strange"};
446            for (int i = 0; i < parts.length; i++)
447            {
448                assertEquals("Wrong key part " + i, parts[i], kit.next());
449            }
450            assertFalse("Too many parts", kit.hasNext());
451        }
452    
453        /**
454         * Tests whether a key with brackets in it can be iterated over.
455         */
456        @Test
457        public void testIterateWithBrackets()
458        {
459            key.append("directory.platform(x86).path");
460            DefaultConfigurationKey.KeyIterator kit = key.iterator();
461            String part = kit.nextKey();
462            assertEquals("Wrong part 1", "directory", part);
463            assertFalse("Has index 1", kit.hasIndex());
464            part = kit.nextKey();
465            assertEquals("Wrong part 2", "platform(x86)", part);
466            assertFalse("Has index 2", kit.hasIndex());
467            part = kit.nextKey();
468            assertEquals("Wrong part 3", "path", part);
469            assertFalse("Has index 3", kit.hasIndex());
470            assertFalse("Too many elements", kit.hasNext());
471        }
472    
473        /**
474         * Tests iterating over an attribute key that has an index.
475         */
476        @Test
477        public void testAttributeKeyWithIndex()
478        {
479            key.append(TESTATTR);
480            key.appendIndex(0);
481            assertEquals("Wrong attribute key with index", TESTATTR + "(0)", key
482                    .toString());
483    
484            DefaultConfigurationKey.KeyIterator it = key.iterator();
485            assertTrue("No first element", it.hasNext());
486            it.next();
487            assertTrue("Index not found", it.hasIndex());
488            assertEquals("Incorrect index", 0, it.getIndex());
489            assertTrue("Attribute not found", it.isAttribute());
490            assertEquals("Wrong plain key", "dataType", it.currentKey(false));
491            assertEquals("Wrong decorated key", TESTATTR, it.currentKey(true));
492        }
493    
494        /**
495         * Tests iteration when the attribute markers equals the property delimiter.
496         */
497        @Test
498        public void testIterateAttributeEqualsPropertyDelimiter()
499        {
500            expressionEngine.setAttributeEnd(null);
501            expressionEngine.setAttributeStart(expressionEngine
502                    .getPropertyDelimiter());
503            key.append("this.isa.key");
504            DefaultConfigurationKey.KeyIterator kit = key.iterator();
505            assertEquals("Wrong first key part", "this", kit.next());
506            assertFalse("First part is an attribute", kit.isAttribute());
507            assertTrue("First part is not a property key", kit.isPropertyKey());
508            assertEquals("Wrong second key part", "isa", kit.next());
509            assertFalse("Second part is an attribute", kit.isAttribute());
510            assertTrue("Second part is not a property key", kit.isPropertyKey());
511            assertEquals("Wrong third key part", "key", kit.next());
512            assertTrue("Third part is not an attribute", kit.isAttribute());
513            assertTrue("Third part is not a property key", kit.isPropertyKey());
514            assertEquals("Wrong decorated key part", "key", kit.currentKey(true));
515        }
516    }