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.