or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

annotations.mdcustom-serialization.mdfield-access.mdindex.mdpolymorphic-schemas.mdruntime-environment.mdschema-generation.mdtype-strategy.md

type-strategy.mddocs/

0

# Type Strategy and Polymorphic Handling

1

2

Advanced type identification and polymorphic serialization strategies for handling inheritance hierarchies, collections, and complex object structures. The type strategy system allows protostuff-runtime to handle polymorphic types, custom serialization delegates, and complex object graphs.

3

4

## Capabilities

5

6

### IdStrategy Base Class

7

8

Abstract base class defining the interface for type identification strategies used in polymorphic serialization.

9

10

```java { .api }

11

/**

12

* Abstract base class for type identification strategies

13

*/

14

public abstract class IdStrategy {

15

16

/**

17

* Configuration flags for strategy behavior

18

*/

19

public final int flags;

20

public final IdStrategy primaryGroup;

21

public final int groupId;

22

23

/**

24

* Check if a delegate is registered for the specified type

25

* @param typeClass The class to check

26

* @return true if a delegate is registered

27

*/

28

public abstract boolean isDelegateRegistered(Class<?> typeClass);

29

30

/**

31

* Get delegate wrapper for polymorphic contexts

32

* @param typeClass The class to get delegate for

33

* @return HasDelegate wrapper or null if not found

34

*/

35

public abstract <T> HasDelegate<T> getDelegateWrapper(Class<? super T> typeClass);

36

37

/**

38

* Get delegate for the specified type

39

* @param typeClass The class to get delegate for

40

* @return Delegate instance or null if not found

41

*/

42

public abstract <T> Delegate<T> getDelegate(Class<? super T> typeClass);

43

44

/**

45

* Check if a type is registered with this strategy

46

* @param typeClass The class to check

47

* @return true if registered

48

*/

49

public abstract boolean isRegistered(Class<?> typeClass);

50

51

/**

52

* Get schema wrapper for the specified type

53

* @param typeClass The class to get schema for

54

* @param create Whether to create if not found

55

* @return HasSchema wrapper

56

*/

57

public abstract <T> HasSchema<T> getSchemaWrapper(Class<T> typeClass, boolean create);

58

}

59

```

60

61

### IdStrategy Configuration Flags

62

63

Configuration constants for controlling strategy behavior across various serialization scenarios.

64

65

```java { .api }

66

/**

67

* Serialize enums by name instead of ordinal value

68

*/

69

public static final int ENUMS_BY_NAME = 1;

70

71

/**

72

* Automatically load polymorphic classes when encountered

73

*/

74

public static final int AUTO_LOAD_POLYMORPHIC_CLASSES = 1 << 1;

75

76

/**

77

* Preserve null elements in collections and arrays

78

*/

79

public static final int PRESERVE_NULL_ELEMENTS = 1 << 2;

80

81

/**

82

* Enable morphing for non-final POJO types

83

*/

84

public static final int MORPH_NON_FINAL_POJOS = 1 << 3;

85

86

/**

87

* Enable morphing for collection interfaces (List, Set, etc.)

88

*/

89

public static final int MORPH_COLLECTION_INTERFACES = 1 << 4;

90

91

/**

92

* Enable morphing for map interfaces

93

*/

94

public static final int MORPH_MAP_INTERFACES = 1 << 5;

95

96

/**

97

* Use collection schema on repeated fields

98

*/

99

public static final int COLLECTION_SCHEMA_ON_REPEATED_FIELDS = 1 << 6;

100

101

/**

102

* Use POJO schema on collection fields

103

*/

104

public static final int POJO_SCHEMA_ON_COLLECTION_FIELDS = 1 << 7;

105

106

/**

107

* Use POJO schema on map fields

108

*/

109

public static final int POJO_SCHEMA_ON_MAP_FIELDS = 1 << 8;

110

111

/**

112

* Default flags combining common settings

113

*/

114

public static final int DEFAULT_FLAGS;

115

```

116

117

### DefaultIdStrategy Implementation

118

119

Concrete implementation of IdStrategy using fully qualified class names (FQCN) as type identifiers.

120

121

```java { .api }

122

/**

123

* Default ID strategy using fully qualified class names

124

*/

125

public final class DefaultIdStrategy extends IdStrategy {

126

127

/**

128

* Create DefaultIdStrategy with default settings

129

*/

130

public DefaultIdStrategy();

131

132

/**

133

* Create DefaultIdStrategy with custom flags

134

* @param flags Configuration flags

135

*/

136

public DefaultIdStrategy(int flags);

137

138

/**

139

* Create DefaultIdStrategy with primary group

140

* @param primaryGroup Primary strategy group

141

* @param groupId Group identifier

142

*/

143

public DefaultIdStrategy(IdStrategy primaryGroup, int groupId);

144

145

/**

146

* Create DefaultIdStrategy with all options

147

* @param flags Configuration flags

148

* @param primaryGroup Primary strategy group

149

* @param groupId Group identifier

150

*/

151

public DefaultIdStrategy(int flags, IdStrategy primaryGroup, int groupId);

152

}

153

```

154

155

### POJO Type Registration

156

157

Methods for registering Plain Old Java Objects with the type strategy.

158

159

```java { .api }

160

/**

161

* Register a POJO type with automatic schema generation

162

* @param typeClass The POJO class to register

163

* @return true if registration was successful

164

*/

165

public <T> boolean registerPojo(Class<T> typeClass);

166

167

/**

168

* Register a POJO type with custom schema

169

* @param typeClass The POJO class to register

170

* @param schema Custom schema for the POJO

171

* @return true if registration was successful

172

*/

173

public <T> boolean registerPojo(Class<T> typeClass, Schema<T> schema);

174

175

/**

176

* Map inheritance relationship for polymorphic handling

177

* @param baseClass The base/parent class

178

* @param typeClass The concrete/child class

179

* @return true if mapping was successful

180

*/

181

public <T> boolean map(Class<? super T> baseClass, Class<T> typeClass);

182

```

183

184

**Usage Examples:**

185

186

```java

187

DefaultIdStrategy strategy = new DefaultIdStrategy();

188

189

// Register POJOs

190

strategy.registerPojo(User.class);

191

strategy.registerPojo(Order.class);

192

193

// Register with custom schema

194

Schema<SpecialObject> customSchema = new MyCustomSchema();

195

strategy.registerPojo(SpecialObject.class, customSchema);

196

197

// Map inheritance hierarchies

198

strategy.map(Animal.class, Dog.class);

199

strategy.map(Animal.class, Cat.class);

200

strategy.map(Shape.class, Circle.class);

201

strategy.map(Shape.class, Rectangle.class);

202

```

203

204

### Enum Type Registration

205

206

Support for registering and configuring enum serialization behavior.

207

208

```java { .api }

209

/**

210

* Register an enum type for polymorphic serialization

211

* @param enumClass The enum class to register

212

* @return true if registration was successful

213

*/

214

public <T extends Enum<T>> boolean registerEnum(Class<T> enumClass);

215

```

216

217

**Usage Examples:**

218

219

```java

220

// Register enums for polymorphic handling

221

strategy.registerEnum(Status.class);

222

strategy.registerEnum(Priority.class);

223

strategy.registerEnum(Color.class);

224

225

// Configure enum serialization by name

226

DefaultIdStrategy strategyWithNames = new DefaultIdStrategy(IdStrategy.ENUMS_BY_NAME);

227

strategyWithNames.registerEnum(Status.class);

228

```

229

230

### Delegate Registration

231

232

Register custom serialization delegates for specific types.

233

234

```java { .api }

235

/**

236

* Register a delegate for custom serialization

237

* @param delegate The delegate implementation

238

* @return true if registration was successful

239

*/

240

public <T> boolean registerDelegate(Delegate<T> delegate);

241

242

/**

243

* Register a delegate by class name

244

* @param className The fully qualified class name

245

* @param delegate The delegate implementation

246

* @return true if registration was successful

247

*/

248

public <T> boolean registerDelegate(String className, Delegate<T> delegate);

249

```

250

251

**Usage Examples:**

252

253

```java

254

// Custom delegate for Date serialization

255

Delegate<Date> dateDelegate = new DateDelegate();

256

strategy.registerDelegate(dateDelegate);

257

258

// Register by class name (useful for optional dependencies)

259

strategy.registerDelegate("java.time.LocalDateTime", new LocalDateTimeDelegate());

260

```

261

262

### Collection and Map Registration

263

264

Register factories for polymorphic collection and map handling.

265

266

```java { .api }

267

/**

268

* Register a collection factory for polymorphic collections

269

* @param factory Collection message factory

270

* @return true if registration was successful

271

*/

272

public boolean registerCollection(CollectionSchema.MessageFactory factory);

273

274

/**

275

* Register a map factory for polymorphic maps

276

* @param factory Map message factory

277

* @return true if registration was successful

278

*/

279

public boolean registerMap(MapSchema.MessageFactory factory);

280

```

281

282

**Usage Examples:**

283

284

```java

285

// Register custom collection factories

286

CollectionSchema.MessageFactory listFactory = new MyListFactory();

287

strategy.registerCollection(listFactory);

288

289

MapSchema.MessageFactory mapFactory = new MyMapFactory();

290

strategy.registerMap(mapFactory);

291

```

292

293

### UnknownTypeException

294

295

Exception thrown when encountering unknown polymorphic types in strict mode.

296

297

```java { .api }

298

/**

299

* Exception thrown for unknown polymorphic types

300

*/

301

public static class UnknownTypeException extends RuntimeException {

302

303

/**

304

* Create exception with type information

305

* @param type The unknown type

306

*/

307

public UnknownTypeException(String type);

308

309

/**

310

* Create exception with type and cause

311

* @param type The unknown type

312

* @param cause The underlying cause

313

*/

314

public UnknownTypeException(String type, Throwable cause);

315

}

316

```

317

318

### IdStrategy Factory Interface

319

320

Factory interface for creating IdStrategy instances, useful for dependency injection and configuration.

321

322

```java { .api }

323

/**

324

* Factory interface for creating IdStrategy instances

325

*/

326

public interface Factory {

327

328

/**

329

* Create a new IdStrategy instance

330

* @return New IdStrategy instance

331

*/

332

IdStrategy create();

333

334

/**

335

* Post-creation configuration hook

336

*/

337

void postCreate();

338

}

339

```

340

341

## Configuration Examples

342

343

### Basic Configuration

344

345

```java

346

// Default strategy with standard settings

347

DefaultIdStrategy basicStrategy = new DefaultIdStrategy();

348

349

// Strategy with enum names instead of ordinals

350

DefaultIdStrategy enumNamesStrategy = new DefaultIdStrategy(IdStrategy.ENUMS_BY_NAME);

351

352

// Strategy with null preservation in collections

353

DefaultIdStrategy nullPreservingStrategy = new DefaultIdStrategy(

354

IdStrategy.PRESERVE_NULL_ELEMENTS | IdStrategy.ENUMS_BY_NAME

355

);

356

```

357

358

### Advanced Configuration

359

360

```java

361

// Comprehensive strategy with multiple flags

362

int advancedFlags = IdStrategy.ENUMS_BY_NAME

363

| IdStrategy.AUTO_LOAD_POLYMORPHIC_CLASSES

364

| IdStrategy.PRESERVE_NULL_ELEMENTS

365

| IdStrategy.MORPH_NON_FINAL_POJOS

366

| IdStrategy.COLLECTION_SCHEMA_ON_REPEATED_FIELDS;

367

368

DefaultIdStrategy advancedStrategy = new DefaultIdStrategy(advancedFlags);

369

370

// Register all application types

371

advancedStrategy.registerPojo(User.class);

372

advancedStrategy.registerPojo(Order.class);

373

advancedStrategy.registerPojo(Product.class);

374

advancedStrategy.registerEnum(Status.class);

375

advancedStrategy.registerEnum(Priority.class);

376

377

// Set up inheritance hierarchies

378

advancedStrategy.map(BaseEntity.class, User.class);

379

advancedStrategy.map(BaseEntity.class, Order.class);

380

advancedStrategy.map(BaseEntity.class, Product.class);

381

```

382

383

### Custom Strategy Implementation

384

385

```java

386

// Custom strategy extending DefaultIdStrategy

387

public class ApplicationIdStrategy extends DefaultIdStrategy {

388

389

public ApplicationIdStrategy() {

390

super(IdStrategy.ENUMS_BY_NAME | IdStrategy.PRESERVE_NULL_ELEMENTS);

391

392

// Register application-specific types

393

registerApplicationTypes();

394

}

395

396

private void registerApplicationTypes() {

397

// POJOs

398

registerPojo(User.class);

399

registerPojo(Order.class);

400

registerPojo(Product.class);

401

402

// Enums

403

registerEnum(Status.class);

404

registerEnum(Priority.class);

405

406

// Custom delegates

407

registerDelegate(new TimestampDelegate());

408

registerDelegate(new MoneyDelegate());

409

410

// Inheritance mappings

411

map(BaseEntity.class, User.class);

412

map(BaseEntity.class, Order.class);

413

}

414

}

415

```

416

417

## Polymorphic Schema Factories

418

419

Enum defining factory types for different polymorphic schema scenarios.

420

421

```java { .api }

422

/**

423

* Predefined polymorphic schema factories

424

*/

425

public enum PolymorphicSchemaFactories {

426

ARRAY, // Array type factory

427

NUMBER, // Number type factory

428

CLASS, // Class type factory

429

ENUM, // Enum type factory

430

COLLECTION, // Collection type factory

431

MAP, // Map type factory

432

THROWABLE, // Throwable type factory

433

POJO, // POJO type factory

434

POJO_MAP, // POJO map factory

435

POJO_COLLECTION, // POJO collection factory

436

OBJECT; // Object type factory

437

438

/**

439

* Get factory from field information

440

* @param f The field to analyze

441

* @param strategy The ID strategy to use

442

* @return Appropriate polymorphic schema factory

443

*/

444

public static PolymorphicSchema.Factory getFactoryFromField(

445

java.lang.reflect.Field f, IdStrategy strategy);

446

447

/**

448

* Get factory from generic type information

449

* @param clazz The class with generic type information

450

* @return Appropriate polymorphic schema factory

451

*/

452

public static PolymorphicSchema.Factory getFactoryFromRepeatedValueGenericType(Class<?> clazz);

453

454

/**

455

* Get schema from collection or map generic type

456

* @param clazz The collection or map class

457

* @param strategy The ID strategy to use

458

* @return Polymorphic schema instance

459

*/

460

public static PolymorphicSchema getSchemaFromCollectionOrMapGenericType(

461

Class<?> clazz, IdStrategy strategy);

462

}

463

```

464

465

## Best Practices

466

467

1. **Strategy Configuration**: Configure your IdStrategy with appropriate flags for your use case

468

2. **Type Registration**: Register all polymorphic types upfront for better performance

469

3. **Inheritance Mapping**: Use `map()` to establish clear inheritance relationships

470

4. **Custom Delegates**: Implement delegates for types requiring special serialization logic

471

5. **Flag Combinations**: Combine flags using bitwise OR operations for complex configurations

472

6. **Factory Pattern**: Use IdStrategy.Factory for dependency injection scenarios