Class CommandHandler<M>

  • Type Parameters:
    M - the class of the messages this command handler processes

    public abstract class CommandHandler<M>
    extends Object
    A base class for command handlers that does the common logic.

    Each method of this class starting with do, should usually be called by a subclass. Typically per each such method a subclass will have an according method that gets the needed arguments injected by the CDI framework. CDI cannot inject beans into methods that use wildcards (like Restriction<? super M>) but only into methods that define concrete type arguments (like Restriction<? super Message>). Due to this fact, this class cannot get the beans injected themselves, but has to rely on the subclass to get the beans injected and forward them to the superclass.

    If a subclass needs to do additional actions like registering message listeners on injected beans, this could for example be done in a method annotated with @PostConstruct.

    • Constructor Detail

      • CommandHandler

        public CommandHandler()
    • Method Detail

      • doSetCommandContextTransformers

        protected void doSetCommandContextTransformers​(Instance<CommandContextTransformer<? super M>> commandContextTransformers)
        Sets the command context transformers for this command handler.

        A subclass will typically have a method where it gets this injected, specific to the handled message type, and forwards its parameter as argument to this method like

        
         @Inject
         void setCommandContextTransformers(
                 @Any Instance<CommandContextTransformer<? super Message>> commandContextTransformers) {
             doSetCommandContextTransformers(commandContextTransformers);
         }
         
        Parameters:
        commandContextTransformers - the command context transformers for this command handler
      • doSetAvailableRestrictions

        protected void doSetAvailableRestrictions​(Instance<Restriction<? super M>> availableRestrictions)
        Sets the available restrictions for this command handler.

        A subclass will typically have a method where it gets these injected, specific to the handled message type, and forwards its parameter as argument to this method like

        
         @Inject
         void setAvailableRestrictions(Instance<Restriction<? super Message>> availableRestrictions) {
             doSetAvailableRestrictions(availableRestrictions);
         }
         
        Parameters:
        availableRestrictions - the available restrictions for this command handler
      • doSetCommands

        protected void doSetCommands​(Instance<Command<? super M>> commands)
        Sets the commands for this command handler.

        A subclass will typically have a method where it gets these injected, specific to the handled message type, and forwards its parameter as argument to this method like

        
         @Inject
         void setCommands(Instance<Command<? super Message>> commands) {
             doSetCommands(commands);
         }
         
        Parameters:
        commands - the available commands for this command handler
      • doHandleMessage

        protected void doHandleMessage​(CommandContext<M> commandContext)
        Handles the given command context.
        • if the command is already set, fast forwards to command execution phase
        • if not but the alias is already set, fast forwards to command computation phase
        • if not but the prefix is already set, fast forwards to alias and parameter string computation phase
        • if no fast forward was done, continues with prefix computation phase

        These phases check the message content for a command invocation, check the configured restrictions for the command and if all passed, invoke the command synchronously or asynchronously as configured.

        If the command was denied by any restriction, a command not allowed CDI event is fired asynchronously. (See for example CommandNotAllowedEventJavacord)

        If the message started with the command prefix, but no matching command was found, a command not found CDI event is fired asynchronously. (See for example CommandNotFoundEventJavacord)

        There are also multiple phases where CommandContextTransformers are called that can influence the further command processing as well as skip phases or abort command processing with a command not found event being fired. The phases and their effect are described at CommandContextTransformer.Phase.

        Parameters:
        commandContext - the command context, usually populated with only message and message content, but not necessarily
        See Also:
        CommandContextTransformer.Phase
      • fireCommandNotAllowedEvent

        protected abstract void fireCommandNotAllowedEvent​(CommandContext<M> commandContext)
        Fires a command not allowed CDI event asynchronously using Event.fireAsync(Object) that can be handled using @ObservesAsync.
        Parameters:
        commandContext - the command context, usually fully populated but not necessarily
        See Also:
        @ObservesAsync
      • fireCommandNotFoundEvent

        protected abstract void fireCommandNotFoundEvent​(CommandContext<M> commandContext)
        Fires a command not found CDI event asynchronously using Event.fireAsync(Object) that can be handled using @ObservesAsync.
        Parameters:
        commandContext - the command context, usually populated according to current phase where the event was fired
        See Also:
        @ObservesAsync
      • executeAsync

        protected void executeAsync​(CommandContext<M> commandContext,
                                    Runnable commandExecutor)
        Executes the given command executor that is caused by the given message asynchronously.

        The default implementation executes the command in a thread pool and logs any throwables on error level. A subclass that has some means to execute tasks asynchronously anyways like the thread pool provided by Javacord, can overwrite this message and replace the asynchronous execution implementation.

        Parameters:
        commandContext - the command context, usually fully populated but not necessarily
        commandExecutor - the executor that runs the actual command implementation
      • getParameterConverterTypeLiteralByMessageType

        public abstract Map.Entry<Class<M>,​TypeLiteral<ParameterConverter<? super M,​?>>> getParameterConverterTypeLiteralByMessageType()
        Returns the map entry for mapping the message class to a parameter converter type literal.
        Returns:
        the map entry for mapping the message class to a parameter converter type literal