2323 */
2424public class Condition {
2525
26- private static Logger log = LoggerFactory .getLogger (Condition .class );
26+ private static Logger log = LoggerFactory .getLogger (Condition .class );
2727
28- /**
29- * Default constructor
30- */
31- public Condition () {
32- }
28+ /**
29+ * Default constructor
30+ */
31+ public Condition () {
32+ }
3333
34- public Map <String , Object > filter = new LinkedHashMap <>();
34+ /**
35+ * A constructor accepting a map as filter
36+ *
37+ * @param filter
38+ */
39+ public Condition (Map <String , Object > filter ) {
40+ this .filter = filter ;
41+ }
3542
36- public List <String > sort = List . of ();
43+ public Map <String , Object > filter = new LinkedHashMap <> ();
3744
38- public Set <String > fields = new LinkedHashSet <> ();
45+ public List <String > sort = List . of ();
3946
40- public int offset = 0 ;
41- public int limit = 100 ;
47+ public Set <String > fields = new LinkedHashSet <>();
4248
43- /**
44- * whether this query is cross-partition or not (default to false)
45- */
46- public boolean crossPartition = false ;
49+ public int offset = 0 ;
50+ public int limit = 100 ;
51+
52+ /**
53+ * whether this query is cross-partition or not (default to false)
54+ */
55+ public boolean crossPartition = false ;
4756
4857 /**
4958 * whether this query is a negative query. (default to false)
@@ -346,23 +355,30 @@ FilterQuery generateFilterQuery(String selectPart, List<SqlParameter> params,
346355
347356 var subFilterQueryToAdd = "" ;
348357
349- if (entry .getKey ().startsWith (SubConditionType .SUB_COND_AND . name () )) {
358+ if (entry .getKey ().startsWith (SubConditionType .AND )) {
350359 // sub query AND
351- var subQueries = extractSubQueries (entry .getValue ());
352- subFilterQueryToAdd = generateFilterQuery4List (subQueries , "AND" , params , conditionIndex , paramIndex );
353-
354- } else if (entry .getKey ().startsWith (SubConditionType .SUB_COND_OR .name ())) {
355- // sub query OR
356- var subQueries = extractSubQueries (entry .getValue ());
357- subFilterQueryToAdd = generateFilterQuery4List (subQueries , "OR" , params , conditionIndex , paramIndex );
358-
359- } else {
360- // normal expression
361- var exp = parse (entry .getKey (), entry .getValue ());
362- var expQuerySpec = exp .toQuerySpec (paramIndex );
363- subFilterQueryToAdd = expQuerySpec .getQueryText ();
364- params .addAll (expQuerySpec .getParameters ());
365- }
360+ var subQueries = extractSubQueries (entry .getValue ());
361+ subFilterQueryToAdd = generateFilterQuery4List (subQueries , "AND" , params , conditionIndex , paramIndex );
362+
363+ } else if (entry .getKey ().startsWith (SubConditionType .OR )) {
364+ // sub query OR
365+ var subQueries = extractSubQueries (entry .getValue ());
366+ subFilterQueryToAdd = generateFilterQuery4List (subQueries , "OR" , params , conditionIndex , paramIndex );
367+
368+ } else if (entry .getKey ().startsWith (SubConditionType .NOT )) {
369+ // sub query NOT
370+ var subQueries = extractSubQueries (entry .getValue ());
371+ var subQueryWithNot = Condition .filter (SubConditionType .AND , subQueries ).not ();
372+ // recursively generate the filterQuery with negative flag true
373+ var filterQueryWithNot = subQueryWithNot .generateFilterQuery ("" , params , conditionIndex , paramIndex );
374+ subFilterQueryToAdd = " " + removeConnectPart (filterQueryWithNot .queryText .toString ());
375+ } else {
376+ // normal expression
377+ var exp = parse (entry .getKey (), entry .getValue ());
378+ var expQuerySpec = exp .toQuerySpec (paramIndex );
379+ subFilterQueryToAdd = expQuerySpec .getQueryText ();
380+ params .addAll (expQuerySpec .getParameters ());
381+ }
366382
367383 if (StringUtils .isNotEmpty (subFilterQueryToAdd )) {
368384 queryTexts .add (subFilterQueryToAdd );
@@ -384,32 +400,57 @@ FilterQuery generateFilterQuery(String selectPart, List<SqlParameter> params,
384400 return new FilterQuery (queryText , params , conditionIndex , paramIndex );
385401 }
386402
387- /**
388- * add negative NOT operator for queryText, if not empty
389- *
390- * @param queryText
391- * @param negative
392- * @return
393- */
394- static String processNegativeQuery (String queryText , boolean negative ) {
395- return negative && StringUtils .isNotEmpty (queryText ) ?
396- " NOT(" + queryText + ")" : queryText ;
397- }
403+ /**
404+ * add negative NOT operator for queryText, if not empty
405+ *
406+ * @param queryText
407+ * @param negative
408+ * @return
409+ */
410+ static String processNegativeQuery (String queryText , boolean negative ) {
411+ return negative && StringUtils .isNotEmpty (queryText ) ?
412+ " NOT(" + queryText + ")" : queryText ;
413+ }
398414
399- /**
400- * extract subQueries for SUB_COND_AND / SUB_COND_OR 's filter value
401- *
402- * @param value
403- */
404- static List < Condition > extractSubQueries (Object value ) {
405- if (value == null ) {
406- return List . of () ;
407- }
415+ /**
416+ * extract subQuery for SUB_COND_AND / SUB_COND_OR 's filter value, single condition only.
417+ *
418+ * @param value
419+ */
420+ static Condition extractSubQuery (Object value ) {
421+ if (value == null ) {
422+ return null ;
423+ }
408424
409425 if (value instanceof Condition ) {
410- return List .of ((Condition ) value );
426+ // single condition
427+ return (Condition ) value ;
428+ } else if (value instanceof Map <?, ?>) {
429+ // single condition in the form of map
430+ return new Condition (JsonUtil .toMap (value ));
431+ } else if (value instanceof Collection <?>) {
432+ throw new IllegalArgumentException ("Cannot convert input to a single condition. Ensure the input is a single value(not a collection)." + value );
433+ }
434+ throw new IllegalArgumentException ("Invalid input. expect a condition or a map. " + value );
435+ }
436+
437+ /**
438+ * extract subQueries for SUB_COND_AND / SUB_COND_OR 's filter value
439+ *
440+ * @param value
441+ */
442+ static List <Condition > extractSubQueries (Object value ) {
443+ if (value == null ) {
444+ return List .of ();
445+ }
446+
447+ if (value instanceof Condition || value instanceof Map <?, ?>) {
448+ // single condition
449+ return List .of (extractSubQuery (value ));
411450 } else if (value instanceof List <?>) {
412- return (List <Condition >) value ;
451+ // multi condition
452+ var listValue = (List <Object >) value ;
453+ return listValue .stream ().map (v -> extractSubQuery (v )).filter (Objects ::nonNull ).collect (Collectors .toList ());
413454 }
414455
415456 return List .of ();
@@ -665,17 +706,6 @@ public static Condition rawSql(String queryText) {
665706 return cond ;
666707 }
667708
668- /**
669- * sub query 's OR / RAW operator
670- *
671- * <p>
672- * TODO SUB_COND_NOT operator
673- * </p>
674- */
675- public enum SubConditionType {
676- SUB_COND_AND , SUB_COND_OR
677- }
678-
679709 /**
680710 * Instead of c.key, return c["key"] or c["key1"]["key2"] for query. In order for cosmosdb reserved words
681711 *
0 commit comments