private async Task <Resource[]> QueryReferenceAsync(IQueryParameters parameters, string correlationIdentifier)
        {
            if (null == parameters)
            {
                throw new ArgumentNullException(nameof(parameters));
            }

            if (string.IsNullOrWhiteSpace(correlationIdentifier))
            {
                throw new ArgumentNullException(nameof(correlationIdentifier));
            }

            if (null == parameters.RequestedAttributePaths || !parameters.RequestedAttributePaths.Any())
            {
                throw new NotSupportedException(FileProviderResources.ExceptionUnsupportedQuery);
            }

            string selectedAttribute = parameters.RequestedAttributePaths.SingleOrDefault();

            if (string.IsNullOrWhiteSpace(selectedAttribute))
            {
                throw new NotSupportedException(FileProviderResources.ExceptionUnsupportedQuery);
            }
            IInformationNotification notificationReferenceQueryAttribute =
                VerboseInformationNotificationFactory.Instance.CreateNotification(
                    selectedAttribute,
                    correlationIdentifier,
                    FileProvider.NotificationIdentifierReferenceQueryAttribute);

            this.Monitor.Inform(notificationReferenceQueryAttribute);

            if
            (
                !string.Equals(
                    selectedAttribute,
                    AttributeNames.Identifier,
                    StringComparison.OrdinalIgnoreCase)
            )
            {
                throw new NotSupportedException(FileProviderResources.ExceptionUnsupportedQuery);
            }

            if (null == parameters.AlternateFilters)
            {
                throw new ArgumentException(FileProviderResources.ExceptionInvalidParameters);
            }

            if (string.IsNullOrWhiteSpace(parameters.SchemaIdentifier))
            {
                throw new ArgumentException(FileProviderResources.ExceptionInvalidParameters);
            }

            string informationAlternateFilterCount = parameters.AlternateFilters.Count.ToString(CultureInfo.InvariantCulture);
            IInformationNotification notificationReferenceQueryFilterCount =
                VerboseInformationNotificationFactory.Instance.CreateNotification(
                    informationAlternateFilterCount,
                    correlationIdentifier,
                    FileProvider.NotificationIdentifierReferenceQueryFilterCount);

            this.Monitor.Inform(notificationReferenceQueryFilterCount);
            if (parameters.AlternateFilters.Count != 1)
            {
                string exceptionMessage =
                    string.Format(
                        CultureInfo.InvariantCulture,
                        FileProviderResources.ExceptionFilterCountTemplate,
                        1,
                        parameters.AlternateFilters.Count);
                throw new NotSupportedException(exceptionMessage);
            }

            IReadOnlyCollection <string> requestedColumns = this.IdentifyRequestedColumns(parameters);

            IFilter filterPrimary = parameters.AlternateFilters.Single();

            if (null == filterPrimary.AdditionalFilter)
            {
                throw new ArgumentException(FileProviderResources.ExceptionInvalidParameters);
            }

            IFilter filterAdditional = filterPrimary.AdditionalFilter;

            if (filterAdditional.AdditionalFilter != null)
            {
                throw new NotSupportedException(FileProviderResources.ExceptionUnsupportedQuery);
            }

            IReadOnlyCollection <IFilter> filters =
                new IFilter[]
            {
                filterPrimary,
                filterAdditional
            };

            IFilter filterIdentifier =
                filters
                .SingleOrDefault(
                    (IFilter item) =>
                    string.Equals(
                        AttributeNames.Identifier,
                        item.AttributePath,
                        StringComparison.OrdinalIgnoreCase));

            if (null == filterIdentifier)
            {
                throw new NotSupportedException(FileProviderResources.ExceptionUnsupportedQuery);
            }

            IRow    row;
            IFilter filterReference =
                filters
                .SingleOrDefault(
                    (IFilter item) =>
                    string.Equals(
                        AttributeNames.Members,
                        item.AttributePath,
                        StringComparison.OrdinalIgnoreCase));

            if (filterReference != null)
            {
                Dictionary <string, string> columns =
                    new Dictionary <string, string>()
                {
                    {
                        AttributeNames.Schemas,
                        parameters.SchemaIdentifier
                    },
                    {
                        AttributeNames.Identifier,
                        filterIdentifier.ComparisonValue
                    },
                    {
                        filterReference.AttributePath,
                        filterReference.ComparisonValue
                    }
                };

                IReadOnlyCollection <IRow> rows = await this.file.Query(columns);

                if (null == rows || !rows.Any())
                {
                    return(new Resource[0]);
                }

                row = await this.file.ReadRow(filterIdentifier.ComparisonValue);
            }
            else
            {
                filterReference =
                    filters
                    .SingleOrDefault(
                        (IFilter item) =>
                        string.Equals(
                            AttributeNames.Manager,
                            item.AttributePath,
                            StringComparison.OrdinalIgnoreCase));
                if (null == filterReference)
                {
                    throw new NotSupportedException(FileProviderResources.ExceptionUnsupportedQuery);
                }

                row = await this.file.ReadRow(filterIdentifier.ComparisonValue);

                if
                (
                    null == row.Columns ||
                    !row
                    .Columns
                    .Any(
                        (KeyValuePair <string, string> columnItem) =>
                        string.Equals(columnItem.Key, filterReference.AttributePath, StringComparison.Ordinal) &&
                        string.Equals(columnItem.Value, filterReference.ComparisonValue, StringComparison.Ordinal))
                )
                {
                    return(new Resource[0]);
                }
            }

            string rowSchema = null;

            if
            (
                !row.Columns.TryGetValue(AttributeNames.Schemas, out rowSchema) ||
                !string.Equals(rowSchema, parameters.SchemaIdentifier, StringComparison.Ordinal)
            )
            {
                return(new Resource[0]);
            }

            IRow            reducedRow      = FileProvider.FilterColumns(row, requestedColumns);
            ResourceFactory resourceFactory = FileProvider.SelectResourceFactoryFor(rowSchema, reducedRow);
            Resource        resource        = resourceFactory.CreateResource();

            Resource[] results =
                new Resource[]
            {
                resource
            };
            return(results);
        }
        public override async Task <Resource> RetrieveAsync(
            IResourceRetrievalParameters parameters,
            string correlationIdentifier)
        {
            if (null == parameters)
            {
                throw new ArgumentNullException(nameof(parameters));
            }

            if (string.IsNullOrWhiteSpace(correlationIdentifier))
            {
                throw new ArgumentNullException(nameof(correlationIdentifier));
            }

            if (null == parameters.ResourceIdentifier)
            {
                throw new ArgumentException(FileProviderResources.ExceptionInvalidParameters);
            }

            if (string.IsNullOrWhiteSpace(parameters.ResourceIdentifier.Identifier))
            {
                throw new ArgumentException(FileProviderResources.ExceptionInvalidResourceIdentifier);
            }

            if (string.IsNullOrWhiteSpace(parameters.SchemaIdentifier))
            {
                throw new ArgumentException(FileProviderResources.ExceptionInvalidParameters);
            }

            IInformationNotification notification =
                VerboseInformationNotificationFactory.Instance.FormatNotification(
                    FileProviderResources.InformationRetrieving,
                    correlationIdentifier,
                    FileProvider.NotificationIdentifierRetrievalStarting,
                    parameters.SchemaIdentifier,
                    parameters.ResourceIdentifier.Identifier);

            this.Monitor.Inform(notification);

            IReadOnlyCollection <string> columnNames = this.IdentifyRequestedColumns(parameters);

            IRow row = await this.file.ReadRow(parameters.ResourceIdentifier.Identifier);

            if (null == row || null == row.Columns)
            {
                return(null);
            }

            string rowSchema = null;

            if
            (
                !row.Columns.TryGetValue(AttributeNames.Schemas, out rowSchema) ||
                !string.Equals(rowSchema, parameters.SchemaIdentifier, StringComparison.Ordinal)
            )
            {
                return(null);
            }

            IRow            reducedRow      = FileProvider.FilterColumns(row, columnNames);
            ResourceFactory resourceFactory = FileProvider.SelectResourceFactoryFor(rowSchema, reducedRow);
            Resource        result          = resourceFactory.CreateResource();

            return(result);
        }
        public override async Task <Resource[]> QueryAsync(IQueryParameters parameters, string correlationIdentifier)
        {
            if (null == parameters)
            {
                throw new ArgumentNullException(nameof(parameters));
            }

            if (string.IsNullOrWhiteSpace(correlationIdentifier))
            {
                throw new ArgumentNullException(nameof(correlationIdentifier));
            }

            if (null == parameters.AlternateFilters)
            {
                throw new ArgumentException(FileProviderResources.ExceptionInvalidParameters);
            }

            if (string.IsNullOrWhiteSpace(parameters.SchemaIdentifier))
            {
                throw new ArgumentException(FileProviderResources.ExceptionInvalidParameters);
            }

            string informationAlternateFilterCount = parameters.AlternateFilters.Count.ToString(CultureInfo.InvariantCulture);
            IInformationNotification notification  =
                VerboseInformationNotificationFactory.Instance.CreateNotification(
                    informationAlternateFilterCount,
                    correlationIdentifier,
                    FileProvider.NotificationIdentifierQueryFilterCount);

            this.Monitor.Inform(notification);
            if (parameters.AlternateFilters.Count != 1)
            {
                string exceptionMessage =
                    string.Format(
                        CultureInfo.InvariantCulture,
                        FileProviderResources.ExceptionFilterCountTemplate,
                        1,
                        parameters.AlternateFilters.Count);
                throw new NotSupportedException(exceptionMessage);
            }

            Resource[] results;
            IFilter    queryFilter = parameters.AlternateFilters.Single();

            if (queryFilter.AdditionalFilter != null)
            {
                results = await this.QueryReferenceAsync(parameters, correlationIdentifier);

                return(results);
            }

            IReadOnlyCollection <string> requestedColumns = this.IdentifyRequestedColumns(parameters);

            if (string.IsNullOrWhiteSpace(queryFilter.AttributePath))
            {
                throw new ArgumentException(FileProviderResources.ExceptionInvalidParameters);
            }

            if (string.IsNullOrWhiteSpace(queryFilter.ComparisonValue))
            {
                throw new ArgumentException(FileProviderResources.ExceptionInvalidParameters);
            }

            Dictionary <string, string> columns =
                new Dictionary <string, string>()
            {
                {
                    AttributeNames.Schemas,
                    parameters.SchemaIdentifier
                },
                {
                    queryFilter.AttributePath,
                    queryFilter.ComparisonValue
                }
            };
            IReadOnlyCollection <IRow> rows = await this.file.Query(columns);

            if (null == rows)
            {
                return(new Resource[0]);
            }

            IList <Resource> resources = new List <Resource>(rows.Count);

            foreach (IRow row in rows)
            {
                string rowSchema = null;
                if
                (
                    !row.Columns.TryGetValue(AttributeNames.Schemas, out rowSchema) ||
                    !string.Equals(rowSchema, parameters.SchemaIdentifier, StringComparison.Ordinal)
                )
                {
                    continue;
                }

                IRow            reducedRow      = FileProvider.FilterColumns(row, requestedColumns);
                ResourceFactory resourceFactory = FileProvider.SelectResourceFactoryFor(rowSchema, reducedRow);
                Resource        resource        = resourceFactory.CreateResource();
                resources.Add(resource);
            }

            results = resources.ToArray();
            return(results);
        }