/*
* Copyright 2013 GiavaCms.org.
*
* Licensed under the Eclipse Public License version 1.0, available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.giavacms.common.repository;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.Query;
import org.giavacms.common.annotation.Condition;
import org.giavacms.common.annotation.NotNullAndNotEmpty;
import org.giavacms.common.annotation.Smart;
import org.giavacms.common.model.Search;
/**
* @author fiorenzo pizza
*
* @param <T>
*/
public abstract class SmartRepository<T> extends AbstractRepository<T>
implements Serializable, Repository<T>
{
private static final long serialVersionUID = 1L;
/**
* criteri di default, comuni a tutti, ma specializzabili da ogni EJB tramite overriding
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
protected Query getRestrictions(Search<T> search, boolean justCount)
{
Class c = search.getObj().getClass();
// se non c'รจ smart tutto come prima
Smart smart_anno = (Smart) c.getAnnotation(Smart.class);
if (smart_anno == null)
{
return super.getRestrictions(search, justCount);
}
// altrimenti costruiamo la query qui
Map<String, Object> params = new HashMap<String, Object>();
String alias = smart_anno.alias();
StringBuffer sb = new StringBuffer(getBaseList(search.getObj()
.getClass(), alias, justCount));
String separator = " where ";
String operator = smart_anno.operator();
Field[] fields = c.getDeclaredFields();
for (Field field : fields)
{
Condition condition = field.getAnnotation(Condition.class);
if (condition == null)
{
continue;
}
field.setAccessible(true);
Object v = null;
try
{
v = field.get(search.getObj());
}
catch (Exception e)
{
// should not happen;
e.printStackTrace();
continue;
}
NotNullAndNotEmpty notNullAndNotEmpty = field
.getAnnotation(NotNullAndNotEmpty.class);
if (v == null && notNullAndNotEmpty != null)
{
continue;
}
// aggiunta alla query
sb.append(separator).append(condition.ejbql());
// aggiunta alla mappa
List<String> paramNames = estrai(condition.ejbql());
for (String paramName : paramNames)
{
params.put(paramName, v);
// come si gestisce il caso like??
// params.put("cognome", likeParam(
// search.getObj().getCognome().toUpperCase()));
}
// separatore
separator = operator;
}
Method[] methods = c.getDeclaredMethods();
for (Method method : methods)
{
Condition condition = method.getAnnotation(Condition.class);
if (condition == null)
{
continue;
}
method.setAccessible(true);
Object[] vs = null;
;
try
{
vs = (Object[]) method.invoke(search.getObj(),
new Object[] {});
}
catch (Exception e)
{
// should not happen
e.printStackTrace();
continue;
}
if (vs == null)
{
continue;
}
NotNullAndNotEmpty notNullAndNotEmpty = method
.getAnnotation(NotNullAndNotEmpty.class);
for (Object v : vs)
{
if (v == null && notNullAndNotEmpty != null)
{
continue;
}
}
// aggiunta alla query
sb.append(separator).append(condition.ejbql());
// aggiunta alla mappa
List<String> paramNames = estrai(condition.ejbql());
for (int i = 0; i < vs.length; i++)
{
params.put(paramNames.get(i), vs[i]);
// come si gestisce il caso like??
// params.put("cognome", likeParam(
// search.getObj().getCognome().toUpperCase()));
}
// separatore
separator = operator;
}
if (!justCount)
{
sb.append(getOrderBy(alias, search.getOrder()));
}
Query q = getEm().createQuery(sb.toString());
for (String param : params.keySet())
{
q.setParameter(param, params.get(param));
}
return q;
}
private List<String> estrai(String ejbql)
{
List<String> names = new ArrayList<String>();
int beginP = ejbql.indexOf(":");
while (beginP >= 0)
{
String subql = ejbql.substring(beginP + 1);
int endP = subql.indexOf(" ");
if (endP > 0)
{
names.add(subql.substring(0, endP));
}
else
{
names.add(subql);
}
ejbql = subql;
beginP = ejbql.indexOf(":");
}
return names;
}
}