001/* 002 * SPDX-FileCopyrightText: none 003 * SPDX-License-Identifier: CC0-1.0 004 */ 005 006package gov.nist.secauto.metaschema.cli.processor.command; 007 008import gov.nist.secauto.metaschema.cli.processor.CLIProcessor.CallingContext; 009import gov.nist.secauto.metaschema.cli.processor.ExitCode; 010import gov.nist.secauto.metaschema.cli.processor.ExitStatus; 011 012import org.apache.commons.cli.CommandLine; 013 014import java.util.Collection; 015import java.util.Collections; 016import java.util.LinkedHashMap; 017import java.util.Map; 018import java.util.stream.Collectors; 019 020import edu.umd.cs.findbugs.annotations.NonNull; 021 022public abstract class AbstractParentCommand implements ICommand { 023 @NonNull 024 private final Map<String, ICommand> commandToSubcommandHandlerMap; 025 private final boolean subCommandRequired; 026 027 @SuppressWarnings("null") 028 protected AbstractParentCommand(boolean subCommandRequired) { 029 this.commandToSubcommandHandlerMap = Collections.synchronizedMap(new LinkedHashMap<>()); 030 this.subCommandRequired = subCommandRequired; 031 } 032 033 protected final void addCommandHandler(ICommand handler) { 034 String commandName = handler.getName(); 035 this.commandToSubcommandHandlerMap.put(commandName, handler); 036 } 037 038 @Override 039 public ICommand getSubCommandByName(String name) { 040 return commandToSubcommandHandlerMap.get(name); 041 } 042 043 @SuppressWarnings("null") 044 @Override 045 public Collection<ICommand> getSubCommands() { 046 return Collections.unmodifiableCollection(commandToSubcommandHandlerMap.values()); 047 } 048 049 @Override 050 public boolean isSubCommandRequired() { 051 return subCommandRequired; 052 } 053 054 @Override 055 public ICommandExecutor newExecutor(CallingContext callingContext, CommandLine cmdLine) { 056 return ICommandExecutor.using(callingContext, cmdLine, this::executeCommand); 057 } 058 059 @NonNull 060 protected ExitStatus executeCommand( 061 @NonNull CallingContext callingContext, 062 @NonNull CommandLine commandLine) { 063 callingContext.showHelp(); 064 ExitStatus status; 065 if (isSubCommandRequired()) { 066 status = ExitCode.INVALID_COMMAND 067 .exitMessage("Please use one of the following sub-commands: " + 068 getSubCommands().stream() 069 .map(ICommand::getName) 070 .collect(Collectors.joining(", "))); 071 } else { 072 status = ExitCode.OK.exit(); 073 } 074 return status; 075 } 076 077}