Coverage Report - org.kuali.rice.krad.service.impl.PersistenceStructureServiceOjbImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
PersistenceStructureServiceOjbImpl
0%
0/284
0%
0/146
5.64
 
 1  
 /**
 2  
  * Copyright 2005-2011 The Kuali Foundation
 3  
  *
 4  
  * Licensed under the Educational Community License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  * http://www.opensource.org/licenses/ecl2.php
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 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  0
 public class PersistenceStructureServiceOjbImpl extends PersistenceServiceImplBase implements PersistenceStructureService {
 46  
 
 47  
         /**
 48  
          * 
 49  
          * special case when the attributeClass passed in doesnt match the class of
 50  
          * the reference-descriptor as defined in ojb-repository. Currently the only
 51  
          * case of this happening is ObjectCode vs. ObjectCodeCurrent.
 52  
          * 
 53  
          * NOTE: This method makes no real sense and is a product of a hack
 54  
          * introduced by KFS for an unknown reason. If you find yourself using this
 55  
          * map stop and go do something else.
 56  
          * 
 57  
          * @param from
 58  
          *            the class in the code
 59  
          * @param to
 60  
          *            the class in the repository
 61  
          */
 62  0
         public static Map<Class, Class> referenceConversionMap = new HashMap<Class, Class>();
 63  
 
 64  
         
 65  
         private PersistenceStructureService persistenceStructureServiceJpa;
 66  
 
 67  
         public PersistenceStructureService getPersistenceStructureServiceJpa() {
 68  0
                 return this.persistenceStructureServiceJpa;
 69  
         }
 70  
 
 71  
         public void setPersistenceStructureServiceJpa(PersistenceStructureService persistenceStructureServiceJpa) {
 72  0
                 this.persistenceStructureServiceJpa = persistenceStructureServiceJpa;
 73  0
         }
 74  
         
 75  
         /**
 76  
          * @see org.kuali.rice.krad.service.PersistenceService#isPersistable(java.lang.Class)
 77  
          */
 78  
         
 79  
         public boolean isPersistable(Class clazz) {
 80  0
                 boolean isPersistable = false;
 81  
                 try {
 82  0
                         if (getClassDescriptor(clazz) != null) {
 83  0
                                 isPersistable = true;
 84  
                         }
 85  0
                 } catch (ClassNotPersistableException e) {
 86  0
                         isPersistable = false;
 87  0
                 }
 88  0
                 return isPersistable;
 89  
         }
 90  
 
 91  
         /**
 92  
          * @see org.kuali.rice.krad.service.PersistenceService#getPrimaryKeys(java.lang.Class)
 93  
          */
 94  
         
 95  
         public List getPrimaryKeys(Class clazz) {
 96  0
                 List pkList = new ArrayList();
 97  0
                 ClassDescriptor classDescriptor = getClassDescriptor(clazz);
 98  0
                 FieldDescriptor keyDescriptors[] = classDescriptor.getPkFields();
 99  0
                 for (int i = 0; i < keyDescriptors.length; ++i) {
 100  0
                         FieldDescriptor keyDescriptor = keyDescriptors[i];
 101  0
                         pkList.add(keyDescriptor.getAttributeName());
 102  
                 }
 103  0
                 return pkList;
 104  
         }
 105  
 
 106  
         /**
 107  
          * @see org.kuali.rice.krad.service.PersistenceMetadataExplorerService#listFieldNames(java.lang.Class)
 108  
          */
 109  
         
 110  
         public List listFieldNames(Class clazz) {
 111  0
                 List fieldNames = new ArrayList(); 
 112  0
                 ClassDescriptor classDescriptor = getClassDescriptor(clazz);
 113  0
                 FieldDescriptor fieldDescriptors[] = classDescriptor.getFieldDescriptions();
 114  0
                 for (int i = 0; i < fieldDescriptors.length; ++i) {
 115  0
                         FieldDescriptor fieldDescriptor = fieldDescriptors[i];
 116  0
                         fieldNames.add(fieldDescriptor.getAttributeName());
 117  
                 }
 118  0
                 return fieldNames;
 119  
         }
 120  
 
 121  
         /**
 122  
          * @see org.kuali.rice.krad.service.PersistenceMetadataService#clearPrimaryKeyFields(java.lang.Object)
 123  
          */
 124  
         // Unit tests only
 125  
         public Object clearPrimaryKeyFields(Object persistableObject) {
 126  0
                 if (persistableObject == null) {
 127  0
                         throw new IllegalArgumentException("invalid (null) persistableObject");
 128  
                 }
 129  
 
 130  0
                 String className = null;
 131  0
                 String fieldName = null;
 132  
                 try {
 133  0
                         className = persistableObject.getClass().getName();
 134  0
                         List fields = listPrimaryKeyFieldNames(persistableObject.getClass());
 135  0
                         for (Iterator i = fields.iterator(); i.hasNext();) {
 136  0
                                 fieldName = (String) i.next();
 137  
 
 138  0
                                 PropertyUtils.setProperty(persistableObject, fieldName, null);
 139  
                         }
 140  
 
 141  0
                         if (persistableObject instanceof PersistableBusinessObject) {
 142  0
                                 ((PersistableBusinessObject) persistableObject).setObjectId(null);
 143  
                         }
 144  0
                 } catch (NoSuchMethodException e) {
 145  0
                         throw new IntrospectionException("no setter for property '" + className + "." + fieldName + "'", e);
 146  0
                 } catch (IllegalAccessException e) {
 147  0
                         throw new IntrospectionException("problem accessing property '" + className + "." + fieldName + "'", e);
 148  0
                 } catch (InvocationTargetException e) {
 149  0
                         throw new IntrospectionException("problem invoking getter for property '" + className + "." + fieldName + "'", e);
 150  0
                 }
 151  
 
 152  0
                 return persistableObject;
 153  
         }
 154  
 
 155  
         /**
 156  
          * @see org.kuali.rice.krad.service.PersistenceMetadataExplorerService#listPersistableSubclasses(java.lang.Class)
 157  
          */
 158  
         
 159  
         // Unit tests only
 160  
         public List listPersistableSubclasses(Class superclazz) {
 161  0
                 if (superclazz == null) {
 162  0
                         throw new IllegalArgumentException("invalid (null) uberclass");
 163  
                 }
 164  
 
 165  0
                 Map allDescriptors = getDescriptorRepository().getDescriptorTable();
 166  0
                 List persistableSubclasses = new ArrayList();
 167  0
                 for (Iterator i = allDescriptors.entrySet().iterator(); i.hasNext();) {
 168  0
                         Map.Entry e = (Map.Entry) i.next();
 169  
 
 170  0
                         Class persistableClass = ((ClassDescriptor) e.getValue()).getClassOfObject();
 171  0
                         if (!superclazz.equals(persistableClass) && superclazz.isAssignableFrom(persistableClass)) {
 172  0
                                 persistableSubclasses.add(persistableClass);
 173  
                         }
 174  0
                 }
 175  0
                 return persistableSubclasses;
 176  
         }
 177  
 
 178  
         /**
 179  
          * @see org.kuali.rice.krad.service.PersistenceService#getRelationshipMetadata(java.lang.Class,
 180  
          *      java.lang.String)
 181  
          */
 182  
         
 183  
         public Map<String, DataObjectRelationship> getRelationshipMetadata(Class persistableClass, String attributeName, String attributePrefix) {
 184  0
                 if (persistableClass == null) {
 185  0
                         throw new IllegalArgumentException("invalid (null) persistableClass");
 186  
                 }
 187  0
                 if (StringUtils.isBlank(attributeName)) {
 188  0
                         throw new IllegalArgumentException("invalid (blank) attributeName");
 189  
                 }
 190  
 
 191  0
                 Map<String, DataObjectRelationship> relationships = new HashMap<String, DataObjectRelationship>();
 192  0
                 ClassDescriptor classDescriptor = getClassDescriptor(persistableClass);
 193  0
                 Vector<ObjectReferenceDescriptor> references = classDescriptor.getObjectReferenceDescriptors();
 194  0
                 for (ObjectReferenceDescriptor objRef : references) {
 195  0
                         Vector fks = objRef.getForeignKeyFields();
 196  0
                         if (fks.contains(attributeName) || objRef.getAttributeName().equals(attributeName)) {
 197  0
                                 Map<String, String> fkToPkRefs = getForeignKeysForReference(persistableClass, objRef.getAttributeName());
 198  0
                                 DataObjectRelationship rel = new DataObjectRelationship(persistableClass, objRef.getAttributeName(), objRef.getItemClass());
 199  0
                                 for (Map.Entry<String, String> ref : fkToPkRefs.entrySet()) {
 200  0
                                         if (StringUtils.isBlank(attributePrefix)) {
 201  0
                                                 rel.getParentToChildReferences().put(ref.getKey(), ref.getValue());
 202  
                                         } else {
 203  0
                                                 rel.getParentToChildReferences().put(attributePrefix + "." + ref.getKey(), ref.getValue());
 204  
                                         }
 205  
                                 }
 206  0
                                 relationships.put(objRef.getAttributeName(), rel);
 207  
                         }
 208  0
                 }
 209  0
                 return relationships;
 210  
         }
 211  
 
 212  
         
 213  
         // Unit tests only
 214  
         public Map<String, DataObjectRelationship> getRelationshipMetadata(Class persistableClass, String attributeName) {
 215  0
                 return getRelationshipMetadata(persistableClass, attributeName, null);
 216  
         }
 217  
 
 218  
         /**
 219  
          * @see org.kuali.rice.krad.service.PersistenceService#getForeignKeyFieldName(java.lang.Object,
 220  
          *      java.lang.String, java.lang.String)
 221  
          */
 222  
         
 223  
         public String getForeignKeyFieldName(Class persistableObjectClass, String attributeName, String pkName) {
 224  0
                 String fkName = "";
 225  0
                 ClassDescriptor classDescriptor = getClassDescriptor(persistableObjectClass);
 226  0
                 ObjectReferenceDescriptor objectReferenceDescriptor = classDescriptor.getObjectReferenceDescriptorByName(attributeName);
 227  0
                 if (objectReferenceDescriptor == null) {
 228  0
                         throw new RuntimeException("Attribute name " + attributeName + " is not a valid reference to class " + persistableObjectClass.getName());
 229  
                 }
 230  0
                 ClassDescriptor referenceDescriptor = this.getClassDescriptor(objectReferenceDescriptor.getItemClass());
 231  
 
 232  0
                 FieldDescriptor[] fkFields = objectReferenceDescriptor.getForeignKeyFieldDescriptors(classDescriptor);
 233  0
                 FieldDescriptor[] pkFields = referenceDescriptor.getPkFields();
 234  0
                 for (int i = 0; i < pkFields.length; i++) {
 235  0
                         FieldDescriptor pkField = pkFields[i];
 236  0
                         if (pkField.getAttributeName().equals(pkName)) {
 237  0
                                 fkName = fkFields[i].getAttributeName();
 238  
                         }
 239  
                 }
 240  0
                 return fkName;
 241  
         }
 242  
 
 243  
         /**
 244  
          * @see org.kuali.rice.krad.service.PersistenceService#getReferencesForForeignKey(java.lang.Class,
 245  
          *      java.lang.String)
 246  
          */
 247  
         
 248  
         public Map getReferencesForForeignKey(Class persistableObjectClass, String attributeName) {
 249  0
                 Map referenceClasses = new HashMap();
 250  0
                 if (PersistableBusinessObject.class.isAssignableFrom(persistableObjectClass)) {
 251  0
                         ClassDescriptor classDescriptor = getClassDescriptor(persistableObjectClass);
 252  0
                         Vector objectReferences = classDescriptor.getObjectReferenceDescriptors();
 253  0
                         for (Iterator iter = objectReferences.iterator(); iter.hasNext();) {
 254  0
                                 ObjectReferenceDescriptor referenceDescriptor = (ObjectReferenceDescriptor) iter.next();
 255  
 
 256  
                                 /*
 257  
                                  * iterate through the fk keys for the reference object and if
 258  
                                  * matches the attributeName add the class as a reference
 259  
                                  */
 260  0
                                 FieldDescriptor[] refFkNames = referenceDescriptor.getForeignKeyFieldDescriptors(classDescriptor);
 261  0
                                 for (int i = 0; i < refFkNames.length; i++) {
 262  0
                                         FieldDescriptor fkField = refFkNames[i];
 263  0
                                         if (fkField.getAttributeName().equals(attributeName)) {
 264  0
                                                 referenceClasses.put(referenceDescriptor.getAttributeName(), referenceDescriptor.getItemClass());
 265  
                                         }
 266  
                                 }
 267  0
                         }
 268  
                 }
 269  0
                 return referenceClasses;
 270  
         }
 271  
 
 272  
         /**
 273  
          * @see org.kuali.rice.krad.service.PersistenceService#getForeignKeysForReference(java.lang.Class,
 274  
          *      java.lang.String) The Map structure is: Key(String fkFieldName) =>
 275  
          *      Value(String pkFieldName) NOTE that this implementation depends on
 276  
          *      the ordering of foreign-key elements in the ojb-repository matching
 277  
          *      the ordering of primary-key declarations of the class on the other
 278  
          *      side of the relationship. This is done because: 1. The current
 279  
          *      version of OJB requires you to declare all of these things in the
 280  
          *      correct (and matching) order in the ojb-repository file for it to
 281  
          *      work at all. 2. There is no other way to match a given foreign-key
 282  
          *      reference to its corresponding primary-key on the opposing side of
 283  
          *      the relationship. Yes, this is a crummy way to do it, but OJB doesnt
 284  
          *      provide explicit matches of foreign-keys to primary keys, and always
 285  
          *      assumes that foreign-keys map to primary keys on the other object,
 286  
          *      and never to a set of candidate keys, or any other column.
 287  
          */
 288  
         
 289  
         public Map getForeignKeysForReference(Class clazz, String attributeName) {
 290  
                 // yelp if nulls were passed in
 291  0
                 if (clazz == null) {
 292  0
                         throw new IllegalArgumentException("The Class passed in for the clazz argument was null.");
 293  
                 }
 294  0
                 if (attributeName == null) {
 295  0
                         throw new IllegalArgumentException("The String passed in for the attributeName argument was null.");
 296  
                 }
 297  
 
 298  
                 // get the class of the attribute name
 299  0
                 Class attributeClass = getBusinessObjectAttributeClass(clazz, attributeName);
 300  0
                 if (attributeClass == null) {
 301  0
                         throw new ReferenceAttributeDoesntExistException("Requested attribute: '" + attributeName + "' does not exist " + "on class: '" + clazz.getName() + "'.");
 302  
                 }
 303  
 
 304  
                 // make sure the class of the attribute descends from BusinessObject,
 305  
                 // otherwise throw an exception
 306  0
                 if (!PersistableBusinessObject.class.isAssignableFrom(attributeClass)) {
 307  0
                         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  0
                 Map fkMap = new HashMap();
 311  
                 
 312  
                 // make sure the attribute designated is listed as a
 313  
                 // reference-descriptor on the clazz specified, otherwise 
 314  
                 // throw an exception (OJB); 
 315  0
                 ClassDescriptor classDescriptor = getClassDescriptor(clazz);
 316  0
                 ObjectReferenceDescriptor referenceDescriptor = classDescriptor.getObjectReferenceDescriptorByName(attributeName);
 317  0
                 if (referenceDescriptor == null) {
 318  0
                         throw new ReferenceAttributeNotAnOjbReferenceException("Attribute requested (" + attributeName + ") is not listed " + "in OJB as a reference-descriptor for class: '" + clazz.getName() + "'");
 319  
                 }
 320  
 
 321  
                 // special case when the attributeClass passed in doesnt match the
 322  
                 // class of the reference-descriptor as defined in ojb-repository.
 323  
                 // Currently
 324  
                 // the only case of this happening is ObjectCode vs.
 325  
                 // ObjectCodeCurrent.
 326  0
                 if (!attributeClass.equals(referenceDescriptor.getItemClass())) {
 327  
 
 328  0
                         if (referenceConversionMap.containsKey(attributeClass)) {
 329  0
                                 attributeClass = referenceConversionMap.get(attributeClass);
 330  
                         } else {
 331  0
                                 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  
                 // get the list of the foreign-keys for this reference-descriptor
 336  
                 // (OJB)
 337  0
                 Vector fkFields = referenceDescriptor.getForeignKeyFields();
 338  0
                 Iterator fkIterator = fkFields.iterator();
 339  
 
 340  
                 // get the list of the corresponding pk fields on the other side of
 341  
                 // the relationship
 342  0
                 List pkFields = getPrimaryKeys(attributeClass);
 343  0
                 Iterator pkIterator = pkFields.iterator();
 344  
 
 345  
                 // make sure the size of the pkIterator is the same as the
 346  
                 // size of the fkIterator, otherwise this whole thing is borked
 347  0
                 if (pkFields.size() != fkFields.size()) {
 348  0
                         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  
                 // walk through the list of the foreign keys, get their types
 352  0
                 while (fkIterator.hasNext()) {
 353  
                         // if there is a next FK but not a next PK, then we've got a big
 354  
                         // problem,
 355  
                         // and cannot continue
 356  0
                         if (!pkIterator.hasNext()) {
 357  0
                                 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  
                         // get the field name of the fk & pk field
 361  0
                         String fkFieldName = (String) fkIterator.next();
 362  0
                         String pkFieldName = (String) pkIterator.next();
 363  
 
 364  
                         // add the fieldName and fieldType to the map
 365  0
                         fkMap.put(fkFieldName, pkFieldName);
 366  0
                 }
 367  
                 
 368  0
                 return fkMap;
 369  
         }
 370  
 
 371  
         
 372  
         public Map<String, String> getInverseForeignKeysForCollection(Class boClass, String collectionName) {
 373  
                 // yelp if nulls were passed in
 374  0
                 if (boClass == null) {
 375  0
                         throw new IllegalArgumentException("The Class passed in for the boClass argument was null.");
 376  
                 }
 377  0
                 if (collectionName == null) {
 378  0
                         throw new IllegalArgumentException("The String passed in for the attributeName argument was null.");
 379  
                 }
 380  
 
 381  0
                 PropertyDescriptor propertyDescriptor = null;
 382  
 
 383  
                 // make an instance of the class passed
 384  
                 Object classInstance;
 385  
                 try {
 386  0
                         classInstance = boClass.newInstance();
 387  0
                 } catch (Exception e) {
 388  0
                         throw new RuntimeException(e);
 389  0
                 }
 390  
 
 391  
                 // make sure the attribute exists at all, throw exception if not
 392  
                 try {
 393  0
                         propertyDescriptor = PropertyUtils.getPropertyDescriptor(classInstance, collectionName);
 394  0
                 } catch (Exception e) {
 395  0
                         throw new RuntimeException(e);
 396  0
                 }
 397  0
                 if (propertyDescriptor == null) {
 398  0
                         throw new ReferenceAttributeDoesntExistException("Requested attribute: '" + collectionName + "' does not exist " + "on class: '" + boClass.getName() + "'. GFK");
 399  
                 }
 400  
 
 401  
                 // get the class of the attribute name
 402  0
                 Class attributeClass = propertyDescriptor.getPropertyType();
 403  
 
 404  
                 // make sure the class of the attribute descends from BusinessObject,
 405  
                 // otherwise throw an exception
 406  0
                 if (!Collection.class.isAssignableFrom(attributeClass)) {
 407  0
                         throw new ObjectNotABusinessObjectRuntimeException("Attribute requested (" + collectionName + ") is of class: " + "'" + attributeClass.getName() + "' and is not a " + "descendent of Collection");
 408  
                 }
 409  
 
 410  
                 // make sure the collection designated is listed as a
 411  
                 // collection-descriptor
 412  
                 // on the boClass specified, otherwise throw an exception
 413  0
                 ClassDescriptor classDescriptor = getClassDescriptor(boClass);
 414  0
                 CollectionDescriptor collectionDescriptor = classDescriptor.getCollectionDescriptorByName(collectionName);
 415  
 
 416  
                 // in collections, the number of keys is equal to the number of keys in
 417  
                 // the parent class (the class with the collection).
 418  
                 // Each of the primary keys on the parent object will be mapped to a
 419  
                 // field in the element object.
 420  
 
 421  0
                 List parentForeignKeys = getPrimaryKeys(boClass);
 422  0
                 Vector childPrimaryKeysLegacy = collectionDescriptor.getForeignKeyFields();
 423  
 
 424  0
                 if (parentForeignKeys.size() != childPrimaryKeysLegacy.size()) {
 425  0
                         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  0
                 Map<String, String> fkToPkMap = new HashMap<String, String>();
 429  
 
 430  0
                 Iterator pFKIter = parentForeignKeys.iterator();
 431  0
                 Iterator cPKIterator = childPrimaryKeysLegacy.iterator();
 432  
 
 433  0
                 while (pFKIter.hasNext()) {
 434  0
                         String parentForeignKey = (String) pFKIter.next();
 435  0
                         String childPrimaryKey = (String) cPKIterator.next();
 436  
 
 437  0
                         fkToPkMap.put(parentForeignKey, childPrimaryKey);
 438  0
                 }
 439  
                                 
 440  0
                 return fkToPkMap;
 441  
         }
 442  
 
 443  
         /**
 444  
          * @see org.kuali.rice.krad.service.PersistenceService#getNestedForeignKeyMap(java.lang.Class)
 445  
          */
 446  
         
 447  
         public Map getNestedForeignKeyMap(Class persistableObjectClass) {
 448  0
                 Map fkMap = new HashMap(); 
 449  0
                 ClassDescriptor classDescriptor = getClassDescriptor(persistableObjectClass);
 450  0
                 Vector objectReferences = classDescriptor.getObjectReferenceDescriptors();
 451  0
                 for (Iterator iter = objectReferences.iterator(); iter.hasNext();) {
 452  0
                         ObjectReferenceDescriptor objectReferenceDescriptor = (ObjectReferenceDescriptor) iter.next();
 453  0
                         ClassDescriptor referenceDescriptor = this.getClassDescriptor(objectReferenceDescriptor.getItemClass());
 454  
 
 455  0
                         FieldDescriptor[] fkFields = objectReferenceDescriptor.getForeignKeyFieldDescriptors(classDescriptor);
 456  0
                         FieldDescriptor[] pkFields = referenceDescriptor.getPkFields();
 457  0
                         for (int i = 0; i < pkFields.length; i++) {
 458  0
                                 FieldDescriptor pkField = pkFields[i];
 459  0
                                 fkMap.put(objectReferenceDescriptor.getAttributeName() + "." + pkField.getAttributeName(), fkFields[i].getAttributeName());
 460  
                         }
 461  0
                 }
 462  
                 
 463  0
                 return fkMap;
 464  
         }
 465  
 
 466  
         /**
 467  
          * @see org.kuali.rice.krad.service.PersistenceMetadataService#hasPrimaryKeyFieldValues(java.lang.Object)
 468  
          */
 469  
         public boolean hasPrimaryKeyFieldValues(Object persistableObject) {
 470  0
                 Map keyFields = getPrimaryKeyFieldValues(persistableObject);
 471  
 
 472  0
                 boolean emptyField = false;
 473  0
                 for (Iterator i = keyFields.entrySet().iterator(); !emptyField && i.hasNext();) {
 474  0
                         Map.Entry e = (Map.Entry) i.next();
 475  
 
 476  0
                         Object fieldValue = e.getValue();
 477  0
                         if (fieldValue == null) {
 478  0
                                 emptyField = true;
 479  0
                         } else if (fieldValue instanceof String) {
 480  0
                                 if (StringUtils.isEmpty((String) fieldValue)) {
 481  0
                                         emptyField = true;
 482  
                                 } else {
 483  0
                                         emptyField = false;
 484  
                                 }
 485  
                         }
 486  0
                 }
 487  
 
 488  0
                 return !emptyField;
 489  
         }
 490  
 
 491  
         /**
 492  
          * @see org.kuali.rice.krad.service.PersistenceService#getForeignKeyFieldsPopulationState(org.kuali.rice.krad.bo.BusinessObject,
 493  
          *      java.lang.String)
 494  
          */
 495  
         public ForeignKeyFieldsPopulationState getForeignKeyFieldsPopulationState(PersistableBusinessObject bo, String referenceName) {
 496  0
                 boolean allFieldsPopulated = true;
 497  0
                 boolean anyFieldsPopulated = false;
 498  0
                 List<String> unpopulatedFields = new ArrayList<String>();
 499  
 
 500  
                 // yelp if nulls were passed in
 501  0
                 if (bo == null) {
 502  0
                         throw new IllegalArgumentException("The Class passed in for the BusinessObject argument was null.");
 503  
                 }
 504  0
                 if (StringUtils.isBlank(referenceName)) {
 505  0
                         throw new IllegalArgumentException("The String passed in for the referenceName argument was null or empty.");
 506  
                 }
 507  
 
 508  0
                 PropertyDescriptor propertyDescriptor = null;
 509  
 
 510  
                 // make sure the attribute exists at all, throw exception if not
 511  
                 try {
 512  0
                         propertyDescriptor = PropertyUtils.getPropertyDescriptor(bo, referenceName);
 513  0
                 } catch (Exception e) {
 514  0
                         throw new RuntimeException(e);
 515  0
                 }
 516  0
                 if (propertyDescriptor == null) {
 517  0
                         throw new ReferenceAttributeDoesntExistException("Requested attribute: '" + referenceName + "' does not exist " + "on class: '" + bo.getClass().getName() + "'.");
 518  
                 }
 519  
 
 520  
                 // get the class of the attribute name
 521  0
                 Class referenceClass = propertyDescriptor.getPropertyType();
 522  
 
 523  
                 // make sure the class of the attribute descends from BusinessObject,
 524  
                 // otherwise throw an exception
 525  0
                 if (!PersistableBusinessObject.class.isAssignableFrom(referenceClass)) {
 526  0
                         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  
                 // make sure the attribute designated is listed as a
 530  
                 // reference-descriptor
 531  
                 // on the clazz specified, otherwise throw an exception (OJB);
 532  
 
 533  0
                 ClassDescriptor classDescriptor = getClassDescriptor(bo.getClass());
 534  
 
 535  
                 // This block is a combination of legacy and jpa
 536  0
                 ObjectReferenceDescriptor referenceDescriptor = classDescriptor.getObjectReferenceDescriptorByName(referenceName);
 537  0
                 if (referenceDescriptor == null) {
 538  0
                         throw new ReferenceAttributeNotAnOjbReferenceException("Attribute requested (" + referenceName + ") is not listed " + "in OJB as a reference-descriptor for class: '" + bo.getClass().getName() + "'");
 539  
                 }
 540  
 
 541  
                 // get the list of the foreign-keys for this reference-descriptor
 542  0
                 Vector fkFieldsLegacy = referenceDescriptor.getForeignKeyFields();
 543  0
                 Iterator fkIteratorLegacy = fkFieldsLegacy.iterator();
 544  
 
 545  
                 // walk through the list of the foreign keys, get their types
 546  0
                 while (fkIteratorLegacy.hasNext()) {
 547  
 
 548  
                         // get the field name of the fk & pk field
 549  0
                         String fkFieldName = (String) fkIteratorLegacy.next();
 550  
 
 551  
                         // get the value for the fk field
 552  0
                         Object fkFieldValue = null;
 553  
                         try {
 554  0
                                 fkFieldValue = PropertyUtils.getSimpleProperty(bo, fkFieldName);
 555  
                         }
 556  
 
 557  
                         // abort if the value is not retrievable
 558  0
                         catch (Exception e) {
 559  0
                                 throw new RuntimeException(e);
 560  0
                         }
 561  
 
 562  
                         // test the value
 563  0
                         if (fkFieldValue == null) {
 564  0
                                 allFieldsPopulated = false;
 565  0
                                 unpopulatedFields.add(fkFieldName);
 566  0
                         } else if (fkFieldValue instanceof String) {
 567  0
                                 if (StringUtils.isBlank((String) fkFieldValue)) {
 568  0
                                         allFieldsPopulated = false;
 569  0
                                         unpopulatedFields.add(fkFieldName);
 570  
                                 } else {
 571  0
                                         anyFieldsPopulated = true;
 572  
                                 }
 573  
                         } else {
 574  0
                                 anyFieldsPopulated = true;
 575  
                         }
 576  0
                 }
 577  
 
 578  
                 // sanity check. if the flag for all fields populated is set, then
 579  
                 // there should be nothing in the unpopulatedFields list
 580  0
                 if (allFieldsPopulated) {
 581  0
                         if (!unpopulatedFields.isEmpty()) {
 582  0
                                 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  0
                 return new ForeignKeyFieldsPopulationState(allFieldsPopulated, anyFieldsPopulated, unpopulatedFields);
 587  
         }
 588  
 
 589  
         /**
 590  
          * @see org.kuali.rice.krad.service.PersistenceStructureService#listReferenceObjectFieldNames(java.lang.Class)
 591  
          */
 592  
         
 593  
         public Map<String, Class> listReferenceObjectFields(Class boClass) {
 594  
                 // validate parameter
 595  0
                 if (boClass == null) {
 596  0
                         throw new IllegalArgumentException("Class specified in the parameter was null.");
 597  
                 }
 598  0
                 if (!PersistableBusinessObject.class.isAssignableFrom(boClass)) {
 599  0
                         throw new IllegalArgumentException("Class specified [" + boClass.getName() + "] must be a class that " + "inherits from BusinessObject.");
 600  
                 }
 601  
 
 602  0
                 Map<String, Class> references = new HashMap<String, Class>();
 603  0
                 ClassDescriptor classDescriptor = getClassDescriptor(boClass);
 604  0
                 Collection<ObjectReferenceDescriptor> referenceDescriptors = classDescriptor.getObjectReferenceDescriptors(true);
 605  
 
 606  0
                 for (ObjectReferenceDescriptor referenceDescriptor : referenceDescriptors) {
 607  
                         /*
 608  
              * Below check is performed for OJB specific inheritance implementation. For more information see the OJB
 609  
              * documentation: http://db.apache.org/ojb/docu/guides/advanced-technique.html#table-per-subclass
 610  
              */
 611  0
             String superReferenceDescriptor = referenceDescriptor.getAttributeName();
 612  0
             if (!SuperReferenceDescriptor.SUPER_FIELD_INTERNAL_NAME.equals(superReferenceDescriptor)) {
 613  0
                 references.put(superReferenceDescriptor, referenceDescriptor.getItemClass());
 614  
             }
 615  0
                 }
 616  
                 
 617  0
                 return references;
 618  
         }
 619  
 
 620  
         
 621  
         public Map<String, Class> listCollectionObjectTypes(Class boClass) {
 622  0
                 if (boClass == null) {
 623  0
                         throw new IllegalArgumentException("Class specified in the parameter was null.");
 624  
                 }
 625  
 
 626  0
                 Map<String, Class> references = new HashMap<String, Class>();
 627  0
                 ClassDescriptor classDescriptor = null;
 628  
                 try {
 629  0
                         classDescriptor = getClassDescriptor(boClass);
 630  0
                 } catch (ClassNotPersistableException cnpe) {
 631  0
                         return references;
 632  0
                 }
 633  
 
 634  0
                 Collection<CollectionDescriptor> collectionDescriptors = classDescriptor.getCollectionDescriptors(true);
 635  0
                 for (CollectionDescriptor collectionDescriptor : collectionDescriptors) {
 636  0
                         references.put(collectionDescriptor.getAttributeName(), collectionDescriptor.getItemClass());
 637  
                 }
 638  
                 
 639  0
                 return references;
 640  
         }
 641  
 
 642  
         public Map<String, Class> listCollectionObjectTypes(PersistableBusinessObject bo) {
 643  
                 // validate parameter
 644  0
                 if (bo == null) {
 645  0
                         throw new IllegalArgumentException("BO specified in the parameter was null.");
 646  
                 }
 647  0
                 if (!(bo instanceof PersistableBusinessObject)) {
 648  0
                         throw new IllegalArgumentException("BO specified [" + bo.getClass().getName() + "] must be a class that " + "inherits from BusinessObject.");
 649  
                 }
 650  
 
 651  0
                 return listCollectionObjectTypes(bo.getClass());
 652  
         }
 653  
 
 654  
         /**
 655  
          * @see org.kuali.rice.krad.service.PersistenceStructureService#listReferenceObjectFieldNames(org.kuali.rice.krad.bo.BusinessObject)
 656  
          */
 657  
         public Map<String, Class> listReferenceObjectFields(PersistableBusinessObject bo) {
 658  
                 // validate parameter
 659  0
                 if (bo == null) {
 660  0
                         throw new IllegalArgumentException("BO specified in the parameter was null.");
 661  
                 }
 662  0
                 if (!(bo instanceof PersistableBusinessObject)) {
 663  0
                         throw new IllegalArgumentException("BO specified [" + bo.getClass().getName() + "] must be a class that " + "inherits from BusinessObject.");
 664  
                 }
 665  
 
 666  0
                 return listReferenceObjectFields(bo.getClass());
 667  
         }
 668  
 
 669  
         
 670  
         public boolean isReferenceUpdatable(Class boClass, String referenceName) {
 671  0
                 ClassDescriptor classDescriptor = getClassDescriptor(boClass);
 672  0
                 ObjectReferenceDescriptor refDesc = classDescriptor.getObjectReferenceDescriptorByName(referenceName);
 673  0
                 return refDesc.getCascadingStore() != ObjectReferenceDescriptor.CASCADE_NONE;
 674  
         }
 675  
 
 676  
         
 677  
         public boolean isCollectionUpdatable(Class boClass, String collectionName) {
 678  0
                 ClassDescriptor cd = getClassDescriptor(boClass);
 679  0
                 CollectionDescriptor collDesc = cd.getCollectionDescriptorByName(collectionName);
 680  0
                 return collDesc.getCascadingStore() != ObjectReferenceDescriptor.CASCADE_NONE;
 681  
         }
 682  
 
 683  
         
 684  
         public boolean hasCollection(Class boClass, String collectionName) {
 685  0
                 ClassDescriptor cd = getClassDescriptor(boClass);
 686  0
                 return cd.getCollectionDescriptorByName(collectionName) != null;
 687  
         }
 688  
 
 689  
         
 690  
         public boolean hasReference(Class boClass, String referenceName) {
 691  0
                 ClassDescriptor cd = getClassDescriptor(boClass);
 692  0
                 return cd.getObjectReferenceDescriptorByName(referenceName) != null;
 693  
         }
 694  
 
 695  
         /**
 696  
          * This overridden method ...
 697  
          * 
 698  
          * @see org.kuali.rice.krad.service.PersistenceStructureService#getTableName(java.lang.Class)
 699  
          */
 700  
         
 701  
         public String getTableName(Class<? extends PersistableBusinessObject> boClass) {
 702  0
                 ClassDescriptor cd = getClassDescriptor(boClass);
 703  0
                 return cd.getFullTableName();
 704  
         }
 705  
         
 706  
         
 707  
 }
 708