Skip to content

Commit

Permalink
feat: add lineage queries for nextstrain, nextclade and gisaid
Browse files Browse the repository at this point in the history
  • Loading branch information
JonasKellerer committed Apr 27, 2023
1 parent 217704e commit e01acda
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 0 deletions.
1 change: 1 addition & 0 deletions lapis2/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ dependencies {
}
testImplementation 'com.ninja-squad:springmockk:4.0.2'
testImplementation 'org.mock-server:mockserver-netty:5.15.0'
implementation "org.jetbrains.kotlin:kotlin-stdlib"
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ single:
nucleotide_mutation
| pangolineage_query
| n_of_query
| nucleotide_insertion
| aa_mutation
| aa_insertion
| nextclade_pangolineage_query
| nextstrain_clade_lineage_query
| gisaid_clade_lineage_query
;

nucleotide_mutation : nucleotide_symbol? position ambigous_nucleotide_symbol?;
Expand All @@ -34,6 +40,30 @@ n_of_match_exactly: 'EXACTLY-';
n_of_number_of_matchers: NUMBER+;
n_of_exprs: expr (',' expr)*;

nucleotide_insertion: 'ins_' position ':' (ambigous_nucleotide_symbol | '?')+;

aa_mutation: gene ':' aa_symbol? position ambigous_aa_symbol?;
aa_symbol: A | R | N | D | C | E | Q | G | H | I | L | K | M | F | P | S | T | W | Y | V | ASTERISK;
ambigous_aa_symbol: aa_symbol | X | MINUS | DOT;
gene: covid_gene;
covid_gene : E | M | N | S | ORF;

aa_insertion: 'ins_' gene ':' (ambigous_aa_symbol | '?')+;

nextclade_pangolineage_query: nextclade_pango_lineage_prefix pangolineage_query;
nextclade_pango_lineage_prefix: 'nextcladePangoLineage:';

nextstrain_clade_lineage_query: nextstrain_clade_prefix nextstrain_clade_query;
nextstrain_clade_prefix: 'nextstrainClade:';
nextstrain_clade_query: NUMBER NUMBER nextstrain_clade_character | 'RECOMBINANT';
nextstrain_clade_character: A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z;

gisaid_clade_lineage_query: gisaid_clade_prefix gisaid_clade_query;
gisaid_clade_prefix: 'gisaid:';
gisaid_clade_query: gisaid_clade_character gisaid_clade_character?;
gisaid_clade_character: A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z;


// lexer rules

A: 'A';
Expand Down Expand Up @@ -68,3 +98,5 @@ ASTERISK: '*';

NUMBER: [0-9];
WHITESPACE: [ \r\n\t] -> skip;

ORF: 'ORF1A' | 'ORF1B' | 'ORF3A' | 'ORF6' | 'ORF7A' | 'ORF7B' | 'ORF8' | 'ORF9B';
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,21 @@ class ExceptionHandler : ResponseEntityExceptionHandler() {
),
)
}

@ExceptionHandler(NotImplementedError::class)
fun handleNotImplementedError(e: NotImplementedError): ResponseEntity<String> {
return ResponseEntity
.status(HttpStatus.NOT_IMPLEMENTED)
.contentType(MediaType.APPLICATION_JSON)
.body(
jacksonObjectMapper().writeValueAsString(
LapisHttpErrorResponse(
"Not implemented",
"${e.message}",
),
),
)
}
}

data class LapisHttpErrorResponse(val title: String, val message: String)
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
package org.genspectrum.lapis.model

import VariantQueryBaseListener
import VariantQueryParser.Aa_insertionContext
import VariantQueryParser.Aa_mutationContext
import VariantQueryParser.AndContext
import VariantQueryParser.Gisaid_clade_lineage_queryContext
import VariantQueryParser.MaybeContext
import VariantQueryParser.N_of_queryContext
import VariantQueryParser.Nextclade_pangolineage_queryContext
import VariantQueryParser.Nextstrain_clade_queryContext
import VariantQueryParser.NotContext
import VariantQueryParser.Nucleotide_insertionContext
import VariantQueryParser.Nucleotide_mutationContext
import VariantQueryParser.OrContext
import VariantQueryParser.Pangolineage_queryContext
Expand Down Expand Up @@ -82,4 +88,28 @@ class VariantQueryCustomListener : VariantQueryBaseListener(), ParseTreeListener

expressionStack.addLast(NOf(n, matchExactly, children.reversed()))
}

override fun enterNucleotide_insertion(ctx: Nucleotide_insertionContext?) {
throw NotImplementedError("Nucleotide insertions are not supported yet.")
}

override fun enterAa_mutation(ctx: Aa_mutationContext?) {
throw NotImplementedError("Amino acid mutations are not supported yet.")
}

override fun enterAa_insertion(ctx: Aa_insertionContext?) {
throw NotImplementedError("Amino acid insertions are not supported yet.")
}

override fun enterNextclade_pangolineage_query(ctx: Nextclade_pangolineage_queryContext?) {
throw NotImplementedError("Nextclade pango lineages are not supported yet.")
}

override fun enterNextstrain_clade_query(ctx: Nextstrain_clade_queryContext?) {
throw NotImplementedError("Nextstrain clade lineages are not supported yet.")
}

override fun enterGisaid_clade_lineage_query(ctx: Gisaid_clade_lineage_queryContext?) {
throw NotImplementedError("Gisaid clade lineages are not supported yet.")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,78 @@ class VariantQueryFacadeTest {
MatcherAssert.assertThat(result, Matchers.equalTo(expectedResult))
}

@Test
fun `given a variant variantQuery with a 'Insertion' expression the map should throw an error`() {
val variantQuery = "ins_1234:GAG"

val exception = assertThrows<NotImplementedError> { underTest.map(variantQuery) }

MatcherAssert.assertThat(
exception.message,
Matchers.equalTo("Nucleotide insertions are not supported yet."),
)
}

@Test
fun `given a valid variant variantQuery with a 'AA mutation' expression the map should throw an error`() {
val variantQuery = "S:N501Y"

val exception = assertThrows<NotImplementedError> { underTest.map(variantQuery) }

MatcherAssert.assertThat(
exception.message,
Matchers.equalTo("Amino acid mutations are not supported yet."),
)
}

@Test
fun `given a valid variant variantQuery with a 'AA insertion' expression the map should throw an error`() {
val variantQuery = "ins_S:N501EPE"

val exception = assertThrows<NotImplementedError> { underTest.map(variantQuery) }

MatcherAssert.assertThat(
exception.message,
Matchers.equalTo("Amino acid insertions are not supported yet."),
)
}

@Test
fun `given a valid variant variantQuery with a 'nextclade pango lineage' expression the map should throw an error`() {
val variantQuery = "nextcladePangoLineage:BA.5*"

val exception = assertThrows<NotImplementedError> { underTest.map(variantQuery) }

MatcherAssert.assertThat(
exception.message,
Matchers.equalTo("Nextclade pango lineages are not supported yet."),
)
}

@Test
fun `given a valid variant variantQuery with a 'Nextstrain clade lineage' expression the map should throw an error`() {
val variantQuery = "nextstrainClade:22B"

val exception = assertThrows<NotImplementedError> { underTest.map(variantQuery) }

MatcherAssert.assertThat(
exception.message,
Matchers.equalTo("Nextstrain clade lineages are not supported yet."),
)
}

@Test
fun `given a valid variant variantQuery with a 'Gisaid clade lineage' expression the map should throw an error`() {
val variantQuery = "gisaid:AB"

val exception = assertThrows<NotImplementedError> { underTest.map(variantQuery) }

MatcherAssert.assertThat(
exception.message,
Matchers.equalTo("Gisaid clade lineages are not supported yet."),
)
}

@Test
fun `given a variantQuery with a exact 'Nof' expression then map should return the corresponding SiloQuery`() {
val variantQuery = "[exactly-3-of: 123A, 234T, 345G]"
Expand Down

0 comments on commit e01acda

Please sign in to comment.