package org.geoserver.hibernate;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.geoserver.catalog.Info;
import org.geoserver.catalog.MetadataMap;
import org.geoserver.ows.util.OwsUtils;
import org.geotools.util.logging.Logging;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.proxy.HibernateProxy;
public class AbstractHibFacade {
/**
* logging instance
*/
protected final Logger LOGGER = Logging.getLogger("org.geoserver.hibernate");
protected SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public SessionFactory getSessionFactory() {
return sessionFactory;
}
/** Simple wrapper to tell which objects are bindable query parameters */
protected static class QueryParam {
Object param;
public QueryParam(Object param) {
this.param = param;
}
}
protected static QueryParam param(Object param) {
return new QueryParam(param);
}
protected Query query(Object... elems) {
final StringBuilder builder = new StringBuilder();
int cnt = 0;
for (Object elem : elems) {
if (elem instanceof String) {
builder.append(elem);
}
else if (elem instanceof Class) {
Class clazz = (Class) elem;
ClassMappings map = ClassMappings.fromInterface(clazz);
if (map != null) {
clazz = map.getImpl();
}
builder.append(clazz.getSimpleName());
}
else if (elem instanceof QueryParam) {
builder.append(":param").append(cnt++);
}
}
Query query = sessionFactory.getCurrentSession().createQuery(builder.toString());
query.setCacheable(true);
cnt = 0;
for (Object elem : elems) {
if (elem instanceof QueryParam) {
query.setParameter("param" + (cnt++), ((QueryParam) elem).param);
}
}
return query;
}
protected Object first(final Query query) {
return first(query, true);
}
protected Object first(final Query query, boolean doWarn) {
query.setMaxResults(doWarn ? 2 : 1);
query.setCacheable(true);
List<?> result = query.list();
if (result.isEmpty()) {
return null;
}
else {
//TODO: add a flag to control exception
if (result.size() > 1) {
throw new RuntimeException("Expected 1 result from " + query + " but got " + result.size());
}
// if (doWarn && result.size() > 1) {
// LOGGER.log(Level.WARNING, "Found too many items in result", new RuntimeException(
// "Trace: Found too many items in query"));
// }
Object ret = result.get(0);
if (ret instanceof HibernateProxy) {
HibernateProxy proxy = (HibernateProxy) ret;
ret = proxy.getHibernateLazyInitializer().getImplementation();
}
if (LOGGER.isLoggable(Level.FINE)){
StringBuilder callerChain = new StringBuilder();
for (StackTraceElement stackTraceElement : new Throwable().getStackTrace()) {
if ("first".equals(stackTraceElement.getMethodName()))
continue;
String cname = stackTraceElement.getClassName();
if (cname.startsWith("org.spring"))
continue;
cname = cname.substring(cname.lastIndexOf(".") + 1);
callerChain.append(cname).append('.').append(stackTraceElement.getMethodName())
.append(':').append(stackTraceElement.getLineNumber()).append(' ');
// if(++num==10) break;
}
LOGGER.fine("FIRST -->" + ret.getClass().getSimpleName() + " --- " + ret + " { "
+ callerChain + "}");
}
return ret;
}
}
protected <T> List<T> list(Class<T> clazz) {
Query query = query("from ", clazz);
query.setCacheable(true);
List<?> result = query.list();
return Collections.unmodifiableList((List<T>) result);
}
protected <T extends Info> T persist(T entity) {
return persist(entity, true);
}
protected <T extends Info> T persist(T entity, boolean clearId) {
if (clearId) {
//hack, clear out id if we are adding a new object
Object id = OwsUtils.get(entity, "id");
if (id != null) {
OwsUtils.set(entity, "id", null);
}
}
try {
MetadataMap md = (MetadataMap) OwsUtils.get(entity, "metadata");
if (md != null) {
md.setId(null);
}
}
catch(IllegalArgumentException e1) {}
catch(ClassCastException e2) {}
sessionFactory.getCurrentSession().persist(entity);
return entity;
}
protected <T extends Info> T merge(T entity) {
return (T) sessionFactory.getCurrentSession().merge(entity);
}
protected void delete(Info entity) {
Session session = sessionFactory.getCurrentSession();
Info attached = (Info) session.merge(entity);
session.delete(attached);
}
}