Make ExtendedProperties support List rather than just Vector

bug 36812, from Henning P. Schmiedehausen

git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/collections/trunk@333060 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Stephen Colebourne 2005-11-13 16:59:51 +00:00
parent e6c681f115
commit d29ce53657
3 changed files with 135 additions and 36 deletions

View File

@ -67,6 +67,8 @@ If this causes major headaches to anyone please contact commons-dev at jakarta.a
<li>CollectionUtils/MapUtils.isEmpty/isNotEmpty - Null-safe checks of collection emptyness [35890]</li> <li>CollectionUtils/MapUtils.isEmpty/isNotEmpty - Null-safe checks of collection emptyness [35890]</li>
<li>CollectionUtils.sizeIsEmpty - Checks if a collection, array, map, iterator or enumeration is empty</li> <li>CollectionUtils.sizeIsEmpty - Checks if a collection, array, map, iterator or enumeration is empty</li>
<li>CollectionUtils/ListUtils - retainAll/removeAll that don't change original colllection</li> <li>CollectionUtils/ListUtils - retainAll/removeAll that don't change original colllection</li>
<li>ExtendedProperties - Accepts List elements (does not enforce Vector) as values [36812]</li>
<li>ExtendedProperties - new Methods getList(String key) and getList(String key, List defaults) [36812]</li>
<li>ExtendedProperties - No longer uses an exception in normal processing [30497]</li> <li>ExtendedProperties - No longer uses an exception in normal processing [30497]</li>
<li>BlockingBuffer - now includes stack trace if InterupttedException occurs [33700]</li> <li>BlockingBuffer - now includes stack trace if InterupttedException occurs [33700]</li>
<li>BlockingBuffer - new methods that allow get and remove with a timeout [27691]</li> <li>BlockingBuffer - new methods that allow get and remove with a timeout [27691]</li>

View File

@ -138,6 +138,7 @@ import java.util.Vector;
* @author Mohan Kishore * @author Mohan Kishore
* @author Stephen Colebourne * @author Stephen Colebourne
* @author Shinobu Kawai * @author Shinobu Kawai
* @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
*/ */
public class ExtendedProperties extends Hashtable { public class ExtendedProperties extends Hashtable {
@ -691,14 +692,14 @@ public class ExtendedProperties extends Hashtable {
if (current instanceof String) { if (current instanceof String) {
// one object already in map - convert it to a vector // one object already in map - convert it to a vector
Vector v = new Vector(2); List values = new Vector(2);
v.addElement(current); values.add(current);
v.addElement(value); values.add(value);
put(key, v); put(key, values);
} else if (current instanceof Vector) { } else if (current instanceof List) {
// already a vector - just add the new token // already a list - just add the new token
((Vector) current).addElement(value); ((List) current).add(value);
} else { } else {
// brand new key - store in keysAsListed to retain order // brand new key - store in keysAsListed to retain order
@ -752,11 +753,10 @@ public class ExtendedProperties extends Hashtable {
currentOutput.append(escape((String) value)); currentOutput.append(escape((String) value));
theWrtr.println(currentOutput.toString()); theWrtr.println(currentOutput.toString());
} else if (value instanceof Vector) { } else if (value instanceof List) {
Vector values = (Vector) value; List values = (List) value;
Enumeration valuesEnum = values.elements(); for (Iterator it = values.iterator(); it.hasNext(); ) {
while (valuesEnum.hasMoreElements()) { String currentElement = (String) it.next();
String currentElement = (String) valuesEnum.nextElement();
StringBuffer currentOutput = new StringBuffer(); StringBuffer currentOutput = new StringBuffer();
currentOutput.append(key); currentOutput.append(key);
currentOutput.append("="); currentOutput.append("=");
@ -931,8 +931,8 @@ public class ExtendedProperties extends Hashtable {
} else { } else {
return interpolate(defaultValue); return interpolate(defaultValue);
} }
} else if (value instanceof Vector) { } else if (value instanceof List) {
return interpolate((String) ((Vector) value).get(0)); return interpolate((String) ((List) value).get(0));
} else { } else {
throw new ClassCastException('\'' + key + "' doesn't map to a String object"); throw new ClassCastException('\'' + key + "' doesn't map to a String object");
} }
@ -945,7 +945,7 @@ public class ExtendedProperties extends Hashtable {
* @param key The configuration key. * @param key The configuration key.
* @return The associated properties if key is found. * @return The associated properties if key is found.
* @throws ClassCastException is thrown if the key maps to an * @throws ClassCastException is thrown if the key maps to an
* object that is not a String/Vector. * object that is not a String/List.
* @throws IllegalArgumentException if one of the tokens is * @throws IllegalArgumentException if one of the tokens is
* malformed (does not contain an equals sign). * malformed (does not contain an equals sign).
*/ */
@ -960,7 +960,7 @@ public class ExtendedProperties extends Hashtable {
* @param key The configuration key. * @param key The configuration key.
* @return The associated properties if key is found. * @return The associated properties if key is found.
* @throws ClassCastException is thrown if the key maps to an * @throws ClassCastException is thrown if the key maps to an
* object that is not a String/Vector. * object that is not a String/List.
* @throws IllegalArgumentException if one of the tokens is * @throws IllegalArgumentException if one of the tokens is
* malformed (does not contain an equals sign). * malformed (does not contain an equals sign).
*/ */
@ -993,19 +993,18 @@ public class ExtendedProperties extends Hashtable {
* @param key The configuration key. * @param key The configuration key.
* @return The associated string array if key is found. * @return The associated string array if key is found.
* @throws ClassCastException is thrown if the key maps to an * @throws ClassCastException is thrown if the key maps to an
* object that is not a String/Vector. * object that is not a String/List.
*/ */
public String[] getStringArray(String key) { public String[] getStringArray(String key) {
Object value = get(key); Object value = get(key);
// What's your vector, Victor? List values;
Vector vector;
if (value instanceof String) { if (value instanceof String) {
vector = new Vector(1); values = new Vector(1);
vector.addElement(value); values.add(value);
} else if (value instanceof Vector) { } else if (value instanceof List) {
vector = (Vector) value; values = (List) value;
} else if (value == null) { } else if (value == null) {
if (defaults != null) { if (defaults != null) {
@ -1014,12 +1013,12 @@ public class ExtendedProperties extends Hashtable {
return new String[0]; return new String[0];
} }
} else { } else {
throw new ClassCastException('\'' + key + "' doesn't map to a String/Vector object"); throw new ClassCastException('\'' + key + "' doesn't map to a String/List object");
} }
String[] tokens = new String[vector.size()]; String[] tokens = new String[values.size()];
for (int i = 0; i < tokens.length; i++) { for (int i = 0; i < tokens.length; i++) {
tokens[i] = (String) vector.elementAt(i); tokens[i] = (String) values.get(i);
} }
return tokens; return tokens;
@ -1039,8 +1038,10 @@ public class ExtendedProperties extends Hashtable {
} }
/** /**
* Get a Vector of strings associated with the given configuration * Get a Vector of strings associated with the given configuration key.
* key. * <p>
* The list is a copy of the internal data of this object, and as
* such you may alter it freely.
* *
* @param key The configuration key. * @param key The configuration key.
* @param defaultValue The default value. * @param defaultValue The default value.
@ -1051,14 +1052,14 @@ public class ExtendedProperties extends Hashtable {
public Vector getVector(String key, Vector defaultValue) { public Vector getVector(String key, Vector defaultValue) {
Object value = get(key); Object value = get(key);
if (value instanceof Vector) { if (value instanceof List) {
return (Vector) value; return new Vector((List) value);
} else if (value instanceof String) { } else if (value instanceof String) {
Vector v = new Vector(1); Vector values = new Vector(1);
v.addElement(value); values.add(value);
put(key, v); put(key, values);
return v; return values;
} else if (value == null) { } else if (value == null) {
if (defaults != null) { if (defaults != null) {
@ -1071,6 +1072,56 @@ public class ExtendedProperties extends Hashtable {
} }
} }
/**
* Get a List of strings associated with the given configuration key.
* <p>
* The list is a copy of the internal data of this object, and as
* such you may alter it freely.
*
* @param key The configuration key.
* @return The associated List object.
* @throws ClassCastException is thrown if the key maps to an
* object that is not a List.
*/
public List getList(String key) {
return getList(key, null);
}
/**
* Get a List of strings associated with the given configuration key.
* <p>
* The list is a copy of the internal data of this object, and as
* such you may alter it freely.
*
* @param key The configuration key.
* @param defaultValue The default value.
* @return The associated List.
* @throws ClassCastException is thrown if the key maps to an
* object that is not a List.
*/
public List getList(String key, List defaultValue) {
Object value = get(key);
if (value instanceof List) {
return new ArrayList((List) value);
} else if (value instanceof String) {
List values = new ArrayList(1);
values.add(value);
put(key, values);
return values;
} else if (value == null) {
if (defaults != null) {
return defaults.getList(key, defaultValue);
} else {
return ((defaultValue == null) ? new ArrayList() : defaultValue);
}
} else {
throw new ClassCastException('\'' + key + "' doesn't map to a List object");
}
}
/** /**
* Get a boolean associated with the given configuration key. * Get a boolean associated with the given configuration key.
* *

View File

@ -33,6 +33,7 @@ import junit.framework.TestSuite;
* @author Mohan Kishore * @author Mohan Kishore
* @author Stephen Colebourne * @author Stephen Colebourne
* @author Shinobu Kawai * @author Shinobu Kawai
* @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
*/ */
public class TestExtendedProperties extends TestCase { public class TestExtendedProperties extends TestCase {
@ -65,14 +66,15 @@ public class TestExtendedProperties extends TestCase {
assertEquals("This returns '1'", eprop.getString("number"), "1"); assertEquals("This returns '1'", eprop.getString("number"), "1");
/* /*
* now add another and get a Vector * now add another and get a Vector/list
*/ */
eprop.addProperty("number", "2"); eprop.addProperty("number", "2");
assertTrue("This returns array", (eprop.getVector("number") instanceof java.util.Vector)); assertTrue("This returns array", (eprop.getVector("number") instanceof java.util.Vector));
assertTrue("This returns array", (eprop.getList("number") instanceof java.util.List));
/* /*
* now test dan's new fix where we get the first scalar * now test dan's new fix where we get the first scalar
* when we access a vector valued * when we access a vector/list valued
* property * property
*/ */
assertTrue("This returns scalar", (eprop.getString("number") instanceof String)); assertTrue("This returns scalar", (eprop.getString("number") instanceof String));
@ -83,6 +85,7 @@ public class TestExtendedProperties extends TestCase {
String prop = "hey, that's a test"; String prop = "hey, that's a test";
eprop.setProperty("prop.string", prop); eprop.setProperty("prop.string", prop);
assertTrue("This returns vector", (eprop.getVector("prop.string") instanceof java.util.Vector)); assertTrue("This returns vector", (eprop.getVector("prop.string") instanceof java.util.Vector));
assertTrue("This returns list", (eprop.getList("prop.string") instanceof java.util.List));
String prop2 = "hey\\, that's a test"; String prop2 = "hey\\, that's a test";
eprop.remove("prop.string"); eprop.remove("prop.string");
@ -99,6 +102,7 @@ public class TestExtendedProperties extends TestCase {
assertTrue("Returns the full string", subEprop.getString("string").equals(prop)); assertTrue("Returns the full string", subEprop.getString("string").equals(prop));
assertTrue("This returns string for subset", (subEprop.getString("string") instanceof java.lang.String)); assertTrue("This returns string for subset", (subEprop.getString("string") instanceof java.lang.String));
assertTrue("This returns array for subset", (subEprop.getVector("string") instanceof java.util.Vector)); assertTrue("This returns array for subset", (subEprop.getVector("string") instanceof java.util.Vector));
assertTrue("This returns array for subset", (subEprop.getList("string") instanceof java.util.List));
} }
@ -134,6 +138,13 @@ public class TestExtendedProperties extends TestCase {
assertEquals("Commas not interpreted properly", assertEquals("Commas not interpreted properly",
"World", ep1.getVector("three").get(1)); "World", ep1.getVector("three").get(1));
assertEquals("Commas not interpreted properly",
2, ep1.getList("three").size());
assertEquals("Commas not interpreted properly",
"Hello", ep1.getList("three").get(0));
assertEquals("Commas not interpreted properly",
"World", ep1.getList("three").get(1));
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
ep1.save(baos, null); ep1.save(baos, null);
bytes = baos.toByteArray(); bytes = baos.toByteArray();
@ -186,10 +197,16 @@ public class TestExtendedProperties extends TestCase {
ByteArrayInputStream bais = new ByteArrayInputStream(bytes); ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ep1.load(bais); ep1.load(bais);
assertEquals(1, ep1.size()); assertEquals(1, ep1.size());
assertEquals(3, ep1.getVector("one").size()); assertEquals(3, ep1.getVector("one").size());
assertEquals("a", ep1.getVector("one").get(0)); assertEquals("a", ep1.getVector("one").get(0));
assertEquals("b", ep1.getVector("one").get(1)); assertEquals("b", ep1.getVector("one").get(1));
assertEquals("c", ep1.getVector("one").get(2)); assertEquals("c", ep1.getVector("one").get(2));
assertEquals(3, ep1.getList("one").size());
assertEquals("a", ep1.getList("one").get(0));
assertEquals("b", ep1.getList("one").get(1));
assertEquals("c", ep1.getList("one").get(2));
} }
public void testMultipleSameKey2() throws Exception { public void testMultipleSameKey2() throws Exception {
@ -205,11 +222,18 @@ public class TestExtendedProperties extends TestCase {
ByteArrayInputStream bais = new ByteArrayInputStream(bytes); ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ep1.load(bais); ep1.load(bais);
assertEquals(1, ep1.size()); assertEquals(1, ep1.size());
assertEquals(4, ep1.getVector("one").size()); assertEquals(4, ep1.getVector("one").size());
assertEquals("a", ep1.getVector("one").get(0)); assertEquals("a", ep1.getVector("one").get(0));
assertEquals("b", ep1.getVector("one").get(1)); assertEquals("b", ep1.getVector("one").get(1));
assertEquals("c", ep1.getVector("one").get(2)); assertEquals("c", ep1.getVector("one").get(2));
assertEquals("d", ep1.getVector("one").get(3)); assertEquals("d", ep1.getVector("one").get(3));
assertEquals(4, ep1.getList("one").size());
assertEquals("a", ep1.getList("one").get(0));
assertEquals("b", ep1.getList("one").get(1));
assertEquals("c", ep1.getList("one").get(2));
assertEquals("d", ep1.getList("one").get(3));
} }
public void testMultipleSameKey3() throws Exception { public void testMultipleSameKey3() throws Exception {
@ -225,10 +249,16 @@ public class TestExtendedProperties extends TestCase {
ByteArrayInputStream bais = new ByteArrayInputStream(bytes); ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ep1.load(bais); ep1.load(bais);
assertEquals(1, ep1.size()); assertEquals(1, ep1.size());
assertEquals(3, ep1.getVector("one").size()); assertEquals(3, ep1.getVector("one").size());
assertEquals("a", ep1.getVector("one").get(0)); assertEquals("a", ep1.getVector("one").get(0));
assertEquals("b", ep1.getVector("one").get(1)); assertEquals("b", ep1.getVector("one").get(1));
assertEquals("c", ep1.getVector("one").get(2)); assertEquals("c", ep1.getVector("one").get(2));
assertEquals(3, ep1.getList("one").size());
assertEquals("a", ep1.getList("one").get(0));
assertEquals("b", ep1.getList("one").get(1));
assertEquals("c", ep1.getList("one").get(2));
} }
public void testMultipleSameKeyByCode() throws Exception { public void testMultipleSameKeyByCode() throws Exception {
@ -236,22 +266,38 @@ public class TestExtendedProperties extends TestCase {
ep1.addProperty("one", "a"); ep1.addProperty("one", "a");
assertEquals(1, ep1.size()); assertEquals(1, ep1.size());
assertEquals(1, ep1.getVector("one").size()); assertEquals(1, ep1.getVector("one").size());
assertEquals("a", ep1.getVector("one").get(0)); assertEquals("a", ep1.getVector("one").get(0));
assertEquals(1, ep1.getList("one").size());
assertEquals("a", ep1.getList("one").get(0));
ep1.addProperty("one", Boolean.TRUE); ep1.addProperty("one", Boolean.TRUE);
assertEquals(1, ep1.size()); assertEquals(1, ep1.size());
assertEquals(2, ep1.getVector("one").size()); assertEquals(2, ep1.getVector("one").size());
assertEquals("a", ep1.getVector("one").get(0)); assertEquals("a", ep1.getVector("one").get(0));
assertEquals(Boolean.TRUE, ep1.getVector("one").get(1)); assertEquals(Boolean.TRUE, ep1.getVector("one").get(1));
assertEquals(2, ep1.getList("one").size());
assertEquals("a", ep1.getList("one").get(0));
assertEquals(Boolean.TRUE, ep1.getList("one").get(1));
ep1.addProperty("one", "c,d"); ep1.addProperty("one", "c,d");
assertEquals(1, ep1.size()); assertEquals(1, ep1.size());
assertEquals(4, ep1.getVector("one").size()); assertEquals(4, ep1.getVector("one").size());
assertEquals("a", ep1.getVector("one").get(0)); assertEquals("a", ep1.getVector("one").get(0));
assertEquals(Boolean.TRUE, ep1.getVector("one").get(1)); assertEquals(Boolean.TRUE, ep1.getVector("one").get(1));
assertEquals("c", ep1.getVector("one").get(2)); assertEquals("c", ep1.getVector("one").get(2));
assertEquals("d", ep1.getVector("one").get(3)); assertEquals("d", ep1.getVector("one").get(3));
assertEquals(4, ep1.getList("one").size());
assertEquals("a", ep1.getList("one").get(0));
assertEquals(Boolean.TRUE, ep1.getList("one").get(1));
assertEquals("c", ep1.getList("one").get(2));
assertEquals("d", ep1.getList("one").get(3));
} }
public void testInheritDefaultProperties() { public void testInheritDefaultProperties() {