/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.aries.samples.ariestrader.core; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.aries.samples.ariestrader.api.persistence.MarketSummaryDataBean; import org.apache.aries.samples.ariestrader.util.Log; import org.apache.aries.samples.ariestrader.util.TradeConfig; import org.apache.aries.samples.ariestrader.api.TradeServicesManager; import org.apache.aries.samples.ariestrader.api.TradeServices; /** * TradeServicesManagerImpl coordinates access to the currently * selected TradeServices implementation and manages the list of * currently available TradeServices implementations. * * @see * org.apache.geronimo.samples.daytrader.api.TradeServicesManager * */ public class TradeServicesManagerImpl implements TradeServicesManager { private static TradeServices[] tradeServicesList = new TradeServices[TradeConfig.runTimeModeNames.length] ; // This lock is used to serialize market summary operations. private static final Integer marketSummaryLock = new Integer(0); private static long nextMarketSummary = System.currentTimeMillis(); private static MarketSummaryDataBean cachedMSDB = null; /** * TradeServicesManagerImpl null constructor */ public TradeServicesManagerImpl() { if (Log.doTrace()) Log.trace("TradeServicesManagerImpl()"); } /** * init */ public void init() { if (Log.doTrace()) Log.trace("TradeServicesManagerImpl:init()"); } /** * Get CurrentModes that are registered */ public ArrayList<Integer> getCurrentModes() { if (Log.doTrace()) Log.trace("TradeServicesManagerImpl:getCurrentModes()"); ArrayList<Integer> modes = new ArrayList<Integer>(); for (int i=0; i<tradeServicesList.length; i++) { TradeServices tradeServicesRef = tradeServicesList[i]; if (tradeServicesRef != null) { modes.add(i); } } return modes; } /** * Get TradeServices reference */ public TradeServices getTradeServices() { if (Log.doTrace()) Log.trace("TradeServicesManagerImpl:getTradeServices()"); return tradeServicesList[TradeConfig.getRunTimeMode().ordinal()]; } /** * Bind a new TradeServices implementation */ public void bindService(TradeServices tradeServices, Map props) { if (Log.doTrace()) Log.trace("TradeServicesManagerImpl:bindService()", tradeServices, props); if (tradeServices != null) { String mode = (String) props.get("mode"); tradeServicesList[Enum.valueOf(TradeConfig.ModeType.class, mode).ordinal()] = tradeServices; } } /** * Unbind a TradeServices implementation */ public void unbindService(TradeServices tradeServices, Map props) { if (Log.doTrace()) Log.trace("TradeServicesManagerImpl:unbindService()", tradeServices, props); if (tradeServices != null) { String mode = (String) props.get("mode"); tradeServicesList[Enum.valueOf(TradeConfig.ModeType.class, mode).ordinal()] = null; } } /** * Market Summary is inherently a heavy database operation. For servers that have a caching * story this is a great place to cache data that is good for a period of time. In order to * provide a flexible framework for this we allow the market summary operation to be * invoked on every transaction, time delayed or never. This is configurable in the * configuration panel. * * @return An instance of the market summary */ public MarketSummaryDataBean getMarketSummary() throws Exception { if (Log.doActionTrace()) { Log.trace("TradeAction:getMarketSummary()"); } if (Log.doTrace()) Log.trace("TradeServicesManagerImpl:getMarketSummary()"); if (TradeConfig.getMarketSummaryInterval() == 0) return getMarketSummaryInternal(); if (TradeConfig.getMarketSummaryInterval() < 0) return cachedMSDB; /** * This is a little funky. If its time to fetch a new Market summary then we'll synchronize * access to make sure only one requester does it. Others will merely return the old copy until * the new MarketSummary has been executed. */ long currentTime = System.currentTimeMillis(); if (currentTime > nextMarketSummary) { long oldNextMarketSummary = nextMarketSummary; boolean fetch = false; synchronized (marketSummaryLock) { /** * Is it still ahead or did we miss lose the race? If we lost then let's get out * of here as the work has already been done. */ if (oldNextMarketSummary == nextMarketSummary) { fetch = true; nextMarketSummary += TradeConfig.getMarketSummaryInterval()*1000; /** * If the server has been idle for a while then its possible that nextMarketSummary * could be way off. Rather than try and play catch up we'll simply get in sync with the * current time + the interval. */ if (nextMarketSummary < currentTime) { nextMarketSummary = currentTime + TradeConfig.getMarketSummaryInterval()*1000; } } } /** * If we're the lucky one then let's update the MarketSummary */ if (fetch) { cachedMSDB = getMarketSummaryInternal(); } } return cachedMSDB; } /** * Compute and return a snapshot of the current market conditions This * includes the TSIA - an index of the price of the top 100 Trade stock * quotes The openTSIA ( the index at the open) The volume of shares traded, * Top Stocks gain and loss * * @return A snapshot of the current market summary */ private MarketSummaryDataBean getMarketSummaryInternal() throws Exception { if (Log.doActionTrace()) { Log.trace("TradeAction:getMarketSummaryInternal()"); } MarketSummaryDataBean marketSummaryData = null; marketSummaryData = tradeServicesList[TradeConfig.getRunTimeMode().ordinal()].getMarketSummary(); return marketSummaryData; } }