/* * Copyright (C) 2017 John Garner * * 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/>. */ package com.pikatimer.race; import com.pikatimer.timing.Segment; import com.pikatimer.timing.Split; import com.pikatimer.util.HibernateUtil; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.CountDownLatch; import java.util.logging.Level; import java.util.logging.Logger; import javafx.beans.Observable; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import org.hibernate.Session; /** * * @author jcgarner */ public class RaceDAO { private static final ObservableList<Race> raceList =FXCollections.observableArrayList( e -> new Observable[] {e.raceNameProperty()}); private static final ObservableList<Wave> waveList =FXCollections.observableArrayList(Wave.extractor()); private static final Map<Integer,Wave> waveMap = new HashMap(); private Map<Integer,Split> splitMap = new HashMap(); // This is mostly precautionary just in case we put the initial race // loading into a background thread for whatever reason final CountDownLatch racesLoadedLatch = new CountDownLatch(1); public Split getSplitByID(Integer splitID) { return splitMap.get(splitID); } /** * SingletonHolder is loaded on the first execution of Singleton.getInstance() * or the first access to SingletonHolder.INSTANCE, not before. */ private static class SingletonHolder { private static final RaceDAO INSTANCE = new RaceDAO(); } public static RaceDAO getInstance() { return SingletonHolder.INSTANCE; } public void addRace(Race r) { Session s=HibernateUtil.getSessionFactory().getCurrentSession(); s.beginTransaction(); s.save(r); s.getTransaction().commit(); raceList.add(r); } public void addSplit (Split w) { Race r = w.getRace(); Session s=HibernateUtil.getSessionFactory().getCurrentSession(); s.beginTransaction(); s.save(w); s.getTransaction().commit(); r.addSplit(w); //System.out.println("Adding Split id: " + w.getID() + "to" + w.getRace().getRaceName()); updateSplitOrder(r); splitMap.put(w.getID(), w); } private void refreshRaceList() { List<Race> list = new ArrayList<>(); Session s=HibernateUtil.getSessionFactory().getCurrentSession(); s.beginTransaction(); //System.out.println("RacedAO.refreshRaceList() Starting the query"); try { list=s.createQuery("from Race order by ID").list(); if (list != null) list.forEach(r -> { AgeGroups ag = r.getAgeGroups(); if (ag != null) ag.getCustomIncrementsList(); }); } catch (Exception e) { System.out.println(e.getMessage()); } s.getTransaction().commit(); //System.out.println("RaceDAO::refreshRaceList() Returning the list"); if(!raceList.isEmpty()) raceList.clear(); raceList.addAll(list); splitMap = new HashMap(); raceList.forEach(r -> r.getSplits().forEach(sp -> splitMap.put(sp.getID(),sp))); racesLoadedLatch.countDown(); } public ObservableList<Race> listRaces() { if(raceList.size() < 1) refreshRaceList(); return raceList; } public void addWave(Wave w) { if (w.getRace() != null) w.getRace().addWave(w); Session s=HibernateUtil.getSessionFactory().getCurrentSession(); s.beginTransaction(); s.save(w); s.getTransaction().commit(); //System.out.println("Adding Wave id: " + w.getID() + "to" + w.getRace().getRaceName()); waveList.add(w); waveMap.put(w.getID(), w); } public void removeWave(Wave w) { w.getRace().removeWave(w); //refreshWaveList(); //System.out.println("removeWaves before: waveList.size()= " + waveList.size()); //System.out.println("Wave: " + w.idProperty()); waveList.forEach(e -> {System.out.println("Possible: " + e.idProperty() + " " + e.equals(w));}); Boolean res = waveList.remove(w); Wave remove = waveMap.remove(w.getID()); //System.out.println("removeWaves after: waveList.size()= " + waveList.size() + " result: " + res); Session s=HibernateUtil.getSessionFactory().getCurrentSession(); s.beginTransaction(); s.delete(w); s.getTransaction().commit(); } public void updateWave (Wave w) { Session s=HibernateUtil.getSessionFactory().getCurrentSession(); s.beginTransaction(); s.update(w); s.getTransaction().commit(); //refreshWaveList(); } public Wave getWaveByID(int id) { //System.out.println("getWaveByID: racesLoadedLatch is now " + racesLoadedLatch.getCount()); try { racesLoadedLatch.await(); } catch (InterruptedException ex) { Logger.getLogger(RaceDAO.class.getName()).log(Level.SEVERE, null, ex); } if (waveMap.isEmpty()) refreshWaveList(); return waveMap.get(id); } public Race getRaceByID (int id){ ObjectProperty<Race> result = new SimpleObjectProperty(); listRaces().forEach(r -> { if (r.getID().intValue() == id) result.set(r); }); return result.get(); } public void refreshWaveList() { if (waveMap.isEmpty()) { waveList.clear(); waveMap.clear(); raceList.forEach( r -> { waveList.addAll(r.getWaves()); }); waveList.forEach(w -> { waveMap.put(w.getID(), w); }); } } public ObservableList<Wave> listWaves() { if(waveList.isEmpty()) refreshWaveList(); //System.out.println("ListWaves for " + waveList.size()); //refreshWaveList(); return waveList; } public void removeRace(Race r) { raceList.remove(r); waveList.removeAll(r.getWaves()); r.getWaves().forEach(w -> waveMap.remove(w.getID())); r.getSplits().forEach(sp -> splitMap.remove(sp.getID())); Session s=HibernateUtil.getSessionFactory().getCurrentSession(); s.beginTransaction(); s.delete(r); s.getTransaction().commit(); } public void removeSplit(Split w) { splitMap.remove(w.getID()); Race r = w.getRace(); r.removeSplit(w); Session s=HibernateUtil.getSessionFactory().getCurrentSession(); s.beginTransaction(); s.delete(w); s.getTransaction().commit(); updateSplitOrder(r); } public void clearAll() { removeRaces(raceList); addRace(new Race()); } public void removeRaces(ObservableList<Race> removeList) { Session s=HibernateUtil.getSessionFactory().getCurrentSession(); s.beginTransaction(); int count = 0; Iterator<Race> deleteMeIterator = removeList.iterator(); while (deleteMeIterator.hasNext()) { Race p = deleteMeIterator.next(); s.delete(p); if ( ++count % 20 == 0 ) { //flush a batch of updates and release memory: s.flush(); s.clear(); } } s.getTransaction().commit(); //Platform.runLater(() -> { refreshRaceList(); // }); } public void updateRace(Race tl) { Session s=HibernateUtil.getSessionFactory().getCurrentSession(); s.beginTransaction(); s.update(tl); s.getTransaction().commit(); } public void updateAwardCategory(AwardCategory a){ Session s=HibernateUtil.getSessionFactory().getCurrentSession(); s.beginTransaction(); s.saveOrUpdate(a); s.getTransaction().commit(); } public void removeAwardCategory(AwardCategory a){ Session s=HibernateUtil.getSessionFactory().getCurrentSession(); s.beginTransaction(); s.delete(a); s.getTransaction().commit(); } public void updateSplit (Split sp) { Session s=HibernateUtil.getSessionFactory().getCurrentSession(); s.beginTransaction(); s.update(sp); s.getTransaction().commit(); } public void updateSplitOrder(Race r) { Session s=HibernateUtil.getSessionFactory().getCurrentSession(); s.beginTransaction(); r.splitsProperty().stream().forEach((item) -> { //System.out.println(self.getRaceName() + " has " + item.getSplitName() + " at " + raceSplits.indexOf(item)); item.splitPositionProperty().set(r.splitsProperty().indexOf(item)+1); s.update(item); }); s.getTransaction().commit(); } public void updateSegment(Segment seg){ Session s=HibernateUtil.getSessionFactory().getCurrentSession(); s.beginTransaction(); s.saveOrUpdate(seg); s.getTransaction().commit(); } public void removeSegment (Segment seg) { Race r = seg.getRace(); r.removeRaceSegment(seg); Session s=HibernateUtil.getSessionFactory().getCurrentSession(); s.beginTransaction(); s.delete(seg); s.getTransaction().commit(); updateSplitOrder(r); } }