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