package net.sourceforge.javautil.database.jpa;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.EntityNotFoundException;
import javax.persistence.EntityTransaction;
import javax.persistence.FlushModeType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.LockModeType;
import javax.persistence.NoResultException;
import javax.persistence.Query;
import net.sourceforge.javautil.database.query.QueryDataScroller;
import net.sourceforge.javautil.database.query.jpa.QueryBuilderSelectJPA;
import net.sourceforge.javautil.database.query.jpa.QueryExecutorJPA;
import net.sourceforge.javautil.database.query.sql.OrderByFragment.Direction;
import org.apache.commons.codec.binary.Base64;
/**
* An implementation of the extended functionality.
*
* @author elponderador
* @author $Author$
* @version $Id$
*/
public class EntityManagerExtendedImpl implements IEntityManagerExtended {
protected final EntityManager em;
private Map<String, Class> converterKeys = new HashMap<String, Class>();
private Map<Class, Method> converterIds = new HashMap<Class, Method>();
public EntityManagerExtendedImpl(EntityManager em) {
this.em = em;
this.em.setFlushMode(FlushModeType.AUTO);
}
/**
* @return The em this is wrapping
*/
public EntityManager getRealEntityManager () { return this.em; }
//
// Extended Implementation
//
public EntityManager getStorage () { return em; }
public QueryDataScroller managedQuery(String fields, String from, String where, String orderBy) {
return this.managedQuery(null, fields, from, where, orderBy);
}
public QueryDataScroller managedQuery(Map<String, Object> parameters, String fields, String from, String where, String orderBy) {
return this.managedQuery(parameters, fields, from, where, orderBy, "", "");
}
public QueryDataScroller managedQuery(String fields, String from, String where, String orderBy, String groupBy, String having) {
return this.managedQuery(null, fields, from, where, orderBy, groupBy, having);
}
public QueryDataScroller managedQuery(Map<String, Object> parameters, String fields, String from, String where, String orderBy, String groupBy, String having) {
QueryBuilderSelectJPA jpa = new QueryBuilderSelectJPA();
for (String table : from.split(",")) {
jpa.getFrom().add(table.trim());
}
for (String field : fields.split(",")) {
jpa.getSelected().addSelected(field.trim());
}
if (where != null && !"".equals(where.trim())) {
jpa.getWhere().addParameterized(where, parameters == null ? new String[0] : parameters.keySet().toArray(new String[parameters.size()]));
if (parameters != null) jpa.getParameters().putAll(parameters);
}
if (groupBy != null && !"".equals(groupBy.trim())) {
jpa.groupBy(groupBy.split(","));
if (having != null && !"".equals(having.trim())) {
jpa.getHaving().addParameterized(having, parameters == null ? new String[0] : parameters.keySet().toArray(new String[parameters.size()]));
if (parameters != null) jpa.getParameters().putAll(parameters);
}
}
if (orderBy != null) {
for (String order : orderBy.split(",")) {
if (order.trim().equals("")) continue;
String[] parts = order.split(" ");
if (parts.length == 2 && "DESC".equalsIgnoreCase( parts[1] )) {
jpa.getOrderBy().addOrderBy(parts[0].trim(), Direction.DESC);
} else {
jpa.getOrderBy().addOrderBy(order.trim());
}
}
}
return new QueryDataScroller(new QueryExecutorJPA(this), jpa);
}
public int execute (String queryString) {
return this.execute(queryString, new HashMap());
}
public int executeNative (String query, Object... pars) {
Query q = this.getStorage().createNativeQuery(query);
for (int i=0; i<pars.length; i++) q.setParameter(i, pars[i]);
return q.executeUpdate();
}
public List getNativeResults (String query) { return this.getNativeResults(query, new Object[0]); }
public List getNativeResults (String query, Object... pars) {
return this.getNativeResults(query, 0, -1, pars);
}
public List getNativeResults (String query, int offset, int max, Object... pars) {
Query q = this.getStorage().createNativeQuery(query);
if (offset > -1) q.setFirstResult(offset);
if (max > 0) q.setMaxResults(max);
return q.getResultList();
}
public List<Map<String,Object>> translate (List<Object[]> results, String... names) {
List<Map<String,Object>> newList = new ArrayList<Map<String,Object>>();
for (Object[] result : results) {
Map<String,Object> map = new LinkedHashMap<String, Object>();
for (int i=0; i<result.length; i++) {
String fn = i >= names.length ? "field" + i : names[i];
map.put(fn, result[i]);
}
newList.add(map);
}
return newList;
}
public <T> T save (T entity) { return this.save(entity, "getId"); }
public <T> T save (T entity, String id) {
try {
Method method = entity.getClass().getMethod(id);
boolean persisted = true;
if (method.getReturnType().isPrimitive() || Number.class.isAssignableFrom(method.getReturnType())) {
Object value = method.invoke(entity);
if (value == null) persisted = false;
else if ("0".equals(value.toString())) persisted = false;
}
if (persisted) this.merge(entity);
else this.persist(entity);
return entity;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public int execute (Map parameters, String queryString) {
return this.execute(queryString, parameters);
}
public int execute (String queryString, Map parameters) {
Query query = this.getStorage().createQuery(queryString);
if (parameters != null) for (Object key : parameters.keySet()) {
Object value = this.translateParameter( parameters.get(key) );
if (queryString.contains(":" + key)) query.setParameter(key.toString(), value);
}
return query.executeUpdate();
}
public Object translateParameter (Object object) { return object; }
public boolean exists (Map parameters, String queryString) {
return this.getResults(parameters, queryString, -1, -1).size() > 0;
}
public Object getSingleResult (String queryString) {
return this.getSingleResult(new HashMap(), queryString);
}
public Object getSingleResult (Map parameters, String queryString) {
try {
Query query = this.getStorage().createQuery(queryString);
query.setFirstResult(0);
query.setMaxResults(1);
if (parameters != null) for (Object key : parameters.keySet()) {
Object value = this.translateParameter( parameters.get(key) );
if (queryString.contains(":" + key)) query.setParameter(key.toString(), value);
}
return query.getSingleResult();
} catch (NoResultException e) {
return null;
}
}
public Map getResultMap (String queryString, String keyMethod) {
return this.getResultMap(new HashMap(), queryString, keyMethod);
}
public Map getResultMap (Map parameters, String queryString, String keyMethod) {
List results = this.getResults(parameters, queryString, -1, -1);
Map map = new LinkedHashMap();
for (Object result : results) {
try {
Method method = result.getClass().getMethod(keyMethod);
String key = String.valueOf( method.invoke(result) );
map.put(key, result);
} catch (Exception e) {
throw new IllegalArgumentException("Could not find field: " + keyMethod, e);
}
}
return map;
}
public List getResults (String queryString) {
return this.getResults(new HashMap(), queryString, -1, -1);
}
public List getResults(String queryString, int offset, int max) {
return this.getResults(new HashMap(), queryString, offset, max);
}
public List getResults(Map parameters, String queryString) {
return this.getResults(parameters, queryString, -1, -1);
}
public List getResults (Map parameters, String queryString, int offset, int max) {
Query query = this.getStorage().createQuery(queryString);
if (offset > -1) query.setFirstResult(offset);
if (max > -1) query.setMaxResults(max);
if (parameters != null) for (Object key : parameters.keySet()) {
Object value = this.translateParameter( parameters.get(key) );
if (queryString.contains(":" + key)) query.setParameter(key.toString(), value);
}
return query.getResultList();
}
//
// Entity Manager Delegation
//
public void clear() {
em.clear();
}
public void close() {
em.close();
}
public boolean contains(Object entity) {
return em.contains(entity);
}
public Query createNamedQuery(String name) {
return em.createNamedQuery(name);
}
public Query createNativeQuery(String sqlString, Class resultClass) {
return em.createNativeQuery(sqlString, resultClass);
}
public Query createNativeQuery(String sqlString, String resultSetMapping) {
return em.createNativeQuery(sqlString, resultSetMapping);
}
public Query createNativeQuery(String sqlString) {
return em.createNativeQuery(sqlString);
}
public Query createQuery(String qlString) {
return em.createQuery(qlString);
}
public <T> T find(Class<T> entityClass, Object primaryKey) {
return em.find(entityClass, primaryKey);
}
public void flush() {
em.flush();
}
public Object getDelegate() {
return em.getDelegate();
}
public FlushModeType getFlushMode() {
return em.getFlushMode();
}
public <T> T getReference(Class<T> entityClass, Object primaryKey) {
return em.getReference(entityClass, primaryKey);
}
public EntityTransaction getTransaction() {
return em.getTransaction();
}
public boolean isOpen() {
return em.isOpen();
}
public void joinTransaction() {
em.joinTransaction();
}
public void lock(Object entity, LockModeType lockMode) {
em.lock(entity, lockMode);
}
public <T> T merge(T entity) {
return em.merge(entity);
}
public void persist(Object entity) {
em.persist(entity);
}
public void refresh(Object entity) {
em.refresh(entity);
}
public void remove(Object entity) {
em.remove(entity);
}
public void setFlushMode(FlushModeType flushMode) {
em.setFlushMode(flushMode);
}
}