Skip to content

Instantly share code, notes, and snippets.

@aembleton
Created August 22, 2012 13:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aembleton/3425402 to your computer and use it in GitHub Desktop.
Save aembleton/3425402 to your computer and use it in GitHub Desktop.
KeyValue
package utils;
import java.util.HashSet;
import java.util.Set;
public class KeyValue {
private static final char DELIMITER = ':';
private static final char KEY_VALUE_DELIMITER = ',';
private static final char ESCAPE_CHAR = '\\';
private static enum State {
key, value
};
/**
* Converts a string of the format "key1:value1, key2:value2, key3:value3" into a set of {@link KeyValuePair}s containing the key value pairs. The control characters :, can be escaped with a
* backslash \
*
* @param str
* The string to process
* @return A {@link Set} of {@link KeyValuePair}s made up from the values in the str
*/
public static Set<KeyValuePair> fromString(String str) {
Set<KeyValuePair> set = new HashSet<KeyValuePair>();
if (str != null) {
StringBuffer key = new StringBuffer();
StringBuffer value = new StringBuffer();
State state = State.key;
char previousChar = ' ';
KeyValue keyValue = new KeyValue();
for (char c : str.toCharArray()) {
switch (c) {
case DELIMITER:
if (previousChar != ESCAPE_CHAR) {
state = State.value;
break;
}
case KEY_VALUE_DELIMITER:
if (previousChar != ESCAPE_CHAR) {
KeyValuePair pair = keyValue.new KeyValuePair(key, value);
set.add(pair);
// clean up
key = new StringBuffer();
value = new StringBuffer();
state = State.key;
break;
}
default:
if (c != ESCAPE_CHAR || previousChar == ESCAPE_CHAR) {
// append to the StringBuffer for either key or value
switch (state) {
case key:
key.append(c);
break;
case value:
value.append(c);
break;
}
}
break;
}
previousChar = c;
}
// add the remaining key value pair onto the set
KeyValuePair pair = keyValue.new KeyValuePair(key, value);
set.add(pair);
}
return set;
}
/**
* Bean to hold a key value pair.
*
* @author aembleton
*
*/
public class KeyValuePair {
private String key = "";
private String value = "";
private KeyValuePair(final StringBuffer keySb, final StringBuffer valueSb) {
if (keySb != null) {
key = keySb.toString().trim();
}
if (valueSb != null) {
value = valueSb.toString().trim();
}
}
public String getKey() {
return key;
}
public String getValue() {
return value;
}
}
}
import java.util.Iterator;
import java.util.Set;
import org.junit.Test;
import play.test.UnitTest;
import utils.KeyValue;
import utils.KeyValue.KeyValuePair;
public class KeyValueTest extends UnitTest {
@Test
public void singleKeyValue() {
Set<KeyValuePair> keyValue = KeyValue.fromString("hello:world");
assertNotNull(keyValue);
assertEquals(1, keyValue.size());
Iterator<KeyValuePair> iterator = keyValue.iterator();
KeyValuePair keyValuePair = iterator.next();
assertNotNull(keyValuePair);
assertEquals("hello", keyValuePair.getKey());
assertEquals("world", keyValuePair.getValue());
}
@Test
public void singleKeyValueWithEscapeInKey() {
Set<KeyValuePair> keyValue = KeyValue.fromString("he\\llo:world");
assertNotNull(keyValue);
assertEquals(1, keyValue.size());
Iterator<KeyValuePair> iterator = keyValue.iterator();
KeyValuePair keyValuePair = iterator.next();
assertNotNull(keyValuePair);
assertEquals("hello", keyValuePair.getKey());
assertEquals("world", keyValuePair.getValue());
}
@Test
public void singleKeyValueWithEscapeInValue() {
Set<KeyValuePair> keyValue = KeyValue.fromString("hello:wor\\ld");
assertNotNull(keyValue);
assertEquals(1, keyValue.size());
Iterator<KeyValuePair> iterator = keyValue.iterator();
KeyValuePair keyValuePair = iterator.next();
assertNotNull(keyValuePair);
assertEquals("hello", keyValuePair.getKey());
assertEquals("world", keyValuePair.getValue());
}
@Test
public void singleKeyValueWithEscapedDelimiter() {
Set<KeyValuePair> keyValue = KeyValue.fromString("hello\\:world");
assertNotNull(keyValue);
assertEquals(1, keyValue.size());
Iterator<KeyValuePair> iterator = keyValue.iterator();
KeyValuePair keyValuePair = iterator.next();
assertNotNull(keyValuePair);
assertEquals("hello:world", keyValuePair.getKey());
assertEquals("", keyValuePair.getValue());
}
@Test
public void multipleKeyValue() {
Set<KeyValuePair> keyValue = KeyValue.fromString("hello:world, foo:bar, name:arthur, customer:user123");
assertNotNull(keyValue);
assertEquals(4, keyValue.size());
Iterator<KeyValuePair> iterator = keyValue.iterator();
while (iterator.hasNext()) {
KeyValuePair keyValuePair = iterator.next();
assertNotNull(keyValuePair);
if (keyValuePair.getKey().equals("hello")) {
assertEquals("world", keyValuePair.getValue());
} else if (keyValuePair.getKey().equals("foo")) {
assertEquals("bar", keyValuePair.getValue());
} else if (keyValuePair.getKey().equals("name")) {
assertEquals("arthur", keyValuePair.getValue());
} else if (keyValuePair.getKey().equals("customer")) {
assertEquals("user123", keyValuePair.getValue());
} else {
fail("Unexpected key:" + keyValuePair.getKey() + " with value:" + keyValuePair.getValue());
}
}
}
@Test
public void multipleKeyValueWithEscapedSeperator() {
Set<KeyValuePair> keyValue = KeyValue.fromString("hello:world\\, foo:bar, name:arthur, customer:user123");
assertNotNull(keyValue);
assertEquals(3, keyValue.size());
Iterator<KeyValuePair> iterator = keyValue.iterator();
while (iterator.hasNext()) {
KeyValuePair keyValuePair = iterator.next();
assertNotNull(keyValuePair);
if (keyValuePair.getKey().equals("hello")) {
assertEquals("world, foobar", keyValuePair.getValue());
} else if (keyValuePair.getKey().equals("name")) {
assertEquals("arthur", keyValuePair.getValue());
} else if (keyValuePair.getKey().equals("customer")) {
assertEquals("user123", keyValuePair.getValue());
} else {
fail("Unexpected key:" + keyValuePair.getKey() + " with value:" + keyValuePair.getValue());
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment