📄 yahoostockserver.java
字号:
/*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Copyright (C) 2008 Yan Cheng Cheok <yccheok@yahoo.com>
*/
package org.yccheok.jstock.engine;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
*
* @author yccheok
*/
public class YahooStockServer extends Subject<YahooStockServer, Integer> implements StockServer {
public YahooStockServer(Country country) {
this.country = country;
baseURL = YahooStockServer.servers.get(country);
if(baseURL == null) {
throw new java.lang.IllegalArgumentException("Illegal country as argument (" + country +")");
}
}
@Override
public Stock getStock(Symbol symbol) throws StockNotFoundException {
final StringBuffer stringBuffer = new StringBuffer(YAHOO_CSV_BASED_URL);
final String _symbol;
try {
_symbol = java.net.URLEncoder.encode(symbol.toString(), "UTF-8");
} catch (UnsupportedEncodingException ex) {
throw new StockNotFoundException("symbol.toString()=" + symbol.toString(), ex);
}
stringBuffer.append(_symbol).append(YAHOO_STOCK_FORMAT);
final String location = stringBuffer.toString();
final HttpClient httpClient = new HttpClient();
for(int retry=0; retry<NUM_OF_RETRY; retry++) {
HttpMethod method = new GetMethod(location);
try {
Utils.setHttpClientProxyFromSystemProperties(httpClient);
httpClient.executeMethod(method);
final String responde = method.getResponseBodyAsString();
final List<Stock> stocks = YahooStockFormat.getInstance().parse(responde);
if(stocks.size() == 1)
return stocks.get(0);
}
catch(HttpException exp) {
log.error("location=" + location, exp);
continue;
}
catch(IOException exp) {
log.error("location=" + location, exp);
continue;
}
finally {
method.releaseConnection();
}
break;
}
throw new StockNotFoundException("Cannot get symbol=" + symbol);
}
public Stock getStock(Code code) throws StockNotFoundException {
return getStock(Symbol.newInstance(code.toString()));
}
private boolean isToleranceAllowed(int currSize, int expectedSize) {
if(currSize >= expectedSize) return true;
if(expectedSize <= 0) return true;
double result = 100.0 - ((double)(expectedSize - currSize) / (double)expectedSize * 100.0);
return (result >= STABILITY_RATE);
}
@Override
public List<Stock> getStocksBySymbols(List<Symbol> symbols) throws StockNotFoundException {
List<Stock> stocks = new ArrayList<Stock>();
if(symbols.size() == 0) return stocks;
final int time = symbols.size() / MAX_STOCK_PER_ITERATION;
final int remainder = symbols.size() % MAX_STOCK_PER_ITERATION;
for(int i=0; i<time; i++) {
final int start = i * MAX_STOCK_PER_ITERATION;
final int end = start + MAX_STOCK_PER_ITERATION;
final StringBuffer stringBuffer = new StringBuffer(YAHOO_CSV_BASED_URL);
final StringBuffer symbolBuffer = new StringBuffer();
final List<Symbol> expectedSymbols = new ArrayList<Symbol>();
final int endLoop = end - 1;
for(int j=start; j<endLoop; j++) {
String symbolString = null;
try {
symbolString = java.net.URLEncoder.encode(symbols.get(j).toString(), "UTF-8");
} catch (UnsupportedEncodingException ex) {
throw new StockNotFoundException("", ex);
}
symbolBuffer.append(symbolString).append("+");
expectedSymbols.add(symbols.get(j));
}
String symbolString = null;
try {
symbolString = java.net.URLEncoder.encode(symbols.get(end - 1).toString(), "UTF-8");
} catch (UnsupportedEncodingException ex) {
throw new StockNotFoundException("", ex);
}
symbolBuffer.append(symbolString);
expectedSymbols.add(symbols.get(end - 1));
final String _symbol = symbolBuffer.toString();
stringBuffer.append(_symbol).append(YAHOO_STOCK_FORMAT);
final String location = stringBuffer.toString();
final HttpClient httpClient = new HttpClient();
boolean success = false;
for(int retry=0; retry<NUM_OF_RETRY; retry++) {
HttpMethod method = new GetMethod(location);
try {
Utils.setHttpClientProxyFromSystemProperties(httpClient);
httpClient.executeMethod(method);
final String responde = method.getResponseBodyAsString();
final List<Stock> tmpStocks = YahooStockFormat.getInstance().parse(responde);
if(tmpStocks.size() != MAX_STOCK_PER_ITERATION) {
if(retry == (NUM_OF_RETRY-1)) {
// throw new StockNotFoundException();
assert(expectedSymbols.size() == MAX_STOCK_PER_ITERATION);
final int currSize = tmpStocks.size();
final int expectedSize = expectedSymbols.size();
if(this.isToleranceAllowed(currSize, expectedSize)) {
List<Symbol> currSymbols = new ArrayList<Symbol>();
List<Stock> emptyStocks = new ArrayList<Stock>();
for(Stock stock : tmpStocks) {
currSymbols.add(stock.getSymbol());
}
for(Symbol symbol : expectedSymbols) {
if(currSymbols.contains(symbol) == false) {
emptyStocks.add(org.yccheok.jstock.gui.Utils.getEmptyStock(Code.newInstance(symbol.toString()), symbol));
}
}
tmpStocks.addAll(emptyStocks);
}
else {
throw new StockNotFoundException("Expected stock size=" + expectedSize + ", Current stock size=" + currSize + ", Request=" + location);
}
} // if(retry == (NUM_OF_RETRY-1))
continue;
} // if(tmpStocks.size() != MAX_STOCK_PER_ITERATION)
stocks.addAll(tmpStocks);
}
catch(HttpException exp) {
log.error("location=" + location, exp);
continue;
}
catch(IOException exp) {
log.error("location=" + location, exp);
continue;
}
finally {
method.releaseConnection();
}
success = true;
break;
}
if(success == false)
throw new StockNotFoundException("Inconsistent stock size (" + stocks.size() + ") and symbol size (" + symbols.size() + ")");
}
final int start = symbols.size() - remainder;
final int end = start + remainder;
final StringBuffer stringBuffer = new StringBuffer(YAHOO_CSV_BASED_URL);
final StringBuffer symbolBuffer = new StringBuffer();
final List<Symbol> expectedSymbols = new ArrayList<Symbol>();
final int endLoop = end - 1;
for(int i=start; i<endLoop; i++) {
String symbolString = null;
try {
symbolString = java.net.URLEncoder.encode(symbols.get(i).toString(), "UTF-8");
} catch (UnsupportedEncodingException ex) {
throw new StockNotFoundException("", ex);
}
symbolBuffer.append(symbolString).append("+");
expectedSymbols.add(symbols.get(i));
}
String symbolString = null;
try {
symbolString = java.net.URLEncoder.encode(symbols.get(end-1).toString(), "UTF-8");
} catch (UnsupportedEncodingException ex) {
throw new StockNotFoundException("", ex);
}
symbolBuffer.append(symbolString);
expectedSymbols.add(symbols.get(end-1));
final String _symbol = symbolBuffer.toString();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -