package com.delect.motiver.server.dao;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.jdo.Transaction;
import org.datanucleus.store.appengine.query.JDOCursorHelper;
import com.delect.motiver.server.PMF;
import com.delect.motiver.server.dao.helper.RoutineSearchParams;
import com.delect.motiver.server.dao.helper.WorkoutSearchParams;
import com.delect.motiver.server.jdo.UserOpenid;
import com.delect.motiver.server.jdo.training.Exercise;
import com.delect.motiver.server.jdo.training.ExerciseName;
import com.delect.motiver.server.jdo.training.ExerciseNameCount;
import com.delect.motiver.server.jdo.training.Routine;
import com.delect.motiver.server.jdo.training.Workout;
import com.delect.motiver.server.service.MyServiceImpl;
import com.delect.motiver.server.util.DateUtils;
import com.delect.motiver.shared.Constants;
import com.google.appengine.api.datastore.Cursor;
import com.prodeagle.java.counters.Counter;
public class TrainingDAO {
/**
* Logger for this class
*/
private static final Logger logger = Logger.getLogger(TrainingDAO.class.getName());
private static TrainingDAO dao;
public static TrainingDAO getInstance() {
if(dao == null) {
dao = new TrainingDAO();
}
return dao;
}
public void addWorkouts(List<Workout> models) throws Exception {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Adding workouts: "+models);
}
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
for(Workout workout : models) {
pm.makePersistent(workout);
}
} catch (Exception e) {
throw e;
}
finally {
if (!pm.isClosed()) {
pm.close();
}
}
}
public void addRoutines(List<Routine> models) throws Exception {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Adding routines: "+models);
}
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
for(Routine routine : models) {
pm.makePersistent(routine);
}
} catch (Exception e) {
throw e;
}
finally {
if (!pm.isClosed()) {
pm.close();
}
}
}
public boolean removeWorkout(Workout model) throws Exception {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Removing workout: "+model);
}
boolean ok = false;
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
//try to update X times
int retries = Constants.LIMIT_UPDATE_RETRIES;
while (true) {
Transaction tx = pm.currentTransaction();
tx.begin();
try {
Workout t = pm.getObjectById(Workout.class, model.getId());
if(t != null) {
pm.deletePersistent(t);
tx.commit();
ok = true;
break;
}
}
catch (Exception e) {
if (tx.isActive()) {
tx.rollback();
}
logger.log(Level.WARNING, "Error deleting workout", e);
//retries used
if (retries == 0) {
throw e;
}
logger.log(Level.WARNING, " Retries left: "+retries);
--retries;
}
}
} catch (Exception e) {
throw e;
}
finally {
if (!pm.isClosed()) {
pm.close();
}
}
return ok;
}
@SuppressWarnings("unchecked")
public List<ExerciseName> getExerciseNames(String locale) throws Exception {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Loading exercise names");
}
//prodeagle counter
Counter.increment("DAO.ExerciseNames");
PersistenceManager pm = PMF.get().getPersistenceManager();
List<ExerciseName> n = new ArrayList<ExerciseName>();
try {
Cursor cursor = null;
Map<String, Object> extensionMap = new HashMap<String, Object>();
//get using cursors
while(true){
Query q = pm.newQuery(ExerciseName.class);
q.setFilter("locale == localeParam");
q.declareParameters("java.lang.String localeParam");
q.setRange(0, 700);
if(cursor != null) {
extensionMap.put(JDOCursorHelper.CURSOR_EXTENSION, cursor);
q.setExtensions(extensionMap);
}
List<ExerciseName> u = (List<ExerciseName>) q.execute(locale);
cursor = JDOCursorHelper.getCursor(u);
n.addAll(u);
if(u.size() == 0) {
break;
}
}
} catch (Exception e) {
throw e;
}
finally {
if (!pm.isClosed()) {
pm.close();
}
}
return n;
}
@SuppressWarnings("unchecked")
public int getExerciseNameCount(UserOpenid user, Long id) throws Exception {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Loading exercise name ("+id+") count for "+user);
}
int count = -1;
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
Query qUse = pm.newQuery(ExerciseNameCount.class);
qUse.setFilter("nameId == nameIdParam && openId == openIdParam");
qUse.declareParameters("java.lang.Long nameIdParam, java.lang.String openIdParam");
qUse.setRange(0, 1);
List<ExerciseNameCount> valueCount = (List<ExerciseNameCount>) qUse.execute(id, user.getUid());
if(valueCount.size() > 0) {
count = valueCount.get(0).getCount();
}
if(count < 0) {
count = 0;
}
} catch (Exception e) {
throw e;
}
finally {
if (!pm.isClosed()) {
pm.close();
}
}
return count;
}
public void addExerciseName(ExerciseName name) {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Adding exercise name: "+name);
}
//prodeagle counter
Counter.increment("DAO.ExerciseName.New");
PersistenceManager pm = PMF.get().getPersistenceManager();
Transaction tx = pm.currentTransaction();
tx.begin();
try {
pm.makePersistent(name);
tx.commit();
} catch (Exception e) {
logger.log(Level.SEVERE, "Error adding exercise name", e);
}
finally {
if(tx.isActive()) {
tx.rollback();
}
if (!pm.isClosed()) {
pm.close();
}
}
}
/**
* Return all routines
* @return
* @throws Exception
*/
@SuppressWarnings("unchecked")
public List<Routine> getRoutines() throws Exception {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Loading ALL routines");
}
PersistenceManager pm = PMF.get().getPersistenceManager();
List<Routine> n = new ArrayList<Routine>();
try {
int i = 0;
while(true){
Query q = pm.newQuery(Routine.class);
q.setOrdering("name ASC");
q.setRange(i, i+100);
List<Routine> u = (List<Routine>) q.execute();
n.addAll(u);
if(u.size() < 100) {
break;
}
i += 100;
}
} catch (Exception e) {
throw e;
}
finally {
if (!pm.isClosed()) {
pm.close();
}
}
return n;
}
public Workout getWorkout(long workoutId) throws Exception {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Loading workout: "+workoutId);
}
//prodeagle counter
Counter.increment("DAO.Workout");
Workout workout = null;
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
Workout jdo = pm.getObjectById(Workout.class, workoutId);
if(jdo != null) {
workout = pm.detachCopy(jdo);
if(jdo.getExercises().size() > 0) {
workout.setExercises(new ArrayList<Exercise>(pm.detachCopyAll(jdo.getExercises())));
}
}
} catch (Exception e) {
throw e;
}
finally {
if (!pm.isClosed()) {
pm.close();
}
}
return workout;
}
public Routine getRoutine(long routineId) throws Exception {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Loading routine: "+routineId);
}
//prodeagle counter
Counter.increment("DAO.Routine");
Routine routine = null;
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
Routine jdo = pm.getObjectById(Routine.class, routineId);
if(jdo != null) {
routine = pm.detachCopy(jdo);
}
} catch (Exception e) {
throw e;
}
finally {
if (!pm.isClosed()) {
pm.close();
}
}
return routine;
}
public void updateWorkout(Workout workout, boolean updateExercises) throws Exception {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Updating workout: "+workout);
}
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
//try to update X times
int retries = Constants.LIMIT_UPDATE_RETRIES;
while (true) {
Transaction tx = pm.currentTransaction();
tx.begin();
try {
Workout t = pm.getObjectById(Workout.class, workout.getId());
if(t != null) {
t.update(workout, false, updateExercises);
}
tx.commit();
break;
}
catch (Exception e) {
if (tx.isActive()) {
tx.rollback();
}
logger.log(Level.WARNING, "Error updating workout", e);
//retries used
if (retries == 0) {
throw e;
}
logger.log(Level.WARNING, " Retries left: "+retries);
--retries;
}
}
} catch (Exception e) {
throw e;
}
finally {
if (!pm.isClosed()) {
pm.close();
}
}
}
public void updateRoutine(Routine routine) throws Exception {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Updating routine: "+routine);
}
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
//try to update X times
int retries = Constants.LIMIT_UPDATE_RETRIES;
while (true) {
Transaction tx = pm.currentTransaction();
tx.begin();
try {
Routine t = pm.getObjectById(Routine.class, routine.getId());
if(t != null) {
t.update(routine, false);
pm.flush();
}
tx.commit();
routine.getWorkouts();
break;
}
catch (Exception e) {
if (tx.isActive()) {
tx.rollback();
}
logger.log(Level.WARNING, "Error updating workout", e);
//retries used
if (retries == 0) {
throw e;
}
logger.log(Level.WARNING, " Retries left: "+retries);
--retries;
}
}
} catch (Exception e) {
throw e;
}
finally {
if (!pm.isClosed()) {
pm.close();
}
}
}
public void updateExerciseName(ExerciseName name) throws Exception {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Updating exercise name: "+name);
}
PersistenceManager pm = PMF.get().getPersistenceManager();
Transaction tx = pm.currentTransaction();
tx.begin();
try {
ExerciseName t = pm.getObjectById(ExerciseName.class, name.getId());
if(t != null) {
t.update(name, false);
}
tx.commit();
} catch (Exception e) {
throw e;
}
finally {
if(tx.isActive()) {
tx.rollback();
}
if (!pm.isClosed()) {
pm.close();
}
}
}
@SuppressWarnings("unchecked")
public Set<Long> getWorkouts(WorkoutSearchParams params) throws Exception {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Loading workouts: "+params);
}
Set<Long> list = new HashSet<Long>();
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
int c = 0;
while(true){
int offset = params.offset + c;
int limit = offset + (params.limit - c);
if(limit - offset > 100) {
limit = offset + 100;
}
limit++;
Date dStart = null;
Date dEnd = null;
Query q = pm.newQuery(Workout.class);
// q.setOrdering("name ASC");
StringBuilder builder = MyServiceImpl.getStringBuilder();
if(params.uid != null) {
builder.append("openId == openIdParam && ");
}
if(params.routineId != null) {
builder.append("routineId == routineParam && ");
if(params.routineDay != null)
builder.append("dayInRoutine == routineDayParam && ");
}
else if(params.date == null) {
builder.append("routineId == 0 && ");
}
if(params.date != null) {
dStart = DateUtils.stripTime(params.date, true);
dEnd = DateUtils.stripTime(params.date, false);
builder.append("date >= dateStartParam && date <= dateEndParam");
}
else {
builder.append("date == null");
}
if(params.minCopyCount > 0) {
builder.append(" && copyCount >= copyCountParam");
q.setOrdering("copyCount DESC");
}
q.setFilter(builder.toString());
q.declareParameters("java.lang.String openIdParam, java.lang.Long routineParam, java.lang.Long routineDayParam, java.lang.Integer copyCountParam, java.util.Date dateStartParam, java.util.Date dateEndParam");
q.setRange(offset, limit);
List<Workout> workouts = (List<Workout>) q.executeWithArray(params.uid, params.routineId, params.routineDay, params.minCopyCount, dStart, dEnd);
//get workouts
if(workouts != null) {
for(Workout m : workouts) {
//if limit reached -> add null value
if(list.size() >= params.limit) {
list.add(null);
break;
}
list.add(m.getId());
}
//if enough found or last query didn't return enough rows
if(list.size() >= params.limit || workouts.size() < limit) {
break;
}
c+= 100;
}
else {
break;
}
}
} catch (Exception e) {
throw e;
}
finally {
if (!pm.isClosed()) {
pm.close();
}
}
return list;
}
@SuppressWarnings("unchecked")
public List<Long> getRoutines(RoutineSearchParams params) throws Exception {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Loading routines: "+params);
}
List<Long> list = new ArrayList<Long>();
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
int c = 0;
while(true){
int offset = params.offset + c;
int limit = offset + (params.limit - c);
if(limit - offset > 100) {
limit = offset + 100;
}
limit++;
Query q = pm.newQuery(Routine.class);
q.setOrdering("name ASC");
StringBuilder builder = MyServiceImpl.getStringBuilder();
if(params.uid != null) {
builder.append("openId == openIdParam && ");
}
if(params.date != null) {
builder.append("date == dateParam");
}
else {
builder.append("date == null");
}
if(params.minCopyCount > 0) {
builder.append(" && copyCount >= copyCountParam");
q.setOrdering("copyCount DESC");
}
q.setFilter(builder.toString());
q.declareParameters("java.lang.String openIdParam, java.lang.Integer copyCountParam, java.util.Date dateParam");
q.setRange(offset, limit);
List<Routine> routines = (List<Routine>) q.execute(params.uid, params.minCopyCount, params.date);
//get routines
if(routines != null) {
for(Routine m : routines) {
//if limit reached -> add null value
if(list.size() >= params.limit) {
list.add(null);
break;
}
list.add(m.getId());
}
//if enough found or last query didn't return enough rows
if(list.size() >= params.limit || routines.size() < limit) {
break;
}
c+= 100;
}
else {
break;
}
}
} catch (Exception e) {
throw e;
}
finally {
if (!pm.isClosed()) {
pm.close();
}
}
return list;
}
public boolean removeWorkouts(Long[] keys) throws Exception {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Removing workouts: "+keys);
}
boolean ok = false;
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
for (Long key : keys) {
//try to update X workouts
int retries = Constants.LIMIT_UPDATE_RETRIES;
while (true) {
Transaction tx = pm.currentTransaction();
tx.begin();
try {
Workout t = pm.getObjectById(Workout.class, key);
if(t != null) {
pm.deletePersistent(t);
tx.commit();
ok = true;
break;
}
}
catch (Exception e) {
if (tx.isActive()) {
tx.rollback();
}
logger.log(Level.WARNING, "Error deleting workout", e);
//retries used
if (retries == 0) {
throw e;
}
logger.log(Level.WARNING, " Retries left: "+retries);
--retries;
}
}
}
} catch (Exception e) {
logger.log(Level.SEVERE, "Error removing workouts", e);
}
finally {
if (!pm.isClosed()) {
pm.close();
}
}
return ok;
}
public boolean removeRoutines(Long[] keys) throws Exception {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Removing routines: "+keys);
}
boolean ok = false;
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
for (Long key : keys) {
//try to update X routines
int retries = Constants.LIMIT_UPDATE_RETRIES;
while (true) {
Transaction tx = pm.currentTransaction();
tx.begin();
try {
Routine t = pm.getObjectById(Routine.class, key);
if(t != null) {
pm.deletePersistent(t);
tx.commit();
ok = true;
break;
}
}
catch (Exception e) {
if (tx.isActive()) {
tx.rollback();
}
logger.log(Level.WARNING, "Error deleting routine", e);
//retries used
if (retries == 0) {
throw e;
}
logger.log(Level.WARNING, " Retries left: "+retries);
--retries;
}
}
}
} catch (Exception e) {
logger.log(Level.SEVERE, "Error removing routines", e);
}
finally {
if (!pm.isClosed()) {
pm.close();
}
}
return ok;
}
public void incrementWorkoutCount(Workout workout) throws Exception {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Incrementing count for: "+workout);
}
PersistenceManager pm = PMF.get().getPersistenceManager();
Transaction tx = pm.currentTransaction();
tx.begin();
try {
Workout t = pm.getObjectById(Workout.class, workout.getId());
if(t != null) {
t.setCount(t.getCount() + 1);
}
tx.commit();
workout.update(t, true, false);
} catch (Exception e) {
throw e;
}
finally {
if(tx.isActive()) {
tx.rollback();
}
if (!pm.isClosed()) {
pm.close();
}
}
}
public void incrementRoutineCount(Routine routine) throws Exception {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Incrementing count for: "+routine);
}
PersistenceManager pm = PMF.get().getPersistenceManager();
Transaction tx = pm.currentTransaction();
tx.begin();
try {
Routine t = pm.getObjectById(Routine.class, routine.getId());
if(t != null) {
t.setCount(t.getCount() + 1);
}
tx.commit();
routine.update(t, true);
} catch (Exception e) {
throw e;
}
finally {
if(tx.isActive()) {
tx.rollback();
}
if (!pm.isClosed()) {
pm.close();
}
}
}
public void addRoutine(Routine routine) throws Exception {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Adding routine: "+routine);
}
List<Routine> list = new ArrayList<Routine>();
list.add(routine);
addRoutines(list);
//get new routine
if(list.size() > 0) {
routine = list.get(0);
}
}
public ExerciseName getExerciseName(Long key) throws Exception {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Loading food name for ID: "+key);
}
Counter.increment("DAO.ExerciseName");
ExerciseName n = null;
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
n = pm.getObjectById(ExerciseName.class, key);
} catch (Exception e) {
throw e;
}
finally {
if (!pm.isClosed()) {
pm.close();
}
}
return n;
}
}