Mercurial > lada > lada-server
view src/main/java/de/intevation/lada/factory/ProbeFactory.java @ 1324:212fe0cfd694 release-2.5
Use correct ort to generate probe.
author | Raimund Renkert <raimund.renkert@intevation.de> |
---|---|
date | Fri, 24 Mar 2017 11:59:19 +0100 |
parents | 9dfb52db6a0f |
children |
line wrap: on
line source
/* Copyright (C) 2013 by Bundesamt fuer Strahlenschutz * Software engineering by Intevation GmbH * * This file is Free Software under the GNU GPL (v>=3) * and comes with ABSOLUTELY NO WARRANTY! Check out * the documentation coming with IMIS-Labordaten-Application for details. */ package de.intevation.lada.factory; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Hashtable; import javax.inject.Inject; import org.apache.log4j.Logger; import de.intevation.lada.model.land.KommentarP; import de.intevation.lada.model.land.Messprogramm; import de.intevation.lada.model.land.MessprogrammMmt; import de.intevation.lada.model.land.Probe; import de.intevation.lada.model.land.Messung; import de.intevation.lada.model.land.Messwert; import de.intevation.lada.model.land.Ortszuordnung; import de.intevation.lada.model.land.OrtszuordnungMp; import de.intevation.lada.model.land.StatusProtokoll; import de.intevation.lada.model.stammdaten.DeskriptorUmwelt; import de.intevation.lada.model.stammdaten.Deskriptoren; import de.intevation.lada.model.stammdaten.Ort; import de.intevation.lada.util.annotation.RepositoryConfig; import de.intevation.lada.util.data.QueryBuilder; import de.intevation.lada.util.data.Repository; import de.intevation.lada.util.data.RepositoryType; import de.intevation.lada.util.rest.Response; /** * This factory creates probe objects and its children using a messprogramm * as template. * * @author <a href="mailto:rrenkert@intevation.de">Raimund Renkert</a> */ public class ProbeFactory { // Day of year representing February 28 private static final int FEBRUARY_28 = 58; private static Hashtable<String, int[]> fieldsTable; public ProbeFactory() { int[] T = { Calendar.DAY_OF_YEAR, Calendar.DAY_OF_YEAR, 1 }; int[] W = { Calendar.DAY_OF_YEAR, Calendar.DAY_OF_YEAR, 7 }; int[] W2 = { Calendar.DAY_OF_YEAR, Calendar.DAY_OF_YEAR, 14 }; int[] W4 = { Calendar.DAY_OF_YEAR, Calendar.DAY_OF_YEAR, 28 }; int[] M = { Calendar.MONTH, Calendar.DAY_OF_MONTH, 1 }; int[] Q = { Calendar.MONTH, Calendar.DAY_OF_MONTH, 3 }; int[] H = { Calendar.MONTH, Calendar.DAY_OF_MONTH, 6 }; int[] J = { Calendar.YEAR, Calendar.DAY_OF_YEAR, 1 }; fieldsTable = new Hashtable<String, int[]>(); fieldsTable.put("T", T); fieldsTable.put("W", W); fieldsTable.put("W2", W2); fieldsTable.put("W4", W4); fieldsTable.put("M", M); fieldsTable.put("Q", Q); fieldsTable.put("H", H); fieldsTable.put("J", J); } private class Intervall { private final int teilVon; private final int teilBis; private final int offset; private final int intervallField; private final int subIntField; private final int intervallFactor; private Calendar from; public Intervall( Messprogramm messprogramm, Calendar start ) { this.teilVon = messprogramm.getTeilintervallVon(); this.teilBis = messprogramm.getTeilintervallBis(); this.offset = messprogramm.getIntervallOffset(); this.intervallField = fieldsTable .get(messprogramm.getProbenintervall())[0]; this.subIntField = fieldsTable .get(messprogramm.getProbenintervall())[1]; this.intervallFactor = fieldsTable .get(messprogramm.getProbenintervall())[2]; this.from = (Calendar)start.clone(); /* Align with beginning of next interval * like first day of next quarter or Monday of next week.*/ if (intervallField == Calendar.DAY_OF_YEAR && intervallFactor % 7 == 0 ) { if (from.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) { from.add(Calendar.WEEK_OF_YEAR, 1); from.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); } } else { int startIntField = start.get(intervallField); from.set( intervallField, startIntField + startIntField % intervallFactor ); } from = adjustSubIntField(from, teilVon); if (start.after(from)) { // to next intervall if start not at first day of intervall this.roll(); } } /** * Return given calendar adjusted to start of intervall (e.g. first * day in quarter) plus offset and given amount of days. * * @param cal Calendar to be adjusted * @param int amount of days to be added (plus offset) * * @return the adjusted Calendar object. */ private Calendar adjustSubIntField(Calendar cal, int teil) { int intValue = cal.get(intervallField); int adjust = offset; if (intervallField != subIntField) { intValue = intValue - intValue % intervallFactor; cal.set(intervallField, intValue); if (subIntField == Calendar.DAY_OF_YEAR) { // Adjust in leap year teil += startInLeapYear() && teil > FEBRUARY_28 ? 1 : 0; } } else { adjust += intValue - 1; } int subIntValue = adjust + Math.min(teil, getDuration()); cal.set(subIntField, subIntValue); return cal; } /** * @return sum of actual maxima for subIntField from beginning of * actual intervall for the next intervallFactor values intervallField * or just intervallFactor, if subIntField == intervallField. */ private int getDuration() { if (subIntField == intervallField) { return intervallFactor; } int duration = 0; Calendar tmp = (Calendar)from.clone(); /* reset to beginning of intervall, e.g. first day of quarter * to compensate possible overflow if * teilVon > maximum of intervallField: */ int intValue = from.get(intervallField); tmp.set( intervallField, intValue - intValue % intervallFactor ); tmp.set(subIntField, tmp.getActualMinimum(subIntField)); for (int i = 0; i < intervallFactor; i++) { duration += tmp.getActualMaximum(subIntField); tmp.add(intervallField, 1); } return duration; } public Date getFrom() { return from.getTime(); } public Date getTo() { Calendar to = (Calendar)from.clone(); to = adjustSubIntField(to, teilBis); return to.getTime(); } public boolean startInLeapYear() { return from.getActualMaximum(Calendar.DAY_OF_YEAR) > 365; } public int getStartDOY() { return from.get(Calendar.DAY_OF_YEAR); } public void roll() { from.add(intervallField, intervallFactor); from = adjustSubIntField(from, teilVon); } } // end Intervall class @Inject Logger logger; /** * The data repository */ @Inject @RepositoryConfig(type = RepositoryType.RW) private Repository repository; /** * Create a list of probe objects * * @param id Messprogramm id * @param from The start date * @param to The end date * * @return List of probe objects. */ public List<Probe> create(Messprogramm messprogramm, Long from, Long to) { Calendar start = Calendar.getInstance(); start.setTimeInMillis(from); Calendar end = Calendar.getInstance(); end.setTimeInMillis(to); /* Adjust to end of the day as we want to generate Probe objects * before or at this day. */ end.set(Calendar.HOUR_OF_DAY, 23); end.set(Calendar.MINUTE, 59); end.set(Calendar.SECOND, 59); int gueltigVon = messprogramm.getGueltigVon(); int gueltigBis = messprogramm.getGueltigBis(); List<Probe> proben = new ArrayList<Probe>(); for (Intervall intervall = new Intervall(messprogramm, start); intervall.getFrom().before(end.getTime()); intervall.roll() ) { /* Leap year adaption of validity period. * It is assumed here (and should be enforced by the data model) * that gueltigVon and gueltigBis are always given relative to * a non-leap year. E.g. a value of 59 is assumed to denote * March 1 and thus has to be adapted in a leap year. */ int leapDay = intervall.startInLeapYear() ? 1 : 0; int actualGueltigVon = gueltigVon > FEBRUARY_28 ? gueltigVon + leapDay : gueltigVon; int actualGueltigBis = gueltigBis > FEBRUARY_28 ? gueltigBis + leapDay : gueltigBis; int solldatumBeginnDOY = intervall.getStartDOY(); if (( // Validity within one year actualGueltigVon < actualGueltigBis && solldatumBeginnDOY >= actualGueltigVon && solldatumBeginnDOY <= actualGueltigBis ) || ( // Validity over turn of the year actualGueltigVon > actualGueltigBis && (solldatumBeginnDOY >= actualGueltigVon || solldatumBeginnDOY <= actualGueltigBis) ) ) { Probe probe = createObjects( messprogramm, intervall.getFrom(), intervall.getTo() ); if (probe != null) { proben.add(probe); } } } return proben; } /** * Create a single probe object. * * @param messprogramm The messprogramm containing probe details * @param startDate The date for 'solldatumbeginn' * @param endDate The date for 'solldatumende' * * @return The new probe object. */ private Probe createObjects( Messprogramm messprogramm, Date startDate, Date endDate ) { QueryBuilder<Probe> builderProbe = new QueryBuilder<Probe>( repository.entityManager("land"), Probe.class); builderProbe.and("mprId", messprogramm.getId()); builderProbe.and("solldatumBeginn", startDate); builderProbe.and("solldatumEnde", endDate); List<Probe> proben = repository.filterPlain(builderProbe.getQuery(), "land"); if (!proben.isEmpty()) { return null; } Probe probe = new Probe(); probe.setBaId(messprogramm.getBaId()); probe.setDatenbasisId(messprogramm.getDatenbasisId()); probe.setMediaDesk(messprogramm.getMediaDesk()); probe.setMstId(messprogramm.getMstId()); probe.setLaborMstId(messprogramm.getLaborMstId()); probe.setProbenartId(messprogramm.getProbenartId()); probe.setProbeNehmerId(messprogramm.getProbeNehmerId()); probe.setSolldatumBeginn(new Timestamp(startDate.getTime())); probe.setSolldatumEnde(new Timestamp(endDate.getTime())); probe.setTest(messprogramm.getTest()); probe.setUmwId(messprogramm.getUmwId()); probe.setMprId(messprogramm.getId()); repository.create(probe, "land"); if (messprogramm.getProbeKommentar() != null && !messprogramm.getProbeKommentar().equals("")) { KommentarP kommentar = new KommentarP(); kommentar.setDatum(new Timestamp(new Date().getTime())); kommentar.setProbeId(probe.getId()); kommentar.setText(messprogramm.getProbeKommentar()); kommentar.setMstId(messprogramm.getMstId()); repository.create(kommentar, "land"); } QueryBuilder<MessprogrammMmt> builder = new QueryBuilder<MessprogrammMmt>( repository.entityManager("land"), MessprogrammMmt.class); builder.and("messprogrammId", messprogramm.getId()); Response response = repository.filter(builder.getQuery(), "land"); @SuppressWarnings("unchecked") List<MessprogrammMmt> mmts = (List<MessprogrammMmt>)response.getData(); for (int i = 0; i < mmts.size(); i++) { MessprogrammMmt mmt = mmts.get(i); Messung messung = new Messung(); messung.setFertig(false); messung.setGeplant(true); messung.setMmtId(mmt.getMmtId()); messung.setNebenprobenNr( messprogramm.getMstId() + mmt.getMmtId()); messung.setProbeId(probe.getId()); repository.create(messung, "land"); for (int mw : mmt.getMessgroessen()) { Messwert wert = new Messwert(); wert.setMessgroesseId(mw); wert.setMessungsId(messung.getId()); wert.setMesswert(0d); wert.setMehId(1); repository.create(wert, "land"); } } QueryBuilder<OrtszuordnungMp> builderOrt = new QueryBuilder<OrtszuordnungMp>( repository.entityManager("land"), OrtszuordnungMp.class); builderOrt.and("messprogrammId", messprogramm.getId()); List<OrtszuordnungMp> orte = repository.filterPlain(builderOrt.getQuery(), "land"); for (OrtszuordnungMp ort : orte) { Ortszuordnung ortP = new Ortszuordnung(); ortP.setOrtszuordnungTyp(ort.getOrtszuordnungTyp()); ortP.setProbeId(probe.getId()); ortP.setOrtId(ort.getOrtId()); ortP.setOrtszusatztext(ort.getOrtszusatztext()); repository.create(ortP, "land"); } // Reolad the probe to have the old id probe = (Probe)repository.getById( Probe.class, probe.getId(), "land").getData(); return probe; } /** * Search for the umwelt id using the 'deskriptor'. * * @param probe The probe object. * * @return The updated probe object. */ public Probe findUmweltId(Probe probe) { String mediaDesk = probe.getMediaDesk(); if (mediaDesk != null) { String[] mediaDeskParts = mediaDesk.split(" "); if (mediaDeskParts.length <= 1) { return probe; } probe.setUmwId(findUmwelt(mediaDeskParts)); } return probe; } /** * Search for the media description using the 'deskriptor'. * * @param probe The probe object * * @return The updated probe object. */ public Probe findMediaDesk(Probe probe) { String mediaDesk = probe.getMediaDesk(); if (mediaDesk != null) { Object result = repository.queryFromString( "SELECT get_media_from_media_desk( :mediaDesk );", "stamm") .setParameter("mediaDesk", mediaDesk) .getSingleResult(); probe.setMedia(result != null ? result.toString() : ""); } return probe; } /** * Search for the umwelt id using the 'deskriptor'. * * @param messprogramm The messprogramm * * @return The updated messprogramm. */ public Messprogramm findUmweltId(Messprogramm messprogramm) { String mediaDesk = messprogramm.getMediaDesk(); if (mediaDesk != null) { String[] mediaDeskParts = mediaDesk.split(" "); if (mediaDeskParts.length <= 1) { return messprogramm; } messprogramm.setUmwId(findUmwelt(mediaDeskParts)); } return messprogramm; } /** * Find the umwelt id for a given deskriptor. * * @param mediaDesk The deskriptor string * * @return The umwelt id or an empty string. */ private String findUmwelt(String[] mediaDesk) { List<Integer> mediaIds = new ArrayList<Integer>(); boolean zebs = false; Integer parent = null; Integer hdParent = null; Integer ndParent = null; if ("01".equals(mediaDesk[1])) { zebs = true; } for (int i = 1; i < mediaDesk.length; i++) { if ("00".equals(mediaDesk[i])) { mediaIds.add(-1); continue; } if (zebs && i < 5) { parent = hdParent; } else if (!zebs && i < 3) { parent = hdParent; } else { parent = ndParent; } QueryBuilder<Deskriptoren> builder = new QueryBuilder<Deskriptoren>( repository.entityManager("stamm"), Deskriptoren.class); if (parent != null) { builder.and("vorgaenger", parent); } builder.and("sn", mediaDesk[i]); builder.and("ebene", i - 1); Response response = repository.filter(builder.getQuery(), "stamm"); @SuppressWarnings("unchecked") List<Deskriptoren> data = (List<Deskriptoren>)response.getData(); if (data.isEmpty()) { return ""; } hdParent = data.get(0).getId(); mediaIds.add(data.get(0).getId()); if (i == 2) { ndParent = data.get(0).getId(); } } return getUmwelt(mediaIds, zebs); } /** * Find the umwelt id in the database using media deskriptor ids. * * @param media The list of media ids. * @param isZebs Flag for type of the deskriptor. * * @return The umwelt id or an empty string. */ private String getUmwelt(List<Integer> media, boolean isZebs) { QueryBuilder<DeskriptorUmwelt> builder = new QueryBuilder<DeskriptorUmwelt>( repository.entityManager("stamm"), DeskriptorUmwelt.class); if (media.size() == 0) { return ""; } int size = 1; for (int i = size; i >= 0; i--) { if (media.get(i) == -1) { continue; } String field = "s" + (i > 9 ? i : "0" + i); builder.and(field, media.get(i)); } Response response = repository.filter(builder.getQuery(), "stamm"); @SuppressWarnings("unchecked") List<DeskriptorUmwelt> data = (List<DeskriptorUmwelt>)response.getData(); if (data.isEmpty()) { return null; } boolean unique = isUnique(data); if (unique) { return data.get(0).getUmwId(); } else { int found = -1; for (int i = 0; i < data.size(); i++) { int matches = 0; int lastMatch = 0; for (int j = size + 1; j < 12; j++) { switch(j) { case 2: if (media.get(2).equals(data.get(i).getS02())) matches += 1; break; case 3: if (media.get(3).equals(data.get(i).getS03())) matches += 1; break; case 4: if (media.get(4).equals(data.get(i).getS04())) matches += 1; break; case 5: if (media.get(5).equals(data.get(i).getS05())) matches +=1; break; case 6: if (media.get(6).equals(data.get(i).getS06())) matches += 1; break; case 7: if (media.get(7).equals(data.get(i).getS07())) matches += 1; break; case 8: if (media.get(8).equals(data.get(i).getS08())) matches += 1; break; case 9: if (media.get(9).equals(data.get(i).getS09())) matches += 1; break; case 10: if (media.get(10).equals(data.get(i).getS10())) matches += 1; break; case 11: if (media.get(11).equals(data.get(i).getS11())) matches += 1; break; } if (matches > lastMatch) { lastMatch = matches; found = i; } } if (found >= 0) { return data.get(found).getUmwId(); } } return null; } } /** * Determine if the entries in the list have the same umwelt id. * * @param list A list of DescriptorUmwelt objects. * * @return true if the objects have the same umwelt id else false. */ private boolean isUnique(List<DeskriptorUmwelt> list) { if (list.isEmpty()) { return false; } String element = list.get(0).getUmwId(); for (int i = 1; i < list.size(); i++) { if (!element.equals(list.get(i))) { return false; } } return true; } }