/* This file is part of JLucrum. JLucrum 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. JLucrum 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 JLucrum. If not, see <http://www.gnu.org/licenses/>. */ package org.jlucrum.datafetcher; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.params.ClientPNames; import org.apache.http.client.params.CookiePolicy; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.protocol.HTTP; import org.apache.http.util.EntityUtils; import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; /** * * @author Evgeni Kappinen */ public class FetcherNasdaqOmxNordic implements MarketFetcher { private DefaultHttpClient httpclient = null; private String url = "http://www.nasdaqomxnordic.com/webproxy/DataFeedProxy.aspx"; private final Map<String, String> stockMap = new HashMap<String, String>(); private final DateTimeFormatter dateFormatter = DateTimeFormat.forPattern("yyyy-MM-dd"); private boolean debug = false; private static int dataMap[] = { 4, 6, 2, 3, 5, 7, 8}; private SourceCache cache = null; public FetcherNasdaqOmxNordic() { //http://en.wikipedia.org/wiki/OMX_Helsinki_25 stockMap.put("Cargotec Oyj", "HEX29983"); stockMap.put("Elisa Oyj", "HEX24254"); stockMap.put("Fortum Oyj", "HEX24271"); stockMap.put("Kemira Oyj", "HEX24292"); stockMap.put("KONE Oyj", "HEX29981"); stockMap.put("Konecranes Oyj", "HEX24284"); stockMap.put("Metso Oyj", "HEX24302"); stockMap.put("Neste Oil", "HEX29375"); stockMap.put("Nokia Oyj", "HEX24311"); stockMap.put("Nokian Renkaat Oyj", "HEX24312"); stockMap.put("Nordea Bank AB", "HEX24308"); stockMap.put("Outokumpu Oyj", "HEX24321"); stockMap.put("Outotec Oyj", "HEX36695"); stockMap.put("Pohjola Bank A", "HEX24316"); stockMap.put("Rautaruukki Oyj", "HEX24342"); stockMap.put("Sampo Oyj A", "HEX24346"); stockMap.put("Sanoma Oyj", "HEX24366"); stockMap.put("Stora Enso Oyj A", "HEX24359"); stockMap.put("Stora Enso Oyj R", "HEX24360"); stockMap.put("TeliaSonera AB", "HEX24381"); stockMap.put("Tieto Oyj", "HEX24376"); stockMap.put("UPM-Kymmene Oyj", "HEX24386"); stockMap.put("Wärtsilä Corporation", "HEX24394"); stockMap.put("YIT Oyj", "HEX24397"); cache = SourceCache.getInstance(stockMap.size()); } private DefaultHttpClient getClient() { if (httpclient != null) { return httpclient; } httpclient = new DefaultHttpClient(); httpclient.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.BROWSER_COMPATIBILITY); return httpclient; } public Map<String, Double> getData(String name, DateTime fromDate, DateTime toDate, int type) { HttpPost httpPost = new HttpPost(this.url); HttpResponse response = null; HashMap<String, Double> retMap = new HashMap<String, Double>(); httpclient = getClient(); List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(); String fixedName = stockMap.get(name); if (fixedName == null) { fixedName = name; } nameValuePairs.add(new BasicNameValuePair("xmlquery", "<post> " + "<param name=\"SubSystem\" value=\"History\"/> " + "<param name=\"Action\" value=\"GetDataSeries\"/>" + "<param name=\"AppendIntraDay\" value=\"no\"/>" + "<param name=\"Instrument\" value=\"" + fixedName + "\"/>" + "<param name=\"FromDate\" value=\"" + dateFormatter.print(fromDate) + "\"/>" + "<param name=\"ToDate\" value=\"" + dateFormatter.print(toDate) + "\"/> " + "<param name=\"hi__a\" value=\"0,1,2,4,21,8,10,11,12,9\"/> " + "<param name=\"ext_xslt\" value=\"/nordicV3/hi_table_shares_adjusted.xsl\"/> " + "<param name=\"ext_xslt_options\" value=\",undefined,\"/> " + "<param name=\"ext_xslt_lang\" value=\"en\"/> " + "<param name=\"ext_xslt_hiddenattrs\" value=\",ip,iv,\"/> " + "<param name=\"ext_xslt_tableId\" value=\"historicalTable\"/> " + "<param name=\"app\" value=\"/osakkeet/Historialliset_kurssitiedot/\"/> " + "</post>")); try { Document doc = (Document) cache.getData(fixedName, fromDate.toString(), toDate.toString()); if (doc == null) { httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, HTTP.UTF_8)); response = httpclient.execute(httpPost); HttpEntity entity = response.getEntity(); String resString = EntityUtils.toString(entity, "UTF-8"); if (debug) { System.out.printf("Respond:%s", resString); } doc = Jsoup.parse(resString); cache.putData(fixedName, fromDate.toString(), toDate.toString(), doc); System.out.printf("Fetched from network:%s\n", name); } Elements elems = doc.select("tr"); Iterator<Element> iter = elems.iterator(); iter.next(); //skip head while(iter.hasNext()) { Element elem = iter.next(); Elements dataElems = elem.getAllElements(); /* Output Example: <tr id="historicalTable-"> <td>2011-09-08</td> <td>25.29</td> <td>24.38</td> <td>24.93</td> <td>24.92</td> <td>895,389</td> <td>22,298,455</td> <td>5,524</td> </tr> */ Element dateElem = dataElems.get(1); Element dataElem = dataElems.get(dataMap[type]); if (dateElem.html() == null || dateElem.html().length() == 0|| dataElem.html() == null || dataElem.html().length() == 0) { continue; } retMap.put(dateElem.html(), Double.valueOf(dataElem.html().replaceAll(",", ""))); if (debug) { System.out.printf("Date:%s data:%s\n", dateElem.html(), dataElem.html()); } } System.out.printf("Fetched %s/%s from NasdaqOmxNordic:%d\n", name, fixedName, retMap.size()); } catch (IOException ex) { Logger.getLogger(FetcherNasdaqOmxNordic.class.getName()).log(Level.SEVERE, null, ex); } return retMap; } @Override public Map<String, Double> fetchDataPeriod(String name, DateTime fromDate, DateTime toDate, int type) { return this.getData(name, fromDate, toDate, type); } @Override public Double fetchData(String name, DateTime date, int type) { throw new UnsupportedOperationException("Not supported yet."); } public static void main(String av[]) { FetcherNasdaqOmxNordic fetcher = new FetcherNasdaqOmxNordic(); fetcher.getData("Metso Oyj", new DateTime().minusDays(120), new DateTime(), 4); } }