コード例 #1
0
        public static RequestParamsBuilder CreateBuilder(ISyncRequest request)
        {
            if (request is AddItemRequest)
            {
                return new ItemRequestParamsBuilder(request);
            }
            if (request is UpdateItemRequest)
            {
                return new UpdateItemRequestParamsBuilder(request);
            }

            if (request is UpdateItemMultiStockRequest)
            {
                return new UpdateItemMultiStockRequestBuilder(request);
            }

            if (request is QueryOrderListRequest)
            {
                return new QueryOrderRequestBuilder(request);
            }

            if (request is MarkShippingRequest)
            {
                return new MarkShippingRequestBuilder(request);
            }

            if (request is UpdateProductImageRequest)
            {
                return new UpdateProductImageRequestBuilder(request);
            }

            return null;
        }
コード例 #2
0
        /// <summary>
        /// Handles sync request
        /// </summary>
        /// <param name="syncRequest">Sync Request</param>
        public void Handle(ISyncRequest syncRequest)
        {

            SyncDescriptor syncDescriptor = resourceManager.GetSyncDescriptor(syncRequest.GetName());

            long requestTimestamp = 0;
            if (requestTimestamps.ContainsKey(syncRequest))
            {
                requestTimestamp = requestTimestamps[syncRequest];
            }

            if (requestTimestamp <= 0)
            {
                syncWorker.AddRequest(syncRequest);
                requestTimestamps.Add(syncRequest, DateTime.Now.Ticks);

                return;
            }


            long syncInterval = syncDescriptor.GetSyncInterval();
            long lastRefreshTimestamp = requestTimestamps[syncRequest];
            long currentTimestamp = DateTime.Now.Ticks;

            long timeDifference = lastRefreshTimestamp + syncInterval;

            if (timeDifference < currentTimestamp)
            {
                syncWorker.AddRequest(syncRequest);
                requestTimestamps.Add(syncRequest, DateTime.Now.Ticks);
            }
        }
コード例 #3
0
ファイル: SyncRouterService.cs プロジェクト: ganesum/Autumn
        public ISyncResponse Execute(ISyncRequest request)
        {
            try
            {
                _log.DebugFormat("Recieved sync request : {0}, Id - {1} @ {2}", request.GetType().Name, request.Id, DateTime.Now);

                var router = IoC.Container.Resolve <ISyncRouter>();

                var response = router.ExecuteRequest(request);

                _log.DebugFormat("Returning sync request : {0}, Id - {1} @ {2}", request.GetType().Name, request.Id, DateTime.Now);

                return(response);
            }
            catch (Exception ex)
            {
                _log.DebugFormat("Failed sync request : {0}, Id - {1} @ {2}. {3}", request.GetType().Name, request.Id, DateTime.Now, ex.Message);

                var genericFault = new GenericFault
                {
                    Operation = request.GetType().FullName,
                    Message   = ex.Message
                };

                throw new FaultException <GenericFault>(genericFault, ex.Message);
            }
        }
コード例 #4
0
        /// <summary>
        /// Handles sync request
        /// </summary>
        /// <param name="syncRequest">Sync Request</param>
        public void Handle(ISyncRequest syncRequest)
        {
            SyncDescriptor syncDescriptor = resourceManager.GetSyncDescriptor(syncRequest.GetName());

            long requestTimestamp = 0;

            if (requestTimestamps.ContainsKey(syncRequest))
            {
                requestTimestamp = requestTimestamps[syncRequest];
            }

            if (requestTimestamp <= 0)
            {
                syncWorker.AddRequest(syncRequest);
                requestTimestamps.Add(syncRequest, DateTime.Now.Ticks);

                return;
            }


            long syncInterval         = syncDescriptor.GetSyncInterval();
            long lastRefreshTimestamp = requestTimestamps[syncRequest];
            long currentTimestamp     = DateTime.Now.Ticks;

            long timeDifference = lastRefreshTimestamp + syncInterval;

            if (timeDifference < currentTimestamp)
            {
                syncWorker.AddRequest(syncRequest);
                requestTimestamps.Add(syncRequest, DateTime.Now.Ticks);
            }
        }
コード例 #5
0
ファイル: SyncRouterService.cs プロジェクト: ganesum/Autumn
        public ISyncResponse Execute(ISyncRequest request)
        {
            try
            {
                _log.DebugFormat("Recieved sync request : {0}, Id - {1} @ {2}", request.GetType().Name, request.Id, DateTime.Now);

                var router = IoC.Container.Resolve<ISyncRouter>();

                var response = router.ExecuteRequest(request);

                _log.DebugFormat("Returning sync request : {0}, Id - {1} @ {2}", request.GetType().Name, request.Id, DateTime.Now);

                return response;
            }
            catch (Exception ex)
            {
                _log.DebugFormat("Failed sync request : {0}, Id - {1} @ {2}. {3}", request.GetType().Name, request.Id, DateTime.Now, ex.Message);

                var genericFault = new GenericFault
                                   {
                                       Operation = request.GetType().FullName,
                                       Message = ex.Message
                                   };

                throw new FaultException<GenericFault>(genericFault, ex.Message);
            }
        }
コード例 #6
0
        internal void GetChangesRequest(ISyncRequest <TId> request)
        {
            var conflictIds = ConflictingItems.Select(i => i.Id);
            var requestIds  = request.Select(i => i.Id);

            ChangesRequest = requestIds.Except(conflictIds);
        }
コード例 #7
0
ファイル: SyncWorker.cs プロジェクト: gitter-badger/connect-1
        public void AddRequest(IRequest request)
        {
            ISyncRequest syncRequest = (ISyncRequest)request;

            if (ContainsRequest(syncRequest))
            {
                return;
            }


            syncRequests.Add(syncRequest);

            /*
             * Fire Sync Queued Event
             */
            ISyncEvents syncEventHandler = resourceManager.GetSyncEventHandler();

            if (syncEventHandler != null)
            {
                syncEventHandler.OnQueue(syncRequest);
            }


            if (!IsWorkerRunning())
            {
                StartWorker();
            }
        }
コード例 #8
0
        /// <summary>
        ///     compares knowledge request to itself (local replica) by comparing individual
        ///     item versions to the ITC stamps received (from destination).
        /// </summary>
        /// <param name="syncRequest"></param>
        /// <returns>
        ///     SyncResult contains:
        ///     1) all conflicting items
        ///     (including normal item content and ID and ITC stamp info)
        ///     2) local items changes with ID and ITC stamp info.
        ///     (including normal item content and ID and ITC stamp info)
        ///     3) ChangesRequest: IDs of items found in KnowledgeRequest
        ///     that are not in conflict and do not already exist (with the same ITC stamp)
        ///     at the local repository
        /// </returns>
        public ISyncResult <TItem, TId> FulfillSyncRequest(ISyncRequest <TId> syncRequest)
        {
            var syncResult = _container.Resolve <ISyncResult <TItem, TId> >();

            syncResult.Build(syncRequest);
            return(syncResult);
        }
コード例 #9
0
ファイル: ImageBuilder.cs プロジェクト: shimerlj/ytoo.service
        /// <summary>
        /// 构建商品图片
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="request"></param>
        private void BuildProductImages(ProductEntity entity, ISyncRequest request)
        {
#if !DEBUG
            using (var db = DbContextHelper.GetDbContext())
            {
                int idx = 1;
                var moreImg = new StringBuilder();
                // reset images for product
                for (int i = 0; i < 5; i++)
                {
                    request.Put(string.Format("uploadPicInfo{0}", ++i), "null");
                }
                request.Put("moreImg", "null");

                var resource =
                    db.Resources.Where(
                        t =>
                            t.SourceId == entity.Id && t.Type == 1 && t.SourceType == (int) SourceType.Product &&
                            t.Status == (int) DataStatus.Normal && t.ColorId.HasValue)
                        .GroupBy(t => t.ColorId, (key, resources) => new{color = key,images = resources}).OrderByDescending(x=>x.images.Count()).FirstOrDefault();

                if (resource == null || !resource.images.Any())
                {
                    throw new WgwSyncException(string.Format("Product {0} has no images",entity.Id));
                }

                foreach (var img in resource.images)
                {
                    var url = string.Format("{0}/{1}_320x0.jpg", WgwConfigHelper.Image_BaseUrl, img.Name);
                    if (idx > 5)
                    {
                        moreImg.Append(url).Append("|");
                    }
                    else
                    {
                        request.Put(string.Format("uploadPicInfo{0}", idx), url);
                    }
                    idx += 1;
                }

                var moreImgStr = moreImg.ToString();
                var len = moreImgStr.Length;
                if (len > 0)
                {
                    request.Put("moreImg", moreImgStr.Substring(0, len - 1));
                }
            }
#else
            request.Put("uploadPicInfo1", "http://ec4.images-amazon.com/images/I/51yQ0l-qvkL._AA135_.jpg");
            request.Put("uploadPicInfo2", "http://ec8.images-amazon.com/images/I/41dBoxFHlyL._AA135_.jpg");
#endif
        }
コード例 #10
0
            public async Task EnqueuePush(ISyncRequest req)
            {
                await sem.WaitAsync();

                if (null == _timer)
                {
                    _timer = new Timer(async state =>
                    {
                        await sem.WaitAsync();
                        using (var scope = serviceProvider.CreateScope())
                        {
                            var pushConfigurationStore = scope.ServiceProvider.GetService <IPushConfigurationStore>();
                            var pushService            = scope.ServiceProvider.GetService <IPushService>();
                            try
                            {
                                var reqs = pushRequests.ToArray();
                                if (reqs.Length > 0)
                                {
                                    var grouped = (await Task.WhenAll(reqs.Select(async request =>
                                    {
                                        var channels = await pushConfigurationStore.GetForOptionsAsync(userId, request.GetChannelOptions());
                                        return(new { request, channels });
                                    })))
                                                  .Where(r => null != r.channels && r.channels.Any())
                                                  .GroupBy(r => r.channels.First().Id, v => v.request);
                                    foreach (var group in grouped)
                                    {
                                        var collection = new PushRequestCollection(group);
                                        try
                                        {
                                            await pushService.Push(group.Key, collection.GetPayload(), collection.GetOptions());
                                        }
                                        catch (Exception e)
                                        {
                                            logger.LogError(e, $"Could not push {collection.GetPayload()} to {group.Key}");
                                        }
                                    }
                                    pushRequests.Clear();
                                }
                            }
                            finally
                            {
                                _timer = null;
                                sem.Release();
                            }
                        }
                    }, null, (int)ThrottleTime.TotalMilliseconds, Timeout.Infinite);
                }
                pushRequests.Add(req);
                sem.Release();
            }
コード例 #11
0
 internal void GetConflictingItems(ISyncRequest <TId> request)
 {
     foreach (SyncItem <TId> syncItem in request)
     {
         var serverItem = Repository.Find(syncItem.Id);
         if (serverItem != null)
         {
             if (ChangeEvaluator.GetWhichChanged(syncItem.Stamp, serverItem.Stamp) == ChangeOccurredIn.Both)
             {
                 _conflictingItems.Add(serverItem);
             }
         }
     }
 }
コード例 #12
0
ファイル: SyncRouter.cs プロジェクト: ganesum/Autumn
        public ISyncResponse ExecuteRequest(ISyncRequest request)
        {
            _log.DebugFormat("Started executing sync request : {0}, Id - {1} @ {2}", request.GetType().Name, request.Id, DateTime.Now);

            var requestType = request.GetType();
            var responseType = _requestResponseService.GetMatchingSyncResponseType(requestType);

            var requestHandlerType = typeof(ISyncRequestHandler<,>).MakeGenericType(requestType, responseType);

            var requestHandler = (ISyncRequestHandler) IoC.Container.Resolve(requestHandlerType);

            var response = requestHandler.Execute(request);

            _log.DebugFormat("Finished executing sync request : {0}, Id - {1} @ {2}", request.GetType().Name, request.Id, DateTime.Now);

            return response;
        }
コード例 #13
0
        public ISyncResponse ExecuteRequest(ISyncRequest request)
        {
            _log.DebugFormat("Started executing sync request : {0}, Id - {1} @ {2}", request.GetType().Name, request.Id, DateTime.Now);

            var requestType  = request.GetType();
            var responseType = _requestResponseService.GetMatchingSyncResponseType(requestType);

            var requestHandlerType = typeof(ISyncRequestHandler <,>).MakeGenericType(requestType, responseType);

            var requestHandler = (ISyncRequestHandler)IoC.Container.Resolve(requestHandlerType);

            var response = requestHandler.Execute(request);

            _log.DebugFormat("Finished executing sync request : {0}, Id - {1} @ {2}", request.GetType().Name, request.Id, DateTime.Now);

            return(response);
        }
コード例 #14
0
ファイル: SyncRequestHandler.cs プロジェクト: ganesum/Autumn
        public ISyncResponse Execute(ISyncRequest request)
        {
            var typedRequest = (TRequest)request;

            _log.DebugFormat("Executing BeforeExecute on sync request : {0}, Id - {1} @ {2}", request.GetType().Name, request.Id, DateTime.Now);

            BeforeExecute(typedRequest);

            _log.DebugFormat("Executing Handle on sync request : {0}, Id - {1} @ {2}", request.GetType().Name, request.Id, DateTime.Now);

            var response = Handle(typedRequest);

            _log.DebugFormat("Executing AfterExecute on sync request : {0}, Id - {1} @ {2}", request.GetType().Name, request.Id, DateTime.Now);

            AfterExecute(response);

            return(response);
        }
コード例 #15
0
ファイル: ImageBuilder.cs プロジェクト: shimerlj/ytoo.service
        /// <summary>
        /// 构建库存和颜色图片
        /// </summary>
        /// <param name="item"></param>
        /// <param name="request"></param>
        private void BuildColorImages(ProductEntity item, ISyncRequest request)
        {
            using (var db = DbContextHelper.GetDbContext())
            {
                var inventories = db.Inventories.Where(i => i.ProductId == item.Id);
                var images = new List<dynamic>();

                foreach (var inventory in inventories)
                {
                    var colorValue = db.ProductPropertyValues.FirstOrDefault(t => t.Id == inventory.PColorId);
                    var color = db.ProductProperties.FirstOrDefault(t => t.Id == colorValue.PropertyId);

                    if (colorValue == null || color == null)
                    {
                        continue;
                    }

                    if (images.Any(x => x.value == colorValue.ValueDesc))
                    {
                        continue;
                    }
                    var img = db.Resources.Where(r => r.SourceId == inventory.ProductId && r.ColorId == inventory.PColorId && r.SourceType == (int)SourceType.Product && r.Status == (int)DataStatus.Normal).OrderByDescending(t=>t.SortOrder).FirstOrDefault();

                    if (img == null)
                    {
                        continue;
                    }
                    images.Add(new { property = color.PropertyDesc, value = colorValue.ValueDesc, url = string.Format("{0}/{1}_120x0.jpg", WgwConfigHelper.Image_BaseUrl, img.Name) });

                }
#if !DEBUG
                var sb = new StringBuilder();
                var colorImgStr = images.Aggregate(sb, (s, img) => sb.AppendFormat("{0}:{1}|{2};", img.property, img.value, img.url),
                   imgs => sb.ToString());

                if (colorImgStr.Length > 0)
                {
                    request.Put("stockAttrImgs", colorImgStr.Substring(0, colorImgStr.Length - 1));
                }
#else
                request.Put("stockAttrImgs", "颜色:花色|http://ec4.images-amazon.com/images/I/51%2B6RQwwhkL._SS45_.jpg;颜色:黑色|http://g-ec4.images-amazon.com/images/G/28/fanting_3P/shoes/123._SS75_V363140790_.jpg;颜色:绿色|http://ec4.images-amazon.com/images/I/41NZt4fsPrL._SS45_.jpg");
#endif
            }
        }
コード例 #16
0
ファイル: RequestTask.cs プロジェクト: ganesum/Autumn
        public Task <TResponse> GetAsync <TResponse>(ISyncRequest <TResponse> request)
            where TResponse : ISyncResponse
        {
            return(Task.Factory.StartNew(() =>
            {
                using (var performanceTester = new PerformanceTester())
                {
                    try
                    {
                        request.Id = Guid.NewGuid();

                        _log.Debug(string.Format("Start RequestTask {0}, Id - {1}", request.GetType(), request.Id));

                        using (var routerServiceProxy = _syncRouterServiceProxyFactory())
                        {
                            var response = routerServiceProxy.Execute(request);

                            _log.Debug(string.Format("Finished RequestTask {0}, Id - {1}. Duration {2}",
                                                     request.GetType(),
                                                     request.Id,
                                                     performanceTester.Result.Milliseconds));

                            return (TResponse)response;
                        }
                    }
                    catch (FaultException <GenericFault> faultException)
                    {
                        throw new RequestException(string.Format("RequestTask failed for {0}, Id - {1}. Reason '{2}'",
                                                                 request.GetType(),
                                                                 request.Id,
                                                                 faultException.Detail.Message),
                                                   faultException);
                    }
                    catch (Exception exception)
                    {
                        throw new RequestException(string.Format("RequestTask failed for {0}, Id - {1}", request.GetType(), request.Id), exception);
                    }
                }
            }));
        }
コード例 #17
0
        public ItemRequestParamsBuilder(ISyncRequest request)
            : base(request)
        {

        }
コード例 #18
0
        /// <summary>
        /// 同步订单
        /// </summary>
        /// <param name="request"></param>
        private void SyncOrdersFromWgw(ISyncRequest request)
        {
            var result = Client.Execute<dynamic>(request);

            if (result.errorCode == 0)
            {
                foreach (var order in result.dealList.dealListVo)
                {
                    var detailRequest = new QueryOrderDetailRequest(order.dealCode.ToString());
                    var detail = Client.Execute<dynamic>(detailRequest);
                    var processor = OrderPrcossorFactory.CreateProcessor(request.RequestParams["dealState"]);
                    if (!processor.Process(order, detail))
                    {
                        _failedCount += 1;
                        Logger.Error(string.Format("Failed to load order detail {0},Error Message{1}", order.dealCode, processor.ErrorMessage));
                    }
                    else
                    {
                        _succeedCount += 1;
                    }
                }
                var maxPage = result.dealList.maxPageNo;
                var currentPage = result.dealList.currPage;
                while (currentPage < maxPage)
                {
                    request.Put("pageindex", currentPage += 1);
                    request.Remove("sign");
                    SyncOrdersFromWgw(request);
                }
            }
            else
            {
                Logger.Error(string.Format("Failed to load order list:{0}", result.errorMessage));
            }
        }
コード例 #19
0
ファイル: SyncWorker.cs プロジェクト: gitter-badger/connect-1
        public void HandleRequests()
        {
            IEnumerator <ISyncRequest> requests       = syncRequests.GetEnumerator();
            ICollection <ISyncRequest> removeRequests = new List <ISyncRequest>();

            while (requests.MoveNext())
            {
                ISyncRequest syncRequest = requests.Current;

                /*
                 * Fire Sync Started Event
                 */
                ISyncEvents syncEventHandler = resourceManager.GetSyncEventHandler();
                if (syncEventHandler != null)
                {
                    syncEventHandler.OnStart(syncRequest);
                }


                /*
                 * Process Request
                 */
                SyncDescriptor refreshDescriptor = resourceManager.GetSyncDescriptor(syncRequest.GetName());

                IEnumerator <String> services = refreshDescriptor.GetServiceDescriptorNames();
                while (services.MoveNext())
                {
                    String service = services.Current;

                    String serviceName = service.Substring(0, service.IndexOf(Constants.SYNC_DESCRIPTOR_SERVICE_SEPARATOR));
                    String requestName = service.Substring(service.IndexOf(Constants.SYNC_DESCRIPTOR_SERVICE_SEPARATOR) + 1, service.Length - (service.IndexOf(Constants.SYNC_DESCRIPTOR_SERVICE_SEPARATOR) + 1));


                    ServiceDescriptor         serviceDescriptor = resourceManager.RequiredServiceDescriptorBasedOnName(serviceName);
                    ServiceDescriptor.Request api = serviceDescriptor.GetRequest(requestName);

                    String apiHandler = api.GetHandler();

                    IService serviceHandler = (IService)ClassUtils.CreateClassInstance(apiHandler);
                    serviceHandler.SetServiceDescriptor(serviceDescriptor);

                    IEnumerator <String> resources = syncRequest.GetResources();
                    while (resources.MoveNext())
                    {
                        String resourceName  = resources.Current;
                        Object resourceValue = syncRequest.GetResource(resourceName);

                        serviceHandler.AddResource(resourceName, resourceValue);
                    }


                    serviceHandler.Invoke();
                }


                /*
                 * Fire Sync Started Event
                 */
                if (syncEventHandler != null)
                {
                    syncEventHandler.OnFinish(syncRequest);
                }


                removeRequests.Add(syncRequest);
            }

            foreach (ISyncRequest removeRequest in removeRequests)
            {
                syncRequests.Remove(removeRequest);
            }

            syncWorkerThread = null;
        }
コード例 #20
0
 public ISyncResult <TItem, TId> SendInitialRequest(ISyncRequest <TId> request)
 {
     return(_receiver.FulfillSyncRequest(request));
 }
コード例 #21
0
 public void Build(ISyncRequest <TId> request)
 {
     GetConflictingItems(request);
     GetChangesRequest(request);
     GetFulfillingReplicaItemChanges(request);
 }
コード例 #22
0
 internal void GetFulfillingReplicaItemChanges(ISyncRequest <TId> request)
 {
     FulfillingReplicaItemChanges = Repository.GetChangesSince(request.RequestingReplica.LastSyncTime);
 }
コード例 #23
0
 public UpdateProductImageRequestBuilder(ISyncRequest request) : base(request)
 {
 }
コード例 #24
0
ファイル: ImageBuilder.cs プロジェクト: shimerlj/ytoo.service
 /// <summary>
 /// 构建商品图片信息
 /// </summary>
 /// <param name="request"></param>
 /// <param name="product"></param>
 public void BuildImage(ISyncRequest request, ProductEntity product)
 {
     this.BuildProductImages(product,request);
     this.BuildColorImages(product,request);
 }
コード例 #25
0
        internal ISyncResult <TItem, TId> SendSyncRequestToRemoteReplica(ISyncRequest <TId> syncRequest)
        {
            var sender = _container.Resolve <ISyncRequestSender <TItem, TId> >();

            return(sender.SendInitialRequest(syncRequest));
        }
コード例 #26
0
 public CloseOrderRequestBuilder(ISyncRequest request) : base(request)
 {
 }
コード例 #27
0
 public UpdateItemMultiStockRequestBuilder(ISyncRequest request) : base(request)
 {
 }
コード例 #28
0
 /// <summary>
 /// Check whether it contains sync request or not
 /// </summary>
 /// <param name="syncRequest">Sync Request</param>
 /// <returns>(true/false) TRUE: If it contains sync request | FALSE: If it does not contains request</returns>
 public bool Contain(ISyncRequest syncRequest)
 {
     return(false);
 }
コード例 #29
0
 /// <summary>
 /// Removes sync request
 /// </summary>
 /// <param name="syncRequest">Sync Request</param>
 public void Remove(ISyncRequest syncRequest)
 {
 }
コード例 #30
0
 public ISyncResponse Execute(ISyncRequest request)
 {
     return(Channel.Execute(request));
 }
コード例 #31
0
 public ItemStatusExecutor(DateTime benchTime, ILog logger, UpOrDownItemRequest request)
     : base(benchTime, logger)
 {
     this._request = request;
 }
コード例 #32
0
 /// <summary>
 /// Check whether it contains sync request or not
 /// </summary>
 /// <param name="syncRequest">Sync Request</param>
 /// <returns>(true/false) TRUE: If it contains sync request | FALSE: If it does not contains request</returns>
 public bool Contain(ISyncRequest syncRequest)
 {
     return false;
 }
コード例 #33
0
 public QueryOrderRequestBuilder(ISyncRequest request) : base(request)
 {
 }
コード例 #34
0
ファイル: StockBuilder.cs プロジェクト: shimerlj/ytoo.service
 public StockBuilder(ISyncRequest request, ProductEntity item)
 {
     this._request = request;
     this._item = item;
 }
コード例 #35
0
        /// <summary>
        /// Removes sync request
        /// </summary>
        /// <param name="syncRequest">Sync Request</param>
        public void Remove(ISyncRequest syncRequest)
        {

        }
コード例 #36
0
 public MarkShippingRequestBuilder(ISyncRequest request) : base(request)
 {
 }
コード例 #37
0
 public async Task PushThrotteled(string userId, ISyncRequest pushRequest)
 {
     var throtteledPushUserService = throtteledPushUserServices.GetOrAdd(userId,
                                                                         new ThrotteledPushUserService(userId, logger, serviceProvider));
     await throtteledPushUserService.EnqueuePush(pushRequest);
 }
コード例 #38
0
 protected RequestParamsBuilder(ISyncRequest request)
 {
     this.Request = request;
 }