1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.service.impl;
17
18 import java.beans.PropertyDescriptor;
19 import java.lang.reflect.InvocationTargetException;
20 import java.util.ArrayList;
21 import java.util.Collection;
22 import java.util.HashMap;
23 import java.util.Iterator;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Vector;
27
28 import org.apache.commons.beanutils.PropertyUtils;
29 import org.apache.commons.lang.StringUtils;
30 import org.apache.ojb.broker.metadata.ClassDescriptor;
31 import org.apache.ojb.broker.metadata.CollectionDescriptor;
32 import org.apache.ojb.broker.metadata.FieldDescriptor;
33 import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
34 import org.apache.ojb.broker.metadata.SuperReferenceDescriptor;
35 import org.kuali.rice.krad.bo.BusinessObjectRelationship;
36 import org.kuali.rice.krad.bo.PersistableBusinessObject;
37 import org.kuali.rice.krad.exception.ClassNotPersistableException;
38 import org.kuali.rice.krad.exception.IntrospectionException;
39 import org.kuali.rice.krad.exception.ObjectNotABusinessObjectRuntimeException;
40 import org.kuali.rice.krad.exception.ReferenceAttributeDoesntExistException;
41 import org.kuali.rice.krad.exception.ReferenceAttributeNotAnOjbReferenceException;
42 import org.kuali.rice.krad.service.PersistenceStructureService;
43 import org.kuali.rice.krad.util.ForeignKeyFieldsPopulationState;
44 import org.kuali.rice.krad.util.spring.Cached;
45
46 public class PersistenceStructureServiceOjbImpl extends PersistenceServiceImplBase implements PersistenceStructureService {
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 public static Map<Class, Class> referenceConversionMap = new HashMap<Class, Class>();
64
65
66 private PersistenceStructureService persistenceStructureServiceJpa;
67
68 public PersistenceStructureService getPersistenceStructureServiceJpa() {
69 return this.persistenceStructureServiceJpa;
70 }
71
72 public void setPersistenceStructureServiceJpa(PersistenceStructureService persistenceStructureServiceJpa) {
73 this.persistenceStructureServiceJpa = persistenceStructureServiceJpa;
74 }
75
76
77
78
79 @Cached
80 public boolean isPersistable(Class clazz) {
81 boolean isPersistable = false;
82 try {
83 if (getClassDescriptor(clazz) != null) {
84 isPersistable = true;
85 }
86 } catch (ClassNotPersistableException e) {
87 isPersistable = false;
88 }
89 return isPersistable;
90 }
91
92
93
94
95 @Cached
96 public List getPrimaryKeys(Class clazz) {
97 List pkList = new ArrayList();
98 ClassDescriptor classDescriptor = getClassDescriptor(clazz);
99 FieldDescriptor keyDescriptors[] = classDescriptor.getPkFields();
100 for (int i = 0; i < keyDescriptors.length; ++i) {
101 FieldDescriptor keyDescriptor = keyDescriptors[i];
102 pkList.add(keyDescriptor.getAttributeName());
103 }
104 return pkList;
105 }
106
107
108
109
110 @Cached
111 public List listFieldNames(Class clazz) {
112 List fieldNames = new ArrayList();
113 ClassDescriptor classDescriptor = getClassDescriptor(clazz);
114 FieldDescriptor fieldDescriptors[] = classDescriptor.getFieldDescriptions();
115 for (int i = 0; i < fieldDescriptors.length; ++i) {
116 FieldDescriptor fieldDescriptor = fieldDescriptors[i];
117 fieldNames.add(fieldDescriptor.getAttributeName());
118 }
119 return fieldNames;
120 }
121
122
123
124
125
126 public Object clearPrimaryKeyFields(Object persistableObject) {
127 if (persistableObject == null) {
128 throw new IllegalArgumentException("invalid (null) persistableObject");
129 }
130
131 String className = null;
132 String fieldName = null;
133 try {
134 className = persistableObject.getClass().getName();
135 List fields = listPrimaryKeyFieldNames(persistableObject.getClass());
136 for (Iterator i = fields.iterator(); i.hasNext();) {
137 fieldName = (String) i.next();
138
139 PropertyUtils.setProperty(persistableObject, fieldName, null);
140 }
141
142 if (persistableObject instanceof PersistableBusinessObject) {
143 ((PersistableBusinessObject) persistableObject).setObjectId(null);
144 }
145 } catch (NoSuchMethodException e) {
146 throw new IntrospectionException("no setter for property '" + className + "." + fieldName + "'", e);
147 } catch (IllegalAccessException e) {
148 throw new IntrospectionException("problem accessing property '" + className + "." + fieldName + "'", e);
149 } catch (InvocationTargetException e) {
150 throw new IntrospectionException("problem invoking getter for property '" + className + "." + fieldName + "'", e);
151 }
152
153 return persistableObject;
154 }
155
156
157
158
159 @Cached
160
161 public List listPersistableSubclasses(Class superclazz) {
162 if (superclazz == null) {
163 throw new IllegalArgumentException("invalid (null) uberclass");
164 }
165
166 Map allDescriptors = getDescriptorRepository().getDescriptorTable();
167 List persistableSubclasses = new ArrayList();
168 for (Iterator i = allDescriptors.entrySet().iterator(); i.hasNext();) {
169 Map.Entry e = (Map.Entry) i.next();
170
171 Class persistableClass = ((ClassDescriptor) e.getValue()).getClassOfObject();
172 if (!superclazz.equals(persistableClass) && superclazz.isAssignableFrom(persistableClass)) {
173 persistableSubclasses.add(persistableClass);
174 }
175 }
176 return persistableSubclasses;
177 }
178
179
180
181
182
183 @Cached
184 public Map<String, BusinessObjectRelationship> getRelationshipMetadata(Class persistableClass, String attributeName, String attributePrefix) {
185 if (persistableClass == null) {
186 throw new IllegalArgumentException("invalid (null) persistableClass");
187 }
188 if (StringUtils.isBlank(attributeName)) {
189 throw new IllegalArgumentException("invalid (blank) attributeName");
190 }
191
192 Map<String, BusinessObjectRelationship> relationships = new HashMap<String, BusinessObjectRelationship>();
193 ClassDescriptor classDescriptor = getClassDescriptor(persistableClass);
194 Vector<ObjectReferenceDescriptor> references = classDescriptor.getObjectReferenceDescriptors();
195 for (ObjectReferenceDescriptor objRef : references) {
196 Vector fks = objRef.getForeignKeyFields();
197 if (fks.contains(attributeName) || objRef.getAttributeName().equals(attributeName)) {
198 Map<String, String> fkToPkRefs = getForeignKeysForReference(persistableClass, objRef.getAttributeName());
199 BusinessObjectRelationship rel = new BusinessObjectRelationship(persistableClass, objRef.getAttributeName(), objRef.getItemClass());
200 for (Map.Entry<String, String> ref : fkToPkRefs.entrySet()) {
201 if (StringUtils.isBlank(attributePrefix)) {
202 rel.getParentToChildReferences().put(ref.getKey(), ref.getValue());
203 } else {
204 rel.getParentToChildReferences().put(attributePrefix + "." + ref.getKey(), ref.getValue());
205 }
206 }
207 relationships.put(objRef.getAttributeName(), rel);
208 }
209 }
210 return relationships;
211 }
212
213 @Cached
214
215 public Map<String, BusinessObjectRelationship> getRelationshipMetadata(Class persistableClass, String attributeName) {
216 return getRelationshipMetadata(persistableClass, attributeName, null);
217 }
218
219
220
221
222
223 @Cached
224 public String getForeignKeyFieldName(Class persistableObjectClass, String attributeName, String pkName) {
225 String fkName = "";
226 ClassDescriptor classDescriptor = getClassDescriptor(persistableObjectClass);
227 ObjectReferenceDescriptor objectReferenceDescriptor = classDescriptor.getObjectReferenceDescriptorByName(attributeName);
228 if (objectReferenceDescriptor == null) {
229 throw new RuntimeException("Attribute name " + attributeName + " is not a valid reference to class " + persistableObjectClass.getName());
230 }
231 ClassDescriptor referenceDescriptor = this.getClassDescriptor(objectReferenceDescriptor.getItemClass());
232
233 FieldDescriptor[] fkFields = objectReferenceDescriptor.getForeignKeyFieldDescriptors(classDescriptor);
234 FieldDescriptor[] pkFields = referenceDescriptor.getPkFields();
235 for (int i = 0; i < pkFields.length; i++) {
236 FieldDescriptor pkField = pkFields[i];
237 if (pkField.getAttributeName().equals(pkName)) {
238 fkName = fkFields[i].getAttributeName();
239 }
240 }
241 return fkName;
242 }
243
244
245
246
247
248 @Cached
249 public Map getReferencesForForeignKey(Class persistableObjectClass, String attributeName) {
250 Map referenceClasses = new HashMap();
251 if (PersistableBusinessObject.class.isAssignableFrom(persistableObjectClass)) {
252 ClassDescriptor classDescriptor = getClassDescriptor(persistableObjectClass);
253 Vector objectReferences = classDescriptor.getObjectReferenceDescriptors();
254 for (Iterator iter = objectReferences.iterator(); iter.hasNext();) {
255 ObjectReferenceDescriptor referenceDescriptor = (ObjectReferenceDescriptor) iter.next();
256
257
258
259
260
261 FieldDescriptor[] refFkNames = referenceDescriptor.getForeignKeyFieldDescriptors(classDescriptor);
262 for (int i = 0; i < refFkNames.length; i++) {
263 FieldDescriptor fkField = refFkNames[i];
264 if (fkField.getAttributeName().equals(attributeName)) {
265 referenceClasses.put(referenceDescriptor.getAttributeName(), referenceDescriptor.getItemClass());
266 }
267 }
268 }
269 }
270 return referenceClasses;
271 }
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289 @Cached
290 public Map getForeignKeysForReference(Class clazz, String attributeName) {
291
292 if (clazz == null) {
293 throw new IllegalArgumentException("The Class passed in for the clazz argument was null.");
294 }
295 if (attributeName == null) {
296 throw new IllegalArgumentException("The String passed in for the attributeName argument was null.");
297 }
298
299
300 Class attributeClass = getBusinessObjectAttributeClass(clazz, attributeName);
301 if (attributeClass == null) {
302 throw new ReferenceAttributeDoesntExistException("Requested attribute: '" + attributeName + "' does not exist " + "on class: '" + clazz.getName() + "'.");
303 }
304
305
306
307 if (!PersistableBusinessObject.class.isAssignableFrom(attributeClass)) {
308 throw new ObjectNotABusinessObjectRuntimeException("Attribute requested (" + attributeName + ") is of class: " + "'" + attributeClass.getName() + "' and is not a " + "descendent of BusinessObject. Only descendents of BusinessObject " + "can be used.");
309 }
310
311 Map fkMap = new HashMap();
312
313
314
315
316 ClassDescriptor classDescriptor = getClassDescriptor(clazz);
317 ObjectReferenceDescriptor referenceDescriptor = classDescriptor.getObjectReferenceDescriptorByName(attributeName);
318 if (referenceDescriptor == null) {
319 throw new ReferenceAttributeNotAnOjbReferenceException("Attribute requested (" + attributeName + ") is not listed " + "in OJB as a reference-descriptor for class: '" + clazz.getName() + "'");
320 }
321
322
323
324
325
326
327 if (!attributeClass.equals(referenceDescriptor.getItemClass())) {
328
329 if (referenceConversionMap.containsKey(attributeClass)) {
330 attributeClass = referenceConversionMap.get(attributeClass);
331 } else {
332 throw new RuntimeException("The Class of the Java member [" + attributeClass.getName() + "] '" + attributeName + "' does not match the class of the " + "reference-descriptor [" + referenceDescriptor.getItemClass().getName() + "]. " + "This is an unhandled special case for which special code needs to be written " + "in this class.");
333 }
334 }
335
336
337
338 Vector fkFields = referenceDescriptor.getForeignKeyFields();
339 Iterator fkIterator = fkFields.iterator();
340
341
342
343 List pkFields = getPrimaryKeys(attributeClass);
344 Iterator pkIterator = pkFields.iterator();
345
346
347
348 if (pkFields.size() != fkFields.size()) {
349 throw new RuntimeException("KualiPersistenceStructureService Error: The number of " + "foreign keys doesnt match the number of primary keys. This may be a " + "result of misconfigured OJB-repository files.");
350 }
351
352
353 while (fkIterator.hasNext()) {
354
355
356
357 if (!pkIterator.hasNext()) {
358 throw new RuntimeException("The number of foriegn keys dont match the number of primary " + "keys for the reference '" + attributeName + "', on BO of type '" + clazz.getName() + "'. " + "This should never happen under normal circumstances, as it means that the OJB repository " + "files are misconfigured.");
359 }
360
361
362 String fkFieldName = (String) fkIterator.next();
363 String pkFieldName = (String) pkIterator.next();
364
365
366 fkMap.put(fkFieldName, pkFieldName);
367 }
368
369 return fkMap;
370 }
371
372 @Cached
373 public Map<String, String> getInverseForeignKeysForCollection(Class boClass, String collectionName) {
374
375 if (boClass == null) {
376 throw new IllegalArgumentException("The Class passed in for the boClass argument was null.");
377 }
378 if (collectionName == null) {
379 throw new IllegalArgumentException("The String passed in for the attributeName argument was null.");
380 }
381
382 PropertyDescriptor propertyDescriptor = null;
383
384
385 Object classInstance;
386 try {
387 classInstance = boClass.newInstance();
388 } catch (Exception e) {
389 throw new RuntimeException(e);
390 }
391
392
393 try {
394 propertyDescriptor = PropertyUtils.getPropertyDescriptor(classInstance, collectionName);
395 } catch (Exception e) {
396 throw new RuntimeException(e);
397 }
398 if (propertyDescriptor == null) {
399 throw new ReferenceAttributeDoesntExistException("Requested attribute: '" + collectionName + "' does not exist " + "on class: '" + boClass.getName() + "'. GFK");
400 }
401
402
403 Class attributeClass = propertyDescriptor.getPropertyType();
404
405
406
407 if (!Collection.class.isAssignableFrom(attributeClass)) {
408 throw new ObjectNotABusinessObjectRuntimeException("Attribute requested (" + collectionName + ") is of class: " + "'" + attributeClass.getName() + "' and is not a " + "descendent of Collection");
409 }
410
411
412
413
414 ClassDescriptor classDescriptor = getClassDescriptor(boClass);
415 CollectionDescriptor collectionDescriptor = classDescriptor.getCollectionDescriptorByName(collectionName);
416
417
418
419
420
421
422 List parentForeignKeys = getPrimaryKeys(boClass);
423 Vector childPrimaryKeysLegacy = collectionDescriptor.getForeignKeyFields();
424
425 if (parentForeignKeys.size() != childPrimaryKeysLegacy.size()) {
426 throw new RuntimeException("The number of keys in the class descriptor and the inverse foreign key mapping for the collection descriptors do not match.");
427 }
428
429 Map<String, String> fkToPkMap = new HashMap<String, String>();
430
431 Iterator pFKIter = parentForeignKeys.iterator();
432 Iterator cPKIterator = childPrimaryKeysLegacy.iterator();
433
434 while (pFKIter.hasNext()) {
435 String parentForeignKey = (String) pFKIter.next();
436 String childPrimaryKey = (String) cPKIterator.next();
437
438 fkToPkMap.put(parentForeignKey, childPrimaryKey);
439 }
440
441 return fkToPkMap;
442 }
443
444
445
446
447 @Cached
448 public Map getNestedForeignKeyMap(Class persistableObjectClass) {
449 Map fkMap = new HashMap();
450 ClassDescriptor classDescriptor = getClassDescriptor(persistableObjectClass);
451 Vector objectReferences = classDescriptor.getObjectReferenceDescriptors();
452 for (Iterator iter = objectReferences.iterator(); iter.hasNext();) {
453 ObjectReferenceDescriptor objectReferenceDescriptor = (ObjectReferenceDescriptor) iter.next();
454 ClassDescriptor referenceDescriptor = this.getClassDescriptor(objectReferenceDescriptor.getItemClass());
455
456 FieldDescriptor[] fkFields = objectReferenceDescriptor.getForeignKeyFieldDescriptors(classDescriptor);
457 FieldDescriptor[] pkFields = referenceDescriptor.getPkFields();
458 for (int i = 0; i < pkFields.length; i++) {
459 FieldDescriptor pkField = pkFields[i];
460 fkMap.put(objectReferenceDescriptor.getAttributeName() + "." + pkField.getAttributeName(), fkFields[i].getAttributeName());
461 }
462 }
463
464 return fkMap;
465 }
466
467
468
469
470 public boolean hasPrimaryKeyFieldValues(Object persistableObject) {
471 Map keyFields = getPrimaryKeyFieldValues(persistableObject);
472
473 boolean emptyField = false;
474 for (Iterator i = keyFields.entrySet().iterator(); !emptyField && i.hasNext();) {
475 Map.Entry e = (Map.Entry) i.next();
476
477 Object fieldValue = e.getValue();
478 if (fieldValue == null) {
479 emptyField = true;
480 } else if (fieldValue instanceof String) {
481 if (StringUtils.isEmpty((String) fieldValue)) {
482 emptyField = true;
483 } else {
484 emptyField = false;
485 }
486 }
487 }
488
489 return !emptyField;
490 }
491
492
493
494
495
496 public ForeignKeyFieldsPopulationState getForeignKeyFieldsPopulationState(PersistableBusinessObject bo, String referenceName) {
497 boolean allFieldsPopulated = true;
498 boolean anyFieldsPopulated = false;
499 List<String> unpopulatedFields = new ArrayList<String>();
500
501
502 if (bo == null) {
503 throw new IllegalArgumentException("The Class passed in for the BusinessObject argument was null.");
504 }
505 if (StringUtils.isBlank(referenceName)) {
506 throw new IllegalArgumentException("The String passed in for the referenceName argument was null or empty.");
507 }
508
509 PropertyDescriptor propertyDescriptor = null;
510
511
512 try {
513 propertyDescriptor = PropertyUtils.getPropertyDescriptor(bo, referenceName);
514 } catch (Exception e) {
515 throw new RuntimeException(e);
516 }
517 if (propertyDescriptor == null) {
518 throw new ReferenceAttributeDoesntExistException("Requested attribute: '" + referenceName + "' does not exist " + "on class: '" + bo.getClass().getName() + "'.");
519 }
520
521
522 Class referenceClass = propertyDescriptor.getPropertyType();
523
524
525
526 if (!PersistableBusinessObject.class.isAssignableFrom(referenceClass)) {
527 throw new ObjectNotABusinessObjectRuntimeException("Attribute requested (" + referenceName + ") is of class: " + "'" + referenceClass.getName() + "' and is not a " + "descendent of BusinessObject. Only descendents of BusinessObject " + "can be used.");
528 }
529
530
531
532
533
534 ClassDescriptor classDescriptor = getClassDescriptor(bo.getClass());
535
536
537 ObjectReferenceDescriptor referenceDescriptor = classDescriptor.getObjectReferenceDescriptorByName(referenceName);
538 if (referenceDescriptor == null) {
539 throw new ReferenceAttributeNotAnOjbReferenceException("Attribute requested (" + referenceName + ") is not listed " + "in OJB as a reference-descriptor for class: '" + bo.getClass().getName() + "'");
540 }
541
542
543 Vector fkFieldsLegacy = referenceDescriptor.getForeignKeyFields();
544 Iterator fkIteratorLegacy = fkFieldsLegacy.iterator();
545
546
547 while (fkIteratorLegacy.hasNext()) {
548
549
550 String fkFieldName = (String) fkIteratorLegacy.next();
551
552
553 Object fkFieldValue = null;
554 try {
555 fkFieldValue = PropertyUtils.getSimpleProperty(bo, fkFieldName);
556 }
557
558
559 catch (Exception e) {
560 throw new RuntimeException(e);
561 }
562
563
564 if (fkFieldValue == null) {
565 allFieldsPopulated = false;
566 unpopulatedFields.add(fkFieldName);
567 } else if (fkFieldValue instanceof String) {
568 if (StringUtils.isBlank((String) fkFieldValue)) {
569 allFieldsPopulated = false;
570 unpopulatedFields.add(fkFieldName);
571 } else {
572 anyFieldsPopulated = true;
573 }
574 } else {
575 anyFieldsPopulated = true;
576 }
577 }
578
579
580
581 if (allFieldsPopulated) {
582 if (!unpopulatedFields.isEmpty()) {
583 throw new RuntimeException("The flag is set that indicates all fields are populated, but there " + "are fields present in the unpopulatedFields list. This should never happen, and indicates " + "that the logic in this method is broken.");
584 }
585 }
586
587 return new ForeignKeyFieldsPopulationState(allFieldsPopulated, anyFieldsPopulated, unpopulatedFields);
588 }
589
590
591
592
593 @Cached
594 public Map<String, Class> listReferenceObjectFields(Class boClass) {
595
596 if (boClass == null) {
597 throw new IllegalArgumentException("Class specified in the parameter was null.");
598 }
599 if (!PersistableBusinessObject.class.isAssignableFrom(boClass)) {
600 throw new IllegalArgumentException("Class specified [" + boClass.getName() + "] must be a class that " + "inherits from BusinessObject.");
601 }
602
603 Map<String, Class> references = new HashMap<String, Class>();
604 ClassDescriptor classDescriptor = getClassDescriptor(boClass);
605 Collection<ObjectReferenceDescriptor> referenceDescriptors = classDescriptor.getObjectReferenceDescriptors(true);
606
607 for (ObjectReferenceDescriptor referenceDescriptor : referenceDescriptors) {
608
609
610
611
612 String superReferenceDescriptor = referenceDescriptor.getAttributeName();
613 if (!SuperReferenceDescriptor.SUPER_FIELD_INTERNAL_NAME.equals(superReferenceDescriptor)) {
614 references.put(superReferenceDescriptor, referenceDescriptor.getItemClass());
615 }
616 }
617
618 return references;
619 }
620
621 @Cached
622 public Map<String, Class> listCollectionObjectTypes(Class boClass) {
623 if (boClass == null) {
624 throw new IllegalArgumentException("Class specified in the parameter was null.");
625 }
626
627 Map<String, Class> references = new HashMap<String, Class>();
628 ClassDescriptor classDescriptor = null;
629 try {
630 classDescriptor = getClassDescriptor(boClass);
631 } catch (ClassNotPersistableException cnpe) {
632 return references;
633 }
634
635 Collection<CollectionDescriptor> collectionDescriptors = classDescriptor.getCollectionDescriptors(true);
636 for (CollectionDescriptor collectionDescriptor : collectionDescriptors) {
637 references.put(collectionDescriptor.getAttributeName(), collectionDescriptor.getItemClass());
638 }
639
640 return references;
641 }
642
643 public Map<String, Class> listCollectionObjectTypes(PersistableBusinessObject bo) {
644
645 if (bo == null) {
646 throw new IllegalArgumentException("BO specified in the parameter was null.");
647 }
648 if (!(bo instanceof PersistableBusinessObject)) {
649 throw new IllegalArgumentException("BO specified [" + bo.getClass().getName() + "] must be a class that " + "inherits from BusinessObject.");
650 }
651
652 return listCollectionObjectTypes(bo.getClass());
653 }
654
655
656
657
658 public Map<String, Class> listReferenceObjectFields(PersistableBusinessObject bo) {
659
660 if (bo == null) {
661 throw new IllegalArgumentException("BO specified in the parameter was null.");
662 }
663 if (!(bo instanceof PersistableBusinessObject)) {
664 throw new IllegalArgumentException("BO specified [" + bo.getClass().getName() + "] must be a class that " + "inherits from BusinessObject.");
665 }
666
667 return listReferenceObjectFields(bo.getClass());
668 }
669
670 @Cached
671 public boolean isReferenceUpdatable(Class boClass, String referenceName) {
672 ClassDescriptor classDescriptor = getClassDescriptor(boClass);
673 ObjectReferenceDescriptor refDesc = classDescriptor.getObjectReferenceDescriptorByName(referenceName);
674 return refDesc.getCascadingStore() != ObjectReferenceDescriptor.CASCADE_NONE;
675 }
676
677 @Cached
678 public boolean isCollectionUpdatable(Class boClass, String collectionName) {
679 ClassDescriptor cd = getClassDescriptor(boClass);
680 CollectionDescriptor collDesc = cd.getCollectionDescriptorByName(collectionName);
681 return collDesc.getCascadingStore() != ObjectReferenceDescriptor.CASCADE_NONE;
682 }
683
684 @Cached
685 public boolean hasCollection(Class boClass, String collectionName) {
686 ClassDescriptor cd = getClassDescriptor(boClass);
687 return cd.getCollectionDescriptorByName(collectionName) != null;
688 }
689
690 @Cached
691 public boolean hasReference(Class boClass, String referenceName) {
692 ClassDescriptor cd = getClassDescriptor(boClass);
693 return cd.getObjectReferenceDescriptorByName(referenceName) != null;
694 }
695
696
697
698
699
700
701 @Cached
702 public String getTableName(Class<? extends PersistableBusinessObject> boClass) {
703 ClassDescriptor cd = getClassDescriptor(boClass);
704 return cd.getFullTableName();
705 }
706
707
708 }
709