@Override
  public void validate() {
    if (!pluginServerFilenames.isEmpty() || !pluginServerPorts.isEmpty()) {
      if (pluginServerFilenames != null && !pluginServerFilenames.isEmpty()) {
        for (String pluginServerFilename : pluginServerFilenames) {
          if (!Files.exists(Paths.get(pluginServerFilename))) {
            throw new ParameterException(
                String.format("Language server path %s does not exist", pluginServerFilename));
          }
        }
      }

      if (pluginServerPorts != null && !pluginServerPorts.isEmpty()) {
        for (String pluginServerPort : pluginServerPorts) {
          try {
            int port = Integer.parseInt(pluginServerPort);
            if (!(port <= NetworkEndpointUtils.MAX_PORT_NUMBER && port > 0)) {
              throw new ParameterException(
                  String.format(
                      "Port out of range. Expected [0, %s], actual %s.",
                      NetworkEndpointUtils.MAX_PORT_NUMBER, pluginServerPort));
            }
          } catch (NumberFormatException e) {
            throw new ParameterException(
                String.format("Port number must be an integer. Got %s instead.", pluginServerPort),
                e);
          }
        }
      }

      var pathCounts = pluginServerFilenames == null ? 0 : pluginServerFilenames.size();
      var portCounts = pluginServerPorts == null ? 0 : pluginServerPorts.size();
      if (pathCounts != portCounts) {
        throw new ParameterException(
            String.format(
                "Number of plugin server paths must be equal to number of plugin server ports."
                    + " Paths: %s. Ports: %s.",
                pathCounts, portCounts));
      }

      if (!pluginServerRpcDeadlineSeconds.isEmpty()) {
        if (pluginServerRpcDeadlineSeconds.size() != pathCounts) {
          throw new ParameterException(
              String.format(
                  "Number of plugin server rpc deadlines must be equal to number of plugin server"
                      + " ports. Paths: %s. Ports: %s. Deadlines: %s",
                  pathCounts, portCounts, pluginServerRpcDeadlineSeconds.size()));
        }
      }
    }

    if (!remotePluginServerAddress.isEmpty()) {
      var addrCounts = remotePluginServerAddress.size();
      var portCounts = remotePluginServerPort.size();
      if (addrCounts != portCounts) {
        throw new ParameterException(
            String.format(
                "Number of remote plugin server paths must be equal to number of plugin server "
                    + "ports. Addresses: %s. Ports: %s.",
                addrCounts, portCounts));
      }

      if (!remotePluginServerRpcDeadlineSeconds.isEmpty()) {
        if (remotePluginServerRpcDeadlineSeconds.size() != addrCounts) {
          throw new ParameterException(
              String.format(
                  "Number of plugin server rpc deadlines must be equal to number of plugin server"
                      + " ports. Paths: %s. Ports: %s. Deadlines: %s",
                  addrCounts, portCounts, pluginServerRpcDeadlineSeconds.size()));
        }
      }

      for (int port : remotePluginServerPort) {
        if (!(port <= NetworkEndpointUtils.MAX_PORT_NUMBER && port > 0)) {
          throw new ParameterException(
              String.format(
                  "Remote plugin server port out of range. Expected [0, %s], actual %s.",
                  NetworkEndpointUtils.MAX_PORT_NUMBER, port));
        }
      }
    }
  }
@Test
  public void validate_whenPythonPluginServerValidNumberOfDeadlines_succeeds() {
    LanguageServerOptions options = new LanguageServerOptions();
    options.remotePluginServerAddress = ImmutableList.of("127.0.0.1");
    options.remotePluginServerPort = ImmutableList.of(10000);
    options.remotePluginServerRpcDeadlineSeconds = ImmutableList.of(150);

    options.validate();
  }