package de.open4me.depot.tools; import java.math.BigDecimal; import java.math.RoundingMode; import java.net.InetSocketAddress; import java.net.Proxy; import java.net.ProxySelector; import java.net.URI; import java.net.URISyntaxException; import java.rmi.RemoteException; import java.sql.Connection; import java.sql.PreparedStatement; import java.util.Date; import java.util.List; import de.open4me.depot.abruf.utils.Utils; import de.open4me.depot.gui.dialogs.KursAktualisierenAnbieterAuswahlDialog; import de.open4me.depot.gui.dialogs.KursAktualisierenDialog; import de.open4me.depot.messaging.KursUpdatesMsg; import de.open4me.depot.sql.GenericObjectSQL; import de.open4me.depot.sql.SQLUtils; import de.willuhn.jameica.system.Application; import de.willuhn.jameica.system.BackgroundTask; import de.willuhn.logging.Logger; import de.willuhn.util.ApplicationException; import de.willuhn.util.ProgressMonitor; import jsq.config.Config; import jsq.config.ConfigTuple; import jsq.datastructes.Const; import jsq.datastructes.Datacontainer; import jsq.fetch.factory.Factory; import jsq.fetcher.history.BaseFetcher; public class UpdateStock implements BackgroundTask { private GenericObjectSQL[] wertpapiere; private boolean forceNewSettings; private boolean abort = false; public UpdateStock(GenericObjectSQL[] context, boolean forceNewSettings) { this.wertpapiere = context; this.forceNewSettings = forceNewSettings; setProxy(); } private void setProxy() { boolean useSystem = Application.getConfig().getUseSystemProxy(); try { if (useSystem) { List<Proxy> proxies; proxies = ProxySelector.getDefault().select(new URI("https://www.willuhn.de/")); Logger.info("Using system proxy settings: " + proxies); for (Proxy p : proxies) { if (p.type() == Proxy.Type.HTTP && p.address() instanceof InetSocketAddress) { InetSocketAddress addr = (InetSocketAddress) p.address(); Factory.setProxy(addr.getHostString(), addr.getPort()); return; } } Logger.error("No default Proxy found"); } else { String host = Application.getConfig().getHttpsProxyHost(); int port = Application.getConfig().getHttpsProxyPort(); if (host != null && host.length() > 0 && port > 0) { Factory.setProxy(host, port); return; } } Logger.info("Keine gültige Proxy-Einstellunge gefunden. (" + useSystem + ")"); } catch (URISyntaxException e) { Logger.error("Keine gültige Proxy-Einstellunge gefunden", e); } } @Override public void run(ProgressMonitor monitor) throws ApplicationException { try { float proWert = 100.0f / wertpapiere.length; float babysteps = proWert / 5; for (int i = 0; i < wertpapiere.length; i++) { if (abort) { return; } GenericObjectSQL wertpapier = wertpapiere[i]; String wpid = wertpapier.getAttribute("id").toString(); String searchterm = getSearchTerm(wertpapier); String anbietername = getAnbieterName(wpid); monitor.setPercentComplete((int) (proWert * i)); monitor.setStatusText("Starte mit " + searchterm); Logger.info("Update Stock: Starte mit " + searchterm); BaseFetcher base; boolean manualWay = (anbietername == null || forceNewSettings); if (manualWay) { base = updateStock(monitor, babysteps, wertpapier, searchterm); } else { base = updateStockAutomatic(anbietername, monitor, babysteps, wertpapier, searchterm, wpid); } monitor.setPercentComplete((int) (monitor.getPercentComplete() + babysteps)); monitor.setStatusText("Speichern"); saveStockData(wertpapier, base); monitor.setStatusText("Ferting mit " + searchterm); Application.getMessagingFactory().sendMessage(new KursUpdatesMsg(wpid)); } } catch (ApplicationException e) { monitor.setStatus(ProgressMonitor.STATUS_ERROR); monitor.setStatusText(e.getMessage()); e.printStackTrace(); throw e; } catch (Exception e) { monitor.setStatus(ProgressMonitor.STATUS_ERROR); monitor.setStatusText(e.getMessage()); e.printStackTrace(); throw new ApplicationException("Fehler beim Abruf der Kurse." , e); } monitor.setStatusText("Fertig"); monitor.setStatus(ProgressMonitor.STATUS_DONE); monitor.setPercentComplete(101); } private String getSearchTerm(GenericObjectSQL wertpapier) throws RemoteException { String searchterm = null; if (!wertpapier.isEmpty("isin")) { searchterm = wertpapier.getAttribute("isin").toString(); } else if (!wertpapier.isEmpty("wkn")) { searchterm = wertpapier.getAttribute("wkn").toString(); } return searchterm; } private BaseFetcher updateStockAutomatic(String anbietername, ProgressMonitor monitor, float babysteps, GenericObjectSQL wertpapier, String searchterm, String wpid) throws Exception { Logger.debug("Gespeicherter Name: " + anbietername); BaseFetcher base = getFetcherByName(anbietername); if (base == null) { Logger.debug("Anbieter nicht gefunden."); doCleanSaveSettings(wpid); throw new ApplicationException("Fehler beim Abruf der Kurse. Bitte nochmal aktualisieren und Einstellungen neu vornehmen!"); } Logger.debug("Anbieter für Kursaktualisierung: " + base.getName()); Date d = new Date(); base.prepare(searchterm, 2000, 1, 1, d.getYear() + 1900, d.getMonth() + 1, d.getDate()); PreparedStatement getCfg = SQLUtils.getPreparedSQL("select value from depotviewer_cfgupdatestock where `wpid`= ? and `key` = ?"); getCfg.setString(1, wpid); while (base.hasMoreConfig()) { if (abort) { return null; } List<Config> cfgs = base.getConfigs(); monitor.setPercentComplete((int) (monitor.getPercentComplete() + babysteps)); monitor.setStatusText(cfgs.toString()); Logger.debug("Notwendige Configs: " + cfgs); for (Config cfg : cfgs) { Logger.debug("Workung on: " + cfg); getCfg.setString(2, cfg.getBeschreibung()); String ret = (String) SQLUtils.getObject(getCfg); if (ret == null) { doCleanSaveSettings(wpid); Logger.debug("Gespeicherter Wert: null"); throw new ApplicationException("Fehler beim Abruf der Kurse. Bitte nochmal aktualisieren und Einstellungen neu vornehmen!"); } ConfigTuple selected = null; for (ConfigTuple opts : cfg.getOptions()) { if (ret.equals(opts.getDescription().toString())) { selected = opts; break; } } if (selected == null) { doCleanSaveSettings(wpid); Logger.debug("Selected is null für " + cfg.getBeschreibung()); throw new ApplicationException("Fehler beim Abruf der Kurse. Bitte nochmal aktualisieren und Einstellungen neu vornehmen!"); } cfg.addSelectedOptions(selected); } base.process(cfgs); } return base; } private BaseFetcher getFetcherByName(String anbietername) { BaseFetcher base = null; for (BaseFetcher x :Factory.getHistoryFetcher()) { if (anbietername.equals(x.getName())) { base = x; break; } } return base; } private BaseFetcher updateStock(ProgressMonitor monitor, float babysteps, GenericObjectSQL wertpapier, String searchterm) throws RemoteException, Exception { BaseFetcher base; KursAktualisierenAnbieterAuswahlDialog dialog1 = new KursAktualisierenAnbieterAuswahlDialog(KursAktualisierenDialog.POSITION_CENTER, wertpapier.getAttribute("wertpapiername").toString()); base = (BaseFetcher) dialog1.open(); Boolean saveSettings = dialog1.getSpeichernSetting(); if (saveSettings) { doSaveAnbieter(wertpapier.getAttribute("id").toString(), base.getName()); } Date d = new Date(); base.prepare(searchterm, 2000, 1, 1, d.getYear() + 1900, d.getMonth() + 1, d.getDate()); while (base.hasMoreConfig()) { if (abort) { return null; } List<Config> cfg = base.getConfigs(); monitor.setPercentComplete((int) (monitor.getPercentComplete() + babysteps)); monitor.setStatusText(cfg.toString()); KursAktualisierenDialog dialog= new KursAktualisierenDialog(KursAktualisierenDialog.POSITION_CENTER, cfg); dialog.open(); base.process(cfg); if (saveSettings) { Logger.debug("Gespeicherte Config: " + cfg); doSaveSettings(wertpapier.getAttribute("id").toString(), cfg); } } return base; } // Speichert die Kursinformationen private static void saveStockData(GenericObjectSQL wertpapier, BaseFetcher base) throws Exception { // Kurse Connection conn = SQLUtils.getConnection(); PreparedStatement del = conn.prepareStatement("delete from depotviewer_kurse where wpid = ? "); del.setString(1, wertpapier.getID()); del.executeUpdate(); PreparedStatement insert = conn.prepareStatement("insert into depotviewer_kurse (wpid, kurs, kursw, kursdatum) values (?,?,?,?)"); for (Datacontainer dc : base.getHistQuotes()) { insert.setString(1, wertpapier.getID()); insert.setBigDecimal(2, (BigDecimal) dc.data.get("last")); insert.setString(3, (String) dc.data.get("currency")); insert.setDate(4, new java.sql.Date(((Date) dc.data.get("date")).getTime())); insert.addBatch(); } insert.executeBatch(); // Events del = conn.prepareStatement("delete from depotviewer_kursevent where wpid = ? "); del.setString(1, wertpapier.getID()); del.executeUpdate(); if (base.getHistEvents() != null) { insert = conn.prepareStatement("insert into depotviewer_kursevent (wpid, ratio, value, aktion, datum, waehrung) values (?,?,?,?,?,?)"); for (Datacontainer dc : base.getHistEvents()) { String action = (String) dc.data.get("action"); if (action.equals(Const.CASHDIVIDEND)) { action = "D"; } else if (action.equals(Const.STOCKDIVIDEND)) { action = "G"; } else if (action.equals(Const.STOCKSPLIT)) { action = "S"; } else if (action.equals(Const.SUBSCRIPTIONRIGHTS)) { action = "B"; } else { System.out.println("Warning: " + action + " is unknown!"); continue; } insert.setString(1, wertpapier.getID()); insert.setString(2, (String) dc.data.get("ratio")); insert.setBigDecimal(3, (BigDecimal) dc.data.get("value")); insert.setString(4, action); insert.setDate(5, new java.sql.Date(((Date) dc.data.get("date")).getTime())); insert.setString(6, (String) dc.data.get("currency")); insert.addBatch(); } insert.executeBatch(); } // PerformanceKurs calcPerformanceKurse(wertpapier, conn); Utils.markRecalc(null); } private static String getAnbieterName(String wpid) throws Exception { PreparedStatement pre = SQLUtils.getPreparedSQL("select value from depotviewer_cfgupdatestock where `wpid`= ? and `key` is null"); pre.setString(1, wpid); return (String) SQLUtils.getObject(pre); } private static void doSaveAnbieter(String string, String name) throws Exception { doCleanSaveSettings(string); PreparedStatement pre = SQLUtils.getPreparedSQL("insert into depotviewer_cfgupdatestock set `wpid`= ?, `key` = ?, `value` = ?"); pre.setString(1, string); pre.setString(2, null); pre.setString(3, name); pre.execute(); } private static void doCleanSaveSettings(String string) throws Exception { PreparedStatement pre = SQLUtils.getPreparedSQL("delete from depotviewer_cfgupdatestock where `wpid`= ?"); pre.setString(1, string); pre.execute(); } private static void doSaveSettings(String wpid, List<Config> cfg) throws Exception { PreparedStatement pre = SQLUtils.getPreparedSQL("insert into depotviewer_cfgupdatestock set `wpid`= ?, `key` = ?, `value` = ?"); for (Config c : cfg) { for (ConfigTuple sel : c.getSelected()) { pre.setString(1, wpid); pre.setString(2, c.getBeschreibung()); pre.setString(3, sel.getDescription()); pre.execute(); } } } private static void calcPerformanceKurse(GenericObjectSQL wertpapier, Connection conn) throws Exception { // Performance Kurs berechnen PreparedStatement update = conn.prepareStatement("update depotviewer_kurse set kursperf = ? where id = ?"); List<GenericObjectSQL> kurse = SQLUtils.getResultSet("select * from depotviewer_kurse where wpid = " + wertpapier.getID() + " order by kursdatum desc", "", "id"); Date lastKurs = null; if (kurse.size() > 0) { lastKurs = (Date) kurse.get(0).getAttribute("kursdatum"); } PreparedStatement queryKursEvet = SQLUtils.getPreparedSQL("select * from depotviewer_kursevent where wpid = ? and datum <= ? order by datum desc"); queryKursEvet.setString(1, wertpapier.getID()); queryKursEvet.setDate(2, SQLUtils.getSQLDate(lastKurs)); List<GenericObjectSQL> kursevt = SQLUtils.getResultSet(queryKursEvet, "depotviewer_kursevent", "", "id"); int kurseEvtIdx = 0; GenericObjectSQL currentEvt = null; if (kursevt.size() > 0 ) { currentEvt = kursevt.get(kurseEvtIdx); } BigDecimal korrektur = new BigDecimal("0.0000"); BigDecimal faktor = new BigDecimal("1.0000"); for (GenericObjectSQL kurs : kurse) { if (kurseEvtIdx < kursevt.size()) { Date kursdatum = (Date) kurs.getAttribute("kursdatum"); Date evtdatum = (Date) currentEvt.getAttribute("datum"); if (evtdatum.getTime() > kursdatum.getTime()) { String action = currentEvt.getAttribute("aktion").toString(); if (action.equals("D")) { korrektur = korrektur.subtract(faktor.multiply((BigDecimal) currentEvt.getAttribute("value"))); } else if (action.equals("S")) { String[] s = ((String) currentEvt.getAttribute("ratio")).split(":"); BigDecimal splitfaktor = (new BigDecimal(s[0])).divide(new BigDecimal(s[1]), 10, RoundingMode.HALF_UP); faktor = faktor.multiply(splitfaktor); } else if (action.equals("G")) { String[] s = ((String) currentEvt.getAttribute("ratio")).split(":"); BigDecimal splitfaktor = (new BigDecimal(s[0])).divide((new BigDecimal(s[1])).add(new BigDecimal(s[0])), 10, RoundingMode.HALF_UP); faktor = faktor.multiply(splitfaktor); } kurseEvtIdx++; if (kurseEvtIdx < kursevt.size()) { currentEvt = kursevt.get(kurseEvtIdx); } } } BigDecimal k = faktor.multiply((BigDecimal) kurs.getAttribute("kurs")); k = k.add(korrektur); update.setBigDecimal(1, k); update.setString(2, kurs.getID()); update.addBatch();; } update.executeBatch(); } @Override public void interrupt() { abort = true; } @Override public boolean isInterrupted() { return false; } }