Interface ParameterParser


  • public interface ParameterParser
    A parser that can semantically parse and validate a command parameter string according to a defined usage string syntax and return the parsed parameters, optionally converted to given types.

    The usage string has to follow this pre-defined format for non-typed parameters:

    • Placeholders for free text without whitespaces (in the value) look like <my placeholder>
    • One placeholder for free text with whitespaces (in the value) is allowed as effectively last parameter and looks like <my placeholder...>
    • Literal parameters look like 'literal'
    • Optional parts are enclosed in square brackets like [<optional placeholder>]
    • Alternatives are enclosed in parentheses and are separated by pipe characters like ('all' | 'some' | 'none')
    • Whitespace characters between the defined tokens are optional and ignored
    Examples:
    • @Usage("<coin type> <amount>")
    • @Usage("['all'] ['exact']")
    • @Usage("[<text...>]")
    • @Usage("(<targetLanguage> '|' | <sourceLanguage> <targetLanguage>) <text...>")
    The values for non-typed parameters are always Strings unless multiple parameters with the same name have a value given by the user like with the pattern <foo> <foo>, in which case the value will be a List<String>.

    For typed parameters the format is almost the same. The only difference is, that a colon (:) followed by a parameter type can optionally be added after a parameter name like for example <amount:integer>. Parameters that do not have a type specified, are implicitly of type string. If a colon is needed within the actual parameter name, a type has to be specified explicitly, as invalid parameter types are not allowed and will trigger an error at runtime.

    To inject the parameter parser for non-typed parameters, just inject this interface. For the typed parser, add the qualifier @Typed to the injected field or parameter.

    Warning: If you for example have

    • an optional placeholder followed by an optional literal like in [<placeholder>] ['literal'] or
    • alternatively a placeholder or literal like in (<placeholder> | 'literal')
    and a user invokes the command with only the parameter literal, it could fit in both parameter slots. You have to decide yourself in which slot it belongs. For cases where the literal parameter can never be meant for the placeholder, you can use Parameters.fixup(String, String) to correct the parameters instance for the two given parameters.
    • Nested Class Summary

      Nested Classes 
      Modifier and Type Interface Description
      static interface  ParameterParser.Typed
      A CDI qualifier that is used for selecting the typed parameter parser instead of the non-typed one which is injected by default.
    • Method Summary

      All Methods Instance Methods Abstract Methods 
      Modifier and Type Method Description
      <V> Parameters<V> parse​(CommandContext<?> commandContext)
      Returns the parsed parameters for the usage of the command that was triggered by the given command context with an optional implicit downcast for the values.
    • Method Detail

      • parse

        <V> Parameters<V> parse​(CommandContext<?> commandContext)
        Returns the parsed parameters for the usage of the command that was triggered by the given command context with an optional implicit downcast for the values. The resulting parameters instance will have the placeholder names and literal parameters as keys and the actual supplied arguments as values. In case of the typed parser the values are the converted ones. If multiple placeholders with the same name have a value like with the pattern <foo> <foo>, the values are returned as List<?> for that parameter.

        If only a certain class is queried from the parameters instance, or there is anyway only a certain class present, the returned reference can implicitly downcast the values by using ParameterParser to define the class. One example for this is the non-typed parser with a usage definition where a parameter name cannot be assigned twice by the user where all values are Strings. V can be defined using an explicit type parameter like with

        
         parameterParser.<String>parse(...).get("placeholder").map(String::intern);
         
        or using implicit type inference like with
        
         Parameters<String> parameters = parameterParser.parse(commandContext);
         

        If multiple unrelated classes are needed, this method should not be called multiple times to produce parameters instances with different value types, as each time the parameter string has to be parsed and each time the arguments need to be converted if necessary. Instead use Parameters<Object> or Parameters<? super Object> and then use the downcasting methods of Parameters, including Parameters.getParameters() to downcast the whole instance, to further narrow down the value type.

        Warning: Be aware that choosing V must be done wisely as it is an unsafe operation. If you for example select String for V and then try to get a User object from the returned parameters instance, you will get a ClassCastException at runtime.

        Warning: If you for example have

        • an optional placeholder followed by an optional literal like in [<placeholder>] ['literal'] or
        • alternatively a placeholder or literal like in (<placeholder> | 'literal')
        and a user invokes the command with only the parameter literal, it could fit in both parameter slots. You have to decide yourself in which slot it belongs. For cases where the literal parameter can never be meant for the placeholder, you can use Parameters.fixup(String, String) to correct the parameters instance for the two given parameters.
        Type Parameters:
        V - the class to which the values are implicitly downcasted
        Parameters:
        commandContext - the command context, usually fully populated but not necessarily
        Returns:
        the parsed and converted parameters
        Throws:
        ParameterParseException - if the parameter string does not adhere to the usage pattern of the given command, which includes that there are arguments given when none were expected; the message is suitable to be directly forwarded to end users
        InvalidParameterFormatException - for the typed parameter parser if the format of a parameter is invalid and could not be parsed; the message should be suitable to be directly forwarded to end users
        InvalidParameterValueException - for the typed parameter parser if the value of a parameter is invalid, for example the id of an unknown user was given; the message should be suitable to be directly forwarded to end users
        See Also:
        Parameters.fixup(String, String)