@@ -21,7 +21,7 @@ public class CQLParser {
2121 private CQLTokenizer lexer ;
2222 private final int compat ; // When false, implement CQL 1.2
2323 private final Set <String > customRelations = new HashSet <String >();
24-
24+
2525 public static final int V1POINT1 = 12368 ;
2626 public static final int V1POINT2 = 12369 ;
2727 public static final int V1POINT1SORT = 12370 ;
@@ -47,10 +47,10 @@ public CQLParser(int compat) {
4747 this .compat = compat ;
4848 this .allowKeywordTerms = true ;
4949 }
50-
50+
5151 /**
52- * Official CQL grammar allows registered keywords like 'and/or/not/sortby/prox'
53- * to be used unquoted in terms. This constructor allows to create an instance
52+ * Official CQL grammar allows registered keywords like 'and/or/not/sortby/prox'
53+ * to be used unquoted in terms. This constructor allows to create an instance
5454 * of a parser that prohibits this behavior while sacrificing compatibility.
5555 * @param compat CQL version compatibility
5656 * @param allowKeywordTerms when false registered keywords are disallowed in unquoted terms
@@ -59,7 +59,7 @@ public CQLParser(int compat, boolean allowKeywordTerms) {
5959 this .compat = compat ;
6060 this .allowKeywordTerms = allowKeywordTerms ;
6161 }
62-
62+
6363 /**
6464 * The new parser implements CQL 1.2
6565 */
@@ -72,24 +72,25 @@ private static void debug(String str) {
7272 if (DEBUG )
7373 System .err .println ("PARSEDEBUG: " + str );
7474 }
75-
75+
7676 /**
7777 * Registers custom relation in this parser. Note that when a custom relation
7878 * is registered the parser is no longer strictly compliant with the chosen spec.
79+ * Custom relations are case-insensitive.
7980 * @param relation
8081 * @return true if custom relation has not been registered already
8182 */
8283 public boolean registerCustomRelation (String relation ) {
83- return customRelations .add (relation );
84+ return customRelations .add (relation . toLowerCase () );
8485 }
85-
86+
8687 /**
8788 * Unregisters previously registered custom relation in this instance of the parser.
8889 * @param relation
8990 * @return true is relation has been previously registered
9091 */
9192 public boolean unregisterCustomRelation (String relation ) {
92- return customRelations .remove (relation );
93+ return customRelations .remove (relation . toLowerCase () );
9394 }
9495
9596 /**
@@ -117,7 +118,7 @@ public CQLNode parse(String cql)
117118 CQLNode root = parseTopLevelPrefixes ("cql.serverChoice" ,
118119 new CQLRelation (compat == V1POINT2 ? "=" : "scr" ));
119120 if (lexer .what () != CQLTokenizer .TT_EOF )
120- throw new CQLParseException ("junk after end: " + lexer .render (),
121+ throw new CQLParseException ("junk after end: " + lexer .render (),
121122 lexer .pos ());
122123
123124 return root ;
@@ -194,7 +195,7 @@ private ModifierSet gatherModifiers(String base)
194195 match ('/' );
195196 if (lexer .what () != CQLTokenizer .TT_WORD )
196197 throw new CQLParseException ("expected modifier, "
197- + "got " + lexer .render (),
198+ + "got " + lexer .render (),
198199 lexer .pos ());
199200 String type = lexer .value ().toLowerCase ();
200201 match (lexer .what ());
@@ -241,7 +242,7 @@ private CQLNode parseTerm(String index, CQLRelation relation)
241242
242243 if (!isRelation ())
243244 break ; //we're done if no relation
244-
245+
245246 //render relation
246247 String relstr = (lexer .what () == CQLTokenizer .TT_WORD ?
247248 lexer .value () : lexer .render (lexer .what (), false ));
@@ -282,40 +283,39 @@ private CQLNode parsePrefix(String index, CQLRelation relation,
282283
283284 return new CQLPrefixNode (name , identifier , node );
284285 }
285-
286+
286287 private boolean isWordOrString () {
287- return CQLTokenizer .TT_WORD == lexer .what ()
288+ return CQLTokenizer .TT_WORD == lexer .what ()
288289 || CQLTokenizer .TT_STRING == lexer .what ();
289290 }
290291
291292 private boolean isRelation () {
292- debug ("isRelation: checking what()=" + lexer .what () +
293- " (" + lexer .render () + ")" );
294- if (lexer .what () == CQLTokenizer .TT_WORD &&
295- (lexer .value ().indexOf ('.' ) >= 0 ||
296- lexer .value ().equals ("any" ) ||
297- lexer .value ().equals ("all" ) ||
298- lexer .value ().equals ("within" ) ||
299- lexer .value ().equals ("encloses" ) ||
300- (lexer .value ().equals ("exact" ) && compat != V1POINT2 ) ||
301- (lexer .value ().equals ("scr" ) && compat != V1POINT2 ) ||
302- (lexer .value ().equals ("adj" ) && compat == V1POINT2 ) ||
303- customRelations .contains (lexer .value ())))
304- return true ;
305-
293+ debug ("isRelation: checking what()=" + lexer .what () +
294+ " (" + lexer .render () + ")" );
295+ if (lexer .what () == CQLTokenizer .TT_WORD ) {
296+ return lexer .value ().indexOf ('.' ) >= 0 ||
297+ lexer .value ().equalsIgnoreCase ("any" ) ||
298+ lexer .value ().equalsIgnoreCase ("all" ) ||
299+ lexer .value ().equalsIgnoreCase ("within" ) ||
300+ lexer .value ().equalsIgnoreCase ("encloses" ) ||
301+ (lexer .value ().equalsIgnoreCase ("exact" ) && compat != V1POINT2 ) ||
302+ (lexer .value ().equalsIgnoreCase ("scr" ) && compat != V1POINT2 ) ||
303+ (lexer .value ().equalsIgnoreCase ("adj" ) && compat == V1POINT2 ) ||
304+ customRelations .stream ().anyMatch (r -> r .equalsIgnoreCase (lexer .value ()));
305+ }
306306 return isSymbolicRelation ();
307307 }
308308
309309 private boolean isSymbolicRelation () {
310- debug ("isSymbolicRelation: checking what()=" + lexer .what () +
311- " (" + lexer .render () + ")" );
312- return (lexer .what () == '<' ||
313- lexer .what () == '>' ||
314- lexer .what () == '=' ||
315- lexer .what () == CQLTokenizer .TT_LE ||
316- lexer .what () == CQLTokenizer .TT_GE ||
317- lexer .what () == CQLTokenizer .TT_NE ||
318- lexer .what () == CQLTokenizer .TT_EQEQ );
310+ debug ("isSymbolicRelation: checking what()=" + lexer .what () +
311+ " (" + lexer .render () + ")" );
312+ return (lexer .what () == '<' ||
313+ lexer .what () == '>' ||
314+ lexer .what () == '=' ||
315+ lexer .what () == CQLTokenizer .TT_LE ||
316+ lexer .what () == CQLTokenizer .TT_GE ||
317+ lexer .what () == CQLTokenizer .TT_NE ||
318+ lexer .what () == CQLTokenizer .TT_EQEQ );
319319 }
320320
321321 private void match (int token )
@@ -324,7 +324,7 @@ private void match(int token)
324324 if (lexer .what () != token )
325325 throw new CQLParseException ("expected " +
326326 lexer .render (token , true ) +
327- ", " + "got " + lexer .render (),
327+ ", " + "got " + lexer .render (),
328328 lexer .pos ());
329329 lexer .move ();
330330 debug ("match() got token=" + lexer .what () + ", value()='" + lexer .value () + "'" );
@@ -500,7 +500,7 @@ public static void main (String[] args) {
500500 f .close ();
501501 System .out .println (root .toPQF (config ));
502502 } catch (IOException ex ) {
503- System .err .println ("Can't load PQF properties:" +
503+ System .err .println ("Can't load PQF properties:" +
504504 ex .getMessage ());
505505 System .exit (5 );
506506 }
0 commit comments