public void TestCreateUser()
        {
            Uri addressBase = new Uri(WebServiceUnitTest.AddressBase);

            IMonitor monitor = new ConsoleMonitor();

            string fileName = CommaDelimitedFileUnitTest.ComposeFileName();

            FileProviderBase provider = null;
            try
            {
                provider = new FileProvider(fileName);
                Service webService = null;
                try
                {
                    webService = new WebService(monitor, provider);
                    webService.Start(addressBase);

                    IDictionary<string, object> json = ProviderTestTemplate<FileProvider>.ComposeUserResource().ToJson();
                    string characters = WebServiceUnitTest.Serializer.Value.Serialize(json);
                    byte[] bytes = Encoding.UTF8.GetBytes(characters);

                    Uri resource = new Uri(addressBase, WebServiceUnitTest.AddressRelativeUsers);

                    WebClient client = null;
                    try
                    {
                        client = new WebClient();
                        client.Headers.Add(HttpRequestHeader.ContentType, WebServiceUnitTest.ContentTypeJson);
                        byte[] response = client.UploadData(resource.AbsoluteUri, WebRequestMethods.Http.Post, bytes);
                        string responseCharacters = Encoding.UTF8.GetString(response);
                        IReadOnlyDictionary<string, object> responseJson =
                            WebServiceUnitTest.Serializer.Value.Deserialize<Dictionary<string, object>>(responseCharacters);
                        Core2EnterpriseUser user = new Core2EnterpriseUserJsonDeserializingFactory().Create(responseJson);
                        Assert.IsNotNull(user);
                        Assert.IsNotNull(
                            user
                            .Schemas
                            .SingleOrDefault(
                                (string item) =>
                                    string.Equals(
                                        SchemaIdentifiers.Core2EnterpriseUser,
                                        item,
                                        StringComparison.Ordinal)));
                        Assert.IsFalse(string.IsNullOrWhiteSpace(user.Identifier));
                        Assert.IsNotNull(user.Metadata);
                        Assert.IsFalse(string.IsNullOrWhiteSpace(user.Metadata.ResourceType));

                        string resourcePath = string.Concat(WebServiceUnitTest.AddressRelativeUser, user.Identifier);
                        resource = new Uri(addressBase, resourcePath);
                        bytes = new byte[0];
                        client.UploadData(resource, WebServiceUnitTest.MethodDelete, bytes);
                    }
                    finally
                    {
                        if (client != null)
                        {
                            client.Dispose();
                            client = null;
                        }
                    }
                }
                finally
                {
                    if (webService != null)
                    {
                        webService.Dispose();
                        webService = null;
                    }
                }
            }
            finally
            {
                if (provider != null)
                {
                    provider.Dispose();
                    provider = null;
                }
            }
            
        }
        private static void Main(string[] arguments)
        {
            if (null == arguments)
            {
                Console.WriteLine(FileProvisioningAgentResources.InformationCommandLineArguments);
                return;
            }

            if (Program.NumberArguments > arguments.Length)
            {
                Console.WriteLine(FileProvisioningAgentResources.InformationCommandLineArguments);
                return;
            }

            string argumentBaseAddress = arguments[0];
            Uri baseAddress = null;
            if (!Uri.TryCreate(argumentBaseAddress, UriKind.Absolute, out baseAddress))
            {
                Console.WriteLine(FileProvisioningAgentResources.InformationCommandLineArguments);
                return;
            }

            string informationBaseAddress =
                string.Format(
                    CultureInfo.InvariantCulture,
                    ProvisioningAgentResources.InformationBaseAddressTemplate,
                    argumentBaseAddress);
            Console.WriteLine(informationBaseAddress);

            IMonitor monitor = new ConsoleMonitor();
            FileProviderBase provider = null;
            try
            {
                provider = new FileProvider(arguments[1]);
                Service webService = null;
                try
                {
                    webService = new WebService(monitor, provider);
                    webService.Start(baseAddress);

                    string informationStarted =
                        string.Format(
                            CultureInfo.InvariantCulture,
                            ProvisioningAgentResources.InformationAgentStartedTemplate,
                            argumentBaseAddress);
                    Console.WriteLine(informationStarted);

                    Console.WriteLine(ProvisioningAgentResources.PromptTerminate);
                    Console.ReadKey(true);
                }
                finally
                {
                    if (webService != null)
                    {
                        webService.Dispose();
                        webService = null;
                    }
                }
            }
            finally
            {
                if (provider != null)
                {
                    provider.Dispose();
                    provider = null;
                }
            }
        }
        public void TestRetrieveGroup()
        {
            Uri addressBase = new Uri(WebServiceUnitTest.AddressBase);

            IMonitor monitor = new ConsoleMonitor();

            string fileName = CommaDelimitedFileUnitTest.ComposeFileName();

            FileProviderBase provider = null;
            try
            {
                provider = new FileProvider(fileName);
                Service webService = null;
                try
                {
                    webService = new WebService(monitor, provider);
                    webService.Start(addressBase);

                    Guid groupIdentifier = Guid.NewGuid();
                    string resourceRelative =
                        string.Format(
                            CultureInfo.InvariantCulture,
                            WebServiceUnitTest.AddressRelativeGroupTemplate,
                            groupIdentifier);
                    Uri resource = new Uri(addressBase, resourceRelative);

                    HttpWebResponse response = null;

                    WebClient client = null;
                    try
                    {
                        client = new WebClient();
                        try
                        {
                            client.DownloadData(resource);
                        }
                        catch (WebException exception)
                        {
                            response = exception.Response as HttpWebResponse;
                        }
                    }
                    finally
                    {
                        if (client != null)
                        {
                            client.Dispose();
                            client = null;
                        }
                    }

                    Assert.IsNotNull(response);
                    Assert.AreEqual(HttpStatusCode.NotFound, response.StatusCode);
                }
                finally
                {
                    if (webService != null)
                    {
                        webService.Dispose();
                        webService = null;
                    }
                }
            }
            finally
            {
                if (provider != null)
                {
                    provider.Dispose();
                    provider = null;
                }
            }

        }
        public override async Task UpdateAsync(IPatch patch, string correlationIdentifier)
        {
            if (null == patch)
            {
                throw new ArgumentNullException(nameof(patch));
            }

            if (null == patch.ResourceIdentifier)
            {
                throw new ArgumentException(FileProviderResources.ExceptionInvalidPatch);
            }

            if (string.IsNullOrWhiteSpace(patch.ResourceIdentifier.Identifier))
            {
                throw new ArgumentException(FileProviderResources.ExceptionInvalidPatch);
            }

            if (null == patch.PatchRequest)
            {
                throw new ArgumentException(FileProviderResources.ExceptionInvalidPatch);
            }

            IInformationNotification notification =
                VerboseInformationNotificationFactory.Instance.FormatNotification(
                    FileProviderResources.InformationPatching,
                    correlationIdentifier,
                    FileProvider.NotificationIdentifierUpdateStarting,
                    patch.ResourceIdentifier.SchemaIdentifier,
                    patch.ResourceIdentifier.Identifier);

            this.Monitor.Inform(notification);

            PatchRequest2Base <PatchOperation2> patchRequest =
                patch.PatchRequest as PatchRequest2Base <PatchOperation2>;

            if (null == patchRequest)
            {
                string unsupportedPatchTypeName = patch.GetType().FullName;
                throw new NotSupportedException(unsupportedPatchTypeName);
            }

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

            string rowSchema = null;

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

            IReadOnlyDictionary <string, string> columns = FileProvider.Apply(patchRequest, rowSchema, row);
            IRow rowReplacement = new Row(row.Key, columns);

            await this.file.ReplaceRow(rowReplacement);

            if (string.Equals(SchemaIdentifiers.WindowsAzureActiveDirectoryGroup, rowSchema, StringComparison.OrdinalIgnoreCase))
            {
                WindowsAzureActiveDirectoryGroup group = new GroupFactory(row).Create();
                await this.UpdateMembersAsync(group, patch);
            }
        }
        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);
        }
        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[]> 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);
        }