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