More getters for VariantContext #712

Merged
merged 8 commits into from Nov 20, 2016
@@ -37,6 +37,8 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
/**
@@ -243,18 +245,62 @@ public Object getAttribute(String key, Object defaultValue) {
return defaultValue;
}
- /** returns the value as an empty list if the key was not found,
- as a java.util.List if the value is a List or an Array,
- as a Collections.singletonList if there is only one value */
+ /**
+ * Gets the attributes from a key as a list.
+ *
+ * Note: int[] and double[] arrays are boxed.
+ *
+ * @return empty list if the key was not found; {@link Collections#singletonList(Object)} if
+ * there is only one value; a list containing the values if the value is a {@link List} or array.
+ */
@SuppressWarnings("unchecked")
public List<Object> getAttributeAsList(String key) {
Object o = getAttribute(key);
if ( o == null ) return Collections.emptyList();
if ( o instanceof List ) return (List<Object>)o;
- if ( o.getClass().isArray() ) return Arrays.asList((Object[])o);
+ if ( o.getClass().isArray() ) {
+ if (o instanceof int[]) {
@yfarjoun

yfarjoun Nov 7, 2016

Contributor

please add a note about special handling of int[] and double[] to the javadoc so that the behavior will be clear.

@magicDGS

magicDGS Nov 7, 2016

Contributor

Done

+ return Arrays.stream((int[])o).boxed().collect(Collectors.toList());
+ } else if (o instanceof double[]) {
+ return Arrays.stream((double[])o).boxed().collect(Collectors.toList());
+ }
+ return Arrays.asList((Object[])o);
+ }
return Collections.singletonList(o);
}
+ private <T> List<T> getAttributeAsList(String key, Function<Object, T> transformer) {
+ return getAttributeAsList(key).stream().map(transformer).collect(Collectors.toList());
+ }
+
+ public List<String> getAttributeAsStringList(String key, String defaultValue) {
+ return getAttributeAsList(key, x -> (x == null) ? defaultValue : String.valueOf(x));
+ }
+
+ public List<Integer> getAttributeAsIntList(String key, Integer defaultValue) {
+ return getAttributeAsList(key, x -> {
+ if (x == null || x == VCFConstants.MISSING_VALUE_v4) {
+ return defaultValue;
+ } else if (x instanceof Number) {
+ return ((Number) x).intValue();
+ } else {
+ return Integer.valueOf((String)x); // throws an exception if this isn't a string
+ }
+ });
+ }
+
+ public List<Double> getAttributeAsDoubleList(String key, Double defaultValue) {
+ return getAttributeAsList(key, x -> {
+ if (x == null || x == VCFConstants.MISSING_VALUE_v4) {
+ return defaultValue;
+ } else if (x instanceof Number) {
+ return ((Number) x).doubleValue();
+ } else {
+ return Double.valueOf((String)x); // throws an exception if this isn't a string
+ }
+ });
+ }
+
public String getAttributeAsString(String key, String defaultValue) {
Object x = getAttribute(key);
if ( x == null ) return defaultValue;
@@ -747,7 +747,9 @@ public Object getAttribute(String key, Object defaultValue) {
as a java.util.List if the value is a List or an Array,
as a Collections.singletonList if there is only one value */
public List<Object> getAttributeAsList(String key) { return commonInfo.getAttributeAsList(key); }
-
+ public List<String> getAttributeAsStringList(String key, String defaultValue) { return commonInfo.getAttributeAsStringList(key, defaultValue); }
+ public List<Integer> getAttributeAsIntList(String key, int defaultValue) { return commonInfo.getAttributeAsIntList(key, defaultValue); }
+ public List<Double> getAttributeAsDoubleList(String key, double defaultValue) { return commonInfo.getAttributeAsDoubleList(key, defaultValue); }
public CommonInfo getCommonInfo() {
return commonInfo;
}
@@ -38,7 +38,6 @@
import htsjdk.variant.bcf2.BCF2Codec;
import htsjdk.variant.vcf.VCFCodec;
import htsjdk.tribble.TribbleException;
-import htsjdk.variant.VariantBaseTest;
import htsjdk.variant.vcf.VCFConstants;
import htsjdk.variant.vcf.VCFFileReader;
@@ -1478,4 +1477,76 @@ public void testExtractStructuralVariationsData(final File vcfFile) {
CloserUtil.close(reader);
}
}
+
+ @Test
+ public void testGetAttributeAsIntList() {
+ final VariantContext context = basicBuilder
+ .attribute("Empty", new int[0])
+ .attribute("DefaultIntegerList", new int[5])
+ .attribute("ListWithMissing", new Object[]{1, null, null})
+ .attribute("IntegerList", new int[]{0, 1, 2, 3})
+ .attribute("DoubleList", new double[]{1.8, 1.6, 2.1})
+ .attribute("StringList", new String[]{"1", "2"})
+ .attribute("NotNumeric", new String[]{"A", "B"})
+ .make();
+ // test an empty value
+ Assert.assertTrue(context.getAttributeAsIntList("Empty", 5).isEmpty());
+ // test as integer
+ Assert.assertEquals(context.getAttributeAsIntList("DefaultIntegerList", 5), Arrays.asList(0, 0, 0, 0, 0));
+ Assert.assertEquals(context.getAttributeAsIntList("ListWithMissing", 5), Arrays.asList(1, 5, 5));
+ Assert.assertEquals(context.getAttributeAsIntList("IntegerList", 5), Arrays.asList(0, 1, 2, 3));
+ Assert.assertEquals(context.getAttributeAsIntList("DoubleList", 5), Arrays.asList(1, 1, 2));
+ Assert.assertEquals(context.getAttributeAsIntList("StringList", 5), Arrays.asList(1, 2));
+ Assert.assertThrows(() -> context.getAttributeAsIntList("NotNumeric", 5));
+ // test the case of a missing key
+ Assert.assertTrue(context.getAttributeAsIntList("MissingList", 5).isEmpty());
+ }
+
+ @Test
+ public void testGetAttributeAsDoubleList() {
+ final VariantContext context = basicBuilder
+ .attribute("Empty", new int[0])
+ .attribute("DefaultIntegerList", new int[5])
+ .attribute("ListWithMissing", new Object[]{1, null, null})
+ .attribute("IntegerList", new int[]{0, 1, 2, 3})
+ .attribute("DoubleList", new double[]{1.8, 1.6, 2.1})
+ .attribute("StringList", new String[]{"1", "2"})
+ .attribute("NotNumeric", new String[]{"A", "B"})
+ .make();
+ // test an empty value
+ Assert.assertTrue(context.getAttributeAsDoubleList("Empty", 5).isEmpty());
+ // test as double
+ Assert.assertEquals(context.getAttributeAsDoubleList("DefaultIntegerList", 5), Arrays.asList(0d, 0d, 0d, 0d, 0d));
+ Assert.assertEquals(context.getAttributeAsDoubleList("ListWithMissing", 5), Arrays.asList(1d, 5d, 5d));
+ Assert.assertEquals(context.getAttributeAsDoubleList("IntegerList", 5), Arrays.asList(0d, 1d, 2d, 3d));
+ Assert.assertEquals(context.getAttributeAsDoubleList("DoubleList", 5), Arrays.asList(1.8, 1.6, 2.1));
+ Assert.assertEquals(context.getAttributeAsDoubleList("StringList", 5), Arrays.asList(1d, 2d));
+ Assert.assertThrows(() -> context.getAttributeAsDoubleList("NotNumeric", 5));
+ // test the case of a missing key
+ Assert.assertTrue(context.getAttributeAsDoubleList("MissingList", 5).isEmpty());
+ }
+
+ @Test
+ public void testGetAttributeAsStringList() {
+ final VariantContext context = basicBuilder
+ .attribute("Empty", new int[0])
+ .attribute("DefaultIntegerList", new int[5])
+ .attribute("ListWithMissing", new Object[]{1, null, null})
+ .attribute("IntegerList", new int[]{0, 1, 2, 3})
+ .attribute("DoubleList", new double[]{1.8, 1.6, 2.1})
+ .attribute("StringList", new String[]{"1", "2"})
+ .attribute("NotNumeric", new String[]{"A", "B"})
+ .make();
+ // test an empty value
+ Assert.assertTrue(context.getAttributeAsStringList("Empty", "empty").isEmpty());
+ // test as string
+ Assert.assertEquals(context.getAttributeAsStringList("DefaultIntegerList", "empty"), Arrays.asList("0", "0", "0", "0", "0"));
+ Assert.assertEquals(context.getAttributeAsStringList("ListWithMissing", "empty"), Arrays.asList("1", "empty", "empty"));
+ Assert.assertEquals(context.getAttributeAsStringList("IntegerList", "empty"), Arrays.asList("0", "1", "2", "3"));
+ Assert.assertEquals(context.getAttributeAsStringList("DoubleList", "empty"), Arrays.asList("1.8", "1.6", "2.1"));
+ Assert.assertEquals(context.getAttributeAsStringList("StringList", "empty"), Arrays.asList("1", "2"));
+ Assert.assertEquals(context.getAttributeAsStringList("NotNumeric", "empty"), Arrays.asList("A", "B"));
@yfarjoun

yfarjoun Nov 19, 2016

Contributor

please test an empty list and a missing list (here and in the other tests too!)

@magicDGS

magicDGS Nov 20, 2016

Contributor

Done

+ // test the case of a missing key
+ Assert.assertTrue(context.getAttributeAsStringList("MissingList", "empty").isEmpty());
+ }
}