Java tutorial
/* * Copyright (c) 2015. * * This file is part of QIS Surveillance App. * * QIS Surveillance App App is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * QIS Surveillance App App 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with QIS Surveillance App. If not, see <http://www.gnu.org/licenses/>. */ package org.eyeseetea.malariacare.data.database.model; import static org.eyeseetea.malariacare.data.database.AppDatabase.optionAlias; import static org.eyeseetea.malariacare.data.database.AppDatabase.optionName; import static org.eyeseetea.malariacare.data.database.AppDatabase.orgUnitAlias; import static org.eyeseetea.malariacare.data.database.AppDatabase.orgUnitName; import static org.eyeseetea.malariacare.data.database.AppDatabase.programAlias; import static org.eyeseetea.malariacare.data.database.AppDatabase.programName; import static org.eyeseetea.malariacare.data.database.AppDatabase.questionAlias; import static org.eyeseetea.malariacare.data.database.AppDatabase.questionName; import static org.eyeseetea.malariacare.data.database.AppDatabase.surveyAlias; import static org.eyeseetea.malariacare.data.database.AppDatabase.surveyName; import static org.eyeseetea.malariacare.data.database.AppDatabase.valueAlias; import static org.eyeseetea.malariacare.data.database.AppDatabase.valueName; import android.content.Context; import android.support.annotation.NonNull; import android.util.Log; import com.raizlabs.android.dbflow.annotation.Column; import com.raizlabs.android.dbflow.annotation.PrimaryKey; import com.raizlabs.android.dbflow.annotation.Table; import com.raizlabs.android.dbflow.config.FlowManager; import com.raizlabs.android.dbflow.sql.language.ConditionGroup; import com.raizlabs.android.dbflow.sql.language.Delete; import com.raizlabs.android.dbflow.sql.language.Join; import com.raizlabs.android.dbflow.sql.language.Method; import com.raizlabs.android.dbflow.sql.language.OrderBy; import com.raizlabs.android.dbflow.sql.language.SQLite; import com.raizlabs.android.dbflow.sql.language.Select; import com.raizlabs.android.dbflow.structure.BaseModel; import com.raizlabs.android.dbflow.structure.database.transaction.ProcessModelTransaction; import com.raizlabs.android.dbflow.structure.database.transaction.Transaction; import org.eyeseetea.malariacare.R; import org.eyeseetea.malariacare.data.IDataSourceCallback; import org.eyeseetea.malariacare.data.database.AppDatabase; import org.eyeseetea.malariacare.data.database.datasources.ProgramLocalDataSource; import org.eyeseetea.malariacare.data.database.utils.PreferencesState; import org.eyeseetea.malariacare.data.database.utils.Session; import org.eyeseetea.malariacare.data.database.utils.SurveyAnsweredRatioCache; import org.eyeseetea.malariacare.data.sync.exporter.IConvertToSDKVisitor; import org.eyeseetea.malariacare.data.sync.exporter.VisitableToSDK; import org.eyeseetea.malariacare.domain.boundary.repositories.IProgramRepository; import org.eyeseetea.malariacare.domain.entity.SurveyAnsweredRatio; import org.eyeseetea.malariacare.domain.exception.ConversionException; import org.eyeseetea.malariacare.strategies.SurveyFragmentStrategy; import org.eyeseetea.malariacare.utils.Constants; import org.hisp.dhis.client.sdk.android.api.persistence.flow.EventFlow; import org.joda.time.DateTime; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; @Table(database = AppDatabase.class, name = "Survey") public class SurveyDB extends BaseModel implements VisitableToSDK { public static final float MAX_AMBER = 80f; public static final float MAX_RED = 50f; @Column @PrimaryKey(autoincrement = true) long id_survey; @Column Long id_program_fk; /** * Reference to the mProgramDB associated to this survey (loaded lazily) */ ProgramDB mProgramDB; @Column Long id_org_unit_fk; /** * Reference to the org unit associated to this survey (loaded lazily) */ OrgUnitDB mOrgUnitDB; @Column Long id_user_fk; /** * Reference to the mUserDB that has created this survey (loaded lazily) */ UserDB mUserDB; @Column Date creation_date; @Column Date completion_date; @Column Date event_date; @Column Date scheduled_date; @Column Integer status; @Column Integer type; @Column String uid_event_fk; /** * List of values for this survey */ List<ValueDB> mValueDBs; /** * List of historic previous schedules */ List<SurveyScheduleDB> mSurveyScheduleDBs; /** * Calculated answered ratio for this survey according to its values */ SurveyAnsweredRatio answeredQuestionRatio; /** * Calculated main ScoreDB for this survey, is not persisted, just calculated on runtime */ Float mainScore; public SurveyDB() { //Set dates this.creation_date = new Date(); this.completion_date = this.creation_date; this.event_date = new Date(); this.scheduled_date = null; this.type = Constants.SURVEY_NO_TYPE; //to avoid NullPointerExceptions } public SurveyDB(OrgUnitDB orgUnitDB, ProgramDB programDB, UserDB userDB) { this(); // Possibilities [ In progress | Completed | Sent ] this.status = Constants.SURVEY_IN_PROGRESS; //Set context of the survey this.setOrgUnit(orgUnitDB); this.setProgram(programDB); this.setUser(userDB); this.setType(Constants.SURVEY_NO_TYPE); } public SurveyDB(OrgUnitDB orgUnitDB, ProgramDB programDB, UserDB userDB, int type) { this(); // Possibilities [ In progress | Completed | Sent ] this.status = Constants.SURVEY_IN_PROGRESS; //Set context of the survey this.setOrgUnit(orgUnitDB); this.setProgram(programDB); this.setUser(userDB); this.type = type; } public Long getId_survey() { return id_survey; } public void setId_survey(Long id_survey) { this.id_survey = id_survey; } public OrgUnitDB getOrgUnitDB() { if (mOrgUnitDB == null) { if (id_org_unit_fk == null) return null; mOrgUnitDB = new Select().from(OrgUnitDB.class).where(OrgUnitDB_Table.id_org_unit.is(id_org_unit_fk)) .querySingle(); } return mOrgUnitDB; } public void setOrgUnitDB(Long id_org_unit) { this.id_org_unit_fk = id_org_unit; this.mOrgUnitDB = null; } public void setOrgUnit(OrgUnitDB orgUnitDB) { this.mOrgUnitDB = orgUnitDB; this.id_org_unit_fk = (orgUnitDB != null) ? orgUnitDB.getId_org_unit() : null; } public ProgramDB getProgramDB() { if (mProgramDB == null) { if (id_program_fk == null) return null; mProgramDB = new Select().from(ProgramDB.class).where(ProgramDB_Table.id_program.is(id_program_fk)) .querySingle(); } return mProgramDB; } public void setProgramDB(Long id_program) { this.id_program_fk = id_program; this.mProgramDB = null; } public void setProgram(ProgramDB programDB) { this.mProgramDB = programDB; this.id_program_fk = (programDB != null) ? programDB.getId_program() : null; } public UserDB getUserDB() { if (mUserDB == null) { if (id_user_fk == null) return null; mUserDB = new Select().from(UserDB.class).where(UserDB_Table.id_user.is(id_user_fk)).querySingle(); } return mUserDB; } public void setUserDB(Long id_user) { this.id_user_fk = id_user; this.mUserDB = null; } public void setUser(UserDB userDB) { this.mUserDB = userDB; this.id_user_fk = (userDB != null) ? userDB.getId_user() : null; } public Date getCreationDate() { return creation_date; } public void setCreationDate(Date creationDate) { this.creation_date = creationDate; } public Date getCompletionDate() { return completion_date; } public void setCompletionDate(Date completionDate) { this.completion_date = completionDate; } public Date getEventDate() { return event_date; } public void setEventDate(Date eventDate) { this.event_date = eventDate; } public Date getScheduledDate() { return scheduled_date; } public void setScheduledDate(Date scheduledDate) { this.scheduled_date = scheduledDate; } public Integer getStatus() { return status; } public void setStatus(Integer status) { this.status = status; } public Integer getType() { return type; } public void setType(Integer type) { this.type = type; } public String getEventUid() { return uid_event_fk; } public void setEventUid(EventFlow event) { this.uid_event_fk = event.getUId(); } public void setEventUid(String eventuid) { this.uid_event_fk = eventuid; } /** * Returns a concrete survey, if it exists */ public static List<SurveyDB> getUnsentSurveys(OrgUnitDB orgUnitDB, ProgramDB programDB) { return new Select().from(SurveyDB.class).where(SurveyDB_Table.id_org_unit_fk.eq(orgUnitDB.getId_org_unit())) .and(SurveyDB_Table.id_program_fk.eq(programDB.getId_program())) .and(SurveyDB_Table.status.isNot(Constants.SURVEY_SENT)) .orderBy(OrderBy.fromProperty(SurveyDB_Table.event_date)) .orderBy(OrderBy.fromProperty(SurveyDB_Table.id_org_unit_fk)).queryList(); } /** * Returns all the malaria surveys with status yet not put to "Sent" */ public static List<SurveyDB> getAllUnsentMalariaSurveys(String malariaProgramUid) { Context context = PreferencesState.getInstance().getContext(); return new Select().from(SurveyDB.class).as(surveyName).join(ProgramDB.class, Join.JoinType.LEFT_OUTER) .as(programName) .on(SurveyDB_Table.id_program_fk.withTable(surveyAlias) .eq(ProgramDB_Table.id_program.withTable(programAlias))) .where(SurveyDB_Table.status.withTable(surveyAlias).isNot(Constants.SURVEY_SENT)) .and(SurveyDB_Table.status.withTable(surveyAlias).isNot(Constants.SURVEY_CONFLICT)) .and(ProgramDB_Table.uid_program.withTable(programAlias).is(malariaProgramUid)) .orderBy(OrderBy.fromProperty(SurveyDB_Table.event_date.withTable(surveyAlias))) .orderBy(OrderBy.fromProperty(SurveyDB_Table.id_org_unit_fk.withTable(surveyAlias))).queryList(); } /** * Returns all the malaria surveys with status put to "Sent" */ public static List<SurveyDB> getAllSentMalariaSurveys(String malariaProgramUid) { Context context = PreferencesState.getInstance().getContext(); return new Select().from(SurveyDB.class).as(surveyName).join(ProgramDB.class, Join.JoinType.LEFT_OUTER) .as(programName) .on(SurveyDB_Table.id_program_fk.withTable(surveyAlias) .eq(ProgramDB_Table.id_program.withTable(programAlias))) .where(ConditionGroup.clause() .and(ProgramDB_Table.uid_program.withTable(programAlias).is(malariaProgramUid)) .and(ConditionGroup.clause() .and(SurveyDB_Table.status.withTable(surveyAlias).is(Constants.SURVEY_SENT))) .or(SurveyDB_Table.status.eq(Constants.SURVEY_CONFLICT))) .orderBy(SurveyDB_Table.event_date, false).queryList(); } /** * Returns all the surveys with status yet not put to "Sent" */ public static List<SurveyDB> getAllUnsentSurveys() { return new Select().from(SurveyDB.class).where(SurveyDB_Table.status.isNot(Constants.SURVEY_SENT)) .and(SurveyDB_Table.status.isNot(Constants.SURVEY_CONFLICT)) .orderBy(OrderBy.fromProperty(SurveyDB_Table.event_date)) .orderBy(OrderBy.fromProperty(SurveyDB_Table.id_org_unit_fk)).queryList(); } /** * Returns the last surveys (by date) with status yet not put to "Sent" */ public static List<SurveyDB> getUnsentSurveys(int limit) { return new Select().from(SurveyDB.class).where(SurveyDB_Table.status.isNot(Constants.SURVEY_SENT)) .limit(limit).orderBy(OrderBy.fromProperty(SurveyDB_Table.event_date)) .orderBy(OrderBy.fromProperty(SurveyDB_Table.id_org_unit_fk)).queryList(); } /** * Returns all the surveys with status put to "quarantine" */ public static List<SurveyDB> getAllQuarantineSurveys() { return new Select().from(SurveyDB.class).where(SurveyDB_Table.status.eq(Constants.SURVEY_QUARANTINE)) .orderBy(OrderBy.fromProperty(SurveyDB_Table.event_date).descending()).queryList(); } /** * Returns all the surveys with status put to "quarantine" */ public static int countQuarantineSurveys() { return (int) SQLite.selectCountOf().from(SurveyDB.class) .where(SurveyDB_Table.status.eq(Constants.SURVEY_QUARANTINE)).count(); } /** * Returns all the surveys with status put to "Sent" */ public static List<SurveyDB> getAllMalariaSurveysToBeSent(String malariaProgramUid) { Context context = PreferencesState.getInstance().getContext(); return new Select().from(SurveyDB.class).as(surveyName).join(ProgramDB.class, Join.JoinType.LEFT_OUTER) .as(programName) .on(SurveyDB_Table.id_program_fk.withTable(surveyAlias) .eq(ProgramDB_Table.id_program.withTable(programAlias))) .where(SurveyDB_Table.status.withTable(surveyAlias).eq(Constants.SURVEY_COMPLETED)) .and(ProgramDB_Table.uid_program.withTable(programAlias).is(malariaProgramUid)) .orderBy(OrderBy.fromProperty(SurveyDB_Table.event_date)) .orderBy(OrderBy.fromProperty(SurveyDB_Table.id_org_unit_fk)).queryList(); } /** * Returns all the surveys */ public static List<SurveyDB> getAllSurveys() { return new Select().from(SurveyDB.class).orderBy(OrderBy.fromProperty(SurveyDB_Table.completion_date)) .queryList(); } /** * Returns the last surveys (by date) with status put to "Sent" */ public static List<SurveyDB> getSentSurveys(int limit) { return new Select().from(SurveyDB.class).where(SurveyDB_Table.status.eq(Constants.SURVEY_SENT)).limit(limit) .orderBy(OrderBy.fromProperty(SurveyDB_Table.event_date)) .orderBy(OrderBy.fromProperty(SurveyDB_Table.id_org_unit_fk)).queryList(); } /** * Returns all the surveys with status put to "Completed" */ public static List<SurveyDB> getAllCompletedSurveys() { return new Select().from(SurveyDB.class).where(SurveyDB_Table.status.eq(Constants.SURVEY_COMPLETED)) .orderBy(OrderBy.fromProperty(SurveyDB_Table.event_date)) .orderBy(OrderBy.fromProperty(SurveyDB_Table.id_org_unit_fk)).queryList(); } public static List<SurveyDB> getAllCompletedSurveysNoReceiptReset() { return new Select().from(SurveyDB.class).where(SurveyDB_Table.status.eq(Constants.SURVEY_COMPLETED)) .and(SurveyDB_Table.type.isNot(Constants.SURVEY_RECEIPT)) .and(SurveyDB_Table.type.isNot(Constants.SURVEY_RESET)) .orderBy(OrderBy.fromProperty(SurveyDB_Table.event_date)) .orderBy(OrderBy.fromProperty(SurveyDB_Table.id_org_unit_fk)).queryList(); } /** * Returns all the surveys with status put to "In progress" */ public static List<SurveyDB> getAllUncompletedSurveys() { return new Select().from(SurveyDB.class).where(SurveyDB_Table.status.is(Constants.SURVEY_IN_PROGRESS)) .orderBy(OrderBy.fromProperty(SurveyDB_Table.event_date)) .orderBy(OrderBy.fromProperty(SurveyDB_Table.id_org_unit_fk)).queryList(); } public static void removeInProgress() { List<SurveyDB> inProgressSurveyDB = getAllUncompletedSurveys(); for (int i = inProgressSurveyDB.size() - 1; i >= 0; i--) { inProgressSurveyDB.get(i).delete(); } } /** * Find the surveys that have been sent after the given date */ public static List<SurveyDB> findSentSurveysAfterDate(Date minDateForMonitor) { return new Select().from(SurveyDB.class).where(SurveyDB_Table.status.eq(Constants.SURVEY_SENT)) .or(SurveyDB_Table.status.eq(Constants.SURVEY_CONFLICT)) .and(SurveyDB_Table.event_date.greaterThanOrEq(minDateForMonitor)).queryList(); } /** * Find the surveys for a mProgramDB, with a type o no type ans with the event date grater than * passed. * * @param programDB The mProgramDB of the survey * @param date The min eventDate of the survey * @return A list of surveys */ public static List<SurveyDB> findSurveysWithProgramAndGreaterDate(ProgramDB programDB, Date date) { return new Select().from(SurveyDB.class).as(surveyName).join(ProgramDB.class, Join.JoinType.LEFT_OUTER) .as(programName) .on(SurveyDB_Table.id_program_fk.withTable(surveyAlias) .eq(ProgramDB_Table.id_program.withTable(programAlias))) .where(ProgramDB_Table.id_program.withTable(programAlias).eq(programDB.getId_program())) .and(SurveyDB_Table.event_date.withTable(surveyAlias).greaterThanOrEq(date)).queryList(); } public static Date getLastDateForSurveyType(int type) { SurveyDB surveyDB = new Select().from(SurveyDB.class).where(SurveyDB_Table.type.eq(type)) .groupBy(SurveyDB_Table.id_survey) .having(SurveyDB_Table.event_date.is(Method.max(SurveyDB_Table.event_date))).querySingle(); if (surveyDB == null) { return new Date(0); } return surveyDB.getEventDate(); } public static SurveyDB getLastSurveyWithType(int type) { SurveyDB surveyDB = new Select().from(SurveyDB.class).where(SurveyDB_Table.type.eq(type)) .orderBy(OrderBy.fromProperty(SurveyDB_Table.event_date).descending()).querySingle(); return surveyDB; } public static List<SurveyDB> getSurveysWithProgramType(ProgramDB programDB, int type) { return new Select().from(SurveyDB.class).as(surveyName).join(ProgramDB.class, Join.JoinType.LEFT_OUTER) .as(programName) .on(SurveyDB_Table.id_program_fk.withTable(surveyAlias) .eq(ProgramDB_Table.id_program.withTable(programAlias))) .where(ProgramDB_Table.id_program.withTable(programAlias).eq(programDB.getId_program())) .and(SurveyDB_Table.type.withTable(surveyAlias).is(type)).queryList(); } /** * Finds a survey by its ID */ public static SurveyDB findById(Long id_survey) { return new Select().from(SurveyDB.class).where(SurveyDB_Table.id_survey.eq(id_survey)).querySingle(); } public static void removeValue(ValueDB valueDB) { valueDB.delete(); } public static int countSurveysByCompletiondate(Date completion_date) { return (int) SQLite.selectCountOf().from(SurveyDB.class) .where(SurveyDB_Table.completion_date.eq(completion_date)).count(); } public static Date getMaxQuarantineEventDate() { SurveyDB surveyDB = new Select().from(SurveyDB.class) .where(SurveyDB_Table.status.eq(Constants.SURVEY_QUARANTINE)) .orderBy(OrderBy.fromProperty(SurveyDB_Table.event_date).descending()).querySingle(); return surveyDB.getEventDate(); } public static List<SurveyDB> getAllSendingSurveys() { return new Select().from(SurveyDB.class).where(SurveyDB_Table.status.eq(Constants.SURVEY_SENDING)) .queryList(); } public Float getCounterValue(QuestionDB questionDB, OptionDB selectedOptionDB) { QuestionDB optionCounter = questionDB.findCounterByOption(selectedOptionDB); if (optionCounter == null) { return 0f; } String counterValue = optionCounter.getQuestionValueBySession(); if (counterValue == null || counterValue.isEmpty()) { return 0f; } return Float.parseFloat(counterValue); } /** * Checks if the survey has been sent or not * * @return true|false */ public boolean isSent() { return Constants.SURVEY_SENT == this.status; } /** * Checks if the survey has been completed or not * * @return true|false */ public boolean isCompleted() { return Constants.SURVEY_COMPLETED == this.status; } /** * Checks if the survey has been in conflict * * @return true|false */ public boolean isConflict() { return Constants.SURVEY_CONFLICT == this.status; } /** * Checks if the survey has been in conflict * * @return true|false */ public boolean isQuarantine() { return Constants.SURVEY_QUARANTINE == this.status; } /** * Checks if the survey has been completed or not * * @return true|false */ public boolean isCompleted(Long idSurvey) { SurveyDB srv = new Select().from(SurveyDB.class).where(SurveyDB_Table.id_survey.eq(idSurvey)).querySingle(); return srv.getStatus().equals(Constants.SURVEY_COMPLETED); } /** * Checks if the survey is in progress * * @return true|false */ public boolean isInProgress() { return this.status == Constants.SURVEY_IN_PROGRESS; } public void saveMainScore() { Float valScore = 0f; if (mainScore != null) { valScore = mainScore; } ScoreDB scoreDB = new ScoreDB(this, "", valScore); scoreDB.save(); } private ScoreDB getScore() { return new Select().from(ScoreDB.class).where(ScoreDB_Table.id_survey_fk.eq(this.getId_survey())) .querySingle(); } @Override public void delete() { ScoreDB scoreDB = getScore(); if (scoreDB != null) { scoreDB.delete(); } for (ValueDB valueDB : getValuesFromDB()) { valueDB.delete(); } super.delete(); } /** * Returns this survey is type A (green) */ public boolean isTypeA() { return this.mainScore >= MAX_AMBER; } /** * Returns this survey is type B (amber) */ public boolean isTypeB() { return this.mainScore >= MAX_RED && !isTypeA(); } /** * Returns the list of answered values from this survey */ public List<ValueDB> getValueDBs() { if (mValueDBs == null) { mValueDBs = new Select().from(ValueDB.class).where(ValueDB_Table.id_survey_fk.eq(this.getId_survey())) .queryList(); } return mValueDBs; } /** * Returns the list of answered values from this survey */ public List<ValueDB> getValuesFromDB() { mValueDBs = new Select().from(ValueDB.class).where(ValueDB_Table.id_survey_fk.eq(this.getId_survey())) .queryList(); return mValueDBs; } /** * Returns the list of answered values from this survey */ public List<ValueDB> getValuesFromDBWithoutSave() { return new Select().from(ValueDB.class).where(ValueDB_Table.id_survey_fk.eq(this.getId_survey())) .queryList(); } /** * Returns the list of mQuestionDBs from answered values */ public List<QuestionDB> getQuestionsFromValues() { List<QuestionDB> questionDBs = new Select().from(QuestionDB.class).as(questionName) .join(ValueDB.class, Join.JoinType.LEFT_OUTER).as(valueName) .on(ValueDB_Table.id_question_fk.withTable(valueAlias) .eq(QuestionDB_Table.id_question.withTable(questionAlias))) .where(ValueDB_Table.id_survey_fk.withTable(valueAlias).eq(this.getId_survey())) .orderBy(OrderBy.fromProperty(QuestionDB_Table.order_pos).ascending()).queryList(); return questionDBs; } /** * Ratio of completion is cached into answeredQuestionRatio in order to speed up loading */ public SurveyAnsweredRatio getAnsweredQuestionRatio() { if (answeredQuestionRatio == null) { answeredQuestionRatio = SurveyAnsweredRatioCache.get(this.getId_survey()); if (answeredQuestionRatio == null) { answeredQuestionRatio = reloadSurveyAnsweredRatio(); } } return answeredQuestionRatio; } /** * Calculates the current ratio of completion for this survey * * @return SurveyAnsweredRatio that hold the total & answered mQuestionDBs. */ public SurveyAnsweredRatio reloadSurveyAnsweredRatio() { SurveyAnsweredRatio surveyAnsweredRatio; //First parent is always required and not calculated. int numRequired = 1; int numAnswered = 0; IProgramRepository programLocalDataSource = new ProgramLocalDataSource(); ProgramDB programDB = ProgramDB.findByUID(programLocalDataSource.getUserProgram().getId()); TabDB tabDB = programDB.getTabDBs().get(0); QuestionDB rootQuestionDB = QuestionDB.findRootQuestion(tabDB); QuestionDB localQuestionDB = rootQuestionDB; numRequired = SurveyFragmentStrategy.getNumRequired(numRequired, localQuestionDB); //Add children required by each parent (value+mQuestionDB) SurveyDB surveyDB = SurveyDB.findById(id_survey); for (ValueDB valueDB : surveyDB.getValuesFromDB()) { if (valueDB.getQuestionDB().isCompulsory() && valueDB.getId_option() != null) { numRequired += QuestionDB.countChildrenByOptionValue(valueDB.getId_option()); } } numAnswered += countCompulsoryBySurvey(this); Log.d("survey answered", "num required: " + numRequired + " num answered: " + numAnswered); surveyAnsweredRatio = new SurveyAnsweredRatio(numRequired, numAnswered); SurveyAnsweredRatioCache.put(this.id_survey, surveyAnsweredRatio); return surveyAnsweredRatio; } public static int countCompulsoryBySurvey(SurveyDB surveyDB) { List<QuestionDB> questionDBs = surveyDB.getQuestionsFromValues(); int countOfCompulsoryValues = 0; for (QuestionDB questionDB : questionDBs) { if (questionDB.isCompulsory()) { countOfCompulsoryValues++; } } return countOfCompulsoryValues; } /** * Updates ratios, status and completion date depending on the mQuestionDB and mAnswerDB (text) */ public void updateSurveyStatus() { //Sent surveys are not updated if (this.isSent() || this.isConflict()) { return; } SurveyAnsweredRatio answeredRatio = this.reloadSurveyAnsweredRatio(); //Update status & completionDate if (answeredRatio.isCompleted()) { complete(); } else { setStatus(Constants.SURVEY_IN_PROGRESS); setCompletionDate(this.event_date); save(); } } public void complete() { setStatus(Constants.SURVEY_COMPLETED); setCompletionDate(new Date()); save(); } /** * Checks if the mAnswerDB to the first mQuestionDB is 'Yes' * * @return true|false */ public boolean isRDT() { //refresh values getValuesFromDB(); return getRDTName() .equals(PreferencesState.getInstance().getContext().getResources().getString(R.string.rdtPositive)); } public boolean isIssueSurvey() { if (type == null) { return false; } return type == Constants.SURVEY_ISSUE; } /** * Since there are three possible values first mQuestionDB (RDT):'Positive','Negative','Not * Tested' * * @return String */ public String getRDTName() { String rdtValue = ""; if (mValueDBs == null) { mValueDBs = ValueDB.listAllBySurvey(this); } if (mValueDBs.size() > 0) { for (ValueDB valueDB : mValueDBs) { //Find the RTS mOptionDB if (valueDB.getOptionDB() != null && valueDB.getQuestionDB() != null && valueDB.getQuestionDB().getCode() .equals(PreferencesState.getInstance().getContext().getString(R.string.RDT_code))) { rdtValue = valueDB.getOptionDB().getCode(); } } } return rdtValue; } /** * Since there are three possible values first mQuestionDB (RDT):'Positive','Negative','Not * Tested' * * @return String */ public String getResultCode() { String rdtValue = ""; if (mValueDBs == null) { mValueDBs = ValueDB.listAllBySurvey(this); } if (mValueDBs.size() > 0) { for (ValueDB valueDB : mValueDBs) { //Find the RTS mOptionDB if (valueDB.getOptionDB() != null && valueDB.getQuestionDB() != null && valueDB.getQuestionDB().getCode().equals( PreferencesState.getInstance().getContext().getString(R.string.Result_code))) { rdtValue = valueDB.getOptionDB().getInternationalizedName(); } } } return rdtValue; } /** * Turns all values from a survey into a string with values separated by commas * * @return String */ public String getValuesToString() { if (mValueDBs == null) { mValueDBs = ValueDB.listAllBySurvey(this); } Iterator<ValueDB> iterator = mValueDBs.iterator(); String valuesStr = ""; //Define a filter to select which values will be turned into string by code_question List<QuestionDB> questionDBs = new ArrayList<>(); for (ValueDB valueDB : mValueDBs) { questionDBs.add(valueDB.getQuestionDB()); } List<String> codeQuestionFilter = new ArrayList<String>(); for (QuestionDB questionDB : questionDBs) { if (questionDB != null && questionDB.isVisible()) { codeQuestionFilter.add(questionDB.getCode()); } } Map map = new HashMap(); while (iterator.hasNext()) { ValueDB valueDB = iterator.next(); //The control dataelements not have mQuestionDBs and its should be ignored if (valueDB.getQuestionDB() == null || valueDB.getValue() == null) { continue; } String qCode = valueDB.getQuestionDB().getCode(); if (codeQuestionFilter.contains(qCode)) { String val = (valueDB.getOptionDB() != null) ? valueDB.getOptionDB().getInternationalizedName() : valueDB.getValue(); if (val != null) { map.put(qCode, val); } } } //Sort values for (int i = 0; i < codeQuestionFilter.size(); i++) { if (map.get(codeQuestionFilter.get(i)) != null) { valuesStr += map.get(codeQuestionFilter.get(i)); if (i < codeQuestionFilter.size() - 1) { valuesStr += ", "; } } } if (valuesStr.endsWith(", ")) { valuesStr = valuesStr.substring(0, valuesStr.lastIndexOf(", ")); } return valuesStr; } public String printValues() { String valuesString = "Survey values: "; if (getValuesFromDB() != null) { for (ValueDB valueDB : mValueDBs) { valuesString += "ValueDB: " + valueDB.getValue(); if (valueDB.getOptionDB() != null) { valuesString += " OptionDB: " + valueDB.getOptionDB().getInternationalizedCode(); } if (valueDB.getQuestionDB() != null) { valuesString += " Question: " + valueDB.getQuestionDB().getDe_name() + "\n"; } } } return valuesString; } /** * This method removes the children mQuestionDB values from when a parent mQuestionDB is removed * * @removeCounters is used to prevent to remove the counter when change the some mQuestionDB in * the * same level * This changed was required because the counter need be child of the mQuestionDB+mOptionDB who * tigger * the counter. */ public void removeChildrenValuesFromQuestionRecursively(QuestionDB questionDB, boolean removeCounters) { List<ValueDB> valueDBs = getValuesFromDB(); List<QuestionDB> questionDBChildren = questionDB.getChildren(); for (int i = valueDBs.size() - 1; i > 0; i--) { //This loop removes recursively the values on the children mQuestionDB if (questionDBChildren.contains(valueDBs.get(i).getQuestionDB())) { //Remove the children values but if the child value is a counter is not removed // in the first level if (!valueDBs.get(i).getQuestionDB().isACounter() || removeCounters) { for (QuestionDB questionDBPropagated : valueDBs.get(i).getQuestionDB() .getPropagationQuestions()) { removeValue(questionDBPropagated.getValueBySurvey(Session.getMalariaSurveyDB())); } removeValue(valueDBs.get(i)); } for (QuestionDB child : questionDBChildren) { removeChildrenValuesFromQuestionRecursively(child, true); } } } } public static List<OrgUnitDB> getQuarantineOrgUnits(long programUid) { return new Select().from(OrgUnitDB.class).as(orgUnitName).join(SurveyDB.class, Join.JoinType.LEFT_OUTER) .as(surveyName) .on(SurveyDB_Table.id_org_unit_fk.withTable(surveyAlias) .eq(OrgUnitDB_Table.id_org_unit.withTable(orgUnitAlias))) .where(SurveyDB_Table.status.eq(Constants.SURVEY_QUARANTINE)) .and(SurveyDB_Table.id_program_fk.eq(programUid)).queryList(); } public static List<SurveyDB> getAllQuarantineSurveysByProgramAndOrgUnit(ProgramDB programDB, OrgUnitDB orgUnitDB) { return new Select().from(SurveyDB.class).where(SurveyDB_Table.status.eq(Constants.SURVEY_QUARANTINE)) .and(SurveyDB_Table.id_program_fk.eq(programDB.getId_program())) .and(SurveyDB_Table.id_org_unit_fk.eq(orgUnitDB.getId_org_unit())) .orderBy(OrderBy.fromProperty(SurveyDB_Table.event_date).descending()).queryList(); } public static Date getMinQuarantineCompletionDateByProgramAndOrgUnit(ProgramDB programDB, OrgUnitDB orgUnitDB) { SurveyDB surveyDB = new Select().from(SurveyDB.class) .where(SurveyDB_Table.status.eq(Constants.SURVEY_QUARANTINE)) .and(SurveyDB_Table.id_program_fk.eq(programDB.getId_program())) .and(SurveyDB_Table.id_org_unit_fk.eq(orgUnitDB.getId_org_unit())) .orderBy(OrderBy.fromProperty(SurveyDB_Table.completion_date).ascending()).querySingle(); return surveyDB.getCompletionDate(); } public static Date getMaxQuarantineEventDateByProgramAndOrgUnit(ProgramDB programDB, OrgUnitDB orgUnitDB) { SurveyDB surveyDB = new Select().from(SurveyDB.class) .where(SurveyDB_Table.status.eq(Constants.SURVEY_QUARANTINE)) .and(SurveyDB_Table.id_program_fk.eq(programDB.getId_program())) .and(SurveyDB_Table.id_org_unit_fk.eq(orgUnitDB.getId_org_unit())) .orderBy(OrderBy.fromProperty(SurveyDB_Table.event_date).descending()).querySingle(); return surveyDB.getEventDate(); } public static void deleteAll() { List<SurveyDB> surveyDBs = SurveyDB.getAllSurveys(); for (SurveyDB surveyDB : surveyDBs) { surveyDB.delete(); } } public static void deleteOlderSentSurveys(int numberOfDaysAfter) { Date dateWithDaysAdded = minusDaysTo(new Date(), numberOfDaysAfter); List<SurveyDB> sentSurveys = getAllSentSurveysOlderThan(dateWithDaysAdded); deleteSurveys(sentSurveys); } public static void deleteSurveys(List<SurveyDB> surveys) { for (SurveyDB surveyDB : surveys) { new Delete().from(ValueDB.class).where(ValueDB_Table.id_survey_fk.eq(surveyDB.getId_survey())); surveyDB.delete(); } } @NonNull public static Date minusDaysTo(Date date, int numberOfDaysAfter) { DateTime dateTime = new DateTime(date); dateTime = dateTime.minusDays(numberOfDaysAfter); return dateTime.toDate(); } @NonNull public static List<SurveyDB> getAllSentSurveysOlderThan(Date oldestAllowedDate) { return new Select().from(SurveyDB.class).where(SurveyDB_Table.status.is(Constants.SURVEY_SENT), SurveyDB_Table.event_date.lessThanOrEq(oldestAllowedDate)).queryList(); } public OptionDB getOptionSelectedForQuestionCode(String questionCode) { return new Select().from(OptionDB.class).as(optionName).join(ValueDB.class, Join.JoinType.LEFT_OUTER) .as(valueName) .on(ValueDB_Table.id_option_fk.withTable(valueAlias) .eq(OptionDB_Table.id_option.withTable(optionAlias))) .join(QuestionDB.class, Join.JoinType.LEFT_OUTER).as(questionName) .on(QuestionDB_Table.id_question.withTable(questionAlias) .eq(ValueDB_Table.id_question_fk.withTable(valueAlias))) .where(ValueDB_Table.id_survey_fk.withTable(valueAlias).eq(this.getId_survey())) .and(QuestionDB_Table.code.withTable(questionAlias).eq(questionCode)).querySingle(); } /** * This method get the return the highest number of total pages in the survey mQuestionDB values. */ public int getMaxTotalPages() { List<ValueDB> valueDBs = getValuesFromDB(); int totalPages = 0; for (ValueDB valueDB : valueDBs) { if (valueDB.getQuestionDB() != null && valueDB.getQuestionDB().getTotalQuestions() > totalPages) { totalPages = valueDB.getQuestionDB().getTotalQuestions(); } } return totalPages; } @Override public void accept(IConvertToSDKVisitor IConvertToSDKVisitor) throws ConversionException { IConvertToSDKVisitor.visit(this); } public static void saveAll(List<SurveyDB> surveyDBs, final IDataSourceCallback<Void> callback) { FlowManager.getDatabase(AppDatabase.class).beginTransactionAsync( new ProcessModelTransaction.Builder<>(new ProcessModelTransaction.ProcessModel<SurveyDB>() { @Override public void processModel(SurveyDB surveyDB) { surveyDB.save(); } }).addAll(surveyDBs).build()).error(new Transaction.Error() { @Override public void onError(Transaction transaction, Throwable error) { callback.onError(error); } }).success(new Transaction.Success() { @Override public void onSuccess(Transaction transaction) { callback.onSuccess(null); } }).build().execute(); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; SurveyDB surveyDB = (SurveyDB) o; if (id_survey != surveyDB.id_survey) return false; if (id_program_fk != null ? !id_program_fk.equals(surveyDB.id_program_fk) : surveyDB.id_program_fk != null) { return false; } if (id_org_unit_fk != null ? !id_org_unit_fk.equals(surveyDB.id_org_unit_fk) : surveyDB.id_org_unit_fk != null) { return false; } if (id_user_fk != null ? !id_user_fk.equals(surveyDB.id_user_fk) : surveyDB.id_user_fk != null) { return false; } if (creation_date != null ? !creation_date.equals(surveyDB.creation_date) : surveyDB.creation_date != null) { return false; } if (completion_date != null ? !completion_date.equals(surveyDB.completion_date) : surveyDB.completion_date != null) { return false; } if (event_date != null ? !event_date.equals(surveyDB.event_date) : surveyDB.event_date != null) { return false; } if (scheduled_date != null ? !scheduled_date.equals(surveyDB.scheduled_date) : surveyDB.scheduled_date != null) { return false; } if (status != null ? !status.equals(surveyDB.status) : surveyDB.status != null) { return false; } return type != null ? type.equals(surveyDB.type) : surveyDB.type == null; } @Override public int hashCode() { int result = (int) (id_survey ^ (id_survey >>> 32)); result = 31 * result + (id_program_fk != null ? id_program_fk.hashCode() : 0); result = 31 * result + (id_org_unit_fk != null ? id_org_unit_fk.hashCode() : 0); result = 31 * result + (id_user_fk != null ? id_user_fk.hashCode() : 0); result = 31 * result + (creation_date != null ? creation_date.hashCode() : 0); result = 31 * result + (completion_date != null ? completion_date.hashCode() : 0); result = 31 * result + (event_date != null ? event_date.hashCode() : 0); result = 31 * result + (scheduled_date != null ? scheduled_date.hashCode() : 0); result = 31 * result + (status != null ? status.hashCode() : 0); result = 31 * result + (type != null ? type.hashCode() : 0); return result; } @Override public String toString() { return "Survey{" + "id_survey=" + id_survey + ", id_program_fk=" + id_program_fk + ", id_org_unit_fk=" + id_org_unit_fk + ", id_user_fk=" + id_user_fk + ", creation_date=" + creation_date + ", completion_date=" + completion_date + ", event_date=" + event_date + ", scheduled_date=" + scheduled_date + ", status=" + status + ", type=" + type + '}'; } }