Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
880b015
feat(genome): add GFF3 file support to genome manifest reader
Istar-Eldritch Jun 16, 2026
08c8035
feat(genome): add GFF3 file support to analysis XML generation
Istar-Eldritch Jun 16, 2026
71e2068
feat(genome): add GFF3 validation integration for genome submissions
Istar-Eldritch Jun 16, 2026
76ff3c0
docs(phase-4): add changelog and update README for GFF3 annotation su…
Istar-Eldritch Jun 16, 2026
0dcf804
fix(genome): harden GFF3 FASTA sequence source and validator robustness
Istar-Eldritch Jun 16, 2026
110c565
fix(genome): replace FastaSequenceSource with FileSequenceSource for …
Istar-Eldritch Jun 16, 2026
09cb52b
refactor(genome): use gff3tools FileSequenceSource gzip support, drop…
Istar-Eldritch Jun 16, 2026
76cbf71
revert(genome): restore FastaSequenceSource, plain FASTA headers, dro…
Istar-Eldritch Jun 16, 2026
bbd44d7
fix(genome): restore FileSequenceSource; FASTA+GFF3 now requires JSON…
Istar-Eldritch Jun 16, 2026
430e59d
Remove chromosome_list requirement for GFF3 submissions
Istar-Eldritch Jun 17, 2026
a0455e6
fix(gff3): address Raj's review comments
Istar-Eldritch Jun 23, 2026
7b7c290
refactor: replace GenomeValidator and TranscriptomeValidator with sin…
Istar-Eldritch Jun 24, 2026
3fa99fb
fix: fix Gff3Validator ReadException and update SequenceSubmissionVal…
Istar-Eldritch Jun 24, 2026
a480498
fix: rewrap SequenceSubmissionValidator javadoc to stay within 100-co…
Istar-Eldritch Jun 24, 2026
ebb93d9
refactor(validator): clean up SequenceSubmissionValidator; fix polysa…
Istar-Eldritch Jun 25, 2026
86c1818
chore: address haseeb-gh review comments (TTENA-207)
Istar-Eldritch Jul 6, 2026
6785bd9
Updating the code to allow only GFF3 file submission.
Rajkumar-D Jul 13, 2026
ad69c16
Updating the code to allow only GFF3 file submission. Fasta and Gff3 …
Rajkumar-D Jul 19, 2026
cb5532d
Changes for dev deployment
Rajkumar-D Jul 20, 2026
33ff05e
remove comment and update version
Rajkumar-D Jul 20, 2026
1f538cf
This is dev only branch
Rajkumar-D Jul 20, 2026
e36e27a
This is dev only branch
Rajkumar-D Jul 20, 2026
95c1341
This is dev only branch
Rajkumar-D Jul 21, 2026
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
7 changes: 6 additions & 1 deletion build.gradle

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we not need a version number update for this change?

Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ plugins {
}

group = 'uk.ac.ebi.ena.webin-cli'
version = '9.0.3'
version = '10.0.0'

repositories {
mavenLocal()
Expand All @@ -28,6 +28,11 @@ repositories {

dependencies {
// dependencies declared as 'api' so they can be exposed to projects that use webin-cli as a library.
api( 'uk.ac.ebi.ena.webin-cli:webin-cli-validator:2.0.9' )
api( 'uk.ac.ebi.ena:gff3tools:4.6.2' ) {
exclude group: 'ch.qos.logback', module: 'logback-classic'
}
implementation( 'uk.ac.ebi.ena:fastareader:1.2.0' )
api( 'uk.ac.ebi.ena.sequence:sequencetools:2.+' )
api( 'uk.ac.ebi.ena.txmbtools:txmbtools:2.+' )
api( 'uk.ac.ebi.ena:readtools:2.+' ) {
Expand Down
7 changes: 4 additions & 3 deletions src/main/java/uk/ac/ebi/ena/webin/cli/WebinCliContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import uk.ac.ebi.embl.api.validation.submission.SubmissionValidator;
import uk.ac.ebi.ena.readtools.validator.ReadsValidator;
import uk.ac.ebi.ena.txmbvalidator.TxmbValidator;
import uk.ac.ebi.ena.webin.cli.context.SequenceSubmissionValidator;
import uk.ac.ebi.ena.webin.cli.context.genome.GenomeManifestReader;
import uk.ac.ebi.ena.webin.cli.context.genome.GenomeXmlWriter;
import uk.ac.ebi.ena.webin.cli.context.polysample.PolySampleManifestReader;
Expand All @@ -37,19 +38,19 @@ public enum WebinCliContext {
GenomeManifest.class,
GenomeManifestReader.class,
GenomeXmlWriter.class,
SubmissionValidator.class,
SequenceSubmissionValidator.class,
"Genome assembly"),
transcriptome(
TranscriptomeManifest.class,
TranscriptomeManifestReader.class,
TranscriptomeXmlWriter.class,
SubmissionValidator.class,
SequenceSubmissionValidator.class,
"Transcriptome assembly"),
sequence(
SequenceManifest.class,
SequenceManifestReader.class,
SequenceXmlWriter.class,
SubmissionValidator.class,
SequenceSubmissionValidator.class,
"Sequence assembly"),
polysample(
PolySampleManifest.class,
Expand Down

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for this validator just like Gff3Validator above:
https://github.com/enasequence/webin-cli/pull/162/changes#r3481076908

Following existing practice, this should be placed in gff3tools unless there is a good reason or everybody agrees that there is no harm in keeping them here in webin-cli.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed that we could move Gff3Validator to gff3tools, but I think SequenceSubmissionValidator should be in webin-cli because it is a generic logic to perform both submissionValidator.validate() and gff3Validation.validate()

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The engine-orchestration core (build ValidationEngine + CompositeSequenceProvider, read GFF3, collect errors/warnings) has no ENA-specific data or credentials in it, so it's a fair candidate to eventually live in gff3tools as a public convenience API, mirroring what sequencetools/readtools/txmbtools already do with SubmissionValidator/ReadsValidator/TxmbValidator. That said, I'd treat it as a follow-up rather than part of this PR, it means a gff3tools release plus a dependency bump here, and the report-writing/SubmissionFile adaptation needs to stay in webin-cli regardless (gff3tools shouldn't depend on webin-cli-validator types). I'm opening gff3tools PR to extract that piece.

For SequenceSubmissionValidator, it should stay in webin-cli. Its whole job is composing SubmissionValidator (sequencetools) + Gff3Validator for a webin-cli submission context; there's no ENA-internal logic in it that would justify moving it, and gff3tools shouldn't need to know about webin-cli's Manifest/Validator interfaces.

Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Copyright 2018-2023 EMBL - European Bioinformatics Institute
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
* file except in compliance with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package uk.ac.ebi.ena.webin.cli.context;

import java.util.List;
import uk.ac.ebi.embl.api.validation.submission.SubmissionValidator;
import uk.ac.ebi.ena.webin.cli.context.genome.Gff3Validator;
import uk.ac.ebi.ena.webin.cli.validator.api.ValidationResponse;
import uk.ac.ebi.ena.webin.cli.validator.api.Validator;
import uk.ac.ebi.ena.webin.cli.validator.file.SubmissionFile;
import uk.ac.ebi.ena.webin.cli.validator.manifest.Manifest;

/**
* Composite validator for genome, transcriptome, and sequence submissions. Runs the sequencetools
* {@link SubmissionValidator} first, then performs client-side GFF3 validation when the manifest
* declares a GFF3 file.
*
* <p>Instantiated reflectively by {@link uk.ac.ebi.ena.webin.cli.WebinCliContext}, so a public
* no-arg constructor is required.
*/
public class SequenceSubmissionValidator implements Validator<Manifest<?>, ValidationResponse> {

private static final String GFF3_TYPE = "GFF3";
private static final String FASTA_TYPE = "FASTA";
private static final String FLATFILE_TYPE = "FLATFILE";

private final SubmissionValidator submissionValidator;
private final Gff3Validator gff3Validator;

public SequenceSubmissionValidator() {
this(new SubmissionValidator(), new Gff3Validator());
}

SequenceSubmissionValidator(
SubmissionValidator submissionValidator, Gff3Validator gff3Validator) {
this.submissionValidator = submissionValidator;
this.gff3Validator = gff3Validator;
}

@Override
public ValidationResponse validate(Manifest<?> manifest) {
List<? extends SubmissionFile<?>> gff3Files = manifest.filesWithTypeName(GFF3_TYPE);
List<? extends SubmissionFile<?>> fastaFiles = manifest.filesWithTypeName(FASTA_TYPE);
boolean gff3Only =
!gff3Files.isEmpty()
&& fastaFiles.isEmpty()
&& manifest.filesWithTypeName(FLATFILE_TYPE).isEmpty();

ValidationResponse response;
if (gff3Only) {
// sequencetools' SubmissionValidator requires at least one FASTA/FLATFILE sequence
// to compute contig/scaffold/chromosome counts, which a GFF3-only submission never
// has. Skip it entirely and rely on Gff3Validator below instead.
response = new ValidationResponse(ValidationResponse.status.VALIDATION_SUCCESS);
} else {
response = submissionValidator.validate(manifest);
if (response == null) {
response = new ValidationResponse();
}
}

if (!gff3Files.isEmpty() && !gff3Validator.validate(gff3Files, fastaFiles)) {
response.setStatus(ValidationResponse.status.VALIDATION_ERROR);
}

return response;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public interface Field {
String UNLOCALISED_LIST = "UNLOCALISED_LIST";
String FASTA = "FASTA";
String FLATFILE = "FLATFILE";
String GFF3 = "GFF3";
String AUTHORS = "AUTHORS";
String ADDRESS = "ADDRESS";
}
Expand All @@ -74,6 +75,7 @@ public interface Description {
String UNLOCALISED_LIST = "Unlocalised sequence list file";
String FASTA = "Fasta file";
String FLATFILE = "Flat file";
String GFF3 = "Annotation in a GFF3 file";
String AUTHORS = "For submission brokers only. Submitter's names as a comma-separated list";
String ADDRESS = "For submission brokers only. Submitter's address";
}
Expand Down Expand Up @@ -190,6 +192,12 @@ public GenomeManifestReader(WebinCliParameters parameters, MetadataProcessorFact
.and()
.file()
.optional()
.name(Field.GFF3)
.desc(Description.GFF3)
.processor(getGff3Processors())
.and()
.file()
.optional()
.name(Field.CHROMOSOME_LIST)
.desc(Description.CHROMOSOME_LIST)
.processor(getChromosomeListProcessors())
Expand Down Expand Up @@ -246,6 +254,9 @@ public GenomeManifestReader(WebinCliParameters parameters, MetadataProcessorFact
.required(Field.FLATFILE)
.required(Field.CHROMOSOME_LIST)
.optional(Field.UNLOCALISED_LIST)
.and()
.group("Annotation in a GFF3 file.")
.required(Field.GFF3)
.build());

if (factory.getStudyProcessor() != null) {
Expand Down Expand Up @@ -308,6 +319,12 @@ private static ManifestFieldProcessor[] getFlatfileProcessors() {
};
}

private static ManifestFieldProcessor[] getGff3Processors() {
return new ManifestFieldProcessor[] {
new ASCIIFileNameProcessor(), new FileSuffixProcessor(ManifestFileSuffix.GFF3_FILE_SUFFIX)
};
}

@Override
public void processManifest() {
getManifestReaderResult()
Expand Down Expand Up @@ -383,6 +400,11 @@ public void processManifest() {
submissionFiles.add(
new SubmissionFile(
GenomeManifest.FileType.UNLOCALISED_LIST, unlocalisedListFile)));
getFiles(getInputDir(), fieldGroup, Field.GFF3)
.forEach(
gff3File ->
submissionFiles.add(
new SubmissionFile(GenomeManifest.FileType.GFF3, gff3File)));

// "primary metagenome" and "binned metagenome" checks
if (ASSEMBLY_TYPE_PRIMARY_METAGENOME.equals(fieldGroup.getValue(Field.ASSEMBLY_TYPE))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,18 @@ protected List<Element> createXmlFileElements(
FileUtils.calculateDigest("MD5", file.toFile()),
"flatfile")));

manifest.files(FileType.GFF3).stream()
.map(file -> file.getFile().toPath())
.forEach(
file ->
list.add(
createFileElement(
inputDir,
uploadDir,
file,
FileUtils.calculateDigest("MD5", file.toFile()),
"gff3")));

return list;
}
}
Loading