Java tutorial
/* * Spirit, a study/biosample management tool for research. * Copyright (C) 2018 Idorsia Pharmaceuticals Ltd., Hegenheimermattweg 91, * CH-4123 Allschwil, Switzerland. * * This program 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. * * This program 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 this program. If not, see <http://www.gnu.org/licenses/> * * @author Joel Freyss */ package com.actelion.research.spiritapp.report; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import com.actelion.research.spiritapp.ui.SpiritFrame; import com.actelion.research.spiritapp.ui.util.POIUtils; import com.actelion.research.spiritcore.business.biosample.Biosample; import com.actelion.research.spiritcore.business.biosample.FoodWater; import com.actelion.research.spiritcore.business.result.Result; import com.actelion.research.spiritcore.business.result.ResultValue; import com.actelion.research.spiritcore.business.study.Group; import com.actelion.research.spiritcore.business.study.Phase; import com.actelion.research.spiritcore.business.study.PhaseFormat; import com.actelion.research.spiritcore.business.study.Study; import com.actelion.research.spiritcore.services.dao.DAOFoodWater; import com.actelion.research.spiritcore.services.dao.DAOResult; import com.actelion.research.spiritcore.services.dao.DAORevision; import com.actelion.research.spiritcore.services.dao.DAOStudy; import com.actelion.research.spiritcore.services.dao.DAOTest; import com.actelion.research.spiritcore.util.ListHashMap; import com.actelion.research.spiritcore.util.MiscUtils; import com.actelion.research.util.FormatterUtils; public class FoodWaterReport extends AbstractReport { public FoodWaterReport() { super(ReportCategory.PARTICIPANTS, "Food / Water", "Food & Water consumption " + MiscUtils .convert2Html("Group\tParticipant\tNo\tContainerId\tTare\tWeight\tN\tConsumption\n" + "A\tParticipant1\tCage1\n" + "A\tParticipant2\tCage1\n")); } @Override protected void populateWorkBook() throws Exception { createWorkBookNew(wb); } protected void createWorkBookNew(Workbook wb) throws Exception { if (study.getPhases().size() == 0) throw new Exception("You cannot generate a FoodWater report if you don't have phases in your study"); Row row; DAOResult.attachOrCreateStudyResultsToTops(study, study.getParticipantsSorted(), null, null); List<FoodWater> fws = DAOFoodWater.getFoodWater(study, null); List<Phase> phases = FoodWater.getPhases(fws); Map<Biosample, List<Biosample>> mapHistory = DAORevision.getHistories(study.getParticipantsSorted()); boolean hasCageChanges = false; for (Biosample top : study.getParticipantsSorted()) { Set<String> containerIds = new HashSet<>(); for (Phase phase : phases) { String containerId = getContainerAt(top, phase, fws, mapHistory.get(top)); if (containerId != null && containerId.length() > 0) containerIds.add(containerId); } if (containerIds.size() > 1) { hasCageChanges = true; break; } } boolean displayCageEachPhase = study.getFirstDate() != null && study.getPhaseFormat() == PhaseFormat.DAY_MINUTES && hasCageChanges; //Loop through Food (i=0) and water (i==1) reports for (int i = 0; i < 2; i++) { //Check if we have some data boolean hasData = false; for (FoodWater fw : fws) { if (i == 0 && (fw.getFoodTare() != null || fw.getFoodWeight() != null)) hasData = true; else if (i == 1 && (fw.getWaterTare() != null || fw.getWaterWeight() != null)) hasData = true; } if (!hasData) continue; Sheet sheet = createSheet(wb, i == 0 ? "Food" : "Water"); createHeadersWithTitle(sheet, study, i == 0 ? "Food Consumption [g/animal/day]" : "Water Consumption [ml/animal/day]"); //Create Table Header row = sheet.createRow(5); row.setHeightInPoints(21f); row = sheet.createRow(6); row.setHeightInPoints(21f); int x = 0; set(sheet, 6, x++, "Group", Style.S_TH_CENTER); set(sheet, 6, x++, "Id", Style.S_TH_CENTER); set(sheet, 6, x++, "No", Style.S_TH_CENTER); if (!displayCageEachPhase) { set(sheet, 6, x++, "Container", Style.S_TH_CENTER); } Phase previousPhase = null; for (Phase phase : phases) { if (previousPhase == null) { set(sheet, 5, x, phase.getShortName() + (phase.getAbsoluteDate() != null ? "[" + FormatterUtils.formatDate(phase.getAbsoluteDate()) + "]" : ""), Style.S_TH_CENTER, 1, 1); if (displayCageEachPhase) set(sheet, 6, x++, "Container", Style.S_TH_CENTER); if (!displayCageEachPhase) set(sheet, 6, x++, "newTare", Style.S_TH_CENTER); } else { set(sheet, 5, x, " -> " + phase.getShortName() + (phase.getAbsoluteDate() != null ? " [" + FormatterUtils.formatDate(phase.getAbsoluteDate()) + "]" : ""), Style.S_TH_CENTER, 1, 2 + (displayCageEachPhase ? 4 : 2)); if (displayCageEachPhase) set(sheet, 6, x++, "ContainerId", Style.S_TH_CENTER); if (displayCageEachPhase) set(sheet, 6, x++, "Tare", Style.S_TH_CENTER); if (displayCageEachPhase) set(sheet, 6, x++, "Weight", Style.S_TH_CENTER); if (displayCageEachPhase) set(sheet, 6, x++, "days", Style.S_TH_CENTER); if (!displayCageEachPhase) set(sheet, 6, x++, "oldTare", Style.S_TH_CENTER); if (!displayCageEachPhase) set(sheet, 6, x++, "newTare", Style.S_TH_CENTER); set(sheet, 6, x++, "n", Style.S_TH_CENTER); set(sheet, 6, x++, "Cons.", Style.S_TH_CENTER); } previousPhase = phase; } int maxX = x - 1; // //Create table data int y = 7; Group previousGroup = null; ListHashMap<Group, Integer> group2Lines = new ListHashMap<>(); for (Biosample b : study.getParticipantsSorted()) { Group gr = b.getInheritedGroup(); group2Lines.add(gr, y); x = 0; set(sheet, y, x++, b.getInheritedGroupString(SpiritFrame.getUsername()), Style.S_TD_BOLD_LEFT); set(sheet, y, x++, b.getSampleId(), Style.S_TD_CENTER); set(sheet, y, x++, b.getSampleName(), Style.S_TD_CENTER); String containerId = null; if (!displayCageEachPhase) { //Display cage at time of death containerId = b.getContainerId(); if (containerId == null || containerId.length() == 0) { List<Biosample> history = mapHistory.get(b); for (Biosample h : history) { if (h.getContainerId() != null && h.getContainerId().length() > 0) { containerId = h.getContainerId(); break; } } } set(sheet, y, x++, containerId, Style.S_TD_BOLD_CENTER); } //data: Loop through phases previousPhase = null; for (Phase phase : phases) { if (displayCageEachPhase) { //Find the containerId of this sample at this date: containerId = getContainerAt(b, phase, fws, mapHistory.get(b)); } if (containerId == null || containerId.length() == 0) containerId = "??"; FoodWater fw = FoodWater.extract(fws, containerId, phase); FoodWater previousFW = fw == null ? null : fw.getPreviousFromList(fws, i == 1); Result r = b.getAuxResult(DAOTest.getTest(DAOTest.FOODWATER_TESTNAME), phase); ResultValue val = r == null || r.getOutputResultValues().size() < 2 ? null : i == 0 ? r.getOutputResultValues().get(0) : r.getOutputResultValues().get(1); String value = val == null ? null : val.getValue(); if (previousPhase == null) { if (displayCageEachPhase) set(sheet, y, x++, containerId, Style.S_TD_BOLD_CENTER); if (!displayCageEachPhase) set(sheet, y, x++, fw == null ? null : i == 0 ? fw.getFoodTare() : fw.getWaterTare(), Style.S_TD_DOUBLE1); } else { if (displayCageEachPhase) set(sheet, y, x++, containerId, Style.S_TD_BOLD_CENTER); if (displayCageEachPhase) set(sheet, y, x++, previousFW == null ? null : i == 0 ? previousFW.getFoodTare() : previousFW.getWaterTare(), Style.S_TD_DOUBLE1); set(sheet, y, x++, fw == null ? null : i == 0 ? fw.getFoodWeight() : fw.getWaterWeight(), Style.S_TD_DOUBLE1); if (displayCageEachPhase) set(sheet, y, x++, previousFW == null ? null : fw.getPhase().getDays() - previousFW.getPhase().getDays(), Style.S_TD_DOUBLE0); if (!displayCageEachPhase) set(sheet, y, x++, fw == null ? null : i == 0 ? fw.getFoodTare() : fw.getWaterTare(), Style.S_TD_DOUBLE1); set(sheet, y, x++, fw == null ? null : fw.getNAnimals(), Style.S_TD_DOUBLE0); set(sheet, y, x++, value, Style.S_TD_DOUBLE1_BLUE); } previousPhase = phase; } if (previousGroup != null && !previousGroup.equals(gr)) { drawLineAbove(sheet, y, 0, maxX, (short) 1); } previousGroup = gr; y++; } // y++; ////////////////////// AVERAGES x = 0; set(sheet, y + 1, x++, "Averages", Style.S_TH_CENTER); set(sheet, y + 1, x++, "", Style.S_TH_CENTER); set(sheet, y + 1, x++, "", Style.S_TH_CENTER); if (!displayCageEachPhase) set(sheet, y + 1, x++, "", Style.S_TH_CENTER); previousPhase = null; for (Phase phase : phases) { if (previousPhase == null) { set(sheet, y, x, phase.getShortName() + (phase.getAbsoluteDate() != null ? " [" + FormatterUtils.formatDate(phase.getAbsoluteDate()) + "]" : ""), Style.S_TH_CENTER); set(sheet, y + 1, x++, "", Style.S_TH_CENTER); } else { set(sheet, y, x, " -> " + phase.getShortName() + (phase.getAbsoluteDate() != null ? " [" + FormatterUtils.formatDate(phase.getAbsoluteDate()) + "]" : ""), Style.S_TH_CENTER, 1, 2 + (displayCageEachPhase ? 4 : 2)); for (int k = 0; k < (displayCageEachPhase ? 4 : 2); k++) { set(sheet, y + 1, x++, "", Style.S_TH_CENTER); } set(sheet, y + 1, x++, "", Style.S_TH_CENTER); set(sheet, y + 1, x++, "Cons.", Style.S_TH_CENTER); } previousPhase = phase; } y += 2; for (Group gr : study.getGroups()) { if (study.getParticipants(gr).size() == 0) continue; x = 0; set(sheet, y, x++, gr == null ? "N/A" : gr.getBlindedName(SpiritFrame.getUsername()), Style.S_TD_BOLD_LEFT); set(sheet, y, x++, "", Style.S_TD_LEFT); set(sheet, y, x++, "", Style.S_TD_LEFT); if (!displayCageEachPhase) set(sheet, y, x++, "", Style.S_TD_BOLD_LEFT); //data: Loop through phases previousPhase = null; for (Phase phase : phases) { List<Integer> lines = group2Lines.get(gr); if (previousPhase == null) { set(sheet, y, x, "", Style.S_TD_DOUBLE1); x += 1; } else { for (int k = 0; k < (displayCageEachPhase ? 4 : 2); k++) { set(sheet, y, x++, "", Style.S_TD_CENTER); } if (lines != null && lines.size() > 0) { int valcol = x + 1; set(sheet, y, x++, "", Style.S_TD_CENTER); setFormula(sheet, y, x++, "IF(COUNT(" + convertLinesToCells(lines, valcol) + ")>0, AVERAGE(" + convertLinesToCells(lines, valcol) + "), \"\")", Style.S_TD_DOUBLE1_BLUE); } else { set(sheet, y, x++, "", Style.S_TD_CENTER); set(sheet, y, x++, "", Style.S_TD_CENTER); } } previousPhase = phase; } y++; } POIUtils.autoSizeColumns(sheet); } } /** * Get the ContainerId of the given biosample at the given date * @param b * @param phase * @param fws * @param history * @return */ private String getContainerAt(Biosample b, Phase phase, Collection<FoodWater> fws, List<Biosample> history) { String containerId = ""; Map<String, Date> cage2fwDate = new HashMap<>(); for (FoodWater fw : FoodWater.extract(fws, phase)) { cage2fwDate.put(fw.getContainerId(), fw.getCreDate()); } Date d = null; containerId = ""; for (Biosample h : history) { String cid = h.getContainerId(); long refTime = cage2fwDate.get(cid) != null ? cage2fwDate.get(cid).getTime() : (phase.getAbsoluteDate().getTime() + 24 * 3600 * 1000L); if (h.getUpdDate().getTime() > refTime) continue; //skip cage change if it happened after the phase if (cid == null || cid.length() == 0 && h.getUpdDate().getTime() >= refTime) continue; //skip cage change to null if it happened at the phase (dead animal) if (d == null || h.getUpdDate().compareTo(d) > 0) { d = h.getUpdDate(); containerId = cid; } } return containerId; } public static void main(String[] args) throws Exception { Study study = DAOStudy.getStudyByStudyId("S-00715"); FoodWaterReport rep = new FoodWaterReport(); rep.populateReport(study); rep.export(null); } }