package brn.distsim.ormapper.util;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class DBLoader extends SessionHandler {

	public DBLoader(String DBUrl, String DBUser, String DBPasswd, int jobId)
			throws ClassNotFoundException, SQLException {
		super(DBUrl, DBUser, DBPasswd, jobId);
		loadSession();
	}

	public synchronized void loadSession() throws SQLException,
			ClassNotMappedException {
		interceptor.setDoDirtyCheck(true);
		ResultSet xmlString = connection.createStatement().executeQuery(
				"SELECT mapping FROM mappings;");
		if (!xmlString.next())
			throw new ClassNotMappedException(Object.class);
		String xml = xmlString.getString(1);
		Configuration cfg = new Configuration().addProperties(hbProps)
				.setInterceptor(interceptor).addXML(xml);

		SessionFactory sessionFactory = cfg.buildSessionFactory();
		if (session != null)
			session.close();
		session = sessionFactory.openSession();
	}

	public void registerLoadInitializer(Class c, Factory f) {
		interceptor.registerFactory(c, f);
	}

	public synchronized List getEntities(int simulationId) {
		try {
			ResultSet entities = connection.createStatement().executeQuery(
					"SELECT DISTINCT entity FROM java_lang_Object WHERE simulationId="
							+ simulationId + ";");
			LinkedList list = new LinkedList();
			while (entities.next()) {
				list.add(entities.getString(1));
			}
			return list;
		} catch (SQLException e) {
			e.printStackTrace();
			return null;
		}
	}

	// /**
	// * safe loading of single Objects. classes are checked, after successful
	// * loading the object is guaranteed to be accessible
	// *
	// * @param id
	// * @param clazz
	// * @return -- doesn't work. There is no apparent way to load objects
	// * non-lazily --
	// */
	// public synchronized Object load(int id, Class clazz) {
	// Object o = session.load(clazz, new Long(id));
	// session.evict(o);
	// return o;
	// }

	/**
	 * quick loading of batches of objects. Objects are lazy loaded, exceptions
	 * may fly when accessing them later on, collection implementations are
	 * replaced by hibernate types.
	 * 
	 * @param simulationId
	 */
	public synchronized Query load(int simulationId) {
		return session.createQuery("from java.lang.Object where simulationId="
				+ simulationId);
	}

	public synchronized Query load(int simulationId, String entity) {
		return session.createQuery("from java.lang.Object where simulationId="
				+ simulationId + " and entity='" + entity + "'");
	}

	public synchronized Query load(int simulationId, Class c) {
		return session.createQuery("from " + c.getName()
				+ " where simulationId=" + simulationId);
	}

	public synchronized Query load(int simulationId, Class c, String entity) {
		return session.createQuery("from " + c.getName()
				+ " where simulationId=" + simulationId + " and entity='"
				+ entity + "'");
	}

}
