docs: @SuppressWarnings("unchecked")
      public static Map<String, Object> normaliseAndValidateQuery(Map<String, Object> query) throws QueryException{
          boolean isWildCard = false;
          if (query.isEmpty()) {
              isWildCard = true;
          }
  
          // First expand the query to include a leading compound predicate
          // if there isn't one already.
          query = addImplicitAnd(query);
  
          // At this point we will have a single entry map, key AND or OR,
          // forming the compound predicate.
          String compoundOperator = (String) query.keySet().toArray()[0];
          List<Object> predicates = new ArrayList<Object>();
          if (query.get(compoundOperator) instanceof List) {
              // Next make sure all the predicates have an operator -- the EQ
              // operator is implicit and we need to add it if there isn't one.
              // Take
              //     [ {"field1": "mike"}, ... ]
              // and make
              //     [ {"field1": { "$eq": "mike"} }, ... ]
              predicates = addImplicitEq((List<Object>) query.get(compoundOperator));
  
              // Then all shorthand operators like $ne, if present, need to be converted
              // to their logical longhand equivalent.
              // Take
              //     [ { "field1": { "$ne": "mike"} }, ... ]
              // and make
              //     [ { "field1": { "$not" : { "$eq": "mike"} } }, ... ]
              predicates = handleShortHandOperators(predicates);
  
              // Now in the event that extraneous $not operators exist in the query,
              // these operators must be compressed down to the their logical equivalent.
              // Take
              //     [ { "field1": { "$not" : { $"not" : { "$eq": "mike"} } } }, ... ]
              // and make
              //     [ { "field1": { "$eq": "mike"} }, ... ]
              predicates = compressMultipleNotOperators(predicates);
  
              // Here we ensure that all non-whole number arguments included in a $mod
              // clause are truncated.  This provides for consistent behavior between
              // the SQL engine and the unindexed matcher.
              // Take
              //     [ { "field1": { "$mod" : [ 2.6, 1.7] } }, ... ]
              // and make
              //     [ { "field1": { "$mod" : [ 2, 1 ] } }, ... ]
              predicates = truncateModArguments(predicates);
          }
  
          Map<String, Object> selector = new HashMap<String, Object>();
          selector.put(compoundOperator, predicates);
          if (!isWildCard) {
              validateSelector(selector);
          }
  
          return selector;
      }