Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: missing value for format fields is an empty string rather than a… #94

Merged
merged 1 commit into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ private Object getNestedVepValue(Field field) {
String separator = Pattern.quote(nestedField.getParent().getSeparator().toString());
int index = nestedField.getIndex();
String parentId = nestedField.getParent().getId();
List<String> infoValues = VcfUtils.getInfoAsStringList(variantContext, parentId);
List<String> infoValues = VcfUtils.getInfoAsStringList(variantContext, parentId, VCFConstants.MISSING_VALUE_v4);
if (!infoValues.isEmpty()) {
String singleValue = infoValues.get(0);
String[] split = singleValue.split(separator, -1);
Expand Down
69 changes: 40 additions & 29 deletions src/main/java/org/molgenis/vcf/decisiontree/utils/VcfUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@ private VcfUtils() {

public static Integer getInfoAsInteger(VariantContext variantContext, Field field) {
Object value = variantContext.getAttribute(field.getId());
return getVcfValueAsInteger(value);
String missingValue = getMissingValue(field);
return getVcfValueAsInteger(value, missingValue);
}

public static List<Integer> getInfoAsIntegerList(VariantContext variantContext, Field field) {
List<Integer> integerValues;

String missingValue = getMissingValue(field);
Object value = variantContext.getAttribute(field.getId());
if (value == null) {
integerValues = List.of();
Expand All @@ -44,15 +46,15 @@ public static List<Integer> getInfoAsIntegerList(VariantContext variantContext,
if (size == 0) {
integerValues = emptyList();
} else if (size == 1) {
integerValues = singletonList(getVcfValueAsInteger(objectValues.get(0)));
integerValues = singletonList(getVcfValueAsInteger(objectValues.get(0), missingValue));
} else {
integerValues = new ArrayList<>(objectValues.size());
for (Object objValue : objectValues) {
integerValues.add(getVcfValueAsInteger(objValue));
integerValues.add(getVcfValueAsInteger(objValue, missingValue));
}
}
} else if (value instanceof String stringValue) {
integerValues = singletonList(getInfoStringValueAsInteger(stringValue));
integerValues = singletonList(getInfoStringValueAsInteger(stringValue, missingValue));
} else {
throw new TypeConversionException(value, Integer.class);
}
Expand All @@ -61,24 +63,24 @@ public static List<Integer> getInfoAsIntegerList(VariantContext variantContext,
}

private static @Nullable
Integer getVcfValueAsInteger(@Nullable Object objValue) {
Integer getVcfValueAsInteger(@Nullable Object objValue, String missingValue) {
Integer intValue;
if (objValue == null) {
intValue = null;
} else if (objValue instanceof Integer integer) {
intValue = integer;
} else if (objValue instanceof String stringValue) {
intValue = getInfoStringValueAsInteger(stringValue);
intValue = getInfoStringValueAsInteger(stringValue, missingValue);
} else {
throw new TypeConversionException(objValue, Integer.class);
}
return intValue;
}

private static @Nullable
Integer getInfoStringValueAsInteger(String infoStrValue) {
Integer getInfoStringValueAsInteger(String infoStrValue, String missingValue) {
Integer intValue;
if (infoStrValue.equals(VCFConstants.MISSING_VALUE_v4)) {
if (infoStrValue.equals(missingValue)) {
intValue = null;
} else {
intValue = Integer.valueOf(infoStrValue);
Expand All @@ -88,11 +90,13 @@ Integer getInfoStringValueAsInteger(String infoStrValue) {

public static Double getInfoAsDouble(VariantContext variantContext, Field field) {
Object value = variantContext.getAttribute(field.getId());
return getVcfValueAsDouble(value);
String missingValue = getMissingValue(field);
return getVcfValueAsDouble(value, missingValue);
}

public static List<Double> getInfoAsDoubleList(VariantContext variantContext, Field field) {
List<Double> doubleValues;
String missingValue = getMissingValue(field);

Object value = variantContext.getAttribute(field.getId());
if (value == null) {
Expand All @@ -102,41 +106,45 @@ public static List<Double> getInfoAsDoubleList(VariantContext variantContext, Fi
if (size == 0) {
doubleValues = emptyList();
} else if (size == 1) {
doubleValues = singletonList(getVcfValueAsDouble(objectValues.get(0)));
doubleValues = singletonList(getVcfValueAsDouble(objectValues.get(0), missingValue));
} else {
doubleValues = new ArrayList<>(objectValues.size());
for (Object objValue : objectValues) {
doubleValues.add(getVcfValueAsDouble(objValue));
doubleValues.add(getVcfValueAsDouble(objValue, missingValue));
}
}
} else if (value instanceof String string) {
doubleValues = singletonList(getInfoStringValueAsDouble(string));
doubleValues = singletonList(getInfoStringValueAsDouble(string, missingValue));
} else {
throw new TypeConversionException(value, Double.class);
}

return doubleValues;
}

private static String getMissingValue(Field field) {
return field.getFieldType() == FORMAT ? "" : VCFConstants.MISSING_VALUE_v4;
}

private static @Nullable
Double getVcfValueAsDouble(@Nullable Object objValue) {
Double getVcfValueAsDouble(@Nullable Object objValue, String missingValue) {
Double doubleValue;
if (objValue == null) {
doubleValue = null;
} else if (objValue instanceof Double doubleVal) {
doubleValue = doubleVal;
} else if (objValue instanceof String string) {
doubleValue = getInfoStringValueAsDouble(string);
doubleValue = getInfoStringValueAsDouble(string, missingValue);
} else {
throw new TypeConversionException(objValue, Double.class);
}
return doubleValue;
}

private static @Nullable
Double getInfoStringValueAsDouble(String infoStrValue) {
Double getInfoStringValueAsDouble(String infoStrValue, String missingValue) {
Double doubleValue;
if (infoStrValue.equals(VCFConstants.MISSING_VALUE_v4)) {
if (infoStrValue.equals(missingValue)) {
doubleValue = null;
} else {
doubleValue = Double.valueOf(infoStrValue);
Expand All @@ -146,19 +154,21 @@ Double getInfoStringValueAsDouble(String infoStrValue) {

public static String getInfoAsString(VariantContext variantContext, Field field) {
Object value = variantContext.getAttribute(field.getId());
return getVcfValueAsString(value);
String missingValue = getMissingValue(field);
return getVcfValueAsString(value, missingValue);
}

public static List<String> getInfoAsStringList(VariantContext variantContext, Field field) {
List<String> strValues;
String id = field.getId();
String missingValue = getMissingValue(field);

strValues = getInfoAsStringList(variantContext, id);
strValues = getInfoAsStringList(variantContext, id, missingValue);

return strValues;
}

public static List<String> getInfoAsStringList(VariantContext variantContext, String id) {
public static List<String> getInfoAsStringList(VariantContext variantContext, String id, String missingValue) {
List<String> strValues;
Object value = variantContext.getAttribute(id);
if (value == null) {
Expand All @@ -168,15 +178,15 @@ public static List<String> getInfoAsStringList(VariantContext variantContext, St
if (size == 0) {
strValues = emptyList();
} else if (size == 1) {
strValues = singletonList(getVcfValueAsString(objectValues.get(0)));
strValues = singletonList(getVcfValueAsString(objectValues.get(0), missingValue));
} else {
strValues = new ArrayList<>(objectValues.size());
for (Object objValue : objectValues) {
strValues.add(getVcfValueAsString(objValue));
strValues.add(getVcfValueAsString(objValue, missingValue));
}
}
} else if (value instanceof String string) {
strValues = singletonList(getInfoStringValueAsString(string));
strValues = singletonList(getInfoStringValueAsString(string, missingValue));
} else {
throw new TypeConversionException(value, String.class);
}
Expand All @@ -185,22 +195,22 @@ public static List<String> getInfoAsStringList(VariantContext variantContext, St
}

private static @Nullable
String getVcfValueAsString(@Nullable Object objValue) {
String getVcfValueAsString(@Nullable Object objValue, String missingValue) {
String strValue;
if (objValue == null) {
strValue = null;
} else if (objValue instanceof String string) {
strValue = getInfoStringValueAsString(string);
strValue = getInfoStringValueAsString(string, missingValue);
} else {
throw new TypeConversionException(objValue, String.class);
}
return strValue;
}

private static @Nullable
String getInfoStringValueAsString(String infoStrValue) {
String getInfoStringValueAsString(String infoStrValue, String missingValue) {
String stringValue;
if (infoStrValue.equals(VCFConstants.MISSING_VALUE_v4)) {
if (infoStrValue.equals(missingValue)) {
stringValue = null;
} else {
stringValue = infoStrValue;
Expand Down Expand Up @@ -241,18 +251,19 @@ public static Object getTypedVcfValue(Field field, String stringValue, String se
public static Object getTypedVcfValue(Field field, String stringValue) {
Object typedValue;
ValueType valueType = field.getValueType();
String missingValue = getMissingValue(field);
switch (valueType) {
case INTEGER:
typedValue = VcfUtils.getVcfValueAsInteger(stringValue);
typedValue = VcfUtils.getVcfValueAsInteger(stringValue, missingValue);
break;
case FLAG:
typedValue = VcfUtils.getVcfValueAsBoolean(stringValue);
break;
case FLOAT:
typedValue = VcfUtils.getVcfValueAsDouble(stringValue);
typedValue = VcfUtils.getVcfValueAsDouble(stringValue, missingValue);
break;
case CHARACTER, STRING:
typedValue = VcfUtils.getVcfValueAsString(stringValue);
typedValue = VcfUtils.getVcfValueAsString(stringValue, missingValue);
break;
default:
throw new UnexpectedEnumException(valueType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import java.util.List;
import org.junit.jupiter.api.Test;
import org.molgenis.vcf.decisiontree.filter.model.FieldImpl;
import org.molgenis.vcf.decisiontree.filter.model.FieldType;

class VcfUtilsTest {

Expand Down Expand Up @@ -299,14 +300,29 @@ void getInfoAsDoubleListSingletonString() {
@Test
void getInfoAsDoubleListSingletonStringMissing() {
String key = "my_key";
FieldImpl field = when(mock(FieldImpl.class).getId()).thenReturn(key).getMock();
FieldImpl field = mock(FieldImpl.class);
when(field.getId()).thenReturn(key);
when(field.getFieldType()).thenReturn(FieldType.INFO);
List<String> values = singletonList(".");
VariantContext variantContext =
when(mock(VariantContext.class).getAttribute(key)).thenReturn(values).getMock();

assertEquals(singletonList(null), VcfUtils.getInfoAsDoubleList(variantContext, field));
}

@Test
void getFormatAsDoubleListSingletonStringMissing() {
String key = "my_key";
FieldImpl field = mock(FieldImpl.class);
when(field.getId()).thenReturn(key);
when(field.getFieldType()).thenReturn(FieldType.FORMAT);
List<String> values = singletonList("");
VariantContext variantContext =
when(mock(VariantContext.class).getAttribute(key)).thenReturn(values).getMock();

assertEquals(singletonList(null), VcfUtils.getInfoAsDoubleList(variantContext, field));
}

@Test
void getInfoAsDoubleListNull() {
String key = "my_key";
Expand Down