/*
Name:
- HibernatePersistenceProvider
Description:
-
Requires:
-
Provides:
-
Part of: ProcessPuzzle Framework, Domain and Business Model Ready Architecture. Provides content, workflow and social networking functionality.
http://www.processpuzzle.com
ProcessPuzzle - Content and Workflow Management Integration Business Platform
Author(s):
- Zsolt Zsuffa
Copyright: (C) 2011 This program is free software: you can redistribute it and/or modify it under the terms of the
GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.processpuzzle.persistence.domain;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.QueryException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.exception.DataException;
import org.hibernate.exception.SQLGrammarException;
import com.processpuzzle.application.configuration.domain.PersistenceContext;
import com.processpuzzle.application.configuration.domain.PersistentDataInitializationStrategies;
import com.processpuzzle.commons.persistence.Entity;
import com.processpuzzle.commons.persistence.PersistentObject;
import com.processpuzzle.commons.persistence.RepositoryResultSet;
import com.processpuzzle.commons.persistence.UnitOfWork;
import com.processpuzzle.commons.persistence.query.Query;
import com.processpuzzle.persistence.query.transformer.domain.QueryTransformerFactory;
public class HibernatePersistenceProvider extends DefaultPersistenceProvider implements QLConstants {
private static final String HIBERNATE_PROPERTY_SELECTOR = "pr:hibernate";
private static Configuration hibernateConfiguration;
private static SessionFactory sessionFactory;
protected static Logger log = LoggerFactory.getLogger( HibernatePersistenceProvider.class );
// Constructors
public HibernatePersistenceProvider( String name, HierarchicalConfiguration configuration, List<Class<?>> persistentClasses,
PersistentDataInitializationStrategies databaseCreationStrategy ) {
super( name, configuration, persistentClasses, databaseCreationStrategy );
}
// Public mutators
public boolean configure() {
super.configure();
hibernateConfiguration = new Configuration();
addPropertiesToTheHibernateConfiguration();
handleDatabaseInitializationStrategy();
addEntityClassesToTheHibernateConfiguration();
try{
initDatabase();
}catch( Exception e ){
throw new PersistenceProviderInitializationException( this.getClass(), e );
}
isConfigured = true;
return isConfigured();
}
@Override
public Integer add( UnitOfWork work, Class<? extends PersistentObject> entityClass, PersistentObject entity ) {
Integer id = null;
HibernateSessionContext sessionContext = (HibernateSessionContext) getSessionContextFor( work );
Session session = sessionContext.getSession();
try{
id = (Integer) session.save( entityClass.getName(), entity );
}catch( DataException e ){
throw new PersistenceProviderException( "add", e );
}catch( HibernateException e ){
throw new PersistenceProviderException( "add", e );
}catch( Exception e ){
// TODO: handle exception
e.printStackTrace();
}
return id;
}
@Override
public void update( UnitOfWork work, Class<? extends PersistentObject> entityClass, PersistentObject entity ) {
Session hibernateSession = ((HibernateSessionContext) getSessionContextFor( work )).getSession();
hibernateSession.update( entityClass.getName(), entity );
}
@Override
public void delete( UnitOfWork work, Class<? extends PersistentObject> entityClass, PersistentObject entity ) {
Session hibernateSession = ((HibernateSessionContext) getSessionContextFor( work )).getSession();
try{
hibernateSession.delete( entity );
}catch( Exception e ){
log.debug( "Deleting object of entity class: " + entityClass.getName() + "caused an error", e );
throw new PersistenceProviderException( "delete", e );
}
}
@SuppressWarnings("unchecked")
@Override
public <P extends PersistentObject> P findById( UnitOfWork work, Class<P> entityClass, Integer id ) {
Session hibernateSession = ((HibernateSessionContext) getSessionContextFor( work )).getSession();
return (P) hibernateSession.get( entityClass, id );
}
@SuppressWarnings( "unchecked" )
@Override
public <P extends PersistentObject> RepositoryResultSet<P> findAll( UnitOfWork work, Class<P> entityClass ) {
RepositoryResultSet<P> retValues = null;
Session hibernateSession = ((HibernateSessionContext) getSessionContextFor( work )).getSession();
com.processpuzzle.persistence.query.domain.DefaultQuery query = new com.processpuzzle.persistence.query.domain.DefaultQuery( (Class<? extends Entity>) entityClass );
String queryStatement = QueryTransformerFactory.createHQLQueryTransformer().createStatement( query );
retValues = new SimpleResultSet<P>( hibernateSession.createQuery( queryStatement ).list() );
return retValues;
}
@Override
public RepositoryResultSet<? extends PersistentObject> findByQuery( UnitOfWork work, Query query ) {
RepositoryResultSet<? extends PersistentObject> resultSet = null;
String queryStatement = null;
try{
Session hibernateSession = ((HibernateSessionContext) getSessionContextFor( work )).getSession();
queryStatement = QueryTransformerFactory.createHQLQueryTransformer().createStatement( query );
org.hibernate.Query hibernateQuery = hibernateSession.createQuery( queryStatement );
if( query.getFirstResult() != null )
hibernateQuery.setFirstResult( query.getFirstResult().intValue() );
if( query.getMaxResults() != null )
hibernateQuery.setMaxResults( query.getMaxResults().intValue() );
List<?> resultList = hibernateQuery.list();
resultSet = determineResultSet( resultList );
}catch( QueryException e ){
log.debug( "Running query: '" + queryStatement + "' raised an exception.", e );
throw new PersistenceProviderException( "findByQuery", e );
}catch( SQLGrammarException e ){
throw new PersistenceProviderException( "findByQuery", e );
}catch( Exception e ){
e.printStackTrace();
throw new Error( "Unhandled exception." );
}
return resultSet;
}
// Properties
public String getDriverClass() {
return configuration.getString( HibernatePersistenceProviderPropertyKey.DRIVER_CLASS.getDefaultKey() );
}
public String getConnectionUrl() {
return configuration.getString( HibernatePersistenceProviderPropertyKey.CONNECTION_URL.getDefaultKey() );
}
public String getUserName() {
return configuration.getString( HibernatePersistenceProviderPropertyKey.USER_NAME.getDefaultKey() );
}
public String getPassword() {
return configuration.getString( HibernatePersistenceProviderPropertyKey.PASSWORD.getDefaultKey() );
}
public Configuration getHibernateConfiguration() {
return hibernateConfiguration;
}
SessionFactory getSessionFactory() {
return sessionFactory;
}
// Private helper methods
@Override
protected SessionContext startNewSessionContext( UnitOfWork work ) {
HibernateSessionContext sessionContext = new HibernateSessionContext( sessionFactory );
return sessionContext;
}
@Override
protected void finishSessionContext( SessionContext context ) {
// TODO Auto-generated method stub
}
@SuppressWarnings( "unchecked" )
private void addPropertiesToTheHibernateConfiguration() {
HierarchicalConfiguration hibernateProperties = configuration.configurationAt( HIBERNATE_PROPERTY_SELECTOR );
for( Iterator<String> iter = hibernateProperties.getKeys(); iter.hasNext(); ){
String propertyKey = (String) iter.next();
String propertyValue = hibernateProperties.getString( propertyKey );
if( propertyKey != "" && propertyValue != "" ){
propertyKey = propertyKey.toLowerCase();
propertyKey = propertyKey.replace( PersistenceContext.NAME_SPACE_PREFIX, "" );
propertyKey = "hibernate." + propertyKey.replace( '/', '.' );
hibernateConfiguration.setProperty( propertyKey, propertyValue );
}
}
}
private void addEntityClassesToTheHibernateConfiguration() {
for( Iterator<Class<?>> iter = persistentClasses.iterator(); iter.hasNext(); ){
Class<?> persistentClass = (Class<?>) iter.next();
try{
log.debug( "Adding: " + persistentClass + " class to Hibernate configuration." );
hibernateConfiguration.addClass( persistentClass );
}catch( MappingException e ){
throw new RepositoryEventHandlerConfigurationException( configuration, e );
}
}
}
@SuppressWarnings( "unchecked" )
private RepositoryResultSet<? extends PersistentObject> determineResultSet( List<?> resultList ) {
RepositoryResultSet<? extends PersistentObject> resultSet = null;
if( resultList != null && resultList.size() > 0 ){
Object firstObject = resultList.get( 0 );
if( firstObject instanceof Long )
resultSet = new AggregatedResult<PersistentLong>( PersistentLong.class, (List<PersistentLong>) resultList );
else
resultSet = new SimpleResultSet<PersistentObject>( (List<PersistentObject>) resultList );
}else
resultSet = new SimpleResultSet<PersistentObject>( (List<PersistentObject>) resultList );
return resultSet;
}
private void handleDatabaseInitializationStrategy() {
if( databaseCreationStrategy == PersistentDataInitializationStrategies.create ){
hibernateConfiguration.setProperty( "hibernate.hbm2ddl.auto", "create" );
}else if( databaseCreationStrategy == PersistentDataInitializationStrategies.dropAndCreate ){
hibernateConfiguration.setProperty( "hibernate.hbm2ddl.auto", "create-drop" );
}else if( databaseCreationStrategy == PersistentDataInitializationStrategies.update ){
hibernateConfiguration.setProperty( "hibernate.hbm2ddl.auto", "update" );
}
}
private void initDatabase() {
try{
sessionFactory = hibernateConfiguration.buildSessionFactory();
}catch( Exception e ){
log.debug( e.getMessage() );
throw new RepositoryEventHandlerConfigurationException( configuration, e );
}
}
@SuppressWarnings( { "unchecked", "unused" } )
private void printProperties() {
for( Iterator iter = hibernateConfiguration.getProperties().entrySet().iterator(); iter.hasNext(); ){
Map.Entry<String, String> propertyEntry = (Map.Entry) iter.next();
String key = propertyEntry.getKey();
String value = propertyEntry.getValue();
System.out.println( key + " = " + value );
}
}
}