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 String getClassName(@NonNull IModule module) {
110
111 return ClassUtils.toClassName(module.getShortName() + "Module");
112 }
113
114 @Override
115 public List<String> getQualifiedSuperinterfaceClassNames(IModelDefinition definition) {
116 IDefinitionBindingConfiguration config = getBindingConfigurationForDefinition(definition);
117 return config == null
118 ? CollectionUtil.emptyList()
119 : config.getInterfacesToImplement();
120 }
121
122
123
124
125
126
127
128
129
130
131
132
133
134 public void addModelBindingConfig(String namespace, String packageName) {
135 if (namespaceToPackageNameMap.containsKey(namespace)) {
136 String oldPackageName = namespaceToPackageNameMap.get(namespace);
137 if (!oldPackageName.equals(packageName)) {
138 throw new IllegalStateException(
139 String.format("Attempt to redefine existing package name '%s' to '%s' for namespace '%s'",
140 oldPackageName,
141 packageName,
142 namespace));
143 }
144 } else {
145 namespaceToPackageNameMap.put(namespace, packageName);
146 }
147 }
148
149
150
151
152
153
154
155
156
157
158
159
160 @NonNull
161 protected String getPackageNameForNamespace(@NonNull String namespace) {
162 String packageName = namespaceToPackageNameMap.get(namespace);
163 if (packageName == null) {
164 packageName = ClassUtils.toPackageName(namespace);
165 }
166 return packageName;
167 }
168
169
170
171
172
173
174
175
176
177 protected MetaschemaBindingConfiguration getMetaschemaBindingConfiguration(@NonNull IModule module) {
178 String moduleUri = ObjectUtils.notNull(module.getLocation().toString());
179 return getMetaschemaBindingConfiguration(moduleUri);
180
181 }
182
183
184
185
186
187
188
189
190
191
192 @Nullable
193 protected MetaschemaBindingConfiguration getMetaschemaBindingConfiguration(@NonNull String moduleUri) {
194 return moduleUrlToMetaschemaBindingConfigurationMap.get(moduleUri);
195 }
196
197
198
199
200
201
202
203
204
205
206
207
208 public MetaschemaBindingConfiguration addMetaschemaBindingConfiguration(
209 @NonNull String moduleUri,
210 @NonNull MetaschemaBindingConfiguration config) {
211 Objects.requireNonNull(moduleUri, "moduleUri");
212 Objects.requireNonNull(config, "config");
213 return moduleUrlToMetaschemaBindingConfigurationMap.put(moduleUri, config);
214 }
215
216
217
218
219
220
221
222
223
224 public void load(Path file) throws IOException {
225 URL resource = file.toAbsolutePath().normalize().toUri().toURL();
226 load(resource);
227 }
228
229
230
231
232
233
234
235
236
237 public void load(File file) throws IOException {
238 load(file.toPath());
239 }
240
241
242
243
244
245
246
247
248
249 public void load(URL resource) throws IOException {
250 MetaschemaBindingsDocument xml;
251 try {
252 xml = MetaschemaBindingsDocument.Factory.parse(resource);
253 } catch (XmlException ex) {
254 throw new IOException(ex);
255 }
256
257 MetaschemaBindingsType bindings = xml.getMetaschemaBindings();
258
259 for (ModelBindingType model : bindings.getModelBindingList()) {
260 processModelBindingConfig(model);
261 }
262
263 for (MetaschemaBindingType metaschema : bindings.getMetaschemaBindingList()) {
264 try {
265 processMetaschemaBindingConfig(resource, metaschema);
266 } catch (MalformedURLException | URISyntaxException ex) {
267 throw new IOException(ex);
268 }
269 }
270 }
271
272 private void processModelBindingConfig(ModelBindingType model) {
273 String namespace = model.getNamespace();
274
275 if (model.isSetJava()) {
276 JavaModelBindingType java = model.getJava();
277 if (java.isSetUsePackageName()) {
278 addModelBindingConfig(namespace, java.getUsePackageName());
279 }
280 }
281 }
282
283 private void processMetaschemaBindingConfig(URL configResource, MetaschemaBindingType metaschema)
284 throws MalformedURLException, URISyntaxException {
285 String href = metaschema.getHref();
286 URL moduleUrl = new URL(configResource, href);
287 String moduleUri = ObjectUtils.notNull(moduleUrl.toURI().normalize().toString());
288
289 MetaschemaBindingConfiguration metaschemaConfig = getMetaschemaBindingConfiguration(moduleUri);
290 if (metaschemaConfig == null) {
291 metaschemaConfig = new MetaschemaBindingConfiguration();
292 addMetaschemaBindingConfiguration(moduleUri, metaschemaConfig);
293 }
294 for (ObjectDefinitionBindingType assemblyBinding : metaschema.getDefineAssemblyBindingList()) {
295 String name = ObjectUtils.requireNonNull(assemblyBinding.getName());
296 IDefinitionBindingConfiguration config = metaschemaConfig.getAssemblyDefinitionBindingConfig(name);
297 config = processDefinitionBindingConfiguration(config, assemblyBinding);
298 metaschemaConfig.addAssemblyDefinitionBindingConfig(name, config);
299 }
300
301 for (ObjectDefinitionBindingType fieldBinding : metaschema.getDefineFieldBindingList()) {
302 String name = ObjectUtils.requireNonNull(fieldBinding.getName());
303 IDefinitionBindingConfiguration config = metaschemaConfig.getFieldDefinitionBindingConfig(name);
304 config = processDefinitionBindingConfiguration(config, fieldBinding);
305 metaschemaConfig.addFieldDefinitionBindingConfig(name, config);
306 }
307 }
308
309 @NonNull
310 private static IMutableDefinitionBindingConfiguration processDefinitionBindingConfiguration(
311 @Nullable IDefinitionBindingConfiguration oldConfig,
312 @NonNull ObjectDefinitionBindingType objectDefinitionBinding) {
313 IMutableDefinitionBindingConfiguration config = oldConfig == null
314 ? new DefaultDefinitionBindingConfiguration()
315 : new DefaultDefinitionBindingConfiguration(oldConfig);
316
317 if (objectDefinitionBinding.isSetJava()) {
318 JavaObjectDefinitionBindingType java = objectDefinitionBinding.getJava();
319 if (java.isSetUseClassName()) {
320 config.setClassName(ObjectUtils.notNull(java.getUseClassName()));
321 }
322
323 if (java.isSetExtendBaseClass()) {
324 config.setQualifiedBaseClassName(ObjectUtils.notNull(java.getExtendBaseClass()));
325 }
326
327 for (String interfaceName : java.getImplementInterfaceList()) {
328 config.addInterfaceToImplement(ObjectUtils.notNull(interfaceName));
329 }
330 }
331 return config;
332 }
333
334 public static final class MetaschemaBindingConfiguration {
335 private final Map<String, IDefinitionBindingConfiguration> assemblyBindingConfigs = new ConcurrentHashMap<>();
336 private final Map<String, IDefinitionBindingConfiguration> fieldBindingConfigs = new ConcurrentHashMap<>();
337
338 private MetaschemaBindingConfiguration() {
339 }
340
341
342
343
344
345
346
347
348
349
350 @Nullable
351 public IDefinitionBindingConfiguration getAssemblyDefinitionBindingConfig(@NonNull String name) {
352 return assemblyBindingConfigs.get(name);
353 }
354
355
356
357
358
359
360
361
362
363
364 @Nullable
365 public IDefinitionBindingConfiguration getFieldDefinitionBindingConfig(@NonNull String name) {
366 return fieldBindingConfigs.get(name);
367 }
368
369
370
371
372
373
374
375
376
377
378
379
380 @Nullable
381 public IDefinitionBindingConfiguration addAssemblyDefinitionBindingConfig(@NonNull String name,
382 @NonNull IDefinitionBindingConfiguration config) {
383 return assemblyBindingConfigs.put(name, config);
384 }
385
386
387
388
389
390
391
392
393
394
395
396
397 @Nullable
398 public IDefinitionBindingConfiguration addFieldDefinitionBindingConfig(@NonNull String name,
399 @NonNull IDefinitionBindingConfiguration config) {
400 return fieldBindingConfigs.put(name, config);
401 }
402 }
403 }