001/* 
002 * JKNIV, whinstone one contract to access your database.
003 * 
004 * Copyright (C) 2017, the original author or authors.
005 *
006 * This library is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 2.1 of the License.
010 * 
011 * This library is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014 * Lesser General Public License for more details.
015 * 
016 * You should have received a copy of the GNU Lesser General Public
017 * License along with this library; if not, write to the Free Software Foundation, Inc., 
018 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
019 */
020package net.sf.jkniv.whinstone;
021
022import java.util.List;
023
024import net.sf.jkniv.sqlegance.NonUniqueResultException;
025import net.sf.jkniv.sqlegance.QueryNotFoundException;
026import net.sf.jkniv.whinstone.transaction.Transactional;
027
028/**
029 * 
030 * A repository holds the connections to data base server, allowing it to be queried through Queryable objects.
031 * 
032 * Repository instances must be thread-safe and usually a single instance is enough per application.
033 * 
034 * @author Alisson Gomes
035 * @since 0.6.0
036 */
037public interface Repository
038{
039    
040    public static final String TRANSACTION_NONE             = "NONE";
041    public static final String TRANSACTION_READ_UNCOMMITTED = "UNCOMMITTED";
042    public static final String TRANSACTION_READ_COMMITTED   = "COMMITTED";
043    public static final String TRANSACTION_REPEATABLE_READ  = "REPEATABLE_READ";
044    public static final String TRANSACTION_SERIALIZABLE     = "SERIALIZABLE";
045    
046    /**
047     * Get one object instance from repository using a query.
048     * 
049     * @param queryable
050     *            The Query name with yours parameters
051     * @param <T> generic type to be returned 
052     * @return Return the object that matches with query. A null reference is
053     *         returned if the query no match anyone object.
054     * @throws QueryNotFoundException when not found the query name
055     * @throws NonUniqueResultException when select or select with group by recovery more one objects
056     */
057    <T> T get(Queryable queryable);
058
059    /**
060     * Get one object instance of type {@code returnType} from repository using a query.
061     * @param queryable The Query name with yours parameters
062     * @param returnType overload the returned type from XML file
063     * @param <T> type of object returned
064     * @return Return the object {@code returnType}that matches with query. A null reference is
065     *         returned if the query no match anyone object.
066     * @throws QueryNotFoundException when not found the query name
067     * @throws NonUniqueResultException when select or select with group by recovery more one objects
068     */
069    <T> T get(Queryable queryable, Class<T> returnType);
070
071    /**
072     * Get one object instance from repository using a query.
073     * @param queryable The Query name with yours parameters
074     * @param customResultRow Customized extractor to process each row from query
075     * @param <T> type of object returned
076     * @param <R> raw type from repository API (Like {@code ResultSet} from JDBC)
077     * @return Return the object {@code returnType} that matches with query. A null reference is
078     *         returned if the query no match anyone object.
079     * @throws QueryNotFoundException when not found the query name
080     * @throws NonUniqueResultException when select or select with group by recovery more one objects
081     */
082    <T,R> T get(Queryable queryable, ResultRow<T,R> customResultRow);
083
084    /**
085     * Get one object instance from repository using a {@code object} as parameter.
086     * @param object object that contains the parameters to retrieve the entity.
087     * @param <T> type of object returned
088     * @return Return the object {@code returnType} that matches with query. A null reference is
089     *         returned if the query no match anyone object.
090     * @throws QueryNotFoundException when not found the query name
091     * @throws NonUniqueResultException when select or select with group by recovery more one objects
092     */
093    <T> T get(T object);
094
095    /**
096     * Get one object instance of type {@code returnType} from repository using a {@code object} as parameter.
097     * @param returnType overload the returned type from XML file
098     * @param object parameters from query to retrieve the object
099     * @param <T> type of object returned
100     * @return Return the object {@code returnType} that matches with query. A null reference is
101     *         returned if the query no match anyone object.
102     * @throws QueryNotFoundException when not found the query name
103     * @throws NonUniqueResultException when select or select with group by recovery more one objects
104     */
105    <T> T get(Class<T> returnType, Object object);
106    
107    /**
108     * Retrieve a number, numerical quantity, string, date, boolean, some primitive value (wrapped), 
109     * the type is checked against jdbc data type.
110     * 
111     * <ul>
112     * <li>java.math.BigDecimal</li>
113     * <li>java.lang.Boolean</li>
114     * <li>java.lang.Byte</li>
115     * <li>java.lang.Double</li>
116     * <li>java.lang.Float</li>
117     * <li>java.lang.Integer</li>
118     * <li>java.lang.Long</li>
119     * <li>java.lang.Short</li>
120     * <li>java.lang.String</li>
121     * <li>java.lang.Character</li>
122     * <li>java.util.Date</li>
123     * </ul>
124     * @param queryable The Query name with yours parameters
125     * @param <T> the single type to be returned
126     * @return Scalar value
127     * @throws QueryNotFoundException when not found the query name
128     * @throws NonUniqueResultException when select or select with group by recovery more one objects
129     */
130    <T> T scalar(Queryable queryable);
131
132    /**
133     * Use the {@link Queryable} to retrieve data and appends the result to {@link Queryable#getParams()} 
134     * parameters, where for each {@code get} method must have a correspondent {@code set}.
135     * 
136     * @param queryable Query with yours parameters
137     * @return return {@code true} if the objects was enriched, {@code false} otherwise.
138     * @throws QueryNotFoundException when not found the query name
139     * @throws NonUniqueResultException if your {@link Queryable} doesn't return one unique value
140     */
141    boolean enrich(Queryable queryable);// TODO test enrich
142                                        // FIXME implements using MAP
143    
144    /**
145     * Retrieve a set of objects {@code T} from repository using a query.
146     * 
147     * @param queryable The Query name with yours parameters
148     * @param <T> generic type to be returned
149     * @return Return a set of object that matches with query. A empty list is
150     *         returned if the query no match anyone object.
151     * @throws QueryNotFoundException when not found the query name
152     */
153    <T> List<T> list(Queryable queryable);
154
155    /**
156     * Retrieve a set of objects {@code returnType} from repository using a query.
157     * @param queryable The Query name with yours parameters
158     * @param returnType overload the returned type from XML file
159     * @param <T> type of object returned
160     * @return Return a set of object that matches with query. A empty list is
161     *         returned if the query no match anyone object.
162     * @throws QueryNotFoundException when not found the query name
163     */
164    <T> List<T> list(Queryable queryable, Class<T> returnType);
165
166    /**
167     * Retrieve a set of objects {@code T} from repository using a query.
168     * @param queryable The Query name with yours parameters
169     * @param customResultRow Customized extractor to process each row from query
170     * @param <T> type of object returned
171     * @param <R> raw type from repository API (Like {@code ResultSet} from JDBC)
172     * @return Return a set of object that matches with query. A empty list is
173     *         returned if the query no match anyone object.
174     * @throws QueryNotFoundException when not found the query name
175     */
176    <T,R> List<T> list(Queryable queryable, ResultRow<T, R> customResultRow);
177
178    /**
179     * Add a new object to repository.
180     * 
181     * @param queryable name of query must be executed to add object to repository
182     * @return Return the number of objects inserted.
183     * @throws QueryNotFoundException when not found the query name
184     */
185    int add(Queryable queryable);
186    
187    /**
188     * Add a new object to repository.
189     * @param entity object to be added to repository
190     * @param <T> type of object returned
191     * @return Return the number of objects inserted.
192     * @throws IllegalArgumentException when entity is null
193     */
194    <T> int add(T entity);
195    
196    /**
197     * Update many objects in repository.
198     * 
199     * @param queryable The Query name with yours parameters
200     * @return Return the number of objects updated.
201     * @throws QueryNotFoundException when not found the query name
202     * @throws IllegalArgumentException
203     *             when the query is different from update sentence
204     */
205    int update(Queryable queryable);
206
207    /**
208     * Update object(s) in repository.
209     * @param entity update the repository with a {@code entity} values mapped at query.
210     * @param <T> type of object returned
211     * @return the instance that was updated to
212     * @throws IllegalArgumentException when entity is null
213     */
214    <T> T update(T entity);
215    
216    /**
217     * Execute a query to remove one or many objects from repository.
218     * 
219     * @param queryable The Query name with yours parameters
220     * @return the number of rows removed.
221     * @throws IllegalArgumentException
222     *             when the query is different from delete
223     */
224    int remove(Queryable queryable);
225    
226    /**
227     * Remove the {@code entity} from repository.
228     * @param entity object with the parameters 
229     * @param <T> type of object returned
230     * @throws IllegalArgumentException when entity is null
231     * @return the number of objects removed.
232     */
233    <T> int remove(T entity);
234    
235    /**
236     * Push the queries from buffer to repository.
237     */
238    void flush();
239    
240    Transactional getTransaction();
241    
242    /**
243     * Close the connection with the database.
244     * After close the repository any query cannot be executed against the database 
245     * then all subsequent access to the repository throw a {@code RepositoryException} 
246     */
247    void close();
248    
249    boolean containsQuery(String name);
250    
251    /**
252     * A domain-specific languages (DSL) from native API: JPA, Couchbase, Cassandra etc.
253     * @param <T> a generic type from DSL API
254     * @return the DSL API to build dynamic queries
255     * @throws UnsupportedDslOperationException when the repository does not supports DSL
256     */
257    <T> T dsl();
258        
259}