or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdjaxb-lifecycle.mdjaxb-model.mdobject-locators.mdstrategic-patterns.mdutilities.md

jaxb-model.mddocs/

0

# JAXB Model Abstraction

1

2

Comprehensive abstraction layer over JAXB model information providing vendor-neutral access to type metadata, property information, and schema details through visitor pattern support. This abstraction enables tools to inspect and work with JAXB model metadata independently of the underlying JAXB implementation.

3

4

## Capabilities

5

6

### Core Model Interfaces

7

8

#### Model Information Root

9

10

```java { .api }

11

interface MModelInfo<T, C> extends MCustomizable {

12

Collection<MBuiltinLeafInfo<T, C>> getBuiltinLeafInfos();

13

Collection<MClassInfo<T, C>> getClassInfos();

14

Collection<MEnumLeafInfo<T, C>> getEnumLeafInfos();

15

Collection<MElementInfo<T, C>> getElementInfos();

16

17

void addBuiltinLeafInfo(MBuiltinLeafInfo<T, C> info);

18

void addClassInfo(MClassInfo<T, C> info);

19

void addEnumLeafInfo(MEnumLeafInfo<T, C> info);

20

void addElementInfo(MElementInfo<T, C> info);

21

22

void removeBuiltinLeafInfo(MBuiltinLeafInfo<T, C> info);

23

void removeClassInfo(MClassInfo<T, C> info);

24

void removeEnumLeafInfo(MEnumLeafInfo<T, C> info);

25

void removeElementInfo(MElementInfo<T, C> info);

26

}

27

```

28

29

#### Type Information

30

31

```java { .api }

32

interface MTypeInfo<T, C> extends MCustomizable {

33

QName getTypeName();

34

boolean isSimpleType();

35

T getTargetType();

36

<V> V acceptTypeInfoVisitor(MTypeInfoVisitor<T, C, V> visitor);

37

}

38

39

interface MClassInfo<T, C> extends MClassTypeInfo<T, C> {

40

List<MPropertyInfo<T, C>> getProperties();

41

MPropertyInfo<T, C> getProperty(String publicName);

42

QName getElementName();

43

MClassTypeInfo<T, C, ?> getBaseTypeInfo();

44

}

45

46

interface MEnumLeafInfo<T, C> extends MTypeInfo<T, C> {

47

List<MEnumConstantInfo<T, C>> getEnumConstants();

48

MEnumConstantInfo<T, C> getEnumConstant(String name);

49

}

50

51

interface MElementInfo<T, C> extends MPackaged, MCustomizable {

52

QName getElementName();

53

MTypeInfo<T, C> getTypeInfo();

54

MElement getElement();

55

}

56

```

57

58

#### Property Information

59

60

```java { .api }

61

interface MPropertyInfo<T, C> extends MTargeted<T>, MCustomizable {

62

String getPrivateName();

63

String getPublicName();

64

boolean isCollection();

65

boolean isRequired();

66

MDefaultValue getDefaultValue();

67

<V> V acceptPropertyInfoVisitor(MPropertyInfoVisitor<T, C, V> visitor);

68

}

69

70

// Specific property types

71

interface MElementPropertyInfo<T, C> extends MSingleTypePropertyInfo<T, C>, MWrappable {

72

QName getWrapperElementName();

73

}

74

75

interface MAttributePropertyInfo<T, C> extends MSingleTypePropertyInfo<T, C> {

76

QName getAttributeName();

77

boolean isRequired();

78

}

79

80

interface MAnyElementPropertyInfo<T, C> extends MPropertyInfo<T, C>, MMixable {

81

boolean isLax();

82

Set<QName> getProcessContents();

83

}

84

85

interface MAnyAttributePropertyInfo<T, C> extends MPropertyInfo<T, C> {

86

// Marker interface for any attribute properties

87

}

88

89

interface MValuePropertyInfo<T, C> extends MSingleTypePropertyInfo<T, C> {

90

// Marker interface for value properties

91

}

92

93

interface MElementRefPropertyInfo<T, C> extends MPropertyInfo<T, C>, MWrappable {

94

MElementInfo<T, C> getElementInfo();

95

}

96

97

interface MElementRefsPropertyInfo<T, C> extends MPropertyInfo<T, C>, MWrappable, MMixable {

98

List<MElementTypeInfo<T, C>> getElementTypeInfos();

99

}

100

101

interface MElementsPropertyInfo<T, C> extends MPropertyInfo<T, C>, MWrappable, MMixable {

102

List<MElementTypeInfo<T, C>> getElementTypeInfos();

103

}

104

```

105

106

### Visitor Pattern Interfaces

107

108

```java { .api }

109

interface MTypeInfoVisitor<T, C, V> {

110

V visitBuiltinLeafInfo(MBuiltinLeafInfo<T, C> info);

111

V visitEnumLeafInfo(MEnumLeafInfo<T, C> info);

112

V visitWildcardTypeInfo(MWildcardTypeInfo<T, C> info);

113

<NTI extends MTypeInfo<T, C>> V visitClassInfo(MClassInfo<T, C> info);

114

<NTI extends MTypeInfo<T, C>> V visitClassRef(MClassRef<T, C> info);

115

}

116

117

interface MClassTypeInfoVisitor<T, C, V> {

118

V visitClassInfo(MClassInfo<T, C> info);

119

V visitClassRef(MClassRef<T, C> info);

120

}

121

122

interface MPropertyInfoVisitor<T, C, V> {

123

V visitElementPropertyInfo(MElementPropertyInfo<T, C> info);

124

V visitElementsPropertyInfo(MElementsPropertyInfo<T, C> info);

125

V visitElementRefPropertyInfo(MElementRefPropertyInfo<T, C> info);

126

V visitElementRefsPropertyInfo(MElementRefsPropertyInfo<T, C> info);

127

V visitAttributePropertyInfo(MAttributePropertyInfo<T, C> info);

128

V visitAnyElementPropertyInfo(MAnyElementPropertyInfo<T, C> info);

129

V visitAnyAttributePropertyInfo(MAnyAttributePropertyInfo<T, C> info);

130

V visitValuePropertyInfo(MValuePropertyInfo<T, C> info);

131

}

132

```

133

134

### Supporting Interfaces

135

136

```java { .api }

137

interface MCustomizable {

138

MCustomizations getCustomizations();

139

void setCustomizations(MCustomizations customizations);

140

}

141

142

interface MOriginated<O> {

143

O getOrigin();

144

}

145

146

interface MPackaged {

147

MPackageInfo getPackageInfo();

148

}

149

150

interface MContained {

151

MContainer getContainer();

152

}

153

154

interface MContainer {

155

Collection<? extends MContained> getContainedInfos();

156

}

157

158

interface MTargeted<T> {

159

T getTargetType();

160

}

161

162

interface MWrappable {

163

QName getWrapperElementName();

164

}

165

166

interface MMixable {

167

boolean isMixed();

168

}

169

170

interface MNillable {

171

boolean isNillable();

172

}

173

```

174

175

### Concrete Implementation Factory

176

177

```java { .api }

178

abstract class CMInfoFactory<T, C, TI extends MTypeInfo<T, C>, CI extends MClassInfo<T, C>,

179

ELI extends MEnumLeafInfo<T, C>, EI extends MElementInfo<T, C>> {

180

181

public abstract MModelInfo<T, C> createModel();

182

183

// Factory methods for creating concrete model implementations

184

protected abstract CI createClassInfo();

185

protected abstract ELI createEnumLeafInfo();

186

protected abstract EI createElementInfo();

187

protected abstract MPropertyInfo<T, C> createPropertyInfo();

188

// ... additional factory methods

189

}

190

```

191

192

### Utility Classes

193

194

```java { .api }

195

abstract class DefaultTypeInfoVisitor<T, C, V> implements MTypeInfoVisitor<T, C, V> {

196

// Default empty implementations for all visitor methods

197

public V visitBuiltinLeafInfo(MBuiltinLeafInfo<T, C> info) { return null; }

198

public V visitEnumLeafInfo(MEnumLeafInfo<T, C> info) { return null; }

199

public V visitWildcardTypeInfo(MWildcardTypeInfo<T, C> info) { return null; }

200

public <NTI extends MTypeInfo<T, C>> V visitClassInfo(MClassInfo<T, C> info) { return null; }

201

public <NTI extends MTypeInfo<T, C>> V visitClassRef(MClassRef<T, C> info) { return null; }

202

}

203

204

abstract class DefaultPropertyInfoVisitor<T, C, V> implements MPropertyInfoVisitor<T, C, V> {

205

// Default empty implementations for all visitor methods

206

public V visitElementPropertyInfo(MElementPropertyInfo<T, C> info) { return null; }

207

public V visitAttributePropertyInfo(MAttributePropertyInfo<T, C> info) { return null; }

208

// ... additional default methods

209

}

210

211

final class XmlTypeUtils {

212

static QName getTypeName(Class<?> targetClass);

213

// Extracts QName from @XmlType annotation

214

}

215

216

final class QNameCollector {

217

Collection<QName> collectQNames(MModelInfo<?, ?> modelInfo);

218

// Collects all QNames from model components

219

}

220

221

final class QNameUtils {

222

static String getKey(QName name);

223

// Converts QName to string key representation

224

}

225

```

226

227

## Usage Examples

228

229

### Basic Model Inspection

230

231

```java

232

import org.jvnet.jaxb2_commons.xml.bind.model.*;

233

import org.jvnet.jaxb2_commons.xml.bind.model.concrete.*;

234

import javax.xml.bind.JAXBContext;

235

236

// Create model from JAXB context

237

JAXBContext context = JAXBContext.newInstance("com.example.schema");

238

CMInfoFactory<Type, Class, ?, ?, ?, ?> factory = new CMInfoFactory<Type, Class, ?, ?, ?, ?>(context);

239

MModelInfo<Type, Class> model = factory.createModel();

240

241

// Inspect class information

242

for (MClassInfo<Type, Class> classInfo : model.getClassInfos()) {

243

System.out.println("Class: " + classInfo.getTargetType().getName());

244

System.out.println("Element Name: " + classInfo.getElementName());

245

246

// Inspect properties

247

for (MPropertyInfo<Type, Class> property : classInfo.getProperties()) {

248

System.out.println(" Property: " + property.getPublicName() +

249

" (" + property.getPrivateName() + ")");

250

System.out.println(" Collection: " + property.isCollection());

251

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

252

}

253

}

254

255

// Inspect enum information

256

for (MEnumLeafInfo<Type, Class> enumInfo : model.getEnumLeafInfos()) {

257

System.out.println("Enum: " + enumInfo.getTargetType().getName());

258

for (MEnumConstantInfo<Type, Class> constant : enumInfo.getEnumConstants()) {

259

System.out.println(" Constant: " + constant.getName());

260

}

261

}

262

```

263

264

### Property Type Analysis with Visitor Pattern

265

266

```java

267

import org.jvnet.jaxb2_commons.xml.bind.model.util.*;

268

269

public class PropertyAnalyzer extends DefaultPropertyInfoVisitor<Type, Class, Void> {

270

271

@Override

272

public Void visitElementPropertyInfo(MElementPropertyInfo<Type, Class> info) {

273

System.out.println("Element Property: " + info.getPublicName());

274

if (info.getWrapperElementName() != null) {

275

System.out.println(" Wrapper: " + info.getWrapperElementName());

276

}

277

return null;

278

}

279

280

@Override

281

public Void visitAttributePropertyInfo(MAttributePropertyInfo<Type, Class> info) {

282

System.out.println("Attribute Property: " + info.getPublicName());

283

System.out.println(" Attribute Name: " + info.getAttributeName());

284

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

285

return null;

286

}

287

288

@Override

289

public Void visitAnyElementPropertyInfo(MAnyElementPropertyInfo<Type, Class> info) {

290

System.out.println("Any Element Property: " + info.getPublicName());

291

System.out.println(" Lax: " + info.isLax());

292

System.out.println(" Mixed: " + info.isMixed());

293

return null;

294

}

295

296

@Override

297

public Void visitElementsPropertyInfo(MElementsPropertyInfo<Type, Class> info) {

298

System.out.println("Elements Property: " + info.getPublicName());

299

System.out.println(" Element Types: " + info.getElementTypeInfos().size());

300

for (MElementTypeInfo<Type, Class> elementType : info.getElementTypeInfos()) {

301

System.out.println(" Element: " + elementType.getElementName());

302

}

303

return null;

304

}

305

}

306

307

// Usage

308

PropertyAnalyzer analyzer = new PropertyAnalyzer();

309

for (MClassInfo<Type, Class> classInfo : model.getClassInfos()) {

310

for (MPropertyInfo<Type, Class> property : classInfo.getProperties()) {

311

property.acceptPropertyInfoVisitor(analyzer);

312

}

313

}

314

```

315

316

### QName Collection and Analysis

317

318

```java

319

import org.jvnet.jaxb2_commons.xml.bind.model.util.*;

320

import javax.xml.namespace.QName;

321

322

public class SchemaAnalyzer {

323

324

public void analyzeSchema(MModelInfo<Type, Class> model) {

325

// Collect all QNames from the model

326

QNameCollector collector = new QNameCollector();

327

Collection<QName> qnames = collector.collectQNames(model);

328

329

// Group by namespace

330

Map<String, List<QName>> namespaceGroups = qnames.stream()

331

.collect(Collectors.groupingBy(QName::getNamespaceURI));

332

333

System.out.println("Schema Analysis:");

334

for (Map.Entry<String, List<QName>> entry : namespaceGroups.entrySet()) {

335

String namespace = entry.getKey();

336

List<QName> names = entry.getValue();

337

338

System.out.println("Namespace: " + (namespace.isEmpty() ? "(default)" : namespace));

339

for (QName name : names) {

340

System.out.println(" " + name.getLocalPart());

341

}

342

}

343

344

// Generate unique keys for QNames

345

for (QName qname : qnames) {

346

String key = QNameUtils.getKey(qname);

347

System.out.println("QName: " + qname + " -> Key: " + key);

348

}

349

}

350

}

351

```

352

353

### Custom Type Info Visitor

354

355

```java

356

import org.jvnet.jaxb2_commons.xml.bind.model.util.*;

357

358

public class TypeInfoAnalyzer extends DefaultTypeInfoVisitor<Type, Class, TypeAnalysisResult> {

359

360

@Override

361

public TypeAnalysisResult visitClassInfo(MClassInfo<Type, Class> info) {

362

TypeAnalysisResult result = new TypeAnalysisResult();

363

result.setTypeName(info.getTypeName());

364

result.setJavaType(info.getTargetType());

365

result.setPropertyCount(info.getProperties().size());

366

367

// Analyze inheritance

368

MClassTypeInfo<Type, Class, ?> baseType = info.getBaseTypeInfo();

369

if (baseType != null) {

370

result.setHasInheritance(true);

371

result.setBaseType(baseType.getTypeName());

372

}

373

374

// Count different property types

375

int elementProps = 0, attributeProps = 0, anyProps = 0;

376

for (MPropertyInfo<Type, Class> prop : info.getProperties()) {

377

prop.acceptPropertyInfoVisitor(new DefaultPropertyInfoVisitor<Type, Class, Void>() {

378

@Override

379

public Void visitElementPropertyInfo(MElementPropertyInfo<Type, Class> info) {

380

elementProps++;

381

return null;

382

}

383

@Override

384

public Void visitAttributePropertyInfo(MAttributePropertyInfo<Type, Class> info) {

385

attributeProps++;

386

return null;

387

}

388

@Override

389

public Void visitAnyElementPropertyInfo(MAnyElementPropertyInfo<Type, Class> info) {

390

anyProps++;

391

return null;

392

}

393

});

394

}

395

396

result.setElementPropertyCount(elementProps);

397

result.setAttributePropertyCount(attributeProps);

398

result.setAnyPropertyCount(anyProps);

399

400

return result;

401

}

402

403

@Override

404

public TypeAnalysisResult visitEnumLeafInfo(MEnumLeafInfo<Type, Class> info) {

405

TypeAnalysisResult result = new TypeAnalysisResult();

406

result.setTypeName(info.getTypeName());

407

result.setJavaType(info.getTargetType());

408

result.setEnumConstantCount(info.getEnumConstants().size());

409

return result;

410

}

411

}

412

413

// Analysis result class

414

public class TypeAnalysisResult {

415

private QName typeName;

416

private Class javaType;

417

private int propertyCount;

418

private boolean hasInheritance;

419

private QName baseType;

420

private int elementPropertyCount;

421

private int attributePropertyCount;

422

private int anyPropertyCount;

423

private int enumConstantCount;

424

425

// getters and setters...

426

}

427

428

// Usage

429

TypeInfoAnalyzer analyzer = new TypeInfoAnalyzer();

430

for (MClassInfo<Type, Class> classInfo : model.getClassInfos()) {

431

TypeAnalysisResult analysis = classInfo.acceptTypeInfoVisitor(analyzer);

432

System.out.println("Analysis for " + analysis.getTypeName() + ":");

433

System.out.println(" Java Type: " + analysis.getJavaType().getSimpleName());

434

System.out.println(" Properties: " + analysis.getPropertyCount());

435

System.out.println(" Elements: " + analysis.getElementPropertyCount());

436

System.out.println(" Attributes: " + analysis.getAttributePropertyCount());

437

if (analysis.isHasInheritance()) {

438

System.out.println(" Base Type: " + analysis.getBaseType());

439

}

440

}

441

```

442

443

### Model Validation and Consistency Checking

444

445

```java

446

public class ModelValidator {

447

448

public void validateModel(MModelInfo<Type, Class> model) {

449

Set<String> errors = new HashSet<>();

450

451

// Validate class information

452

for (MClassInfo<Type, Class> classInfo : model.getClassInfos()) {

453

validateClassInfo(classInfo, errors);

454

}

455

456

// Validate element information

457

for (MElementInfo<Type, Class> elementInfo : model.getElementInfos()) {

458

validateElementInfo(elementInfo, errors);

459

}

460

461

// Report validation results

462

if (errors.isEmpty()) {

463

System.out.println("Model validation passed");

464

} else {

465

System.out.println("Model validation failed with errors:");

466

errors.forEach(System.out::println);

467

}

468

}

469

470

private void validateClassInfo(MClassInfo<Type, Class> classInfo, Set<String> errors) {

471

if (classInfo.getTypeName() == null) {

472

errors.add("Class " + classInfo.getTargetType().getName() + " has null type name");

473

}

474

475

// Check for duplicate property names

476

Set<String> propertyNames = new HashSet<>();

477

for (MPropertyInfo<Type, Class> property : classInfo.getProperties()) {

478

String publicName = property.getPublicName();

479

if (!propertyNames.add(publicName)) {

480

errors.add("Class " + classInfo.getTargetType().getName() +

481

" has duplicate property: " + publicName);

482

}

483

484

validatePropertyInfo(property, classInfo, errors);

485

}

486

}

487

488

private void validatePropertyInfo(MPropertyInfo<Type, Class> property,

489

MClassInfo<Type, Class> owner, Set<String> errors) {

490

if (property.getPublicName() == null || property.getPublicName().trim().isEmpty()) {

491

errors.add("Property in class " + owner.getTargetType().getName() +

492

" has null or empty public name");

493

}

494

495

if (property.getPrivateName() == null || property.getPrivateName().trim().isEmpty()) {

496

errors.add("Property " + property.getPublicName() + " in class " +

497

owner.getTargetType().getName() + " has null or empty private name");

498

}

499

}

500

501

private void validateElementInfo(MElementInfo<Type, Class> elementInfo, Set<String> errors) {

502

if (elementInfo.getElementName() == null) {

503

errors.add("Element info has null element name");

504

}

505

506

if (elementInfo.getTypeInfo() == null) {

507

errors.add("Element " + elementInfo.getElementName() + " has null type info");

508

}

509

}

510

}

511

```

512

513

## Model Abstraction Architecture

514

515

The model abstraction provides several key benefits:

516

517

1. **Vendor Independence**: Works with different JAXB implementations (RI, MOXy, etc.)

518

2. **Visitor Pattern**: Enables type-safe traversal and analysis of model components

519

3. **Complete Metadata Access**: Exposes all JAXB model information including types, properties, and relationships

520

4. **Extensibility**: Supports custom analysis and transformation through visitor implementations

521

5. **Origin Tracking**: Maintains links to original JAXB model components where available

522

523

This abstraction is essential for tools that need to analyze, validate, or transform JAXB models independently of the underlying JAXB implementation.