public void AddDeserializer(ContentType contentType, DeserializerFactory deserializerFactory)
        {
            if (contentType == null)
                throw new ArgumentNullException(nameof(contentType));
            if (deserializerFactory == null)
                throw new ArgumentNullException(nameof(deserializerFactory));

            if (_deserializerFactories.ContainsKey(contentType.MediaType))
                return;

            _deserializerFactories[contentType.MediaType] = deserializerFactory;
        }
Beispiel #2
0
        public void AddMessageDeserializer(ContentType contentType, DeserializerFactory deserializerFactory)
        {
            if (contentType == null)
                throw new ArgumentNullException(nameof(contentType));
            if (deserializerFactory == null)
                throw new ArgumentNullException(nameof(deserializerFactory));

            if (_deserializer.IsValueCreated)
                throw new ConfigurationException("The deserializer has already been created, no additional deserializers can be added.");

            if (_deserializerFactories.ContainsKey(contentType.MediaType))
                return;

            _deserializerFactories[contentType.MediaType] = deserializerFactory;
        }
Beispiel #3
0
        public static AppendObjectCommand Create(IServiceClient client, Uri endpoint, ExecutionContext context,
                                                 AppendObjectRequest request)
        {
            OssUtils.CheckBucketName(request.BucketName);
            OssUtils.CheckObjectKey(request.Key);

            if (request.Content == null)
            {
                throw new ArgumentNullException("request.Content");
            }

            request.ObjectMetadata = request.ObjectMetadata ?? new ObjectMetadata();
            if (request.ObjectMetadata.ContentType == null)
            {
                request.ObjectMetadata.ContentType = HttpUtils.GetContentType(request.Key, null);
            }

            var conf           = OssUtils.GetClientConfiguration(client);
            var originalStream = request.Content;
            var streamLength   = request.Content.Length;

            // setup progress
            var callback = request.StreamTransferProgress;

            if (callback != null)
            {
                originalStream = OssUtils.SetupProgressListeners(originalStream, conf.ProgressUpdateInterval, client, callback);
            }

            // wrap input stream in MD5Stream
            if (conf.EnalbeMD5Check)
            {
                var hashStream = new MD5Stream(originalStream, null, streamLength);
                request.Content = hashStream;
                context.ResponseHandlers.Add(new MD5DigestCheckHandler(hashStream));
            }

            return(new AppendObjectCommand(client, endpoint, context,
                                           DeserializerFactory.GetFactory().CreateAppendObjectReusltDeserializer(),
                                           request));
        }
Beispiel #4
0
 public SmartSqlConfig()
 {
     Settings             = Settings.Default;
     SqlMaps              = new Dictionary <string, SqlMap>();
     Filters              = new FilterCollection();
     ObjectFactoryBuilder = new ExpressionObjectFactoryBuilder();
     TagBuilderFactory    = new TagBuilderFactory();
     TypeHandlerFactory   = new TypeHandlerFactory();
     LoggerFactory        = NullLoggerFactory.Instance;
     DeserializerFactory  = new DeserializerFactory();
     Properties           = new Properties();
     IdGenerators         = new Dictionary <string, IIdGenerator>
     {
         { nameof(SnowflakeId.Default), SnowflakeId.Default }
     };
     DbSessionFactory         = new DbSessionFactory(this);
     SessionStore             = new DbSessionStore(DbSessionFactory);
     StatementAnalyzer        = new StatementAnalyzer();
     InvokeSucceedListener    = new InvokeSucceedListener();
     DbSessionFactory.Opened += (sender, args) => { InvokeSucceedListener.BindDbSessionEvent(args.DbSession); };
 }
        public static CompleteMultipartUploadCommand Create(IServiceClient client, Uri endpoint, ExecutionContext context,
                                                            CompleteMultipartUploadRequest completeMultipartUploadRequest)
        {
            OssUtils.CheckBucketName(completeMultipartUploadRequest.BucketName);
            OssUtils.CheckObjectKey(completeMultipartUploadRequest.Key);

            if (string.IsNullOrEmpty(completeMultipartUploadRequest.UploadId))
            {
                throw new ArgumentException(Resources.ExceptionIfArgumentStringIsNullOrEmpty, "uploadId");
            }

            // handle upload callback error 203
            if (completeMultipartUploadRequest.IsCallbackRequest())
            {
                context.ResponseHandlers.Add(new CallbackResponseHandler());
            }

            return(new CompleteMultipartUploadCommand(client, endpoint, context,
                                                      DeserializerFactory.GetFactory().CreateCompleteUploadResultDeserializer(completeMultipartUploadRequest),
                                                      completeMultipartUploadRequest));
        }
Beispiel #6
0
        public static AppendObjectCommand Create(IServiceClient client, Uri endpoint, ExecutionContext context,
                                                 AppendObjectRequest request)
        {
            OssUtils.CheckBucketName(request.BucketName);
            OssUtils.CheckObjectKey(request.Key);

            if (request.Content == null)
            {
                throw new ArgumentNullException("request.Content");
            }

            request.ObjectMetadata = request.ObjectMetadata ?? new ObjectMetadata();
            if (request.ObjectMetadata.ContentType == null)
            {
                request.ObjectMetadata.ContentType = HttpUtils.GetContentType(request.Key, null);
            }

            return(new AppendObjectCommand(client, endpoint, context,
                                           DeserializerFactory.GetFactory().CreateAppendObjectReusltDeserializer(),
                                           request));
        }
Beispiel #7
0
        public void PrimitiveTypesSequence_SerializeAndDeserializeBack_OriginAndDeserializedAreEqual()
        {
            var origin = new object[]
            {
                "fortyTwo",
                42,
                42d,
                MyEnumDefType.Two,
                MyEnumULongType.Max
            };
            var sequenceTypes = origin.Select(o => o.GetType()).ToArray();

            var serializer   = SerializerFactory.CreateDefault().Create(sequenceTypes);
            var deserializer = DeserializerFactory.CreateDefault().Create(sequenceTypes);
            var stream       = new MemoryStream();

            serializer.Serialize(origin, stream);
            stream.Position = 0;
            var deserialized = (object[])deserializer.Deserialize(stream, (int)stream.Length);

            CollectionAssert.AreEqual(origin, deserialized);
        }
        protected void ErrorHandle(ServiceResponse response)
        {
            // Treats NotModified(Http status code) specially.
            if (response.StatusCode == HttpStatusCode.NotModified)
            {
                throw ExceptionFactory.CreateException(HttpStatusCode.NotModified.ToString(), response.Failure.Message, null, null);
            }

            ErrorResult errorResult = null;

            try
            {
                var deserializer = DeserializerFactory.GetFactory().CreateErrorResultDeserializer();
                if (deserializer == null)
                {
                    // Re-throw the web exception if the response cannot be parsed.
                    response.EnsureSuccessful();
                }
                else
                {
                    errorResult = deserializer.Deserialize(response);
                }
            }
            catch (XmlException)
            {
                // Re-throw the web exception if the response cannot be parsed.
                response.EnsureSuccessful();
            }
            catch (InvalidOperationException)
            {
                // Re-throw the web exception if the response cannot be parsed.
                response.EnsureSuccessful();
            }

            // This throw must be out of the try block because otherwise
            // the exception would be caught be the following catch.
            Debug.Assert(errorResult != null);
            throw ExceptionFactory.CreateException(errorResult.Code, errorResult.Message, errorResult.RequestId, errorResult.HostId);
        }
Beispiel #9
0
        public static PutObjectCommand Create(IServiceClient client, Uri endpoint, ExecutionContext context,
                                              string bucketName, string key,
                                              Stream content, ObjectMetadata metadata)
        {
            OssUtils.CheckBucketName(bucketName);
            OssUtils.CheckObjectKey(key);

            if (content == null)
            {
                throw new ArgumentNullException("content");
            }

            var ossObject = new OssObject(key)
            {
                BucketName = bucketName,
                Content    = content,
                Metadata   = metadata ?? new ObjectMetadata()
            };

            return(new PutObjectCommand(client, endpoint, context,
                                        DeserializerFactory.GetFactory().CreatePutObjectReusltDeserializer(),
                                        ossObject));
        }
Beispiel #10
0
        public void AddMessageDeserializer(ContentType contentType, DeserializerFactory deserializerFactory)
        {
            if (contentType == null)
            {
                throw new ArgumentNullException(nameof(contentType));
            }
            if (deserializerFactory == null)
            {
                throw new ArgumentNullException(nameof(deserializerFactory));
            }

            if (_deserializer.IsValueCreated)
            {
                throw new ConfigurationException("The deserializer has already been created, no additional deserializers can be added.");
            }

            if (_deserializerFactories.ContainsKey(contentType.MediaType))
            {
                return;
            }

            _deserializerFactories[contentType.MediaType] = deserializerFactory;
        }
        static public async Task Handle(HttpResponseMessage response)
        {
            if (!response.IsSuccessStatusCode)
            {
                ErrorResult errorResult = null;
                try
                {
                    IDeserializer <HttpResponseMessage, Task <ErrorResult> > d = DeserializerFactory.GetFactory().CreateErrorResultDeserializer();

                    errorResult = await d.Deserialize(response);
                }
                catch (XmlException ex)
                {
                    throw ex;
                    //response.EnsureSuccessful();
                }
                catch (InvalidOperationException invalidEx)
                {
                    throw invalidEx;
                    //response.EnsureSuccessful();
                }
                throw ExceptionFactory.CreateException(errorResult.Code, errorResult.Message, errorResult.RequestId, errorResult.HostId);
            }
        }
Beispiel #12
0
        public static UploadPartCommand Create(IServiceClient client, Uri endpoint, ExecutionContext context,
                                               UploadPartRequest uploadPartRequest)
        {
            OssUtils.CheckBucketName(uploadPartRequest.BucketName);
            OssUtils.CheckObjectKey(uploadPartRequest.Key);

            if (string.IsNullOrEmpty(uploadPartRequest.UploadId))
            {
                throw new ArgumentException("uploadId should be specified");
            }
            if (!uploadPartRequest.PartNumber.HasValue)
            {
                throw new ArgumentException("partNumber should be specified");
            }
            if (!uploadPartRequest.PartSize.HasValue)
            {
                throw new ArgumentException("partSize should be specified");
            }
            if (uploadPartRequest.InputStream == null)
            {
                throw new ArgumentException("inputStream should be specified");
            }

            if (uploadPartRequest.PartSize < 0 || uploadPartRequest.PartSize > OssUtils.MaxFileSize)
            {
                throw new ArgumentException("partSize not live in valid range");
            }
            if (!OssUtils.IsPartNumberInRange(uploadPartRequest.PartNumber))
            {
                throw new ArgumentException("partNumber not live in valid range");
            }

            return(new UploadPartCommand(client, endpoint, context,
                                         DeserializerFactory.GetFactory().CreateUploadPartResultDeserializer(uploadPartRequest.PartNumber.Value),
                                         uploadPartRequest));
        }
Beispiel #13
0
        public async Task <PutObjectResult> PutObject(string bucketName, string key, Stream content, ObjectMetadata metadata,
                                                      Action <HttpProcessData> uploadProcessCallback = null, CancellationToken?cancellationToken = null)
        {
            PutObjectResult        result = null;
            HttpClientHandler      hand   = null;
            ProgressMessageHandler processMessageHander = null;
            HttpClient             localHttpClient      = null;
            OssHttpRequestMessage  httpRequestMessage   = null;
            HttpResponseMessage    response             = null;

            try
            {
                hand = new HttpClientHandler();
                processMessageHander     = new ProgressMessageHandler(hand);
                localHttpClient          = new HttpClient(processMessageHander);
                localHttpClient.Timeout += new TimeSpan(2 * TimeSpan.TicksPerHour);
                httpRequestMessage       = new OssHttpRequestMessage(bucketName, key);



                httpRequestMessage.Method       = HttpMethod.Put;
                httpRequestMessage.Headers.Date = DateTime.UtcNow;
                httpRequestMessage.Content      = new StreamContent(content);


                OssClientHelper.initialHttpRequestMessage(httpRequestMessage, metadata);



                OssRequestSigner.Sign(httpRequestMessage, networkCredential);

                if (uploadProcessCallback != null)
                {
                    processMessageHander.HttpSendProgress += (sender, e) =>
                    {
                        uploadProcessCallback(new HttpProcessData()
                        {
                            TotalBytes         = e.TotalBytes,
                            BytesTransferred   = e.BytesTransferred,
                            ProgressPercentage = e.ProgressPercentage
                        });
                    };
                }


                if (cancellationToken != null)
                {
                    response = await localHttpClient.SendAsync(httpRequestMessage, (CancellationToken)cancellationToken);
                }
                else
                {
                    response = await localHttpClient.SendAsync(httpRequestMessage);
                }

                if (response.IsSuccessStatusCode == false)
                {
                    await ErrorResponseHandler.Handle(response);
                }

                var temp = DeserializerFactory.GetFactory().CreatePutObjectReusltDeserializer();
                result = temp.Deserialize(response);
                //localHttpClient.Dispose();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (hand != null)
                {
                    hand.Dispose();
                }

                if (processMessageHander != null)
                {
                    processMessageHander.Dispose();
                }

                if (localHttpClient != null)
                {
                    localHttpClient.Dispose();
                }

                if (httpRequestMessage != null)
                {
                    httpRequestMessage.Dispose();
                }


                if (response != null)
                {
                    response.Dispose();
                }
            }

            return(result);
        }
Beispiel #14
0
        public async Task <OssObject> GetObject(GetObjectRequest getObjectRequest,
                                                Action <HttpProcessData> downloadProcessCallback = null, CancellationToken?cancellationToken = null)
        {
            OssObject result = null;

            HttpClientHandler      hand = null;
            ProgressMessageHandler processMessageHander = null;
            HttpClient             localHttpClient      = null;
            OssHttpRequestMessage  httpRequestMessage   = null;
            HttpResponseMessage    response             = null;

            try
            {
                hand = new HttpClientHandler();
                processMessageHander     = new ProgressMessageHandler(hand);
                localHttpClient          = new HttpClient(processMessageHander);
                localHttpClient.Timeout += new TimeSpan(2 * TimeSpan.TicksPerHour);

                httpRequestMessage = new OssHttpRequestMessage(getObjectRequest.BucketName, getObjectRequest.Key);
                getObjectRequest.ResponseHeaders.Populate(httpRequestMessage.Headers);
                getObjectRequest.Populate(httpRequestMessage.Headers);

                httpRequestMessage.Method       = HttpMethod.Get;
                httpRequestMessage.Headers.Date = DateTime.UtcNow;

                OssRequestSigner.Sign(httpRequestMessage, networkCredential);
                if (downloadProcessCallback != null)
                {
                    processMessageHander.HttpReceiveProgress += (sender, e) =>
                    {
                        downloadProcessCallback(new HttpProcessData()
                        {
                            TotalBytes         = e.TotalBytes,
                            BytesTransferred   = e.BytesTransferred,
                            ProgressPercentage = e.ProgressPercentage
                        });;
                    };
                }

                if (cancellationToken != null)
                {
                    response = await localHttpClient.SendAsync(httpRequestMessage, (CancellationToken)cancellationToken);
                }
                else
                {
                    response = await localHttpClient.SendAsync(httpRequestMessage);
                }


                if (response.IsSuccessStatusCode == false)
                {
                    await ErrorResponseHandler.Handle(response);
                }

                var temp = DeserializerFactory.GetFactory().CreateGetObjectResultDeserializer(getObjectRequest);
                result = await temp.Deserialize(response);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (hand != null)
                {
                    hand.Dispose();
                }

                if (processMessageHander != null)
                {
                    processMessageHander.Dispose();
                }

                if (localHttpClient != null)
                {
                    localHttpClient.Dispose();
                }

                if (httpRequestMessage != null)
                {
                    httpRequestMessage.Dispose();
                }
            }


            return(result);
        }
Beispiel #15
0
        public async Task <MultipartUploadResult> MultipartUpload(MultiUploadRequestData multiUploadObject,
                                                                  Action <HttpProcessData> uploadProcessCallback = null, CancellationToken?cancellationToken = null)
        {
            MultipartUploadResult result = null;

            HttpClientHandler      hand = null;
            ProgressMessageHandler processMessageHander = null;
            HttpClient             localHttpClient      = null;
            OssHttpRequestMessage  httpRequestMessage   = null;
            HttpResponseMessage    response             = null;

            try
            {
                hand = new HttpClientHandler();
                processMessageHander     = new ProgressMessageHandler(hand);
                localHttpClient          = new HttpClient(processMessageHander);
                localHttpClient.Timeout += new TimeSpan(2 * TimeSpan.TicksPerHour);

                Dictionary <string, string> parameters = new Dictionary <string, string>();
                parameters.Add("partNumber", multiUploadObject.PartNumber);
                parameters.Add("uploadId", multiUploadObject.UploadId);

                httpRequestMessage = new OssHttpRequestMessage(multiUploadObject.Bucket, multiUploadObject.Key, parameters);

                httpRequestMessage.Method       = HttpMethod.Put;
                httpRequestMessage.Headers.Date = DateTime.UtcNow;
                httpRequestMessage.Content      = new StreamContent(multiUploadObject.Content);

                if (uploadProcessCallback != null)
                {
                    processMessageHander.HttpSendProgress += (sender, e) =>
                    {
                        uploadProcessCallback(new HttpProcessData()
                        {
                            TotalBytes         = e.TotalBytes,
                            BytesTransferred   = e.BytesTransferred,
                            ProgressPercentage = e.ProgressPercentage
                        });
                    };
                }


                OssRequestSigner.Sign(httpRequestMessage, networkCredential);

                if (cancellationToken != null)
                {
                    response = await localHttpClient.SendAsync(httpRequestMessage, (CancellationToken)cancellationToken);
                }
                else
                {
                    response = await localHttpClient.SendAsync(httpRequestMessage);
                }

                if (response.IsSuccessStatusCode == false)
                {
                    await ErrorResponseHandler.Handle(response);
                }
                var deseserializer = DeserializerFactory.GetFactory().CreateMultipartUploadDeserializer();
                result = deseserializer.Deserialize(response);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (hand != null)
                {
                    hand.Dispose();
                }

                if (processMessageHander != null)
                {
                    processMessageHander.Dispose();
                }

                if (localHttpClient != null)
                {
                    localHttpClient.Dispose();
                }

                if (httpRequestMessage != null)
                {
                    httpRequestMessage.Dispose();
                }


                if (response != null)
                {
                    response.Dispose();
                }
            }
            return(result);
        }
 public SupportMessageDeserializerReceiveEndpointSpecification(ContentType contentType, DeserializerFactory deserializerFactory)
 {
     _contentType = contentType;
     _deserializerFactory = deserializerFactory;
 }
Beispiel #17
0
 public void AddMessageDeserializer(ContentType contentType, DeserializerFactory deserializerFactory)
 {
     _serializerBuilder.AddDeserializer(contentType, deserializerFactory);
 }
 public static RestoreObjectCommand Create(IServiceClient client, Uri endpoint,
                                           ExecutionContext context,
                                           string bucketName, string key)
 {
     return(new RestoreObjectCommand(client, endpoint, context, bucketName, key, DeserializerFactory.GetFactory().CreateRestoreObjectResultDeserializer()));
 }
Beispiel #19
0
 public void AddMessageDeserializer(ContentType contentType, DeserializerFactory deserializerFactory)
 {
     _serializerBuilder.AddDeserializer(contentType, deserializerFactory);
 }
 public SupportMessageDeserializerReceiveEndpointSpecification(ContentType contentType, DeserializerFactory deserializerFactory)
 {
     _contentType         = contentType;
     _deserializerFactory = deserializerFactory;
 }
 public SupportMessageDeserializerBusFactorySpecification(ContentType contentType, DeserializerFactory deserializerFactory)
 {
     _contentType         = contentType;
     _deserializerFactory = deserializerFactory;
 }
Beispiel #22
0
        public void EmptyDeserializeFactory_Create_Throws()
        {
            var factory = new DeserializerFactory();

            Assert.Throws <TypeCannotBeDeserializedException>(() => factory.Create(typeof(int)));
        }
 public RestClientOptions()
 {
     DefaultSerializer   = new JsonSerializer();
     DeserializerFactory = new DeserializerFactory(new PlainTextDeserializer());
     DeserializerFactory.AddDeserializer(new JsonDeserializer());
 }
Beispiel #24
0
 void IReceiveEndpointConfigurator.AddMessageDeserializer(ContentType contentType, DeserializerFactory deserializerFactory)
 {
     _configurator.AddMessageDeserializer(contentType, deserializerFactory);
 }
Beispiel #25
0
 public static RestoreObjectCommand Create(IServiceClient client, Uri endpoint,
                                           ExecutionContext context,
                                           RestoreObjectRequest request)
 {
     return(new RestoreObjectCommand(client, endpoint, context, request, DeserializerFactory.GetFactory().CreateRestoreObjectResultDeserializer()));
 }
 public static void Register()
 {
     DeserializerFactory.addFactory(ch.cyberduck.core.Factory.NATIVE_PLATFORM, new Factory());
 }
 public static ListLiveChannelCommand Create(IServiceClient client, Uri endpoint, ExecutionContext context,
                                             ListLiveChannelRequest request)
 {
     return(new ListLiveChannelCommand(client, endpoint, context,
                                       DeserializerFactory.GetFactory().CreateListLiveChannelResultDeserializer(), request));
 }
 public SupportMessageDeserializerBusFactorySpecification(ContentType contentType, DeserializerFactory deserializerFactory)
 {
     _contentType = contentType;
     _deserializerFactory = deserializerFactory;
 }
        public static UploadPartCommand Create(IServiceClient client, Uri endpoint, ExecutionContext context,
                                               UploadPartRequest uploadPartRequest)
        {
            OssUtils.CheckBucketName(uploadPartRequest.BucketName);
            OssUtils.CheckObjectKey(uploadPartRequest.Key);

            if (string.IsNullOrEmpty(uploadPartRequest.UploadId))
            {
                throw new ArgumentException("uploadId should be specified");
            }
            if (!uploadPartRequest.PartNumber.HasValue)
            {
                throw new ArgumentException("partNumber should be specified");
            }
            if (!uploadPartRequest.PartSize.HasValue)
            {
                throw new ArgumentException("partSize should be specified");
            }
            if (uploadPartRequest.InputStream == null)
            {
                throw new ArgumentException("inputStream should be specified");
            }

            if (uploadPartRequest.PartSize < 0 || uploadPartRequest.PartSize > OssUtils.MaxFileSize)
            {
                throw new ArgumentException("partSize not live in valid range");
            }
            if (!OssUtils.IsPartNumberInRange(uploadPartRequest.PartNumber))
            {
                throw new ArgumentException("partNumber not live in valid range");
            }

            var conf           = OssUtils.GetClientConfiguration(client);
            var originalStream = uploadPartRequest.InputStream;
            var streamLength   = uploadPartRequest.PartSize.Value;

            // wrap input stream in PartialWrapperStream
            originalStream = new PartialWrapperStream(originalStream, streamLength);

            // setup progress
            var callback = uploadPartRequest.StreamTransferProgress;

            if (callback != null)
            {
                originalStream = OssUtils.SetupProgressListeners(originalStream, conf.ProgressUpdateInterval, client, callback);
                uploadPartRequest.InputStream = originalStream;
            }

            // wrap input stream in MD5Stream
            if (conf.EnalbeMD5Check)
            {
                var hashStream = new MD5Stream(originalStream, null, streamLength);
                uploadPartRequest.InputStream = hashStream;
                context.ResponseHandlers.Add(new MD5DigestCheckHandler(hashStream));
            }
            else if (conf.EnableCrcCheck)
            {
                var hashStream = new Crc64Stream(originalStream, null, streamLength);
                uploadPartRequest.InputStream = hashStream;
                context.ResponseHandlers.Add(new Crc64CheckHandler(hashStream));
            }

            return(new UploadPartCommand(client, endpoint, context,
                                         DeserializerFactory.GetFactory().CreateUploadPartResultDeserializer(uploadPartRequest.PartNumber.Value, streamLength),
                                         uploadPartRequest));
        }
 public void AddMessageDeserializer(ContentType contentType, DeserializerFactory deserializerFactory)
 {
     _configuration.Serialization.AddDeserializer(contentType, deserializerFactory);
 }
 public static DeleteObjectsCommand Create(IServiceClient client, Uri endpoint, ExecutionContext context, DeleteObjectsRequest deleteObjectsRequest)
 {
     OssUtils.CheckBucketName(deleteObjectsRequest.BucketName);
     return(new DeleteObjectsCommand(client, endpoint, context, DeserializerFactory.GetFactory().CreateDeleteObjectsResultDeserializer(), deleteObjectsRequest));
 }