or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-api.mdindex.mdpath-template.mdresource-names.md

resource-names.mddocs/

0

# Resource Names

1

2

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.

3

4

## Capabilities

5

6

### ResourceName Interface

7

8

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.

9

10

```java { .api }

11

/**

12

* Interface that all resource name types must implement

13

*/

14

interface ResourceName {

15

/**

16

* Returns a map of field names to their values for this resource name

17

* @return An unmodifiable map from field names to field values

18

*/

19

Map<String, String> getFieldValuesMap();

20

21

/**

22

* Returns the value of the specified field name

23

* @param fieldName The name of the field to retrieve

24

* @return The field value, or null if the field doesn't exist

25

*/

26

String getFieldValue(String fieldName);

27

}

28

```

29

30

**Usage Examples:**

31

32

```java

33

import com.google.api.resourcenames.ResourceName;

34

35

// Assume you have a generated resource name class like ProjectName

36

// This is just an example - actual generated classes would implement this interface

37

class ProjectName implements ResourceName {

38

private final String project;

39

40

public ProjectName(String project) {

41

this.project = project;

42

}

43

44

@Override

45

public Map<String, String> getFieldValuesMap() {

46

return Collections.singletonMap("project", project);

47

}

48

49

@Override

50

public String getFieldValue(String fieldName) {

51

return "project".equals(fieldName) ? project : null;

52

}

53

54

@Override

55

public String toString() {

56

return "projects/" + project;

57

}

58

}

59

60

// Using the ResourceName interface polymorphically

61

ResourceName resourceName = new ProjectName("my-project");

62

Map<String, String> fields = resourceName.getFieldValuesMap();

63

// fields contains: {"project": "my-project"}

64

65

String projectValue = resourceName.getFieldValue("project");

66

// projectValue is: "my-project"

67

68

String nonExistentField = resourceName.getFieldValue("topic");

69

// nonExistentField is: null

70

```

71

72

### UntypedResourceName Class

73

74

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.

75

76

```java { .api }

77

/**

78

* A resource name implementation for unknown formats

79

*/

80

class UntypedResourceName implements ResourceName {

81

/**

82

* Creates an UntypedResourceName from an existing ResourceName

83

* @param resourceName The existing resource name to wrap

84

* @return An UntypedResourceName instance

85

*/

86

static UntypedResourceName of(ResourceName resourceName);

87

88

/**

89

* Parses a formatted string into an UntypedResourceName

90

* @param formattedString The resource name string to parse

91

* @return An UntypedResourceName instance

92

* @throws NullPointerException If formattedString is null

93

*/

94

static UntypedResourceName parse(String formattedString);

95

96

/**

97

* Checks if the given string can be parsed as an UntypedResourceName

98

* @param formattedString The string to check

99

* @return True if the string is non-null (UntypedResourceName accepts any non-null string)

100

*/

101

static boolean isParsableFrom(String formattedString);

102

103

@Override

104

public Map<String, String> getFieldValuesMap() {

105

// Returns map with empty string key mapping to the raw resource name

106

return ImmutableMap.of("", rawResourceName);

107

}

108

109

@Override

110

public String getFieldValue(String fieldName) {

111

// Returns the raw resource name if fieldName is empty string, null otherwise

112

return "".equals(fieldName) ? rawResourceName : null;

113

}

114

115

/**

116

* Returns the original formatted string

117

* @return The original resource name string

118

*/

119

@Override

120

public String toString();

121

}

122

```

123

124

**Usage Examples:**

125

126

```java

127

import com.google.api.resourcenames.UntypedResourceName;

128

import com.google.api.resourcenames.ResourceName;

129

130

// Create from string - accepts any non-null string

131

UntypedResourceName untyped = UntypedResourceName.parse("projects/my-project/topics/my-topic");

132

String value = untyped.toString();

133

// value is: "projects/my-project/topics/my-topic"

134

135

// Check if a string can be parsed (always true for non-null strings)

136

boolean canParse = UntypedResourceName.isParsableFrom("any-string-at-all");

137

// canParse is: true

138

139

boolean cannotParse = UntypedResourceName.isParsableFrom(null);

140

// cannotParse is: false

141

142

// Create from existing ResourceName

143

ResourceName existingResource = /* some existing resource name */;

144

UntypedResourceName wrapped = UntypedResourceName.of(existingResource);

145

146

// Field access - returns the raw value for empty string key, null for other keys

147

String fieldValue = untyped.getFieldValue("project");

148

// fieldValue is: null (field name doesn't match empty string)

149

150

String rawValue = untyped.getFieldValue("");

151

// rawValue is: "projects/my-project/topics/my-topic" (raw resource name string)

152

153

Map<String, String> fields = untyped.getFieldValuesMap();

154

// fields is: {"": "projects/my-project/topics/my-topic"} (empty string key maps to raw value)

155

156

// Useful as a fallback when parsing fails for typed resource names

157

String resourceString = "unknown/format/resource/name";

158

try {

159

// Try to parse as specific resource type first

160

ProjectName typed = ProjectName.parse(resourceString);

161

} catch (Exception e) {

162

// Fall back to untyped if specific parsing fails

163

UntypedResourceName fallback = UntypedResourceName.parse(resourceString);

164

// Always succeeds for non-null strings

165

}

166

```

167

168

### ResourceNameFactory Interface

169

170

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

171

172

```java { .api }

173

/**

174

* Factory interface for creating ResourceName instances

175

* @param <T> The type of ResourceName this factory creates

176

*/

177

interface ResourceNameFactory<T extends ResourceName> {

178

/**

179

* Parses a formatted string into a ResourceName of type T

180

* @param formattedString The resource name string to parse

181

* @return A parsed ResourceName instance

182

* @throws IllegalArgumentException If the string cannot be parsed

183

*/

184

T parse(String formattedString);

185

}

186

```

187

188

**Usage Examples:**

189

190

```java

191

import com.google.api.resourcenames.ResourceNameFactory;

192

import com.google.api.resourcenames.ResourceName;

193

194

// Example implementation for a hypothetical ProjectName class

195

class ProjectNameFactory implements ResourceNameFactory<ProjectName> {

196

@Override

197

public ProjectName parse(String formattedString) {

198

if (!formattedString.startsWith("projects/")) {

199

throw new IllegalArgumentException("Invalid project name format: " + formattedString);

200

}

201

String projectId = formattedString.substring("projects/".length());

202

return new ProjectName(projectId);

203

}

204

}

205

206

// Using the factory

207

ResourceNameFactory<ProjectName> factory = new ProjectNameFactory();

208

ProjectName project = factory.parse("projects/my-project");

209

210

// Factories enable polymorphic resource name creation

211

ResourceNameFactory<? extends ResourceName> genericFactory = getFactoryForType("project");

212

ResourceName resource = genericFactory.parse("projects/my-project");

213

```

214

215

## Common Patterns

216

217

### Polymorphic Resource Name Handling

218

219

```java

220

import com.google.api.resourcenames.ResourceName;

221

import com.google.api.resourcenames.UntypedResourceName;

222

223

// Handle different resource name types uniformly

224

public void processResource(ResourceName resourceName) {

225

// Access fields polymorphically

226

Map<String, String> fields = resourceName.getFieldValuesMap();

227

228

// Log all field values

229

for (Map.Entry<String, String> entry : fields.entrySet()) {

230

System.out.println(entry.getKey() + ": " + entry.getValue());

231

}

232

233

// Check for specific fields

234

String project = resourceName.getFieldValue("project");

235

if (project != null) {

236

System.out.println("Project: " + project);

237

}

238

239

// Get the string representation

240

String resourceString = resourceName.toString();

241

System.out.println("Resource: " + resourceString);

242

}

243

244

// Can be called with any ResourceName implementation

245

processResource(new ProjectName("my-project"));

246

processResource(UntypedResourceName.parse("custom/resource/format"));

247

```

248

249

### Fallback Parsing Strategy

250

251

```java

252

import com.google.api.resourcenames.UntypedResourceName;

253

254

// Robust resource name parsing with fallback

255

public ResourceName parseResourceName(String resourceString, String expectedType) {

256

try {

257

// Try to parse as specific known types first

258

switch (expectedType) {

259

case "project":

260

return ProjectName.parse(resourceString);

261

case "topic":

262

return TopicName.parse(resourceString);

263

case "subscription":

264

return SubscriptionName.parse(resourceString);

265

default:

266

// Unknown type - use untyped

267

return UntypedResourceName.parse(resourceString);

268

}

269

} catch (Exception e) {

270

// If parsing fails, fall back to untyped

271

System.err.println("Failed to parse as " + expectedType + ", using untyped: " + e.getMessage());

272

return UntypedResourceName.parse(resourceString);

273

}

274

}

275

276

// Usage

277

ResourceName resource1 = parseResourceName("projects/my-project", "project");

278

// Returns a strongly-typed ProjectName

279

280

ResourceName resource2 = parseResourceName("unknown/format", "project");

281

// Returns an UntypedResourceName (parsing failed)

282

283

ResourceName resource3 = parseResourceName("custom/resource/path", "unknown");

284

// Returns an UntypedResourceName (unknown type)

285

```

286

287

### Factory-Based Resource Creation

288

289

```java

290

import com.google.api.resourcenames.ResourceNameFactory;

291

import java.util.HashMap;

292

import java.util.Map;

293

294

// Registry of factories for different resource types

295

public class ResourceNameRegistry {

296

private final Map<String, ResourceNameFactory<? extends ResourceName>> factories = new HashMap<>();

297

298

public void registerFactory(String type, ResourceNameFactory<? extends ResourceName> factory) {

299

factories.put(type, factory);

300

}

301

302

public ResourceName parse(String type, String resourceString) {

303

ResourceNameFactory<? extends ResourceName> factory = factories.get(type);

304

if (factory != null) {

305

try {

306

return factory.parse(resourceString);

307

} catch (Exception e) {

308

// Fall back to untyped on parsing failure

309

return UntypedResourceName.parse(resourceString);

310

}

311

} else {

312

// Unknown type - use untyped

313

return UntypedResourceName.parse(resourceString);

314

}

315

}

316

}

317

318

// Setup and usage

319

ResourceNameRegistry registry = new ResourceNameRegistry();

320

registry.registerFactory("project", new ProjectNameFactory());

321

registry.registerFactory("topic", new TopicNameFactory());

322

323

// Parse different resource types

324

ResourceName project = registry.parse("project", "projects/my-project");

325

ResourceName topic = registry.parse("topic", "projects/my-project/topics/my-topic");

326

ResourceName unknown = registry.parse("unknown", "some/custom/format");

327

```

328

329

### Resource Name Validation

330

331

```java

332

import com.google.api.resourcenames.ResourceName;

333

import com.google.api.resourcenames.UntypedResourceName;

334

335

// Validate and extract information from resource names

336

public class ResourceNameValidator {

337

338

public boolean isValidProject(ResourceName resourceName) {

339

String project = resourceName.getFieldValue("project");

340

return project != null && !project.isEmpty() && project.matches("[a-z][a-z0-9-]*");

341

}

342

343

public boolean isTypedResourceName(ResourceName resourceName) {

344

// UntypedResourceName returns empty field map

345

return !resourceName.getFieldValuesMap().isEmpty();

346

}

347

348

public String extractProjectId(ResourceName resourceName) {

349

String project = resourceName.getFieldValue("project");

350

if (project == null) {

351

// Try to extract from string representation

352

String resourceString = resourceName.toString();

353

if (resourceString.startsWith("projects/")) {

354

String[] parts = resourceString.split("/");

355

if (parts.length >= 2) {

356

return parts[1];

357

}

358

}

359

}

360

return project;

361

}

362

}

363

364

// Usage

365

ResourceNameValidator validator = new ResourceNameValidator();

366

367

ResourceName typedResource = new ProjectName("my-project");

368

boolean isValid = validator.isValidProject(typedResource); // true

369

boolean isTyped = validator.isTypedResourceName(typedResource); // true

370

371

ResourceName untypedResource = UntypedResourceName.parse("projects/my-project");

372

boolean isValidUntyped = validator.isValidProject(untypedResource); // false (no field extraction)

373

boolean isTypedUntyped = validator.isTypedResourceName(untypedResource); // false

374

String projectId = validator.extractProjectId(untypedResource); // "my-project" (extracted from string)

375

```

376

377

## Integration with Path Templates

378

379

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

380

381

```java

382

import com.google.api.pathtemplate.PathTemplate;

383

import com.google.api.pathtemplate.TemplatedResourceName;

384

import com.google.api.resourcenames.ResourceName;

385

386

// TemplatedResourceName implements ResourceName interface

387

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

388

TemplatedResourceName templatedName = TemplatedResourceName.create(

389

template,

390

"projects/my-project/topics/my-topic"

391

);

392

393

// Use as ResourceName

394

ResourceName resourceName = templatedName;

395

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

396

String topic = resourceName.getFieldValue("topic"); // "my-topic"

397

398

Map<String, String> fields = resourceName.getFieldValuesMap();

399

// fields contains: {"project": "my-project", "topic": "my-topic"}

400

401

// Convert to string

402

String resourceString = resourceName.toString();

403

// resourceString is: "projects/my-project/topics/my-topic"

404

```