From de2ec4c9caf88cb6e9bd1b3821dd170d132f851e Mon Sep 17 00:00:00 2001 From: Louis Bergelson Date: Fri, 4 Oct 2024 10:38:22 -0400 Subject: [PATCH 1/2] Use full path with scheme in beta VCFDecoder * Replace toPath().toString() with toUriString() this should prevent the scheme from being cutoff unintentionally --- .../beta/codecs/variants/vcf/VCFDecoder.java | 4 ++-- .../codecs/variants/vcf/HtsVCFCodecTest.java | 24 ++++++++++++++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/main/java/htsjdk/beta/codecs/variants/vcf/VCFDecoder.java b/src/main/java/htsjdk/beta/codecs/variants/vcf/VCFDecoder.java index 1413f6ef58..6e2c5f79a0 100644 --- a/src/main/java/htsjdk/beta/codecs/variants/vcf/VCFDecoder.java +++ b/src/main/java/htsjdk/beta/codecs/variants/vcf/VCFDecoder.java @@ -206,9 +206,9 @@ private static FeatureReader getVCFReader( //TODO: this resolves the index automatically. it should check to make sure the provided index // matches the one that is automatically resolved, otherwise throw since the request will not be honored return AbstractFeatureReader.getFeatureReader( - variantsIOPath.toPath().toString(), + variantsIOPath.getURIString(), indexIOPath.isPresent() ? - indexIOPath.get().toPath().toString() : + indexIOPath.get().getURIString() : null, vcfCodec, indexIOPath.isPresent(), diff --git a/src/test/java/htsjdk/beta/codecs/variants/vcf/HtsVCFCodecTest.java b/src/test/java/htsjdk/beta/codecs/variants/vcf/HtsVCFCodecTest.java index 0c9e6c458b..a565233868 100644 --- a/src/test/java/htsjdk/beta/codecs/variants/vcf/HtsVCFCodecTest.java +++ b/src/test/java/htsjdk/beta/codecs/variants/vcf/HtsVCFCodecTest.java @@ -1,5 +1,8 @@ package htsjdk.beta.codecs.variants.vcf; +import com.google.common.jimfs.Configuration; +import com.google.common.jimfs.Jimfs; +import com.google.common.jimfs.SystemJimfsFileSystemProvider; import htsjdk.HtsjdkTest; import htsjdk.beta.codecs.variants.vcf.vcfv3_2.VCFCodecV3_2; import htsjdk.beta.codecs.variants.vcf.vcfv3_3.VCFCodecV3_3; @@ -26,6 +29,7 @@ import htsjdk.beta.plugin.variants.VariantsEncoder; import htsjdk.beta.plugin.variants.VariantsFormats; import htsjdk.samtools.util.IOUtil; +import htsjdk.tribble.TestUtils; import htsjdk.variant.variantcontext.VariantContext; import htsjdk.variant.vcf.VCFHeader; import org.testng.Assert; @@ -36,6 +40,9 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.nio.file.FileSystem; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Arrays; import java.util.Collections; import java.util.function.Function; @@ -60,11 +67,26 @@ private Object[][] vcfReadWriteTests() { }; } + @Test + public void testRoundTripNio() throws IOException { + try(FileSystem fs = Jimfs.newFileSystem("test", Configuration.unix())){ + final IOPath outputPath = IOUtils.createTempPath("roundTripVCFThroughPath", ".vcf"); + Path tribbleFileInJimfs = TestUtils.getTribbleFileInJimfs(TEST_VCF_WITH_INDEX.getRawInputString(), TEST_VCF_INDEX.getRawInputString(), fs); + HtsPath vcf = new HtsPath(tribbleFileInJimfs.toUri().toString()); + checkCodecAndReadWriteVcf( vcf , VCFCodecV4_0.VCF_V40_VERSION , outputPath); + } + } + @Test(dataProvider = "vcfReadWriteTests") public void testRoundTripVCFThroughPath(final IOPath inputPath, final HtsVersion expectedCodecVersion) { + final IOPath outputPath = IOUtils.createTempPath("roundTripVCFThroughPath", ".vcf"); + + checkCodecAndReadWriteVcf(inputPath, expectedCodecVersion, outputPath); + } + + private void checkCodecAndReadWriteVcf(IOPath inputPath, HtsVersion expectedCodecVersion, IOPath outputPath) { // some test files require "AllowMissingFields" options for writing final VariantsEncoderOptions variantsEncoderOptions = new VariantsEncoderOptions().setAllowFieldsMissingFromHeader(true); - final IOPath outputPath = IOUtils.createTempPath("roundTripVCFThroughPath", ".vcf"); try (final VariantsDecoder variantsDecoder = HtsDefaultRegistry.getVariantsResolver().getVariantsDecoder(inputPath); final VariantsEncoder variantsEncoder = HtsDefaultRegistry.getVariantsResolver().getVariantsEncoder( From 58d48b69e622043a9f03e511ace4b8d7809b8fb1 Mon Sep 17 00:00:00 2001 From: Louis Bergelson Date: Fri, 4 Oct 2024 17:45:21 -0400 Subject: [PATCH 2/2] Refactor optional handling for clarity --- .../beta/codecs/variants/vcf/VCFDecoder.java | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/main/java/htsjdk/beta/codecs/variants/vcf/VCFDecoder.java b/src/main/java/htsjdk/beta/codecs/variants/vcf/VCFDecoder.java index 6e2c5f79a0..31674fa064 100644 --- a/src/main/java/htsjdk/beta/codecs/variants/vcf/VCFDecoder.java +++ b/src/main/java/htsjdk/beta/codecs/variants/vcf/VCFDecoder.java @@ -26,8 +26,10 @@ import htsjdk.variant.vcf.VCFHeader; import java.io.IOException; +import java.nio.channels.SeekableByteChannel; import java.util.List; import java.util.Optional; +import java.util.function.Function; /** * InternalAPII @@ -197,7 +199,7 @@ private static FeatureReader getVCFReader( "The provided %s resource (%s) must be a readable/input resource", BundleResourceType.CT_VARIANT_CONTEXTS, variantsResource)); - } else if (!variantsResource.getIOPath().isPresent()) { + } else if (variantsResource.getIOPath().isEmpty()) { throw new HtsjdkUnsupportedOperationException("VCF reader from stream not implemented"); } final IOPath variantsIOPath = variantsResource.getIOPath().get(); @@ -207,24 +209,18 @@ private static FeatureReader getVCFReader( // matches the one that is automatically resolved, otherwise throw since the request will not be honored return AbstractFeatureReader.getFeatureReader( variantsIOPath.getURIString(), - indexIOPath.isPresent() ? - indexIOPath.get().getURIString() : - null, + indexIOPath.map(IOPath::getURIString).orElse(null), vcfCodec, indexIOPath.isPresent(), - decoderOptions.getVariantsChannelTransformer().isPresent() ? - decoderOptions.getVariantsChannelTransformer().get() : - null, - decoderOptions.getIndexChannelTransformer().isPresent() ? - decoderOptions.getIndexChannelTransformer().get() : - null + decoderOptions.getVariantsChannelTransformer().orElse(null), + decoderOptions.getIndexChannelTransformer().orElse(null) ); } // the underlying readers can't handle index streams, so for now we can only handle IOPaths private static Optional getIndexIOPath(final Bundle inputBundle) { final Optional optIndexResource = inputBundle.get(BundleResourceType.CT_VARIANTS_INDEX); - if (!optIndexResource.isPresent()) { + if (optIndexResource.isEmpty()) { return Optional.empty(); } final BundleResource indexResource = optIndexResource.get(); @@ -234,7 +230,7 @@ private static Optional getIndexIOPath(final Bundle inputBundle) { BundleResourceType.CT_VARIANTS_INDEX, indexResource)); } - if (!indexResource.getIOPath().isPresent()) { + if (indexResource.getIOPath().isEmpty()) { throw new HtsjdkUnsupportedOperationException("Reading a VCF index from a stream not implemented"); } return indexResource.getIOPath();