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.DataTypeService;
30 import gov.nist.secauto.metaschema.core.datatype.IDataTypeAdapter;
31 import gov.nist.secauto.metaschema.core.model.IModule;
32 import gov.nist.secauto.metaschema.core.model.constraint.IConstraintSet;
33 import gov.nist.secauto.metaschema.core.util.CollectionUtil;
34 import gov.nist.secauto.metaschema.core.util.ObjectUtils;
35 import gov.nist.secauto.metaschema.databind.io.BindingException;
36 import gov.nist.secauto.metaschema.databind.io.DefaultBoundLoader;
37 import gov.nist.secauto.metaschema.databind.io.Format;
38 import gov.nist.secauto.metaschema.databind.io.IBoundLoader;
39 import gov.nist.secauto.metaschema.databind.io.IDeserializer;
40 import gov.nist.secauto.metaschema.databind.io.ISerializer;
41 import gov.nist.secauto.metaschema.databind.io.json.DefaultJsonDeserializer;
42 import gov.nist.secauto.metaschema.databind.io.json.DefaultJsonSerializer;
43 import gov.nist.secauto.metaschema.databind.io.xml.DefaultXmlDeserializer;
44 import gov.nist.secauto.metaschema.databind.io.xml.DefaultXmlSerializer;
45 import gov.nist.secauto.metaschema.databind.io.yaml.DefaultYamlDeserializer;
46 import gov.nist.secauto.metaschema.databind.io.yaml.DefaultYamlSerializer;
47 import gov.nist.secauto.metaschema.databind.model.IAssemblyClassBinding;
48 import gov.nist.secauto.metaschema.databind.model.IClassBinding;
49
50 import java.util.LinkedList;
51 import java.util.List;
52 import java.util.Map;
53 import java.util.Objects;
54 import java.util.Set;
55
56 import javax.xml.namespace.QName;
57
58 import edu.umd.cs.findbugs.annotations.NonNull;
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74 public class DefaultBindingContext implements IBindingContext {
75 private static DefaultBindingContext singleton;
76 @NonNull
77 private final IModuleLoaderStrategy moduleLoaderStrategy;
78 @NonNull
79 private final List<IBindingMatcher> bindingMatchers = new LinkedList<>();
80
81
82
83
84
85
86 @NonNull
87 public static DefaultBindingContext instance() {
88 synchronized (DefaultBindingContext.class) {
89 if (singleton == null) {
90 singleton = new DefaultBindingContext();
91 }
92 }
93 return ObjectUtils.notNull(singleton);
94 }
95
96
97
98
99
100
101
102 public DefaultBindingContext(@NonNull Set<IConstraintSet> externalConstraintSets) {
103
104 moduleLoaderStrategy = new ExternalConstraintsModuleLoaderStrategy(this, externalConstraintSets);
105 }
106
107
108
109
110 public DefaultBindingContext() {
111
112 moduleLoaderStrategy = new SimpleModuleLoaderStrategy(this);
113 }
114
115 @Override
116 public IModule getModuleByClass(@NonNull Class<? extends IModule> clazz) {
117 return moduleLoaderStrategy.getModuleByClass(clazz);
118 }
119
120 @Override
121 public IClassBinding getClassBinding(@NonNull Class<?> clazz) {
122 return moduleLoaderStrategy.getClassBinding(clazz);
123 }
124
125 @Override
126 public Map<Class<?>, IClassBinding> getClassBindingsByClass() {
127 return moduleLoaderStrategy.getClassBindingsByClass();
128 }
129
130 @Override
131 public <TYPE extends IDataTypeAdapter<?>> TYPE getJavaTypeAdapterInstance(@NonNull Class<TYPE> clazz) {
132 return DataTypeService.getInstance().getJavaTypeAdapterByClass(clazz);
133 }
134
135
136
137
138
139
140 @Override
141 public <CLASS> ISerializer<CLASS> newSerializer(@NonNull Format format, @NonNull Class<CLASS> clazz) {
142 Objects.requireNonNull(format, "format");
143 IAssemblyClassBinding classBinding = (IAssemblyClassBinding) getClassBinding(clazz);
144 if (classBinding == null) {
145 throw new IllegalStateException(String.format("Class '%s' is not bound", clazz.getClass().getName()));
146 }
147 ISerializer<CLASS> retval;
148 switch (format) {
149 case JSON:
150 retval = new DefaultJsonSerializer<>(classBinding);
151 break;
152 case XML:
153 retval = new DefaultXmlSerializer<>(classBinding);
154 break;
155 case YAML:
156 retval = new DefaultYamlSerializer<>(classBinding);
157 break;
158 default:
159 throw new UnsupportedOperationException(String.format("Unsupported format '%s'", format));
160 }
161 return retval;
162 }
163
164
165
166
167
168
169 @Override
170 public <CLASS> IDeserializer<CLASS> newDeserializer(@NonNull Format format, @NonNull Class<CLASS> clazz) {
171 IAssemblyClassBinding classBinding = (IAssemblyClassBinding) getClassBinding(clazz);
172 if (classBinding == null) {
173 throw new IllegalStateException(String.format("Class '%s' is not bound", clazz.getName()));
174 }
175 IDeserializer<CLASS> retval;
176 switch (format) {
177 case JSON:
178 retval = new DefaultJsonDeserializer<>(classBinding);
179 break;
180 case XML:
181 retval = new DefaultXmlDeserializer<>(classBinding);
182 break;
183 case YAML:
184 retval = new DefaultYamlDeserializer<>(classBinding);
185 break;
186 default:
187 throw new UnsupportedOperationException(String.format("Unsupported format '%s'", format));
188 }
189
190 return retval;
191 }
192
193 @Override
194 public DefaultBindingContext registerBindingMatcher(@NonNull IBindingMatcher matcher) {
195 synchronized (this) {
196 bindingMatchers.add(matcher);
197 }
198 return this;
199 }
200
201
202
203
204
205
206
207 @NonNull
208 protected List<? extends IBindingMatcher> getBindingMatchers() {
209 synchronized (this) {
210 return CollectionUtil.unmodifiableList(bindingMatchers);
211 }
212 }
213
214 @Override
215 public Class<?> getBoundClassForXmlQName(@NonNull QName rootQName) {
216 Class<?> retval = null;
217 for (IBindingMatcher matcher : getBindingMatchers()) {
218 retval = matcher.getBoundClassForXmlQName(rootQName);
219 if (retval != null) {
220 break;
221 }
222 }
223 return retval;
224 }
225
226 @Override
227 public Class<?> getBoundClassForJsonName(@NonNull String rootName) {
228 Class<?> retval = null;
229 for (IBindingMatcher matcher : getBindingMatchers()) {
230 retval = matcher.getBoundClassForJsonName(rootName);
231 if (retval != null) {
232 break;
233 }
234 }
235 return retval;
236 }
237
238 @Override
239 public IBoundLoader newBoundLoader() {
240 return new DefaultBoundLoader(this);
241 }
242
243 @Override
244 public <CLASS> CLASS copyBoundObject(@NonNull CLASS other, Object parentInstance) throws BindingException {
245 IClassBinding classBinding = getClassBinding(other.getClass());
246 if (classBinding == null) {
247 throw new IllegalStateException(String.format("Class '%s' is not bound", other.getClass().getName()));
248 }
249 @SuppressWarnings("unchecked") CLASS retval = (CLASS) classBinding.copyBoundObject(other, parentInstance);
250 return retval;
251 }
252 }