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

resource-names.mddocs/

Resource Names

Resource name functionality provides type-safe handling of Google API resource identifiers. This system enables consistent resource name parsing, validation, and field access across different resource types and formats.

Capabilities

ResourceName Interface

Core interface that all generated resource name types must implement. Provides standardized access to resource name field values and enables polymorphic handling of different resource name types.

/**
 * Interface that all resource name types must implement
 */
interface ResourceName {
    /**
     * Returns a map of field names to their values for this resource name
     * @return An unmodifiable map from field names to field values
     */
    Map<String, String> getFieldValuesMap();
    
    /**
     * Returns the value of the specified field name
     * @param fieldName The name of the field to retrieve
     * @return The field value, or null if the field doesn't exist
     */
    String getFieldValue(String fieldName);
}

Usage Examples:

import com.google.api.resourcenames.ResourceName;

// Assume you have a generated resource name class like ProjectName
// This is just an example - actual generated classes would implement this interface
class ProjectName implements ResourceName {
    private final String project;
    
    public ProjectName(String project) {
        this.project = project;
    }
    
    @Override
    public Map<String, String> getFieldValuesMap() {
        return Collections.singletonMap("project", project);
    }
    
    @Override  
    public String getFieldValue(String fieldName) {
        return "project".equals(fieldName) ? project : null;
    }
    
    @Override
    public String toString() {
        return "projects/" + project;
    }
}

// Using the ResourceName interface polymorphically
ResourceName resourceName = new ProjectName("my-project");
Map<String, String> fields = resourceName.getFieldValuesMap();
// fields contains: {"project": "my-project"}

String projectValue = resourceName.getFieldValue("project");
// projectValue is: "my-project"

String nonExistentField = resourceName.getFieldValue("topic");
// nonExistentField is: null

UntypedResourceName Class

A fallback resource name implementation for handling resource names with unknown or unexpected formats. Always accepts any non-null string as a valid resource name.

/**
 * A resource name implementation for unknown formats
 */
class UntypedResourceName implements ResourceName {
    /**
     * Creates an UntypedResourceName from an existing ResourceName
     * @param resourceName The existing resource name to wrap
     * @return An UntypedResourceName instance
     */
    static UntypedResourceName of(ResourceName resourceName);
    
    /**
     * Parses a formatted string into an UntypedResourceName
     * @param formattedString The resource name string to parse
     * @return An UntypedResourceName instance
     * @throws NullPointerException If formattedString is null
     */
    static UntypedResourceName parse(String formattedString);
    
    /**
     * Checks if the given string can be parsed as an UntypedResourceName
     * @param formattedString The string to check
     * @return True if the string is non-null (UntypedResourceName accepts any non-null string)
     */
    static boolean isParsableFrom(String formattedString);
    
    @Override
    public Map<String, String> getFieldValuesMap() {
        // Returns map with empty string key mapping to the raw resource name
        return ImmutableMap.of("", rawResourceName);
    }
    
    @Override
    public String getFieldValue(String fieldName) {
        // Returns the raw resource name if fieldName is empty string, null otherwise
        return "".equals(fieldName) ? rawResourceName : null;
    }
    
    /**
     * Returns the original formatted string
     * @return The original resource name string
     */
    @Override
    public String toString();
}

Usage Examples:

import com.google.api.resourcenames.UntypedResourceName;
import com.google.api.resourcenames.ResourceName;

// Create from string - accepts any non-null string
UntypedResourceName untyped = UntypedResourceName.parse("projects/my-project/topics/my-topic");
String value = untyped.toString(); 
// value is: "projects/my-project/topics/my-topic"

// Check if a string can be parsed (always true for non-null strings)
boolean canParse = UntypedResourceName.isParsableFrom("any-string-at-all");
// canParse is: true

boolean cannotParse = UntypedResourceName.isParsableFrom(null);
// cannotParse is: false

// Create from existing ResourceName
ResourceName existingResource = /* some existing resource name */;
UntypedResourceName wrapped = UntypedResourceName.of(existingResource);

// Field access - returns the raw value for empty string key, null for other keys
String fieldValue = untyped.getFieldValue("project");
// fieldValue is: null (field name doesn't match empty string)

String rawValue = untyped.getFieldValue("");
// rawValue is: "projects/my-project/topics/my-topic" (raw resource name string)

Map<String, String> fields = untyped.getFieldValuesMap();
// fields is: {"": "projects/my-project/topics/my-topic"} (empty string key maps to raw value)

// Useful as a fallback when parsing fails for typed resource names
String resourceString = "unknown/format/resource/name";
try {
    // Try to parse as specific resource type first
    ProjectName typed = ProjectName.parse(resourceString);
} catch (Exception e) {
    // Fall back to untyped if specific parsing fails
    UntypedResourceName fallback = UntypedResourceName.parse(resourceString);
    // Always succeeds for non-null strings
}

ResourceNameFactory Interface

Factory interface for creating ResourceName instances from formatted strings. Used by generated resource name classes to provide a consistent parsing interface.

/**
 * Factory interface for creating ResourceName instances
 * @param <T> The type of ResourceName this factory creates
 */
interface ResourceNameFactory<T extends ResourceName> {
    /**
     * Parses a formatted string into a ResourceName of type T
     * @param formattedString The resource name string to parse
     * @return A parsed ResourceName instance
     * @throws IllegalArgumentException If the string cannot be parsed
     */
    T parse(String formattedString);
}

Usage Examples:

import com.google.api.resourcenames.ResourceNameFactory;
import com.google.api.resourcenames.ResourceName;

// Example implementation for a hypothetical ProjectName class
class ProjectNameFactory implements ResourceNameFactory<ProjectName> {
    @Override
    public ProjectName parse(String formattedString) {
        if (!formattedString.startsWith("projects/")) {
            throw new IllegalArgumentException("Invalid project name format: " + formattedString);
        }
        String projectId = formattedString.substring("projects/".length());
        return new ProjectName(projectId);
    }
}

// Using the factory
ResourceNameFactory<ProjectName> factory = new ProjectNameFactory();
ProjectName project = factory.parse("projects/my-project");

// Factories enable polymorphic resource name creation
ResourceNameFactory<? extends ResourceName> genericFactory = getFactoryForType("project");
ResourceName resource = genericFactory.parse("projects/my-project");

Common Patterns

Polymorphic Resource Name Handling

import com.google.api.resourcenames.ResourceName;
import com.google.api.resourcenames.UntypedResourceName;

// Handle different resource name types uniformly
public void processResource(ResourceName resourceName) {
    // Access fields polymorphically
    Map<String, String> fields = resourceName.getFieldValuesMap();
    
    // Log all field values
    for (Map.Entry<String, String> entry : fields.entrySet()) {
        System.out.println(entry.getKey() + ": " + entry.getValue());
    }
    
    // Check for specific fields
    String project = resourceName.getFieldValue("project");
    if (project != null) {
        System.out.println("Project: " + project);
    }
    
    // Get the string representation
    String resourceString = resourceName.toString();
    System.out.println("Resource: " + resourceString);
}

// Can be called with any ResourceName implementation
processResource(new ProjectName("my-project"));
processResource(UntypedResourceName.parse("custom/resource/format"));

Fallback Parsing Strategy

import com.google.api.resourcenames.UntypedResourceName;

// Robust resource name parsing with fallback
public ResourceName parseResourceName(String resourceString, String expectedType) {
    try {
        // Try to parse as specific known types first
        switch (expectedType) {
            case "project":
                return ProjectName.parse(resourceString);
            case "topic":
                return TopicName.parse(resourceString);
            case "subscription":
                return SubscriptionName.parse(resourceString);
            default:
                // Unknown type - use untyped
                return UntypedResourceName.parse(resourceString);
        }
    } catch (Exception e) {
        // If parsing fails, fall back to untyped
        System.err.println("Failed to parse as " + expectedType + ", using untyped: " + e.getMessage());
        return UntypedResourceName.parse(resourceString);
    }
}

// Usage
ResourceName resource1 = parseResourceName("projects/my-project", "project");
// Returns a strongly-typed ProjectName

ResourceName resource2 = parseResourceName("unknown/format", "project");  
// Returns an UntypedResourceName (parsing failed)

ResourceName resource3 = parseResourceName("custom/resource/path", "unknown");
// Returns an UntypedResourceName (unknown type)

Factory-Based Resource Creation

import com.google.api.resourcenames.ResourceNameFactory;
import java.util.HashMap;
import java.util.Map;

// Registry of factories for different resource types
public class ResourceNameRegistry {
    private final Map<String, ResourceNameFactory<? extends ResourceName>> factories = new HashMap<>();
    
    public void registerFactory(String type, ResourceNameFactory<? extends ResourceName> factory) {
        factories.put(type, factory);
    }
    
    public ResourceName parse(String type, String resourceString) {
        ResourceNameFactory<? extends ResourceName> factory = factories.get(type);
        if (factory != null) {
            try {
                return factory.parse(resourceString);
            } catch (Exception e) {
                // Fall back to untyped on parsing failure
                return UntypedResourceName.parse(resourceString);
            }
        } else {
            // Unknown type - use untyped
            return UntypedResourceName.parse(resourceString);
        }
    }
}

// Setup and usage
ResourceNameRegistry registry = new ResourceNameRegistry();
registry.registerFactory("project", new ProjectNameFactory());
registry.registerFactory("topic", new TopicNameFactory());

// Parse different resource types
ResourceName project = registry.parse("project", "projects/my-project");
ResourceName topic = registry.parse("topic", "projects/my-project/topics/my-topic");
ResourceName unknown = registry.parse("unknown", "some/custom/format");

Resource Name Validation

import com.google.api.resourcenames.ResourceName;
import com.google.api.resourcenames.UntypedResourceName;

// Validate and extract information from resource names
public class ResourceNameValidator {
    
    public boolean isValidProject(ResourceName resourceName) {
        String project = resourceName.getFieldValue("project");
        return project != null && !project.isEmpty() && project.matches("[a-z][a-z0-9-]*");
    }
    
    public boolean isTypedResourceName(ResourceName resourceName) {
        // UntypedResourceName returns empty field map
        return !resourceName.getFieldValuesMap().isEmpty();
    }
    
    public String extractProjectId(ResourceName resourceName) {
        String project = resourceName.getFieldValue("project");
        if (project == null) {
            // Try to extract from string representation
            String resourceString = resourceName.toString();
            if (resourceString.startsWith("projects/")) {
                String[] parts = resourceString.split("/");
                if (parts.length >= 2) {
                    return parts[1];
                }
            }
        }
        return project;
    }
}

// Usage
ResourceNameValidator validator = new ResourceNameValidator();

ResourceName typedResource = new ProjectName("my-project");
boolean isValid = validator.isValidProject(typedResource); // true
boolean isTyped = validator.isTypedResourceName(typedResource); // true

ResourceName untypedResource = UntypedResourceName.parse("projects/my-project");
boolean isValidUntyped = validator.isValidProject(untypedResource); // false (no field extraction)
boolean isTypedUntyped = validator.isTypedResourceName(untypedResource); // false
String projectId = validator.extractProjectId(untypedResource); // "my-project" (extracted from string)

Integration with Path Templates

Resource names work seamlessly with path templates for comprehensive resource handling:

import com.google.api.pathtemplate.PathTemplate;
import com.google.api.pathtemplate.TemplatedResourceName;
import com.google.api.resourcenames.ResourceName;

// TemplatedResourceName implements ResourceName interface
PathTemplate template = PathTemplate.create("projects/{project}/topics/{topic}");
TemplatedResourceName templatedName = TemplatedResourceName.create(
    template, 
    "projects/my-project/topics/my-topic"
);

// Use as ResourceName
ResourceName resourceName = templatedName;
String project = resourceName.getFieldValue("project"); // "my-project"
String topic = resourceName.getFieldValue("topic");     // "my-topic"

Map<String, String> fields = resourceName.getFieldValuesMap();
// fields contains: {"project": "my-project", "topic": "my-topic"}

// Convert to string
String resourceString = resourceName.toString();
// resourceString is: "projects/my-project/topics/my-topic"

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