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.Comparator;
023import java.util.Iterator;
024
025import net.sf.jkniv.sqlegance.Sql;
026import net.sf.jkniv.whinstone.params.AutoBindParams;
027import net.sf.jkniv.whinstone.params.ParameterException;
028import net.sf.jkniv.whinstone.params.ParameterNotFoundException;
029import net.sf.jkniv.whinstone.statement.StatementAdapter;
030import net.sf.jkniv.whinstone.types.RegisterType;
031
032/**
033 * This class represent a query object to find the query to be performed and
034 * your parameters like: query parameters, offset and max objects to return.
035 * 
036 * The instance of {@code Queryable} is bound with the SQL executed, so some {@code Queryable} 
037 * re-executing <b>must be evicted</b>, like:
038 * 
039 * <pre>
040 *   Queryable myQuery = QueryFactory.of("my-query");
041 *   Number number = repository.scalar(myQuery);
042 *   
043 *   List list = repository.list(myQuery); // wrong myQuery as marked with scalar result
044 * </pre>
045 * 
046 * @author Alisson Gomes
047 * @since 0.6.0
048 */
049public interface Queryable
050{
051    /**
052     * The query name used to localize the query at in XML file.
053     * 
054     * @return Return the name of the query.
055     */
056    String getName();
057    
058    /**
059     * Parameters of query. Can be objects like Author, Book, etc. or a
060     * java.util.Map.
061     * @param <T> generic type to return
062     * @return the parameters to use at query.
063     */
064    <T> T getParams();
065    
066    /**
067     * Recover the value of the named parameter (can be nested), with no type conversions.
068     * 
069     * @param name indexed and/or nested name of the property to be recovered
070     * @return the property value
071     * @throws ParameterNotFoundException when cannot find the property.
072     */
073    Param getProperty(String name);
074    
075    Param getProperty(String name, int index);
076    
077    /**
078     * Get the number from first row from query result. If not set, rows will be
079     * retrieved beginning from row 0.
080     * 
081     * @return return a row number, numbered from 0.
082     */
083    int getOffset();
084    
085    /**
086     * Set the number from first row from query result. If not set, rows will be
087     * retrieved beginning from row 0.
088     * 
089     * @param value initial value of row number
090     */
091    void setOffset(int value);
092    
093    /**
094     * Get the maximum number of rows from query result.
095     * 
096     * @return Return the maximum number.
097     */
098    int getMax();
099    
100    /**
101     * Set the maximum number of rows from query result.
102     * 
103     * @param value max row number to be fetch
104     */
105    void setMax(int value);
106    
107    /** 
108     * Get total of rows that query can retrieve, filled after query is
109     * executed. Useful to make pagination.
110     * 
111     * @return return the number of rows from query result.
112     * <ul>
113     *  <li>{@code n} - the real rows total</li> 
114     *  <li>{@code -1} - the query isn't executed yet</li> 
115     *  <li>{@code -2} - the query was executed successfully but the number of rows is unavailable, 
116     *  for example, result from cache always return this</li> 
117     *  <li>{@code -3} - the query was executed with error and the number of rows is unavailable</li> 
118     * </ul>
119     */
120    long getTotal();
121    
122    /**
123     * Set total of rows if run non paging query. 
124     * @param total of records running full select
125     */
126    void setTotal(long total);
127
128    /**
129     * Is there a max row limit indicated?
130     *
131     * @return true whether a max row limit was indicated, false otherwise.
132     */
133    boolean isPaging();
134    
135    /**
136     * Is there a offset to skip first rows?
137     * 
138     * @return return true if have query must be paging, false otherwise.
139     */
140    boolean hasRowsOffset();
141
142    /**
143     * Mark the query as scalar value, means must be return just one value
144     */
145    void scalar();
146    // FIXME design when invoked as scalar the query cannot be execute another way, always is scalar
147    // return IllegalStateException when this happen
148    
149    /**
150     * verify if the query is scalar value.
151     * @return <code>true</code> when the retrieve unique value, <code>false</code> otherwise
152     */
153    boolean isScalar();
154    
155    /**
156     * Check if SQL object was bind to this instance.
157     * @return {@code true} when was bind, {@code false} otherwise.
158     */
159    boolean isBoundSql();
160        
161    /**
162     * Check if the parameters from queryable was bind to {@link StatementAdapter} instance.
163     * 
164     * @return {@code true} when was bind, {@code false} otherwise.
165     */
166    boolean isBoundParams();
167    
168    boolean isTypeOfNull();
169    
170    boolean isTypeOfBasic();
171
172    boolean isTypeOfArrayBasicTypes();
173
174    boolean isTypeOfCollectionBasicTypes();
175
176    boolean isTypeOfArrayPojo();
177
178    boolean isTypeOfArrayMap();
179
180    boolean isTypeOfCollectionMap();
181    
182    boolean isTypeOfCollectionPojo();
183
184    boolean isTypeOfCollectionArray();
185    
186    /**
187     * verify if the parameter is an array
188     * @return <code>true</code> when they are, <code>false</code> otherwise
189     */
190    boolean isTypeOfArray();
191    
192    /**
193     * verify if the parameter is a collection
194     * @return <code>true</code> when they are, <code>false</code> otherwise
195     */
196    boolean isTypeOfCollection();
197    
198    /**
199     * verify if the parameter is a collection or array
200     * @return <code>true</code> when they are, <code>false</code> otherwise
201     */
202    boolean isTypeOfBulk();
203    
204    /**
205     * verify if the parameter is a map
206     * @return <code>true</code> when they are, <code>false</code> otherwise
207     */
208    boolean isTypeOfMap();
209
210    /**
211     * verify if the parameter is a pojo
212     * @return <code>true</code> when is, <code>false</code> otherwise
213     */
214    boolean isTypeOfPojo();
215
216    // TODO test iterator over basic types (String, Date, Numbers...)
217    /**
218     * 
219     * Returns an iterator over the collection of {@code params} or array of {@code params}. 
220     * There are no guarantees concerning the order in which the elements are returned
221     * 
222     * @return an <tt>Iterator</tt> over the elements in {@code params}
223     * @throws UnsupportedOperationException when {@code params} isn't collection or array.
224     * @throws NullPointerException when {@code params} is {@code null}.
225     */
226    Iterator<Param> iterator();
227    
228    /**
229     * Extract the values from {@code params} matching the names array.
230     * 
231     * @return an {@code array} of values from {@code params}, base-zero array is returned when 
232     * the names doesn't match.
233     * @throws ParameterException when a parameter values not correspond the type expected
234     */
235    Param[] values();
236    
237    
238    /**
239     * Bind Sql to {@link Queryable} instance generating the raw query.
240     * 
241     * @param sql The instance of static or dynamic SQL statement
242     * @throws IllegalStateException when o {@code sql} is tried to be reassigned 
243     */
244    void bind(Sql sql);
245    
246    <T, R> AutoBindParams bind(StatementAdapter<T, R> adapter);
247    
248    /**
249     * Dynamic SQL statement from XML file.
250     * 
251     * @return SQL statement.
252     */
253    Sql getDynamicSql();
254    
255    /**
256     * Final SQL statement ready to prepared statement.
257     * 
258     * <p><b>Note: </b>Needs to bind {@link #bind(Sql)} before to call this method.
259     * 
260     * @return Final SQL statement using question mark read to prepared statement
261     */
262    String query();
263    
264    /**
265     * Final SQL statement ready to prepared statement to count the total of records from original query. 
266     * 
267     * <p><b>Note: </b>Needs to bind {@link #bind(Sql)} before to call this method.
268     * 
269     * @return SQL statement using question mark read to prepared statement
270     */
271    String queryCount();
272    
273    /**
274     * Name of parameters that bound with final SQL statement
275     * 
276     * @return parameters names that was query bound, array based-zero is return if query no have parameters
277     */
278    String[] getParamsNames();
279
280    /**
281     * Overload the return type from XML query.
282     * @param <T> type of return class
283     * @return the class to return by repository using this query
284     */
285    <T> Class<T> getReturnType();
286    
287    /**
288     * Default value of {@code getReturnType()} is {@code java.util.Map} instance,
289     * this method check if there is a type is not default.
290     * @return {@code true} if there is a return type, {@code false} otherwise
291     */
292    boolean hasReturnType();
293    
294    /**
295     * Specifies intentionally to no retrieve the data from cache, the query must be hit the database
296     */
297    void cacheIgnore();
298    
299    /**
300     * Verify was marked to ignore the cache.
301     * @return <code>true</code> when cache ignore was invoked, <code>false</code> otherwise.
302     */
303    boolean isCacheIgnore();
304    
305    /**
306     * Indicate the query result is from cache, isn't from repository.
307     * @return {@code true} when the result fetch from cache, {@code false} when fetch from repository
308     */
309    boolean isCached();
310    
311    /**
312     * mark the query result as cache
313     */
314    void cached();
315
316    /**
317     * Get a record of which page selected to mark the reader's place
318     * @return A string that enables you to specify which page of results you require
319     * @see <a href="https://docs.datastax.com/en/developer/java-driver/3.2/manual/paging/#saving-and-reusing-the-paging-state">Saving and reusing the paging state</a>
320     * @see <a href="https://docs.couchdb.org/en/stable/api/database/find.html#pagination">Find Pagination</a>
321     */
322    String getBookmark();
323    
324    /**
325     * Define a page selected to mark the reader's place
326     * @param bookmark A string that enables you to specify which page of results you require
327     * @see <a href="https://docs.datastax.com/en/developer/java-driver/3.2/manual/paging/#saving-and-reusing-the-paging-state">Saving and reusing the paging state</a>
328     * @see <a href="https://docs.couchdb.org/en/stable/api/database/find.html#pagination">Find Pagination</a>
329     */
330    void setBookmark(String bookmark);
331    
332    //void setRegisterType(RegisterType registerType);
333    
334    RegisterType getRegisterType();
335    
336    /**
337     * A comparison function, which imposes a total ordering on some collection of objects
338     * @param <T> type to be comparable
339     * @return comparator instance
340     */
341    <T> Comparator<T> getSorter();
342    
343    /**
344     * A filter function, to keep the result which imposes a total ordering on some collection of objects
345     * @param <T> the type of the items to be filtered
346     * @return comparator instance
347     */
348    <T> Filter<T> getFilter();
349    
350    /**
351     * Has an ordering imposed by a comparator.
352     * @return {@code true} when the results must be sorted, {@code false} otherwise.
353     */
354    boolean hasSorter();
355    
356    /**
357     * Has an filter to include/exclude rows from result.
358     * @return {@code true} when the results must be filtered, {@code false} otherwise.
359     */
360    boolean hasFilter();
361    
362    
363}