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.codegen.config;
28
29 import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition;
30 import gov.nist.secauto.metaschema.core.model.IFieldDefinition;
31 import gov.nist.secauto.metaschema.core.model.IFlagContainer;
32 import gov.nist.secauto.metaschema.core.model.IModule;
33 import gov.nist.secauto.metaschema.core.util.ObjectUtils;
34 import gov.nist.secauto.metaschema.databind.codegen.ClassUtils;
35 import gov.nist.secauto.metaschema.databind.codegen.xmlbeans.JavaModelBindingType;
36 import gov.nist.secauto.metaschema.databind.codegen.xmlbeans.JavaObjectDefinitionBindingType;
37 import gov.nist.secauto.metaschema.databind.codegen.xmlbeans.MetaschemaBindingType;
38 import gov.nist.secauto.metaschema.databind.codegen.xmlbeans.MetaschemaBindingsDocument;
39 import gov.nist.secauto.metaschema.databind.codegen.xmlbeans.MetaschemaBindingsType;
40 import gov.nist.secauto.metaschema.databind.codegen.xmlbeans.ModelBindingType;
41 import gov.nist.secauto.metaschema.databind.codegen.xmlbeans.ObjectDefinitionBindingType;
42
43 import org.apache.xmlbeans.XmlException;
44
45 import java.io.File;
46 import java.io.IOException;
47 import java.net.MalformedURLException;
48 import java.net.URI;
49 import java.net.URISyntaxException;
50 import java.net.URL;
51 import java.nio.file.Path;
52 import java.util.Map;
53 import java.util.Objects;
54 import java.util.concurrent.ConcurrentHashMap;
55
56 import edu.umd.cs.findbugs.annotations.NonNull;
57 import edu.umd.cs.findbugs.annotations.Nullable;
58
59 public class DefaultBindingConfiguration implements IBindingConfiguration {
60 private final Map<String, String> namespaceToPackageNameMap = new ConcurrentHashMap<>();
61
62 private final Map<String, MetaschemaBindingConfiguration> moduleUrlToMetaschemaBindingConfigurationMap
63 = new ConcurrentHashMap<>();
64
65 @Override
66 public String getPackageNameForModule(IModule module) {
67 URI namespace = module.getXmlNamespace();
68 return getPackageNameForNamespace(ObjectUtils.notNull(namespace.toASCIIString()));
69 }
70
71
72
73
74
75
76
77
78
79 @Nullable
80 public IDefinitionBindingConfiguration getBindingConfigurationForDefinition(
81 @NonNull IFlagContainer definition) {
82 String moduleUri = ObjectUtils.notNull(definition.getContainingModule().getLocation().toString());
83 String definitionName = definition.getName();
84
85 MetaschemaBindingConfiguration metaschemaConfig = getMetaschemaBindingConfiguration(moduleUri);
86
87 IDefinitionBindingConfiguration retval = null;
88 if (metaschemaConfig != null) {
89 switch (definition.getModelType()) {
90 case ASSEMBLY:
91 retval = metaschemaConfig.getAssemblyDefinitionBindingConfig(definitionName);
92 break;
93 case FIELD:
94 retval = metaschemaConfig.getFieldDefinitionBindingConfig(definitionName);
95 break;
96 default:
97 throw new UnsupportedOperationException(
98 String.format("Unsupported definition type '%s'", definition.getModelType()));
99 }
100 }
101 return retval;
102 }
103
104 @Override
105 public String getQualifiedBaseClassName(IFlagContainer definition) {
106 IDefinitionBindingConfiguration config = getBindingConfigurationForDefinition(definition);
107
108 String retval = null;
109 if (config != null) {
110 retval = config.getQualifiedBaseClassName();
111 }
112 return retval;
113 }
114
115 @Override
116 public String getClassName(IFlagContainer definition) {
117 IDefinitionBindingConfiguration config = getBindingConfigurationForDefinition(definition);
118
119 String retval = null;
120 if (config != null) {
121 retval = config.getClassName();
122 }
123
124 if (retval == null) {
125 retval = ClassUtils.toClassName(definition.getName());
126 }
127 return retval;
128 }
129
130 @Override
131 public @NonNull String getClassName(@NonNull IModule module) {
132
133 return ClassUtils.toClassName(module.getShortName() + "Module");
134 }
135
136
137
138
139
140
141
142
143
144
145
146
147
148 public void addModelBindingConfig(String namespace, String packageName) {
149 if (namespaceToPackageNameMap.containsKey(namespace)) {
150 String oldPackageName = namespaceToPackageNameMap.get(namespace);
151 if (!oldPackageName.equals(packageName)) {
152 throw new IllegalStateException(
153 String.format("Attempt to redefine existing package name '%s' to '%s' for namespace '%s'",
154 oldPackageName,
155 packageName,
156 namespace));
157 }
158 } else {
159 namespaceToPackageNameMap.put(namespace, packageName);
160 }
161 }
162
163
164
165
166
167
168
169
170
171
172
173
174 @NonNull
175 protected String getPackageNameForNamespace(@NonNull String namespace) {
176 String packageName = namespaceToPackageNameMap.get(namespace);
177 if (packageName == null) {
178 packageName = ClassUtils.toPackageName(namespace);
179 }
180 return packageName;
181 }
182
183
184
185
186
187
188
189
190
191 protected MetaschemaBindingConfiguration getMetaschemaBindingConfiguration(@NonNull IModule module) {
192 String moduleUri = ObjectUtils.notNull(module.getLocation().toString());
193 return getMetaschemaBindingConfiguration(moduleUri);
194
195 }
196
197
198
199
200
201
202
203
204
205
206 @Nullable
207 protected MetaschemaBindingConfiguration getMetaschemaBindingConfiguration(@NonNull String moduleUri) {
208 return moduleUrlToMetaschemaBindingConfigurationMap.get(moduleUri);
209 }
210
211
212
213
214
215
216
217
218
219
220
221
222 public MetaschemaBindingConfiguration addMetaschemaBindingConfiguration(
223 @NonNull String moduleUri,
224 @NonNull MetaschemaBindingConfiguration config) {
225 Objects.requireNonNull(moduleUri, "moduleUri");
226 Objects.requireNonNull(config, "config");
227 return moduleUrlToMetaschemaBindingConfigurationMap.put(moduleUri, config);
228 }
229
230
231
232
233
234
235
236
237
238 public void load(Path file) throws IOException {
239 URL resource = file.toUri().toURL();
240 load(resource);
241 }
242
243
244
245
246
247
248
249
250
251 public void load(File file) throws IOException {
252 URL resource = file.toURI().toURL();
253 load(resource);
254 }
255
256
257
258
259
260
261
262
263
264 public void load(URL resource) throws IOException {
265 MetaschemaBindingsDocument xml;
266 try {
267 xml = MetaschemaBindingsDocument.Factory.parse(resource);
268 } catch (XmlException ex) {
269 throw new IOException(ex);
270 }
271
272 MetaschemaBindingsType bindings = xml.getMetaschemaBindings();
273
274 for (ModelBindingType model : bindings.getModelBindingList()) {
275 processModelBindingConfig(model);
276 }
277
278 for (MetaschemaBindingType metaschema : bindings.getMetaschemaBindingList()) {
279 try {
280 processMetaschemaBindingConfig(resource, metaschema);
281 } catch (MalformedURLException | URISyntaxException ex) {
282 throw new IOException(ex);
283 }
284 }
285 }
286
287 private void processModelBindingConfig(ModelBindingType model) {
288 String namespace = model.getNamespace();
289
290 if (model.isSetJava()) {
291 JavaModelBindingType java = model.getJava();
292 if (java.isSetUsePackageName()) {
293 addModelBindingConfig(namespace, java.getUsePackageName());
294 }
295 }
296 }
297
298 private void processMetaschemaBindingConfig(URL configResource, MetaschemaBindingType metaschema)
299 throws MalformedURLException, URISyntaxException {
300 String href = metaschema.getHref();
301 URL moduleUrl = new URL(configResource, href);
302 String moduleUri = ObjectUtils.notNull(moduleUrl.toURI().toString());
303
304 MetaschemaBindingConfiguration metaschemaConfig = getMetaschemaBindingConfiguration(moduleUri);
305 if (metaschemaConfig == null) {
306 metaschemaConfig = new MetaschemaBindingConfiguration();
307 addMetaschemaBindingConfiguration(moduleUri, metaschemaConfig);
308 }
309 for (ObjectDefinitionBindingType assemblyBinding : metaschema.getDefineAssemblyBindingList()) {
310 String name = ObjectUtils.requireNonNull(assemblyBinding.getName());
311 IDefinitionBindingConfiguration config = metaschemaConfig.getAssemblyDefinitionBindingConfig(name);
312 config = processDefinitionBindingConfiguration(config, assemblyBinding);
313 metaschemaConfig.addAssemblyDefinitionBindingConfig(name, config);
314 }
315
316 for (ObjectDefinitionBindingType fieldBinding : metaschema.getDefineFieldBindingList()) {
317 String name = ObjectUtils.requireNonNull(fieldBinding.getName());
318 IDefinitionBindingConfiguration config = metaschemaConfig.getFieldDefinitionBindingConfig(name);
319 config = processDefinitionBindingConfiguration(config, fieldBinding);
320 metaschemaConfig.addFieldDefinitionBindingConfig(name, config);
321 }
322 }
323
324 @NonNull
325 private static IMutableDefinitionBindingConfiguration processDefinitionBindingConfiguration(
326 @Nullable IDefinitionBindingConfiguration oldConfig,
327 @NonNull ObjectDefinitionBindingType objectDefinitionBinding) {
328 IMutableDefinitionBindingConfiguration config;
329 if (oldConfig != null) {
330 config = new DefaultDefinitionBindingConfiguration(oldConfig);
331 } else {
332 config = new DefaultDefinitionBindingConfiguration();
333 }
334
335 if (objectDefinitionBinding.isSetJava()) {
336 JavaObjectDefinitionBindingType java = objectDefinitionBinding.getJava();
337 if (java.isSetUseClassName()) {
338 config.setClassName(ObjectUtils.notNull(java.getUseClassName()));
339 }
340
341 if (java.isSetExtendBaseClass()) {
342 config.setQualifiedBaseClassName(ObjectUtils.notNull(java.getExtendBaseClass()));
343 }
344
345 for (String interfaceName : java.getImplementInterfaceList()) {
346 config.addInterfaceToImplement(ObjectUtils.notNull(interfaceName));
347 }
348 }
349 return config;
350 }
351
352 public static final class MetaschemaBindingConfiguration {
353 private final Map<String, IDefinitionBindingConfiguration> assemblyBindingConfigs = new ConcurrentHashMap<>();
354 private final Map<String, IDefinitionBindingConfiguration> fieldBindingConfigs = new ConcurrentHashMap<>();
355
356 private MetaschemaBindingConfiguration() {
357 }
358
359
360
361
362
363
364
365
366
367
368 @Nullable
369 public IDefinitionBindingConfiguration getAssemblyDefinitionBindingConfig(@NonNull String name) {
370 return assemblyBindingConfigs.get(name);
371 }
372
373
374
375
376
377
378
379
380
381
382 @Nullable
383 public IDefinitionBindingConfiguration getFieldDefinitionBindingConfig(@NonNull String name) {
384 return fieldBindingConfigs.get(name);
385 }
386
387
388
389
390
391
392
393
394
395
396
397
398 @Nullable
399 public IDefinitionBindingConfiguration addAssemblyDefinitionBindingConfig(@NonNull String name,
400 @NonNull IDefinitionBindingConfiguration config) {
401 return assemblyBindingConfigs.put(name, config);
402 }
403
404
405
406
407
408
409
410
411
412
413
414
415 @Nullable
416 public IDefinitionBindingConfiguration addFieldDefinitionBindingConfig(@NonNull String name,
417 @NonNull IDefinitionBindingConfiguration config) {
418 return fieldBindingConfigs.put(name, config);
419 }
420 }
421 }