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