/// <summary>
        /// Refreshes the standard fields cache.
        /// </summary>
        /// <param name="client">The client to use to retrieve the standard fields.</param>
        /// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None"/>.</param>
        /// <returns></returns>
        public static async Task RefreshStandardFieldsAsync(IEncompassApiClient client, CancellationToken cancellationToken = default)
        {
            Preconditions.NotNull(client, nameof(client));

            var entityTypes      = (await client.Schema.GetLoanSchemaAsync(includeFieldExtensions: true, cancellationToken).ConfigureAwait(false)).EntityTypes;
            var loanEntitySchema = entityTypes["Loan"];
            var fields           = new Dictionary <string, StandardFieldInfo>(StringComparer.OrdinalIgnoreCase);
            var fieldPatterns    = new Dictionary <string, StandardFieldInfo>(StringComparer.OrdinalIgnoreCase)
            {
                { "CX.{0}", new StandardFieldInfo("CX.{0}", "Loan.CustomFields[(FieldName == 'CX.{0}')].StringValue")
                  {
                      Format = LoanFieldFormat.STRING
                  } },
                { "CUST{0:00}FV", new StandardFieldInfo("CUST{0:00}FV", "Loan.CustomFields[(FieldName == 'CUST{0:00}FV')].StringValue")
                  {
                      Format = LoanFieldFormat.STRING
                  } }
            };

            PopulateFieldMappings("Loan", "Loan", null, loanEntitySchema, null, entityTypes, fields, fieldPatterns, extendedFieldInfo: true, null, null, null);

            foreach (var pair in FieldMappings._standardFields)
            {
                var fieldId           = pair.Key;
                var currentDescriptor = pair.Value;
                if (fields.TryGetValue(fieldId, out var fieldInfo))
                {
                    fields.Remove(fieldId);
                    if ((!string.IsNullOrEmpty(fieldInfo.Description) && currentDescriptor.Description != fieldInfo.Description) || currentDescriptor.ReadOnly != (fieldInfo.ReadOnly == true) || (!string.Equals(currentDescriptor.ModelPath, fieldInfo.ModelPath, StringComparison.OrdinalIgnoreCase) && !string.Equals(currentDescriptor.ModelPath, CreateModelPath(fieldInfo.ModelPath) !.ToString(), StringComparison.OrdinalIgnoreCase)))
                    {
                        var modelPath       = CreateModelPath(string.Equals(currentDescriptor.ModelPath, fieldInfo.ModelPath, StringComparison.OrdinalIgnoreCase) ? currentDescriptor.ModelPath : fieldInfo.ModelPath) !;
                        var modelPathString = modelPath.ToString();
                        var descriptor      = new NonStandardFieldDescriptor(fieldInfo.FieldId, modelPath, modelPathString, fieldInfo.Description, fieldInfo.Format, fieldInfo.Options, fieldInfo.ReadOnly == true);
                        FieldMappings._standardFields[fieldId] = descriptor;
                    }
                }
                else if (!currentDescriptor._userAdded)
                {
                    FieldMappings._standardFields.TryRemove(fieldId, out _);
                }
            }

            foreach (var pair in fields)
            {
                var fieldInfo       = pair.Value;
                var modelPath       = CreateModelPath(fieldInfo.ModelPath) !;
                var modelPathString = modelPath.ToString();
                var descriptor      = new NonStandardFieldDescriptor(fieldInfo.FieldId, modelPath, modelPathString, fieldInfo.Description, fieldInfo.Format, fieldInfo.Options, fieldInfo.ReadOnly == true);
                FieldMappings.AddField(descriptor);
            }

            foreach (var pair in FieldPatternMappings._standardFieldPatterns)
            {
                var fieldPattern      = pair.Key;
                var currentDescriptor = pair.Value;
                if (fieldPatterns.TryGetValue(fieldPattern, out var fieldInfo))
                {
                    fieldPatterns.Remove(fieldPattern);
                    if (!string.Equals(currentDescriptor.ModelPath, fieldInfo.ModelPath, StringComparison.OrdinalIgnoreCase) || currentDescriptor.ReadOnly != (fieldInfo.ReadOnly == true))
                    {
                        var modelPathPattern = string.Equals(currentDescriptor.ModelPath, fieldInfo.ModelPath, StringComparison.OrdinalIgnoreCase) ? currentDescriptor.ModelPath : fieldInfo.ModelPath;
                        var descriptor       = new NonStandardFieldDescriptor(fieldInfo.FieldId, CreateModelPath(string.Format(modelPathPattern, 1)) !, modelPathPattern, currentDescriptor.Description, fieldInfo.Format, fieldInfo.Options, fieldInfo.ReadOnly == true, multiInstance: true);
                        FieldPatternMappings._standardFieldPatterns[fieldPattern] = descriptor;
                    }
                }
                else if (!currentDescriptor._userAdded)
                {
                    FieldPatternMappings._standardFieldPatterns.TryRemove(fieldPattern, out _);
                }
            }

            foreach (var pair in fieldPatterns)
            {
                var fieldInfo        = pair.Value;
                var modelPathPattern = fieldInfo.ModelPath;
                var descriptor       = new NonStandardFieldDescriptor(fieldInfo.FieldId, CreateModelPath(string.Format(modelPathPattern, 1)) !, modelPathPattern, fieldInfo.Description, fieldInfo.Format, fieldInfo.Options, fieldInfo.ReadOnly == true, multiInstance: true);
                FieldPatternMappings.AddField(descriptor);
            }

            StandardFieldsLastRefreshedUtc = DateTime.UtcNow;
        }
        static LoanFieldDescriptors()
        {
            // Use embedded resource file for built-in field mappings to save assembly space
            using (var stream = typeof(LoanFieldDescriptors).GetTypeInfo().Assembly.GetManifestResourceStream("EncompassApi.LoanFields.zip"))
            {
                using (var zip = new ZipArchive(stream))
                {
                    using (var jsonStream = zip.GetEntry("LoanFields.json").Open())
                    {
                        using (var sr = new StreamReader(jsonStream))
                        {
                            using (var jr = new JsonTextReader(sr))
                            {
                                var loanFields = JsonHelper.DefaultPublicSerializer.Deserialize <List <StandardFieldInfo> >(jr);

                                foreach (var loanField in loanFields)
                                {
                                    var modelPathString = loanField.ModelPath;
                                    var modelPath       = CreateModelPath(modelPathString) !;
                                    modelPathString = modelPath.ToString();
                                    FieldDescriptor descriptor;
                                    if (loanField.Format.HasValue)
                                    {
                                        descriptor = new NonStandardFieldDescriptor(loanField.FieldId, modelPath, modelPathString, loanField.Description, loanField.Format, loanField.Options, loanField.ReadOnly ?? false);
                                    }
                                    else
                                    {
                                        descriptor = new FieldDescriptor(loanField.FieldId, modelPath, modelPathString, loanField.Description);
                                    }
                                    FieldMappings.AddField(descriptor);
                                }
                            }
                        }
                    }

                    using (var jsonStream = zip.GetEntry("VirtualFields.json").Open())
                    {
                        using (var sr = new StreamReader(jsonStream))
                        {
                            using (var jr = new JsonTextReader(sr))
                            {
                                var virtualFields = JsonHelper.DefaultPublicSerializer.Deserialize <List <VirtualFieldInfo> >(jr);

                                foreach (var virtualField in virtualFields)
                                {
                                    var modelPath  = $"Loan.VirtualFields['{virtualField.FieldId}']";
                                    var descriptor = new NonStandardFieldDescriptor(virtualField.FieldId, CreateModelPath(modelPath) !, modelPath, virtualField.Description, virtualField.Format, virtualField.Options, readOnly: true);
                                    FieldMappings.AddField(descriptor);
                                }
                            }
                        }
                    }

                    using (var jsonStream = zip.GetEntry("LoanFieldPatterns.json").Open())
                    {
                        using (var sr = new StreamReader(jsonStream))
                        {
                            using (var jr = new JsonTextReader(sr))
                            {
                                var loanFieldPatterns = JsonHelper.DefaultPublicSerializer.Deserialize <List <StandardFieldInfo> >(jr);

                                foreach (var loanFieldPattern in loanFieldPatterns)
                                {
                                    var modelPathPattern = loanFieldPattern.ModelPath;
                                    var descriptor       = new FieldDescriptor(loanFieldPattern.FieldId, CreateModelPath(string.Format(modelPathPattern, 1)) !, modelPathPattern, loanFieldPattern.Description, multiInstance: true);
                                    FieldPatternMappings.AddField(descriptor);
                                }
                            }
                        }
                    }

                    using (var jsonStream = zip.GetEntry("VirtualFieldPatterns.json").Open())
                    {
                        using (var sr = new StreamReader(jsonStream))
                        {
                            using (var jr = new JsonTextReader(sr))
                            {
                                var virtualFieldPatterns = JsonHelper.DefaultPublicSerializer.Deserialize <List <VirtualFieldInfo> >(jr);

                                foreach (var virtualFieldPattern in virtualFieldPatterns)
                                {
                                    var modelPathPattern = $"Loan.VirtualFields['{virtualFieldPattern.FieldId}']";
                                    var descriptor       = new NonStandardFieldDescriptor(virtualFieldPattern.FieldId, CreateModelPath(string.Format(modelPathPattern, 1)) !, modelPathPattern, virtualFieldPattern.Description, virtualFieldPattern.Format, virtualFieldPattern.Options, readOnly: true, multiInstance: true);
                                    FieldPatternMappings.AddField(descriptor);
                                }
                            }
                        }
                    }
                }
            }
        }