@Override
 protected ValidateQueryResponse newResponse(
     ValidateQueryRequest request,
     AtomicReferenceArray shardsResponses,
     ClusterState clusterState) {
   int successfulShards = 0;
   int failedShards = 0;
   boolean valid = true;
   List<ShardOperationFailedException> shardFailures = null;
   List<QueryExplanation> queryExplanations = null;
   for (int i = 0; i < shardsResponses.length(); i++) {
     Object shardResponse = shardsResponses.get(i);
     if (shardResponse == null) {
       // simply ignore non active shards
     } else if (shardResponse instanceof BroadcastShardOperationFailedException) {
       failedShards++;
       if (shardFailures == null) {
         shardFailures = new ArrayList<>();
       }
       shardFailures.add(
           new DefaultShardOperationFailedException(
               (BroadcastShardOperationFailedException) shardResponse));
     } else {
       ShardValidateQueryResponse validateQueryResponse =
           (ShardValidateQueryResponse) shardResponse;
       valid = valid && validateQueryResponse.isValid();
       if (request.explain() || request.rewrite()) {
         if (queryExplanations == null) {
           queryExplanations = new ArrayList<>();
         }
         queryExplanations.add(
             new QueryExplanation(
                 validateQueryResponse.getIndex(),
                 validateQueryResponse.isValid(),
                 validateQueryResponse.getExplanation(),
                 validateQueryResponse.getError()));
       }
       successfulShards++;
     }
   }
   return new ValidateQueryResponse(
       valid,
       queryExplanations,
       shardsResponses.length(),
       successfulShards,
       failedShards,
       shardFailures);
 }
 @Override
 protected ShardValidateQueryRequest newShardRequest(
     int numShards, ShardRouting shard, ValidateQueryRequest request) {
   String[] filteringAliases =
       indexNameExpressionResolver.filteringAliases(
           clusterService.state(), shard.getIndexName(), request.indices());
   return new ShardValidateQueryRequest(shard.shardId(), filteringAliases, request);
 }
 @Override
 protected GroupShardsIterator shards(
     ClusterState clusterState, ValidateQueryRequest request, String[] concreteIndices) {
   // Hard-code routing to limit request to a single shard, but still, randomize it...
   Map<String, Set<String>> routingMap =
       indexNameExpressionResolver.resolveSearchRouting(
           clusterState, Integer.toString(Randomness.get().nextInt(1000)), request.indices());
   return clusterService
       .operationRouting()
       .searchShards(clusterState, concreteIndices, routingMap, "_local");
 }
 @Override
 protected void doExecute(
     Task task, ValidateQueryRequest request, ActionListener<ValidateQueryResponse> listener) {
   request.nowInMillis = System.currentTimeMillis();
   super.doExecute(task, request, listener);
 }