RSQLFilterDialect implements SubqueryFilterDialect, JoinFilterDialect { @Override public FilterExpression parseGlobalExpression(String path, MultivaluedMap<String, String> filterParams) throws ParseException { if (filterParams.size() != 1) { throw new ParseException(SINGLE_PARAMETER_ONLY); } MultivaluedMap.Entry<String, List<String>> entry = CollectionUtils.get(filterParams, 0); String queryParamName = entry.getKey(); if (!"filter".equals(queryParamName)) { throw new ParseException(INVALID_QUERY_PARAMETER + queryParamName); } List<String> queryParamValues = entry.getValue(); if (queryParamValues.size() != 1) { throw new ParseException(SINGLE_PARAMETER_ONLY); } String queryParamValue = queryParamValues.get(0); String normalizedPath = JsonApiParser.normalizePath(path); String[] pathComponents = normalizedPath.split("/"); String lastPathComponent = pathComponents.length > 0 ? pathComponents[pathComponents.length - 1] : ""; Class entityType = dictionary.getEntityClass(lastPathComponent); if (entityType == null) { throw new ParseException("No such collection: " + lastPathComponent); } return parseFilterExpression(queryParamValue, entityType, true); } RSQLFilterDialect(EntityDictionary dictionary);  RSQLFilterDialect(EntityDictionary dictionary, CaseSensitivityStrategy caseSensitivityStrategy); @Override FilterExpression parseGlobalExpression(String path, MultivaluedMap<String, String> filterParams); @Override Map<String, FilterExpression> parseTypedExpression(String path, MultivaluedMap<String, String> filterParams); FilterExpression parseFilterExpression(String expressionText,
                                                  Class<?> entityType,
                                                  boolean allowNestedToManyAssociations);  }
@Test public void testGlobalExpressionParsing() throws Exception { MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<>(); queryParams.add( "filter", "title==*foo*;authors.name==Hemingway" ); FilterExpression expression = dialect.parseGlobalExpression("/book", queryParams); assertEquals( "(book.title INFIX_CASE_INSENSITIVE [foo] AND book.authors.name IN_INSENSITIVE [Hemingway])", expression.toString() ); }
@Test public void testEqualOperator() throws Exception { MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<>(); queryParams.add( "filter", "title==Hemingway" ); FilterExpression expression = dialect.parseGlobalExpression("/book", queryParams); assertEquals("book.title IN_INSENSITIVE [Hemingway]", expression.toString()); }
@Test public void testNotEqualOperator() throws Exception { MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<>(); queryParams.add( "filter", "title!=Hemingway" ); FilterExpression expression = dialect.parseGlobalExpression("/book", queryParams); assertEquals("NOT (book.title IN_INSENSITIVE [Hemingway])", expression.toString()); }
@Test public void testInOperator() throws Exception { MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<>(); queryParams.add( "filter", "title=in=Hemingway" ); FilterExpression expression = dialect.parseGlobalExpression("/book", queryParams); assertEquals("book.title IN_INSENSITIVE [Hemingway]", expression.toString()); }
@Test public void testOutOperator() throws Exception { MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<>(); queryParams.add( "filter", "title=out=Hemingway" ); FilterExpression expression = dialect.parseGlobalExpression("/book", queryParams); assertEquals("NOT (book.title IN_INSENSITIVE [Hemingway])", expression.toString()); }
@Test public void testNumericComparisonOperator() throws Exception { MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<>(); queryParams.add( "filter", "(publishDate=gt=5,publishDate=ge=5,publishDate=lt=10,publishDate=le=10);" + "(publishDate>5,publishDate>=5,publishDate<10,publishDate<=10)" ); FilterExpression expression = dialect.parseGlobalExpression("/book", queryParams); assertEquals( "((((book.publishDate GT [5] OR book.publishDate GE [5]) " + "OR book.publishDate LT [10]) OR book.publishDate LE [10]) AND " + "(((book.publishDate GT [5] OR book.publishDate GE [5]) " + "OR book.publishDate LT [10]) OR book.publishDate LE [10]))", expression.toString() ); }
@Test public void testSubstringOperator() throws Exception { MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<>(); queryParams.add( "filter", "title==*Hemingway*,title==*Hemingway,title==Hemingway*" ); FilterExpression expression = dialect.parseGlobalExpression("/book", queryParams); assertEquals( "((book.title INFIX_CASE_INSENSITIVE [Hemingway] " + "OR book.title POSTFIX_CASE_INSENSITIVE [Hemingway]) " + "OR book.title PREFIX_CASE_INSENSITIVE [Hemingway])", expression.toString() ); }
@Test public void testExpressionGrouping() throws Exception { MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<>(); queryParams.add( "filter", "title==foo;(title==bar;title==baz)" ); FilterExpression expression = dialect.parseGlobalExpression("/book", queryParams); assertEquals( "(book.title IN_INSENSITIVE [foo] AND (book.title IN_INSENSITIVE [bar] " + "AND book.title IN_INSENSITIVE [baz]))", expression.toString() ); }
@Test public void testIsnullOperatorBool() throws Exception { MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<>(); queryParams.add( "filter", "title=isnull=true" ); FilterExpression expression = dialect.parseGlobalExpression("/book", queryParams); assertEquals("book.title ISNULL []", expression.toString()); }
@Test public void testIsnullOperatorInt() throws Exception { MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<>(); queryParams.add( "filter", "title=isnull=1" ); FilterExpression expression = dialect.parseGlobalExpression("/book", queryParams); assertEquals("book.title ISNULL []", expression.toString()); }
@Test public void testNotnullOperatorBool() throws Exception { MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<>(); queryParams.add( "filter", "title=isnull=false" ); FilterExpression expression = dialect.parseGlobalExpression("/book", queryParams); assertEquals("book.title NOTNULL []", expression.toString()); }
@Test public void testNotnullOperatorInt() throws Exception { MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<>(); queryParams.add( "filter", "title=isnull=0" ); FilterExpression expression = dialect.parseGlobalExpression("/book", queryParams); assertEquals("book.title NOTNULL []", expression.toString()); }
@Test public void testFilterOnCustomizedLongIdField() throws ParseException { MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<>(); queryParams.add( "filter", "id==1" ); FilterExpression expression = dialect.parseGlobalExpression("/job", queryParams); assertEquals("job.jobId IN [1]", expression.toString()); }
@Test public void testFilterOnCustomizedStringIdField() throws ParseException { MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<>(); queryParams.add( "filter", "id==*identifier*" ); FilterExpression expression = dialect.parseGlobalExpression("/stringForId", queryParams); assertEquals("stringId.surrogateKey INFIX_CASE_INSENSITIVE [identifier]", expression.toString()); }
@Test public void testInfixFilterOnPrimitiveIdField() throws ParseException { MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<>(); queryParams.add( "filter", "id==*1*" ); FilterExpression expression = dialect.parseGlobalExpression("/primitiveTypeId", queryParams); assertEquals(expression.toString(), "primitiveId.primitiveId INFIX_CASE_INSENSITIVE [1]" ); }
@Test public void testIsemptyOperatorBool() throws Exception { MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<>(); queryParams.add( "filter", "title=isempty=true" ); FilterExpression expression = dialect.parseGlobalExpression("/book", queryParams); assertEquals("book.title ISEMPTY []", expression.toString()); }
@Test public void testIsemptyOperatorInt() throws Exception { MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<>(); queryParams.add( "filter", "authors=isempty=1" ); FilterExpression expression = dialect.parseGlobalExpression("/book", queryParams); assertEquals("book.authors ISEMPTY []", expression.toString()); }
@Test public void testNotemptyOperatorBool() throws Exception { MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<>(); queryParams.add( "filter", "authors=isempty=false" ); FilterExpression expression = dialect.parseGlobalExpression("/book", queryParams); assertEquals("book.authors NOTEMPTY []", expression.toString()); }
@Test public void testNotemptyOperatorInt() throws Exception { MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<>(); queryParams.add( "filter", "title=isempty=0" ); FilterExpression expression = dialect.parseGlobalExpression("/book", queryParams); assertEquals("book.title NOTEMPTY []", expression.toString()); }
@Test public void testMemberOfOperatorInt() throws Exception { MultivaluedMap<String, String> queryParams = new MultivaluedHashMap<>(); queryParams.add( "filter", "awards=hasmember=title1" ); FilterExpression expression = dialect.parseGlobalExpression("/book", queryParams); assertEquals("book.awards HASMEMBER [title1]", expression.toString()); }