package org.marketcetera.marketdata.yahoo; import static org.marketcetera.marketdata.AssetClass.EQUITY; import static org.marketcetera.marketdata.AssetClass.FUTURE; import static org.marketcetera.marketdata.AssetClass.OPTION; import static org.marketcetera.marketdata.Capability.EVENT_BOUNDARY; import static org.marketcetera.marketdata.Capability.LATEST_TICK; import static org.marketcetera.marketdata.Capability.MARKET_STAT; import static org.marketcetera.marketdata.Capability.TOP_OF_BOOK; import java.util.*; import java.util.concurrent.atomic.AtomicLong; import javax.annotation.concurrent.GuardedBy; import org.marketcetera.core.NoMoreIDsException; import org.marketcetera.marketdata.*; import org.marketcetera.util.misc.ClassVersion; /* $License$ */ /** * Market data feed implementation for the Yahoo market data supplier. * * @author <a href="mailto:colin@marketcetera.com">Colin DuPlantis</a> * @version $Id: YahooFeed.java 16154 2012-07-14 16:34:05Z colin $ * @since 2.1.4 */ @ClassVersion("$Id: YahooFeed.java 16154 2012-07-14 16:34:05Z colin $") class YahooFeed extends AbstractMarketDataFeed<YahooFeedToken, YahooFeedCredentials, YahooFeedMessageTranslator, YahooFeedEventTranslator, List<YahooRequest>, YahooFeed> implements YahooFeedServices { /* (non-Javadoc) * @see org.marketcetera.marketdata.MarketDataFeed#getCapabilities() */ @Override public Set<Capability> getCapabilities() { return capabilities; } /* (non-Javadoc) * @see org.marketcetera.marketdata.MarketDataFeed#getSupportedAssetClasses() */ @Override public Set<AssetClass> getSupportedAssetClasses() { return assetClasses; } /* (non-Javadoc) * @see org.marketcetera.marketdata.yahoo.FeedServices#doDataReceived(java.lang.String, java.lang.Object) */ @Override public void doDataReceived(String inHandle, Object inData) { dataReceived(inHandle, inData); } /* (non-Javadoc) * @see org.marketcetera.marketdata.yahoo.FeedServices#getRefreshInterval() */ @Override public int getRefreshInterval() { return refreshInterval; } /** * Resets the request counter. */ void resetCounter() { client.resetRequestcounter(); } /** * Gets the current request counter. * * @return a <code>long</code> value */ long getRequestCounter() { return client.getRequestCounter(); } /** * Create a new YahooFeed instance. * * @param inProviderName a <code>String</code> value * @throws NoMoreIDsException if the feed cannot be constructed */ YahooFeed(String inProviderName, YahooClientFactory inFactory) throws NoMoreIDsException { super(FeedType.DELAYED, inProviderName); client = inFactory.getClient(this); } /** * Sets the refresh interval for retrieving market data. * * <p>Changing this value takes effect immediately. * * @param inRefreshInterval an <code>int</code> value */ void setRefreshInterval(int inRefreshInterval) { refreshInterval = inRefreshInterval; } /* (non-Javadoc) * @see org.marketcetera.marketdata.AbstractMarketDataFeed#doCancel(java.lang.String) */ @Override protected void doCancel(String inHandle) { synchronized(requests) { YahooRequest request = requests.remove(inHandle); if(request != null) { client.cancel(request); } } } /* (non-Javadoc) * @see org.marketcetera.marketdata.AbstractMarketDataFeed#doLogin(org.marketcetera.marketdata.MarketDataFeedCredentials) */ @Override protected boolean doLogin(YahooFeedCredentials inCredentials) { return client.login(inCredentials); } /* (non-Javadoc) * @see org.marketcetera.marketdata.AbstractMarketDataFeed#doLogout() */ @Override protected void doLogout() { client.logout(); } /* (non-Javadoc) * @see org.marketcetera.marketdata.AbstractMarketDataFeed#isLoggedIn() */ @Override protected boolean isLoggedIn() { return client.isLoggedIn(); } /* (non-Javadoc) * @see org.marketcetera.marketdata.AbstractMarketDataFeed#doMarketDataRequest(java.lang.Object) */ @Override protected List<String> doMarketDataRequest(List<YahooRequest> inRequests) throws FeedException { List<String> handles = new ArrayList<String>(); synchronized(requests) { for(YahooRequest request : inRequests) { String handle = generateHandle(); handles.add(handle); request.setHandle(handle); requests.put(handle, request); client.request(request); } return handles; } } /* (non-Javadoc) * @see org.marketcetera.marketdata.AbstractMarketDataFeed#generateToken(org.marketcetera.marketdata.MarketDataFeedTokenSpec) */ @Override protected YahooFeedToken generateToken(MarketDataFeedTokenSpec inTokenSpec) throws FeedException { return new YahooFeedToken(inTokenSpec, this); } /* (non-Javadoc) * @see org.marketcetera.marketdata.AbstractMarketDataFeed#getEventTranslator() */ @Override protected YahooFeedEventTranslator getEventTranslator() { return YahooFeedEventTranslator.INSTANCE; } /* (non-Javadoc) * @see org.marketcetera.marketdata.AbstractMarketDataFeed#getMessageTranslator() */ @Override protected YahooFeedMessageTranslator getMessageTranslator() { return YahooFeedMessageTranslator.INSTANCE; } /** * Generates a request handle. * * @return a <code>String</code> value */ private String generateHandle() { return String.format("yahoo-%s", //$NON-NLS-1$ counter.incrementAndGet()); } /** * default interval at which to refresh the market data */ private volatile int refreshInterval = 250; /** * asset classes supported by this adapter */ private static final Set<AssetClass> assetClasses = new HashSet<AssetClass>(Arrays.asList(new AssetClass[] { EQUITY,OPTION,FUTURE })); /** * capabilities of this adapter */ private static final Set<Capability> capabilities = new HashSet<Capability>(Arrays.asList(new Capability[] { TOP_OF_BOOK,LATEST_TICK,MARKET_STAT,EVENT_BOUNDARY })); /** * stores the active requests */ @GuardedBy("requests") private final Map<String,YahooRequest> requests = new HashMap<String,YahooRequest>(); /** * counter used to count requests */ private final AtomicLong counter = new AtomicLong(0); /** * client implementation to use */ private final YahooClient client; }