001    // Copyright 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    
021    import org.hibernate.SessionFactory;
022    import org.hibernate.classic.Session;
023    import org.hibernate.metadata.ClassMetadata;
024    
025    /**
026     * Superclass of both {@link ReadableDAOImpl} and {@link WriteableDAOImpl}.
027     * 
028     * @author Thiago H. de Paula Figueiredo
029     * @param <T> the entity class related to this DAO.
030     * @param <K> the type of the field that represents the entity class' primary key.
031     */
032    public class BaseHibernateDAO<T, K extends Serializable> {
033    
034            private final SessionFactory sessionFactory;
035    
036            private final Class<T> entityClass;
037    
038            private final ClassMetadata classMetadata;
039    
040            private final String primaryKeyPropertyName;
041    
042            /**
043             * Constructor that takes a {@link Class} and a {@link SessionFactory}.
044             * 
045             * @param clasz a {@link Class}.
046             * @param sessionFactory a {@link SessionFactory}. It cannot be null.
047             */
048            @SuppressWarnings("unchecked")
049            public BaseHibernateDAO(SessionFactory sessionFactory) {
050                    this(null, sessionFactory);
051            }
052    
053            /**
054             * Constructor that takes a {@link Class} and a {@link SessionFactory}.
055             * 
056             * @param clasz a {@link Class}.
057             * @param sessionFactory a {@link SessionFactory}. It cannot be null.
058             */
059            @SuppressWarnings("unchecked")
060            public BaseHibernateDAO(Class<T> clasz, SessionFactory sessionFactory) {
061    
062                    if (sessionFactory == null) {
063                            throw new IllegalArgumentException("Parameter sessionFactory cannot be null");
064                    }
065    
066                    this.sessionFactory = sessionFactory;
067    
068                    entityClass = clasz != null ? clasz : extractEntityClassFromHierarchy();
069                    classMetadata = sessionFactory.getClassMetadata(getEntityClass());
070    
071                    if (getClassMetadata() == null) {
072                            throw new RuntimeException("Class " + getEntityClass().getName() + " is not mapped");
073                    }
074    
075                    primaryKeyPropertyName = getClassMetadata().getIdentifierPropertyName();
076    
077                    assert getEntityClass() != null;
078                    assert getClassMetadata() != null;
079                    assert getPrimaryKeyPropertyName() != null;
080    
081            }
082    
083            /**
084             * @return
085             */
086            @SuppressWarnings("unchecked")
087            private Class<T> extractEntityClassFromHierarchy() {
088    
089                    final Type genericSuperclass = getClass().getGenericSuperclass();
090                    final ParameterizedType parameterizedType = ((ParameterizedType) genericSuperclass);
091                    return (Class<T>) parameterizedType.getActualTypeArguments()[0];
092    
093            }
094    
095            /**
096             * Returns the entity class handled by this DAO.
097             * 
098             * @return a {@link Class<T>}.
099             */
100            protected final Class<T> getEntityClass() {
101                    return entityClass;
102            }
103    
104            /**
105             * Returns a {@link Session}. This implementation returns
106             * {@link SessionFactory#getCurrentSession()} and can be overriden if needed.
107             * 
108             * @return a {@link Session}.
109             */
110            protected Session getSession() {
111                    return getSessionFactory().getCurrentSession();
112            }
113    
114            /**
115             * Returns this DAO's {@link SessionFactory}.
116             * 
117             * @return a {@link SessionFactory}.
118             */
119            protected final SessionFactory getSessionFactory() {
120                    return sessionFactory;
121            }
122    
123            /**
124             * Returns the {@link ClassMetadata} for the corresponding entity class.
125             * 
126             * @return a {@link ClassMetadata}.
127             */
128            protected final ClassMetadata getClassMetadata() {
129                    return classMetadata;
130            }
131    
132            /**
133             * Returns the name of the id property.
134             * 
135             * @return a {@link String}.
136             */
137            protected String getPrimaryKeyPropertyName() {
138                    return primaryKeyPropertyName;
139            }
140    
141    }