universal.go
Overview
The universal.go file implements the universal package, which provides an abstraction layer over multiple launchers (specifically sublaunchers such as console and web launchers). This package allows the selection of one launcher based on command-line parameters and then delegates argument parsing and execution responsibilities to the chosen launcher. It acts as a router that dispatches command-line arguments to the appropriate sublauncher.
Types and Functions
uniLauncher (struct)
The core struct in this package, uniLauncher, maintains:
chosenLauncher launcher.SubLauncher
The sublauncher selected after parsing the command-line arguments.sublaunchers []launcher.SubLauncher
A slice of available sublaunchers registered in the universal launcher.
NewLauncher
func NewLauncher(sublaunchers ...launcher.SubLauncher) launcher.Launcher
Purpose:
Constructs a new universal launcher instance with the specified sublaunchers. The first sublauncher in the list is used as the default if no command-line argument selects a specific launcher.Parameters:
Variadic list of sublaunchers implementing thelauncher.SubLauncherinterface.Returns:
An instance oflauncher.Launcherthat routes commands to one of the provided sublaunchers.Usage:
uni := universal.NewLauncher(consoleLauncher, webLauncher)
(l *uniLauncher) Execute
func (l *uniLauncher) Execute(ctx context.Context, config *launcher.Config, args []string) error
Purpose:
Implements thelauncher.Launcherinterface. Parses command-line arguments, selects a sublauncher, and executes it. Returns an error if there are unparsed arguments left.Parameters:
ctx context.Context: Execution context for cancellation and deadlines.config *launcher.Config: Configuration passed to the launcher.args []string: Command-line arguments.
Returns:
Anerrorif argument parsing or execution fails.Behavior:
Delegates toParseAndRunwith the helperErrorOnUnparsedArgsto enforce no leftover arguments.
(l *uniLauncher) ParseAndRun
func (l *uniLauncher) ParseAndRun(ctx context.Context, config *launcher.Config, args []string, parseRemaining func([]string) error) error
Purpose:
Parses the arguments to select and configure the sublauncher, then runs that sublauncher. Allows a custom hook function to process any remaining unparsed arguments.Parameters:
ctx context.Context: Execution context.config *launcher.Config: Launcher configuration.args []string: Command-line arguments.parseRemaining func([]string) error: Optional callback for handling any leftover arguments after parsing.
Returns:
Anerrorif parsing or execution fails, or if theparseRemaininghook returns an error.Implementation Details:
Calls internal
parsemethod to assign the chosen launcher and parse arguments.If a
parseRemainingfunction is provided, it is called with leftover arguments.Calls internal
runmethod to execute the chosen sublauncher.
(l *uniLauncher) parse
func (l *uniLauncher) parse(args []string) ([]string, error)
Purpose:
Determines the appropriate sublauncher based on the first argument keyword and parses the remaining arguments using the selected sublauncher.Parameters:
args []string: Command-line arguments.
Returns:
[]string: Any remaining arguments not parsed by the sublauncher.error: If keyword conflicts exist or no sublaunchers are configured.
Implementation Details:
Builds a map of keywords to sublaunchers to ensure uniqueness.
Defaults to the first sublauncher if no arguments or unrecognized keyword.
If the first argument matches a keyword, it uses the corresponding sublauncher and parses the rest of the arguments.
Otherwise, the default sublauncher parses all arguments.
Error Cases:
Duplicate keywords among sublaunchers.
No sublaunchers registered.
(l *uniLauncher) run
func (l *uniLauncher) run(ctx context.Context, config *launcher.Config) error
Purpose:
Executes the previously chosen sublauncher by calling itsRunmethod.Parameters:
ctx context.Context: Execution context.config *launcher.Config: Configuration for the launcher.
Returns:
Anerrorfrom the sublauncher'sRunmethod if execution fails.
(l *uniLauncher) CommandLineSyntax
func (l *uniLauncher) CommandLineSyntax() string
Purpose:
Returns a formatted string describing the command-line syntax for the universal launcher and its sublaunchers.Returns:
A multi-line string describing the launcher usage, including each sublauncher's keyword, short description, and detailed syntax.Implementation Details:
Prints a list of keywords with their simple descriptions.
Follows with detailed syntax for each sublauncher.
(l *uniLauncher) simpleDescription
func (l *uniLauncher) simpleDescription() string
Purpose:
Provides a brief textual description of the universal launcher’s behavior.Returns:
A string explaining the universal launcher’s routing logic.
ErrorOnUnparsedArgs
func ErrorOnUnparsedArgs(args []string) error
Purpose:
Utility function that returns an error if the provided argument slice is not empty, signaling leftover unparsed arguments.Parameters:
args []string: Arguments left after parsing.
Returns:
errorindicating which arguments could not be parsed, ornilif none remain.
Usage:
Used as a hook inParseAndRunto enforce complete argument parsing.
Implementation Details and Algorithms
Keyword-based Dispatcher:
The universal launcher maintains a mapping from unique keywords to sublaunchers. The first command-line argument is inspected as a keyword to select the sublauncher.
If this keyword matches a sublauncher, the rest of the arguments are parsed by that sublauncher.
Otherwise, the default sublauncher (first in the slice) handles the whole argument list.Argument Parsing and Execution Flow:
TheExecutemethod triggers parsing and execution. Parsing detects the sublauncher and delegates argument parsing to it. If there are leftover arguments,ErrorOnUnparsedArgsreports them as errors. Execution is performed by calling the chosen sublauncher'sRunmethod.Error Handling:
The code ensures that sublauncher keywords are unique and that at least one sublauncher is registered. It properly propagates errors from parsing and execution.
Interaction with Other System Components
launcher.SubLauncher Interface:
The universal launcher depends on thelauncher.SubLauncherinterface, which must provide methods likeKeyword(),Parse([]string) ([]string, error),Run(context.Context, *launcher.Config) error,SimpleDescription() string, andCommandLineSyntax() string. This interface is part of thelauncherpackage imported from"google.golang.org/adk/cmd/launcher".launcher.Launcher Interface:
The universal launcher implements thelauncher.Launcherinterface, allowing it to be used interchangeably with other launchers in the system.Launcher Config:
Thelauncher.Configstructure is passed to sublaunchers during execution, providing configuration and context as part of the launcher framework.Command-line Interface:
The package is designed for command-line applications where different modes or subcommands are handled by different sublaunchers. It centralizes argument parsing and routing.
Usage Example
// Create sublaunchers (consoleLauncher, webLauncher are assumed to implement launcher.SubLauncher)
uni := universal.NewLauncher(consoleLauncher, webLauncher)
// Execute with arguments, context and config
err := uni.Execute(context.Background(), config, os.Args[1:])
if err != nil {
fmt.Printf("Error: %v\n", err)
}
Class Diagram
classDiagram
class uniLauncher {
-chosenLauncher: SubLauncher
-sublaunchers: []SubLauncher
+Execute(ctx, config, args) error
+ParseAndRun(ctx, config, args, parseRemaining) error
+parse(args) ([]string, error)
+run(ctx, config) error
+CommandLineSyntax() string
-simpleDescription() string
}
uniLauncher ..> launcher.SubLauncher : uses
uniLauncher ..> launcher.Launcher : implements