/*
 * Copyright 2000-2004 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.marevol.utils.hibernate;

import java.io.Serializable;
import java.sql.Connection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.portlet.PortletConfig;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.CacheMode;
import org.hibernate.Criteria;
import org.hibernate.EntityMode;
import org.hibernate.Filter;
import org.hibernate.FlushMode;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.Query;
import org.hibernate.ReplicationMode;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.stat.SessionStatistics;

/**
 *  Hibernate Utility
 * 
 * @author <a href="mailto:shinsuke@yahoo.co.jp">Shinsuke Sugaya</a>
 * @deprecated
 */
public class HibernateUtil
{
    private static Log log = LogFactory.getLog(HibernateUtil.class);

    public static final String WEBAPP_ROOT = "\\$\\{webappRoot\\}";

    private static SessionFactory sessionFactory = null;

    public static final ThreadLocal session = new ThreadLocal();

    public static final ThreadLocal transaction = new ThreadLocal();

    public static void init()
    {
        try
        {
            // Create the SessionFactory
            sessionFactory = new Configuration().configure().buildSessionFactory();
        }
        catch (Throwable ex)
        {
            // Make sure you log the exception, as it might be swallowed
            log.error("Initial SessionFactory creation failed.", ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static void init(PortletConfig portletConfig)
    {
        String webappRoot = portletConfig.getPortletContext().getRealPath("/");
        if (log.isDebugEnabled())
        {
            log.debug("init(PortletConfig) -  : webappRoot=" + webappRoot);
        }

        // To avoid StringIndexOutOfBoundsException.. \ -> \\\\
        webappRoot = webappRoot.replaceAll("\\\\", "\\\\\\\\\\\\\\\\");

        HashMap map = new HashMap();
        map.put(WEBAPP_ROOT, webappRoot);
        init(map);
    }

    public static void init(Map map)
    {

        Configuration config = new Configuration().configure();
        for (Enumeration e = config.getProperties().keys(); e.hasMoreElements();)
        {
            String key = (String) e.nextElement();
            String value = config.getProperty(key);
            if (log.isDebugEnabled())
            {
                log.debug("init(Map) -  : key=" + key + ", value=" + value);
            }

            Iterator ite = map.keySet().iterator();
            while (ite.hasNext())
            {
                String keyword = (String) ite.next();
                if (value.matches(".*" + keyword + ".*"))
                {
                    if (log.isDebugEnabled())
                    {
                        log.debug("init(Map) -  : key=" + key + ", value=" + value+", keyword="+keyword+", val="+ map.get(keyword));
                    }
                    value = value.replaceAll(keyword, (String) map.get(keyword));
                    config.setProperty(key, value);
                    if (log.isDebugEnabled())
                    {
                        log.debug("init(Map) -  : REPLACED: key=" + key + ", value=" + value);
                    }
                }
            }

            // for HSQL
            if (key.equals("hibernate.connection.url") && value.startsWith("jdbc:hsqldb:"))
            {
                value = value.replace('\\', '/');
                config.setProperty(key, value);
                if (log.isDebugEnabled())
                {
                    log.debug("init(Map) -  : REPLACED: key=" + key + ", value=" + value);
                }
            }
        }

        try
        {
            // Create the SessionFactory
            sessionFactory = config.buildSessionFactory();
        }
        catch (Throwable ex)
        {
            // Make sure you log the exception, as it might be swallowed
            log.error("Initial SessionFactory creation failed.", ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    private static SessionFactory getSessionFactoryInstance()
    {
        if (sessionFactory == null)
        {
            init();
        }
        return sessionFactory;
    }

    public static void openSession()
    {
        getCurrentSession();
    }

    public static Session getCurrentSession()
    {
        Session s = (Session) session.get();
        // Open a new Session, if this Thread has none yet
        if (s == null)
        {
            s = getSessionFactoryInstance().openSession();
            session.set(s);
        }
        return s;
    }

    public static void closeSession()
    {
        Session s = (Session) session.get();
        if (s != null)
        {
            s.close();
        }
        session.set(null);
    }

    public static Transaction beginTransaction()
    {

        Transaction tx = (Transaction) transaction.get();
        if (tx == null)
        {
            tx = getCurrentSession().beginTransaction();
            transaction.set(tx);
        }
        return tx;
    }

    public static void commit()
    {
        Transaction tx = (Transaction) transaction.get();
        if (tx != null)
        {
            tx.commit();
        }
        transaction.set(null);
    }

    public static void rollback()
    {
        Transaction tx = (Transaction) transaction.get();
        if (tx != null)
        {
            tx.rollback();
        }
        transaction.set(null);
    }

    public static Serializable save(Object arg0)
    {
        return getCurrentSession().save(arg0);
    }

    public static Object load(Class arg0, Serializable arg1)
    {
        return getCurrentSession().load(arg0, arg1);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#cancelQuery()
     */
    public static void cancelQuery() throws HibernateException
    {
        getCurrentSession().cancelQuery();
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#clear()
     */
    public static void clear()
    {
        getCurrentSession().clear();
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#close()
     */
    public static Connection close() throws HibernateException
    {
        return getCurrentSession().close();
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#connection()
     */
    public static Connection connection() throws HibernateException
    {
        return getCurrentSession().connection();
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#contains(java.lang.Object)
     */
    public static boolean contains(Object arg0)
    {
        return getCurrentSession().contains(arg0);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#createCriteria(java.lang.Class, java.lang.String)
     */
    public static Criteria createCriteria(Class arg0, String arg1)
    {
        return getCurrentSession().createCriteria(arg0, arg1);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#createCriteria(java.lang.Class)
     */
    public static Criteria createCriteria(Class arg0)
    {
        return getCurrentSession().createCriteria(arg0);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#createCriteria(java.lang.String, java.lang.String)
     */
    public static Criteria createCriteria(String arg0, String arg1)
    {
        return getCurrentSession().createCriteria(arg0, arg1);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#createCriteria(java.lang.String)
     */
    public static Criteria createCriteria(String arg0)
    {
        return getCurrentSession().createCriteria(arg0);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#createFilter(java.lang.Object, java.lang.String)
     */
    public static Query createFilter(Object arg0, String arg1) throws HibernateException
    {
        return getCurrentSession().createFilter(arg0, arg1);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#createQuery(java.lang.String)
     */
    public static Query createQuery(String arg0) throws HibernateException
    {
        return getCurrentSession().createQuery(arg0);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#createSQLQuery(java.lang.String)
     */
    public static SQLQuery createSQLQuery(String arg0) throws HibernateException
    {
        return getCurrentSession().createSQLQuery(arg0);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#delete(java.lang.Object)
     */
    public static void delete(Object arg0) throws HibernateException
    {
        getCurrentSession().delete(arg0);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#disableFilter(java.lang.String)
     */
    public static void disableFilter(String arg0)
    {
        getCurrentSession().disableFilter(arg0);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#disconnect()
     */
    public static Connection disconnect() throws HibernateException
    {
        return getCurrentSession().disconnect();
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#enableFilter(java.lang.String)
     */
    public static Filter enableFilter(String arg0)
    {
        return getCurrentSession().enableFilter(arg0);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#evict(java.lang.Object)
     */
    public static void evict(Object arg0) throws HibernateException
    {
        getCurrentSession().evict(arg0);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#flush()
     */
    public static void flush() throws HibernateException
    {
        getCurrentSession().flush();
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#get(java.lang.Class, java.io.Serializable, org.hibernate.LockMode)
     */
    public static Object get(Class arg0, Serializable arg1, LockMode arg2) throws HibernateException
    {
        return getCurrentSession().get(arg0, arg1, arg2);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#get(java.lang.Class, java.io.Serializable)
     */
    public static Object get(Class arg0, Serializable arg1) throws HibernateException
    {
        return getCurrentSession().get(arg0, arg1);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#get(java.lang.String, java.io.Serializable, org.hibernate.LockMode)
     */
    public static Object get(String arg0, Serializable arg1, LockMode arg2) throws HibernateException
    {
        return getCurrentSession().get(arg0, arg1, arg2);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#get(java.lang.String, java.io.Serializable)
     */
    public static Object get(String arg0, Serializable arg1) throws HibernateException
    {
        return getCurrentSession().get(arg0, arg1);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#getCacheMode()
     */
    public static CacheMode getCacheMode()
    {
        return getCurrentSession().getCacheMode();
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#getCurrentLockMode(java.lang.Object)
     */
    public static LockMode getCurrentLockMode(Object arg0) throws HibernateException
    {
        return getCurrentSession().getCurrentLockMode(arg0);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#getEnabledFilter(java.lang.String)
     */
    public static Filter getEnabledFilter(String arg0)
    {
        return getCurrentSession().getEnabledFilter(arg0);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#getEntityMode()
     */
    public static EntityMode getEntityMode()
    {
        return getCurrentSession().getEntityMode();
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#getEntityName(java.lang.Object)
     */
    public static String getEntityName(Object arg0) throws HibernateException
    {
        return getCurrentSession().getEntityName(arg0);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#getFlushMode()
     */
    public static FlushMode getFlushMode()
    {
        return getCurrentSession().getFlushMode();
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#getIdentifier(java.lang.Object)
     */
    public static Serializable getIdentifier(Object arg0) throws HibernateException
    {
        return getCurrentSession().getIdentifier(arg0);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#getNamedQuery(java.lang.String)
     */
    public static Query getNamedQuery(String arg0) throws HibernateException
    {
        return getCurrentSession().getNamedQuery(arg0);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#getSession(org.hibernate.EntityMode)
     */
    public static Session getSession(EntityMode arg0)
    {
        return getCurrentSession().getSession(arg0);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#getSessionFactory()
     */
    public static SessionFactory getSessionFactory()
    {
        return getCurrentSession().getSessionFactory();
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#getStatistics()
     */
    public static SessionStatistics getStatistics()
    {
        return getCurrentSession().getStatistics();
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#isConnected()
     */
    public static boolean isConnected()
    {
        return getCurrentSession().isConnected();
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#isDirty()
     */
    public static boolean isDirty() throws HibernateException
    {
        return getCurrentSession().isDirty();
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#isOpen()
     */
    public static boolean isOpen()
    {
        return getCurrentSession().isOpen();
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#load(java.lang.Class, java.io.Serializable, org.hibernate.LockMode)
     */
    public static Object load(Class arg0, Serializable arg1, LockMode arg2) throws HibernateException
    {
        return getCurrentSession().load(arg0, arg1, arg2);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#load(java.lang.Object, java.io.Serializable)
     */
    public static void load(Object arg0, Serializable arg1) throws HibernateException
    {
        getCurrentSession().load(arg0, arg1);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#load(java.lang.String, java.io.Serializable, org.hibernate.LockMode)
     */
    public static Object load(String arg0, Serializable arg1, LockMode arg2) throws HibernateException
    {
        return getCurrentSession().load(arg0, arg1, arg2);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#load(java.lang.String, java.io.Serializable)
     */
    public static Object load(String arg0, Serializable arg1) throws HibernateException
    {
        return getCurrentSession().load(arg0, arg1);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#lock(java.lang.Object, org.hibernate.LockMode)
     */
    public static void lock(Object arg0, LockMode arg1) throws HibernateException
    {
        getCurrentSession().lock(arg0, arg1);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#lock(java.lang.String, java.lang.Object, org.hibernate.LockMode)
     */
    public static void lock(String arg0, Object arg1, LockMode arg2) throws HibernateException
    {
        getCurrentSession().lock(arg0, arg1, arg2);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#merge(java.lang.Object)
     */
    public static Object merge(Object arg0) throws HibernateException
    {
        return getCurrentSession().merge(arg0);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#merge(java.lang.String, java.lang.Object)
     */
    public static Object merge(String arg0, Object arg1) throws HibernateException
    {
        return getCurrentSession().merge(arg0, arg1);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#persist(java.lang.Object)
     */
    public static void persist(Object arg0) throws HibernateException
    {
        getCurrentSession().persist(arg0);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#persist(java.lang.String, java.lang.Object)
     */
    public static void persist(String arg0, Object arg1) throws HibernateException
    {
        getCurrentSession().persist(arg0, arg1);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#reconnect()
     */
    public static void reconnect() throws HibernateException
    {
        getCurrentSession().reconnect();
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#reconnect(java.sql.Connection)
     */
    public static void reconnect(Connection arg0) throws HibernateException
    {
        getCurrentSession().reconnect(arg0);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#refresh(java.lang.Object, org.hibernate.LockMode)
     */
    public static void refresh(Object arg0, LockMode arg1) throws HibernateException
    {
        getCurrentSession().refresh(arg0, arg1);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#refresh(java.lang.Object)
     */
    public static void refresh(Object arg0) throws HibernateException
    {
        getCurrentSession().refresh(arg0);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#replicate(java.lang.Object, org.hibernate.ReplicationMode)
     */
    public static void replicate(Object arg0, ReplicationMode arg1) throws HibernateException
    {
        getCurrentSession().replicate(arg0, arg1);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#replicate(java.lang.String, java.lang.Object, org.hibernate.ReplicationMode)
     */
    public static void replicate(String arg0, Object arg1, ReplicationMode arg2) throws HibernateException
    {
        getCurrentSession().replicate(arg0, arg1, arg2);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#save(java.lang.Object, java.io.Serializable)
     */
    public static void save(Object arg0, Serializable arg1) throws HibernateException
    {
        getCurrentSession().save(arg0, arg1);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#save(java.lang.String, java.lang.Object, java.io.Serializable)
     */
    public static void save(String arg0, Object arg1, Serializable arg2) throws HibernateException
    {
        getCurrentSession().save(arg0, arg1, arg2);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#save(java.lang.String, java.lang.Object)
     */
    public static Serializable save(String arg0, Object arg1) throws HibernateException
    {
        return getCurrentSession().save(arg0, arg1);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#saveOrUpdate(java.lang.Object)
     */
    public static void saveOrUpdate(Object arg0) throws HibernateException
    {
        getCurrentSession().saveOrUpdate(arg0);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#saveOrUpdate(java.lang.String, java.lang.Object)
     */
    public static void saveOrUpdate(String arg0, Object arg1) throws HibernateException
    {
        getCurrentSession().saveOrUpdate(arg0, arg1);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#setCacheMode(org.hibernate.CacheMode)
     */
    public static void setCacheMode(CacheMode arg0)
    {
        getCurrentSession().setCacheMode(arg0);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#setFlushMode(org.hibernate.FlushMode)
     */
    public static void setFlushMode(FlushMode arg0)
    {
        getCurrentSession().setFlushMode(arg0);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#update(java.lang.Object, java.io.Serializable)
     */
    public static void update(Object arg0, Serializable arg1) throws HibernateException
    {
        getCurrentSession().update(arg0, arg1);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#update(java.lang.Object)
     */
    public static void update(Object arg0) throws HibernateException
    {
        getCurrentSession().update(arg0);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#update(java.lang.String, java.lang.Object, java.io.Serializable)
     */
    public static void update(String arg0, Object arg1, Serializable arg2) throws HibernateException
    {
        getCurrentSession().update(arg0, arg1, arg2);
    }

    /* (non-Javadoc)
     * @see org.hibernate.Session#update(java.lang.String, java.lang.Object)
     */
    public static void update(String arg0, Object arg1) throws HibernateException
    {
        getCurrentSession().update(arg0, arg1);
    }

}
