class AnalyzedMLRuleRequest extends RemoteRule.RemoteRequest {
    final List<MLServerProto.AnalyzedMatchRequest> requests;
    final List<AnalyzedSentence> sentences;

    public AnalyzedMLRuleRequest(List<MLServerProto.AnalyzedMatchRequest> requests, List<AnalyzedSentence> sentences) {
      this.requests = requests;
      this.sentences = sentences;
    }
  }

  @Override
  protected RemoteRule.RemoteRequest prepareRequest(List<AnalyzedSentence> sentences, @Nullable Long textSessionId) {<FILL_FUNCTION_BODY>

    List<Long> ids = Collections.emptyList();
    // TODO this is a temp fix to avoid sending too long sentences to the server
    List<AnalyzedSentence> filteredSentences = sentences.stream()
      .filter(s -> s.getText().length() <= maxSentenceLength)
      .collect(Collectors.toList());

    if (textSessionId != null) {
      ids = Collections.nCopies(filteredSentences.size(), textSessionId);
    }
    if (sendAnalyzedData) {
      List<MLServerProto.AnalyzedMatchRequest> requests = new ArrayList<>();

      for (int offset = 0; offset < filteredSentences.size(); offset += batchSize) {
        MLServerProto.AnalyzedMatchRequest req = MLServerProto.AnalyzedMatchRequest.newBuilder()
          .addAllSentences(filteredSentences
            .subList(offset, Math.min(filteredSentences.size(), offset + batchSize))
            .stream().map(GRPCUtils::toGRPC).collect(Collectors.toList()))
          .setInputLogging(inputLogging)
          .addAllTextSessionID(textSessionId != null ?
            ids.subList(offset, Math.min(filteredSentences.size(), offset + batchSize))
            : Collections.emptyList())
          .build();
        requests.add(req);
      }
      return new AnalyzedMLRuleRequest(requests, filteredSentences);
    } else {
      List<MLServerProto.MatchRequest> requests = new ArrayList<>();

      for (int offset = 0; offset < filteredSentences.size(); offset += batchSize) {
        List<String> text = filteredSentences.stream().map(AnalyzedSentence::getText).map(s -> {
          if (whitespaceNormalisation) {
            // non-breaking space can be treated as normal space
            return WHITESPACE_REGEX.matcher(s).replaceAll(" ");
          } else {
            return s;
          }
        }).collect(Collectors.toList());
        MLServerProto.MatchRequest req = MLServerProto.MatchRequest.newBuilder()
          .addAllSentences(text.subList(offset, Math.min(text.size(), offset + batchSize)))
          .setInputLogging(inputLogging)
          .addAllTextSessionID(textSessionId != null ?
                              ids.subList(offset, Math.min(text.size(), offset + batchSize))
                              : Collections.emptyList())
          .build();
        requests.add(req);
      }
      if (requests.size() > 1) {
        logger.debug("Split {} sentences into {} requests for {}", filteredSentences.size(), requests.size(), getId());
      }
      return new MLRuleRequest(requests, filteredSentences, textSessionId);
    }
  
<methods>public void <init>(org.languagetool.Language, java.util.ResourceBundle, org.languagetool.rules.RemoteRuleConfig, boolean, java.lang.String) ,public void <init>(org.languagetool.Language, java.util.ResourceBundle, org.languagetool.rules.RemoteRuleConfig, boolean) ,public CircuitBreaker circuitBreaker() ,public static void fixMatchOffsets(org.languagetool.AnalyzedSentence, List<org.languagetool.rules.RuleMatch>) ,public java.lang.String getId() ,public org.languagetool.rules.RemoteRuleConfig getServiceConfiguration() ,public long getTimeout(long) ,public boolean isPremium() ,public org.languagetool.rules.RuleMatch[] match(org.languagetool.AnalyzedSentence) throws java.io.IOException,public FutureTask<org.languagetool.rules.RemoteRuleResult> run(List<org.languagetool.AnalyzedSentence>) ,public FutureTask<org.languagetool.rules.RemoteRuleResult> run(List<org.languagetool.AnalyzedSentence>, java.lang.Long) ,public static void shutdown() <variables>protected static final ConcurrentMap<java.lang.String,CircuitBreaker> circuitBreakers,protected final non-sealed boolean filterMatches,protected final non-sealed boolean fixOffsets,protected final non-sealed boolean inputLogging,private static final Logger logger,protected final non-sealed org.languagetool.JLanguageTool lt,protected final non-sealed boolean premium,protected final non-sealed org.languagetool.Language ruleLanguage,protected final non-sealed org.languagetool.rules.RemoteRuleConfig serviceConfiguration,protected static final List<java.lang.Runnable> shutdownRoutines,protected final non-sealed java.util.regex.Pattern suppressMisspelledMatch,protected final non-sealed java.util.regex.Pattern suppressMisspelledSuggestions,protected final non-sealed boolean whitespaceNormalisation