1 package org.synchronoss.cpo.core.meta;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 import jakarta.xml.bind.JAXBContext;
26 import jakarta.xml.bind.JAXBElement;
27 import jakarta.xml.bind.JAXBException;
28 import jakarta.xml.bind.Marshaller;
29 import java.io.File;
30 import java.io.OutputStream;
31 import java.io.Writer;
32 import java.lang.reflect.Constructor;
33 import java.lang.reflect.InvocationTargetException;
34 import java.util.ArrayList;
35 import java.util.Collection;
36 import java.util.Collections;
37 import java.util.List;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40 import org.synchronoss.cpo.core.CpoException;
41 import org.synchronoss.cpo.core.cache.CpoMetaDescriptorCache;
42 import org.synchronoss.cpo.core.exporter.CoreMetaXmlObjectExporter;
43 import org.synchronoss.cpo.core.exporter.MetaXmlObjectExporter;
44 import org.synchronoss.cpo.core.helper.CpoClassLoader;
45 import org.synchronoss.cpo.core.helper.ExceptionHelper;
46 import org.synchronoss.cpo.core.helper.XmlHelper;
47 import org.synchronoss.cpo.core.meta.domain.*;
48 import org.synchronoss.cpo.core.parser.ExpressionParser;
49 import org.synchronoss.cpo.cpometa.CtCpoMetaData;
50 import org.synchronoss.cpo.cpometa.ObjectFactory;
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 public class CpoMetaDescriptor extends CpoMetaDescriptorCache
68 implements CpoMetaAdapter, CpoMetaExportable {
69 private static final Logger logger = LoggerFactory.getLogger(CpoMetaDescriptor.class);
70 private String name = null;
71 private boolean caseSensitive = true;
72 private AbstractCpoMetaAdapter metaAdapter = null;
73
74
75 private String defaultPackageName;
76
77 private CpoMetaDescriptor() {}
78
79 protected CpoMetaDescriptor(String name, boolean caseSensitive) throws CpoException {
80 this.name = name;
81 this.caseSensitive = caseSensitive;
82
83
84 try {
85 Class<?> metaAdapterClass = getMetaAdapterClass();
86 logger.debug("Creating MetaAdapter: " + metaAdapterClass.getName());
87 metaAdapter =
88 (AbstractCpoMetaAdapter) metaAdapterClass.getDeclaredConstructor().newInstance();
89 logger.debug("Created MetaAdapter: " + metaAdapterClass.getName());
90 } catch (InstantiationException ie) {
91 throw new CpoException("Could not instantiate CpoMetaAdapter: ", ie);
92 } catch (IllegalAccessException iae) {
93 throw new CpoException("Could not access CpoMetaAdapter: ", iae);
94 } catch (ClassCastException cce) {
95 throw new CpoException(
96 "CpoMetaAdapter must extend AbstractCpoMetaAdapter: "
97 + getMetaAdapterClass().getName()
98 + ":",
99 cce);
100 } catch (InvocationTargetException e) {
101 throw new CpoException(
102 "Could not invoke constructor for CpoMetaAdapter: "
103 + getMetaAdapterClass().getName()
104 + ":",
105 e);
106 } catch (NoSuchMethodException e) {
107 throw new CpoException(
108 "Could not find a default constructor for CpoMetaAdapter: "
109 + getMetaAdapterClass().getName()
110 + ":",
111 e);
112 }
113 }
114
115 protected Class<?> getMetaAdapterClass() throws CpoException {
116 throw new CpoException("getMetaAdapterClass() must be implemented");
117 }
118
119
120
121
122
123
124
125
126 public static boolean isValidMetaDescriptor(CpoMetaDescriptor metaDescriptor) {
127 return findCpoMetaDescriptor(metaDescriptor.getName()) != null;
128 }
129
130
131
132
133
134
135
136
137 public static CpoMetaDescriptor getInstance(String name) throws CpoException {
138 return findCpoMetaDescriptor(name);
139 }
140
141
142
143
144
145
146
147 public static void removeInstance(String name) throws CpoException {
148 removeCpoMetaDescriptor(name);
149 }
150
151
152
153
154
155
156 public static void clearAllInstances() throws CpoException {
157 clearCpoMetaDescriptorCache();
158 }
159
160
161
162
163
164
165
166
167
168
169
170 public static CpoMetaDescriptor getInstance(String name, String metaXml, boolean caseSensitive)
171 throws CpoException {
172 List<String> metaXmls = new ArrayList<>();
173 metaXmls.add(metaXml);
174 return createUpdateInstance(name, metaXmls, caseSensitive);
175 }
176
177
178
179
180
181
182
183
184
185
186
187
188 public static CpoMetaDescriptor getInstance(
189 String name, List<String> metaXmls, boolean caseSensitive) throws CpoException {
190 return createUpdateInstance(name, metaXmls, caseSensitive);
191 }
192
193
194
195
196
197
198
199
200
201
202
203
204 public static CpoMetaDescriptor getInstance(String name, String[] metaXmls, boolean caseSensitive)
205 throws CpoException {
206 return createUpdateInstance(name, metaXmls, caseSensitive);
207 }
208
209
210
211
212
213
214 public static Collection<String> getCpoMetaDescriptorNames() {
215 return CpoMetaDescriptorCache.getCpoMetaDescriptorNames();
216 }
217
218
219
220
221
222
223
224
225
226
227 public static void refreshDescriptorMeta(String name, List<String> metaXmls) throws CpoException {
228 refreshDescriptorMeta(name, metaXmls, false);
229 }
230
231
232
233
234
235
236
237
238
239
240
241 public static void refreshDescriptorMeta(String name, List<String> metaXmls, boolean overwrite)
242 throws CpoException {
243 CpoMetaDescriptor metaDescriptor = findCpoMetaDescriptor(name);
244 if (metaDescriptor != null) {
245 metaDescriptor.refreshDescriptorMeta(metaXmls, overwrite);
246 }
247 }
248
249
250
251
252
253
254
255 public void refreshDescriptorMeta(List<String> metaXmls) throws CpoException {
256 refreshDescriptorMeta(metaXmls, false);
257 }
258
259
260
261
262
263
264
265
266
267 public void refreshDescriptorMeta(List<String> metaXmls, boolean overwrite) throws CpoException {
268 if (overwrite) {
269 getCpoMetaAdapter().removeAllCpoClass();
270 }
271 createUpdateInstance(this.getName(), metaXmls, caseSensitive);
272 }
273
274 protected static CpoMetaDescriptor createUpdateInstance(
275 String name, List<String> metaXmls, boolean caseSensitive) throws CpoException {
276 return createUpdateInstance(name, metaXmls.toArray(new String[0]), caseSensitive);
277 }
278
279 protected static CpoMetaDescriptor createUpdateInstance(
280 String name, String[] metaXmls, boolean caseSensitive) throws CpoException {
281 CpoMetaDescriptor metaDescriptor = findCpoMetaDescriptor(name);
282 String metaDescriptorClassName = null;
283 var errBuilder = new StringBuilder();
284
285 logger.debug("CpoMetaDescriptor: " + metaDescriptor);
286
287 for (String metaXml : metaXmls) {
288 logger.debug("Processing: " + metaXml);
289 errBuilder.setLength(0);
290 CtCpoMetaData ctCpoMetaData =
291 XmlHelper.unmarshalXmlObject(
292 XmlHelper.CPO_META_XSD, metaXml, CtCpoMetaData.class, errBuilder);
293 if (!errBuilder.isEmpty()) {
294 throw new RuntimeException("Error parsing CPO meta XML: " + errBuilder.toString());
295 }
296
297 try {
298 if (metaDescriptor == null) {
299 logger.debug("Getting descriptor name");
300 metaDescriptorClassName = ctCpoMetaData.getMetaDescriptor();
301 logger.debug("Getting the Class");
302 Class<?> clazz = CpoClassLoader.forName(metaDescriptorClassName);
303 logger.debug("Getting the Constructor");
304 Constructor<?> cons = clazz.getConstructor(String.class, boolean.class);
305 logger.debug("Creating the instance");
306 metaDescriptor = (CpoMetaDescriptor) cons.newInstance(name, caseSensitive);
307 logger.debug("Adding the MetaDescriptor");
308 addCpoMetaDescriptor(metaDescriptor);
309 } else if (!metaDescriptor.getClass().getName().equals(ctCpoMetaData.getMetaDescriptor())) {
310 throw new CpoException(
311 "Error processing multiple metaXml files. All files must have the same"
312 + " CpoMetaDescriptor class name.");
313 }
314
315 metaDescriptor.setDefaultPackageName(ctCpoMetaData.getDefaultPackageName());
316 metaDescriptor.getCpoMetaAdapter().loadCpoMetaDataDocument(ctCpoMetaData, caseSensitive);
317 } catch (ClassNotFoundException cnfe) {
318 throw new CpoException(
319 "CpoMetaAdapter not found: "
320 + metaDescriptorClassName
321 + ": "
322 + ExceptionHelper.getLocalizedMessage(cnfe));
323 } catch (IllegalAccessException iae) {
324 throw new CpoException(
325 "Could not access CpoMetaAdapter: "
326 + metaDescriptorClassName
327 + ": "
328 + ExceptionHelper.getLocalizedMessage(iae));
329 } catch (InstantiationException ie) {
330 throw new CpoException(
331 "Could not instantiate CpoMetaAdapter: "
332 + metaDescriptorClassName
333 + ": "
334 + ExceptionHelper.getLocalizedMessage(ie));
335 } catch (InvocationTargetException ite) {
336 throw new CpoException(
337 "Could not invoke constructor: "
338 + metaDescriptorClassName
339 + ": "
340 + ExceptionHelper.getLocalizedMessage(ite));
341 } catch (IllegalArgumentException iae) {
342 throw new CpoException(
343 "Illegal Argument to constructor: "
344 + metaDescriptorClassName
345 + ": "
346 + ExceptionHelper.getLocalizedMessage(iae));
347 } catch (NoSuchMethodException nsme) {
348 throw new CpoException(
349 "Could not find constructor: "
350 + metaDescriptorClassName
351 + ": "
352 + ExceptionHelper.getLocalizedMessage(nsme));
353 } catch (SecurityException se) {
354 throw new CpoException(
355 "Not allowed to access constructor: "
356 + metaDescriptorClassName
357 + ": "
358 + ExceptionHelper.getLocalizedMessage(se));
359 } catch (ClassCastException cce) {
360 throw new CpoException(
361 "Class is not instance of CpoMetaDescriptor: "
362 + metaDescriptorClassName
363 + ":"
364 + ExceptionHelper.getLocalizedMessage(cce));
365 }
366 }
367
368 return metaDescriptor;
369 }
370
371 protected static CpoMetaDescriptor createUpdateInstance(
372 CpoMetaDescriptor metaDescriptor, CpoMetaAdapter metaAdapter) throws CpoException {
373 if (metaDescriptor != null && metaAdapter != null) {
374 addCpoMetaDescriptor(metaDescriptor);
375 }
376 return metaDescriptor;
377 }
378
379 protected AbstractCpoMetaAdapter getCpoMetaAdapter() {
380 return metaAdapter;
381 }
382
383
384 @Override
385 public <T> CpoClass getMetaClass(T bean) throws CpoException {
386 CpoClass cpoClass = getCpoMetaAdapter().getMetaClass(bean);
387 if (cpoClass != null) {
388 cpoClass.loadRunTimeInfo(this);
389 }
390
391 return cpoClass;
392 }
393
394
395 @Override
396 public List<CpoClass> getCpoClasses() throws CpoException {
397 return getCpoMetaAdapter().getCpoClasses();
398 }
399
400
401
402
403
404
405
406 public void addCpoClass(CpoClass cpoClass) throws CpoException {
407 getCpoMetaAdapter().addCpoClass(cpoClass);
408 }
409
410
411
412
413
414
415
416 public void removeCpoClass(CpoClass cpoClass) throws CpoException {
417 getCpoMetaAdapter().removeCpoClass(cpoClass);
418 }
419
420
421 @Override
422 public ExpressionParser getExpressionParser() throws CpoException {
423 return getCpoMetaAdapter().getExpressionParser();
424 }
425
426
427 @Override
428 public String getDataTypeName(CpoAttribute attribute) throws CpoException {
429 return getCpoMetaAdapter().getDataTypeName(attribute);
430 }
431
432
433 @Override
434 public Class<?> getDataTypeJavaClass(CpoAttribute attribute) throws CpoException {
435 return getCpoMetaAdapter().getDataTypeJavaClass(attribute);
436 }
437
438
439 @Override
440 public int getDataTypeInt(String dataTypeName) throws CpoException {
441 return getCpoMetaAdapter().getDataTypeInt(dataTypeName);
442 }
443
444
445 @Override
446 public DataTypeMapEntry<?> getDataTypeMapEntry(int dataTypeInt) throws CpoException {
447 return getCpoMetaAdapter().getDataTypeMapEntry(dataTypeInt);
448 }
449
450
451 @Override
452 public List<String> getAllowableDataTypes() throws CpoException {
453 return getCpoMetaAdapter().getAllowableDataTypes();
454 }
455
456
457
458
459
460
461
462
463 public CpoClass createCpoClass() throws CpoException {
464 return getCpoMetaAdapter().createCpoClass(caseSensitive);
465 }
466
467
468
469
470
471
472
473 public CpoAttribute createCpoAttribute() throws CpoException {
474 return getCpoMetaAdapter().createCpoAttribute();
475 }
476
477
478
479
480
481
482
483 public CpoFunctionGroup createCpoFunctionGroup() throws CpoException {
484 return getCpoMetaAdapter().createCpoFunctionGroup();
485 }
486
487
488
489
490
491
492
493 public CpoFunction createCpoFunction() throws CpoException {
494 return getCpoMetaAdapter().createCpoFunction();
495 }
496
497
498
499
500
501
502
503 public CpoArgument createCpoArgument() throws CpoException {
504 return getCpoMetaAdapter().createCpoArgument();
505 }
506
507
508
509
510
511
512
513 public String getDefaultPackageName() {
514 return defaultPackageName;
515 }
516
517
518
519
520
521
522
523 public void setDefaultPackageName(String packageName) {
524 if (packageName != null) {
525 defaultPackageName = packageName;
526 }
527 }
528
529
530
531
532
533
534 public String getName() {
535 return name;
536 }
537
538 protected MetaXmlObjectExporter getMetaXmlObjectExporter() {
539 return new CoreMetaXmlObjectExporter(this);
540 }
541
542 protected final CtCpoMetaData buildCpoMetaData() {
543 MetaXmlObjectExporter metaXmlObjectExporter = getMetaXmlObjectExporter();
544
545
546 List<CpoClass> classList = new ArrayList<>();
547 classList.addAll(getCpoMetaAdapter().getCpoClasses());
548 Collections.sort(classList);
549 for (CpoClass cpoClass : classList) {
550 cpoClass.acceptMetaDFVisitor(metaXmlObjectExporter);
551 }
552 return metaXmlObjectExporter.getCpoMetaData();
553 }
554
555 private JAXBElement<CtCpoMetaData> getJaxbElement(CtCpoMetaData ctCpoMetaData) {
556 ObjectFactory factory = new ObjectFactory();
557 return factory.createCpoMetaData(ctCpoMetaData);
558 }
559
560 private Marshaller createMarshaller() throws JAXBException {
561 JAXBContext jaxbContext = JAXBContext.newInstance(CtCpoMetaData.class);
562 Marshaller marshaller = jaxbContext.createMarshaller();
563 XmlHelper.setMarshallerProperties(marshaller);
564 return marshaller;
565 }
566
567
568 @Override
569 public final void export(File file) throws CpoException {
570 try {
571 CtCpoMetaData ctCpoMetaData = buildCpoMetaData();
572 Marshaller marshaller = createMarshaller();
573 marshaller.marshal(getJaxbElement(ctCpoMetaData), file);
574 } catch (JAXBException ex) {
575 throw new CpoException(ex);
576 }
577 }
578
579
580 @Override
581 public final void export(Writer writer) throws CpoException {
582 try {
583 CtCpoMetaData ctCpoMetaData = buildCpoMetaData();
584 Marshaller marshaller = createMarshaller();
585 marshaller.marshal(getJaxbElement(ctCpoMetaData), writer);
586 } catch (JAXBException ex) {
587 throw new CpoException(ex);
588 }
589 }
590
591
592 @Override
593 public final void export(OutputStream outputStream) throws CpoException {
594 try {
595 CtCpoMetaData ctCpoMetaData = buildCpoMetaData();
596 Marshaller marshaller = createMarshaller();
597 marshaller.marshal(getJaxbElement(ctCpoMetaData), outputStream);
598 } catch (JAXBException ex) {
599 throw new CpoException(ex);
600 }
601 }
602
603
604
605
606
607
608 public boolean isCaseSensitive() {
609 return caseSensitive;
610 }
611 }