001 /**
002 * Copyright 2005-2012 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.rice.krad.service.impl;
017
018 import java.beans.PropertyDescriptor;
019 import java.util.ArrayList;
020 import java.util.Collection;
021 import java.util.HashMap;
022 import java.util.Iterator;
023 import java.util.List;
024 import java.util.Map;
025 import java.util.Set;
026
027 import org.apache.commons.beanutils.PropertyUtils;
028 import org.apache.commons.lang.StringUtils;
029 import org.kuali.rice.core.framework.persistence.jpa.metadata.EntityDescriptor;
030 import org.kuali.rice.core.framework.persistence.jpa.metadata.JoinColumnDescriptor;
031 import org.kuali.rice.core.framework.persistence.jpa.metadata.MetadataManager;
032 import org.kuali.rice.core.framework.persistence.jpa.metadata.ObjectDescriptor;
033 import org.kuali.rice.krad.bo.DataObjectRelationship;
034 import org.kuali.rice.krad.bo.PersistableBusinessObject;
035 import org.kuali.rice.krad.exception.ObjectNotABusinessObjectRuntimeException;
036 import org.kuali.rice.krad.exception.ReferenceAttributeDoesntExistException;
037 import org.kuali.rice.krad.exception.ReferenceAttributeNotAnOjbReferenceException;
038 import org.kuali.rice.krad.service.PersistenceStructureService;
039 import org.kuali.rice.krad.util.ForeignKeyFieldsPopulationState;
040
041 public class PersistenceStructureServiceJpaImpl extends PersistenceServiceImplBase implements PersistenceStructureService {
042
043 /**
044 *
045 * special case when the attributeClass passed in doesnt match the class of
046 * the reference-descriptor as defined in ojb-repository. Currently the only
047 * case of this happening is ObjectCode vs. ObjectCodeCurrent.
048 *
049 * NOTE: This method makes no real sense and is a product of a hack
050 * introduced by KFS for an unknown reason. If you find yourself using this
051 * map stop and go do something else.
052 *
053 * @param from
054 * the class in the code
055 * @param to
056 * the class in the repository
057 */
058 public static Map<Class, Class> referenceConversionMap = new HashMap<Class, Class>();
059
060 /**
061 * @see org.kuali.rice.krad.service.PersistenceService#isPersistable(java.lang.Class)
062 */
063
064 public boolean isPersistable(Class clazz) {
065 boolean isPersistable = false;
066
067 if (MetadataManager.getEntityDescriptor(clazz) != null) {
068 isPersistable = true;
069 }
070
071 return isPersistable;
072 }
073
074 /**
075 * @see org.kuali.rice.krad.service.PersistenceService#getPrimaryKeys(java.lang.Class)
076 */
077
078 public List getPrimaryKeys(Class clazz) {
079 List pkList = new ArrayList();
080
081 EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(clazz);
082 for (org.kuali.rice.core.framework.persistence.jpa.metadata.FieldDescriptor field : descriptor.getPrimaryKeys()) {
083 pkList.add(field.getName());
084 }
085
086 return pkList;
087 }
088
089 /**
090 * @see org.kuali.rice.krad.service.PersistenceMetadataExplorerService#listFieldNames(java.lang.Class)
091 */
092
093 public List listFieldNames(Class clazz) {
094 List fieldNames = new ArrayList();
095
096 EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(clazz);
097 for (org.kuali.rice.core.framework.persistence.jpa.metadata.FieldDescriptor field : descriptor.getFields()) {
098 fieldNames.add(field.getName());
099 }
100
101 return fieldNames;
102 }
103
104 /**
105 * @see org.kuali.rice.krad.service.PersistenceMetadataService#clearPrimaryKeyFields(java.lang.Object)
106 */
107 // Unit tests only
108 // TODO: Write JPA Version
109 public Object clearPrimaryKeyFields(Object persistableObject) {
110 /*
111 * if (persistableObject == null) { throw new
112 * IllegalArgumentException("invalid (null) persistableObject"); }
113 *
114 * String className = null; String fieldName = null; try { className =
115 * persistableObject.getClass().getName(); List fields =
116 * listPrimaryKeyFieldNames(persistableObject.getClass()); for (Iterator
117 * i = fields.iterator(); i.hasNext();) { fieldName = (String) i.next();
118 *
119 * PropertyUtils.setProperty(persistableObject, fieldName, null); }
120 *
121 * if (persistableObject instanceof PersistableBusinessObject) {
122 * ((PersistableBusinessObject) persistableObject).setObjectId(null); } }
123 * catch (NoSuchMethodException e) { throw new
124 * IntrospectionException("no setter for property '" + className + "." +
125 * fieldName + "'", e); } catch (IllegalAccessException e) { throw new
126 * IntrospectionException("problem accessing property '" + className +
127 * "." + fieldName + "'", e); } catch (InvocationTargetException e) {
128 * throw new IntrospectionException("problem invoking getter for
129 * property '" + className + "." + fieldName + "'", e); }
130 */
131 return persistableObject;
132 }
133
134 /**
135 * @see org.kuali.rice.krad.service.PersistenceMetadataExplorerService#listPersistableSubclasses(java.lang.Class)
136 */
137
138 // Unit tests only
139 // TODO: Write JPA Version
140 public List listPersistableSubclasses(Class superclazz) {
141 List persistableSubclasses = new ArrayList();
142 /*
143 * if (superclazz == null) { throw new IllegalArgumentException("invalid
144 * (null) uberclass"); }
145 *
146 * Map allDescriptors = getDescriptorRepository().getDescriptorTable();
147 * for (Iterator i = allDescriptors.entrySet().iterator(); i.hasNext();) {
148 * Map.Entry e = (Map.Entry) i.next();
149 *
150 * Class persistableClass = ((ClassDescriptor)
151 * e.getValue()).getClassOfObject(); if
152 * (!superclazz.equals(persistableClass) &&
153 * superclazz.isAssignableFrom(persistableClass)) {
154 * persistableSubclasses.add(persistableClass); } }
155 */
156 return persistableSubclasses;
157 }
158
159 /**
160 * @see org.kuali.rice.krad.service.PersistenceService#getRelationshipMetadata(java.lang.Class,
161 * java.lang.String)
162 */
163
164 public Map<String, DataObjectRelationship> getRelationshipMetadata(Class persistableClass, String attributeName, String attributePrefix) {
165 if (persistableClass == null) {
166 throw new IllegalArgumentException("invalid (null) persistableClass");
167 }
168 if (StringUtils.isBlank(attributeName)) {
169 throw new IllegalArgumentException("invalid (blank) attributeName");
170 }
171
172 Map<String, DataObjectRelationship> relationships = new HashMap<String, DataObjectRelationship>();
173
174 EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(persistableClass);
175 for (ObjectDescriptor objectDescriptor : descriptor.getObjectRelationships()) {
176 List<String> fks = objectDescriptor.getForeignKeyFields();
177 if (fks.contains(attributeName) || objectDescriptor.getAttributeName().equals(attributeName)) {
178 Map<String, String> fkToPkRefs = getForeignKeysForReference(persistableClass, objectDescriptor.getAttributeName());
179 DataObjectRelationship
180 rel = new DataObjectRelationship(persistableClass, objectDescriptor.getAttributeName(), objectDescriptor.getTargetEntity());
181 for (Map.Entry<String, String> ref : fkToPkRefs.entrySet()) {
182 if (StringUtils.isBlank(attributePrefix)) {
183 rel.getParentToChildReferences().put(ref.getKey(), ref.getValue());
184 } else {
185 rel.getParentToChildReferences().put(attributePrefix + "." + ref.getKey(), ref.getValue());
186 }
187 }
188 relationships.put(objectDescriptor.getAttributeName(), rel);
189 }
190 }
191
192 return relationships;
193 }
194
195
196 // Unit tests only
197 public Map<String, DataObjectRelationship> getRelationshipMetadata(Class persistableClass, String attributeName) {
198 return getRelationshipMetadata(persistableClass, attributeName, null);
199 }
200
201 /**
202 * @see org.kuali.rice.krad.service.PersistenceService#getForeignKeyFieldName(java.lang.Object,
203 * java.lang.String, java.lang.String)
204 */
205
206 public String getForeignKeyFieldName(Class persistableObjectClass, String attributeName, String pkName) {
207 String fkName = null;
208
209 EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(persistableObjectClass);
210 ObjectDescriptor objectDescriptor = descriptor.getObjectDescriptorByName(attributeName);
211 if (objectDescriptor == null) {
212 throw new RuntimeException("Attribute name " + attributeName + " is not a valid reference to class " + persistableObjectClass.getName());
213 }
214 List<org.kuali.rice.core.framework.persistence.jpa.metadata.FieldDescriptor> matches = new ArrayList<org.kuali.rice.core.framework.persistence.jpa.metadata.FieldDescriptor>();
215 for (org.kuali.rice.core.framework.persistence.jpa.metadata.FieldDescriptor field : descriptor.getFields()) {
216 String column = field.getColumn();
217 for (JoinColumnDescriptor join : objectDescriptor.getJoinColumnDescriptors()) {
218 if (column != null && column.equals(join.getName())) {
219 matches.add(field);
220 }
221 }
222 }
223
224 if (matches.size() == 1) {
225 fkName = matches.get(0).getName();
226 } else {
227 throw new RuntimeException("Implement me!");
228 }
229
230 return fkName;
231 }
232
233 /**
234 * @see org.kuali.rice.krad.service.PersistenceService#getReferencesForForeignKey(java.lang.Class,
235 * java.lang.String)
236 */
237
238 public Map getReferencesForForeignKey(Class persistableObjectClass, String attributeName) {
239 Map referenceClasses = new HashMap();
240
241 if (PersistableBusinessObject.class.isAssignableFrom(persistableObjectClass)) {
242 EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(persistableObjectClass);
243 for (ObjectDescriptor objectDescriptor : descriptor.getObjectRelationships()) {
244 List<String> refFkNames = objectDescriptor.getForeignKeyFields();
245 for (String fk : refFkNames) {
246 if (fk.equals(attributeName)) {
247 referenceClasses.put(objectDescriptor.getAttributeName(), objectDescriptor.getTargetEntity());
248 }
249 }
250 }
251 }
252
253 return referenceClasses;
254 }
255
256 /**
257 * @see org.kuali.rice.krad.service.PersistenceService#getForeignKeysForReference(java.lang.Class,
258 * java.lang.String) The Map structure is: Key(String fkFieldName) =>
259 * Value(String pkFieldName) NOTE that this implementation depends on
260 * the ordering of foreign-key elements in the ojb-repository matching
261 * the ordering of primary-key declarations of the class on the other
262 * side of the relationship. This is done because: 1. The current
263 * version of OJB requires you to declare all of these things in the
264 * correct (and matching) order in the ojb-repository file for it to
265 * work at all. 2. There is no other way to match a given foreign-key
266 * reference to its corresponding primary-key on the opposing side of
267 * the relationship. Yes, this is a crummy way to do it, but OJB doesnt
268 * provide explicit matches of foreign-keys to primary keys, and always
269 * assumes that foreign-keys map to primary keys on the other object,
270 * and never to a set of candidate keys, or any other column.
271 */
272
273 public Map getForeignKeysForReference(Class clazz, String attributeName) {
274
275 // yelp if nulls were passed in
276 if (clazz == null) {
277 throw new IllegalArgumentException("The Class passed in for the clazz argument was null.");
278 }
279 if (attributeName == null) {
280 throw new IllegalArgumentException("The String passed in for the attributeName argument was null.");
281 }
282
283 // get the class of the attribute name
284 Class attributeClass = getBusinessObjectAttributeClass(clazz, attributeName);
285 if (attributeClass == null) {
286 throw new ReferenceAttributeDoesntExistException("Requested attribute: '" + attributeName + "' does not exist on class: '" + clazz.getName() + "'.");
287 }
288
289 // make sure the class of the attribute descends from BusinessObject,
290 // otherwise throw an exception
291 if (!PersistableBusinessObject.class.isAssignableFrom(attributeClass)) {
292 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.");
293 }
294
295 return determineFkMap(clazz, attributeName, attributeClass);
296 }
297
298 private Map determineFkMap(Class clazz, String attributeName, Class attributeClass) {
299 Map fkMap = new HashMap();
300 EntityDescriptor entityDescriptor = MetadataManager.getEntityDescriptor(clazz);
301 ObjectDescriptor objectDescriptor = entityDescriptor.getObjectDescriptorByName(attributeName);
302 if (objectDescriptor == null) {
303 throw new ReferenceAttributeNotAnOjbReferenceException("Attribute requested (" + attributeName + ") is not defined in JPA annotations for class: '" + clazz.getName() + "'");
304 }
305
306 // special case when the attributeClass passed in doesnt match the
307 // class of the reference-descriptor as defined in ojb-repository.
308 // Currently
309 // the only case of this happening is ObjectCode vs.
310 // ObjectCodeCurrent.
311 if (!attributeClass.equals(objectDescriptor.getTargetEntity())) {
312 if (referenceConversionMap.containsKey(attributeClass)) {
313 attributeClass = referenceConversionMap.get(attributeClass);
314 } else {
315 throw new RuntimeException("The Class of the Java member [" + attributeClass.getName() + "] '" + attributeName + "' does not match the class of the reference [" + objectDescriptor.getTargetEntity().getName() + "]. " + "This is an unhandled special case for which special code needs to be written in this class.");
316 }
317 }
318
319 // get the list of the foreign-keys for this reference-descriptor
320 // (OJB)
321 List<String> fkFields = objectDescriptor.getForeignKeyFields();
322 Iterator<String> fkIterator = fkFields.iterator();
323
324 // get the list of the corresponding pk fields on the other side of
325 // the relationship
326 List pkFields = getPrimaryKeys(attributeClass);
327 Iterator pkIterator = pkFields.iterator();
328
329 // make sure the size of the pkIterator is the same as the
330 // size of the fkIterator, otherwise this whole thing is borked
331 if (pkFields.size() != fkFields.size()) {
332 throw new RuntimeException("KualiPersistenceStructureService Error: The number of " + "foreign keys doesnt match the number of primary keys.");
333 }
334
335 // walk through the list of the foreign keys, get their types
336 while (fkIterator.hasNext()) {
337 // if there is a next FK but not a next PK, then we've got a big
338 // problem,
339 // and cannot continue
340 if (!pkIterator.hasNext()) {
341 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.");
342 }
343
344 // get the field name of the fk & pk field
345 String fkFieldName = (String) fkIterator.next();
346 String pkFieldName = (String) pkIterator.next();
347
348 // add the fieldName and fieldType to the map
349 fkMap.put(fkFieldName, pkFieldName);
350 }
351 return fkMap;
352 }
353
354
355 public Map<String, String> getInverseForeignKeysForCollection(Class boClass, String collectionName) {
356 // yelp if nulls were passed in
357 if (boClass == null) {
358 throw new IllegalArgumentException("The Class passed in for the boClass argument was null.");
359 }
360 if (collectionName == null) {
361 throw new IllegalArgumentException("The String passed in for the attributeName argument was null.");
362 }
363
364 PropertyDescriptor propertyDescriptor = null;
365
366 // make an instance of the class passed
367 Object classInstance;
368 try {
369 classInstance = boClass.newInstance();
370 } catch (Exception e) {
371 throw new RuntimeException(e);
372 }
373
374 // make sure the attribute exists at all, throw exception if not
375 try {
376 propertyDescriptor = PropertyUtils.getPropertyDescriptor(classInstance, collectionName);
377 } catch (Exception e) {
378 throw new RuntimeException(e);
379 }
380 if (propertyDescriptor == null) {
381 throw new ReferenceAttributeDoesntExistException("Requested attribute: '" + collectionName + "' does not exist " + "on class: '" + boClass.getName() + "'. GFK");
382 }
383
384 // get the class of the attribute name
385 Class attributeClass = propertyDescriptor.getPropertyType();
386
387 // make sure the class of the attribute descends from BusinessObject,
388 // otherwise throw an exception
389 if (!Collection.class.isAssignableFrom(attributeClass)) {
390 throw new ObjectNotABusinessObjectRuntimeException("Attribute requested (" + collectionName + ") is of class: " + "'" + attributeClass.getName() + "' and is not a " + "descendent of Collection");
391 }
392
393 EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(boClass);
394 org.kuali.rice.core.framework.persistence.jpa.metadata.CollectionDescriptor cd = descriptor.getCollectionDescriptorByName(collectionName);
395 List<String> childPrimaryKeys = cd.getForeignKeyFields();
396
397 List parentForeignKeys = getPrimaryKeys(boClass);
398
399 if (parentForeignKeys.size() != childPrimaryKeys.size()) {
400 throw new RuntimeException("The number of keys in the class descriptor and the inverse foreign key mapping for the collection descriptors do not match.");
401 }
402
403 Map<String, String> fkToPkMap = new HashMap<String, String>();
404 Iterator pFKIter = parentForeignKeys.iterator();
405 Iterator cPKIterator = childPrimaryKeys.iterator();
406
407 while (pFKIter.hasNext()) {
408 String parentForeignKey = (String) pFKIter.next();
409 String childPrimaryKey = (String) cPKIterator.next();
410
411 fkToPkMap.put(parentForeignKey, childPrimaryKey);
412 }
413 return fkToPkMap;
414 }
415
416 /**
417 * @see org.kuali.rice.krad.service.PersistenceService#getNestedForeignKeyMap(java.lang.Class)
418 */
419
420 public Map getNestedForeignKeyMap(Class persistableObjectClass) {
421 Map fkMap = new HashMap();
422
423 // Rice JPA MetadataManager
424 // Note: Not sure how to test this method, and JPA and OJB ordering of
425 // PK/FK is not the same as well. This should be tested more thoroughly.
426 EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(persistableObjectClass);
427 for (ObjectDescriptor objectReferenceDescriptor : descriptor.getObjectRelationships()) {
428 EntityDescriptor referenceDescriptor = MetadataManager.getEntityDescriptor(objectReferenceDescriptor.getTargetEntity());
429 List<String> fkFields = objectReferenceDescriptor.getForeignKeyFields();
430 Set<org.kuali.rice.core.framework.persistence.jpa.metadata.FieldDescriptor> pkFields = referenceDescriptor.getPrimaryKeys();
431 int i = 0;
432 for (org.kuali.rice.core.framework.persistence.jpa.metadata.FieldDescriptor fd : pkFields) {
433 fkMap.put(objectReferenceDescriptor.getAttributeName() + "." + fd.getName(), fkFields.get(i));
434 i++;
435 }
436 }
437
438 return fkMap;
439 }
440
441 /**
442 * @see org.kuali.rice.krad.service.PersistenceMetadataService#hasPrimaryKeyFieldValues(java.lang.Object)
443 */
444 public boolean hasPrimaryKeyFieldValues(Object persistableObject) {
445 Map keyFields = getPrimaryKeyFieldValues(persistableObject);
446
447 boolean emptyField = false;
448 for (Iterator i = keyFields.entrySet().iterator(); !emptyField && i.hasNext();) {
449 Map.Entry e = (Map.Entry) i.next();
450
451 Object fieldValue = e.getValue();
452 if (fieldValue == null) {
453 emptyField = true;
454 } else if (fieldValue instanceof String) {
455 if (StringUtils.isEmpty((String) fieldValue)) {
456 emptyField = true;
457 } else {
458 emptyField = false;
459 }
460 }
461 }
462
463 return !emptyField;
464 }
465
466 /**
467 * @see org.kuali.rice.krad.service.PersistenceService#getForeignKeyFieldsPopulationState(org.kuali.rice.krad.bo.BusinessObject,
468 * java.lang.String)
469 */
470 public ForeignKeyFieldsPopulationState getForeignKeyFieldsPopulationState(PersistableBusinessObject bo, String referenceName) {
471
472 boolean allFieldsPopulated = true;
473 boolean anyFieldsPopulated = false;
474 List<String> unpopulatedFields = new ArrayList<String>();
475
476 // yelp if nulls were passed in
477 if (bo == null) {
478 throw new IllegalArgumentException("The Class passed in for the BusinessObject argument was null.");
479 }
480 if (StringUtils.isBlank(referenceName)) {
481 throw new IllegalArgumentException("The String passed in for the referenceName argument was null or empty.");
482 }
483
484 PropertyDescriptor propertyDescriptor = null;
485
486 // make sure the attribute exists at all, throw exception if not
487 try {
488 propertyDescriptor = PropertyUtils.getPropertyDescriptor(bo, referenceName);
489 } catch (Exception e) {
490 throw new RuntimeException(e);
491 }
492 if (propertyDescriptor == null) {
493 throw new ReferenceAttributeDoesntExistException("Requested attribute: '" + referenceName + "' does not exist " + "on class: '" + bo.getClass().getName() + "'.");
494 }
495
496 // get the class of the attribute name
497 Class referenceClass = propertyDescriptor.getPropertyType();
498
499 // make sure the class of the attribute descends from BusinessObject,
500 // otherwise throw an exception
501 if (!PersistableBusinessObject.class.isAssignableFrom(referenceClass)) {
502 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.");
503 }
504
505 EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(bo.getClass());
506 ObjectDescriptor objectDescriptor = descriptor.getObjectDescriptorByName(referenceName);
507
508 if (objectDescriptor == null) {
509 throw new ReferenceAttributeNotAnOjbReferenceException("Attribute requested (" + referenceName + ") is not listed " + "in OJB as a reference-descriptor for class: '" + bo.getClass().getName() + "'");
510 }
511
512 List<String> fkFields = objectDescriptor.getForeignKeyFields();
513 Iterator fkIterator = fkFields.iterator();
514
515 // walk through the list of the foreign keys, get their types
516 while (fkIterator.hasNext()) {
517
518 // get the field name of the fk & pk field
519 String fkFieldName = (String) fkIterator.next();
520
521 // get the value for the fk field
522 Object fkFieldValue = null;
523 try {
524 fkFieldValue = PropertyUtils.getSimpleProperty(bo, fkFieldName);
525 }
526
527 // abort if the value is not retrievable
528 catch (Exception e) {
529 throw new RuntimeException(e);
530 }
531
532 // test the value
533 if (fkFieldValue == null) {
534 allFieldsPopulated = false;
535 unpopulatedFields.add(fkFieldName);
536 } else if (fkFieldValue instanceof String) {
537 if (StringUtils.isBlank((String) fkFieldValue)) {
538 allFieldsPopulated = false;
539 unpopulatedFields.add(fkFieldName);
540 } else {
541 anyFieldsPopulated = true;
542 }
543 } else {
544 anyFieldsPopulated = true;
545 }
546 }
547
548 // sanity check. if the flag for all fields populated is set, then
549 // there should be nothing in the unpopulatedFields list
550 if (allFieldsPopulated) {
551 if (!unpopulatedFields.isEmpty()) {
552 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.");
553 }
554 }
555
556 return new ForeignKeyFieldsPopulationState(allFieldsPopulated, anyFieldsPopulated, unpopulatedFields);
557 }
558
559 /**
560 * @see org.kuali.rice.krad.service.PersistenceStructureService#listReferenceObjectFieldNames(java.lang.Class)
561 */
562
563 public Map<String, Class> listReferenceObjectFields(Class boClass) {
564 // validate parameter
565 if (boClass == null) {
566 throw new IllegalArgumentException("Class specified in the parameter was null.");
567 }
568 if (!PersistableBusinessObject.class.isAssignableFrom(boClass)) {
569 throw new IllegalArgumentException("Class specified [" + boClass.getName() + "] must be a class that " + "inherits from BusinessObject.");
570 }
571
572 EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(boClass);
573 Map<String, Class> references = new HashMap();
574 for (org.kuali.rice.core.framework.persistence.jpa.metadata.ObjectDescriptor od : descriptor.getObjectRelationships()) {
575 references.put(od.getAttributeName(), od.getTargetEntity());
576 }
577
578 return references;
579 }
580
581
582 public Map<String, Class> listCollectionObjectTypes(Class boClass) {
583 if (boClass == null) {
584 throw new IllegalArgumentException("Class specified in the parameter was null.");
585 }
586
587 Map<String, Class> references = new HashMap();
588
589 EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(boClass);
590 if (descriptor == null) {
591 return references;
592 }
593
594 for (org.kuali.rice.core.framework.persistence.jpa.metadata.CollectionDescriptor cd : descriptor.getCollectionRelationships()) {
595 references.put(cd.getAttributeName(), cd.getTargetEntity());
596 }
597
598 return references;
599 }
600
601 public Map<String, Class> listCollectionObjectTypes(PersistableBusinessObject bo) {
602 // validate parameter
603 if (bo == null) {
604 throw new IllegalArgumentException("BO specified in the parameter was null.");
605 }
606 if (!(bo instanceof PersistableBusinessObject)) {
607 throw new IllegalArgumentException("BO specified [" + bo.getClass().getName() + "] must be a class that " + "inherits from BusinessObject.");
608 }
609
610 return listCollectionObjectTypes(bo.getClass());
611 }
612
613 /**
614 * @see org.kuali.rice.krad.service.PersistenceStructureService#listReferenceObjectFieldNames(org.kuali.rice.krad.bo.BusinessObject)
615 */
616 public Map<String, Class> listReferenceObjectFields(PersistableBusinessObject bo) {
617 // validate parameter
618 if (bo == null) {
619 throw new IllegalArgumentException("BO specified in the parameter was null.");
620 }
621 if (!(bo instanceof PersistableBusinessObject)) {
622 throw new IllegalArgumentException("BO specified [" + bo.getClass().getName() + "] must be a class that " + "inherits from BusinessObject.");
623 }
624
625 return listReferenceObjectFields(bo.getClass());
626 }
627
628
629 public boolean isReferenceUpdatable(Class boClass, String referenceName) {
630 EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(boClass);
631 return descriptor.getObjectDescriptorByName(referenceName).isUpdateable();
632 // for (CascadeType ct : descriptor.getObjectDescriptorByName(referenceName).getCascade()) {
633 // if (ct.equals(CascadeType.ALL) || ct.equals(CascadeType.MERGE) || ct.equals(CascadeType.PERSIST)) {
634 // return true;
635 // }
636 // }
637 // return false;
638 }
639
640
641 public boolean isCollectionUpdatable(Class boClass, String collectionName) {
642 EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(boClass);
643 return descriptor.getCollectionDescriptorByName(collectionName).isUpdateable();
644 // for (CascadeType ct : descriptor.getCollectionDescriptorByName(collectionName).getCascade()) {
645 // if (ct.equals(CascadeType.ALL) || ct.equals(CascadeType.MERGE) || ct.equals(CascadeType.PERSIST)) {
646 // return true;
647 // }
648 // }
649 // return false;
650 }
651
652
653 public boolean hasCollection(Class boClass, String collectionName) {
654 EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(boClass);
655 return descriptor.getCollectionDescriptorByName(collectionName) != null;
656 }
657
658
659 public boolean hasReference(Class boClass, String referenceName) {
660 EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(boClass);
661 return descriptor.getObjectDescriptorByName(referenceName) != null;
662 }
663
664 /**
665 * @see org.kuali.rice.krad.service.PersistenceStructureService#getTableName(java.lang.Class)
666 */
667
668 public String getTableName(Class<? extends PersistableBusinessObject> boClass) {
669 EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(boClass);
670 return descriptor.getTable();
671 }
672 }
673