/* * 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.helper; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map.Entry; import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; import org.waterforpeople.mapping.analytics.domain.AccessPointStatusSummary; import org.waterforpeople.mapping.dao.AccessPointDao; import org.waterforpeople.mapping.dao.AccessPointScoreDetailDao; import org.waterforpeople.mapping.dao.SurveyAttributeMappingDao; import org.waterforpeople.mapping.dao.SurveyInstanceDAO; import org.waterforpeople.mapping.domain.AccessPoint; import org.waterforpeople.mapping.domain.AccessPoint.AccessPointType; import org.waterforpeople.mapping.domain.AccessPointMappingHistory; import org.waterforpeople.mapping.domain.AccessPointScoreComputationItem; import org.waterforpeople.mapping.domain.AccessPointScoreDetail; import org.waterforpeople.mapping.domain.GeoCoordinates; import org.waterforpeople.mapping.domain.QuestionAnswerStore; import org.waterforpeople.mapping.domain.SurveyAttributeMapping; import com.beoui.geocell.GeocellManager; import com.beoui.geocell.model.Point; import com.gallatinsystems.common.util.PropertyUtil; import com.gallatinsystems.common.util.StringUtil; import com.gallatinsystems.framework.analytics.summarization.DataSummarizationRequest; import com.gallatinsystems.framework.dao.BaseDAO; import com.gallatinsystems.framework.domain.DataChangeRecord; import com.gallatinsystems.gis.coordinate.utilities.CoordinateUtilities; import com.gallatinsystems.gis.location.GeoLocationServiceGeonamesImpl; import com.gallatinsystems.gis.location.GeoPlace; import com.gallatinsystems.gis.map.domain.OGRFeature; import com.gallatinsystems.standards.dao.DistanceStandardDao; import com.gallatinsystems.standards.dao.StandardScoringDao; import com.gallatinsystems.standards.domain.DistanceStandard; import com.gallatinsystems.standards.domain.LevelOfServiceScore; import com.gallatinsystems.standards.domain.Standard.StandardType; import com.gallatinsystems.standards.domain.StandardScoring; import com.gallatinsystems.survey.dao.QuestionDao; import com.gallatinsystems.survey.domain.Question; import com.google.appengine.api.taskqueue.Queue; import com.google.appengine.api.taskqueue.QueueFactory; import com.google.appengine.api.taskqueue.TaskOptions; public class AccessPointHelper { private static String photo_url_root; private static final String GEO_TYPE = "GEO"; private static final String PHOTO_TYPE = "IMAGE"; private SurveyAttributeMappingDao mappingDao; private static final String SCORE_AP_DYNAMIC_FLAG = "scoreAPDynamicFlag"; static { Properties props = System.getProperties(); photo_url_root = props.getProperty("photo_url_root"); } private static Logger logger = Logger.getLogger(AccessPointHelper.class .getName()); public AccessPointHelper() { mappingDao = new SurveyAttributeMappingDao(); } public AccessPoint getAccessPoint(Long id) { BaseDAO<AccessPoint> apDAO = new BaseDAO<AccessPoint>(AccessPoint.class); return apDAO.getByKey(id); } public AccessPoint getAccessPoint(Long id, Boolean needScoreDetail) { BaseDAO<AccessPoint> apDAO = new BaseDAO<AccessPoint>(AccessPoint.class); AccessPointScoreDetailDao apddao = new AccessPointScoreDetailDao(); AccessPoint ap = apDAO.getByKey(id); List<AccessPointScoreDetail> apScoreSummaryList = apddao .listByAccessPointId(id); if (apScoreSummaryList != null && !apScoreSummaryList.isEmpty()) ap.setApScoreDetailList(apScoreSummaryList); return ap; } public void processSurveyInstance(String surveyInstanceId) { // Get the survey and QuestionAnswerStore // Get the surveyDefinition SurveyInstanceDAO sid = new SurveyInstanceDAO(); List<QuestionAnswerStore> questionAnswerList = sid .listQuestionAnswerStore(Long.parseLong(surveyInstanceId), null); Collection<AccessPoint> apList = null; if (questionAnswerList != null && questionAnswerList.size() > 0) { try { apList = parseAccessPoint(new Long(questionAnswerList.get(0) .getSurveyId()), questionAnswerList, AccessPoint.AccessPointType.WATER_POINT); } catch (Exception ex) { logger.log(Level.SEVERE, "problem parsing access point.", ex); } if (apList != null) { for (AccessPoint ap : apList) { try { saveAccessPoint(ap); } catch (Exception ex) { logger.log( Level.SEVERE, "Inside processSurveyInstance could not save AP for SurveyInstanceId: " + surveyInstanceId + ":" + ap.toString() + " ex: " + ex + " exMessage: " + ex.getMessage()); } } } } } private Collection<AccessPoint> parseAccessPoint(Long surveyId, List<QuestionAnswerStore> questionAnswerList, AccessPoint.AccessPointType accessPointType) { Collection<AccessPoint> apList = null; List<SurveyAttributeMapping> mappings = mappingDao .listMappingsBySurvey(surveyId); if (mappings != null) { apList = parseAccessPoint(surveyId, questionAnswerList, mappings); } else { logger.log(Level.SEVERE, "NO mappings for survey " + surveyId); } return apList; } /** * uses the saved mappings for the survey definition to parse values in the questionAnswerStore * into attributes of an AccessPoint object TODO: figure out way around known limitation of only * having 1 GEO response per survey * * @param questionAnswerList * @param mappings * @return */ private Collection<AccessPoint> parseAccessPoint(Long surveyId, List<QuestionAnswerStore> questionAnswerList, List<SurveyAttributeMapping> mappings) { HashMap<String, AccessPoint> apMap = new HashMap<String, AccessPoint>(); List<AccessPointMappingHistory> apmhList = new ArrayList<AccessPointMappingHistory>(); List<Question> questionList = new QuestionDao() .listQuestionsBySurvey(surveyId); if (questionAnswerList != null) { for (QuestionAnswerStore qas : questionAnswerList) { SurveyAttributeMapping mapping = getMappingForQuestion( mappings, qas.getQuestionID()); if (mapping != null) { List<String> types = mapping.getApTypes(); if (types == null || types.size() == 0) { // default the list to be access point if nothing is // specified (for backward compatibility) types.add(AccessPointType.WATER_POINT.toString()); } else { if (types.contains(AccessPointType.PUBLIC_INSTITUTION .toString()) && (types.contains(AccessPointType.HEALTH_POSTS .toString()) || types .contains(AccessPointType.SCHOOL .toString()))) { types.remove(AccessPointType.PUBLIC_INSTITUTION .toString()); } } for (String type : types) { AccessPointMappingHistory apmh = new AccessPointMappingHistory(); apmh.setSource(this.getClass().getName()); apmh.setSurveyId(surveyId); apmh.setSurveyInstanceId(qas.getSurveyInstanceId()); apmh.setQuestionId(Long.parseLong(qas.getQuestionID())); apmh.addAccessPointType(type); try { AccessPoint ap = apMap.get(type); if (ap == null) { ap = new AccessPoint(); ap.setPointType(AccessPointType.valueOf(type)); // if(AccessPointType.PUBLIC_INSTITUTION.toString().equals(type)){ // //get the pointType value from the survey to // properly set it // // } apMap.put(type, ap); } ap.setCollectionDate(qas.getCollectionDate()); setAccessPointField(ap, qas, mapping, apmh); } catch (NoSuchFieldException e) { logger.log( Level.SEVERE, "Could not map field to access point: " + mapping.getAttributeName() + ". Check the surveyAttribueMapping for surveyId " + surveyId); } catch (IllegalAccessException e) { logger.log(Level.SEVERE, "Could not set field to access point: " + mapping.getAttributeName() + ". Illegal access."); } for (Question q : questionList) { if (q.getKey().getId() == Long.parseLong(qas .getQuestionID())) { apmh.setQuestionText(q.getText()); break; } } apmhList.add(apmh); } } // if (apmhList.size() > 0) { // BaseDAO<AccessPointMappingHistory> apmhDao = new // BaseDAO<AccessPointMappingHistory>( // AccessPointMappingHistory.class); // apmhDao.save(apmhList); // } } } return apMap.values(); } /** * uses reflection to set the field on access point based on the value in questionAnswerStore * and the field name in the mapping * * @param ap * @param qas * @param mapping * @throws SecurityException * @throws NoSuchFieldException * @throws IllegalArgumentException * @throws IllegalAccessException */ public static void setAccessPointField(AccessPoint ap, QuestionAnswerStore qas, SurveyAttributeMapping mapping, AccessPointMappingHistory apmh) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException { apmh.setResponseAnswerType(qas.getType()); QuestionDao qDao = new QuestionDao(); ap.setSurveyId(qas.getSurveyId()); ap.setSurveyInstanceId(qas.getSurveyInstanceId()); Question q = qDao.getByKey(Long.parseLong(qas.getQuestionID())); if (!qas.getType().equals(q.getType().toString())) { qas.setType(q.getType().toString()); logger.log(Level.INFO, "Remapping question type value because QAS version is incorrect"); } // FREE_TEXT, OPTION, NUMBER, GEO, PHOTO, VIDEO, SCAN, TRACK, NAME, // STRENGTH if (GEO_TYPE.equals(q.getType().toString())) { GeoCoordinates geoC = GeoCoordinates.extractGeoCoordinate(qas .getValue()); if (geoC != null) { ap.setLatitude(geoC.getLatitude()); ap.setLongitude(geoC.getLongitude()); ap.setAltitude(geoC.getAltitude()); if (ap.getCommunityCode() == null && geoC.getCode() != null) { ap.setCommunityCode(geoC.getCode()); } apmh.setSurveyResponse(geoC.getLatitude() + "|" + geoC.getLongitude() + "|" + geoC.getAltitude()); apmh.setQuestionAnswerType("GEO"); apmh.setAccessPointValue(ap.getLatitude() + "|" + ap.getLongitude() + "|" + ap.getAltitude()); apmh.setAccessPointField("Latitude,Longitude,Altitude"); } } else { apmh.setSurveyResponse(qas.getValue()); // if it's a value or OTHER type Field f = ap.getClass() .getDeclaredField(mapping.getAttributeName()); if (!f.isAccessible()) { f.setAccessible(true); } apmh.setAccessPointField(f.getName()); // TODO: Hack. In the QAS the type is PHOTO, but we were looking for // image this is why we were getting /sdcard I think. if (PHOTO_TYPE.equals(q.getType().toString()) || qas.getType().equals("PHOTO")) { String newURL = null; String[] photoParts = qas.getValue().split("/"); if (photoParts.length > 1) { newURL = photo_url_root + photoParts[photoParts.length - 1]; } else if (photoParts.length == 1) { // handle the case where we only have the filename (no // paths) newURL = photo_url_root + photoParts[0]; } f.set(ap, newURL); apmh.setQuestionAnswerType("PHOTO"); apmh.setAccessPointValue(ap.getPhotoURL()); } else if (mapping.getAttributeName().equals("pointType")) { if (qas.getValue().contains("Health")) { f.set(ap, AccessPointType.HEALTH_POSTS); } else { qas.setValue(qas.getValue().replace(" ", "_")); f.set(ap, AccessPointType.valueOf(qas.getValue() .toUpperCase())); } } else { String stringVal = qas.getValue(); if (stringVal != null && stringVal.trim().length() > 0) { if (f.getType() == String.class) { f.set(ap, qas.getValue()); apmh.setQuestionAnswerType("String"); apmh.setAccessPointValue(f.get(ap).toString()); } else if (f.getType() == AccessPoint.Status.class) { String val = qas.getValue(); f.set(ap, encodeStatus(val, ap.getPointType())); apmh.setQuestionAnswerType("STATUS"); apmh.setAccessPointValue(f.get(ap).toString()); } else if (f.getType() == Double.class) { try { Double val = Double.parseDouble(stringVal.trim()); f.set(ap, val); apmh.setQuestionAnswerType("DOUBLE"); apmh.setAccessPointValue(f.get(ap).toString()); } catch (Exception e) { logger.log(Level.SEVERE, "Could not parse " + stringVal + " as double", e); apmh.setMappingMessage("Could not parse " + stringVal + " as double"); } } else if (f.getType() == Long.class) { try { String temp = stringVal.trim(); if (temp.contains(".")) { temp = temp.substring(0, temp.indexOf(".")); } Long val = Long.parseLong(temp); f.set(ap, val); logger.info("Setting " + f.getName() + " to " + val + " for ap: " + (ap.getKey() != null ? ap.getKey() .getId() : "UNSET")); apmh.setQuestionAnswerType("LONG"); apmh.setAccessPointValue(f.get(ap).toString()); } catch (Exception e) { logger.log(Level.SEVERE, "Could not parse " + stringVal + " as long", e); apmh.setMappingMessage("Could not parse " + stringVal + " as long"); } } else if (f.getType() == Boolean.class) { try { Boolean val = null; if (stringVal.toLowerCase().contains("yes")) { val = true; } else if (stringVal.toLowerCase().contains("no")) { val = false; } else { if (stringVal == null || stringVal.equals("")) { val = null; } val = Boolean.parseBoolean(stringVal.trim()); } f.set(ap, val); apmh.setQuestionAnswerType("BOOLEAN"); apmh.setAccessPointValue(f.get(ap).toString()); } catch (Exception e) { logger.log(Level.SEVERE, "Could not parse " + stringVal + " as boolean", e); apmh.setMappingMessage("Could not parse " + stringVal + " as boolean"); } } } } } } /** * reads value of field from AccessPoint via reflection * * @param ap * @param field * @return */ public static String getAccessPointFieldAsString(AccessPoint ap, String field) { try { Field f = ap.getClass().getDeclaredField(field); if (!f.isAccessible()) { f.setAccessible(true); } Object val = f.get(ap); if (val != null) { return val.toString(); } } catch (Exception e) { logger.log(Level.SEVERE, "Could not extract field value: " + field, e); } return null; } private SurveyAttributeMapping getMappingForQuestion( List<SurveyAttributeMapping> mappings, String questionId) { if (mappings != null) { for (SurveyAttributeMapping mapping : mappings) { if (mapping.getSurveyQuestionId().equals(questionId)) { return mapping; } } } return null; } /** * generates a unique code based on the lat/lon passed in. Current algorithm returns the * concatenation of the integer portion of 1000 times absolute value of lat and lon in base 36 * * @param lat * @param lon * @return */ private String generateCode(double lat, double lon) { Long code = Long.parseLong((int) ((Math.abs(lat) * 10000d)) + "" + (int) ((Math.abs(lon) * 10000d))); return Long.toString(code, 36); } /** * saves an access point and fires off a summarization message * * @param ap * @return */ public AccessPoint saveAccessPoint(AccessPoint ap) { AccessPointDao apDao = new AccessPointDao(); AccessPoint apCurrent = null; if (ap != null) { if (ap.getPointType() != null && ap.getLatitude() != null && ap.getLongitude() != null) { apCurrent = apDao.findAccessPoint(ap.getPointType(), ap.getLatitude(), ap.getLongitude(), ap.getCollectionDate()); if (apCurrent != null) { // if (!apCurrent.getKey().equals(ap.getKey())) { ap.setKey(apCurrent.getKey()); // } } if (ap.getAccessPointCode() == null) { ap.setAccessPointCode(generateCode(ap.getLatitude(), ap.getLongitude())); logger.log( Level.INFO, "No APCode set in ap so setting to: " + ap.getAccessPointCode()); } if (ap.getCommunityCode() == null) { if (ap.getAccessPointCode() != null) ap.setCommunityCode(ap.getAccessPointCode()); logger.log( Level.INFO, "No Community Code set in ap so setting to: " + ap.getAccessPointCode()); } if (ap.getKey() != null) { String oldValues = null; if (ap != null && ap.getKey() != null && apCurrent == null) { apCurrent = apDao.getByKey(ap.getKey()); } if (apCurrent != null) { oldValues = formChangeRecordString(apCurrent); if (apCurrent != null) { ap.setKey(apCurrent.getKey()); apCurrent = ap; logger.log(Level.INFO, "Found existing point and updating it." + apCurrent.getKey().getId()); } // TODO: Hack since the fileUrl keeps getting set to // incorrect value // Changing from apCurrent to ap ap = apDao.save(ap); String newValues = formChangeRecordString(ap); if (oldValues != null) { DataChangeRecord change = new DataChangeRecord( AccessPointStatusSummary.class.getName(), "n/a", oldValues, newValues); Queue queue = QueueFactory.getQueue("dataUpdate"); queue.add(TaskOptions.Builder .withUrl("/app_worker/dataupdate") .param(DataSummarizationRequest.OBJECT_KEY, ap.getKey().getId() + "") .param(DataSummarizationRequest.OBJECT_TYPE, "AccessPointSummaryChange") .param(DataSummarizationRequest.VALUE_KEY, change.packString())); } } } else { logger.log(Level.INFO, "Did not find existing point" + ap.toString()); if (ap.getGeocells() == null || ap.getGeocells().size() == 0) { if (ap.getLatitude() != null && ap.getLongitude() != null && ap.getLongitude() < 180 && ap.getLatitude() < 180) { try { ap.setGeocells(GeocellManager .generateGeoCell(new Point(ap .getLatitude(), ap .getLongitude()))); } catch (Exception ex) { logger.log(Level.INFO, "Could not generate GeoCell for AP: " + ap.getKey().getId() + " error: " + ex); } } } try { ap = apDao.save(ap); } catch (Exception ex) { logger.log(Level.INFO, "Could not save point" + ex); } if (ap.getKey() != null) { Queue summQueue = QueueFactory .getQueue("dataSummarization"); summQueue.add(TaskOptions.Builder .withUrl("/app_worker/datasummarization") .param("objectKey", ap.getKey().getId() + "") .param("type", "AccessPoint")); } else { logger.log( Level.SEVERE, "After saving could not get key" + ap.toString()); } } } } if (ap != null) { if (Boolean.parseBoolean(PropertyUtil .getProperty(SCORE_AP_DYNAMIC_FLAG))) { AccessPointHelper aph = new AccessPointHelper(); aph.scoreAccessPointNew(ap); } return ap; } else return null; } private String formChangeRecordString(AccessPoint ap) { String changeString = null; if (ap != null) { changeString = (ap.getCountryCode() != null ? ap.getCountryCode() : "") + "|" + (ap.getCommunityCode() != null ? ap.getCommunityCode() : "") + "|" + (ap.getPointType() != null ? ap.getPointType().toString() : "") + "|" + (ap.getPointStatus() != null ? ap.getPointStatus() .toString() : "") + "|" + StringUtil.getYearString(ap.getCollectionDate()); } return changeString; } public List<AccessPoint> listAccessPoint(String cursorString) { AccessPointDao apDao = new AccessPointDao(); return apDao.list(cursorString); } public static AccessPoint.Status encodeStatus(String statusVal, AccessPoint.AccessPointType pointType) { AccessPoint.Status status = null; statusVal = statusVal.toLowerCase().trim(); if (pointType.equals(AccessPointType.WATER_POINT)) { if ("functioning but with problems".equals(statusVal) || "working but with problems".equals(statusVal)) { status = AccessPoint.Status.FUNCTIONING_WITH_PROBLEMS; } else if ("broken down system".equals(statusVal) || "broken down".equals(statusVal) || statusVal.contains("broken")) { status = AccessPoint.Status.BROKEN_DOWN; } else if ("no improved system".equals(statusVal) || "not a protected waterpoint".equals(statusVal)) { status = AccessPoint.Status.NO_IMPROVED_SYSTEM; } else if ("functioning and meets government standards" .equals(statusVal) || "working and protected".equals(statusVal)) { status = AccessPoint.Status.FUNCTIONING_HIGH; } else if ("high".equalsIgnoreCase(statusVal) || "functioning".equals(statusVal)) { status = AccessPoint.Status.FUNCTIONING_HIGH; } else if ("ok".equalsIgnoreCase(statusVal)) { status = AccessPoint.Status.FUNCTIONING_OK; } else { status = AccessPoint.Status.FUNCTIONING_WITH_PROBLEMS; } } else if (pointType.equals(AccessPointType.SANITATION_POINT)) { if ("latrine full".equals(statusVal)) status = AccessPoint.Status.LATRINE_FULL; else if ("Latrine used but technical problems evident" .toLowerCase().trim().equals(statusVal)) status = AccessPoint.Status.LATRINE_USED_TECH_PROBLEMS; else if ("Latrine not being used due to structural/technical problems" .toLowerCase().equals(statusVal)) status = AccessPoint.Status.LATRINE_NOT_USED_TECH_STRUCT_PROBLEMS; else if ("Do not Know".toLowerCase().equals(statusVal)) status = AccessPoint.Status.LATRINE_DO_NOT_KNOW; else if ("Functional".toLowerCase().equals(statusVal)) status = AccessPoint.Status.LATRINE_FUNCTIONAL; } else { if ("functioning but with problems".equals(statusVal)) { status = AccessPoint.Status.FUNCTIONING_WITH_PROBLEMS; } else if ("broken down system".equals(statusVal)) { status = AccessPoint.Status.BROKEN_DOWN; } else if ("no improved system".equals(statusVal)) status = AccessPoint.Status.NO_IMPROVED_SYSTEM; else if ("functioning and meets government standards" .equals(statusVal)) status = AccessPoint.Status.FUNCTIONING_HIGH; else if ("high".equalsIgnoreCase(statusVal)) { status = AccessPoint.Status.FUNCTIONING_HIGH; } else if ("ok".equalsIgnoreCase(statusVal)) { status = AccessPoint.Status.FUNCTIONING_OK; } else { status = AccessPoint.Status.FUNCTIONING_WITH_PROBLEMS; } } return status; } public AccessPoint setGeoDetails(AccessPoint point) { if (point.getLatitude() != null && point.getLongitude() != null) { GeoLocationServiceGeonamesImpl gs = new GeoLocationServiceGeonamesImpl(); GeoPlace geoPlace = gs.manualLookup(point.getLatitude().toString(), point.getLongitude().toString(), OGRFeature.FeatureType.SUB_COUNTRY_OTHER); if (geoPlace != null) { point.setCountryCode(geoPlace.getCountryCode()); point.setSub1(geoPlace.getSub1()); point.setSub2(geoPlace.getSub2()); point.setSub3(geoPlace.getSub3()); point.setSub4(geoPlace.getSub4()); point.setSub5(geoPlace.getSub5()); point.setSub6(geoPlace.getSub6()); } else if (geoPlace == null && point.getCountryCode() == null) { GeoPlace geoPlaceCountry = gs.manualLookup(point.getLatitude() .toString(), point.getLongitude().toString(), OGRFeature.FeatureType.COUNTRY); if (geoPlaceCountry != null) { point.setCountryCode(geoPlaceCountry.getCountryCode()); } } } return point; } public AccessPoint scoreAccessPointDynamic(AccessPoint ap) { AccessPointScoreDetail apss = new AccessPointScoreDetail(); HashMap<Long, Integer> scoreBucketMap = new HashMap<Long, Integer>(); logger.log(Level.INFO, "About to compute score for: " + ap.getCommunityCode()); StandardScoringDao ssDao = new StandardScoringDao(); List<StandardScoring> ssList = ssDao.listStandardScoring(ap); ArrayList<AccessPointScoreComputationItem> apsciList = new ArrayList<AccessPointScoreComputationItem>(); if (ssList != null && !ssList.isEmpty()) { Integer score = 0; for (StandardScoring item : ssList) { if (scoreBucketMap.containsKey(item.getScoreBucketId())) { score = scoreBucketMap.get(item.getScoreBucketId()); } else { scoreBucketMap.put(item.getScoreBucketId(), 0); } try { AccessPointScoreComputationItem apsi = executeItemScore(ap, score, item); score = apsi.getScoreItem(); apsciList.add(apsi); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } scoreBucketMap.put(item.getScoreBucketId(), score); } for (Entry<Long, Integer> item : scoreBucketMap.entrySet()) { String scoreBucketName = null; for (StandardScoring ssitem : ssList) { if (ssitem.getScoreBucketId().equals(item.getKey())) { scoreBucketName = ssitem.getScoreBucket(); } } apss.setScoreBucketId(item.getKey()); apss.setScoreBucket(scoreBucketName); apss.setScore(item.getValue()); apss.setScoreComputationItems(apsciList); ap.setScore(score); ap.setScoreComputationDate(new Date()); apss.setComputationDate(ap.getScoreComputationDate()); ap.setApScoreDetail(apss); } } return ap; } private AccessPointScoreComputationItem executeItemScore(AccessPoint ap, Integer score, StandardScoring item) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { String criteriaType = item.getCriteriaType(); String scoreItemMessage = null; if (item.getCriteriaType().equals("Distance")) { if (ap.getNumberOutsideAcceptableDistance() != null && ap.getNumberOutsideAcceptableDistance() == 0) { score = score + item.getPositiveScore(); scoreItemMessage = item.getPositiveMessage(); } else { scoreItemMessage = item.getNegativeMessage(); } } else { item.setEvaluateField(StringUtil .capitalizeFirstCharacterString(item.getEvaluateField())); if (criteriaType.equals("String")) { Method m = AccessPoint.class.getMethod( "get" + item.getEvaluateField(), (Class<?>[]) null); String value = (String) m.invoke(ap, (Object[]) null); if (item.getPositiveOperator().equals("==")) { if (item.getPositiveCriteria().equals(value)) { score = score + item.getPositiveScore(); scoreItemMessage = item.getPositiveMessage(); } } else if (item.getPositiveOperator().equals("!=")) { if (!item.getPositiveCriteria().equals(value)) { score = score + item.getPositiveScore(); scoreItemMessage = item.getPositiveMessage(); } } else if (item.getNegativeOperator().equals("==")) { if (item.getNegativeCriteria().equals(value)) { score = score + item.getNegativeScore(); scoreItemMessage = item.getNegativeMessage(); } } else if (item.getNegativeOperator().equals("!=")) { if (!item.getNegativeCriteria().equals(value)) { score = score + item.getNegativeScore(); scoreItemMessage = item.getNegativeMessage(); } } } else if (criteriaType.equals("Boolean")) { Method m = AccessPoint.class.getMethod( "get" + item.getEvaluateField(), (Class<?>[]) null); Boolean value = null; String type = m.getReturnType().toString(); if (type.equals("class java.lang.Boolean")) { value = Boolean.parseBoolean(m.invoke(ap, (Object[]) null).toString()); if (item.getPositiveOperator().equals("==")) { if (Boolean.parseBoolean(item.getPositiveCriteria()) == value) { score = score + item.getPositiveScore(); scoreItemMessage = item.getPositiveMessage(); } } else if (item.getPositiveOperator().equals("!=")) { if (Boolean.parseBoolean(item.getPositiveCriteria()) != value) { score = score + item.getPositiveScore(); scoreItemMessage = item.getPositiveMessage(); } } if (item.getNegativeOperator() != null && item.getNegativeOperator().equals("==")) { if (Boolean.parseBoolean(item.getNegativeCriteria()) == value) { score = score + item.getNegativeScore(); scoreItemMessage = item.getNegativeMessage(); } } else if (item.getNegativeOperator() != null && item.getNegativeOperator().equals("!=")) { if (Boolean.parseBoolean(item.getNegativeCriteria()) != value) { score = score + item.getNegativeScore(); scoreItemMessage = item.getNegativeMessage(); } } } } else if (criteriaType.equals("Integer") || criteriaType.equals("Number")) { Method m = AccessPoint.class.getMethod( "get" + item.getEvaluateField(), (Class<?>[]) null); Float value = null; if (m.getReturnType().toString().equals("class java.lang.Long")) value = Float.parseFloat(((Long) m.invoke(ap, (Object[]) null)) .toString()); else if (m.getReturnType().toString() .equals("class java.lang.Integer")) value = Float.parseFloat(((Integer) m.invoke(ap, (Object[]) null)) .toString()); else if (m.getReturnType().toString() .equals("class java.lang.Double")) value = Float.parseFloat(((Double) m.invoke(ap, (Object[]) null)) .toString()); if (item.getPositiveOperator().equals("<=")) { if (Integer.parseInt(item.getPositiveCriteria()) <= value) { score = score + item.getPositiveScore(); scoreItemMessage = item.getPositiveMessage(); } } else if (item.getPositiveOperator().equals("<")) { if (Integer.parseInt(item.getPositiveCriteria()) < value) { score = score + item.getPositiveScore(); scoreItemMessage = item.getPositiveMessage(); } } else if (item.getPositiveOperator().equals("==")) { if (Integer.parseInt(item.getPositiveCriteria()) == value) { score = score + item.getPositiveScore(); scoreItemMessage = item.getPositiveMessage(); } } else if (item.getPositiveOperator().equals("!=")) { if (Integer.parseInt(item.getPositiveCriteria()) != value) { score = score + item.getPositiveScore(); scoreItemMessage = item.getPositiveMessage(); } } else if (item.getPositiveOperator().equals(">=")) { if (Integer.parseInt(item.getPositiveCriteria()) >= value) { score = score + item.getPositiveScore(); scoreItemMessage = item.getPositiveMessage(); } } else if (item.getPositiveOperator().equals(">")) { if (Integer.parseInt(item.getPositiveCriteria()) > value) { score = score + item.getPositiveScore(); scoreItemMessage = item.getPositiveMessage(); } } else if (item.getNegativeOperator().equals("<=")) { if (Integer.parseInt(item.getNegativeCriteria()) <= value) { score = score + item.getNegativeScore(); scoreItemMessage = item.getNegativeMessage(); } } else if (item.getNegativeOperator().equals("<")) { if (Integer.parseInt(item.getNegativeCriteria()) < value) { score = score + item.getNegativeScore(); scoreItemMessage = item.getNegativeMessage(); } } else if (item.getNegativeOperator().equals("==")) { if (Integer.parseInt(item.getNegativeCriteria()) == value) { score = score + item.getNegativeScore(); scoreItemMessage = item.getNegativeMessage(); } } else if (item.getNegativeOperator().equals("!=")) { if (Integer.parseInt(item.getNegativeCriteria()) != value) { score = score + item.getNegativeScore(); scoreItemMessage = item.getNegativeMessage(); } } else if (item.getNegativeOperator().equals(">=")) { if (Integer.parseInt(item.getNegativeCriteria()) >= value) { score = score + item.getNegativeScore(); scoreItemMessage = item.getNegativeMessage(); } } else if (item.getNegativeOperator().equals(">")) { if (Integer.parseInt(item.getNegativeCriteria()) > value) { score = score + item.getNegativeScore(); scoreItemMessage = item.getNegativeMessage(); } } } } return new AccessPointScoreComputationItem(score, scoreItemMessage); } public void scoreAccessPointNew(AccessPoint ap) { ScoringHelper sh = new ScoringHelper(); if (ap.getPointType().equals(AccessPointType.WATER_POINT)) { BaseDAO<LevelOfServiceScore> losDao = new BaseDAO<LevelOfServiceScore>( LevelOfServiceScore.class); LevelOfServiceScore los = sh.scoreWaterPointByLevelOfService(ap, StandardType.WaterPointLevelOfService); ap = computeDistanceRule(ap); if (ap.getImprovedWaterPointFlag()) { if (ap.getNumberOutsideAcceptableDistance() >= 1) { los.setScore(los.getScore() + 0); los.addScoreDetail("Plus 0 Number of households outside of govt max acceptable distance is" + ap.getNumberOutsideAcceptableDistance()); losDao.save(los); } else { los.setScore(los.getScore() + 1); los.addScoreDetail("Plus 1 Number of households outside of govt max acceptable distance is" + ap.getNumberOutsideAcceptableDistance()); losDao.save(los); } } else { losDao.save(los); } LevelOfServiceScore losSustain = sh .scoreWaterPointByLevelOfService(ap, StandardType.WaterPointSustainability); losDao.save(losSustain); } } public static AccessPoint scoreAccessPoint(AccessPoint ap) { // Is there an improved water system no=0, yes=1 // Provide enough drinking water for community everyday of year no=0, // yes=1, don't know=0, // Water system been down in 30 days: No=1,yes=0 // Are there current problems: no=1,yes=0 // meet govt quantity standards:no=0,yes=1 // Is there a tarriff or fee no=0,yes=1 AccessPointScoreDetail apss = new AccessPointScoreDetail(); logger.log(Level.INFO, "About to compute score for: " + ap.getCommunityCode()); Integer score = 0; if (ap.getPointType().equals(AccessPoint.AccessPointType.WATER_POINT)) { // added other conditions to guess if it's an improved point or not // since the scoring seems like it's flawed if ((ap.isImprovedWaterPointFlag() != null && ap .isImprovedWaterPointFlag()) || (ap.getConstructionDateYear() != null && !ap .getConstructionDateYear().trim() .equalsIgnoreCase("na")) || (ap.getConstructionDateYear() != null && !ap .getConstructionDateYear().trim() .equalsIgnoreCase("n/a"))) { score++; apss.addScoreComputationItem(1, "Plus 1 for Improved Water System = true: "); if (ap.getProvideAdequateQuantity() != null && ap.getProvideAdequateQuantity().equals(true)) { score++; apss.addScoreComputationItem(1, "Plus 1 for Provide Adequate Quantity = true: "); } else { apss.addScoreComputationItem(1, "Plus 0 for Provide Adequate Quantity = false or null: "); } if (ap.getHasSystemBeenDown1DayFlag() != null && !ap.getHasSystemBeenDown1DayFlag().equals(true)) { score++; apss.addScoreComputationItem(1, "Plus 1 for Has System Been Down 1 Day Flag = false: "); } else { apss.addScoreComputationItem(1, "Plus 0 for Has System Been Down 1 Day Flag = true or null: "); } if (ap.getCurrentProblem() == null) { score++; apss.addScoreComputationItem(1, "Plus 1 for Get Current Problem = null"); } else { apss.addScoreComputationItem(1, "Plus 0 for Get Current Problem != null value: " + ap.getCurrentProblem()); } if (ap.isCollectTariffFlag() != null && ap.isCollectTariffFlag()) { score++; apss.addScoreComputationItem(1, "Plus 1 for Collect Tariff Flag = true "); } else { apss.addScoreComputationItem(1, "Plus 0 for Collect Tariff Flag = false or null: "); } } else { apss.addScoreComputationItem(1, "Plus 0 for Improved Water System = false or null: "); } apss.setScore(score); ap.setScore(score); ap.setScoreComputationDate(new Date()); apss.setComputationDate(ap.getScoreComputationDate()); logger.log(Level.INFO, "AP Collected in 2011 so scoring: " + ap.getCommunityCode() + "/" + ap.getCollectionDate() + " score: " + score); if (score == 0) { ap.setPointStatus(AccessPoint.Status.NO_IMPROVED_SYSTEM); apss.setStatus(AccessPoint.Status.NO_IMPROVED_SYSTEM.toString()); } else if (score >= 1 && score <= 2) { ap.setPointStatus(AccessPoint.Status.BROKEN_DOWN); apss.setStatus(AccessPoint.Status.BROKEN_DOWN.toString()); } else if (score >= 3 && score <= 4) { ap.setPointStatus(AccessPoint.Status.FUNCTIONING_WITH_PROBLEMS); apss.setStatus(AccessPoint.Status.FUNCTIONING_WITH_PROBLEMS .toString()); } else if (score >= 5) { ap.setPointStatus(AccessPoint.Status.FUNCTIONING_HIGH); apss.setStatus(AccessPoint.Status.FUNCTIONING_HIGH.toString()); } else { ap.setPointStatus(AccessPoint.Status.OTHER); apss.setStatus(AccessPoint.Status.OTHER.toString()); } ap.setApScoreDetail(apss); } return ap; } public AccessPoint computeDistanceRule(AccessPoint ap) { AccessPointDao apDao = new AccessPointDao(); if (ap != null) { // StandardScoringDao ssDao = new StandardScoringDao(); // List<StandardScoring> ssList = ssDao // .listLocalDistanceStandardScoringForAccessPoint(ap); Integer acceptableDistance = 500; DistanceStandardDao distanceStandardDao = new DistanceStandardDao(); DistanceStandard ds = distanceStandardDao.findDistanceStandard( StandardType.WaterPointLevelOfService, ap.getCountryCode(), ap.getLocationType()); if (ds != null) { acceptableDistance = ds.getMaxDistance(); } // if (ssList != null && !ssList.isEmpty()) { // StandardScoring ssItem = ssList.get(0); // if (ssItem != null && ssItem.getPositiveCriteria() != null) // targetDistance = Integer.parseInt(ssItem // .getPositiveCriteria()); // } if (ap.getTypeTechnologyString().equals( "Gravity Fed System with Household Taps")) { // ToDo: check against tech type of HH, but need to know which // question ap.setNumberWithinAcceptableDistance(ap .getNumberWithinAcceptableDistance() + 1); } else if (ap.getPointType().equals( AccessPoint.AccessPointType.WATER_POINT) && (ap.getCommunityCode() != null)) { List<AccessPoint> apList = apDao.listAccessPointByLocation( ap.getCountryCode(), ap.getCommunityCode(), AccessPointType.HOUSEHOLD.toString(), null, "all"); if (apList != null && !apList.isEmpty()) { for (AccessPoint hh : apList) { Double distance = CoordinateUtilities.computeDistance( ap.getLatitude(), ap.getLongitude(), hh.getLatitude(), hh.getLongitude()); if (distance != null && distance < acceptableDistance) { ap.setNumberWithinAcceptableDistance(ap .getNumberWithinAcceptableDistance() + 1); } else { ap.setNumberOutsideAcceptableDistance(ap .getNumberOutsideAcceptableDistance() + 1); } } apDao.save(ap); } } else if (ap.getPointType().equals(AccessPointType.HOUSEHOLD) && ap.getCommunityCode() != null) { List<AccessPoint> apList = apDao.listAccessPointByLocation( ap.getCountryCode(), ap.getCommunityCode(), AccessPointType.WATER_POINT.toString(), null, "all"); AccessPoint minDistanceWaterPoint = null; Double minDistance = null; for (AccessPoint wp : apList) { Double distance = CoordinateUtilities.computeDistance( ap.getLatitude(), ap.getLongitude(), wp.getLatitude(), wp.getLongitude()); if (minDistance == null || distance < minDistance) { minDistance = CoordinateUtilities.computeDistance( ap.getLatitude(), ap.getLongitude(), wp.getLatitude(), wp.getLongitude()); minDistanceWaterPoint = wp; } } if (minDistance != null && minDistance < acceptableDistance) { minDistanceWaterPoint .setNumberWithinAcceptableDistance(minDistanceWaterPoint .getNumberWithinAcceptableDistance() + 1); } else { minDistanceWaterPoint .setNumberOutsideAcceptableDistance(minDistanceWaterPoint // FIXME: NPE .getNumberOutsideAcceptableDistance()); } apDao.save(minDistanceWaterPoint); } } return ap; } }