diff --git a/CHANGELOG.md b/CHANGELOG.md index 461b5eba..c703d722 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,11 @@ CIFTools Changelog This project uses semantic versioning. Furthermore, this project provides code that was generated from schemata. Any schema change that introduces a breaking change in the generated code is considered as breaking for the whole project. Additional information is provided below when this occurs (named `Breaking schema changes`). Most of these occur in experimental categories and are unlikely to affect your code. `Breaking API changes` will be avoided starting with version 1.0.0. +Unreleased +------------- +### Bug fixes +* BCIF writing: fix behavior when the model contains empty categories + ciftools-java 7.0.1 - March 2025 ------------- ### Bug fixes diff --git a/src/main/java/org/rcsb/cif/binary/BinaryCifWriter.java b/src/main/java/org/rcsb/cif/binary/BinaryCifWriter.java index 4a6b9bff..4e6cb6e5 100644 --- a/src/main/java/org/rcsb/cif/binary/BinaryCifWriter.java +++ b/src/main/java/org/rcsb/cif/binary/BinaryCifWriter.java @@ -57,6 +57,7 @@ private Map encodeFile(CifFile cifFile) { // filter category names List filteredCategories = cifBlock.categories() + .filter(Category::isDefined) // at least 1 row present .filter(category -> options.filterCategory(category.getCategoryName())) .collect(Collectors.toList()); Object[] categories = new Object[filteredCategories.size()]; @@ -68,9 +69,6 @@ private Map encodeFile(CifFile cifFile) { for (Category category : filteredCategories) { String categoryName = category.getCategoryName(); int rowCount = category.getRowCount(); - if (rowCount == 0) { - continue; - } Map categoryMap = new LinkedHashMap<>(); categoryMap.put("name", "_" + category.getCategoryName()); diff --git a/src/test/java/org/rcsb/cif/WriterTest.java b/src/test/java/org/rcsb/cif/WriterTest.java index c252f35b..4dd64638 100644 --- a/src/test/java/org/rcsb/cif/WriterTest.java +++ b/src/test/java/org/rcsb/cif/WriterTest.java @@ -21,11 +21,13 @@ import org.rcsb.cif.schema.core.CifCoreFile; import org.rcsb.cif.schema.mm.MmCifBlock; import org.rcsb.cif.schema.mm.MmCifFile; +import org.rcsb.cif.schema.mm.PdbxStructModResidue; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.regex.Pattern; @@ -257,4 +259,17 @@ void whenReadingChecksum_thenNotTreatedAsInt() throws IOException { assertEquals("0197355516942160", cifFile.getFirstBlock().getMaTargetRefDbDetails().getSeqDbSequenceChecksum().get(0)); assertNotNull(CifIO.writeBinary(cifFile)); } + + @Test + void whenEmptyCategory_thenNotWritten() throws IOException { + MmCifFile cifFile = CifIO.readFromInputStream(TestHelper.getInputStream("bcif/1acj.bcif.gz")).as(StandardSchemata.MMCIF); + MmCifBlock block = cifFile.getFirstBlock(); + PdbxStructModResidue modResidue = block.getPdbxStructModResidue(); // this access adds an empty to the block + assertFalse(modResidue.isDefined(), "category should be undefined"); + + byte[] text = CifIO.writeText(cifFile); + assertFalse(CifIO.readFromInputStream(new ByteArrayInputStream(text)).as(StandardSchemata.MMCIF).getFirstBlock().getPdbxStructModResidue().isDefined()); + byte[] binary = CifIO.writeBinary(cifFile); + assertFalse(CifIO.readFromInputStream(new ByteArrayInputStream(binary)).as(StandardSchemata.MMCIF).getFirstBlock().getPdbxStructModResidue().isDefined()); + } }