@startuml command-class-diagram title CR-Core — Command framework (class diagram) skinparam classAttributeIconSize 0 hide empty members package "fr.luc.crcore.command" { interface Command { + getName(): String + getAliases(): List + getPermission(): String + isPlayerOnly(): boolean + getDescription(): String + execute(ctx: CommandContext): CommandResult + tabComplete(sender, argIndex, partial): List + matches(label: String): boolean } abstract class AbstractCommand { - name: String - aliases: List - permission: String - playerOnly: boolean - description: String - usage: String - arguments: List # addAlias(...): void # permission(p): void # playerOnly(): void # description(d): void # usage(u): void # argument(name, type): void # optionalArgument(name, type): void # buildContext(sender, label, subArgs): CommandContext + getRequiredArgumentCount(): int + getTotalArgumentCount(): int + getUsage(): String } abstract class BaseCommand { - subCommandsByName: Map - subCommandsByAlias: Map # addSubCommand(sub: SubCommand): void + findSubCommand(label: String): Optional + getSubCommands(): Collection # execute(ctx): CommandResult + onCommand(sender, cmd, label, args): boolean + onTabComplete(sender, cmd, alias, args): List # checkAccess(sender, target): boolean # handleResult(sender, result): void } abstract class SubCommand { + {abstract} execute(ctx: CommandContext): CommandResult } class CommandContext { - sender: CommandSender - label: String - rawArgs: String[] - parsedArgs: Map + getSender(): CommandSender + isPlayer(): boolean + getPlayer(): Optional + requirePlayer(): Player + get(name: String): T + getOptional(name): Optional + has(name): boolean + reply(msg): void } class CommandResult { - type: Type - message: String + getType(): Type + getMessage(): String + isSuccess(): boolean + {static} success(): CommandResult + {static} success(msg): CommandResult + {static} failure(msg): CommandResult + {static} invalidUsage(): CommandResult + {static} noPermission(): CommandResult + {static} playerOnly(): CommandResult } enum "CommandResult.Type" as ResultType { SUCCESS FAILURE INVALID_USAGE NO_PERMISSION PLAYER_ONLY } class CommandException interface "ArgumentType" as ArgumentType { + parse(input: String): T + suggestions(sender, partial): List } class ArgumentTypes << (S, #FFC107) static >> { + {static} STRING: ArgumentType + {static} INTEGER: ArgumentType + {static} DOUBLE: ArgumentType + {static} BOOLEAN: ArgumentType + {static} ONLINE_PLAYER: ArgumentType + {static} enumOf(type): ArgumentType + {static} choice(choices): ArgumentType } class ArgumentDef << (P, #BBBBBB) package-private >> { - name: String - type: ArgumentType - required: boolean } AbstractCommand ..|> Command BaseCommand --|> AbstractCommand SubCommand --|> AbstractCommand BaseCommand "1" o-- "*" SubCommand : subCommands AbstractCommand "1" *-- "*" ArgumentDef : arguments ArgumentDef --> ArgumentType CommandResult +-- ResultType CommandException --|> RuntimeException BaseCommand ..> CommandContext : creates AbstractCommand ..> CommandContext : creates SubCommand ..> CommandResult : returns } @enduml