Better String[] Transformer, RFC.

This commit is contained in:
Ray Greenwell
2010-07-02 03:49:43 +00:00
parent 846ea920b6
commit f4c7b7fef4
@@ -20,8 +20,24 @@
package com.samskivert.depot;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import com.samskivert.depot.annotation.Column;
//import com.google.common.annotations.Beta;
import com.google.common.base.Preconditions;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
/**
* Contains various generally useful {@link Transformer} implementations. To use a transformer, you
* specify it via a {@link Column} annotation. For example:
@@ -57,4 +73,109 @@ public class Transformers
return values;
}
}
//@Beta
public static class StringArray implements Transformer<String[], String>
{
public String toPersistent (String[] value)
{
if (value == null) {
return null;
}
return StringIterable.toPersistent0(Arrays.asList(value));
}
public String[] fromPersistent (Class<?> ftype, String encoded)
{
if (encoded == null) {
return null;
}
return Iterables.toArray(StringIterable.fromPersistent0(encoded), String.class);
}
}
//@Beta
public static class StringIterable implements Transformer<Iterable<String>, String>
{
public String toPersistent (Iterable<String> value)
{
return toPersistent0(value);
}
public Iterable<String> fromPersistent (Class<?> ftype, String encoded)
{
ArrayList<String> value = fromPersistent0(encoded);
if (value == null ||
ftype == ArrayList.class || ftype == List.class || ftype == Collection.class ||
ftype == Iterable.class) {
return value;
}
if (ftype == LinkedList.class) {
return Lists.newLinkedList(value);
}
if (ftype == HashSet.class || ftype == Set.class) {
return Sets.newHashSet(value);
}
// else: reflection? See if it's a collection, call the 0-arg constructor, add all
// and return? Something?
return value;
}
protected static String toPersistent0 (Iterable<String> value)
{
if (value == null) {
return null;
}
StringBuilder buf = new StringBuilder();
for (String s : value) {
if (s == null) {
buf.append('\uFFFC');
} else {
s = s.replace("\\", "\\\\"); // turn \ into \\
s = s.replace("\n", "\\n"); // turn newline into \n
s = s.replace("\uFFFC", "\\\uFFFC"); // preslash the nullmarker too
buf.append(s).append('\n');
}
}
return buf.toString();
}
protected static ArrayList<String> fromPersistent0 (String encoded)
{
if (encoded == null) {
return null;
}
ArrayList<String> value = Lists.newArrayList();
StringBuilder buf = new StringBuilder(encoded.length());
for (int ii = 0, nn = encoded.length(); ii < nn; ii++) {
char c = encoded.charAt(ii);
switch (c) {
case '\uFFFC':
Preconditions.checkArgument(buf.length() == 0, "Invalid encoded string");
value.add(null);
break;
case '\n':
value.add(buf.toString()); // TODO: intern?
buf.setLength(0);
break;
case '\\':
try {
buf.append(encoded.charAt(++ii)); // take the next char at face value
} catch (IndexOutOfBoundsException e) {
throw new IllegalArgumentException("Invalid encoded string", e);
}
break;
default:
buf.append(c);
break;
}
}
// make sure there are no left-over characters
Preconditions.checkArgument(buf.length() == 0, "Invalid encoded string");
return value;
}
}
}