001    // Copyright 2007-2008 Thiago H. de Paula Figueiredo
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package br.com.arsmachina.dao.hibernate;
016    
017    import java.io.Serializable;
018    import java.lang.reflect.ParameterizedType;
019    import java.lang.reflect.Type;
020    import java.util.List;
021    
022    import org.hibernate.Criteria;
023    import org.hibernate.SessionFactory;
024    import org.hibernate.classic.Session;
025    import org.hibernate.criterion.Example;
026    import org.hibernate.metadata.ClassMetadata;
027    
028    import br.com.arsmachina.dao.DAO;
029    import br.com.arsmachina.dao.SortCriterion;
030    
031    /**
032     * {@link AbstractDAO} implementation using Hibernate. All methods use {@link #getSession()} to get
033     * a {@link Session}. All methods delegate its calls to an internal {@link ReadableDAOImpl} or
034     * {@link WriteableDAOImpl} instance.
035     * 
036     * @author Thiago H. de Paula Figueiredo
037     * @param <T> the entity class related to this DAO.
038     * @param <K> the type of the field that represents the entity class' primary key.
039     */
040    public class GenericDAOImpl<T, K extends Serializable> implements DAO<T, K> {
041    
042            final private InternalReadableDAOImpl readableDAO;
043    
044            final private InternalWriteableDAOImpl writeableDAO;
045    
046            /**
047             * Single public constructor.
048             * 
049             * @param sessionFactory a {@link SessionFactory}. It cannot be null.
050             */
051            @SuppressWarnings("unchecked")
052            public GenericDAOImpl(SessionFactory sessionFactory) {
053    
054                    if (sessionFactory == null) {
055                            throw new IllegalArgumentException("Parameter sessionFactory cannot be null");
056                    }
057    
058                    final Type genericSuperclass = getClass().getGenericSuperclass();
059                    final ParameterizedType parameterizedType = ((ParameterizedType) genericSuperclass);
060                    Class clasz = (Class<T>) parameterizedType.getActualTypeArguments()[0];
061    
062                    readableDAO = new InternalReadableDAOImpl(clasz, sessionFactory);
063                    writeableDAO = new InternalWriteableDAOImpl(clasz, sessionFactory);
064    
065            }
066    
067            /**
068             * Constructor made specifically for {@link ConcreteDAOImpl}. It shouldn't be used in
069             * any other class. 
070             * 
071             * @param clasz the entity class. It cannot be null.
072             * @param sessionFactory a {@link SessionFactory}. It cannot be null.
073             */
074            GenericDAOImpl(Class<T> clasz, SessionFactory sessionFactory) {
075                    
076                    if (clasz == null) {
077                            throw new IllegalArgumentException("Parameter clasz cannot be null");
078                    }
079                    
080                    if (sessionFactory == null) {
081                            throw new IllegalArgumentException("Parameter sessionFactory cannot be null");
082                    }
083                    
084                    readableDAO = new InternalReadableDAOImpl(clasz, sessionFactory);
085                    writeableDAO = new InternalWriteableDAOImpl(clasz, sessionFactory);
086                    
087            }
088    
089            public int countAll() {
090                    return readableDAO.countAll();
091            }
092    
093            public List<T> findAll() {
094                    return readableDAO.findAll();
095            }
096    
097            public List<T> findAll(int firstResult, int maximumResults, SortCriterion... sortingConstraints) {
098                    return readableDAO.findAll(firstResult, maximumResults, sortingConstraints);
099            }
100    
101            public List<T> findByExample(T example) {
102                    return readableDAO.findByExample(example);
103            }
104    
105            public T findById(K id) {
106                    return readableDAO.findById(id);
107            }
108    
109            public List<T> findByIds(K... ids) {
110                    return readableDAO.findByIds(ids);
111            }
112    
113            public void refresh(T object) {
114                    readableDAO.refresh(object);
115            }
116    
117            public void delete(T object) {
118                    writeableDAO.delete(object);
119            }
120    
121            public void delete(K id) {
122                    writeableDAO.delete(id);
123            }
124    
125            public void evict(T object) {
126                    writeableDAO.evict(object);
127            }
128    
129            public boolean isPersistent(T object) {
130                    return writeableDAO.isPersistent(object);
131            }
132    
133            public void save(T object) {
134                    writeableDAO.save(object);
135            }
136    
137            public T update(T object) {
138                    return writeableDAO.update(object);
139            }
140    
141            public T reattach(T object) {
142                    return readableDAO.reattach(object);
143            }
144    
145            public SortCriterion[] getDefaultSortCriteria() {
146                    return readableDAO.getDefaultSortCriteria();
147            }
148    
149            /**
150             * Invokes <code>readableDAO.addSortCriteria()<code>.
151             * @param criteria
152             * @see br.com.arsmachina.dao.hibernate.ReadableDAOImpl#addSortCriteria(org.hibernate.Criteria)
153             */
154            protected void addSortCriteria(Criteria criteria) {
155                    readableDAO.addSortCriteria(criteria);
156            }
157            
158            
159            
160            /**
161             * Invokes <code>delegate.addSortCriteria()<code>.
162             * @param criteria
163             * @param sortCriteria
164             * @see br.com.arsmachina.dao.hibernate.ReadableDAOImpl#addSortCriteria(org.hibernate.Criteria, br.com.arsmachina.dao.SortCriterion[])
165             */
166            public final void addSortCriteria(Criteria criteria, SortCriterion... sortCriteria) {
167                    readableDAO.addSortCriteria(criteria, sortCriteria);
168            }
169    
170            /**
171             * Invokes <code>readableDAO.createCriteria()<code>.
172             * @return
173             * @see br.com.arsmachina.dao.hibernate.ReadableDAOImpl#createCriteria()
174             */
175            protected Criteria createCriteria() {
176                    return readableDAO.createCriteria();
177            }
178            
179            
180    
181            /**
182             * Invokes <code>delegate.createCriteria()<code>.
183             * @param sortCriteria
184             * @return
185             * @see br.com.arsmachina.dao.hibernate.ReadableDAOImpl#createCriteria(br.com.arsmachina.dao.SortCriterion[])
186             */
187            protected Criteria createCriteria(SortCriterion... sortCriteria) {
188                    return readableDAO.createCriteria(sortCriteria);
189            }
190            
191            
192    
193            /**
194             * Invokes <code>delegate.createCriteria()<code>.
195             * @param firstIndex
196             * @param maximumResults
197             * @param sortCriteria
198             * @return
199             * @see br.com.arsmachina.dao.hibernate.ReadableDAOImpl#createCriteria(int, int, br.com.arsmachina.dao.SortCriterion[])
200             */
201            public Criteria createCriteria(int firstIndex, int maximumResults,
202                            SortCriterion... sortCriteria) {
203                    return readableDAO.createCriteria(firstIndex, maximumResults, sortCriteria);
204            }
205    
206            /**
207             * Invokes <code>readableDAO.createExample()<code>.
208             * @param entity
209             * @return
210             * @see br.com.arsmachina.dao.hibernate.ReadableDAOImpl#createExample(java.lang.Object)
211             */
212            protected Example createExample(T entity) {
213                    return readableDAO.createExample(entity);
214            }
215    
216            /**
217             * Returns the entity class handled by this DAO.
218             * 
219             * @return a {@link Class<T>}.
220             */
221            protected final Class<T> getEntityClass() {
222                    return readableDAO.getEntityClass();
223            }
224    
225            /**
226             * Returns a {@link Session}. This implementation returns
227             * {@link SessionFactory#getCurrentSession()} and can be overriden if needed.
228             * 
229             * @return a {@link Session}.
230             */
231            protected Session getSession() {
232                    return getSessionFactory().getCurrentSession();
233            }
234    
235            /**
236             * Returns this DAO's {@link SessionFactory}.
237             * 
238             * @return a {@link SessionFactory}.
239             */
240            protected final SessionFactory getSessionFactory() {
241                    return readableDAO.getSessionFactory();
242            }
243    
244            /**
245             * Returns the {@link ClassMetadata} for the corresponding entity class.
246             * 
247             * @return a {@link ClassMetadata}.
248             */
249            final protected ClassMetadata getClassMetadata() {
250                    return readableDAO.getClassMetadata();
251            }
252    
253            /**
254             * Returns the name of the property.
255             * 
256             * @return a {@link String}.
257             */
258            public String getPrimaryKeyPropertyName() {
259                    return readableDAO.getPrimaryKeyPropertyName();
260            }
261    
262            /**
263             * Concrete {@link ReadableDAOImpl} subclass.
264             * 
265             * @author Thiago H. de Paula Figueiredo
266             * @param <T>
267             * @param <K>
268             */
269            private final class InternalReadableDAOImpl extends ReadableDAOImpl<T, K> {
270    
271                    public InternalReadableDAOImpl(Class<T> clasz, SessionFactory sessionFactory) {
272                            super(clasz, sessionFactory);
273                    }
274    
275            }
276    
277            /**
278             * Concrete {@link WriteableDAOImpl} subclass.
279             * 
280             * @author Thiago H. de Paula Figueiredo
281             * @param <T>
282             * @param <K>
283             */
284            private final class InternalWriteableDAOImpl extends WriteableDAOImpl<T, K> {
285    
286                    public InternalWriteableDAOImpl(Class<T> clasz, SessionFactory sessionFactory) {
287                            super(clasz, sessionFactory);
288                    }
289    
290            }
291    
292    }