0
# Validation Framework
1
2
The validation framework provides JSON Schema validation properties and type checking utilities for ensuring proper data handling and constraint validation throughout the code generation process.
3
4
## Core Validation Interface
5
6
### IJsonSchemaValidationProperties
7
8
Defines JSON Schema validation properties implemented by models, properties, parameters, and responses.
9
10
```java { .api }
11
interface IJsonSchemaValidationProperties {
12
// Type identification methods
13
boolean getIsModel(); // Is a custom model/object type
14
boolean getIsArray(); // Is an array/list type
15
boolean getIsMap(); // Is a map/dictionary type
16
boolean getIsString(); // Is a string type
17
boolean getIsNumber(); // Is any numeric type
18
boolean getIsInteger(); // Is an integer type
19
boolean getIsBoolean(); // Is a boolean type
20
boolean getIsDate(); // Is a date type
21
boolean getIsDateTime(); // Is a date-time type
22
boolean getIsPrimitiveType(); // Is a primitive type (string, number, boolean)
23
boolean getIsEnum(); // Is an enumeration type
24
25
// Validation constraint methods
26
String getPattern(); // Regular expression pattern
27
String getMinimum(); // Minimum value for numbers
28
String getMaximum(); // Maximum value for numbers
29
boolean getExclusiveMinimum(); // Exclusive minimum flag
30
boolean getExclusiveMaximum(); // Exclusive maximum flag
31
Integer getMinLength(); // Minimum string length
32
Integer getMaxLength(); // Maximum string length
33
Integer getMinItems(); // Minimum array items
34
Integer getMaxItems(); // Maximum array items
35
boolean getUniqueItems(); // Array items must be unique
36
Integer getMinProperties(); // Minimum object properties
37
Integer getMaxProperties(); // Maximum object properties
38
Number getMultipleOf(); // Number must be multiple of this value
39
40
// Schema relationship methods
41
CodegenProperty getItems(); // For arrays - item type
42
CodegenProperty getAdditionalProperties(); // For objects - additional props type
43
List<CodegenProperty> getVars(); // Object properties
44
List<CodegenProperty> getRequiredVars(); // Required object properties
45
CodegenComposedSchemas getComposedSchemas(); // oneOf/anyOf/allOf schemas
46
47
// Type processing methods
48
void setTypeProperties(Schema p, OpenAPI openAPI); // Set type properties from schema
49
String getBaseType(); // Get base type name
50
String getComplexType(); // Get full type with generics
51
Set<String> getImports(boolean importContainerType, boolean importBaseType, FeatureSet featureSet);
52
}
53
```
54
55
## Model Type Checking
56
57
### Schema Type Utilities
58
59
Static utilities for checking OpenAPI schema types.
60
61
```java { .api }
62
class ModelUtils {
63
// Schema type checking
64
public static boolean isObjectSchema(Schema schema);
65
public static boolean isComposedSchema(Schema schema); // oneOf/anyOf/allOf
66
public static boolean isMapSchema(Schema schema);
67
public static boolean isArraySchema(Schema schema);
68
public static boolean isStringSchema(Schema schema);
69
public static boolean isIntegerSchema(Schema schema);
70
public static boolean isNumberSchema(Schema schema);
71
public static boolean isBooleanSchema(Schema schema);
72
public static boolean isNullType(Schema schema);
73
public static boolean isAnyType(Schema schema);
74
75
// Format-specific type checking
76
public static boolean isDateSchema(Schema schema); // date format
77
public static boolean isDateTimeSchema(Schema schema); // date-time format
78
public static boolean isByteArraySchema(Schema schema); // byte format
79
public static boolean isBinarySchema(Schema schema); // binary format
80
public static boolean isFileSchema(Schema schema); // file type
81
public static boolean isUUIDSchema(Schema schema); // uuid format
82
public static boolean isEmailSchema(Schema schema); // email format
83
public static boolean isPasswordSchema(Schema schema); // password format
84
85
// Schema analysis
86
public static List<String> getAllUsedSchemas(OpenAPI openAPI); // Find all referenced schemas
87
public static List<String> getUnusedSchemas(OpenAPI openAPI); // Find unused schemas
88
public static String getSimpleRef(String ref); // Extract name from $ref
89
public static Schema unaliasSchema(Schema schema, OpenAPI openAPI); // Resolve schema aliases
90
91
// Model utilities
92
public static CodegenModel getModelByName(final String name, final Map<String, ModelsMap> models);
93
public static boolean isGenerateAliasAsModel();
94
public static void setGenerateAliasAsModel(boolean value);
95
}
96
```
97
98
## Exception Handling
99
100
### SpecValidationException
101
102
Exception thrown when OpenAPI specification validation fails.
103
104
```java { .api }
105
class SpecValidationException extends RuntimeException {
106
// Constructors
107
public SpecValidationException();
108
public SpecValidationException(String message);
109
public SpecValidationException(String message, Throwable cause);
110
public SpecValidationException(Throwable cause);
111
112
// Error and warning handling
113
public Set<String> getErrors(); // Get validation errors
114
public void setErrors(Set<String> errors);
115
public Set<String> getWarnings(); // Get validation warnings
116
public void setWarnings(Set<String> warnings);
117
118
// Overridden methods
119
public String getMessage(); // Get formatted error message
120
}
121
```
122
123
### GeneratorNotFoundException
124
125
Exception thrown when a specified generator cannot be found.
126
127
```java { .api }
128
class GeneratorNotFoundException extends RuntimeException {
129
// Inherits standard RuntimeException constructors
130
}
131
```
132
133
## Usage Examples
134
135
### Custom Validation in Generators
136
137
```java
138
public class ValidatingGenerator extends DefaultCodegen {
139
140
@Override
141
public CodegenModel fromModel(String name, Schema schema) {
142
CodegenModel model = super.fromModel(name, schema);
143
144
// Validate model properties
145
validateModelProperties(model);
146
147
return model;
148
}
149
150
private void validateModelProperties(CodegenModel model) {
151
for (CodegenProperty property : model.vars) {
152
validateProperty(property);
153
}
154
}
155
156
private void validateProperty(CodegenProperty property) {
157
// Check string length constraints
158
if (property.getIsString()) {
159
if (property.getMinLength() != null && property.getMaxLength() != null) {
160
if (property.getMinLength() > property.getMaxLength()) {
161
throw new SpecValidationException(
162
"Property " + property.name + " has minLength > maxLength");
163
}
164
}
165
}
166
167
// Check numeric constraints
168
if (property.getIsNumber()) {
169
if (property.getMinimum() != null && property.getMaximum() != null) {
170
try {
171
double min = Double.parseDouble(property.getMinimum());
172
double max = Double.parseDouble(property.getMaximum());
173
if (min > max) {
174
throw new SpecValidationException(
175
"Property " + property.name + " has minimum > maximum");
176
}
177
} catch (NumberFormatException e) {
178
throw new SpecValidationException(
179
"Invalid numeric constraint for property " + property.name, e);
180
}
181
}
182
}
183
184
// Check array constraints
185
if (property.getIsArray()) {
186
if (property.getMinItems() != null && property.getMaxItems() != null) {
187
if (property.getMinItems() > property.getMaxItems()) {
188
throw new SpecValidationException(
189
"Property " + property.name + " has minItems > maxItems");
190
}
191
}
192
}
193
}
194
}
195
```
196
197
### Type-Specific Processing
198
199
```java
200
public class TypeAwareGenerator extends DefaultCodegen {
201
202
@Override
203
public CodegenProperty fromProperty(String name, Schema propertySchema) {
204
CodegenProperty property = super.fromProperty(name, propertySchema);
205
206
// Add type-specific processing
207
if (property.getIsString()) {
208
processStringProperty(property);
209
} else if (property.getIsNumber()) {
210
processNumericProperty(property);
211
} else if (property.getIsArray()) {
212
processArrayProperty(property);
213
} else if (property.getIsMap()) {
214
processMapProperty(property);
215
} else if (property.getIsModel()) {
216
processModelProperty(property);
217
}
218
219
return property;
220
}
221
222
private void processStringProperty(CodegenProperty property) {
223
// Add string-specific validation and formatting
224
if (property.getPattern() != null) {
225
property.vendorExtensions.put("x-pattern-validation", true);
226
}
227
228
if (property.getMinLength() != null || property.getMaxLength() != null) {
229
property.vendorExtensions.put("x-length-validation", true);
230
}
231
232
// Check for specific formats
233
if ("email".equals(property.dataFormat)) {
234
property.vendorExtensions.put("x-email-validation", true);
235
} else if ("uuid".equals(property.dataFormat)) {
236
property.vendorExtensions.put("x-uuid-format", true);
237
}
238
}
239
240
private void processNumericProperty(CodegenProperty property) {
241
// Add numeric validation
242
if (property.getMinimum() != null || property.getMaximum() != null) {
243
property.vendorExtensions.put("x-range-validation", true);
244
}
245
246
if (property.getMultipleOf() != null) {
247
property.vendorExtensions.put("x-multiple-validation", true);
248
}
249
250
// Check for exclusive bounds
251
if (property.getExclusiveMinimum() || property.getExclusiveMaximum()) {
252
property.vendorExtensions.put("x-exclusive-bounds", true);
253
}
254
}
255
256
private void processArrayProperty(CodegenProperty property) {
257
// Process array constraints
258
if (property.getMinItems() != null || property.getMaxItems() != null) {
259
property.vendorExtensions.put("x-array-size-validation", true);
260
}
261
262
if (property.getUniqueItems()) {
263
property.vendorExtensions.put("x-unique-items", true);
264
}
265
266
// Process array item type
267
if (property.getItems() != null) {
268
CodegenProperty items = property.getItems();
269
property.vendorExtensions.put("x-item-type", items.dataType);
270
}
271
}
272
}
273
```
274
275
### Schema Analysis
276
277
```java
278
public class SchemaAnalyzer {
279
280
public void analyzeOpenAPISpec(OpenAPI openAPI) {
281
// Find all used schemas
282
List<String> usedSchemas = ModelUtils.getAllUsedSchemas(openAPI);
283
System.out.println("Used schemas: " + usedSchemas);
284
285
// Find unused schemas
286
List<String> unusedSchemas = ModelUtils.getUnusedSchemas(openAPI);
287
if (!unusedSchemas.isEmpty()) {
288
System.out.println("Warning: Unused schemas found: " + unusedSchemas);
289
}
290
291
// Analyze schemas by type
292
Map<String, Schema> schemas = openAPI.getComponents().getSchemas();
293
for (Map.Entry<String, Schema> entry : schemas.entrySet()) {
294
String name = entry.getKey();
295
Schema schema = entry.getValue();
296
297
analyzeSchema(name, schema);
298
}
299
}
300
301
private void analyzeSchema(String name, Schema schema) {
302
System.out.println("Analyzing schema: " + name);
303
304
if (ModelUtils.isObjectSchema(schema)) {
305
System.out.println(" Type: Object");
306
analyzeObjectSchema(schema);
307
} else if (ModelUtils.isArraySchema(schema)) {
308
System.out.println(" Type: Array");
309
analyzeArraySchema(schema);
310
} else if (ModelUtils.isStringSchema(schema)) {
311
System.out.println(" Type: String");
312
analyzeStringSchema(schema);
313
} else if (ModelUtils.isNumberSchema(schema)) {
314
System.out.println(" Type: Number");
315
analyzeNumericSchema(schema);
316
} else if (ModelUtils.isComposedSchema(schema)) {
317
System.out.println(" Type: Composed (oneOf/anyOf/allOf)");
318
analyzeComposedSchema(schema);
319
}
320
}
321
322
private void analyzeObjectSchema(Schema schema) {
323
Map<String, Schema> properties = schema.getProperties();
324
if (properties != null) {
325
System.out.println(" Properties: " + properties.keySet());
326
}
327
328
List<String> required = schema.getRequired();
329
if (required != null && !required.isEmpty()) {
330
System.out.println(" Required: " + required);
331
}
332
}
333
334
private void analyzeStringSchema(Schema schema) {
335
if (schema.getFormat() != null) {
336
System.out.println(" Format: " + schema.getFormat());
337
}
338
if (schema.getPattern() != null) {
339
System.out.println(" Pattern: " + schema.getPattern());
340
}
341
if (schema.getMinLength() != null) {
342
System.out.println(" MinLength: " + schema.getMinLength());
343
}
344
if (schema.getMaxLength() != null) {
345
System.out.println(" MaxLength: " + schema.getMaxLength());
346
}
347
}
348
}
349
```
350
351
### Exception Handling
352
353
```java
354
public class SafeGenerator extends DefaultGenerator {
355
356
@Override
357
public List<File> generate() {
358
try {
359
return super.generate();
360
} catch (SpecValidationException e) {
361
System.err.println("Specification validation failed:");
362
363
// Print validation errors
364
if (e.getErrors() != null && !e.getErrors().isEmpty()) {
365
System.err.println("Errors:");
366
for (String error : e.getErrors()) {
367
System.err.println(" - " + error);
368
}
369
}
370
371
// Print validation warnings
372
if (e.getWarnings() != null && !e.getWarnings().isEmpty()) {
373
System.err.println("Warnings:");
374
for (String warning : e.getWarnings()) {
375
System.err.println(" - " + warning);
376
}
377
}
378
379
throw e; // Re-throw to stop generation
380
} catch (GeneratorNotFoundException e) {
381
System.err.println("Generator not found: " + e.getMessage());
382
System.err.println("Available generators: " + getAvailableGenerators());
383
throw e;
384
}
385
}
386
387
private List<String> getAvailableGenerators() {
388
// Return list of available generator names
389
return Arrays.asList("java", "python", "javascript", "typescript", "go", "ruby");
390
}
391
}
392
```