1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package gov.nist.secauto.metaschema.databind;
28
29 import gov.nist.secauto.metaschema.core.datatype.IDataTypeAdapter;
30 import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
31 import gov.nist.secauto.metaschema.core.metapath.StaticContext;
32 import gov.nist.secauto.metaschema.core.metapath.item.node.IDocumentNodeItem;
33 import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem;
34 import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition;
35 import gov.nist.secauto.metaschema.core.model.IFlagContainer;
36 import gov.nist.secauto.metaschema.core.model.IModule;
37 import gov.nist.secauto.metaschema.core.model.constraint.DefaultConstraintValidator;
38 import gov.nist.secauto.metaschema.core.model.constraint.FindingCollectingConstraintValidationHandler;
39 import gov.nist.secauto.metaschema.core.model.constraint.IConstraintValidationHandler;
40 import gov.nist.secauto.metaschema.core.model.constraint.IConstraintValidator;
41 import gov.nist.secauto.metaschema.core.model.validation.AggregateValidationResult;
42 import gov.nist.secauto.metaschema.core.model.validation.IValidationResult;
43 import gov.nist.secauto.metaschema.core.model.validation.JsonSchemaContentValidator;
44 import gov.nist.secauto.metaschema.core.model.validation.XmlSchemaContentValidator;
45 import gov.nist.secauto.metaschema.core.util.ObjectUtils;
46 import gov.nist.secauto.metaschema.databind.codegen.ModuleCompilerHelper;
47 import gov.nist.secauto.metaschema.databind.io.BindingException;
48 import gov.nist.secauto.metaschema.databind.io.DeserializationFeature;
49 import gov.nist.secauto.metaschema.databind.io.Format;
50 import gov.nist.secauto.metaschema.databind.io.IBoundLoader;
51 import gov.nist.secauto.metaschema.databind.io.IDeserializer;
52 import gov.nist.secauto.metaschema.databind.io.ISerializer;
53 import gov.nist.secauto.metaschema.databind.io.yaml.YamlOperations;
54 import gov.nist.secauto.metaschema.databind.model.IAssemblyClassBinding;
55 import gov.nist.secauto.metaschema.databind.model.IClassBinding;
56 import gov.nist.secauto.metaschema.databind.model.annotations.MetaschemaAssembly;
57 import gov.nist.secauto.metaschema.databind.model.annotations.MetaschemaField;
58
59 import org.json.JSONObject;
60 import org.xml.sax.SAXException;
61
62 import java.io.IOException;
63 import java.math.BigInteger;
64 import java.nio.file.Files;
65 import java.nio.file.Path;
66 import java.time.ZonedDateTime;
67 import java.util.List;
68
69 import javax.xml.namespace.QName;
70 import javax.xml.transform.Source;
71
72 import edu.umd.cs.findbugs.annotations.NonNull;
73 import edu.umd.cs.findbugs.annotations.Nullable;
74
75
76
77
78
79 public interface IBindingContext extends IModuleLoaderStrategy {
80
81
82
83
84
85
86
87 @NonNull
88 static IBindingContext instance() {
89 return DefaultBindingContext.instance();
90 }
91
92
93
94
95
96
97
98
99 @NonNull
100 IBindingContext registerBindingMatcher(@NonNull IBindingMatcher matcher);
101
102
103
104
105
106
107
108
109
110 @Nullable
111 Class<?> getBoundClassForXmlQName(@NonNull QName rootQName);
112
113
114
115
116
117
118
119
120
121
122 @Nullable
123 Class<?> getBoundClassForJsonName(@NonNull String rootName);
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140 @Nullable
141 <TYPE extends IDataTypeAdapter<?>> TYPE getJavaTypeAdapterInstance(@NonNull Class<TYPE> clazz);
142
143
144
145
146
147
148
149
150
151
152
153
154
155 @SuppressWarnings("PMD.UseProperClassLoader")
156 @NonNull
157 default IBindingContext registerModule(
158 @NonNull IModule module,
159 @NonNull Path compilePath) throws IOException {
160 Files.createDirectories(compilePath);
161
162 ClassLoader classLoader = ModuleCompilerHelper.newClassLoader(
163 compilePath,
164 ObjectUtils.notNull(Thread.currentThread().getContextClassLoader()));
165
166 ModuleCompilerHelper.compileMetaschema(module, compilePath).getGlobalDefinitionClassesAsStream()
167 .filter(definitionInfo -> {
168 boolean retval = false;
169 IFlagContainer definition = definitionInfo.getDefinition();
170 if (definition instanceof IAssemblyDefinition) {
171 IAssemblyDefinition assembly = (IAssemblyDefinition) definition;
172 if (assembly.isRoot()) {
173 retval = true;
174 }
175 }
176 return retval;
177 })
178 .map(
179 generatedClass -> {
180 try {
181 @SuppressWarnings("unchecked") Class<IAssemblyClassBinding> clazz
182 = ObjectUtils.notNull((Class<IAssemblyClassBinding>) classLoader
183 .loadClass(generatedClass.getClassName().reflectionName()));
184
185 IAssemblyDefinition definition = (IAssemblyDefinition) generatedClass.getDefinition();
186 return new DynamicBindingMatcher(
187 definition,
188 clazz);
189 } catch (ClassNotFoundException ex) {
190 throw new IllegalStateException(ex);
191 }
192 })
193 .forEachOrdered(
194 matcher -> registerBindingMatcher(
195 ObjectUtils.notNull(
196 matcher)));
197 return this;
198 }
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222 @NonNull
223 <CLASS> ISerializer<CLASS> newSerializer(@NonNull Format format, @NonNull Class<CLASS> clazz);
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247 @NonNull
248 <CLASS> IDeserializer<CLASS> newDeserializer(@NonNull Format format, @NonNull Class<CLASS> clazz);
249
250
251
252
253
254
255 @NonNull
256 IBoundLoader newBoundLoader();
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275 @NonNull
276 <CLASS> CLASS copyBoundObject(@NonNull CLASS other, Object parentInstance) throws BindingException;
277
278
279
280
281
282
283
284
285
286 default IConstraintValidator newValidator(@NonNull IConstraintValidationHandler handler) {
287 IBoundLoader loader = newBoundLoader();
288 loader.disableFeature(DeserializationFeature.DESERIALIZE_VALIDATE_CONSTRAINTS);
289
290 DynamicContext context = StaticContext.newInstance().newDynamicContext();
291 context.setDocumentLoader(loader);
292
293 return new DefaultConstraintValidator(context, handler);
294 }
295
296
297
298
299
300
301
302
303
304
305
306 default IValidationResult validate(@NonNull INodeItem nodeItem) {
307 FindingCollectingConstraintValidationHandler handler = new FindingCollectingConstraintValidationHandler();
308 IConstraintValidator validator = newValidator(handler);
309 validator.validate(nodeItem);
310 validator.finalizeValidation();
311 return handler;
312 }
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330 default IValidationResult validate(
331 @NonNull Path target,
332 @NonNull Format asFormat,
333 @NonNull IValidationSchemaProvider schemaProvider) throws IOException, SAXException {
334 IValidationResult retval;
335 switch (asFormat) {
336 case JSON:
337 retval = new JsonSchemaContentValidator(schemaProvider.getJsonSchema()).validate(target);
338 break;
339 case XML:
340 List<Source> schemaSources = schemaProvider.getXmlSchemas();
341 retval = new XmlSchemaContentValidator(schemaSources).validate(target);
342 break;
343 case YAML:
344 JSONObject json = YamlOperations.yamlToJson(YamlOperations.parseYaml(target));
345 assert json != null;
346 retval = new JsonSchemaContentValidator(schemaProvider.getJsonSchema())
347 .validate(json, ObjectUtils.notNull(target.toUri()));
348 break;
349 default:
350 throw new UnsupportedOperationException("Unsupported format: " + asFormat.name());
351 }
352
353 if (retval.isPassing()) {
354 IValidationResult constraintValidationResult = validateWithConstraints(target);
355 retval = AggregateValidationResult.aggregate(retval, constraintValidationResult);
356 }
357 return retval;
358 }
359
360
361
362
363
364
365
366
367
368
369
370 default IValidationResult validateWithConstraints(@NonNull Path target) throws IOException {
371 IBoundLoader loader = newBoundLoader();
372 loader.disableFeature(DeserializationFeature.DESERIALIZE_VALIDATE_CONSTRAINTS);
373
374 DynamicContext dynamicContext = StaticContext.newInstance().newDynamicContext();
375 dynamicContext.setDocumentLoader(loader);
376 IDocumentNodeItem nodeItem = loader.loadAsNodeItem(target);
377
378 return validate(nodeItem);
379 }
380
381 interface IValidationSchemaProvider {
382
383
384
385
386
387
388
389 @NonNull
390 JSONObject getJsonSchema() throws IOException;
391
392
393
394
395
396
397
398
399 @NonNull
400 List<Source> getXmlSchemas() throws IOException;
401 }
402
403 }