Coverage Report - org.kuali.rice.kns.service.impl.PersistenceStructureServiceJpaImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
PersistenceStructureServiceJpaImpl
0%
0/237
0%
0/134
5.292
 
 1  
 /*
 2  
  * Copyright 2006-2008 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.kns.service.impl;
 17  
 
 18  
 import java.beans.PropertyDescriptor;
 19  
 import java.util.ArrayList;
 20  
 import java.util.Collection;
 21  
 import java.util.HashMap;
 22  
 import java.util.Iterator;
 23  
 import java.util.List;
 24  
 import java.util.Map;
 25  
 import java.util.Set;
 26  
 
 27  
 import javax.persistence.CascadeType;
 28  
 
 29  
 import org.apache.commons.beanutils.PropertyUtils;
 30  
 import org.apache.commons.lang.StringUtils;
 31  
 import org.kuali.rice.core.jpa.metadata.EntityDescriptor;
 32  
 import org.kuali.rice.core.jpa.metadata.JoinColumnDescriptor;
 33  
 import org.kuali.rice.core.jpa.metadata.MetadataManager;
 34  
 import org.kuali.rice.core.jpa.metadata.ObjectDescriptor;
 35  
 import org.kuali.rice.kns.bo.BusinessObjectRelationship;
 36  
 import org.kuali.rice.kns.bo.PersistableBusinessObject;
 37  
 import org.kuali.rice.kim.bo.Person;
 38  
 import org.kuali.rice.kns.exception.ObjectNotABusinessObjectRuntimeException;
 39  
 import org.kuali.rice.kns.exception.ReferenceAttributeDoesntExistException;
 40  
 import org.kuali.rice.kns.exception.ReferenceAttributeNotAnOjbReferenceException;
 41  
 import org.kuali.rice.kns.service.PersistenceStructureService;
 42  
 import org.kuali.rice.kns.util.ForeignKeyFieldsPopulationState;
 43  
 import org.kuali.rice.kns.util.spring.Cached;
 44  
 
 45  0
 public class PersistenceStructureServiceJpaImpl 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  
          * @see org.kuali.rice.kns.service.PersistenceService#isPersistable(java.lang.Class)
 66  
          */
 67  
         @Cached
 68  
         public boolean isPersistable(Class clazz) {
 69  0
                 boolean isPersistable = false;
 70  
 
 71  0
                 if (MetadataManager.getEntityDescriptor(clazz) != null) {
 72  0
                         isPersistable = true;
 73  
                 }
 74  
 
 75  0
                 return isPersistable;
 76  
         }
 77  
 
 78  
         /**
 79  
          * @see org.kuali.rice.kns.service.PersistenceService#getPrimaryKeys(java.lang.Class)
 80  
          */
 81  
         @Cached
 82  
         public List getPrimaryKeys(Class clazz) {
 83  0
                 List pkList = new ArrayList();
 84  
 
 85  0
                 EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(clazz);
 86  0
                 for (org.kuali.rice.core.jpa.metadata.FieldDescriptor field : descriptor.getPrimaryKeys()) {
 87  0
                         pkList.add(field.getName());
 88  
                 }
 89  
 
 90  0
                 return pkList;
 91  
         }
 92  
 
 93  
         /**
 94  
          * @see org.kuali.rice.kns.service.PersistenceMetadataExplorerService#listFieldNames(java.lang.Class)
 95  
          */
 96  
         @Cached
 97  
         public List listFieldNames(Class clazz) {
 98  0
                 List fieldNames = new ArrayList();
 99  
 
 100  0
                 EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(clazz);
 101  0
                 for (org.kuali.rice.core.jpa.metadata.FieldDescriptor field : descriptor.getFields()) {
 102  0
                         fieldNames.add(field.getName());
 103  
                 }
 104  
 
 105  0
                 return fieldNames;
 106  
         }
 107  
 
 108  
         /**
 109  
          * @see org.kuali.rice.kns.service.PersistenceMetadataService#clearPrimaryKeyFields(java.lang.Object)
 110  
          */
 111  
         // Unit tests only
 112  
         // TODO: Write JPA Version
 113  
         public Object clearPrimaryKeyFields(Object persistableObject) {
 114  
                 /*
 115  
                  * if (persistableObject == null) { throw new
 116  
                  * IllegalArgumentException("invalid (null) persistableObject"); }
 117  
                  * 
 118  
                  * String className = null; String fieldName = null; try { className =
 119  
                  * persistableObject.getClass().getName(); List fields =
 120  
                  * listPrimaryKeyFieldNames(persistableObject.getClass()); for (Iterator
 121  
                  * i = fields.iterator(); i.hasNext();) { fieldName = (String) i.next();
 122  
                  * 
 123  
                  * PropertyUtils.setProperty(persistableObject, fieldName, null); }
 124  
                  * 
 125  
                  * if (persistableObject instanceof PersistableBusinessObject) {
 126  
                  * ((PersistableBusinessObject) persistableObject).setObjectId(null); } }
 127  
                  * catch (NoSuchMethodException e) { throw new
 128  
                  * IntrospectionException("no setter for property '" + className + "." +
 129  
                  * fieldName + "'", e); } catch (IllegalAccessException e) { throw new
 130  
                  * IntrospectionException("problem accessing property '" + className +
 131  
                  * "." + fieldName + "'", e); } catch (InvocationTargetException e) {
 132  
                  * throw new IntrospectionException("problem invoking getter for
 133  
                  * property '" + className + "." + fieldName + "'", e); }
 134  
                  */
 135  0
                 return persistableObject;
 136  
         }
 137  
 
 138  
         /**
 139  
          * @see org.kuali.rice.kns.service.PersistenceMetadataExplorerService#listPersistableSubclasses(java.lang.Class)
 140  
          */
 141  
         @Cached
 142  
         // Unit tests only
 143  
         // TODO: Write JPA Version
 144  
         public List listPersistableSubclasses(Class superclazz) {
 145  0
                 List persistableSubclasses = new ArrayList();
 146  
                 /*
 147  
                  * if (superclazz == null) { throw new IllegalArgumentException("invalid
 148  
                  * (null) uberclass"); }
 149  
                  * 
 150  
                  * Map allDescriptors = getDescriptorRepository().getDescriptorTable();
 151  
                  * for (Iterator i = allDescriptors.entrySet().iterator(); i.hasNext();) {
 152  
                  * Map.Entry e = (Map.Entry) i.next();
 153  
                  * 
 154  
                  * Class persistableClass = ((ClassDescriptor)
 155  
                  * e.getValue()).getClassOfObject(); if
 156  
                  * (!superclazz.equals(persistableClass) &&
 157  
                  * superclazz.isAssignableFrom(persistableClass)) {
 158  
                  * persistableSubclasses.add(persistableClass); } }
 159  
                  */
 160  0
                 return persistableSubclasses;
 161  
         }
 162  
 
 163  
         /**
 164  
          * @see org.kuali.rice.kns.service.PersistenceService#getRelationshipMetadata(java.lang.Class,
 165  
          *      java.lang.String)
 166  
          */
 167  
         @Cached
 168  
         public Map<String, BusinessObjectRelationship> getRelationshipMetadata(Class persistableClass, String attributeName, String attributePrefix) {
 169  0
                 if (persistableClass == null) {
 170  0
                         throw new IllegalArgumentException("invalid (null) persistableClass");
 171  
                 }
 172  0
                 if (StringUtils.isBlank(attributeName)) {
 173  0
                         throw new IllegalArgumentException("invalid (blank) attributeName");
 174  
                 }
 175  
 
 176  0
                 Map<String, BusinessObjectRelationship> relationships = new HashMap<String, BusinessObjectRelationship>();
 177  
 
 178  0
                 EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(persistableClass);
 179  0
                 for (ObjectDescriptor objectDescriptor : descriptor.getObjectRelationships()) {
 180  0
                         List<String> fks = objectDescriptor.getForeignKeyFields();
 181  0
                         if (fks.contains(attributeName) || objectDescriptor.getAttributeName().equals(attributeName)) {
 182  0
                                 Map<String, String> fkToPkRefs = getForeignKeysForReference(persistableClass, objectDescriptor.getAttributeName());
 183  0
                                 BusinessObjectRelationship rel = new BusinessObjectRelationship(persistableClass, objectDescriptor.getAttributeName(), objectDescriptor.getTargetEntity());
 184  0
                                 for (Map.Entry<String, String> ref : fkToPkRefs.entrySet()) {
 185  0
                                         if (StringUtils.isBlank(attributePrefix)) {
 186  0
                                                 rel.getParentToChildReferences().put(ref.getKey(), ref.getValue());
 187  
                                         } else {
 188  0
                                                 rel.getParentToChildReferences().put(attributePrefix + "." + ref.getKey(), ref.getValue());
 189  
                                         }
 190  
                                 }
 191  0
                                 relationships.put(objectDescriptor.getAttributeName(), rel);
 192  
                         }
 193  0
                 }
 194  
 
 195  0
                 return relationships;
 196  
         }
 197  
 
 198  
         @Cached
 199  
         // Unit tests only
 200  
         public Map<String, BusinessObjectRelationship> getRelationshipMetadata(Class persistableClass, String attributeName) {
 201  0
                 return getRelationshipMetadata(persistableClass, attributeName, null);
 202  
         }
 203  
 
 204  
         /**
 205  
          * @see org.kuali.rice.kns.service.PersistenceService#getForeignKeyFieldName(java.lang.Object,
 206  
          *      java.lang.String, java.lang.String)
 207  
          */
 208  
         @Cached
 209  
         public String getForeignKeyFieldName(Class persistableObjectClass, String attributeName, String pkName) {
 210  0
                 String fkName = null;
 211  
 
 212  0
                 EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(persistableObjectClass);
 213  0
                 ObjectDescriptor objectDescriptor = descriptor.getObjectDescriptorByName(attributeName);
 214  0
                 if (objectDescriptor == null) {
 215  0
                         throw new RuntimeException("Attribute name " + attributeName + " is not a valid reference to class " + persistableObjectClass.getName());
 216  
                 }
 217  0
                 List<org.kuali.rice.core.jpa.metadata.FieldDescriptor> matches = new ArrayList<org.kuali.rice.core.jpa.metadata.FieldDescriptor>();
 218  0
                 for (org.kuali.rice.core.jpa.metadata.FieldDescriptor field : descriptor.getFields()) {
 219  0
                         String column = field.getColumn();
 220  0
                         for (JoinColumnDescriptor join : objectDescriptor.getJoinColumnDescriptors()) {
 221  0
                                 if (column != null && column.equals(join.getName())) {
 222  0
                                         matches.add(field);
 223  
                                 }
 224  
                         }
 225  0
                 }
 226  
 
 227  0
                 if (matches.size() == 1) {
 228  0
                         fkName = matches.get(0).getName();
 229  
                 } else {
 230  0
                         throw new RuntimeException("Implement me!");
 231  
                 }
 232  
 
 233  0
                 return fkName;
 234  
         }
 235  
 
 236  
         /**
 237  
          * @see org.kuali.rice.kns.service.PersistenceService#getReferencesForForeignKey(java.lang.Class,
 238  
          *      java.lang.String)
 239  
          */
 240  
         @Cached
 241  
         public Map getReferencesForForeignKey(Class persistableObjectClass, String attributeName) {
 242  0
                 Map referenceClasses = new HashMap();
 243  
 
 244  0
                 if (PersistableBusinessObject.class.isAssignableFrom(persistableObjectClass)) {
 245  0
                         EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(persistableObjectClass);
 246  0
                         for (ObjectDescriptor objectDescriptor : descriptor.getObjectRelationships()) {
 247  0
                                 List<String> refFkNames = objectDescriptor.getForeignKeyFields();
 248  0
                                 for (String fk : refFkNames) {
 249  0
                                         if (fk.equals(attributeName)) {
 250  0
                                                 referenceClasses.put(objectDescriptor.getAttributeName(), objectDescriptor.getTargetEntity());
 251  
                                         }
 252  
                                 }
 253  0
                         }
 254  
                 }
 255  
 
 256  0
                 return referenceClasses;
 257  
         }
 258  
 
 259  
         /**
 260  
          * @see org.kuali.rice.kns.service.PersistenceService#getForeignKeysForReference(java.lang.Class,
 261  
          *      java.lang.String) The Map structure is: Key(String fkFieldName) =>
 262  
          *      Value(String pkFieldName) NOTE that this implementation depends on
 263  
          *      the ordering of foreign-key elements in the ojb-repository matching
 264  
          *      the ordering of primary-key declarations of the class on the other
 265  
          *      side of the relationship. This is done because: 1. The current
 266  
          *      version of OJB requires you to declare all of these things in the
 267  
          *      correct (and matching) order in the ojb-repository file for it to
 268  
          *      work at all. 2. There is no other way to match a given foreign-key
 269  
          *      reference to its corresponding primary-key on the opposing side of
 270  
          *      the relationship. Yes, this is a crummy way to do it, but OJB doesnt
 271  
          *      provide explicit matches of foreign-keys to primary keys, and always
 272  
          *      assumes that foreign-keys map to primary keys on the other object,
 273  
          *      and never to a set of candidate keys, or any other column.
 274  
          */
 275  
         @Cached
 276  
         public Map getForeignKeysForReference(Class clazz, String attributeName) {
 277  
 
 278  
                 // yelp if nulls were passed in
 279  0
                 if (clazz == null) {
 280  0
                         throw new IllegalArgumentException("The Class passed in for the clazz argument was null.");
 281  
                 }
 282  0
                 if (attributeName == null) {
 283  0
                         throw new IllegalArgumentException("The String passed in for the attributeName argument was null.");
 284  
                 }
 285  
 
 286  
                 // get the class of the attribute name
 287  0
                 Class attributeClass = getBusinessObjectAttributeClass(clazz, attributeName);
 288  0
                 if (attributeClass == null) {
 289  0
                         throw new ReferenceAttributeDoesntExistException("Requested attribute: '" + attributeName + "' does not exist on class: '" + clazz.getName() + "'.");
 290  
                 }
 291  
 
 292  
                 // make sure the class of the attribute descends from BusinessObject,
 293  
                 // otherwise throw an exception
 294  0
                 if (!PersistableBusinessObject.class.isAssignableFrom(attributeClass)) {
 295  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.");
 296  
                 }
 297  
 
 298  0
                 return determineFkMap(clazz, attributeName, attributeClass);
 299  
         }
 300  
 
 301  
         private Map determineFkMap(Class clazz, String attributeName, Class attributeClass) {
 302  0
                 Map fkMap = new HashMap();
 303  0
                 EntityDescriptor entityDescriptor = MetadataManager.getEntityDescriptor(clazz);
 304  0
                 ObjectDescriptor objectDescriptor = entityDescriptor.getObjectDescriptorByName(attributeName);
 305  0
                 if (objectDescriptor == null) {
 306  0
                         throw new ReferenceAttributeNotAnOjbReferenceException("Attribute requested (" + attributeName + ") is not defined in JPA annotations for class: '" + clazz.getName() + "'");
 307  
                 }
 308  
 
 309  
                 // special case when the attributeClass passed in doesnt match the
 310  
                 // class of the reference-descriptor as defined in ojb-repository.
 311  
                 // Currently
 312  
                 // the only case of this happening is ObjectCode vs.
 313  
                 // ObjectCodeCurrent.
 314  0
                 if (!attributeClass.equals(objectDescriptor.getTargetEntity())) {
 315  0
                         if (referenceConversionMap.containsKey(attributeClass)) {
 316  0
                                 attributeClass = referenceConversionMap.get(attributeClass);
 317  
                         } else {
 318  0
                                 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.");
 319  
                         }
 320  
                 }
 321  
 
 322  
                 // get the list of the foreign-keys for this reference-descriptor
 323  
                 // (OJB)
 324  0
                 List<String> fkFields = objectDescriptor.getForeignKeyFields();
 325  0
                 Iterator<String> fkIterator = fkFields.iterator();
 326  
 
 327  
                 // get the list of the corresponding pk fields on the other side of
 328  
                 // the relationship
 329  0
                 List pkFields = getPrimaryKeys(attributeClass);
 330  0
                 Iterator pkIterator = pkFields.iterator();
 331  
 
 332  
                 // make sure the size of the pkIterator is the same as the
 333  
                 // size of the fkIterator, otherwise this whole thing is borked
 334  0
                 if (pkFields.size() != fkFields.size()) {
 335  0
                         throw new RuntimeException("KualiPersistenceStructureService Error: The number of " + "foreign keys doesnt match the number of primary keys.");
 336  
                 }
 337  
 
 338  
                 // walk through the list of the foreign keys, get their types
 339  0
                 while (fkIterator.hasNext()) {
 340  
                         // if there is a next FK but not a next PK, then we've got a big
 341  
                         // problem,
 342  
                         // and cannot continue
 343  0
                         if (!pkIterator.hasNext()) {
 344  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.");
 345  
                         }
 346  
 
 347  
                         // get the field name of the fk & pk field
 348  0
                         String fkFieldName = (String) fkIterator.next();
 349  0
                         String pkFieldName = (String) pkIterator.next();
 350  
 
 351  
                         // add the fieldName and fieldType to the map
 352  0
                         fkMap.put(fkFieldName, pkFieldName);
 353  0
                 }
 354  0
                 return fkMap;
 355  
         }
 356  
 
 357  
         @Cached
 358  
         public Map<String, String> getInverseForeignKeysForCollection(Class boClass, String collectionName) {
 359  
                 // yelp if nulls were passed in
 360  0
                 if (boClass == null) {
 361  0
                         throw new IllegalArgumentException("The Class passed in for the boClass argument was null.");
 362  
                 }
 363  0
                 if (collectionName == null) {
 364  0
                         throw new IllegalArgumentException("The String passed in for the attributeName argument was null.");
 365  
                 }
 366  
 
 367  0
                 PropertyDescriptor propertyDescriptor = null;
 368  
 
 369  
                 // make an instance of the class passed
 370  
                 Object classInstance;
 371  
                 try {
 372  0
                         classInstance = boClass.newInstance();
 373  0
                 } catch (Exception e) {
 374  0
                         throw new RuntimeException(e);
 375  0
                 }
 376  
 
 377  
                 // make sure the attribute exists at all, throw exception if not
 378  
                 try {
 379  0
                         propertyDescriptor = PropertyUtils.getPropertyDescriptor(classInstance, collectionName);
 380  0
                 } catch (Exception e) {
 381  0
                         throw new RuntimeException(e);
 382  0
                 }
 383  0
                 if (propertyDescriptor == null) {
 384  0
                         throw new ReferenceAttributeDoesntExistException("Requested attribute: '" + collectionName + "' does not exist " + "on class: '" + boClass.getName() + "'. GFK");
 385  
                 }
 386  
 
 387  
                 // get the class of the attribute name
 388  0
                 Class attributeClass = propertyDescriptor.getPropertyType();
 389  
 
 390  
                 // make sure the class of the attribute descends from BusinessObject,
 391  
                 // otherwise throw an exception
 392  0
                 if (!Collection.class.isAssignableFrom(attributeClass)) {
 393  0
                         throw new ObjectNotABusinessObjectRuntimeException("Attribute requested (" + collectionName + ") is of class: " + "'" + attributeClass.getName() + "' and is not a " + "descendent of Collection");
 394  
                 }
 395  
 
 396  0
                 EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(boClass);
 397  0
                 org.kuali.rice.core.jpa.metadata.CollectionDescriptor cd = descriptor.getCollectionDescriptorByName(collectionName);
 398  0
                 List<String> childPrimaryKeys = cd.getForeignKeyFields();
 399  
 
 400  0
                 List parentForeignKeys = getPrimaryKeys(boClass);
 401  
 
 402  0
                 if (parentForeignKeys.size() != childPrimaryKeys.size()) {
 403  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.");
 404  
                 }
 405  
 
 406  0
                 Map<String, String> fkToPkMap = new HashMap<String, String>();
 407  0
                 Iterator pFKIter = parentForeignKeys.iterator();
 408  0
                 Iterator cPKIterator = childPrimaryKeys.iterator();
 409  
 
 410  0
                 while (pFKIter.hasNext()) {
 411  0
                         String parentForeignKey = (String) pFKIter.next();
 412  0
                         String childPrimaryKey = (String) cPKIterator.next();
 413  
 
 414  0
                         fkToPkMap.put(parentForeignKey, childPrimaryKey);
 415  0
                 }
 416  0
                 return fkToPkMap;
 417  
         }
 418  
 
 419  
         /**
 420  
          * @see org.kuali.rice.kns.service.PersistenceService#getNestedForeignKeyMap(java.lang.Class)
 421  
          */
 422  
         @Cached
 423  
         public Map getNestedForeignKeyMap(Class persistableObjectClass) {
 424  0
                 Map fkMap = new HashMap();
 425  
 
 426  
                 // Rice JPA MetadataManager
 427  
                 // Note: Not sure how to test this method, and JPA and OJB ordering of
 428  
                 // PK/FK is not the same as well. This should be tested more thoroughly.
 429  0
                 EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(persistableObjectClass);
 430  0
                 for (ObjectDescriptor objectReferenceDescriptor : descriptor.getObjectRelationships()) {
 431  0
                         EntityDescriptor referenceDescriptor = MetadataManager.getEntityDescriptor(objectReferenceDescriptor.getTargetEntity());
 432  0
                         List<String> fkFields = objectReferenceDescriptor.getForeignKeyFields();
 433  0
                         Set<org.kuali.rice.core.jpa.metadata.FieldDescriptor> pkFields = referenceDescriptor.getPrimaryKeys();
 434  0
                         int i = 0;
 435  0
                         for (org.kuali.rice.core.jpa.metadata.FieldDescriptor fd : pkFields) {
 436  0
                                 fkMap.put(objectReferenceDescriptor.getAttributeName() + "." + fd.getName(), fkFields.get(i));
 437  0
                                 i++;
 438  
                         }
 439  0
                 }
 440  
 
 441  0
                 return fkMap;
 442  
         }
 443  
 
 444  
         /**
 445  
          * @see org.kuali.rice.kns.service.PersistenceMetadataService#hasPrimaryKeyFieldValues(java.lang.Object)
 446  
          */
 447  
         public boolean hasPrimaryKeyFieldValues(Object persistableObject) {
 448  0
                 Map keyFields = getPrimaryKeyFieldValues(persistableObject);
 449  
 
 450  0
                 boolean emptyField = false;
 451  0
                 for (Iterator i = keyFields.entrySet().iterator(); !emptyField && i.hasNext();) {
 452  0
                         Map.Entry e = (Map.Entry) i.next();
 453  
 
 454  0
                         Object fieldValue = e.getValue();
 455  0
                         if (fieldValue == null) {
 456  0
                                 emptyField = true;
 457  0
                         } else if (fieldValue instanceof String) {
 458  0
                                 if (StringUtils.isEmpty((String) fieldValue)) {
 459  0
                                         emptyField = true;
 460  
                                 } else {
 461  0
                                         emptyField = false;
 462  
                                 }
 463  
                         }
 464  0
                 }
 465  
 
 466  0
                 return !emptyField;
 467  
         }
 468  
 
 469  
         /**
 470  
          * @see org.kuali.rice.kns.service.PersistenceService#getForeignKeyFieldsPopulationState(org.kuali.rice.kns.bo.BusinessObject,
 471  
          *      java.lang.String)
 472  
          */
 473  
         public ForeignKeyFieldsPopulationState getForeignKeyFieldsPopulationState(PersistableBusinessObject bo, String referenceName) {
 474  
 
 475  0
                 boolean allFieldsPopulated = true;
 476  0
                 boolean anyFieldsPopulated = false;
 477  0
                 List<String> unpopulatedFields = new ArrayList<String>();
 478  
 
 479  
                 // yelp if nulls were passed in
 480  0
                 if (bo == null) {
 481  0
                         throw new IllegalArgumentException("The Class passed in for the BusinessObject argument was null.");
 482  
                 }
 483  0
                 if (StringUtils.isBlank(referenceName)) {
 484  0
                         throw new IllegalArgumentException("The String passed in for the referenceName argument was null or empty.");
 485  
                 }
 486  
 
 487  0
                 PropertyDescriptor propertyDescriptor = null;
 488  
 
 489  
                 // make sure the attribute exists at all, throw exception if not
 490  
                 try {
 491  0
                         propertyDescriptor = PropertyUtils.getPropertyDescriptor(bo, referenceName);
 492  0
                 } catch (Exception e) {
 493  0
                         throw new RuntimeException(e);
 494  0
                 }
 495  0
                 if (propertyDescriptor == null) {
 496  0
                         throw new ReferenceAttributeDoesntExistException("Requested attribute: '" + referenceName + "' does not exist " + "on class: '" + bo.getClass().getName() + "'.");
 497  
                 }
 498  
 
 499  
                 // get the class of the attribute name
 500  0
                 Class referenceClass = propertyDescriptor.getPropertyType();
 501  
 
 502  
                 // make sure the class of the attribute descends from BusinessObject,
 503  
                 // otherwise throw an exception
 504  0
                 if (!PersistableBusinessObject.class.isAssignableFrom(referenceClass)) {
 505  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.");
 506  
                 }
 507  
 
 508  0
                 EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(bo.getClass());
 509  0
                 ObjectDescriptor objectDescriptor = descriptor.getObjectDescriptorByName(referenceName);
 510  
 
 511  0
                 if (objectDescriptor == null) {
 512  0
                         throw new ReferenceAttributeNotAnOjbReferenceException("Attribute requested (" + referenceName + ") is not listed " + "in OJB as a reference-descriptor for class: '" + bo.getClass().getName() + "'");
 513  
                 }
 514  
 
 515  0
                 List<String> fkFields = objectDescriptor.getForeignKeyFields();
 516  0
                 Iterator fkIterator = fkFields.iterator();
 517  
 
 518  
                 // walk through the list of the foreign keys, get their types
 519  0
                 while (fkIterator.hasNext()) {
 520  
 
 521  
                         // get the field name of the fk & pk field
 522  0
                         String fkFieldName = (String) fkIterator.next();
 523  
 
 524  
                         // get the value for the fk field
 525  0
                         Object fkFieldValue = null;
 526  
                         try {
 527  0
                                 fkFieldValue = PropertyUtils.getSimpleProperty(bo, fkFieldName);
 528  
                         }
 529  
 
 530  
                         // abort if the value is not retrievable
 531  0
                         catch (Exception e) {
 532  0
                                 throw new RuntimeException(e);
 533  0
                         }
 534  
 
 535  
                         // test the value
 536  0
                         if (fkFieldValue == null) {
 537  0
                                 allFieldsPopulated = false;
 538  0
                                 unpopulatedFields.add(fkFieldName);
 539  0
                         } else if (fkFieldValue instanceof String) {
 540  0
                                 if (StringUtils.isBlank((String) fkFieldValue)) {
 541  0
                                         allFieldsPopulated = false;
 542  0
                                         unpopulatedFields.add(fkFieldName);
 543  
                                 } else {
 544  0
                                         anyFieldsPopulated = true;
 545  
                                 }
 546  
                         } else {
 547  0
                                 anyFieldsPopulated = true;
 548  
                         }
 549  0
                 }
 550  
 
 551  
                 // sanity check. if the flag for all fields populated is set, then
 552  
                 // there should be nothing in the unpopulatedFields list
 553  0
                 if (allFieldsPopulated) {
 554  0
                         if (!unpopulatedFields.isEmpty()) {
 555  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.");
 556  
                         }
 557  
                 }
 558  
 
 559  0
                 return new ForeignKeyFieldsPopulationState(allFieldsPopulated, anyFieldsPopulated, unpopulatedFields);
 560  
         }
 561  
 
 562  
         /**
 563  
          * @see org.kuali.rice.kns.service.PersistenceStructureService#listReferenceObjectFieldNames(java.lang.Class)
 564  
          */
 565  
         @Cached
 566  
         public Map<String, Class> listReferenceObjectFields(Class boClass) {
 567  
                 // validate parameter
 568  0
                 if (boClass == null) {
 569  0
                         throw new IllegalArgumentException("Class specified in the parameter was null.");
 570  
                 }
 571  0
                 if (!PersistableBusinessObject.class.isAssignableFrom(boClass)) {
 572  0
                         throw new IllegalArgumentException("Class specified [" + boClass.getName() + "] must be a class that " + "inherits from BusinessObject.");
 573  
                 }
 574  
 
 575  0
                 EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(boClass);
 576  0
                 Map<String, Class> references = new HashMap();
 577  0
                 for (org.kuali.rice.core.jpa.metadata.ObjectDescriptor od : descriptor.getObjectRelationships()) {
 578  0
                         references.put(od.getAttributeName(), od.getTargetEntity());
 579  
                 }
 580  
 
 581  0
                 return references;
 582  
         }
 583  
 
 584  
         @Cached
 585  
         public Map<String, Class> listCollectionObjectTypes(Class boClass) {
 586  0
                 if (boClass == null) {
 587  0
                         throw new IllegalArgumentException("Class specified in the parameter was null.");
 588  
                 }
 589  
 
 590  0
                 Map<String, Class> references = new HashMap();
 591  
 
 592  0
                 EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(boClass);
 593  0
                 if (descriptor == null) {
 594  0
                         return references;
 595  
                 }
 596  
 
 597  0
                 for (org.kuali.rice.core.jpa.metadata.CollectionDescriptor cd : descriptor.getCollectionRelationships()) {
 598  0
                         references.put(cd.getAttributeName(), cd.getTargetEntity());
 599  
                 }
 600  
 
 601  0
                 return references;
 602  
         }
 603  
 
 604  
         public Map<String, Class> listCollectionObjectTypes(PersistableBusinessObject bo) {
 605  
                 // validate parameter
 606  0
                 if (bo == null) {
 607  0
                         throw new IllegalArgumentException("BO specified in the parameter was null.");
 608  
                 }
 609  0
                 if (!(bo instanceof PersistableBusinessObject)) {
 610  0
                         throw new IllegalArgumentException("BO specified [" + bo.getClass().getName() + "] must be a class that " + "inherits from BusinessObject.");
 611  
                 }
 612  
 
 613  0
                 return listCollectionObjectTypes(bo.getClass());
 614  
         }
 615  
 
 616  
         /**
 617  
          * @see org.kuali.rice.kns.service.PersistenceStructureService#listReferenceObjectFieldNames(org.kuali.rice.kns.bo.BusinessObject)
 618  
          */
 619  
         public Map<String, Class> listReferenceObjectFields(PersistableBusinessObject bo) {
 620  
                 // validate parameter
 621  0
                 if (bo == null) {
 622  0
                         throw new IllegalArgumentException("BO specified in the parameter was null.");
 623  
                 }
 624  0
                 if (!(bo instanceof PersistableBusinessObject)) {
 625  0
                         throw new IllegalArgumentException("BO specified [" + bo.getClass().getName() + "] must be a class that " + "inherits from BusinessObject.");
 626  
                 }
 627  
 
 628  0
                 return listReferenceObjectFields(bo.getClass());
 629  
         }
 630  
 
 631  
         @Cached
 632  
         public boolean isReferenceUpdatable(Class boClass, String referenceName) {
 633  0
                 EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(boClass);
 634  0
                 return descriptor.getObjectDescriptorByName(referenceName).isUpdateable();
 635  
 //                for (CascadeType ct : descriptor.getObjectDescriptorByName(referenceName).getCascade()) {
 636  
 //                        if (ct.equals(CascadeType.ALL) || ct.equals(CascadeType.MERGE) || ct.equals(CascadeType.PERSIST)) {
 637  
 //                                return true;
 638  
 //                        }
 639  
 //                }
 640  
 //                return false;
 641  
         }
 642  
 
 643  
         @Cached
 644  
         public boolean isCollectionUpdatable(Class boClass, String collectionName) {
 645  0
                 EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(boClass);
 646  0
                 return descriptor.getCollectionDescriptorByName(collectionName).isUpdateable();
 647  
 //                for (CascadeType ct : descriptor.getCollectionDescriptorByName(collectionName).getCascade()) {
 648  
 //                        if (ct.equals(CascadeType.ALL) || ct.equals(CascadeType.MERGE) || ct.equals(CascadeType.PERSIST)) {
 649  
 //                                return true;
 650  
 //                        }
 651  
 //                }
 652  
 //                return false;
 653  
         }
 654  
 
 655  
         @Cached
 656  
         public boolean hasCollection(Class boClass, String collectionName) {
 657  0
                 EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(boClass);
 658  0
                 return descriptor.getCollectionDescriptorByName(collectionName) != null;
 659  
         }
 660  
 
 661  
         @Cached
 662  
         public boolean hasReference(Class boClass, String referenceName) {
 663  0
                 EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(boClass);
 664  0
                 return descriptor.getObjectDescriptorByName(referenceName) != null;
 665  
         }
 666  
 
 667  
         /**
 668  
          * @see org.kuali.rice.kns.service.PersistenceStructureService#getTableName(java.lang.Class)
 669  
          */
 670  
         @Cached
 671  
         public String getTableName(Class<? extends PersistableBusinessObject> boClass) {
 672  0
                 EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(boClass);
 673  0
                 return descriptor.getTable();
 674  
         }
 675  
 }
 676