static ReassignPartitionsCommandOptions validateAndParseArgs(String[] args) {
        ReassignPartitionsCommandOptions opts = new ReassignPartitionsCommandOptions(args);

        CommandLineUtils.maybePrintHelpOrVersion(opts, HELP_TEXT);

        // Determine which action we should perform.
        List<OptionSpec<?>> validActions = Arrays.asList(opts.generateOpt, opts.executeOpt, opts.verifyOpt,
            opts.cancelOpt, opts.listOpt);

        List<OptionSpec<?>> allActions = validActions.stream()
            .filter(a -> opts.options.has(a))
            .collect(Collectors.toList());

        if (allActions.size() != 1) {
            CommandLineUtils.printUsageAndExit(opts.parser, String.format("Command must include exactly one action: %s",
                validActions.stream().map(a -> "--" + a.options().get(0)).collect(Collectors.joining(", "))));
        }

        OptionSpec<?> action = allActions.get(0);

        if (!opts.options.has(opts.bootstrapServerOpt))
            CommandLineUtils.printUsageAndExit(opts.parser, "Please specify --bootstrap-server");

        // Make sure that we have all the required arguments for our action.
        Map<OptionSpec<?>, List<OptionSpec<?>>> requiredArgs = new HashMap<>();

        requiredArgs.put(opts.verifyOpt, Collections.singletonList(
            opts.reassignmentJsonFileOpt
        ));
        requiredArgs.put(opts.generateOpt, Arrays.asList(
            opts.topicsToMoveJsonFileOpt,
            opts.brokerListOpt
        ));
        requiredArgs.put(opts.executeOpt, Collections.singletonList(
            opts.reassignmentJsonFileOpt
        ));
        requiredArgs.put(opts.cancelOpt, Collections.singletonList(
            opts.reassignmentJsonFileOpt
        ));
        requiredArgs.put(opts.listOpt, Collections.emptyList());

        CommandLineUtils.checkRequiredArgs(opts.parser, opts.options, requiredArgs.get(action).toArray(new OptionSpec[0]));

        Map<OptionSpec<?>, List<OptionSpec<?>>> permittedArgs = new HashMap<>();

        permittedArgs.put(opts.verifyOpt, Arrays.asList(
            opts.bootstrapServerOpt,
            opts.commandConfigOpt,
            opts.preserveThrottlesOpt
        ));
        permittedArgs.put(opts.generateOpt, Arrays.asList(
            opts.bootstrapServerOpt,
            opts.brokerListOpt,
            opts.commandConfigOpt,
            opts.disableRackAware
        ));
        permittedArgs.put(opts.executeOpt, Arrays.asList(
            opts.additionalOpt,
            opts.bootstrapServerOpt,
            opts.commandConfigOpt,
            opts.interBrokerThrottleOpt,
            opts.replicaAlterLogDirsThrottleOpt,
            opts.timeoutOpt
        ));
        permittedArgs.put(opts.cancelOpt, Arrays.asList(
            opts.bootstrapServerOpt,
            opts.commandConfigOpt,
            opts.preserveThrottlesOpt,
            opts.timeoutOpt
        ));
        permittedArgs.put(opts.listOpt, Arrays.asList(
            opts.bootstrapServerOpt,
            opts.commandConfigOpt
        ));

        opts.options.specs().forEach(opt -> {
            if (!opt.equals(action) &&
                !requiredArgs.getOrDefault(action, Collections.emptyList()).contains(opt) &&
                !permittedArgs.getOrDefault(action, Collections.emptyList()).contains(opt)) {
                CommandLineUtils.printUsageAndExit(opts.parser,
                    String.format("Option \"%s\" can't be used with action \"%s\"", opt, action));
            }
        });

        return opts;
    }
The entry point for the --cancel command.

@param adminClient           The AdminClient to use.
@param jsonString            The JSON string to use for the topics and partitions to cancel.
@param preserveThrottles     True if we should avoid changing topic or broker throttles.
@param timeoutMs             The maximum time in ms to wait for log directory
                             replica assignment to begin.
@param time                  The Time object to use.

@return                      A tuple of the partition reassignments that were cancelled,
                             and the replica movements that were cancelled.
tools/src/main/java/org/apache/kafka/tools/reassign/ReassignPartitionsCommand.java