/*
* Copyright (C) 2010-2015 Stichting Akvo (Akvo Foundation)
*
* This file is part of Akvo FLOW.
*
* Akvo FLOW is free software: you can redistribute it and modify it under the terms of
* the GNU Affero General Public License (AGPL) as published by the Free Software Foundation,
* either version 3 of the License or any later version.
*
* Akvo FLOW is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Affero General Public License included below for more details.
*
* The full license text can also be seen at <http://www.gnu.org/licenses/agpl.html>.
*/
package org.waterforpeople.mapping.dao;
import static com.gallatinsystems.common.util.MemCacheUtils.containsKey;
import static com.gallatinsystems.common.util.MemCacheUtils.initCache;
import static com.gallatinsystems.common.util.MemCacheUtils.putObjects;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import javax.jdo.PersistenceManager;
import net.sf.jsr107cache.Cache;
import net.sf.jsr107cache.CacheException;
import org.waterforpeople.mapping.domain.QuestionAnswerStore;
import com.gallatinsystems.framework.dao.BaseDAO;
import com.gallatinsystems.framework.domain.BaseDomain;
import com.gallatinsystems.framework.servlet.PersistenceFilter;
public class QuestionAnswerStoreDao extends BaseDAO<QuestionAnswerStore> {
private Cache cache;
public QuestionAnswerStoreDao() {
super(QuestionAnswerStore.class);
cache = initCache(4 * 60 * 60); // cache questions list for 4 hours
}
public List<QuestionAnswerStore> listBySurvey(Long surveyId) {
return super.listByProperty("surveyId", surveyId, "Long");
}
public List<QuestionAnswerStore> listByQuestion(Long questionId) {
return super.listByProperty("questionID", questionId.toString(),
"String", "createdDateTime");
}
@SuppressWarnings("unchecked")
public List<QuestionAnswerStore> listByQuestion(Long questionId, String cursor, Integer pageSize) {
PersistenceManager pm = PersistenceFilter.getManager();
javax.jdo.Query query = pm.newQuery(QuestionAnswerStore.class);
StringBuilder filterString = new StringBuilder();
StringBuilder paramString = new StringBuilder();
Map<String, Object> paramMap = new HashMap<String, Object>();
appendNonNullParam("questionID", filterString, paramString, "String",
String.valueOf(questionId),
paramMap);
query.setFilter(filterString.toString());
query.declareParameters(paramString.toString());
query.setOrdering("createdDateTime");
prepareCursor(cursor, pageSize, query);
return (List<QuestionAnswerStore>) query.executeWithMap(paramMap);
}
/**
* lists all the QuestionAnswerStore objects that match the type passed in
*
* @param type
* @param cursor
* @param pageSize
* @return
*/
@SuppressWarnings("unchecked")
public List<QuestionAnswerStore> listByTypeAndDate(String type,
Long surveyId, Date sinceDate, String cursor, Integer pageSize) {
PersistenceManager pm = PersistenceFilter.getManager();
javax.jdo.Query query = pm.newQuery(QuestionAnswerStore.class);
Map<String, Object> paramMap = null;
StringBuilder filterString = new StringBuilder();
StringBuilder paramString = new StringBuilder();
paramMap = new HashMap<String, Object>();
appendNonNullParam("type", filterString, paramString, "String", type,
paramMap);
appendNonNullParam("surveyId", filterString, paramString, "Long",
surveyId, paramMap);
appendNonNullParam("lastUpdateDateTime", filterString, paramString,
"Date", sinceDate, paramMap, GTE_OP);
if (sinceDate != null) {
query.declareImports("import java.util.Date");
}
query.setFilter(filterString.toString());
query.declareParameters(paramString.toString());
prepareCursor(cursor, pageSize, query);
return (List<QuestionAnswerStore>) query.executeWithMap(paramMap);
}
@SuppressWarnings("unchecked")
public List<QuestionAnswerStore> listByTypeValue(String type, String value) {
PersistenceManager pm = PersistenceFilter.getManager();
javax.jdo.Query query = pm.newQuery(QuestionAnswerStore.class);
Map<String, Object> paramMap = null;
StringBuilder filterString = new StringBuilder();
StringBuilder paramString = new StringBuilder();
paramMap = new HashMap<String, Object>();
appendNonNullParam("type", filterString, paramString, "String", type,
paramMap);
appendNonNullParam("value", filterString, paramString, "String", value,
paramMap);
query.setFilter(filterString.toString());
query.declareParameters(paramString.toString());
return (List<QuestionAnswerStore>) query.executeWithMap(paramMap);
}
/**
* lists all the QuestionAnswerStore objects that match the type passed in
*
* @param sinceDate
* @param cursor
* @param pageSize
* @return
*/
@SuppressWarnings("unchecked")
public List<QuestionAnswerStore> listByNotNullCollectionDateBefore(
Date sinceDate, String cursor, Integer pageSize) {
PersistenceManager pm = PersistenceFilter.getManager();
javax.jdo.Query query = pm.newQuery(QuestionAnswerStore.class);
Map<String, Object> paramMap = null;
StringBuilder filterString = new StringBuilder();
StringBuilder paramString = new StringBuilder();
paramMap = new HashMap<String, Object>();
appendNonNullParam("collectionDate", filterString, paramString, "Date",
sinceDate, paramMap, LTE_OP);
if (sinceDate != null) {
query.declareImports("import java.util.Date");
}
query.setFilter(filterString.toString());
query.declareParameters(paramString.toString());
prepareCursor(cursor, pageSize, query);
return (List<QuestionAnswerStore>) query.executeWithMap(paramMap);
}
@SuppressWarnings("unchecked")
public List<QuestionAnswerStore> listByNotNullCollectionDateAfter(
Date sinceDate, String cursor, Integer pageSize) {
PersistenceManager pm = PersistenceFilter.getManager();
javax.jdo.Query query = pm.newQuery(QuestionAnswerStore.class);
Map<String, Object> paramMap = null;
StringBuilder filterString = new StringBuilder();
StringBuilder paramString = new StringBuilder();
paramMap = new HashMap<String, Object>();
appendNonNullParam("collectionDate", filterString, paramString, "Date",
sinceDate, paramMap, GTE_OP);
if (sinceDate != null) {
query.declareImports("import java.util.Date");
}
query.setFilter(filterString.toString());
query.declareParameters(paramString.toString());
// prepareCursor(cursor, pageSize, query);
log.log(Level.INFO, query.toString());
return (List<QuestionAnswerStore>) query.executeWithMap(paramMap);
}
/**
* lists all the QuestionAnswerStore objects that match the type passed in
*
* @param sinceDate
* @param cursor
* @param pageSize
* @return
*/
@SuppressWarnings("unchecked")
public List<QuestionAnswerStore> listByExactDateString() {
PersistenceManager pm = PersistenceFilter.getManager();
javax.jdo.Query query = pm.newQuery("select from "
+ QuestionAnswerStore.class.getName()
+ " where collectionDate == 5674906531303000000");
log.log(Level.INFO, query.toString());
return (List<QuestionAnswerStore>) query.execute();
}
public List<QuestionAnswerStore> listBySurveyInstance(Long surveyInstanceId) {
List<QuestionAnswerStore> responses = super.listByProperty("surveyInstanceId",
surveyInstanceId, "Long");
cache(responses);
return responses;
}
public Map<Long, Map<Integer, QuestionAnswerStore>> mapByQuestionIdAndIteration(
List<QuestionAnswerStore> qasList) {
Map<Long, Map<Integer, QuestionAnswerStore>> responseMap = new HashMap<>();
for (QuestionAnswerStore a : qasList) {
Long questionId = Long.parseLong(a.getQuestionID());
Integer iteration = a.getIteration();
// default iteration = 0
iteration = iteration == null ? 0 : iteration;
Map<Integer, QuestionAnswerStore> iterationMap = responseMap.get(questionId);
if (iterationMap == null) {
iterationMap = new HashMap<>();
responseMap.put(questionId, iterationMap);
}
iterationMap.put(iteration, a);
}
return responseMap;
}
public Map<Long, QuestionAnswerStore> mapByQuestionId(List<QuestionAnswerStore> qasList) {
Map<Long, QuestionAnswerStore> qasMap = new HashMap<Long, QuestionAnswerStore>();
try {
for (QuestionAnswerStore a : qasList) {
if (a.getQuestionID() != null) {
qasMap.put(Long.parseLong(a.getQuestionID()), a);
}
}
return qasMap;
} catch (NumberFormatException e) {
return Collections.emptyMap();
}
}
@SuppressWarnings("unchecked")
public QuestionAnswerStore getByQuestionAndSurveyInstance(Long questionId, Long surveyInstanceId) {
String cacheKey;
try {
cacheKey = getCacheKey(surveyInstanceId + "-" + questionId);
if (containsKey(cache, cacheKey)) {
return (QuestionAnswerStore) cache.get(cacheKey);
}
} catch (CacheException e) {
log.log(Level.WARNING, e.getMessage());
}
PersistenceManager pm = PersistenceFilter.getManager();
javax.jdo.Query query = pm.newQuery(QuestionAnswerStore.class);
query.setFilter("surveyInstanceId == surveyInstanceIdParam && questionID == questionIdParam");
query.declareParameters("Long surveyInstanceIdParam, String questionIdParam");
List<QuestionAnswerStore> results = (List<QuestionAnswerStore>) query.execute(
surveyInstanceId, questionId.toString());
if (results != null && results.size() > 0) {
return results.get(0);
} else {
return null;
}
}
public boolean isCached(Long questionId, Long surveyInstanceId) {
try {
return containsKey(cache, getCacheKey(surveyInstanceId + "-" + questionId));
} catch (CacheException e) {
// ignore
}
return false;
}
/**
* Saves response and update cache
*
* @param reponse
*/
public QuestionAnswerStore save(QuestionAnswerStore reponse) {
// first save and get Id
QuestionAnswerStore savedResponse = super.save(reponse);
cache(Arrays.asList(savedResponse));
return savedResponse;
}
/**
* Save a collection of responses and cache
*
* @param responseList
* @return
*/
public List<QuestionAnswerStore> save(List<QuestionAnswerStore> responseList) {
List<QuestionAnswerStore> savedResponses = (List<QuestionAnswerStore>) super
.save(responseList);
cache(savedResponses);
return savedResponses;
}
/**
* Delete from cache and datastore
*
* @param response
*/
public void delete(QuestionAnswerStore response) {
uncache(Arrays.asList(response));
super.delete(response);
}
/**
* Delete response list from cache and datastore
*
* @param responsesList
*/
public void delete(List<QuestionAnswerStore> responsesList) {
uncache(responsesList);
super.delete(responsesList);
}
/**
* Add a collection of QuestionAnswerStore objects to the cache
*
* @param responseList
*/
private void cache(List<QuestionAnswerStore> responseList) {
if (responseList == null || responseList.isEmpty()) {
return;
}
Map<Object, Object> cacheMap = new HashMap<Object, Object>();
for (QuestionAnswerStore response : responseList) {
if (response == null) {
continue;
}
String cacheKey = null;
try {
cacheKey = getCacheKey(response);
cacheMap.put(cacheKey, response);
} catch (CacheException e) {
log.log(Level.WARNING, e.getMessage());
}
}
putObjects(cache, cacheMap);
}
/**
* Remove a collection of responses from the cache
*
* @param responsesList
*/
private void uncache(List<QuestionAnswerStore> responsesList) {
if (responsesList == null || responsesList.isEmpty()) {
return;
}
for (QuestionAnswerStore response : responsesList) {
if (response == null) {
continue;
}
String cacheKey = null;
try {
cacheKey = getCacheKey(response);
if (containsKey(cache, cacheKey)) {
cache.remove(cacheKey);
}
} catch (CacheException e) {
log.log(Level.WARNING, e.getMessage());
}
}
}
/**
* Construct cache key for QuestionAnswerStore objects. Assumes the combination of
* surveyInstanceId and questionId are unique across all QuestionAnswerStore entities.
*
* @param response
* @return
* @throws CacheException
*/
@Override
public String getCacheKey(BaseDomain object) throws CacheException {
QuestionAnswerStore response = (QuestionAnswerStore) object;
if (response.getSurveyInstanceId() == null || response.getQuestionID() == null) {
throw new CacheException(
"Cannnot create cache key without surveyInstanceId and questionId");
}
return response.getClass().getSimpleName() + "-" + response.getSurveyInstanceId() + "-"
+ response.getQuestionID();
}
}