View Javadoc
1   /**
2    * Copyright 2005-2015 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;
17  
18  import java.lang.reflect.InvocationTargetException;
19  import java.util.Collection;
20  import java.util.List;
21  import java.util.Map;
22  
23  import org.kuali.rice.core.api.uif.RemotableQuickFinder;
24  import org.kuali.rice.krad.bo.DataObjectRelationship;
25  import org.kuali.rice.krad.util.ForeignKeyFieldsPopulationState;
26  
27  /**
28   * Adapter that supports "legacy" KNS/KRAD persistence, metadata, and object utility frameworks via runtime
29   * argument inspection
30   *
31   * @deprecated This class is deprecated by default, applications should *never*
32   * use this adapter directly
33   *
34   * @author Kuali Rice Team (rice.collab@kuali.org).
35   */
36  @Deprecated
37  public interface LegacyDataAppAdapter {
38  
39      // BusinessObjectService
40  
41      /**
42       * Saves the passed in object or list of objects via the persistence layer.
43       *
44       * @param dataObject the data object to save
45       */
46      <T> T save(T dataObject);
47  
48      /**
49       * Links up any contained objects, and then saves the passed in object via the persistence layer.
50       *
51       * @param dataObject the data object to link and save
52       */
53      <T> T linkAndSave(T dataObject);
54  
55      <T> T saveDocument(T document);
56  
57      /**
58       * Retrieves an object instance identified by its primary key. For composite keys, use {@link #findByPrimaryKey(Class, Map)}
59       *
60       * @param clazz data object type class
61       * @param primaryKey the primary key object
62       * @return data object instance
63       */
64      <T> T findBySinglePrimaryKey(Class<T> clazz, Object primaryKey);
65  
66      /**
67       * Retrieves an object instance identified by its primary keys and values. This can be done by constructing a map where the key
68       * to the map entry is the primary key attribute and the value of the entry being the primary key value. For composite keys,
69       * pass in each primaryKey attribute and its value as a map entry.
70       *
71       * @param clazz data object type class
72       * @param primaryKeys map of String->Object key values
73       * @return data object instance
74       */
75      <T> T findByPrimaryKey(Class<T> clazz, Map<String, ?> primaryKeys);
76  
77      /**
78       * Deletes a data object from the database.
79       *
80       * @param dataObject the data object to delete
81       */
82      void delete(Object dataObject);
83  
84      /**
85       * Deletes data objects from the database.
86       *
87       * @param clazz the entity type to delete
88       * @param fieldValues map String->Object of field values to match
89       */
90      public void deleteMatching(Class<?> clazz, Map<String, ?> fieldValues);
91      /**
92       * Retrieves an object instance identified by the class of the given object and the object's primary key values.
93       *
94       * @param dataObject the data object
95       * @return the retrieved data object or null if not found
96       */
97      <T> T retrieve(T dataObject);
98  
99      /**
100      * This method retrieves a collection of data objects populated with data, such that each record in the database populates a
101      * new object instance.This will only retrieve business objects by class type.
102      *
103      * @param clazz the data object type class
104      * @return collection of all data objects of given type
105      */
106     <T> Collection<T> findAll(Class<T> clazz);
107 
108     /**
109      * This method retrieves a collection of data objects populated with data, such that each record in the database populates a
110      * new object instance. This will retrieve data objects by class type and also by criteria passed in as key-value pairs,
111      * specifically attribute name and its expected value.
112      *
113      * @param clazz the data object type class
114      * @param fieldValues map String->Object of field values
115      * @return collection of matching data objects
116      */
117     <T> Collection<T> findMatching(Class<T> clazz, Map<String, ?> fieldValues);
118 
119     /**
120      * This method retrieves a collection of business objects populated with data, such that each record in the database populates a
121      * new object instance. This will retrieve business objects by class type and also by criteria passed in as key-value pairs,
122      * specifically attribute name and its expected value. Performs an order by on sort field.
123      *
124      * @param clazz
125      * @param fieldValues
126      * @return collection of business objects
127      */
128     <T> Collection<T> findMatchingOrderBy(Class<T> clazz, Map<String, ?> fieldValues, String sortField, boolean sortAscending);
129     // PersistenceService
130 
131     /**
132      * This method retrieves the primary key field values for the given data object
133      *
134      * @param dataObject data object whose primary key field name,value pairs you want
135      * @return a Map containing the names and values of primary key fields for the data object
136      * @throws IllegalArgumentException if the given Object is null
137      * @throws org.kuali.rice.krad.exception.ClassNotPersistableException if the given object is of a type not mapped in ORM
138      */
139     Map<String, ?> getPrimaryKeyFieldValues(Object dataObject);
140 
141     /**
142      * @param persistableObject object whose objects need to be filled in based on primary keys
143      * @throws IllegalArgumentException if the given Object is null
144      * @throws org.kuali.rice.krad.exception.ClassNotPersistableException if the given object is of a type not described in the OJB repository
145      */
146     void retrieveNonKeyFields(Object persistableObject);
147 
148     /**
149      * @param persistableObject object whose specified reference object needs to be filled in based on primary keys
150      * @param referenceObjectName the name of the reference object that will be filled in based on primary key values
151      * @throws IllegalArgumentException if the given Object is null
152      * @throws org.kuali.rice.krad.exception.ClassNotPersistableException if the given object is of a type not described in the OJB repository
153      */
154     void retrieveReferenceObject(Object persistableObject, String referenceObjectName);
155 
156     /**
157      * This method refreshes all reference objects to this main object that are 'non-updateable'. In general, this means that if a
158      * reference object is configured to not be updated when the parent document is saved, then they are non-updated.
159      * This will not refresh updateable objects, which can cause problems when you're creating new objects.
160      * See PersistenceServiceImpl.isUpdateableReference() for the full logic.
161      * @param persistableObject - the businessObject to be refreshed
162      */
163     void refreshAllNonUpdatingReferences(Object persistableObject);
164 
165     /**
166      * Returns the object underlying any ORM proxy layers
167      * @param o the object for which to determine the underlying non-ORM-proxy target
168      * @return the underlying non-ORM-proxy object
169      */
170     Object resolveProxy(Object o);
171 
172     /**
173      * Returns whether the object is an ORM proxy
174      * @param object the candidate object
175      * @return true if the object is an ORM proxy
176      */
177     boolean isProxied(Object object);
178 
179     // LookupService
180 
181     /**
182      * Returns a collection of objects based on the given search parameters.
183      * Search results are bounded by the KNS search results limit determined for the class.
184      *
185      * @param clazz the data object type
186      * @param formProps field values for query
187      * @param unbounded whether the search results should be bounded
188      * @param allPrimaryKeyValuesPresentAndNotWildcard indicates whether or not the search only contains non-wildcarded primary key values
189      * @param searchResultsLimit if the search is bounded, the search results limit, otherwise ignored. null is equivalent to KNS default for the clazz
190      * @return collection of matching data objects
191      * @deprecated please use {@link #findCollectionBySearchHelper(Class, java.util.Map, java.util.List, boolean, boolean, Integer)}  instead
192      */
193     @Deprecated
194     <T> Collection<T> findCollectionBySearchHelper(Class<T> clazz, Map<String, String> formProps, boolean unbounded,
195             boolean allPrimaryKeyValuesPresentAndNotWildcard, Integer searchResultsLimit);
196 
197     /**
198      * Returns a collection of objects based on the given search parameters.
199      *
200      * <p>
201      * Search results are bounded by the KNS search results limit determined for the class.
202      * This implementation further isolates the UIFramework from the LookupService and should be used
203      * in place of the deprecated method.
204      * </p>
205      *
206      * @param clazz the data object type
207      * @param formProps field values for query
208      * @param wildcardAsLiteralPropertyNames list of fields for query that do not allow wildcards
209      * @param unbounded whether the search results should be bounded
210      * @param allPrimaryKeyValuesPresentAndNotWildcard indicates whether or not the search only contains non-wildcarded primary key values
211      * @param searchResultsLimit if the search is bounded, the search results limit, otherwise ignored. null is equivalent to KNS default for the clazz
212      * @return collection of matching data objects
213      */
214     <T> Collection<T> findCollectionBySearchHelper(Class<T> clazz, Map<String, String> formProps,
215             List<String> wildcardAsLiteralPropertyNames, boolean unbounded,
216             boolean allPrimaryKeyValuesPresentAndNotWildcard, Integer searchResultsLimit);
217 
218     /**
219      * Retrieves a Object based on the search criteria, which should uniquely
220      * identify a record.
221      *
222      * @param clazz the data object type
223      * @param formProps field values for query
224      * @return first object in returned search results, or null if none found
225      */
226     <T> T findObjectBySearch(Class<T> clazz, Map<String, String> formProps);
227 
228     boolean allPrimaryKeyValuesPresentAndNotWildcard(Class<?> boClass, Map<String, String> formProps);
229 
230     // DAO interfaces are hoisted for krad or krad/kns shared services which still need to be preserved.
231     // they will internally call LegacyDataAdapter
232 
233     // PersistenceStructureService
234 
235     /**
236      * Returns a list of primary key field names for the given class.
237      */
238     List<String> listPrimaryKeyFieldNames(Class<?> clazz);
239 
240     /**
241      * Determines the type of the collection object on the class with the collection with the given property name.
242      *
243      * @param containingClass the class of the object containing the collection
244      * @param collectionPropertyName the name of the property identifying the collection
245      *
246      * @return the Class of elements in the identified collection
247      *
248      * @throws IllegalArgumentException if the given class is not available in metadata or if the given collection property name is incorrect
249      */
250     Class<?> determineCollectionObjectType(Class<?> containingClass, String collectionPropertyName);
251 
252     /**
253      *
254      * This method checks the foreign keys for a reference on a given BO, and tests that all fk fields are populated if any are
255      * populated.
256      *
257      * In other words, for a given reference, it finds all the attributes of the BO that make up the foreign keys, and checks to see
258      * if they all have values. It also keeps a list of all the fieldNames that do not have values.
259      *
260      * @param bo - A populated BusinessObject descendent. Must contain an attributed named referenceName.
261      * @param referenceName - The name of the field that is a reference we are analyzing.
262      * @return A populated ForeignKeyFieldsPopulation object which represents the state of population for the foreign key fields.
263      */
264     ForeignKeyFieldsPopulationState getForeignKeyFieldsPopulationState(Object bo, String referenceName);
265 
266     /**
267      *
268      * This method will return a Map of all the foreign key fields and the corresponding primary key fields for a given reference.
269      *
270      * The Map structure is: Key(String fkFieldName) => Value(String pkFieldName)
271      *
272      * @param clazz - Class that contains the named reference
273      * @param attributeName - Name of the member that is the reference you want foreign keys for
274      * @return returns a Map populated as described above, with one entry per foreign key field
275      *
276      */
277     Map<String,String> getForeignKeysForReference(Class<?> clazz, String attributeName);
278 
279     /**
280      * @param persistableObject
281      * @return true if all primary key fields of the string have a non-null (and non-empty, for Strings) value
282      * @throws IllegalArgumentException if the given Object is null
283      * @throws org.kuali.rice.krad.exception.ClassNotPersistableException if the given object is of a type not described in the OJB repository
284      */
285     boolean hasPrimaryKeyFieldValues(Object persistableObject);
286 
287     /**
288      * Returns whether there is a reference defined in the persistence layer with the given name.
289      * Depending on the type of underlying persistence mechanism, this method may or may not return true
290      * when the referenceName really refers to a collection type.
291      *
292      * To determine whether a reference is a collection, use the hasCollection method instead.
293      *
294      * In OJB, this method will return false for collection references.
295      *
296      * @param boClass
297      * @param referenceName
298      * @return true if the reference exists
299      */
300     boolean hasReference(Class<?> boClass, String referenceName);
301 
302     /**
303      * Returns whether BOs of the given class have a collection defined within them with the given collection name.
304      *
305      * @param boClass
306      * @param collectionName
307      * @return true if a collection is defined
308      */
309     boolean hasCollection(Class<?> boClass, String collectionName);
310 
311     boolean isExtensionAttribute(Class<?> boClass, String attributePropertyName, Class<?> propertyType);
312 
313     Class<?> getExtensionAttributeClass(Class<?> boClass, String attributePropertyName);
314 
315     // DataObjectMetadataService
316 
317     /**
318      * Determines the primary keys for the class of the given object, then for each
319      * key field retrieves the value from the object instance and populates the return
320      * map with the primary key name as the map key and the object value as the map value
321      *
322      * <p>Has DOMDS on the end because this is the version that delegates to DataObjectMetaDataService</p>
323      *
324      * @param dataObject - object whose primary key field name,value pairs you want
325      * @return a Map containing the names and values of fields for the given class which
326      *         are designated as key fields in the OJB repository file or DataDictionary
327      * @throws IllegalArgumentException if the given Object is null
328      */
329     Map<String, ?> getPrimaryKeyFieldValuesDOMDS(Object dataObject);
330 
331     /**
332      * Compares two dataObject instances for equality based on primary keys
333      *
334      * @param do1
335      * @param do2
336      * @return boolean indicating whether the two objects are equal.
337      */
338     boolean equalsByPrimaryKeys(Object do1, Object do2);
339 
340     // ObjectUtils
341 
342 //    /**
343 //     * Casts the given object to a PersistableBusinessObject, checking first whether or not it is a valid
344 //     * PersistableBusinessObject.
345 //     *
346 //     * @param object the object to cast to a PersistableBusinessObject, must be non-null
347 //     * @return the PersistableBusinessObject for the given object, will never return null
348 //     * @throws IllegalArgumentException if the given object is null or does not represent a valid PersistableBusinessObject
349 //     */
350 //    PersistableBusinessObject toPersistableBusinessObject(Object object);
351 
352     /**
353      * Materializes any references on the given object.
354      *
355      * @param object object to materialize
356      */
357     void materializeAllSubObjects(Object object);
358 
359     /**
360      * Returns the type of the property with the given name on the supplied object. The property path may be nested.
361      *
362      * @param object the object against which to search
363      * @param propertyName the (optionally nested) property name for which to locate the type
364      * @return the type of the property
365      * @throws RuntimeException if a problem occurred (i.e. bad property name), this exception will be different
366      *         depending on whether the underlying implementation is calling legacy code or not
367      */
368     Class<?> getPropertyType(Object object, String propertyName);
369 
370     // PersistableBusinessObjectBase
371 
372     /**
373      * Creates an instance of the extension for the given business object class.
374      */
375     Object getExtension(Class<?> businessObjectClass)
376             throws InstantiationException, IllegalAccessException;
377 
378     /**
379      * Refreshes the specified reference object on the given business object.
380      */
381     void refreshReferenceObject(Object businessObject, String referenceObjectName);
382 
383     // Misc...
384 
385     /**
386      * Determines if the given ojbect is "lockable".
387      *
388      * @param object object for which to determine lockable
389      * @return true if lockable, false otherwise
390      */
391     boolean isLockable(Object object);
392 
393     /**
394      * Verifies that the version number of the given data object (if it has one) matches what is currently in the
395      * database. If not, then the GlobalVariables message map will be updated with an error message and a
396      * ValidationException will be thrown.
397      *
398      * <p>If this particular data object does not have versioning, this method will do nothing.</p>
399      *
400      * @param dataObject the data object to check the version number for
401      *
402      * @throws org.kuali.rice.krad.exception.ValidationException if the version number doesn't match
403      */
404     void verifyVersionNumber(Object dataObject);
405 
406     /**
407      * Returns the builder for a remotable quick finder for the given attribute name on the given containing class.
408      *
409      * @param containingClass the class on which to locate the attribute
410      * @param attributeName the name of the attribute for which to build the quickfinder on the specified containing class
411      * @return the remotable quickfinder, or null if no such finder could be created
412      */
413     RemotableQuickFinder.Builder createQuickFinder(Class<?> containingClass, String attributeName);
414 
415     boolean isReferenceUpdatable(Class<?> boClass, String referenceName);
416 
417     /**
418      *
419      * This method uses the persistence layer to determine the list of reference objects contained within this parent object. For
420      * example, an Account object contains sub-objects such as Chart, as well as the key that connects the two, String
421      * chartOfAccountsCode.
422      *
423      * The return structure is: Map<referenceName, referenceClass>.
424      *
425      * As an example, an Account object passed into this would return:
426      *
427      * 0:['chartOfAccounts', org.kuali.module.chart.bo.Chart] 1:['organization', org.kuali.module.chart.bo.Org] etc.
428      *
429      * @param boClass Class that would like to be analyzed for reference names
430      * @return Map containing the reference name for the key as a string, and the class of the reference as the value. If the object
431      *         contains no references, then this Map will be empty.
432      *
433      */
434     Map<String, Class> listReferenceObjectFields(Class<?> boClass);
435 
436     boolean isCollectionUpdatable(Class<?> boClass, String collectionName);
437 
438     Map<String, Class> listCollectionObjectTypes(Class<?> boClass);
439 
440     /**
441      *
442      * This method attempts to retrieve the reference from a BO if it exists.
443      *
444      * @param bo - populated BusinessObject instance that includes the referenceName property
445      * @param referenceName - name of the member/property to load
446      * @return A populated object from the DB, if it exists
447      *
448      */
449     Object getReferenceIfExists(Object bo, String referenceName);
450 
451     /**
452      *
453      * This method examines whether all the foreign key fields for the specified reference contain values.
454      *
455      * @param bo
456      * @param referenceName
457      * @return true if they all are accessible and have values, false otherwise
458      *
459      */
460     boolean allForeignKeyValuesPopulatedForReference(Object bo, String referenceName);
461 
462     /**
463      * This method gets the title attribute from the datadictionary for the given data object class
464      * @param dataObjectClass
465      * @return title if available, otherwise null
466      */
467     String getTitleAttribute(Class<?> dataObjectClass);
468 
469     /**
470      *
471      * @param dataObjectClass
472      * @return  true is supported, otherwise false
473      */
474     boolean areNotesSupported(Class<?> dataObjectClass);
475 
476     /**
477      * Gets the identifier for a data object
478      * @param dataObject data object
479      * @return data object identifier
480      */
481     String getDataObjectIdentifierString(Object dataObject);
482 
483     /**
484      * Get Inquiry class if not the title attribute
485      * @param dataObject
486      * @param propertyName
487      * @return class that represents the inquiry object class, null otherwise
488      */
489     Class<?> getInquiryObjectClassIfNotTitle(Object dataObject, String propertyName);
490 
491     /**
492      * Get Inquiry parameters for given keys for data object/property name
493      * @param dataObject
494      * @param keys
495      * @param propertyName
496      * @return map of key value pairs, empty map otherwise
497      */
498     Map<String,String> getInquiryParameters(Object dataObject, List<String> keys, String propertyName);
499 
500 
501     /**
502      * Determines whether the given data object class has an associated lookup in the local
503      * running application
504      *
505      * @param dataObjectClass data object class to find lookup for
506      * @return boolean true if a lookup exists for the data object class, false if not
507      */
508     boolean hasLocalLookup(Class<?> dataObjectClass);
509 
510     /**
511      * Determines whether the given data object class has an associated inquiry in the local
512      * running application
513      *
514      * @param dataObjectClass data object class to find inquiry for
515      * @return boolean true if a inquiry exists for the data object class, false if not
516      */
517     boolean hasLocalInquiry(Class<?> dataObjectClass);
518 
519     /**
520      * Attempts to find a relationship for the given attribute within the given
521      * data object
522      *
523      * <p>
524      * First the data dictionary is queried to find any relationship definitions
525      * setup that include the attribute, if found the
526      * <code>BusinessObjectRetationship</code> is build from that. If not and
527      * the data object class is persistent, relationships are retrieved from the
528      * persistence service. Nested attributes are handled in addition to
529      * external business objects. If multiple relationships are found, the one
530      * that contains the least amount of joining keys is returned
531      * </p>
532      *
533      * @param dataObject - data object instance that contains the attribute
534      * @param dataObjectClass - class for the data object that contains the attribute
535      * @param attributeName - property name for the attribute
536      * @param attributePrefix - property prefix for the attribute
537      * @param keysOnly - indicates whether only primary key fields should be returned
538      * in the relationship
539      * @param supportsLookup - indicates whether the relationship should support lookup
540      * @param supportsInquiry - indicates whether the relationship should support inquiry
541      * @return BusinessObjectRelationship for the attribute, or null if not
542      *         found
543      */
544     DataObjectRelationship getDataObjectRelationship(Object dataObject, Class<?> dataObjectClass,
545             String attributeName, String attributePrefix, boolean keysOnly, boolean supportsLookup,
546             boolean supportsInquiry);
547 
548 
549     /**
550      * Determines if a class is persistable
551      *
552      * @param dataObjectClass - data object instance that contains the attribute
553      * @return true if the given Class is persistable (is known to OJB or JPA)
554      */
555     boolean isPersistable(Class<?> dataObjectClass);
556 
557     /**
558      * Recursive; sets all occurences of the property in the object, its nested objects and its object lists with the
559      * given value.
560      *
561      * @param bo
562      * @param propertyName
563      * @param type
564      * @param propertyValue
565      * @throws NoSuchMethodException
566      * @throws java.lang.reflect.InvocationTargetException
567      * @throws IllegalAccessException
568      */
569     void setObjectPropertyDeep(Object bo, String propertyName, Class<?> type,
570             Object propertyValue) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException;
571 
572     /**
573      * Attempts to find the Class for the given potentially proxied object
574      *
575      * @param object the potentially proxied object to find the Class of
576      * @return the best Class which could be found for the given object
577      */
578     Class<?> materializeClassForProxiedObject(Object object);
579 
580     /**
581      * This method safely extracts either simple values OR nested values. For example, if the bo is SubAccount, and the
582      * fieldName is
583      * a21SubAccount.subAccountTypeCode, this thing makes sure it gets the value off the very end attribute, no matter
584      * how deeply
585      * nested it is. The code would be slightly simpler if this was done recursively, but this is safer, and consumes a
586      * constant
587      * amount of memory, no matter how deeply nested it goes.
588      *
589      * @param bo
590      * @param fieldName
591      * @return The field value if it exists. If it doesnt, and the name is invalid, and
592      */
593     Object getNestedValue(Object bo, String fieldName);
594 
595     /**
596      * This method safely creates a object from a class
597      * Convenience method to create new object and throw a runtime exception if it cannot
598      * If the class is an {@link org.kuali.rice.krad.bo.ExternalizableBusinessObject}, this method will determine the interface for the EBO and
599      * query the
600      * appropriate module service to create a new instance.
601      *
602      * @param clazz
603      * @return a newInstance() of clazz
604      */
605     Object createNewObjectFromClass(Class clazz);
606 
607     /**
608      * This method is a OJB Proxy-safe way to test for null on a proxied object that may or may not be materialized yet.
609      * It is safe
610      * to use on a proxy (materialized or non-materialized) or on a non-proxy (ie, regular object). Note that this will
611      * force a
612      * materialization of the proxy if the object is a proxy and unmaterialized.
613      *
614      * @param object - any object, proxied or not, materialized or not
615      * @return true if the object (or underlying materialized object) is null, false otherwise
616      */
617     boolean isNull(Object object);
618 
619     /**
620      * Sets the property of an object with the given value. Converts using the formatter of the given type if one is
621      * found.
622      *
623      * @param bo
624      * @param propertyName
625      * @param propertyType
626      * @param propertyValue
627      * @throws NoSuchMethodException
628      * @throws InvocationTargetException
629      * @throws IllegalAccessException
630      */
631     void setObjectProperty(Object bo, String propertyName, Class propertyType,
632             Object propertyValue) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException;
633 
634 }