001/**
002 * Copyright 2005-2016 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.rice.krad.data;
017
018import org.kuali.rice.core.api.criteria.QueryByCriteria;
019import org.kuali.rice.core.api.criteria.QueryResults;
020import org.kuali.rice.krad.data.metadata.MetadataRepository;
021import org.springframework.dao.DataAccessException;
022import org.springframework.dao.IncorrectResultSizeDataAccessException;
023
024/**
025 * The primary API for interacting with the data layer.
026 *
027 * <p>Contains basic data access and query operations for supported data objects. Also provides access to the
028 * {@link MetadataRepository} which contains information about the structure and relationships between data objects.</p>
029 *
030 * <p>This service supports the ability to create a {@link DataObjectWrapper} for a given data object. This
031 * wrapper allows for accessing and manipulating properties within the data object as well as performing various
032 * metadata-aware operations on the data object.</p>
033 *
034 * <p>This service is meant to act as a facade to specific persistence and query-capable solutions and data stores.
035 * Implementations of this service may provide transactional capabilities where it makes sense to do so (and depending
036 * on the transactional support of the backend persistence technology). The documentation for the specific
037 * implementation of DataObjectService that is being used should be consulted for specifics on transaction
038 * semantics.</p>
039 *
040 * @author Kuali Rice Team (rice.collab@kuali.org)
041 */
042public interface DataObjectService {
043
044    /**
045     * Invoked to retrieve a data object instance by a single primary key field or id object. In the
046     * case of a compound primary key consisting of multiple attributes on the data object, a
047     * {@link CompoundKey} can be passed in order to encapsulate these into a single argument.
048     *
049     * @param type the type of the data object to find
050     * @param id the id representing the primary key of the data object to find
051     * @param <T> the data object class type
052     *
053     * @return the entity with the given primary key or null if none found
054     *
055     * @throws IllegalArgumentException if {@code type} does not denote a data object type or {@code id} is not a valid
056     * type for the data object's primary key or is null
057     * @throws DataAccessException if data access fails
058     *
059     * @see CompoundKey
060     */
061    <T> T find(Class<T> type, Object id);
062
063    /**
064     * Executes a query for the given data object. If the given QueryByCriteria is empty or null, then
065     * all data objects for the given type will be returned. Depending on the given criteria and the
066     * implementation for the query execution, not all matching results may be returned. The QueryResults
067     * will contain information on whether or not there are additional results which can be used for paging
068     * and similar functionality.
069     *
070     * @param type the type of the data objects to query
071     * @param queryByCriteria query object, can contain sorting and page request configuration
072     * @param <T> the data object class type
073     *
074     * @return the results of the query, will never return null but may return empty results
075     *
076     * @throws IllegalArgumentException if {@code type} does not denote a data object type, also if the
077     *  {@code queryByCriteria} is null or empty.
078     * @throws DataAccessException if data access fails
079     */
080    <T> QueryResults<T> findMatching(Class<T> type, QueryByCriteria queryByCriteria);
081
082    /**
083     * Executes a query for the given data object returning all data objects for the given type.
084     *
085     * @param type tye type of data objects to query
086     * @param <T> the data object class type
087     *
088     * @return the results of the query, will never return null but may return empty results.
089     *
090     * @throws IllegalArgumentException if {@code type} is null.
091     * @throws DataAccessException if data access fails.
092     */
093    <T> QueryResults<T> findAll(Class<T> type);
094
095    /**
096     * Executes a query for the data object matching the given queryByCriteria and expecting a single unique result to
097     * be returned. If no results match the given criteria, then null will be returned. If the given criteria matches
098     * more than one result, then an {@link IncorrectResultSizeDataAccessException} will be
099     * thrown.
100     *
101     * @param type the type of the data object to query
102     * @param queryByCriteria query object defining the criteria for the query
103     * @param <T> the data object class type
104     *
105     * @return the single result of the query, or null if no objects were matched
106     *
107     * @throws IllegalArgumentException if {@code type} does not denote a data object type
108     * @throws IncorrectResultSizeDataAccessException if more than one object matched the given criteria
109     */
110    <T> T findUnique(Class<T> type, QueryByCriteria queryByCriteria);
111
112    /**
113     * Deletes a given data object.
114     *
115     * @param dataObject the data object to delete
116     *
117     * @throws IllegalArgumentException if {@code dataObject} is not a valid data object
118     * @throws DataAccessException if data access fails
119     */
120    void delete(Object dataObject);
121
122    /**
123     * Deletes records for the given type and matching the given criteria.  If the given type is null then an
124     *  IllegalArgumentException will be thrown.  If the given criteria is null or empty an IllegalArgumentException
125     *  is also thrown to help prevent table truncations.
126     *
127     * @param type the type of data objects to delete
128     * @param queryByCriteria query object
129     *
130     * @throws IllegalArgumentException if {@code type} is null or if the {@code QueryByCriteria} is null or empty
131     * @throws DataAccessException if data access fails
132     */
133    <T> void deleteMatching(Class<T> type, QueryByCriteria queryByCriteria);
134
135    /**
136     * Removes all records for the given data object type
137     *
138     * @param type the type of data objects
139     * @param <T> the data object class type.
140     *
141     * @throws IllegalArgumentException if {@code type} is null
142     * @throws DataAccessException if data access fails
143     */
144    <T> void deleteAll(Class<T> type);
145
146    /**
147     * Saves the given data object, determining whether or not this is a new data object which is being created, or an
148     * existing one which should be updated.
149     *
150     * <p>Optional persistence options can be passed to indicate whether or not linking should be performed prior to
151     * persistence. By default, linking is performed.</p>
152     *
153     * @param dataObject the data object to save
154     * @param options the options to use when saving the data object
155     * @param <T> the data object class type
156     *
157     * @return the saved data object, calling code should always use the reference the object returned from this method
158     * for future operations after calling the save since it could have been updated
159     *
160     * @throws IllegalArgumentException if {@code dataObject} is not a valid data object
161     * @throws DataAccessException if data access fails
162     */
163        <T> T save(T dataObject, PersistenceOption... options);
164
165    /**
166     * Flushes any outstanding work to the backend data store.
167     *
168     * <p>Depending on the backend persistence implementation for the given type, this method may or may not do
169     * anything.</p>
170     *
171     * @param type the type of the data object for which to perform the flush. This is primarily used to identify the
172     * context in which to perform the flush.
173     */
174    void flush(Class<?> type);
175
176
177    /**
178     * Returns the MetadataRepository which provides access to all data object metadata known to the system.
179     *
180     * @return the MetadataRepository
181     */
182    MetadataRepository getMetadataRepository();
183
184    /**
185     * Wraps the given data object in an accessor which provides numerous utility and helper methods related to
186     * accessing data and attributes on the data object.
187     *
188     * @param dataObject the data object to wrap, must be non-null
189     * @param <T> the type of the data object
190     *
191     * @return an accessor which wraps the given data object and it's associated metadata and provides utility and
192     *         methods useful when accessing data and attributes on the data object
193     *
194     * @throws IllegalArgumentException if the given data object is null or an invalid data object type
195     */
196    <T> DataObjectWrapper<T> wrap(T dataObject);
197
198    /**
199     * Returns a copy of the given data object instance.
200     *
201     * <p>The method of copying is provider dependent, and will handle instances (including nested) using whatever
202     * measures might be required to deal with the quirks of said provider (e.g. fetching lazy loaded relations).
203     * </p>
204     *
205     * @param dataObject the data object to copy
206     * @param <T> the type of the data object
207     *
208     * @return a copy of the given data object
209     */
210        <T> T copyInstance(T dataObject, CopyOption... options);
211
212    /**
213     * Returns whether the DataObjectService supports the given type, where
214     * "supports" means that there is at least one PersistenceProvider that handles the given type.
215     *
216     * @param type the data object type
217     *
218     * @return whether the DataObjectService supports the given type
219     */
220    <T> boolean supports(Class<T> type);
221
222}