/* * Copyright (C) 2010-2012 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 java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.jdo.PersistenceManager; import org.waterforpeople.mapping.domain.AccessPoint; import org.waterforpeople.mapping.domain.AccessPoint.AccessPointType; import org.waterforpeople.mapping.domain.AccessPointScoreDetail; import org.waterforpeople.mapping.helper.AccessPointHelper; import com.beoui.geocell.GeocellManager; import com.beoui.geocell.model.GeocellQuery; import com.beoui.geocell.model.Point; import com.gallatinsystems.common.util.PropertyUtil; import com.gallatinsystems.framework.dao.BaseDAO; import com.gallatinsystems.framework.servlet.PersistenceFilter; import com.google.appengine.api.datastore.Cursor; import com.google.appengine.api.datastore.DatastoreService; import com.google.appengine.api.datastore.DatastoreServiceFactory; import com.google.appengine.api.datastore.Entity; import com.google.appengine.api.datastore.FetchOptions; import com.google.appengine.api.datastore.Key; import com.google.appengine.api.datastore.PreparedQuery; import com.google.appengine.api.datastore.Query; import com.google.appengine.api.datastore.Query.FilterOperator; /** * dao for manipulating access points * * @author Christopher Fagiani */ public class AccessPointDao extends BaseDAO<AccessPoint> { private static final String SCORE_AP_FLAG = "scoreAPFlag"; private static final int MAX_RESULTS = 40; public AccessPointDao() { super(AccessPoint.class); } public Iterable<Entity> listRawEntity(Boolean returnKeysOnly) { DatastoreService datastore = DatastoreServiceFactory .getDatastoreService(); // The Query interface assembles a query Query q = new Query("AccessPoint"); if (returnKeysOnly) { q.setKeysOnly(); } PreparedQuery pq = datastore.prepare(q); return pq.asIterable(); } public Iterable<Entity> listRawEntity(Boolean returnKeysOnly, String countryCode, String communityCode, String accessPointCode, String cursorString) { DatastoreService datastore = DatastoreServiceFactory .getDatastoreService(); // The Query interface assembles a query Query q = new Query("AccessPoint"); int pageSize = 50; if (returnKeysOnly) { q.setKeysOnly(); } if (countryCode != null) q.addFilter("countryCode", FilterOperator.EQUAL, countryCode); if (communityCode != null) q.addFilter("communtiyCode", FilterOperator.EQUAL, communityCode); if (accessPointCode != null) q.addFilter("accessPointCode", FilterOperator.EQUAL, accessPointCode); PreparedQuery pq = datastore.prepare(q); FetchOptions fetchOptions = FetchOptions.Builder.withLimit(pageSize); String startCursor = cursorString; if (startCursor != null) { fetchOptions.startCursor(Cursor.fromWebSafeString(startCursor)); } return pq.asIterable(fetchOptions); } public AccessPoint findByKey(Key key) { return super.getByKey(key); } /** * Lists all access points that are near the point identified by the lat/lon parameters in order * of increasing distance. if maxDistance is 0, all points (up to MAX_RESULTS) are returned * otherwise, only those points maxDistance meters away or less are returned */ public List<AccessPoint> listNearbyAccessPoints(Double lat, Double lon, String countryCode, double maxDistance, String cursor) { PersistenceManager pm = PersistenceFilter.getManager(); if (lat != null && lon != null) { Point loc = new Point(lat, lon); List<Object> params = new ArrayList<Object>(); params.add(countryCode); GeocellQuery gq = new GeocellQuery( "countryCode == countryCodeParam", "String countryCodeParam", params); return GeocellManager.proximityFetch(loc, MAX_RESULTS, maxDistance, AccessPoint.class, gq, pm); } else { return listAccessPointByLocation(countryCode, null, null, null, cursor); } } /** * lists all the access points for the country/community/type passed in * * @param country * @param community * @param type * @return */ public List<AccessPoint> listAccessPointByLocation(String country, String community, String type, Date updatedSinceDate, String cursorString) { return listAccessPointByLocation(country, community, type, updatedSinceDate, cursorString, DEFAULT_RESULT_COUNT); } /** * lists all the access points for the country/community/type passed in * * @param country * @param community * @param type * @return */ @SuppressWarnings("unchecked") public List<AccessPoint> listAccessPointByLocation(String country, String community, String type, Date updatedSinceDate, String cursorString, Integer pageSize) { PersistenceManager pm = PersistenceFilter.getManager(); javax.jdo.Query query = pm.newQuery(AccessPoint.class); Map<String, Object> paramMap = null; StringBuilder filterString = new StringBuilder(); StringBuilder paramString = new StringBuilder(); paramMap = new HashMap<String, Object>(); appendNonNullParam("countryCode", filterString, paramString, "String", country, paramMap); appendNonNullParam("communityCode", filterString, paramString, "String", community, paramMap); appendNonNullParam("pointType", filterString, paramString, "String", type, paramMap); appendNonNullParam("lastUpdateDateTime", filterString, paramString, "Date", updatedSinceDate, paramMap, GTE_OP); if (updatedSinceDate != null) { query.declareImports("import java.util.Date"); } query.setOrdering("lastUpdateDateTime desc"); query.setFilter(filterString.toString()); query.declareParameters(paramString.toString()); prepareCursor(cursorString, pageSize, query); List<AccessPoint> results = (List<AccessPoint>) query .executeWithMap(paramMap); return results; } /** * searches for access points that match all of the non-null params * * @param country * @param community * @param constDateFrom * @param constDateTo * @param type * @param tech * @return */ @SuppressWarnings("unchecked") public List<AccessPoint> searchAccessPoints(String country, String community, Date collDateFrom, Date collDateTo, String type, String tech, Date constructionDateFrom, Date constructionDateTo, String orderByField, String orderByDir, Integer pageSize, String cursorString) { Map<String, Object> paramMap = new HashMap<String, Object>(); javax.jdo.Query query = constructQuery(country, community, collDateFrom, collDateTo, type, tech, constructionDateFrom, constructionDateTo, null, orderByField, orderByDir, paramMap); prepareCursor(cursorString, pageSize, query); List<AccessPoint> results = (List<AccessPoint>) query .executeWithMap(paramMap); return results; } /** * searches for access points that match all of the non-null params * * @param country * @param community * @param constDateFrom * @param constDateTo * @param type * @param tech * @return */ @SuppressWarnings("unchecked") public List<AccessPoint> searchAccessPoints(String country, String community, Date collDateFrom, Date collDateTo, String type, String tech, Date constructionDateFrom, Date constructionDateTo, String org, String orderByField, String orderByDir, Integer pageSize, String cursorString) { Map<String, Object> paramMap = new HashMap<String, Object>(); javax.jdo.Query query = constructQuery(country, community, collDateFrom, collDateTo, type, tech, constructionDateFrom, constructionDateTo, org, orderByField, orderByDir, paramMap); prepareCursor(cursorString, pageSize, query); List<AccessPoint> results = (List<AccessPoint>) query .executeWithMap(paramMap); return results; } public void deleteByQuery(String country, String community, Date collDateFrom, Date collDateTo, String type, String tech, Date constructionDateFrom, Date constructionDateTo) { Map<String, Object> paramMap = new HashMap<String, Object>(); javax.jdo.Query query = constructQuery(country, community, collDateFrom, collDateTo, type, tech, constructionDateFrom, constructionDateTo, null, null, null, paramMap); query.deletePersistentAll(paramMap); } public List<AccessPoint> listBySubLevel(String countryCode, Integer level, String subValue, String cursor, AccessPoint.AccessPointType type, Integer desiredResults) { PersistenceManager pm = PersistenceFilter.getManager(); javax.jdo.Query query = pm.newQuery(AccessPoint.class); StringBuilder filterString = new StringBuilder(); StringBuilder paramString = new StringBuilder(); Map<String, Object> paramMap = null; paramMap = new HashMap<String, Object>(); appendNonNullParam("pointType", filterString, paramString, "String", type, paramMap); appendNonNullParam("countryCode", filterString, paramString, "String", countryCode, paramMap); appendNonNullParam("sub" + level, filterString, paramString, "String", subValue, paramMap); query.setFilter(filterString.toString()); query.declareParameters(paramString.toString()); prepareCursor(cursor, desiredResults, query); @SuppressWarnings("unchecked") List<AccessPoint> results = (List<AccessPoint>) query .executeWithMap(paramMap); return results; } private javax.jdo.Query constructQuery(String country, String community, Date collDateFrom, Date collDateTo, String type, String tech, Date constructionDateFrom, Date constructionDateTo, String org, String orderByField, String orderByDir, Map<String, Object> paramMap) { PersistenceManager pm = PersistenceFilter.getManager(); javax.jdo.Query query = pm.newQuery(AccessPoint.class); StringBuilder filterString = new StringBuilder(); StringBuilder paramString = new StringBuilder(); appendNonNullParam("countryCode", filterString, paramString, "String", country, paramMap); appendNonNullParam("communityCode", filterString, paramString, "String", community, paramMap); appendNonNullParam("pointType", filterString, paramString, "String", type, paramMap); appendNonNullParam("typeTechnologyString", filterString, paramString, "String", tech, paramMap); if (org != null) { // TODO: hack need to refactor to org and orgRole instead of // hardcoded to WFP if (org.trim().equalsIgnoreCase("wfp")) { appendNonNullParam("waterForPeopleProjectFlag", filterString, paramString, "Boolean", true, paramMap); } else { appendNonNullParam("waterForPeopleProjectFlag", filterString, paramString, "Boolean", false, paramMap); } } appendNonNullParam("collectionDate", filterString, paramString, "Date", collDateFrom, paramMap, GTE_OP); appendNonNullParam("collectionDate", filterString, paramString, "Date", collDateTo, paramMap, LTE_OP); appendNonNullParam("constructionDate", filterString, paramString, "Date", constructionDateFrom, paramMap, GTE_OP); appendNonNullParam("constructionDate", filterString, paramString, "Date", constructionDateTo, paramMap, LTE_OP); if (orderByField != null) { String ordering = orderByDir; if (ordering == null) { ordering = "asc"; } query.setOrdering(orderByField + " " + ordering); } query.setFilter(filterString.toString()); query.declareParameters(paramString.toString()); if (collDateFrom != null || collDateTo != null || constructionDateFrom != null || constructionDateTo != null) { query.declareImports("import java.util.Date"); } return query; } @SuppressWarnings("unchecked") public AccessPoint findAccessPoint(AccessPoint.AccessPointType type, Double lat, Double lon, Date collectionDate) { PersistenceManager pm = PersistenceFilter.getManager(); javax.jdo.Query query = pm.newQuery(AccessPoint.class); StringBuilder filterString = new StringBuilder(); StringBuilder paramString = new StringBuilder(); Map<String, Object> paramMap = null; paramMap = new HashMap<String, Object>(); appendNonNullParam("pointType", filterString, paramString, "String", type, paramMap); appendNonNullParam("latitude", filterString, paramString, "Double", lat, paramMap); appendNonNullParam("longitude", filterString, paramString, "Double", lon, paramMap); appendNonNullParam("collectionDate", filterString, paramString, "Date", collectionDate, paramMap, EQ_OP); query.declareImports("import java.util.Date"); query.setFilter(filterString.toString()); query.declareParameters(paramString.toString()); List<AccessPoint> results = (List<AccessPoint>) query .executeWithMap(paramMap); if (results != null && results.size() >= 1) return results.get(0); else return null; } /** * lists all access points by the technology type string * * @param countryCode * @param technologyType * @param cursorString * @return */ @SuppressWarnings("unchecked") public List<AccessPoint> listAccessPointsByTechnology(String countryCode, String technologyType, String cursorString) { PersistenceManager pm = PersistenceFilter.getManager(); javax.jdo.Query q = pm.newQuery(AccessPoint.class); q.setFilter("countryCode == countryCodeParam && typeTechnologyString == typeTechnologyParam"); q.declareParameters("String countryCodeParam, String typeTechnologyParam"); prepareCursor(cursorString, q); List<AccessPoint> result = (List<AccessPoint>) q.execute(countryCode, technologyType); return result; } /** * lists all access points in order of decreasing date (either collection or construction date * depending on the dateColumn passed in) * * @param dateColumn * @param orderDirection * @param cursorString * @return */ @SuppressWarnings("unchecked") public List<AccessPoint> listAccessPointsByDateOrdered(String dateColumn, String orderDirection, String cursorString) { PersistenceManager pm = PersistenceFilter.getManager(); javax.jdo.Query q = pm.newQuery(AccessPoint.class); q.setOrdering(dateColumn + " " + orderDirection); prepareCursor(cursorString, q); List<AccessPoint> result = (List<AccessPoint>) q.execute(); return result; } @SuppressWarnings("unchecked") public List<AccessPoint> listAccessPointBySubLevel(Integer subLevel, String subName, String cursorString) { PersistenceManager pm = PersistenceFilter.getManager(); Map<String, Object> paramMap = null; StringBuilder filterString = new StringBuilder(); StringBuilder paramString = new StringBuilder(); paramMap = new HashMap<String, Object>(); javax.jdo.Query q = pm.newQuery(AccessPoint.class); appendNonNullParam("sub" + subLevel, filterString, paramString, "String", subName, paramMap); q.setOrdering("createdDateTime desc"); q.setFilter(filterString.toString()); q.declareParameters(paramString.toString()); List<AccessPoint> result = (List<AccessPoint>) q .executeWithMap(paramMap); return result; } /** * lists all access points that contain invalid data * * @param cursorString * @return */ @SuppressWarnings("unchecked") public List<AccessPoint> listAccessPointsWithErrors(String cursorString) { PersistenceManager pm = PersistenceFilter.getManager(); javax.jdo.Query q = pm.newQuery(AccessPoint.class); q.setOrdering("createdDateTime desc"); // q.setFilter("latitude == 0.0 || longitude == 0.0 || pointStatus == null"); q.setFilter("latitude == 0.0"); prepareCursor(cursorString, q); List<AccessPoint> result = (List<AccessPoint>) q.execute(); return result; } @SuppressWarnings("unchecked") public AccessPoint findAccessPoint(String communityCode, AccessPointType pointType) { PersistenceManager pm = PersistenceFilter.getManager(); javax.jdo.Query query = pm.newQuery(AccessPoint.class); Map<String, Object> paramMap = null; StringBuilder filterString = new StringBuilder(); StringBuilder paramString = new StringBuilder(); paramMap = new HashMap<String, Object>(); appendNonNullParam("communityCode", filterString, paramString, "String", communityCode, paramMap); appendNonNullParam("pointType", filterString, paramString, "String", pointType.toString(), paramMap); query.setOrdering("collectionDate desc"); query.setFilter(filterString.toString()); query.declareParameters(paramString.toString()); List<AccessPoint> results = (List<AccessPoint>) query .executeWithMap(paramMap); if (results != null && results.size() >= 1) return results.get(0); else return null; } @SuppressWarnings("unchecked") public List<AccessPoint> listAccessPointsByBoundingBox( AccessPointType pointType, Double lat1, Double lat2, Double long1, Double long2, String cursorString, Integer maxResults) { PersistenceManager pm = PersistenceFilter.getManager(); javax.jdo.Query query = pm.newQuery(AccessPoint.class); Map<String, Object> paramMap = null; StringBuilder filterString = new StringBuilder(); StringBuilder paramString = new StringBuilder(); paramMap = new HashMap<String, Object>(); appendNonNullParam("pointType", filterString, paramString, "String", pointType.toString(), paramMap); appendNonNullParam("latitude", filterString, paramString, "Double", lat1, paramMap, LTE_OP); appendNonNullParam("latitude", filterString, paramString, "Double", lat2, paramMap, GTE_OP); query.setFilter(filterString.toString()); query.declareParameters(paramString.toString()); prepareCursor(cursorString, maxResults, query); List<AccessPoint> results = (List<AccessPoint>) query .executeWithMap(paramMap); // List<AccessPoint> resultsInBox = new ArrayList<AccessPoint>(); // if (!results.isEmpty() && results != null) { // for (AccessPoint ap : results) { // if (ap.getLongitude() < long1 && ap.getLongitude() > long2) { // resultsInBox.add(ap); // } // } // } return results; } /** * finds a single access point by its sms code. If there is more than one, it will return the * one with the latest collectionDate * * @param code * @return */ public AccessPoint findAccessPointBySMSCode(String code) { List<AccessPoint> apList = listByProperty("smsCode", code, "String"); AccessPoint latest = null; if (apList != null) { for (AccessPoint point : apList) { if (latest == null) { latest = point; } else { if (latest.getCollectionDate() != null && point.getCollectionDate() != null) { if (latest.getCollectionDate().before( point.getCollectionDate())) { latest = point; } } else { latest = point; } } } } return latest; } public AccessPoint save(AccessPoint point) { if (Boolean.parseBoolean(PropertyUtil.getProperty(SCORE_AP_FLAG))) point = AccessPointHelper.scoreAccessPoint(point); point = super.save(point); if (point.getApScoreDetailList() != null) { for (AccessPointScoreDetail item : point.getApScoreDetailList()) { if (item.getKey() == null) { item.setAccessPointId(point.getKey().getId()); AccessPointScoreDetailDao apsddao = new AccessPointScoreDetailDao(); apsddao.save(item); } } } return point; } }