or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

async.mdcore.mdindex.mdmetadata.mdprotocols.mdschemes.mdservers.mdtransports.mdutilities.md

metadata.mddocs/

0

# Metadata and Reflection

1

2

Runtime metadata support for Thrift objects, enabling reflection, introspection, and dynamic handling of Thrift structures. The metadata system provides detailed information about Thrift object structure, field types, and requirements.

3

4

## Capabilities

5

6

### Field Metadata

7

8

Core metadata classes for describing Thrift struct fields and their properties.

9

10

```java { .api }

11

/**

12

* Stores metadata information about a Thrift struct field

13

*/

14

public class FieldMetaData {

15

/** Field name */

16

public final String fieldName;

17

18

/** Field requirement type (REQUIRED, OPTIONAL, DEFAULT) */

19

public final byte requirementType;

20

21

/** Value metadata describing the field's type */

22

public final FieldValueMetaData valueMetaData;

23

24

/** Create field metadata */

25

public FieldMetaData(String fieldName, byte requirementType, FieldValueMetaData valueMetaData);

26

27

/** Add struct metadata map for a Thrift class */

28

public static <T extends TBase<T, F>, F extends TFieldIdEnum> void addStructMetaDataMap(

29

Class<T> sClass, Map<F, FieldMetaData> map);

30

31

/** Get struct metadata map for a Thrift class */

32

public static <T extends TBase<T, F>, F extends TFieldIdEnum> Map<F, FieldMetaData> getStructMetaDataMap(

33

Class<T> sClass);

34

35

/** Get field annotations */

36

public Map<String, String> getFieldAnnotations();

37

}

38

39

/**

40

* Base class for field value metadata describing field types

41

*/

42

public class FieldValueMetaData {

43

/** Thrift type constant for this field */

44

public final byte type;

45

46

/** Type name for typedef fields */

47

public final String typedefName;

48

49

/** Create field value metadata */

50

public FieldValueMetaData(byte type);

51

52

/** Create field value metadata with typedef name */

53

public FieldValueMetaData(byte type, String typedefName);

54

55

/** Check if this is a typedef field */

56

public boolean isTypedef();

57

58

/** Get typedef name (if applicable) */

59

public String getTypedefName();

60

61

/** Check if this field represents binary data */

62

public boolean isBinary();

63

}

64

```

65

66

**Usage Examples:**

67

68

```java

69

import org.apache.thrift.meta_data.FieldMetaData;

70

import org.apache.thrift.meta_data.FieldValueMetaData;

71

import org.apache.thrift.TFieldRequirementType;

72

import org.apache.thrift.protocol.TType;

73

74

// Access metadata for a Thrift struct

75

public class MetadataExample {

76

public void inspectStruct() {

77

// Get metadata map for MyStruct class

78

Map<MyStruct._Fields, FieldMetaData> metaDataMap =

79

FieldMetaData.getStructMetaDataMap(MyStruct.class);

80

81

// Iterate through all fields

82

for (Map.Entry<MyStruct._Fields, FieldMetaData> entry : metaDataMap.entrySet()) {

83

MyStruct._Fields field = entry.getKey();

84

FieldMetaData metaData = entry.getValue();

85

86

System.out.println("Field: " + metaData.fieldName);

87

System.out.println(" Type: " + getTypeName(metaData.valueMetaData.type));

88

System.out.println(" Required: " + isRequired(metaData.requirementType));

89

System.out.println(" Typedef: " + metaData.valueMetaData.isTypedef());

90

}

91

}

92

93

private String getTypeName(byte type) {

94

switch (type) {

95

case TType.STRING: return "string";

96

case TType.I32: return "i32";

97

case TType.I64: return "i64";

98

case TType.BOOL: return "bool";

99

case TType.STRUCT: return "struct";

100

case TType.LIST: return "list";

101

case TType.MAP: return "map";

102

case TType.SET: return "set";

103

default: return "unknown";

104

}

105

}

106

107

private boolean isRequired(byte requirementType) {

108

return requirementType == TFieldRequirementType.REQUIRED;

109

}

110

}

111

```

112

113

### Specialized Metadata Types

114

115

Specific metadata classes for different Thrift data types.

116

117

```java { .api }

118

/**

119

* Metadata for struct types

120

*/

121

public class StructMetaData extends FieldValueMetaData {

122

/** The struct class */

123

public final Class<? extends TBase> structClass;

124

125

/** Create struct metadata */

126

public StructMetaData(byte type, Class<? extends TBase> structClass);

127

}

128

129

/**

130

* Metadata for list types

131

*/

132

public class ListMetaData extends FieldValueMetaData {

133

/** Element type metadata */

134

public final FieldValueMetaData elemMetaData;

135

136

/** Create list metadata */

137

public ListMetaData(byte type, FieldValueMetaData elemMetaData);

138

}

139

140

/**

141

* Metadata for map types

142

*/

143

public class MapMetaData extends FieldValueMetaData {

144

/** Key type metadata */

145

public final FieldValueMetaData keyMetaData;

146

147

/** Value type metadata */

148

public final FieldValueMetaData valueMetaData;

149

150

/** Create map metadata */

151

public MapMetaData(byte type, FieldValueMetaData keyMetaData, FieldValueMetaData valueMetaData);

152

}

153

154

/**

155

* Metadata for set types

156

*/

157

public class SetMetaData extends FieldValueMetaData {

158

/** Element type metadata */

159

public final FieldValueMetaData elemMetaData;

160

161

/** Create set metadata */

162

public SetMetaData(byte type, FieldValueMetaData elemMetaData);

163

}

164

165

/**

166

* Metadata for enum types

167

*/

168

public class EnumMetaData extends FieldValueMetaData {

169

/** The enum class */

170

public final Class<? extends TEnum> enumClass;

171

172

/** Create enum metadata */

173

public EnumMetaData(byte type, Class<? extends TEnum> enumClass);

174

}

175

```

176

177

**Usage Examples:**

178

179

```java

180

import org.apache.thrift.meta_data.*;

181

import org.apache.thrift.protocol.TType;

182

183

// Example of working with complex type metadata

184

public class ComplexMetadataExample {

185

public void analyzeComplexField(FieldMetaData fieldMetaData) {

186

FieldValueMetaData valueMetaData = fieldMetaData.valueMetaData;

187

188

switch (valueMetaData.type) {

189

case TType.STRUCT:

190

StructMetaData structMeta = (StructMetaData) valueMetaData;

191

System.out.println("Struct type: " + structMeta.structClass.getSimpleName());

192

break;

193

194

case TType.LIST:

195

ListMetaData listMeta = (ListMetaData) valueMetaData;

196

System.out.println("List of: " + getTypeName(listMeta.elemMetaData.type));

197

break;

198

199

case TType.MAP:

200

MapMetaData mapMeta = (MapMetaData) valueMetaData;

201

System.out.println("Map<" +

202

getTypeName(mapMeta.keyMetaData.type) + ", " +

203

getTypeName(mapMeta.valueMetaData.type) + ">");

204

break;

205

206

case TType.SET:

207

SetMetaData setMeta = (SetMetaData) valueMetaData;

208

System.out.println("Set of: " + getTypeName(setMeta.elemMetaData.type));

209

break;

210

211

case TType.ENUM: // Note: This would be a custom extension

212

EnumMetaData enumMeta = (EnumMetaData) valueMetaData;

213

System.out.println("Enum type: " + enumMeta.enumClass.getSimpleName());

214

break;

215

216

default:

217

System.out.println("Primitive type: " + getTypeName(valueMetaData.type));

218

}

219

}

220

221

private String getTypeName(byte type) {

222

// Implementation from previous example

223

switch (type) {

224

case TType.STRING: return "string";

225

case TType.I32: return "i32";

226

case TType.I64: return "i64";

227

case TType.BOOL: return "bool";

228

case TType.DOUBLE: return "double";

229

case TType.BYTE: return "byte";

230

case TType.I16: return "i16";

231

default: return "type_" + type;

232

}

233

}

234

}

235

```

236

237

### Generated Code Integration

238

239

Generated Thrift classes automatically include metadata initialization.

240

241

```java

242

// Example of how metadata is typically set up in generated code

243

public class MyStruct implements TBase<MyStruct, MyStruct._Fields> {

244

245

// Field enum

246

public enum _Fields implements TFieldIdEnum {

247

NAME((short)1, "name"),

248

VALUE((short)2, "value"),

249

ITEMS((short)3, "items");

250

251

private final short _thriftId;

252

private final String _fieldName;

253

254

_Fields(short thriftId, String fieldName) {

255

_thriftId = thriftId;

256

_fieldName = fieldName;

257

}

258

259

public short getThriftFieldId() {

260

return _thriftId;

261

}

262

263

public String getFieldName() {

264

return _fieldName;

265

}

266

}

267

268

// Metadata map setup

269

public static final Map<_Fields, FieldMetaData> metaDataMap;

270

static {

271

Map<_Fields, FieldMetaData> tmpMap = new EnumMap<_Fields, FieldMetaData>(_Fields.class);

272

273

tmpMap.put(_Fields.NAME, new FieldMetaData("name",

274

TFieldRequirementType.REQUIRED,

275

new FieldValueMetaData(TType.STRING)));

276

277

tmpMap.put(_Fields.VALUE, new FieldMetaData("value",

278

TFieldRequirementType.OPTIONAL,

279

new FieldValueMetaData(TType.I32)));

280

281

tmpMap.put(_Fields.ITEMS, new FieldMetaData("items",

282

TFieldRequirementType.OPTIONAL,

283

new ListMetaData(TType.LIST, new FieldValueMetaData(TType.STRING))));

284

285

metaDataMap = Collections.unmodifiableMap(tmpMap);

286

FieldMetaData.addStructMetaDataMap(MyStruct.class, metaDataMap);

287

}

288

}

289

```

290

291

### Runtime Field Validation

292

293

Using metadata for runtime validation and introspection.

294

295

```java

296

import org.apache.thrift.meta_data.FieldMetaData;

297

import org.apache.thrift.TFieldRequirementType;

298

299

// Example utility for validating Thrift objects using metadata

300

public class ThriftValidator {

301

302

public static <T extends TBase<T, F>, F extends TFieldIdEnum> boolean validate(T struct) {

303

Map<F, FieldMetaData> metaDataMap = FieldMetaData.getStructMetaDataMap((Class<T>) struct.getClass());

304

305

for (Map.Entry<F, FieldMetaData> entry : metaDataMap.entrySet()) {

306

F field = entry.getKey();

307

FieldMetaData metaData = entry.getValue();

308

309

// Check required fields

310

if (metaData.requirementType == TFieldRequirementType.REQUIRED) {

311

if (!struct.isSet(field)) {

312

System.err.println("Required field missing: " + metaData.fieldName);

313

return false;

314

}

315

}

316

317

// Additional type-specific validation could be added here

318

if (struct.isSet(field)) {

319

Object value = struct.getFieldValue(field);

320

if (!validateFieldValue(value, metaData.valueMetaData)) {

321

System.err.println("Invalid value for field: " + metaData.fieldName);

322

return false;

323

}

324

}

325

}

326

327

return true;

328

}

329

330

private static boolean validateFieldValue(Object value, FieldValueMetaData metaData) {

331

if (value == null) return true;

332

333

switch (metaData.type) {

334

case TType.STRING:

335

return value instanceof String;

336

case TType.I32:

337

return value instanceof Integer;

338

case TType.I64:

339

return value instanceof Long;

340

case TType.BOOL:

341

return value instanceof Boolean;

342

case TType.DOUBLE:

343

return value instanceof Double;

344

case TType.LIST:

345

return value instanceof List;

346

case TType.MAP:

347

return value instanceof Map;

348

case TType.SET:

349

return value instanceof Set;

350

case TType.STRUCT:

351

return value instanceof TBase;

352

default:

353

return true; // Unknown type, assume valid

354

}

355

}

356

}

357

```

358

359

### Dynamic Object Creation

360

361

Using metadata to create and populate Thrift objects dynamically.

362

363

```java

364

import org.apache.thrift.meta_data.FieldMetaData;

365

import org.apache.thrift.meta_data.StructMetaData;

366

import java.util.Map;

367

368

// Example utility for creating Thrift objects from data maps

369

public class DynamicThriftBuilder {

370

371

@SuppressWarnings("unchecked")

372

public static <T extends TBase<T, F>, F extends TFieldIdEnum> T build(

373

Class<T> clazz, Map<String, Object> data) throws Exception {

374

375

// Create instance

376

T instance = clazz.newInstance();

377

378

// Get metadata

379

Map<F, FieldMetaData> metaDataMap = FieldMetaData.getStructMetaDataMap(clazz);

380

381

// Populate fields from data map

382

for (Map.Entry<F, FieldMetaData> entry : metaDataMap.entrySet()) {

383

F field = entry.getKey();

384

FieldMetaData metaData = entry.getValue();

385

String fieldName = metaData.fieldName;

386

387

if (data.containsKey(fieldName)) {

388

Object value = data.get(fieldName);

389

Object convertedValue = convertValue(value, metaData.valueMetaData);

390

instance.setFieldValue(field, convertedValue);

391

}

392

}

393

394

return instance;

395

}

396

397

private static Object convertValue(Object value, FieldValueMetaData metaData) {

398

if (value == null) return null;

399

400

// Simple type conversion logic

401

switch (metaData.type) {

402

case TType.STRING:

403

return value.toString();

404

case TType.I32:

405

return value instanceof Number ? ((Number) value).intValue() : Integer.parseInt(value.toString());

406

case TType.I64:

407

return value instanceof Number ? ((Number) value).longValue() : Long.parseLong(value.toString());

408

case TType.BOOL:

409

return value instanceof Boolean ? value : Boolean.parseBoolean(value.toString());

410

case TType.DOUBLE:

411

return value instanceof Number ? ((Number) value).doubleValue() : Double.parseDouble(value.toString());

412

default:

413

return value; // Return as-is for complex types

414

}

415

}

416

}

417

418

// Usage example

419

Map<String, Object> data = new HashMap<>();

420

data.put("name", "example");

421

data.put("value", 42);

422

data.put("items", Arrays.asList("item1", "item2"));

423

424

MyStruct struct = DynamicThriftBuilder.build(MyStruct.class, data);

425

```

426

427

### Debugging and Introspection

428

429

Using metadata for debugging and development tools.

430

431

```java

432

// Utility for pretty-printing Thrift objects using metadata

433

public class ThriftPrinter {

434

435

public static <T extends TBase<T, F>, F extends TFieldIdEnum> String toString(T struct) {

436

StringBuilder sb = new StringBuilder();

437

Map<F, FieldMetaData> metaDataMap = FieldMetaData.getStructMetaDataMap((Class<T>) struct.getClass());

438

439

sb.append(struct.getClass().getSimpleName()).append("{\n");

440

441

for (Map.Entry<F, FieldMetaData> entry : metaDataMap.entrySet()) {

442

F field = entry.getKey();

443

FieldMetaData metaData = entry.getValue();

444

445

sb.append(" ").append(metaData.fieldName).append(": ");

446

447

if (struct.isSet(field)) {

448

Object value = struct.getFieldValue(field);

449

String requirement = getRequirementString(metaData.requirementType);

450

sb.append(value).append(" (").append(requirement).append(")");

451

} else {

452

sb.append("<not set>");

453

}

454

sb.append("\n");

455

}

456

457

sb.append("}");

458

return sb.toString();

459

}

460

461

private static String getRequirementString(byte requirementType) {

462

switch (requirementType) {

463

case TFieldRequirementType.REQUIRED:

464

return "required";

465

case TFieldRequirementType.OPTIONAL:

466

return "optional";

467

default:

468

return "default";

469

}

470

}

471

}

472

```

473

474

The metadata system provides powerful runtime introspection capabilities, enabling dynamic handling, validation, and debugging of Thrift objects without requiring compile-time knowledge of their structure.