CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-google-api--api-common

Common utilities for Google APIs in Java

Pending
Overview
Eval results
Files

path-template.mddocs/

Path Templates

Path template functionality provides URL pattern matching, variable extraction, and path generation capabilities essential for Google API resource name handling. This system enables type-safe manipulation of REST API resource paths with variable substitution.

Capabilities

PathTemplate Class

Core class for representing and processing path templates. Supports variable extraction from paths, path generation from variables, and template validation.

/**
 * Represents a path template which can be used to parse and serialize resource names
 */
class PathTemplate {
    /**
     * Creates a template from the given pattern
     * @param template The template pattern string (e.g., "projects/{project}/topics/{topic}")
     * @return A PathTemplate instance
     * @throws ValidationException If the template is invalid
     */
    static PathTemplate create(String template);
    
    /**
     * Creates a template from the given pattern without URL encoding
     * @param template The template pattern string
     * @return A PathTemplate instance
     * @throws ValidationException If the template is invalid
     */
    static PathTemplate createWithoutUrlEncoding(String template);
    
    /**
     * Matches the given resource path against this template
     * @param path The resource path to match
     * @return True if the path matches this template
     */
    boolean matches(String path);
    
    /**
     * Matches the given resource path and extracts the variable values
     * @param path The resource path to match
     * @return A map from variable names to their values
     * @throws ValidationException If the path does not match this template
     */
    Map<String, String> match(String path);
    
    /**
     * Matches a full resource name (including endpoint) and extracts variables
     * @param path The full resource path to match
     * @return A map from variable names to their values, including $hostname if present
     * @throws ValidationException If the path does not match this template
     */
    Map<String, String> matchFromFullName(String path);
    
    /**
     * Matches the path and returns the variable map, with validation and custom error messaging
     * @param path The resource path to match
     * @param exceptionMessagePrefix The prefix for the exception message if validation fails
     * @return A map from variable names to their values
     * @throws ValidationException If the path does not match this template
     */
    Map<String, String> validatedMatch(String path, String exceptionMessagePrefix);
    
    /**
     * Validates that the given path matches this template
     * @param path The resource path to validate
     * @param exceptionMessagePrefix The prefix for the exception message if validation fails
     * @throws ValidationException If the path does not match this template
     */
    void validate(String path, String exceptionMessagePrefix);
    
    /**
     * Instantiates the template using the provided variable values
     * @param values A map from variable names to their values
     * @return The instantiated path
     * @throws ValidationException If required variables are missing
     */
    String instantiate(Map<String, String> values);
    
    /**
     * Instantiates the template using the provided key-value pairs
     * @param keysAndValues Alternating keys and values (key1, value1, key2, value2, ...)
     * @return The instantiated path
     * @throws ValidationException If required variables are missing or wrong number of arguments
     */
    String instantiate(String... keysAndValues);
    
    /**
     * Instantiates the template allowing unbound variables to remain as wildcards
     * @param values A map from variable names to their values
     * @return The partially instantiated path with wildcards for unbound variables
     */
    String instantiatePartial(Map<String, String> values);
    
    /**
     * Returns the set of variable names used in this template
     * @return A set of variable names
     */
    Set<String> vars();
    
    /**
     * Returns the parent template (template with the last segment removed)
     * @return The parent template, or null if this template has no parent
     */
    PathTemplate parentTemplate();
    
    /**
     * Returns a template where all variables are replaced with wildcards
     * @return A template with wildcards instead of variables
     */
    PathTemplate withoutVars();
    
    /**
     * Returns a sub-template for the specified variable
     * @param varName The variable name
     * @return The sub-template, or null if the variable doesn't exist
     */
    PathTemplate subTemplate(String varName);
    
    /**
     * Returns the single variable name if this template has exactly one variable
     * @return The variable name, or null if the template doesn't have exactly one variable
     */
    String singleVar();
    
    /**
     * Returns true if this template ends with a literal string (not a variable)
     * @return True if the template ends with a literal
     */
    boolean endsWithLiteral();
    
    /**
     * Returns true if this template ends with a custom verb
     * @return True if the template ends with a custom verb
     */
    boolean endsWithCustomVerb();
    
    /**
     * Creates a TemplatedResourceName from the given path using this template
     * @param path The resource path
     * @return A TemplatedResourceName instance
     * @throws ValidationException If the path does not match this template
     */
    TemplatedResourceName parse(String path);
    
    /**
     * Encodes the given values as a path using positional matching
     * @param values The values to encode
     * @return The encoded path
     */
    String encode(String... values);
    
    /**
     * Decodes a path into positional values
     * @param path The path to decode
     * @return A list of decoded values
     */
    List<String> decode(String path);
}

Constants:

/**
 * Special variable name for hostname bindings in full resource names
 */
String HOSTNAME_VAR = "$hostname";

Usage Examples:

import com.google.api.pathtemplate.PathTemplate;
import java.util.Map;

// Create a path template
PathTemplate template = PathTemplate.create("projects/{project}/topics/{topic}");

// Extract variables from a path
Map<String, String> vars = template.match("projects/my-project/topics/my-topic");
// vars contains: {"project": "my-project", "topic": "my-topic"}

// Generate a path from variables
String path = template.instantiate("project", "my-project", "topic", "my-topic");
// path is: "projects/my-project/topics/my-topic"

// Check if a path matches
boolean matches = template.matches("projects/test/topics/news");
// matches is true

// Get all variable names in the template
Set<String> variableNames = template.vars();
// variableNames contains: ["project", "topic"]

// Work with nested resources - get parent template
PathTemplate parent = template.parentTemplate();
// parent template is: "projects/{project}"

// Handle full resource names with endpoints
PathTemplate fullTemplate = PathTemplate.create("projects/{project}/topics/{topic}");
Map<String, String> fullVars = fullTemplate.matchFromFullName(
    "//pubsub.googleapis.com/projects/my-project/topics/my-topic"
);
// fullVars contains: {"$hostname": "pubsub.googleapis.com", "project": "my-project", "topic": "my-topic"}

TemplatedResourceName Class

A resource name implementation that combines a path template with variable values, implementing the Map<String, String> interface for easy access to variable values.

/**
 * A resource name that is based on a path template
 */
class TemplatedResourceName implements Map<String, String> {
    /**
     * Creates a TemplatedResourceName from a template and resource path
     * @param template The path template
     * @param path The resource path that matches the template
     * @return A TemplatedResourceName instance
     * @throws ValidationException If the path does not match the template
     */
    static TemplatedResourceName create(PathTemplate template, String path);
    
    /**
     * Creates a TemplatedResourceName from a template and variable values
     * @param template The path template
     * @param values A map of variable names to values
     * @return A TemplatedResourceName instance
     * @throws ValidationException If required variables are missing
     */
    static TemplatedResourceName create(PathTemplate template, Map<String, String> values);
    
    /**
     * Creates a TemplatedResourceName from a template and full resource name (including endpoint)
     * @param template The path template
     * @param path The full resource path including endpoint
     * @return A TemplatedResourceName instance
     * @throws ValidationException If the path does not match the template
     */
    static TemplatedResourceName createFromFullName(PathTemplate template, String path);
    
    /**
     * Returns the path template used to create this resource name
     * @return The path template
     */
    PathTemplate template();
    
    /**
     * Returns true if this resource name has an endpoint
     * @return True if an endpoint is present
     */
    boolean hasEndpoint();
    
    /**
     * Returns the endpoint of this resource name, or null if none
     * @return The endpoint string, or null
     */
    String endpoint();
    
    /**
     * Creates a copy of this resource name with the specified endpoint
     * @param endpoint The endpoint to set
     * @return A new TemplatedResourceName with the specified endpoint
     */
    TemplatedResourceName withEndpoint(String endpoint);
    
    /**
     * Returns the parent resource name by using the parent template
     * @return The parent resource name, or null if this resource has no parent
     */
    TemplatedResourceName parentName();
    
    /**
     * Returns true if this resource name starts with the given parent name
     * @param parentName The potential parent resource name
     * @return True if this resource is a child of the given parent
     */
    boolean startsWith(TemplatedResourceName parentName);
    
    /**
     * Resolves this resource name to a resource object via API call
     * @param resourceType The type of resource to resolve to
     * @param version The API version to use
     * @return The resolved resource
     * @throws Exception If the resolution fails
     */
    <T> T resolve(Class<T> resourceType, String version) throws Exception;
}

Resource Name Resolver:

/**
 * Interface for pluggable resource name resolution
 */
interface Resolver {
    /**
     * Resolves a resource name to a resource object
     * @param resourceName The resource name to resolve
     * @param resourceType The type of resource to resolve to
     * @param version The API version to use
     * @return The resolved resource
     * @throws Exception If the resolution fails
     */
    <T> T resolve(TemplatedResourceName resourceName, Class<T> resourceType, String version) throws Exception;
}

/**
 * Registers a global resource name resolver
 * @param resolver The resolver to register
 */
static void registerResourceNameResolver(Resolver resolver);

Usage Examples:

import com.google.api.pathtemplate.PathTemplate;
import com.google.api.pathtemplate.TemplatedResourceName;
import java.util.HashMap;
import java.util.Map;

// Create from path and template
PathTemplate template = PathTemplate.create("projects/{project}/topics/{topic}");
TemplatedResourceName resourceName = TemplatedResourceName.create(
    template, 
    "projects/my-project/topics/my-topic"
);

// Access variable values (implements Map<String, String>)
String project = resourceName.get("project"); // "my-project"
String topic = resourceName.get("topic");     // "my-topic"

// Create from template and values
Map<String, String> values = new HashMap<>();
values.put("project", "another-project");
values.put("topic", "another-topic");
TemplatedResourceName fromValues = TemplatedResourceName.create(template, values);

// Work with parent resources
TemplatedResourceName parent = resourceName.parentName();
// parent represents "projects/my-project"

boolean isChild = resourceName.startsWith(parent); // true

// Work with endpoints
TemplatedResourceName withEndpoint = resourceName.withEndpoint("pubsub.googleapis.com");
boolean hasEndpoint = withEndpoint.hasEndpoint(); // true
String endpoint = withEndpoint.endpoint(); // "pubsub.googleapis.com"

// Create from full name with endpoint
TemplatedResourceName fromFullName = TemplatedResourceName.createFromFullName(
    template,
    "//pubsub.googleapis.com/projects/my-project/topics/my-topic"
);

ValidationException

Exception thrown when path template operations fail validation, with support for contextual error messages.

/**
 * Exception thrown when path template validation fails
 */
class ValidationException extends IllegalArgumentException {
    /**
     * Creates a ValidationException with the given message
     * @param message The error message
     */
    public ValidationException(String message);
    
    /**
     * Creates a ValidationException with the given message and cause
     * @param message The error message
     * @param cause The underlying cause
     */
    public ValidationException(String message, Throwable cause);
    
    /**
     * Sets a validation context for the current thread
     * @param context The validation context description
     */
    static void pushCurrentThreadValidationContext(String context);
    
    /**
     * Clears the validation context for the current thread
     */
    static void popCurrentThreadValidationContext();
}

Usage Examples:

import com.google.api.pathtemplate.PathTemplate;
import com.google.api.pathtemplate.ValidationException;

PathTemplate template = PathTemplate.create("projects/{project}/topics/{topic}");

try {
    // This will throw ValidationException because the path doesn't match
    template.match("projects/my-project/buckets/my-bucket");
} catch (ValidationException e) {
    System.err.println("Path validation failed: " + e.getMessage());
}

// Use validation context for better error messages
ValidationException.pushCurrentThreadValidationContext("Processing user input");
try {
    template.validate("invalid/path", "User provided path");
} catch (ValidationException e) {
    // Exception message will include context information
    System.err.println("Validation error: " + e.getMessage());
} finally {
    ValidationException.popCurrentThreadValidationContext();
}

Common Patterns

Resource Hierarchy Navigation

// Navigate up and down resource hierarchies
PathTemplate projectTemplate = PathTemplate.create("projects/{project}");
PathTemplate topicTemplate = PathTemplate.create("projects/{project}/topics/{topic}");
PathTemplate subscriptionTemplate = PathTemplate.create("projects/{project}/subscriptions/{subscription}");

// Create resource names
TemplatedResourceName project = TemplatedResourceName.create(projectTemplate, "projects/my-project");
TemplatedResourceName topic = TemplatedResourceName.create(topicTemplate, "projects/my-project/topics/news");

// Check relationships
boolean isChild = topic.startsWith(project); // true

// Get parent
TemplatedResourceName topicParent = topic.parentName();
// topicParent represents "projects/my-project"

Template Composition

// Create templates for different resource types in the same project
PathTemplate baseTemplate = PathTemplate.create("projects/{project}");
Set<String> baseVars = baseTemplate.vars(); // ["project"]

// Extend templates while maintaining the base structure
PathTemplate topicTemplate = PathTemplate.create("projects/{project}/topics/{topic}");
PathTemplate subscriptionTemplate = PathTemplate.create("projects/{project}/subscriptions/{subscription}");

// Extract common variables
Map<String, String> topicVars = topicTemplate.match("projects/my-project/topics/news");
String commonProject = topicVars.get("project"); // "my-project"

Map<String, String> subVars = subscriptionTemplate.match("projects/my-project/subscriptions/alerts");  
String sameProject = subVars.get("project"); // "my-project" (same as above)

Partial Path Generation

PathTemplate template = PathTemplate.create("projects/{project}/topics/{topic}/subscriptions/{subscription}");

// Generate partial paths when not all variables are known
Map<String, String> partialValues = new HashMap<>();
partialValues.put("project", "my-project");
partialValues.put("topic", "news");
// subscription is missing

String partial = template.instantiatePartial(partialValues);
// partial is: "projects/my-project/topics/news/subscriptions/*"

Install with Tessl CLI

npx tessl i tessl/maven-com-google-api--api-common

docs

core-api.md

index.md

path-template.md

resource-names.md

tile.json