blob: 59c44928148ce4521beec3cab83ee8e9ceb7a5ef [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.configuration2.tree;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.NoSuchElementException;
import org.junit.Before;
import org.junit.Test;
/**
* Test class for DefaultConfigurationKey.
*
* @author Oliver Heger
*/
public class TestDefaultConfigurationKey
{
/** Constant for a test key. */
private static final String TESTPROPS = "tables.table(0).fields.field(1)";
/** Constant for a test attribute key. */
private static final String TESTATTR = "[@dataType]";
/** Constant for a complex attribute key. */
private static final String TESTKEY = TESTPROPS + TESTATTR;
/** Stores the expression engine of the key to test. */
private DefaultExpressionEngine expressionEngine;
/** Stores the object to be tested. */
private DefaultConfigurationKey key;
@Before
public void setUp() throws Exception
{
expressionEngine = DefaultExpressionEngine.INSTANCE;
key = new DefaultConfigurationKey(expressionEngine);
}
/**
* Helper method to create a key instance with the given content.
*
* @param k the key for initialization
* @return the newly created {@code DefaultConfigurationKey} instance
*/
private DefaultConfigurationKey key(final String k)
{
return new DefaultConfigurationKey(expressionEngine, k);
}
/**
* Tests setting the expression engine to null. This should not be allowed.
*/
@Test(expected = IllegalArgumentException.class)
public void testSetNullExpressionEngine()
{
new DefaultConfigurationKey(null);
}
/**
* Tests the isAttributeKey() method with several keys.
*/
@Test
public void testIsAttributeKey()
{
assertTrue("Attribute key not detected", key.isAttributeKey(TESTATTR));
assertFalse("Property key considered as attribute", key
.isAttributeKey(TESTPROPS));
assertFalse("Null key considered as attribute", key
.isAttributeKey(null));
}
/**
* Returns a builder for symbols with default property settings.
*
* @return the initialized builder object
*/
private DefaultExpressionEngineSymbols.Builder symbols()
{
return new DefaultExpressionEngineSymbols.Builder(
expressionEngine.getSymbols());
}
/**
* Tests if attribute keys are correctly detected if no end markers are set.
* (In this test case we use the same delimiter for attributes as for simple
* properties.)
*/
@Test
public void testIsAttributeKeyWithoutEndMarkers()
{
final DefaultExpressionEngineSymbols symbols =
symbols()
.setAttributeEnd(null)
.setAttributeStart(
DefaultExpressionEngineSymbols.DEFAULT_PROPERTY_DELIMITER)
.create();
expressionEngine = new DefaultExpressionEngine(symbols);
key = new DefaultConfigurationKey(expressionEngine);
assertTrue(
"Attribute key not detected",
key.isAttributeKey(DefaultExpressionEngineSymbols.DEFAULT_PROPERTY_DELIMITER
+ "test"));
assertFalse("Property key considered as attribute key",
key.isAttributeKey(TESTATTR));
}
/**
* Tests removing leading delimiters.
*/
@Test
public void testTrimLeft()
{
assertEquals("Key was not left trimmed", "test.", key
.trimLeft(".test."));
assertEquals("Too much left trimming", "..test.", key
.trimLeft("..test."));
}
/**
* Tests removing trailing delimiters.
*/
@Test
public void testTrimRight()
{
assertEquals("Key was not right trimmed", ".test", key
.trimRight(".test."));
assertEquals("Too much right trimming", ".test..", key
.trimRight(".test.."));
}
/**
* Tests removing delimiters.
*/
@Test
public void testTrim()
{
assertEquals("Key was not trimmed", "test", key.trim(".test."));
assertEquals("Null key could not be processed", "", key.trim(null));
assertEquals("Delimiter could not be processed", "", key
.trim(DefaultExpressionEngineSymbols.DEFAULT_PROPERTY_DELIMITER));
}
/**
* Tests appending keys.
*/
@Test
public void testAppend()
{
key.append("tables").append("table(0).");
key.append("fields.").append("field(1)");
key.append(null).append(TESTATTR);
assertEquals("Wrong key", TESTKEY, key.toString());
}
/**
* Tests appending keys that contain delimiters.
*/
@Test
public void testAppendDelimiters()
{
key.append("key..").append("test").append(".");
key.append(".more").append("..tests");
assertEquals("Wrong key", "key...test.more...tests", key.toString());
}
/**
* Tests appending keys that contain delimiters when no escaped delimiter
* is defined.
*/
@Test
public void testAppendDelimitersWithoutEscaping()
{
expressionEngine =
new DefaultExpressionEngine(symbols().setEscapedDelimiter(null)
.create());
key = new DefaultConfigurationKey(expressionEngine);
key.append("key.......").append("test").append(".");
key.append(".more").append("..tests");
assertEquals("Wrong constructed key", "key.test.more.tests", key
.toString());
}
/**
* Tests calling append with the escape flag.
*/
@Test
public void testAppendWithEscapeFlag()
{
key.append(".key.test.", true);
key.append(".more").append(".tests", true);
assertEquals("Wrong constructed key", "..key..test...more...tests", key
.toString());
}
/**
* Tests constructing keys for attributes.
*/
@Test
public void testConstructAttributeKey()
{
assertEquals("Wrong attribute key", TESTATTR, key
.constructAttributeKey("dataType"));
assertEquals("Attribute key was incorrectly converted", TESTATTR, key
.constructAttributeKey(TESTATTR));
assertEquals("Null key could not be processed", "", key
.constructAttributeKey(null));
}
/**
* Tests constructing attribute keys when no end markers are defined. In
* this test case we use the property delimiter as attribute prefix.
*/
@Test
public void testConstructAttributeKeyWithoutEndMarkers()
{
final DefaultExpressionEngineSymbols symbols =
symbols()
.setAttributeEnd(null)
.setAttributeStart(
expressionEngine.getSymbols()
.getPropertyDelimiter()).create();
expressionEngine = new DefaultExpressionEngine(symbols);
key = new DefaultConfigurationKey(expressionEngine);
assertEquals("Wrong attribute key", ".test", key
.constructAttributeKey("test"));
assertEquals("Attribute key was incorrectly converted", ".test", key
.constructAttributeKey(".test"));
}
/**
* Tests appending attribute keys.
*/
@Test
public void testAppendAttribute()
{
key.appendAttribute("dataType");
assertEquals("Attribute key not correctly appended", TESTATTR, key
.toString());
}
/**
* Tests appending an attribute key that is already decorated-
*/
@Test
public void testAppendDecoratedAttributeKey()
{
key.appendAttribute(TESTATTR);
assertEquals("Decorated attribute key not correctly appended",
TESTATTR, key.toString());
}
/**
* Tests appending a null attribute key.
*/
@Test
public void testAppendNullAttributeKey()
{
key.appendAttribute(null);
assertEquals("Null attribute key not correctly appended", "", key
.toString());
}
/**
* Tests appending an index to a key.
*/
@Test
public void testAppendIndex()
{
key.append("test").appendIndex(42);
assertEquals("Index was not correctly appended", "test(42)", key
.toString());
}
/**
* Tests constructing a complex key by chaining multiple append operations.
*/
@Test
public void testAppendComplexKey()
{
key.append("tables").append("table.").appendIndex(0);
key.append("fields.").append("field").appendIndex(1);
key.appendAttribute("dataType");
assertEquals("Wrong complex key", TESTKEY, key.toString());
}
/**
* Tests getting and setting the key's length.
*/
@Test
public void testLength()
{
key.append(TESTPROPS);
assertEquals("Wrong length", TESTPROPS.length(), key.length());
key.appendAttribute("dataType");
assertEquals("Wrong length", TESTKEY.length(), key.length());
key.setLength(TESTPROPS.length());
assertEquals("Wrong length after shortening", TESTPROPS.length(), key
.length());
assertEquals("Wrong resulting key", TESTPROPS, key.toString());
}
/**
* Tests comparing configuration keys.
*/
@Test
public void testEquals()
{
final DefaultConfigurationKey k1 = key(TESTKEY);
assertTrue("Key not equal to itself", k1.equals(k1));
final DefaultConfigurationKey k2 = key(TESTKEY);
assertTrue("Keys are not equal", k1.equals(k2));
assertTrue("Not reflexiv", k2.equals(k1));
assertEquals("Hash codes not equal", k1.hashCode(), k2.hashCode());
k2.append("anotherPart");
assertFalse("Keys considered equal", k1.equals(k2));
assertFalse("Keys considered equal (2)", k2.equals(k1));
assertFalse("Key equals null key", k1.equals(null));
assertFalse("Equal with string", k1.equals(TESTKEY));
}
/**
* Tests determining an attribute key's name.
*/
@Test
public void testAttributeName()
{
assertEquals("Plain key not detected", "test", key
.attributeName("test"));
assertEquals("Attribute markers not stripped", "dataType", key
.attributeName(TESTATTR));
assertNull("Null key not processed", key.attributeName(null));
}
/**
* Tests to iterate over a simple key.
*/
@Test
public void testIterate()
{
key.append(TESTKEY);
final DefaultConfigurationKey.KeyIterator it = key.iterator();
assertTrue("No key parts", it.hasNext());
assertEquals("Wrong key part", "tables", it.nextKey());
assertEquals("Wrong key part", "table", it.nextKey());
assertTrue("No index found", it.hasIndex());
assertEquals("Wrong index", 0, it.getIndex());
assertEquals("Wrong key part", "fields", it.nextKey());
assertFalse("Found an index", it.hasIndex());
assertEquals("Wrong key part", "field", it.nextKey(true));
assertEquals("Wrong index", 1, it.getIndex());
assertFalse("Found an attribute", it.isAttribute());
assertEquals("Wrong current key", "field", it.currentKey(true));
assertEquals("Wrong key part", "dataType", it.nextKey());
assertEquals("Wrong decorated key part", "[@dataType]", it
.currentKey(true));
assertTrue("Attribute not found", it.isAttribute());
assertFalse("Too many key parts", it.hasNext());
try
{
it.next();
fail("Could iterate over the iteration's end!");
}
catch (final NoSuchElementException nex)
{
// ok
}
}
/**
* Tests an iteration where the remove() method is called. This is not
* supported.
*/
@Test(expected = UnsupportedOperationException.class)
public void testIterateWithRemove()
{
assertFalse(key.iterator().hasNext());
key.append("simple");
final DefaultConfigurationKey.KeyIterator it = key.iterator();
assertTrue(it.hasNext());
assertEquals("simple", it.next());
it.remove();
}
/**
* Tests iterating over some funny keys.
*/
@Test
public void testIterateStrangeKeys()
{
key = new DefaultConfigurationKey(expressionEngine, "key.");
DefaultConfigurationKey.KeyIterator it = key.iterator();
assertTrue("Too few key parts", it.hasNext());
assertEquals("Wrong key part", "key", it.next());
assertFalse("Too many key parts", it.hasNext());
key = new DefaultConfigurationKey(expressionEngine, ".");
it = key.iterator();
assertFalse("Simple delimiter key has more parts", it.hasNext());
key = new DefaultConfigurationKey(expressionEngine,
"key().index()undefined(0).test");
it = key.iterator();
assertEquals("Wrong first part", "key()", it.next());
assertFalse("Index detected in first part", it.hasIndex());
assertEquals("Wrong second part", "index()undefined", it.nextKey(false));
assertTrue("No index detected in second part", it.hasIndex());
assertEquals("Wrong index value", 0, it.getIndex());
}
/**
* Tests iterating over keys with escaped delimiters.
*/
@Test
public void testIterateEscapedDelimiters()
{
key.append("my..elem");
key.append("trailing..dot..");
key.append(".strange");
assertEquals("my..elem.trailing..dot...strange", key.toString());
final DefaultConfigurationKey.KeyIterator kit = key.iterator();
assertEquals("Wrong first part", "my.elem", kit.nextKey());
assertEquals("Wrong second part", "trailing.dot.", kit.nextKey());
assertEquals("Wrong third part", "strange", kit.nextKey());
assertFalse("Too many parts", kit.hasNext());
}
/**
* Tests iterating over keys when a different escaped delimiter is used.
*/
@Test
public void testIterateAlternativeEscapeDelimiter()
{
expressionEngine =
new DefaultExpressionEngine(symbols()
.setEscapedDelimiter("\\.").create());
key = new DefaultConfigurationKey(expressionEngine);
key.append("\\.my\\.elem");
key.append("trailing\\.dot\\.");
key.append(".strange");
assertEquals("\\.my\\.elem.trailing\\.dot\\..strange", key.toString());
final DefaultConfigurationKey.KeyIterator kit = key.iterator();
assertEquals("Wrong first part", ".my.elem", kit.nextKey());
assertEquals("Wrong second part", "trailing.dot.", kit.nextKey());
assertEquals("Wrong third part", "strange", kit.nextKey());
assertFalse("Too many parts", kit.hasNext());
}
/**
* Tests iterating when no escape delimiter is defined.
*/
@Test
public void testIterateWithoutEscapeDelimiter()
{
expressionEngine =
new DefaultExpressionEngine(symbols()
.setEscapedDelimiter(null).create());
key = new DefaultConfigurationKey(expressionEngine);
key.append("..my..elem.trailing..dot...strange");
assertEquals("Wrong key", "my..elem.trailing..dot...strange", key
.toString());
final DefaultConfigurationKey.KeyIterator kit = key.iterator();
final String[] parts =
{ "my", "elem", "trailing", "dot", "strange"};
for (int i = 0; i < parts.length; i++)
{
assertEquals("Wrong key part " + i, parts[i], kit.next());
}
assertFalse("Too many parts", kit.hasNext());
}
/**
* Tests whether a key with brackets in it can be iterated over.
*/
@Test
public void testIterateWithBrackets()
{
key.append("directory.platform(x86).path");
final DefaultConfigurationKey.KeyIterator kit = key.iterator();
String part = kit.nextKey();
assertEquals("Wrong part 1", "directory", part);
assertFalse("Has index 1", kit.hasIndex());
part = kit.nextKey();
assertEquals("Wrong part 2", "platform(x86)", part);
assertFalse("Has index 2", kit.hasIndex());
part = kit.nextKey();
assertEquals("Wrong part 3", "path", part);
assertFalse("Has index 3", kit.hasIndex());
assertFalse("Too many elements", kit.hasNext());
}
/**
* Tests iterating over an attribute key that has an index.
*/
@Test
public void testAttributeKeyWithIndex()
{
key.append(TESTATTR);
key.appendIndex(0);
assertEquals("Wrong attribute key with index", TESTATTR + "(0)", key
.toString());
final DefaultConfigurationKey.KeyIterator it = key.iterator();
assertTrue("No first element", it.hasNext());
it.next();
assertTrue("Index not found", it.hasIndex());
assertEquals("Incorrect index", 0, it.getIndex());
assertTrue("Attribute not found", it.isAttribute());
assertEquals("Wrong plain key", "dataType", it.currentKey(false));
assertEquals("Wrong decorated key", TESTATTR, it.currentKey(true));
}
/**
* Tests iteration when the attribute markers equals the property delimiter.
*/
@Test
public void testIterateAttributeEqualsPropertyDelimiter()
{
expressionEngine =
new DefaultExpressionEngine(
symbols()
.setAttributeEnd(null)
.setAttributeStart(
DefaultExpressionEngineSymbols.DEFAULT_PROPERTY_DELIMITER)
.create());
key = new DefaultConfigurationKey(expressionEngine);
key.append("this.isa.key");
final DefaultConfigurationKey.KeyIterator kit = key.iterator();
assertEquals("Wrong first key part", "this", kit.next());
assertFalse("First part is an attribute", kit.isAttribute());
assertTrue("First part is not a property key", kit.isPropertyKey());
assertEquals("Wrong second key part", "isa", kit.next());
assertFalse("Second part is an attribute", kit.isAttribute());
assertTrue("Second part is not a property key", kit.isPropertyKey());
assertEquals("Wrong third key part", "key", kit.next());
assertTrue("Third part is not an attribute", kit.isAttribute());
assertTrue("Third part is not a property key", kit.isPropertyKey());
assertEquals("Wrong decorated key part", "key", kit.currentKey(true));
}
/**
* Tests whether common key parts can be extracted.
*/
@Test
public void testCommonKey()
{
final DefaultConfigurationKey k1 = key(TESTKEY);
DefaultConfigurationKey k2 = key("tables.table(0).name");
DefaultConfigurationKey kc = k1.commonKey(k2);
assertEquals("Wrong common key (1)", key("tables.table(0)"), kc);
assertEquals("Not symmetric", kc, k2.commonKey(k1));
k2 = key("tables.table(1).fields.field(1)");
kc = k1.commonKey(k2);
assertEquals("Wrong common key (2)", key("tables"), kc);
k2 = key("completely.different.key");
kc = k1.commonKey(k2);
assertEquals("Got a common key for different keys", 0, kc.length());
kc = k1.commonKey(key);
assertEquals("Got a common key for empty key", 0, kc.length());
kc = k1.commonKey(k1);
assertEquals("Wrong result for reflexiv invocation", kc, k1);
}
/**
* Tries to call commonKey() with null input.
*/
@Test(expected = IllegalArgumentException.class)
public void testCommonKeyNull()
{
key.commonKey(null);
}
/**
* Tests differenceKey() on the same object.
*/
@Test
public void testDifferenceKeySame()
{
final DefaultConfigurationKey k1 = key(TESTKEY);
final DefaultConfigurationKey kd = k1.differenceKey(k1);
assertEquals("Got difference for same keys", 0, kd.length());
}
/**
* Tests the differenceKey() method.
*/
@Test
public void testDifferenceKey()
{
final DefaultConfigurationKey k1 = key(TESTKEY);
DefaultConfigurationKey k2 = key("tables.table(0).name");
DefaultConfigurationKey kd = k1.differenceKey(k2);
assertEquals("Wrong difference (1)", "name", kd.toString());
k2 = key("tables.table(1).fields.field(1)");
kd = k1.differenceKey(k2);
assertEquals("Wrong difference (2)", "table(1).fields.field(1)", kd.toString());
k2 = key("completely.different.key");
kd = k1.differenceKey(k2);
assertEquals("Wrong difference (3)", k2, kd);
}
}