Esempio n. 1
0
        private void WriteDocumentsJson(DocumentsOperationContext context, bool metadataOnly, IEnumerable <Document> documentsToWrite,
                                        IncludeDocumentsCommand includeDocs, List <Document> includes)
        {
            HttpContext.Response.Headers["Content-Type"] = "application/json; charset=utf-8";
            using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
            {
                writer.WriteStartObject();
                writer.WritePropertyName("Results");
                writer.WriteDocuments(context, documentsToWrite, metadataOnly);

                includeDocs.Fill(includes);

                writer.WriteComma();
                writer.WritePropertyName("Includes");
                if (includes.Count > 0)
                {
                    writer.WriteDocuments(context, includes, metadataOnly);
                }
                else
                {
                    writer.WriteStartArray();
                    writer.WriteEndArray();
                }

                writer.WriteEndObject();
            }
        }
        public Task GetCollectionDocuments()
        {
            using (ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
                using (context.OpenReadTransaction())
                {
                    var sw        = Stopwatch.StartNew();
                    var pageSize  = GetPageSize();
                    var documents = Database.DocumentsStorage.GetDocumentsInReverseEtagOrder(context, GetStringQueryString("name"), GetStart(), pageSize);

                    int  numberOfResults;
                    long totalDocumentsSizeInBytes;

                    using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                    {
                        writer.WriteStartObject();
                        writer.WritePropertyName("Results");
                        writer.WriteDocuments(context, documents, metadataOnly: false, numberOfResults: out numberOfResults, out totalDocumentsSizeInBytes);
                        writer.WriteEndObject();
                    }

                    AddPagingPerformanceHint(PagingOperationType.Documents, "Collection", HttpContext.Request.QueryString.Value, numberOfResults, pageSize, sw.ElapsedMilliseconds, totalDocumentsSizeInBytes);
                }

            return(Task.CompletedTask);
        }
Esempio n. 3
0
 private void WriteRevisionsJson(JsonOperationContext context, bool metadataOnly, IEnumerable <Document> documentsToWrite, out long numberOfResults)
 {
     using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
     {
         writer.WriteStartObject();
         writer.WritePropertyName(nameof(GetDocumentsResult.Results));
         writer.WriteDocuments(context, documentsToWrite, metadataOnly, out numberOfResults);
         writer.WriteEndObject();
     }
 }
Esempio n. 4
0
        private void GetDocuments(DocumentsOperationContext context, bool metadataOnly)
        {
            var sw = Stopwatch.StartNew();

            // everything here operates on all docs
            var databaseChangeVector = DocumentsStorage.GetDatabaseChangeVector(context);

            if (GetStringFromHeaders("If-None-Match") == databaseChangeVector)
            {
                HttpContext.Response.StatusCode = (int)HttpStatusCode.NotModified;
                return;
            }
            HttpContext.Response.Headers["ETag"] = "\"" + databaseChangeVector + "\"";

            var etag         = GetLongQueryString("etag", false);
            var start        = GetStart();
            var pageSize     = GetPageSize();
            var isStartsWith = HttpContext.Request.Query.ContainsKey("startsWith");

            IEnumerable <Document> documents;

            if (etag != null)
            {
                documents = Database.DocumentsStorage.GetDocumentsFrom(context, etag.Value, start, pageSize);
            }
            else if (isStartsWith)
            {
                documents = Database.DocumentsStorage.GetDocumentsStartingWith(context,
                                                                               HttpContext.Request.Query["startsWith"],
                                                                               HttpContext.Request.Query["matches"],
                                                                               HttpContext.Request.Query["exclude"],
                                                                               HttpContext.Request.Query["startAfter"],
                                                                               start,
                                                                               pageSize);
            }
            else // recent docs
            {
                documents = Database.DocumentsStorage.GetDocumentsInReverseEtagOrder(context, start, pageSize);
            }

            int numberOfResults;

            using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
            {
                writer.WriteStartObject();
                writer.WritePropertyName("Results");

                writer.WriteDocuments(context, documents, metadataOnly, out numberOfResults);

                writer.WriteEndObject();
            }

            AddPagingPerformanceHint(PagingOperationType.Documents, isStartsWith ? nameof(DocumentsStorage.GetDocumentsStartingWith) : nameof(GetDocuments), HttpContext, numberOfResults, pageSize, sw.Elapsed);
        }
Esempio n. 5
0
        public Task StreamDocsGet()
        {
            var start    = GetStart();
            var pageSize = GetPageSize();

            using (Database.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
                using (context.OpenReadTransaction())
                {
                    var initialState = new DocsStreamingIterationState(context, Database.Configuration.Databases.PulseReadTransactionLimit)
                    {
                        Start = start,
                        Take  = pageSize
                    };

                    if (HttpContext.Request.Query.ContainsKey("startsWith"))
                    {
                        initialState.StartsWith = HttpContext.Request.Query["startsWith"];
                        initialState.Excludes   = HttpContext.Request.Query["excludes"];
                        initialState.Matches    = HttpContext.Request.Query["matches"];
                        initialState.StartAfter = HttpContext.Request.Query["startAfter"];
                        initialState.Skip       = new Reference <long>();
                    }

                    var documentsEnumerator = new PulsedTransactionEnumerator <Document, DocsStreamingIterationState>(context, state =>
                    {
                        if (string.IsNullOrEmpty(state.StartsWith) == false)
                        {
                            return(Database.DocumentsStorage.GetDocumentsStartingWith(context, state.StartsWith, state.Matches, state.Excludes, state.StartAfter,
                                                                                      state.LastIteratedEtag == null ? state.Start : 0, // if we iterated already some docs then we pass 0 as Start and rely on state.Skip
                                                                                      state.Take,
                                                                                      state.Skip));
                        }

                        if (state.LastIteratedEtag != null)
                        {
                            return(Database.DocumentsStorage.GetDocumentsInReverseEtagOrderFrom(context, state.LastIteratedEtag.Value, state.Take, skip: 1)); // we seek to LastIteratedEtag but skip 1 item because we iterated it already
                        }
                        return(Database.DocumentsStorage.GetDocumentsInReverseEtagOrder(context, state.Start, state.Take));
                    },
                                                                                                                      initialState);

                    using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                    {
                        writer.WriteStartObject();
                        writer.WritePropertyName("Results");

                        writer.WriteDocuments(context, documentsEnumerator, metadataOnly: false, numberOfResults: out long _);

                        writer.WriteEndObject();
                    }
                }

            return(Task.CompletedTask);
        }
Esempio n. 6
0
        private void GetRevisions(DocumentsOperationContext context, bool metadataOnly)
        {
            var sw = Stopwatch.StartNew();

            var id       = GetQueryStringValueAndAssertIfSingleAndNotEmpty("id");
            var before   = GetDateTimeQueryString("before");
            var start    = GetStart();
            var pageSize = GetPageSize();

            Document[] revisions = Array.Empty <Document>();
            long       count     = 0;

            if (before != null)
            {
                var revision = Database.DocumentsStorage.RevisionsStorage.GetRevisionBefore(context, id, before.Value);
                if (revision != null)
                {
                    count     = 1;
                    revisions = new[] { revision };
                }
            }
            else
            {
                (revisions, count) = Database.DocumentsStorage.RevisionsStorage.GetRevisions(context, id, start, pageSize);
            }


            var actualChangeVector = revisions.Length == 0 ? "" : revisions[0].ChangeVector;

            if (GetStringFromHeaders("If-None-Match") == actualChangeVector)
            {
                HttpContext.Response.StatusCode = (int)HttpStatusCode.NotModified;
                return;
            }

            HttpContext.Response.Headers["ETag"] = "\"" + actualChangeVector + "\"";

            int loadedRevisionsCount;

            using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
            {
                writer.WriteStartObject();
                writer.WritePropertyName("Results");
                writer.WriteDocuments(context, revisions, metadataOnly, out loadedRevisionsCount);

                writer.WriteComma();

                writer.WritePropertyName("TotalResults");
                writer.WriteInteger(count);
                writer.WriteEndObject();
            }

            AddPagingPerformanceHint(PagingOperationType.Revisions, nameof(GetRevisions), HttpContext.Request.QueryString.Value, loadedRevisionsCount, pageSize, sw.ElapsedMilliseconds);
        }
Esempio n. 7
0
        public Task GetRevisionsBin()
        {
            var revisionsStorage = Database.DocumentsStorage.RevisionsStorage;

            if (revisionsStorage.Configuration == null)
            {
                throw new RevisionsDisabledException();
            }

            var sw       = Stopwatch.StartNew();
            var etag     = GetLongQueryString("etag", false) ?? long.MaxValue;
            var pageSize = GetPageSize();

            using (ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
                using (context.OpenReadTransaction())
                {
                    revisionsStorage.GetLatestRevisionsBinEntryEtag(context, etag, out var actualChangeVector);
                    if (actualChangeVector != null)
                    {
                        if (GetStringFromHeaders("If-None-Match") == actualChangeVector)
                        {
                            HttpContext.Response.StatusCode = (int)HttpStatusCode.NotModified;
                            return(Task.CompletedTask);
                        }

                        HttpContext.Response.Headers["ETag"] = "\"" + actualChangeVector + "\"";
                    }

                    int  count;
                    long totalDocumentsSizeInBytes;

                    using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                    {
                        writer.WriteStartObject();
                        writer.WritePropertyName("Results");

                        var revisions = revisionsStorage.GetRevisionsBinEntries(context, etag, pageSize);
                        writer.WriteDocuments(context, revisions, false, out count, out totalDocumentsSizeInBytes);

                        writer.WriteEndObject();
                    }

                    AddPagingPerformanceHint(PagingOperationType.Revisions, nameof(GetRevisionsBin), HttpContext.Request.QueryString.Value, count, pageSize, sw.ElapsedMilliseconds, totalDocumentsSizeInBytes);
                }

            return(Task.CompletedTask);
        }
Esempio n. 8
0
        public Task GetCollectionDocuments()
        {
            DocumentsOperationContext context;

            using (ContextPool.AllocateOperationContext(out context))
                using (context.OpenReadTransaction())
                {
                    var documents = Database.DocumentsStorage.GetDocumentsInReverseEtagOrder(context, GetStringQueryString("name"), GetStart(), GetPageSize());

                    using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                    {
                        writer.WriteDocuments(context, documents, metadataOnly: false);
                    }
                }

            return(Task.CompletedTask);
        }
Esempio n. 9
0
        public Task GetResolvedConflictsSince()
        {
            var since = GetStringQueryString("since", required: false);
            var take  = GetIntValueQueryString("take", required: false) ?? 1024;
            var date  = Convert.ToDateTime(since).ToUniversalTime();

            using (ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
                using (context.OpenReadTransaction())
                    using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                    {
                        writer.WriteStartObject();
                        writer.WritePropertyName("Results");
                        var revisions = Database.DocumentsStorage.RevisionsStorage.GetResolvedDocumentsSince(context, date, take);
                        writer.WriteDocuments(context, revisions, false, out _);
                        writer.WriteEndObject();
                    }
            return(Task.CompletedTask);
        }
Esempio n. 10
0
        private Task GetRevisions()
        {
            var id           = GetQueryStringValueAndAssertIfSingleAndNotEmpty("id");
            var metadataOnly = GetBoolValueQueryString("metadata-only", required: false) ?? false;

            using (ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
                using (context.OpenReadTransaction())
                {
                    var revisionsStorage = Database.DocumentsStorage.RevisionsStorage;

                    var sw        = Stopwatch.StartNew();
                    var start     = GetStart();
                    var pageSize  = GetPageSize();
                    var revisions = revisionsStorage.GetRevisions(context, id, start, pageSize);

                    var actualChangeVector = revisions.Revisions.Length == 0 ? "" : revisions.Revisions[0].ChangeVector;

                    if (GetStringFromHeaders("If-None-Match") == actualChangeVector)
                    {
                        HttpContext.Response.StatusCode = (int)HttpStatusCode.NotModified;
                        return(Task.CompletedTask);
                    }

                    HttpContext.Response.Headers["ETag"] = "\"" + actualChangeVector + "\"";

                    int count;
                    using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                    {
                        writer.WriteStartObject();
                        writer.WritePropertyName("Results");
                        writer.WriteDocuments(context, revisions.Revisions, metadataOnly, out count);

                        writer.WriteComma();

                        writer.WritePropertyName("TotalResults");
                        writer.WriteInteger(revisions.Count);
                        writer.WriteEndObject();
                    }

                    AddPagingPerformanceHint(PagingOperationType.Revisions, nameof(GetRevisions), HttpContext, count, pageSize, sw.Elapsed);
                }

            return(Task.CompletedTask);
        }
Esempio n. 11
0
        public Task GetRevisionsFor()
        {
            var versioningStorage = Database.BundleLoader.VersioningStorage;

            if (versioningStorage == null)
            {
                throw new InvalidOperationException("Versioning is disabled");
            }

            var key = GetQueryStringValueAndAssertIfSingleAndNotEmpty("key");

            DocumentsOperationContext context;

            using (ContextPool.AllocateOperationContext(out context))
                using (context.OpenReadTransaction())
                {
                    int start     = GetIntValueQueryString("start", false) ?? 0;
                    int take      = GetIntValueQueryString("pageSize", false) ?? 25;
                    var revisions = versioningStorage.GetRevisions(context, key, start, take).ToList();

                    long actualEtag = revisions.Count == 0 ? int.MinValue : revisions[revisions.Count - 1].Etag;
                    if (GetLongFromHeaders("If-None-Match") == actualEtag)
                    {
                        HttpContext.Response.StatusCode = 304;
                        return(Task.CompletedTask);
                    }

                    HttpContext.Response.Headers["Content-Type"] = "application/json; charset=utf-8";
                    HttpContext.Response.Headers["ETag"]         = actualEtag.ToString();

                    using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                    {
                        writer.WriteStartObject();
                        writer.WritePropertyName("Results");
                        writer.WriteDocuments(context, revisions, false);
                        writer.WriteEndObject();
                    }
                }

            return(Task.CompletedTask);
        }
Esempio n. 12
0
        public Task StreamDocsGet()
        {
            var transformerName = GetStringQueryString("transformer", required: false);
            var start           = GetStart();
            var pageSize        = GetPageSize();

            using (Database.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
                using (context.OpenReadTransaction())
                {
                    IEnumerable <Document> documents;
                    if (HttpContext.Request.Query.ContainsKey("startsWith"))
                    {
                        documents = Database.DocumentsStorage.GetDocumentsStartingWith(context,
                                                                                       HttpContext.Request.Query["startsWith"],
                                                                                       HttpContext.Request.Query["matches"],
                                                                                       HttpContext.Request.Query["excludes"],
                                                                                       HttpContext.Request.Query["startAfter"],
                                                                                       start,
                                                                                       pageSize);
                    }
                    else // recent docs
                    {
                        documents = Database.DocumentsStorage.GetDocumentsInReverseEtagOrder(context, start, pageSize);
                    }

                    using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                    {
                        writer.WriteStartObject();
                        writer.WritePropertyName("Results");

                        writer.WriteDocuments(context, documents, metadataOnly: false, numberOfResults: out int _);

                        writer.WriteEndObject();
                    }
                }

            return(Task.CompletedTask);
        }
Esempio n. 13
0
        private void WriteDocumentsJson(JsonOperationContext context, bool metadataOnly, IEnumerable <Document> documentsToWrite, List <Document> includes, out int numberOfResults)
        {
            using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
            {
                writer.WriteStartObject();
                writer.WritePropertyName(nameof(GetDocumentResult.Results));
                writer.WriteDocuments(context, documentsToWrite, metadataOnly, out numberOfResults);

                writer.WriteComma();
                writer.WritePropertyName(nameof(GetDocumentResult.Includes));
                if (includes.Count > 0)
                {
                    writer.WriteIncludes(context, includes);
                }
                else
                {
                    writer.WriteStartObject();
                    writer.WriteEndObject();
                }

                writer.WriteEndObject();
            }
        }
Esempio n. 14
0
        private Task GetRevision(string changeVector)
        {
            using (ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
                using (context.OpenReadTransaction())
                {
                    var revisionsStorage = Database.DocumentsStorage.RevisionsStorage;
                    var revision         = revisionsStorage.GetRevision(context, changeVector);
                    if (revision == null)
                    {
                        HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                        return(Task.CompletedTask);
                    }

                    using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                    {
                        writer.WriteStartObject();
                        writer.WritePropertyName("Results");
                        writer.WriteDocuments(context, new[] { revision }, metadataOnly: false, numberOfResults: out int _);
                        writer.WriteEndObject();
                    }
                }

            return(Task.CompletedTask);
        }
Esempio n. 15
0
        public Task StreamDocsGet()
        {
            var transformerName = GetStringQueryString("transformer", required: false);

            Transformer transformer = null;

            if (string.IsNullOrEmpty(transformerName) == false)
            {
                transformer = Database.TransformerStore.GetTransformer(transformerName);
                if (transformer == null)
                {
                    throw new TransformerDoesNotExistsException("No transformer with the name: " + transformerName);
                }
            }

            DocumentsOperationContext context;

            using (Database.DocumentsStorage.ContextPool.AllocateOperationContext(out context))
                using (context.OpenReadTransaction())
                {
                    var etag = GetLongQueryString("etag", false);
                    IEnumerable <Document> documents;
                    if (etag != null)
                    {
                        documents = Database.DocumentsStorage.GetDocumentsFrom(context, etag.Value, GetStart(), GetPageSize());
                    }
                    else if (HttpContext.Request.Query.ContainsKey("startsWith"))
                    {
                        documents = Database.DocumentsStorage.GetDocumentsStartingWith(context,
                                                                                       HttpContext.Request.Query["startsWith"],
                                                                                       HttpContext.Request.Query["matches"],
                                                                                       HttpContext.Request.Query["excludes"],
                                                                                       GetStart(),
                                                                                       GetPageSize()
                                                                                       );
                    }
                    else // recent docs
                    {
                        documents = Database.DocumentsStorage.GetDocumentsInReverseEtagOrder(context, GetStart(), GetPageSize());
                    }

                    using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                    {
                        writer.WriteStartObject();
                        writer.WritePropertyName("Results");

                        if (transformer != null)
                        {
                            var transformerParameters = GetTransformerParameters(context);

                            using (var scope = transformer.OpenTransformationScope(transformerParameters, null, Database.DocumentsStorage,
                                                                                   Database.TransformerStore, context))
                            {
                                writer.WriteDocuments(context, scope.Transform(documents).ToList(), metadataOnly: false);
                            }
                        }
                        else
                        {
                            writer.WriteDocuments(context, documents, metadataOnly: false);
                        }

                        writer.WriteEndObject();
                    }
                }

            return(Task.CompletedTask);
        }
        public static void WriteQueryResult <TResult, TInclude>(this BlittableJsonTextWriter writer, JsonOperationContext context, QueryResultBase <TResult, TInclude> result, bool metadataOnly, out int numberOfResults, bool partial = false)
        {
            if (partial == false)
            {
                writer.WriteStartObject();
            }

            writer.WritePropertyName(nameof(result.IndexName));
            writer.WriteString(result.IndexName);
            writer.WriteComma();

            var results = (object)result.Results;

            if (results is List <Document> documents)
            {
                writer.WritePropertyName(nameof(result.Results));
                writer.WriteDocuments(context, documents, metadataOnly, out numberOfResults);
                writer.WriteComma();
            }
            else if (results is List <BlittableJsonReaderObject> objects)
            {
                writer.WritePropertyName(nameof(result.Results));
                writer.WriteObjects(context, objects, out numberOfResults);
                writer.WriteComma();
            }
            else
            {
                throw new NotSupportedException($"Cannot write query result of '{typeof(TResult)}' type in '{result.GetType()}'.");
            }

            var includes = (object)result.Includes;

            if (includes is List <Document> includeDocuments)
            {
                writer.WritePropertyName(nameof(result.Includes));
                writer.WriteIncludes(context, includeDocuments);
                writer.WriteComma();
            }
            else if (includes is List <BlittableJsonReaderObject> includeObjects)
            {
                if (includeObjects.Count != 0)
                {
                    throw new NotSupportedException("Cannot write query includes of List<BlittableJsonReaderObject>, but got non zero response");
                }

                writer.WritePropertyName(nameof(result.Includes));
                writer.WriteStartObject();
                writer.WriteEndObject();
                writer.WriteComma();
            }
            else
            {
                throw new NotSupportedException($"Cannot write query includes of '{typeof(TInclude)}' type in '{result.GetType()}'.");
            }

            writer.WritePropertyName(nameof(result.IndexTimestamp));
            writer.WriteString(result.IndexTimestamp.ToString(Default.DateTimeFormatsToWrite));
            writer.WriteComma();

            writer.WritePropertyName(nameof(result.LastQueryTime));
            writer.WriteString(result.LastQueryTime.ToString(Default.DateTimeFormatsToWrite));
            writer.WriteComma();

            writer.WritePropertyName(nameof(result.IsStale));
            writer.WriteBool(result.IsStale);
            writer.WriteComma();

            writer.WritePropertyName(nameof(result.ResultEtag));
            writer.WriteInteger(result.ResultEtag);

            if (partial == false)
            {
                writer.WriteEndObject();
            }
        }
Esempio n. 17
0
        private void GetDocuments(DocumentsOperationContext context, Transformer transformer, bool metadataOnly)
        {
            // everything here operates on all docs
            var actualEtag = ComputeAllDocumentsEtag(context);

            if (GetLongFromHeaders("If-None-Match") == actualEtag)
            {
                HttpContext.Response.StatusCode = 304;
                return;
            }
            HttpContext.Response.Headers["ETag"] = "\"" + actualEtag + "\"";

            var etag = GetLongQueryString("etag", false);
            IEnumerable <Document> documents;
            bool isLoadStartingWith = false;

            if (etag != null)
            {
                documents = Database.DocumentsStorage.GetDocumentsFrom(context, etag.Value, GetStart(), GetPageSize());
            }
            else if (HttpContext.Request.Query.ContainsKey("startsWith"))
            {
                isLoadStartingWith = true;

                documents = Database.DocumentsStorage.GetDocumentsStartingWith(context,
                                                                               HttpContext.Request.Query["startsWith"],
                                                                               HttpContext.Request.Query["matches"],
                                                                               HttpContext.Request.Query["excludes"],
                                                                               GetStart(),
                                                                               GetPageSize()
                                                                               );
            }
            else // recent docs
            {
                documents = Database.DocumentsStorage.GetDocumentsInReverseEtagOrder(context, GetStart(), GetPageSize());
            }


            using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
            {
                if (isLoadStartingWith)
                {
                    writer.WriteStartObject();
                    writer.WritePropertyName("Results");
                }

                if (transformer != null)
                {
                    var transformerParameters = GetTransformerParameters(context);

                    using (var scope = transformer.OpenTransformationScope(transformerParameters, null, Database.DocumentsStorage,
                                                                           Database.TransformerStore, context))
                    {
                        writer.WriteDocuments(context, scope.Transform(documents).ToList(), metadataOnly);
                    }
                }
                else
                {
                    writer.WriteDocuments(context, documents, metadataOnly);
                }

                if (isLoadStartingWith)
                {
                    writer.WriteEndObject();
                }
            }
        }