/// <summary> /// Performs a lookup for the givern security id if recursiveLookup is true. /// </summary> /// <param name="securityIdDetails">The details of the security id for which to perform lookup.</param> /// <param name="lookupService">The lookup service to use</param> /// <returns>the security data.</returns> /// /// <exception cref="UnknownSecurityIdTypeException"> /// if the type of the given security id is unknown. /// </exception> /// <exception cref="InvalidSecurityIdFormatException">if the format of security id is invalid.</exception> /// <exception cref="SecurityIdParsingException">if any other error occurs in parsing the id.</exception> /// <exception cref="ServiceNotAvailableException">if the lookup service is not available.</exception> /// <exception cref="SecurityLookupException">if any error occurs when looking up the security data.</exception> /// <exception cref="SecurityDataCombiningException">if fail to combine the security data.</exception> private SecurityData PerformRecursiveLookup(SecurityIdDetails securityIdDetails, ISecurityLookupService lookupService) { // check cache to get the securityDataRecord SecurityDataRecord securityDataRecord = securityDataCache[securityIdDetails.Id] as SecurityDataRecord; if (securityDataRecord != null) { return(securityDataRecord.SecurityData); } else { //Get the security data for lookupService SecurityData securityData = lookupService.Lookup(securityIdDetails); //Add current id to cache. This prevents from infinite recursion due to cyclic references. securityDataCache[securityIdDetails.Id] = new SecurityDataRecord(securityData, true); //Create all possible cross-references and store in combinedData SecurityData combinedData = securityData; foreach (string refId in securityData.ReferenceIds) { //Check the reference id in cache SecurityDataRecord refRecord = securityDataCache[refId] as SecurityDataRecord; SecurityData refData; //if not present in cache, the load from lookup if (refRecord == null) { //Get details of the reference id SecurityIdDetails refDetails = securityIdParser.Parse(refId); //get lookup service for the refId ISecurityLookupService refLookupService = null; securityLookupServices.TryGetValue(refDetails.Type, out refLookupService); //No lookup service found for current type. if (refLookupService == null) { throw new NoSuchSecurityLookupServiceException( "No lookup service exists for the security type: " + refDetails.Type); } refData = PerformRecursiveLookup(securityIdParser.Parse(refId), refLookupService); } else { refData = refRecord.SecurityData; } //Combine the current combined data with combinedData = securityDataCombiner.Combine(combinedData, refData); } //All cross-refernced ids must now point to the same combinedData instance AddUpdateCache(combinedData); return(combinedData); } }
/// <summary> /// Performs a lookup for the givern security id if recursiveLookup is false and referenceLookup is true. /// </summary> /// <param name="securityIdDetails">The details of the security id for which to perform lookup.</param> /// <param name="lookupService">The lookup service to use</param> /// <returns>the security data.</returns> /// /// <exception cref="ServiceNotAvailableException">if the lookup service is not available.</exception> /// <exception cref="SecurityLookupException">if any error occurs when looking up the security data.</exception> /// <exception cref="SecurityDataCombiningException">if fail to combine the security data.</exception> private SecurityData PerformReferenceLookup(SecurityIdDetails securityIdDetails, ISecurityLookupService lookupService) { // check cache to get the securityDataRecord SecurityDataRecord securityDataRecord = securityDataCache[securityIdDetails.Id] as SecurityDataRecord; if (securityDataRecord != null && securityDataRecord.IsLookedUp) { return(securityDataRecord.SecurityData); } else if (securityDataRecord == null) { return(PerformSimpleLookup(securityIdDetails, lookupService)); } else { //Get the security data for lookupService SecurityData securityData = lookupService.Lookup(securityIdDetails); //Combine the record in cache with the one returned. securityData = securityDataCombiner.Combine(securityData, securityDataRecord.SecurityData); //Add or update cache with the cross-referenced security data AddUpdateCache(securityData); return(securityData); } }
/// <summary> /// <para>Lookup the security data by the given security id details.</para> /// </summary> /// /// <param name="securityIdDetails">the security id details used to lookup security data.</param> /// <returns>the security data.</returns> /// /// <exception cref="SelfDocumentingException">Wraps ArgumentNullException is argument is null.</exception> /// <exception cref="UnknownSecurityIdTypeException">if type of the given security id is unknown.</exception> /// <exception cref="InvalidSecurityIdFormatException">if the format of security id is invalid.</exception> /// <exception cref="SecurityIdParsingException">if any other error occurs in parsing the id.</exception> /// <exception cref="NoSuchSecurityLookupServiceException">if there is no corresponding ISecurityLookupService /// defined for the specific security identifier type.</exception> /// <exception cref="ServiceNotAvailableException">if the lookup service is not available.</exception> /// <exception cref="SecurityLookupException">if any error occurs when looking up the security data.</exception> public SecurityData Lookup(SecurityIdDetails securityIdDetails) { ISecurityLookupService lookupService = null; try { Helper.ValidateNotNull(securityIdDetails, "securityIdDetails"); // get corresponding lookup service. Use TryGetValue so that KeyNotFoundException is not encountered. securityLookupServices.TryGetValue(securityIdDetails.Type, out lookupService); //No lookup service found for current type. if (lookupService == null) { throw new NoSuchSecurityLookupServiceException( "No lookup service exists for the security type: " + securityIdDetails.Type); } //Since cache is checked and updated many times in the same function, //there needs to control against race conditions. lock (securityDataCache) { if (recursiveLookup) { return(PerformRecursiveLookup(securityIdDetails, lookupService)); } else if (referenceLookup) { return(PerformReferenceLookup(securityIdDetails, lookupService)); } else { return(PerformSimpleLookup(securityIdDetails, lookupService)); } } } catch (Exception e) { throw Helper.GetSelfDocumentingException(e, "Unable to perform lookup.", "TopCoder.FinancialService.Utility.FinancialSecurityManager.Lookup(SecurityIdDetails)", new string[] { "securityIdParser", "securityLookupServices", "recursiveLookup", "referenceLookup", "securityDataCache", "securityDataCombiner" }, new object[] { securityIdParser, securityLookupServices, recursiveLookup, referenceLookup, securityDataCache, securityDataCombiner }, new string[] { "securityIdDetails" }, new object[] { securityIdDetails }, new string[] { "lookupService" }, new object[] { lookupService }); } }
/// <summary> /// Performs a lookup for the givern security id if recursiveLookup and referenceLookup are both false. /// </summary> /// <param name="securityIdDetails">The details of the security id for which to perform lookup.</param> /// <param name="lookupService">The lookup service to use</param> /// <returns>the security data.</returns> /// /// <exception cref="ServiceNotAvailableException">if the lookup service is not available.</exception> /// <exception cref="SecurityLookupException">if any error occurs when looking up the security data.</exception> /// <exception cref="SecurityDataCombiningException">if fail to combine the security data.</exception> private SecurityData PerformSimpleLookup(SecurityIdDetails securityIdDetails, ISecurityLookupService lookupService) { // check cache to get the securityDataRecord SecurityDataRecord securityDataRecord = securityDataCache[securityIdDetails.Id] as SecurityDataRecord; if (securityDataRecord != null) { return(securityDataRecord.SecurityData); } else { //If not in cache then perform lookup SecurityData securityData = lookupService.Lookup(securityIdDetails); //Combine with itself. Combining a securityData instance with itself has the effect of //adding the securityID to the referenceIds SecurityData combinedData = securityDataCombiner.Combine(securityData, securityData); //Create all possible cross references foreach (string refId in securityData.ReferenceIds) { //Check the reference id in cache SecurityDataRecord refSecurityData = securityDataCache[refId] as SecurityDataRecord; if (refSecurityData != null) { combinedData = securityDataCombiner.Combine(securityData, refSecurityData.SecurityData); } } //Add or update cache with the cross-referenced security data AddUpdateCache(combinedData); return(combinedData); } }
/// <summary> /// <para>Build the FinancialSecurityManager object using the given IConfiguration object.</para> /// </summary> /// /// <param name="configuration">the IConfiguration to load configuration.</param> /// <returns>the created FinancialSecurityManager object.</returns> /// /// <exception cref="SelfDocumentingException"> /// Wraps ArgumentNullException if the given argument is null. /// Wraps ConfigurationErrorsException if the configured value is invalid, or any required /// property is missing. /// </exception> public static FinancialSecurityManager BuildFinancialSecurityManager(IConfiguration configuration) { //Declare local variables ISecurityIdParser securityIdParser = null; ConfigurationAPIObjectFactory of = null; string ofDefinitionsKey = null; string securityIdParserKey = null; string[] securityIdTypes = null; string[] securityLookupServiceKeys = null; IDictionary <string, ISecurityLookupService> securityLookupServices = null; bool recursiveLookup = false, referenceLookup = false; ICache cache = null; string securityDataCacheKey = null; ISecurityDataCombiner combiner = null; string securityDataCombinerKey = null; try { Helper.ValidateNotNull(configuration, "configuration"); //Get the key of the nested object definition to use ofDefinitionsKey = GetConfigValue(configuration, "objectfactory_key", true, false); try { //Create the Obejct Factory instance using the nested definition to use. of = new ConfigurationAPIObjectFactory(configuration[ofDefinitionsKey]); } catch (Exception e) { throw new ConfigurationErrorsException( "Unable to create ConfigurationAPIObjectFactory instance from object factory", e); } //Create ISecurityIdParser instance if needed. securityIdParserKey = GetConfigValue(configuration, "security_id_parser_key", false, false); if (securityIdParserKey != null) { try { securityIdParser = (ISecurityIdParser)of.CreateDefinedObject(securityIdParserKey); } catch (Exception e) { throw new ConfigurationErrorsException( "Unable to create ISecurityIdParser instance from object factory", e); } } //Get the security types and the keys for creating their respective ISecurityLookupService instances securityIdTypes = GetConfigArrayValue( configuration, "security_id_types", true, false); securityLookupServiceKeys = GetConfigArrayValue( configuration, "security_lookup_service_keys", true, false); //Length of both must be same if (securityIdTypes.Length != securityLookupServiceKeys.Length) { throw new ConfigurationErrorsException( "Arrays for security_id_types and security_lookup_service_keys must be of same length."); } //Generate dictionary of security types to lookup service mappings. securityLookupServices = new Dictionary <string, ISecurityLookupService>(); for (int i = 0; i < securityIdTypes.Length; i++) { //If any keys are empty, throw exception if (securityIdTypes[i].Trim().Equals(String.Empty) || securityLookupServiceKeys[i].Trim().Equals(String.Empty)) { throw new ConfigurationErrorsException("Arrays for security_id_types and " + "security_lookup_service_keys must not contain empty elements"); } else { try { //Create the lookup service instance from ObjectFactory ISecurityLookupService lookupService = (ISecurityLookupService) of.CreateDefinedObject(securityLookupServiceKeys[i]); //Add type to lookup mapping to dictionary securityLookupServices[securityIdTypes[i]] = lookupService; } catch (Exception e) { throw new ConfigurationErrorsException( "Unable to create ISecurityLookupService instance from object factory", e); } } } //Set recursive_lookup and referenceLookup try { recursiveLookup = bool.Parse(GetConfigValue(configuration, "recursive_lookup", true, false)); referenceLookup = bool.Parse(GetConfigValue(configuration, "reference_lookup", true, false)); } catch (FormatException fe) { throw new ConfigurationErrorsException("Unable to parse value to boolean.", fe); } //Load cache securityDataCacheKey = GetConfigValue(configuration, "security_data_cache_key", true, false); try { cache = (ICache)of.CreateDefinedObject(securityDataCacheKey); } catch (Exception e) { throw new ConfigurationErrorsException( "Unable to create ICache instance from object factory", e); } //Load data combiner securityDataCombinerKey = GetConfigValue(configuration, "security_data_combiner_key", true, false); try { combiner = (ISecurityDataCombiner)of.CreateDefinedObject(securityDataCombinerKey); } catch (Exception e) { throw new ConfigurationErrorsException( "Unable to create ISecurityDataCombiner instance from object factory", e); } //Create and return FinancialSecurityManager instance if (securityIdParser == null) { return(new FinancialSecurityManager( securityLookupServices, combiner, recursiveLookup, referenceLookup, cache)); } else { return(new FinancialSecurityManager( securityIdParser, securityLookupServices, combiner, recursiveLookup, referenceLookup, cache)); } } catch (Exception e) { throw Helper.GetSelfDocumentingException(e, "Unable to build FinancialSecurityManager instance from configuration.", "TopCoder.FinancialService.Utility.FinancialSecurityManagerBuilder.BuildFinancialSecurityManager", new string[0], new object[0], new string[] { "configuration" }, new object[] { configuration }, new string[] { "securityIdParser", "of", "of_definitions_key", "security_id_parser_key", "security_id_types", "security_lookup_service_keys", "securityLookupServices", "recursiveLookup", "referenceLookup", "cache", "securityDataCacheKey", "combiner", "securityDataCombinerKey" }, new object[] { securityIdParser, of, ofDefinitionsKey, securityIdParserKey, securityIdTypes, securityLookupServiceKeys, securityLookupServices, recursiveLookup, referenceLookup, cache, securityDataCacheKey, combiner, securityDataCombinerKey }); } }