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