View Javadoc
1   // license-header java merge-point
2   //
3   // Attention: Generated code! Do not modify by hand!
4   // Generated by: hibernate/search/PropertySearch.java.vsl in andromda-spring-cartridge.
5   //
6   package fr.ifremer.quadrige3.core.dao;
7   
8   /*-
9    * #%L
10   * Quadrige3 Core :: Client API
11   * %%
12   * Copyright (C) 2017 - 2024 Ifremer
13   * %%
14   * This program is free software: you can redistribute it and/or modify
15   * it under the terms of the GNU Affero General Public License as published by
16   * the Free Software Foundation, either version 3 of the License, or
17   * (at your option) any later version.
18   * 
19   * This program is distributed in the hope that it will be useful,
20   * but WITHOUT ANY WARRANTY; without even the implied warranty of
21   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22   * GNU General Public License for more details.
23   * 
24   * You should have received a copy of the GNU Affero General Public License
25   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
26   * #L%
27   */
28  import java.util.Calendar;
29  import java.util.Date;
30  import java.util.List;
31  import java.util.StringTokenizer;
32  import org.apache.commons.beanutils.ConversionException;
33  import org.apache.commons.beanutils.ConvertUtils;
34  import org.apache.commons.beanutils.Converter;
35  import org.apache.commons.beanutils.PropertyUtils;
36  import org.apache.commons.beanutils.converters.IntegerConverter;
37  import org.apache.commons.beanutils.converters.LongConverter;
38  import org.apache.commons.beanutils.converters.ShortConverter;
39  import org.hibernate.HibernateException;
40  import org.hibernate.Session;
41  import org.hibernate.criterion.MatchMode;
42  import org.hibernate.criterion.Projections;
43  
44  /**
45   * Provides the ability to search by properties.
46   */
47  @SuppressWarnings({"unchecked"})
48  public class PropertySearch
49      extends CriteriaSearch
50  {
51      private Search search;
52  
53      /**
54       * Constructor for PropertySearch. Creates a <code>PropertySearch</code> instance
55       * from the given arguments.
56       *
57       * @param session The Hibernate session.
58       * @param entityType The <code>Class</code> of the result.
59       * @param searchIn the object that specifies the search criteria.
60       */
61      public PropertySearch(
62          final Session session,
63          final Class entityType,
64          final Search searchIn)
65      {
66          super(session, entityType);
67          this.search = searchIn;
68          try
69          {
70              this.initializeConverters();
71              this.getConfiguration().setForceEagerLoading(searchIn.isEagerFetching());
72              final SearchParameter[] parameters = searchIn.getParameters();
73              if (parameters != null)
74              {
75                  for (int ctr = 0; ctr < parameters.length; ctr++)
76                  {
77                      final SearchParameter searchParameter = parameters[ctr];
78  
79                      Object value;
80                      switch (searchParameter.getComparator())
81                      {
82                          case SearchParameter.IN_COMPARATOR :
83                              value = searchParameter.getValue();
84                              break;
85                          case SearchParameter.NOT_IN_COMPARATOR :
86                              value = searchParameter.getValue();
87                              break;
88                          default :
89                              value = this.getValue(entityType, searchParameter);
90                              break;
91                      }
92  
93                      // - now add the parameter.
94                      final CriteriaSearchParameter parameter =
95                          new CriteriaSearchParameter(value,
96                              searchParameter.getName(),
97                              searchParameter.getComparator());
98                      parameter.setOrderDirection(searchParameter.getOrder());
99                      parameter.setSearchIfNull(searchParameter.isSearchIfNull());
100                     switch (searchParameter.getMatch())
101                     {
102                         case SearchParameter.MATCH_ANYWHERE :
103                             parameter.setMatchMode(MatchMode.ANYWHERE);
104                             break;
105                         case SearchParameter.MATCH_START :
106                             parameter.setMatchMode(MatchMode.START);
107                             break;
108                         case SearchParameter.MATCH_END :
109                             parameter.setMatchMode(MatchMode.END);
110                             break;
111                         default:
112                             parameter.setMatchMode(MatchMode.EXACT);
113                             break;
114                     }
115                     this.addParameter(parameter);
116                     if (searchIn.isUseSqlLimiting())
117                     {
118                         if (searchIn.getPageNumber() > 0 && searchIn.getPageSize() > 0)
119                         {
120                             // - set the first result as part of pagination support
121                             this.getConfiguration().setFirstResult(new Integer(this.calculateFirstResult(searchIn.getPageNumber(), searchIn.getPageSize())));
122                             this.getConfiguration().setMaximumResultSize(new Integer(searchIn.getPageSize()));
123                         }
124                     }
125                 }
126             }
127         }
128         catch (Exception exception)
129         {
130             throw new RuntimeException(exception);
131         }
132     }
133 
134     /**
135      * Stores the total count when sql limiting isn't used.
136      */
137     private int totalCount;
138 
139     /**
140      * Gets the total possible count of objects returned in this search.
141      * @return totalCount
142      */
143     public int getTotalCount()
144     {
145         int count;
146         if (this.search.isUseSqlLimiting())
147         {
148             // Remove first result requirement
149             this.getConfiguration().setFirstResult(new Integer(0));
150             this.getRootCriteria().setProjection(
151                 Projections.projectionList().add(
152                     Projections.rowCount()));
153             count = ((Long)this.executeAsList().iterator().next()).intValue();
154         }
155         else
156         {
157             count = this.totalCount;
158         }
159         return count;
160     }
161 
162     /**
163      * @see CriteriaSearch#executeAsList()
164      */
165     @Override
166     public List executeAsList()
167         throws HibernateException
168     {
169         List results = super.executeAsList();
170         if (!this.search.isUseSqlLimiting() && this.search.getPageNumber() > 0 && this.search.getPageSize() > 0)
171         {
172             int start = this.calculateFirstResult(this.search.getPageNumber(), this.search.getPageSize());
173             int end = this.calculateLastResult(this.search.getPageNumber(), this.search.getPageSize());
174             this.totalCount = results.size();
175             if (this.totalCount < start)
176             {
177                 start = this.totalCount;
178             }
179             if (this.totalCount < end)
180             {
181                 end = this.totalCount;
182             }
183             results = results.subList(start, end);
184         }
185         return results;
186     }
187 
188     /**
189      * Calculates the first result based upon page size and current
190      * desired page.
191      *
192      * @param pageNumber the page number to retrieve.
193      * @param pageSize the page size to retrieve.
194      *
195      * @return the calculated first result.
196      */
197     private int calculateFirstResult(int pageNumber, int pageSize)
198     {
199         int firstResult = 0;
200         if (pageNumber > 0 && pageSize > 0)
201         {
202             firstResult = (pageNumber - 1) * pageSize;
203         }
204         return firstResult;
205     }
206 
207     /**
208      * Calculates the last result based upon page size and current
209      * desired page.
210      *
211      * @param pageNumber the page number to retrieve.
212      * @param pageSize the page size to retrieve.
213      *
214      * @return the calculated first result.
215      */
216     private int calculateLastResult(int pageNumber, int pageSize)
217     {
218         int lastResult = 0;
219         if (pageNumber > 0 && pageSize > 0)
220         {
221             lastResult = pageNumber * pageSize;
222         }
223         return lastResult;
224     }
225 
226     private static final String PERIOD = ".";
227 
228     /**
229      * Initializes the converters to behave the way we want when converting values (we don't
230      * want empty strings converted to zeros, like beanutils does by default)
231      */
232     private void initializeConverters()
233     {
234         ConvertUtils.register(new LongConverter(null), Long.class);
235         ConvertUtils.register(new IntegerConverter(null), Integer.class);
236         ConvertUtils.register(new ShortConverter(null), Short.class);
237         ConvertUtils.register(new CalendarConverter(), Calendar.class);
238         ConvertUtils.register(new DateConverter(), Date.class);
239     }
240 
241     /**
242      * <p>Convert the value to an object of the specified class (if
243      * possible).</p>
244      *
245      * @param value Value to be converted (may be null)
246      * @param type Class of the value to be converted to
247      * @return The converted value
248      *
249      * @exception ConversionException if thrown by an underlying Converter
250      */
251     protected Object convert(Object value, Class type)
252     {
253         Converter converter = ConvertUtils.lookup(type);
254         Object result;
255         if (converter != null)
256         {
257             result = converter.convert(type, value);
258         }
259         else
260         {
261             result = value;
262         }
263         return result;
264     }
265 
266     /**
267      * Converts the value contained within the parameter to the type which Hibernate expects.
268      *
269      * @param entityType the class of the entity for which the search is being performed.
270      * @param parameter the parameter from which to get the value.
271      * @return the appropriate value.
272      */
273     private Object getValue(Class type, final SearchParameter parameter)
274     {
275         try
276         {
277             Object value = parameter.getValue();
278             // - don't try to convert null values or classes
279             if (value != null && !value.getClass().equals(Class.class))
280             {
281                 Class propertyType = type;
282                 for (final StringTokenizer tokenizer = new StringTokenizer(parameter.getName(), PERIOD); tokenizer.hasMoreTokens();)
283                 {
284                     final String token = tokenizer.nextToken().trim();
285                     Class lastType = type;
286                     type = CriteriaSearchProperties.getPropertyType(type, token);
287                     if (!tokenizer.hasMoreTokens())
288                     {
289                         break;
290                     }
291                     if (type == null)
292                     {
293                         throw new RuntimeException("No accessible property named '" + token + "', exists on: " + lastType.getName());
294                     }
295                     propertyType = type;
296                 }
297                 final Object object = propertyType.newInstance();
298                 final String name = parameter.getName().replaceAll(".*\\" + PERIOD, "");
299                 try
300                 {
301                     value = convert(value, PropertyUtils.getPropertyType(object, name));
302                 }
303                 catch (final NoSuchMethodException noSuchMethodException)
304                 {
305                     throw new RuntimeException("No accessible property named '" + name + "', exists on: " + propertyType.getName());
306                 }
307             }
308             return value;
309         }
310         catch (final Exception exception)
311         {
312             throw new RuntimeException(exception);
313         }
314     }
315 
316     /**
317      * A beanutils converter that converts Calendar objects to Date instances.
318      */
319     private static final class DateConverter
320         implements Converter
321     {
322         public DateConverter()
323         {
324             // Empty block comment
325         }
326 
327         /**
328          * @see org.apache.commons.beanutils.Converter#convert(Class, Object)
329          */
330         public Object convert(
331             Class type,
332             Object value)
333             throws ConversionException
334         {
335             if (value != null)
336             {
337                 try
338                 {
339                     if (value instanceof Calendar)
340                     {
341                         value = ((Calendar)value).getTime();
342                     }
343                 }
344                 catch (Exception ex)
345                 {
346                     throw new ConversionException(ex);
347                 }
348             }
349             return value;
350         }
351     }
352 
353     /**
354      * A beanutils converter that converts Date objects to Calendar instances.
355      */
356     private static final class CalendarConverter
357         implements Converter
358     {
359         public CalendarConverter()
360         {
361             // Empty block comment
362         }
363 
364         /**
365          * @see org.apache.commons.beanutils.Converter#convert(Class, Object)
366          */
367         public Object convert(
368             Class type,
369             Object value)
370             throws ConversionException
371         {
372             if (value != null)
373             {
374                 try
375                 {
376                     if (value instanceof Date)
377                     {
378                         Calendar calendar = Calendar.getInstance();
379                         calendar.setTime((Date)value);
380                         value = calendar;
381                     }
382                 }
383                 catch (Exception ex)
384                 {
385                     throw new ConversionException(ex);
386                 }
387             }
388             return value;
389         }
390     }
391 }