From 900fd0e99a46fab414da25616e3b226aff4bfec9 Mon Sep 17 00:00:00 2001 From: Eugene Date: Tue, 28 Sep 2021 12:03:19 -0700 Subject: [PATCH] Fixed boolean operators (and, or) and introduced wildcard() function (#72) * Fixed boolean operators (and, or) and introduced wildcard() function * Update to use latest api-search-query-lexer SNAPSHOT * Like operator Co-authored-by: Eugene Co-authored-by: Jordan Padams <33492486+jordanpadams@users.noreply.github.com> --- pom.xml | 2 +- .../MyProductsApiBareController.java | 7 +- .../elasticsearch/Antlr4SearchListener.java | 153 +++++++++++------- .../elasticsearch/ElasticSearchUtil.java | 4 +- .../serializer/Pds4XmlProductSerializer.java | 9 -- .../Antlr4SearchListenerTest.java | 61 +++---- 6 files changed, 121 insertions(+), 115 deletions(-) diff --git a/pom.xml b/pom.xml index 6eef2cc1..0ead9c8b 100644 --- a/pom.xml +++ b/pom.xml @@ -277,7 +277,7 @@ POSSIBILITY OF SUCH DAMAGE. gov.nasa.pds api-search-query-lexer - 0.2.0 + 1.0.0-SNAPSHOT diff --git a/src/main/java/gov/nasa/pds/api/engineering/controllers/MyProductsApiBareController.java b/src/main/java/gov/nasa/pds/api/engineering/controllers/MyProductsApiBareController.java index 6d9ca90a..7171910b 100644 --- a/src/main/java/gov/nasa/pds/api/engineering/controllers/MyProductsApiBareController.java +++ b/src/main/java/gov/nasa/pds/api/engineering/controllers/MyProductsApiBareController.java @@ -185,7 +185,7 @@ protected ResponseEntity getProductsResponseEntity(String q, String keyw List fields, List sort, boolean onlySummary) { String accept = this.request.getHeader("Accept"); - log.info("accept value is " + accept); + log.debug("accept value is " + accept); if ((accept != null && (accept.contains("application/json") || accept.contains("application/pds4+json") @@ -236,7 +236,7 @@ protected ResponseEntity getProductsResponseEntity(String q, String keyw protected ResponseEntity getAllProductsResponseEntity(String lidvid, int start, int limit) { String accept = this.request.getHeader("Accept"); - log.info("accept value is " + accept); + log.debug("accept value is " + accept); if ((accept != null && (accept.contains("application/json") || accept.contains("text/html") || accept.contains("application/xml") || accept.contains("*/*"))) || (accept == null)) { @@ -370,10 +370,9 @@ protected URL getBaseURL() { baseURL = new URL(this.context.getScheme(), this.context.getServerName(), this.context.getServerPort(), this.contextPath); } - MyProductsApiBareController.log.info("baseUrl is " + baseURL.toString()); + log.debug("baseUrl is " + baseURL.toString()); return baseURL; - } catch (MalformedURLException e) { log.error("Server URL was not retrieved"); return null; diff --git a/src/main/java/gov/nasa/pds/api/engineering/elasticsearch/Antlr4SearchListener.java b/src/main/java/gov/nasa/pds/api/engineering/elasticsearch/Antlr4SearchListener.java index c022f48d..a91a5229 100644 --- a/src/main/java/gov/nasa/pds/api/engineering/elasticsearch/Antlr4SearchListener.java +++ b/src/main/java/gov/nasa/pds/api/engineering/elasticsearch/Antlr4SearchListener.java @@ -27,13 +27,14 @@ enum operation { eq, ge, gt, le, lt, ne }; private static final Logger log = LoggerFactory.getLogger(Antlr4SearchListener.class); private BoolQueryBuilder query = new BoolQueryBuilder(); - private boolean wildcard = false; + private conjunctions conjunction = conjunctions.AND; final private Deque stack_conjunction = new ArrayDeque(); final private Deque stack_queries = new ArrayDeque(); final private Deque> stack_musts = new ArrayDeque>(); final private Deque> stack_nots = new ArrayDeque>(); final private Deque> stack_shoulds = new ArrayDeque>(); + int depth = 0; private List musts = new ArrayList(); private List nots = new ArrayList(); @@ -115,68 +116,108 @@ public void enterOrStatement(SearchParser.OrStatementContext ctx) this.conjunction = conjunctions.OR; } - @Override - public void enterComparison(SearchParser.ComparisonContext ctx) - { - this.wildcard = ctx.VALUE() != null && (ctx.VALUE().getSymbol().getText().contains("*") || ctx.VALUE().getSymbol().getText().contains("?")); - } - @Override - public void exitComparison(SearchParser.ComparisonContext ctx) - { - final String left = ElasticSearchUtil.jsonPropertyToElasticProperty (ctx.FIELD(0).getSymbol().getText()); - String right; - QueryBuilder comparator = null; - - // the second term of the comparison can be first tokenized as FIELD (string without quote) since FIELD is before VALUE (string with optional wildcard, no quote) in the ANTLR4 grammar. - if (ctx.FIELD(1) != null) right = ctx.FIELD(1).getSymbol().getText(); - else if (ctx.NUMBER() != null) right = ctx.NUMBER().getSymbol().getText(); - else if (ctx.STRINGVAL() != null) - { - right = ctx.STRINGVAL().getSymbol().getText(); - right = right.substring(1, right.length()-1); - } - else if (ctx.VALUE() != null) right = ctx.VALUE().getSymbol().getText(); - else - { - log.error("Panic, there are more data types than this version of the lexer knows about."); - throw new ParseCancellationException(); // PANIC: listener out of sync with the grammar - } + @Override + public void enterComparison(SearchParser.ComparisonContext ctx) + { + } - if (this.operator == operation.eq || this.operator == operation.ne) - { - if (this.wildcard) comparator = new WildcardQueryBuilder(left, right); - else comparator = new MatchQueryBuilder(left, right); - } - else - { - comparator = new RangeQueryBuilder(left); - - if (this.operator == operation.ge) ((RangeQueryBuilder)comparator).gte(right); - else if (this.operator == operation.gt) ((RangeQueryBuilder)comparator).gt(right); - else if (this.operator == operation.le) ((RangeQueryBuilder)comparator).lte(right); - else if (this.operator == operation.lt) ((RangeQueryBuilder)comparator).lt(right); - else - { - log.error("Panic, there are more range operators than this version of the lexer knows about"); - throw new ParseCancellationException(); // PANIC: listener out of sync with the grammar - } - } - if (this.operator == operation.ne) this.nots.add(comparator); - else if (this.conjunction == conjunctions.AND) this.musts.add(comparator); - else this.shoulds.add(comparator); - } + @Override + public void exitComparison(SearchParser.ComparisonContext ctx) + { + final String left = ElasticSearchUtil.jsonPropertyToElasticProperty(ctx.FIELD().getSymbol().getText()); + + String right; + QueryBuilder comparator = null; + + if (ctx.NUMBER() != null) + { + right = ctx.NUMBER().getSymbol().getText(); + } + else if (ctx.STRINGVAL() != null) + { + right = ctx.STRINGVAL().getSymbol().getText(); + right = right.substring(1, right.length() - 1); + } + else + { + log.error("Panic, there are more data types than this version of the lexer knows about."); + throw new ParseCancellationException(); // PANIC: listener out of sync with the grammar + } + + if (this.operator == operation.eq || this.operator == operation.ne) + { + comparator = new MatchQueryBuilder(left, right); + } + else + { + comparator = new RangeQueryBuilder(left); + + if (this.operator == operation.ge) + ((RangeQueryBuilder) comparator).gte(right); + else if (this.operator == operation.gt) + ((RangeQueryBuilder) comparator).gt(right); + else if (this.operator == operation.le) + ((RangeQueryBuilder) comparator).lte(right); + else if (this.operator == operation.lt) + ((RangeQueryBuilder) comparator).lt(right); + else + { + log.error("Panic, there are more range operators than this version of the lexer knows about"); + throw new ParseCancellationException(); // PANIC: listener out of sync with the grammar + } + } + + if (this.operator == operation.ne) + { + this.nots.add(comparator); + } + else if (this.conjunction == conjunctions.AND) + { + this.musts.add(comparator); + } + else + { + this.shoulds.add(comparator); + } + } + + + @Override + public void enterLikeComparison(SearchParser.LikeComparisonContext ctx) + { + } + + + @Override + public void exitLikeComparison(SearchParser.LikeComparisonContext ctx) + { + final String left = ElasticSearchUtil.jsonPropertyToElasticProperty(ctx.FIELD().getText()); + + String right = ctx.STRINGVAL().getText(); + right = right.substring(1, right.length() - 1); + + QueryBuilder comparator = new WildcardQueryBuilder(left, right); + + if("not".equalsIgnoreCase(ctx.getChild(1).getText())) + { + this.nots.add(comparator); + } + else if(this.conjunction == conjunctions.AND) + { + this.musts.add(comparator); + } + else + { + this.shoulds.add(comparator); + } + } + @Override public void enterOperator(SearchParser.OperatorContext ctx) { - if (this.wildcard && ctx.EQ() == null && ctx.NE() == null) - { - log.warn("Cannot use wildcards with <, <=, >=, or >"); - throw new ParseCancellationException(); - } - if (ctx.EQ() != null) this.operator = operation.eq; else if (ctx.GE() != null) this.operator = operation.ge; else if (ctx.GT() != null) this.operator = operation.gt; diff --git a/src/main/java/gov/nasa/pds/api/engineering/elasticsearch/ElasticSearchUtil.java b/src/main/java/gov/nasa/pds/api/engineering/elasticsearch/ElasticSearchUtil.java index 77c27875..a71c46f9 100644 --- a/src/main/java/gov/nasa/pds/api/engineering/elasticsearch/ElasticSearchUtil.java +++ b/src/main/java/gov/nasa/pds/api/engineering/elasticsearch/ElasticSearchUtil.java @@ -131,7 +131,7 @@ static private Product addPropertiesFromESEntity( } static public ProductWithXmlLabel ESentityProductToAPIProduct(EntitytProductWithBlob ep, URL baseURL) { - ElasticSearchUtil.log.info("convert ES object to API object with XML label"); + log.debug("convert ES object to API object with XML label"); ProductWithXmlLabel product = new ProductWithXmlLabel(); product.setLabelXml(ep.getPDS4XML()); return (ProductWithXmlLabel)addPropertiesFromESEntity(product, ep, baseURL); @@ -139,7 +139,7 @@ static public ProductWithXmlLabel ESentityProductToAPIProduct(EntitytProductWith static public Product ESentityProductToAPIProduct(EntityProduct ep, URL baseURL) { - ElasticSearchUtil.log.info("convert ES object to API object without XML label"); + log.debug("convert ES object to API object without XML label"); Product product = new Product(); diff --git a/src/main/java/gov/nasa/pds/api/engineering/serializer/Pds4XmlProductSerializer.java b/src/main/java/gov/nasa/pds/api/engineering/serializer/Pds4XmlProductSerializer.java index 80d277c1..96a6d507 100644 --- a/src/main/java/gov/nasa/pds/api/engineering/serializer/Pds4XmlProductSerializer.java +++ b/src/main/java/gov/nasa/pds/api/engineering/serializer/Pds4XmlProductSerializer.java @@ -1,12 +1,8 @@ package gov.nasa.pds.api.engineering.serializer; -import gov.nasa.pds.model.Product; import gov.nasa.pds.api.model.xml.ProductWithXmlLabel; -import gov.nasa.pds.model.Metadata; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; -import java.util.Scanner; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamWriter; @@ -18,11 +14,6 @@ import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.http.converter.HttpMessageNotWritableException; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.SerializerProvider; -import com.fasterxml.jackson.databind.ser.std.StdSerializer; -import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator; - public class Pds4XmlProductSerializer extends AbstractHttpMessageConverter { diff --git a/src/test/java/gov/nasa/pds/api/engineering/elasticsearch/Antlr4SearchListenerTest.java b/src/test/java/gov/nasa/pds/api/engineering/elasticsearch/Antlr4SearchListenerTest.java index 11dc5dac..4b365727 100644 --- a/src/test/java/gov/nasa/pds/api/engineering/elasticsearch/Antlr4SearchListenerTest.java +++ b/src/test/java/gov/nasa/pds/api/engineering/elasticsearch/Antlr4SearchListenerTest.java @@ -53,9 +53,9 @@ private BoolQueryBuilder run (String query) } @Test - public void testEqualWildcard() + public void testLikeWildcard() { - String qs = "lid eq *pdart14_meap"; + String qs = "lid like \"*pdart14_meap\""; BoolQueryBuilder query = this.run(qs); Assertions.assertEquals (query.must().size(), 1); @@ -66,20 +66,22 @@ public void testEqualWildcard() Assertions.assertEquals (((WildcardQueryBuilder)query.must().get(0)).value(), "*pdart14_meap"); } - @Test - public void testNotEqualWildchar() - { - String qs = "lid ne pdart14_meap?"; - BoolQueryBuilder query = this.run(qs); - - Assertions.assertEquals (query.must().size(), 0); - Assertions.assertEquals (query.mustNot().size(), 1); - Assertions.assertEquals (query.should().size(), 0); - Assertions.assertTrue (query.mustNot().get(0) instanceof WildcardQueryBuilder); - Assertions.assertEquals (((WildcardQueryBuilder)query.mustNot().get(0)).fieldName(), "lid"); - Assertions.assertEquals (((WildcardQueryBuilder)query.mustNot().get(0)).value(), "pdart14_meap?"); - } - + + @Test + public void testNotLikeWildchar() + { + String qs = "lid not like \"pdart14_meap?\""; + BoolQueryBuilder query = this.run(qs); + + Assertions.assertEquals(query.must().size(), 0); + Assertions.assertEquals(query.mustNot().size(), 1); + Assertions.assertEquals(query.should().size(), 0); + Assertions.assertTrue(query.mustNot().get(0) instanceof WildcardQueryBuilder); + Assertions.assertEquals(((WildcardQueryBuilder) query.mustNot().get(0)).fieldName(), "lid"); + Assertions.assertEquals(((WildcardQueryBuilder) query.mustNot().get(0)).value(), "pdart14_meap?"); + } + + @Test public void testEscape() { @@ -94,20 +96,6 @@ public void testEscape() Assertions.assertEquals (((MatchQueryBuilder)query.must().get(0)).value(), "*pdart14_meap?"); } - @Test - public void testGroup() - { - String qs = "( lid eq *pdart14_meap* )"; - BoolQueryBuilder query = this.run(qs); - - Assertions.assertEquals (query.must().size(), 1); - Assertions.assertEquals (query.mustNot().size(), 0); - Assertions.assertEquals (query.should().size(), 0); - Assertions.assertTrue (query.must().get(0) instanceof WildcardQueryBuilder); - Assertions.assertEquals (((WildcardQueryBuilder)query.must().get(0)).fieldName(), "lid"); - Assertions.assertEquals (((WildcardQueryBuilder)query.must().get(0)).value(), "*pdart14_meap*"); - - } @Test public void testGroupedStatementAndExclusiveInequality() @@ -227,19 +215,6 @@ public void testNestedGrouping() Assertions.assertFalse (((RangeQueryBuilder)nest.must().get(1)).includeUpper()); } - @Test - public void testNoWildcard() - { - String qs = "ref_lid_target eq urn:nasa:pds:context:target:planet.mercury"; - BoolQueryBuilder query = this.run(qs); - - Assertions.assertEquals (query.must().size(), 1); - Assertions.assertEquals (query.mustNot().size(), 0); - Assertions.assertEquals (query.should().size(), 0); - Assertions.assertTrue (query.must().get(0) instanceof MatchQueryBuilder); - Assertions.assertEquals (((MatchQueryBuilder)query.must().get(0)).fieldName(), "ref_lid_target"); - Assertions.assertEquals (((MatchQueryBuilder)query.must().get(0)).value(), "urn:nasa:pds:context:target:planet.mercury"); - } @Test public void testNoWildcardQuoted()