public async Task <IList <IGstLookupResult> > LookupGstDataAsync(GstLookupInputType inputType, string input, bool validateInput = false)
        {
            if (validateInput)
            {
                GstInputValidator.ValidateInput(inputType, input);
            }

            GstWebScraper scraper;
            var           pool = _pools[inputType];

            while (pool.TryDequeue(out scraper) && scraper.ShouldDispose)
            {
            }
            if (scraper == null)
            {
                scraper = new GstWebScraper();
            }

            try {
                return(await scraper.LookupGstDataAsync(inputType, input));
            } finally {
                if (!scraper.ShouldDispose)
                {
                    pool.Enqueue(scraper);
                }
            }
        }
Ejemplo n.º 2
0
 public static CachedGstEntity CreateForError(GstLookupInputType inputType, string input, KnownCustomsGstErrorCode error)
 {
     return(new CachedGstEntity {
         PartitionKey = GetPartitionKey(inputType, input),
         RowKey = "000",
         KnownErrorCode = error.ToString()
     });
 }
        public async Task <IList <IGstLookupResult> > LookupGstDataAsync(GstLookupInputType inputType, string input, bool validateInput = false)
        {
            // Customs' server will return empty result if I send the same request two times in a row,
            // so I'm going to cache the most recent result and return that if the same requests were sent twice.
            var currentInput = Tuple.Create(inputType, input);

            if (currentInput.Equals(_previousInput))
            {
                if (_previousResults.Count > 0)
                {
                    var result = (GstLookupResult)_previousResults[0];
                    result.IsLiveData = false;
                }
                return(_previousResults);
            }

            if (validateInput)
            {
                GstInputValidator.ValidateInput(inputType, input);
            }

            if (_accessCount > 0)
            {
                throw new NotSupportedException(Resources.SingleLookupErrorMessage);
            }

            try {
                if (Interlocked.Increment(ref _accessCount) > 1)
                {
                    throw new NotSupportedException(Resources.SingleLookupErrorMessage);
                }

                if (!_isInitialized)
                {
                    await InitializeTokenAsync();
                    await LoadFrontPageAsync();
                    await BrowseToLookupPageAsync();

                    _isInitialized = true;
                }

                if (_inputType == null || _inputType != inputType)
                {
                    await SelectLookupInputTypeAsync(inputType);
                }

                var results = await ExecuteLookupAsync(input);

                _previousInput   = currentInput;
                _previousResults = results;
                return(results);
            } catch (WebException ex) {
                throw new CustomsGstException(ex.Message, innerException: ex);
            } finally {
                Interlocked.Decrement(ref _accessCount);
            }
        }
        async Task SelectLookupInputTypeAsync(GstLookupInputType inputType)
        {
            var req = new RestRequest("_/Recalc");

            switch (inputType)
            {
            case GstLookupInputType.GstNumber:
                req.AddParameter("d-3", "true");
                req.AddParameter("d-5", "");
                req.AddParameter("d-6", "false");
                req.AddParameter("d-7", "");
                req.AddParameter("d-8", "false");
                req.AddParameter("d-9", "");
                req.AddParameter("LASTFOCUSFIELD__", "d-3");
                req.AddParameter("DOC_MODAL_ID__", 0);
                req.AddParameter("RECALC_SOURCE__", "d-3");
                break;

            case GstLookupInputType.BusinessRegNumber:
                req.AddParameter("d-3", "false");
                req.AddParameter("d-5", "");
                req.AddParameter("d-6", "true");
                req.AddParameter("d-7", "");
                req.AddParameter("d-8", "false");
                req.AddParameter("d-9", "");
                req.AddParameter("LASTFOCUSFIELD__", "d-6");
                req.AddParameter("DOC_MODAL_ID__", 0);
                req.AddParameter("RECALC_SOURCE__", "d-6");
                break;

            case GstLookupInputType.BusinessName:
                req.AddParameter("d-3", "false");
                req.AddParameter("d-5", "");
                req.AddParameter("d-6", "false");
                req.AddParameter("d-7", "");
                req.AddParameter("d-8", "true");
                req.AddParameter("d-9", "");
                req.AddParameter("LASTFOCUSFIELD__", "d-8");
                req.AddParameter("DOC_MODAL_ID__", 0);
                req.AddParameter("RECALC_SOURCE__", "d-8");
                break;
            }

            req.AddParameter("RECALC_TRIGGER__", "CheckboxClick");
            req.AddParameter("FAST_VERLAST__", _token);
            req.AddParameter("FAST_VERLAST_SOURCE__", _tokenSource);
            req.AddParameter("FAST_CLIENT_WHEN__", GetJavascriptTime());
            req.AddParameter("FAST_CLIENT_WINDOW__", _windowId);
            req.AddParameter("FAST_CLIENT_AJAX_ID__", GetAjaxId());

            var resp = await _client.ExecutePostTaskAsync(req);

            UpdateTokenForNextRequest(resp);
            _inputType = inputType;
        }
Ejemplo n.º 5
0
        public static CachedGstEntity CreateForResult(GstLookupInputType inputType, string input, IGstLookupResult liveResult, int sequence)
        {
            if (!liveResult.IsLiveData)
            {
                throw new ArgumentException(Resources.WebApiCannotCacheStaleData, "liveResult");
            }

            return(new CachedGstEntity {
                PartitionKey = GetPartitionKey(inputType, input),
                RowKey = sequence.ToString("000"),
                GstNumber = liveResult.GstNumber,
                LegalName = liveResult.LegalName,
                TradingName = liveResult.TradingName,
                CommenceDate = liveResult.CommenceDate,
                Status = liveResult.Status
            });
        }
Ejemplo n.º 6
0
        public static void ValidateInput(GstLookupInputType inputType, string input)
        {
            if (inputType == GstLookupInputType.GstNumber && !GstNumberRegex.IsMatch(input))
            {
                throw new InvalidGstInputException(Resources.InvalidGstNumberValidationMessage);
            }

            if (inputType == GstLookupInputType.BusinessRegNumber && !BusinessRegNumberRegex.IsMatch(input))
            {
                throw new InvalidGstInputException(Resources.InvalidBusinessRegNumberValidationMessage);
            }

            if (inputType == GstLookupInputType.BusinessName && input.Length <= 3)
            {
                throw new InvalidGstInputException(Resources.BusinessNameTooShortValidationMessage);
            }
        }
Ejemplo n.º 7
0
        public static string GetPartitionKey(GstLookupInputType inputType, string input)
        {
            switch (inputType)
            {
            case GstLookupInputType.GstNumber:
                return(PartitionKeyPrefixForGstNumber + input);

            case GstLookupInputType.BusinessRegNumber:
                return(PartitionKeyPrefixForBusinessRegNumber + new string(
                           input.Where(char.IsLetterOrDigit).Select(char.ToUpperInvariant).ToArray()));

            case GstLookupInputType.BusinessName:
                return(PartitionKeyPrefixForBusinessNameQuery +
                       input.ToUpperInvariant().Replace(' ', '_'));

            default:
                throw new NotSupportedException();
            }
        }
        public async Task <IList <IGstLookupResult> > LookupGstDataAsync(GstLookupInputType inputType, string input, bool validateInput = false)
        {
            if (validateInput)
            {
                GstInputValidator.ValidateInput(inputType, input);
            }

            // Retrieve all entities of the given Partition Key.
            var partitionKey  = CachedGstEntity.GetPartitionKey(inputType, input);
            var resultsQuery  = Table.CreateQuery <CachedGstEntity>().Where(e => e.PartitionKey == partitionKey);
            var cachedResults = new List <IGstLookupResult>();

            TableContinuationToken continuationToken = null;

            do
            {
                var segment = await resultsQuery.AsTableQuery().ExecuteSegmentedAsync(continuationToken);

                cachedResults.AddRange(segment.Results);
                continuationToken = segment.ContinuationToken;
            } while (continuationToken != null);

            // Return if there is any entity in the cache.
            if (cachedResults.Count > 0)
            {
                return(cachedResults);
            }

            // Lookup Customs' server and cache the results.
            IList <IGstLookupResult> lookupResults;

            try {
                lookupResults = await _dataSource.LookupGstDataAsync(inputType, input);
            } catch (CustomsGstException ex) {
                if (ex.KnownErrorCode == KnownCustomsGstErrorCode.Over100Results)
                {
#pragma warning disable 4014
                    InsertAsync(CachedGstEntity.CreateForError(
                                    inputType, input, KnownCustomsGstErrorCode.Over100Results));
                }
#pragma warning restore 4014
                throw;
            }

            if (lookupResults.Count == 0)
            {
#pragma warning disable 4014
                InsertAndScheduleDeleteAsync(CachedGstEntity.CreateForError(
                                                 inputType, input, KnownCustomsGstErrorCode.NoResult), 6);
                return(lookupResults);

#pragma warning restore 4014
            }

            if (lookupResults[0].IsLiveData)
            {
                CachedGstEntity lastCachedResult = null;

                var batchOp = new TableBatchOperation();
                for (var i = 0; i < lookupResults.Count; i++)
                {
                    lastCachedResult = CachedGstEntity.CreateForResult(inputType, input, lookupResults[i], i);
                    batchOp.InsertOrReplace(lastCachedResult);
                }
#pragma warning disable 4014
                Table.ExecuteBatchAsync(batchOp);
#pragma warning restore 4014

                if (inputType == GstLookupInputType.BusinessName)
                {
                    Debug.Assert(lastCachedResult != null, "cacheResult shouldn't be null here");
#pragma warning disable 4014
                    ScheduleDeleteAsync(lastCachedResult, 6);
#pragma warning restore 4014
                }
            }

            return(lookupResults);
        }