//
// 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.
//
// .NET Service Configuration V2.0 for Design Considerations for Service-Oriented Applications based on Windows Communication Foundation. Created with Microsoft .NET Framework 3.5 and Microsoft Visual Studio. Copyright 2008, Microsoft Corporation.
//======================================================================================================
// Code originally contributed by Microsoft Corporation.
// This contribution to the Stonehenge project is limited strictly
// to the source code that is submitted in this submission.
// Any technology, including underlying platform technology,
// that is referenced or required by the submitted source code
// is not a part of the contribution.
// For example and not by way of limitation,
// any systems/Windows libraries (WPF, WCF, ASP.NET etc.)
// required to run the submitted source code is not a part of the contribution
//======================================================================================================
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Runtime.Serialization;
using System.Collections.Generic;
using System.Threading;
using System.Configuration;
using Trade.BusinessServiceContract;
using Trade.BusinessServiceDataContract;
using Trade.StockTraderWebApplicationSettings;
using Trade.Client;
using Trade.Utility;
using Trade.ConfigClient;
using Trade.ConfigServiceContract;
using Trade.ConfigServiceDataContract;
namespace Trade.BusinessServiceClient
{
///
/// This is the WCF client class for the remote Business Services, connecting to any Web Service platform
/// via WCF (.NET, J2EE etc.) that implements ITradeServices. This class implements channel initialization and
/// load balancing/failover logic across cached channel instances specific to the Configuration Management/Node services
/// implemented in StockTrader via the LoadBalancingClient.Client class, now re-used across all clients
/// implementing the configuration service.
///
[System.Runtime.Serialization.KnownType(typeof(AccountDataModel))]
public class BusinessServiceClient : ITradeServices
{
public Client.Client bslclient;
public BusinessServiceClient()
{
//Clears the cache of the client so that changes in the database configuration can
//be recognized without restarts
Initialize();
//Using the database configuration system - this BusinessServiceClient is created based on the CLIENTTOBS
//Configuration Settings specified in the database i.e. the row containing DOTNET_CLIENT
var configClient = new ConfigServiceClient();
var clientRequest = new ClientConfigRequest();
clientRequest.ClientName = Settings.CLIENT_LABEL;
var clientConfig = configClient.GetClientConfig(clientRequest);
//In case the client cannot be properly configured from the database, look up the default ACCESSMODE from the
//App.config file
if (clientConfig == null)
{
throw new Exception(StockTraderUtility.EXCEPTION_MESSAGE_BAD_CONFIG);
}
//If configuration information was properly received from the database then choose the appropriate business
//service based on the info in the CLIENTTOBS table i.e. the row with DOTNET_CLIENT
try
{
if (ConfigurationManager.AppSettings.Get(clientConfig.BSName) == null)
throw new Exception(string.Format("The WCF endpoint for {0} was not defined in the configuration", clientConfig.BSName));
bslclient = new Client.Client(ConfigurationManager.AppSettings.Get(clientConfig.BSName), clientConfig.BS, Settings.BSL_USERID, Settings.BSL_PASSWORD, true);
}
catch
{
throw new Exception(string.Format(StockTraderUtility.EXCEPTION_MESSAGE_BAD_CONFIG, clientRequest.ClientName));
}
}
public ITradeServices Channel
{
get
{
return bslclient.Channel;
}
set
{
bslclient.Channel = value;
}
}
public void emptyMethodAction()
{
try
{
this.Channel.emptyMethodAction();
}
catch
{
this.Channel = null;
throw;
}
}
///
/// Logs user in/authenticates against StockTrader database.
///
/// User id to authenticate.
/// Password for authentication
public AccountDataModel login(string userID, string password)
{
try
{
if (userID == null)
userID = GetDefaultUserId();
return this.Channel.login(userID, password);
}
catch
{
this.Channel = null;
throw;
}
}
///
/// Gets recent orders for a user. Transforms data from DataContract to model UI class for HTML display.
///
/// User id to retrieve data for.
public List getOrders(string userID)
{
try
{
if (userID == null)
userID = GetDefaultUserId();
return this.Channel.getOrders(userID);
}
catch
{
this.Channel = null;
throw;
}
}
///
/// Gets account data for a user. Transforms data from DataContract to model UI class for HTML display.
///
/// User id to retrieve data for.
public AccountDataModel getAccountData(string userID)
{
try
{
if (userID == null)
userID = GetDefaultUserId();
return this.Channel.getAccountData(userID);
}
catch
{
this.Channel = null;
throw;
}
}
///
/// Gets account profile data for a user. Transforms data from DataContract to model UI class for HTML display.
///
/// User id to retrieve data for.
public AccountProfileDataModel getAccountProfileData(string userID)
{
try
{
if (userID == null)
userID = GetDefaultUserId();
return this.Channel.getAccountProfileData(userID);
}
catch
{
this.Channel = null;
throw;
}
}
///
/// Updates account profile data for a user.
///
/// Profile data model class with updated info.
public AccountProfileDataModel updateAccountProfile(AccountProfileDataModel profileData)
{
try
{
return this.Channel.updateAccountProfile(profileData);
}
catch
{
this.Channel = null;
throw;
}
}
///
/// Logs a user out--updates logout count.
///
/// User id to logout.
public void logout(string userID)
{
try
{
if (userID == null)
userID = GetDefaultUserId();
this.Channel.logout(userID);
}
catch
{
this.Channel = null;
throw;
}
return;
}
///
/// Performs a stock buy operation.
///
/// User id to create/submit order for.
/// Stock symbol to buy.
/// Shares to buy
public OrderDataModel buy(string userID, string symbol, double quantity, int orderProcessingMode)
{
try
{
if (userID == null)
userID = GetDefaultUserId();
return this.Channel.buy(userID, symbol, quantity, orderProcessingMode);
}
catch
{
this.Channel = null;
throw;
}
}
///
/// Performs a holding sell operation.
///
/// User id to create/submit order for.
/// Holding id to sell off.
/// Shares to sell.
public OrderDataModel sell(string userID, int holdingID, int orderProcessingMode)
{
try
{
if (userID == null)
userID = GetDefaultUserId();
return this.Channel.sell(userID, holdingID, orderProcessingMode);
}
catch
{
this.Channel = null;
throw;
}
}
///
/// Gets holding data for a user. Transforms data from DataContract to model UI class for HTML display.
///
/// User id to retrieve data for.
public List getHoldings(string userID)
{
try
{
if (userID == null)
userID = GetDefaultUserId();
return this.Channel.getHoldings(userID);
}
catch
{
this.Channel = null;
throw;
}
}
///
/// Registers/adds new user to database.
///
/// User id for account creation/login purposes as specified by user.
/// Password as specified by user.
/// Name as specified by user.
/// Address as specified by user.
/// Email as specified by user.
/// Credit card number as specified by user.
/// Open balance as specified by user.
public AccountDataModel register(string userID, string password, string fullname, string address, string email, string creditcard, decimal openBalance)
{
try
{
return this.Channel.register(userID, password, fullname, address, email, creditcard, openBalance);
}
catch
{
this.Channel = null;
throw;
}
}
///
/// Gets any closed orders for a user--orders that have been processed. Also updates status to complete.
///
/// User id to retrieve data for.
public List getClosedOrders(string userID)
{
try
{
if (userID == null)
userID = GetDefaultUserId();
return this.Channel.getClosedOrders(userID);
}
catch
{
this.Channel = null;
throw;
}
}
///
/// Gets the current market summary. This results in an expensive DB query in the DAL; hence look to cache data returned for 60 second or so.
///
public MarketSummaryDataModelWS getMarketSummary()
{
try
{
return this.Channel.getMarketSummary();
}
catch
{
this.Channel = null;
throw;
}
}
///
/// Gets a single quote based on symbol.
///
/// Symbol to get data for.
public QuoteDataModel getQuote(string symbol)
{
try
{
return this.Channel.getQuote(symbol);
}
catch
{
this.Channel = null;
throw;
}
}
///
/// Gets a holding for a user. Transforms data from DataContract to model UI class for HTML display.
///
/// User id to retrieve data for.
/// Holding id to retrieve data for.
public HoldingDataModel getHolding(string userID, int holdingID)
{
try
{
if (userID == null)
userID = GetDefaultUserId();
return this.Channel.getHolding(userID, holdingID);
}
catch
{
this.Channel = null;
throw;
}
}
///
/// Gets specific top n orders for a user. Transforms data from DataContract to model UI class for HTML display.
///
/// User id to retrieve data for.
public List getTopOrders(string userID)
{
try
{
if (userID == null)
userID = GetDefaultUserId();
return this.Channel.getTopOrders(userID);
}
catch
{
this.Channel = null;
throw;
}
}
///
/// Allows user to sell part of a holding vs. all. Not implemented by Trade 6.1 on WebSphere.
///
/// User id to submit sell for.
/// Holding id to sell.
/// Number of shares to sell.
public OrderDataModel sellEnhanced(string userID, int holdingID, double quantity)
{
try
{
if (userID == null)
userID = GetDefaultUserId();
return this.Channel.sellEnhanced(userID, holdingID, quantity);
}
catch
{
this.Channel = null;
throw;
}
}
///
/// Simple online check method.
///
public void isOnline()
{
try
{
this.Channel.isOnline();
return;
}
catch
{
this.Channel = null;
throw;
}
}
///
/// A Static method that clears the cache of the Client Service
///
public static void Initialize()
{
Client.Client.ClearCache();
}
///
/// TODO: Hack for metro
///
///
private string GetDefaultUserId()
{
return Settings.BSL_USERID;
}
}
}