internal static void PopulateFieldMappings(string entityName, string currentPath, Type?ellieType, EntitySchema entitySchema, EntitySchema?previousEntitySchema, Dictionary <string, EntitySchema> entityTypes, Dictionary <string, StandardFieldInfo> fields, Dictionary <string, StandardFieldInfo> fieldPatterns, bool extendedFieldInfo, PopulateFieldMappingsAction?action, Func <string, string>?descriptionRetriever, TextWriter?output) { var requiredProperties = new HashSet <string>(); var serializeWholeList = false; var properties = entitySchema.Properties; foreach (var pair in properties) { var propertyName = pair.Key; var propertySchema = pair.Value; var description = propertySchema.Description; var ellieProperty = ellieType?.GetTypeInfo().GetDeclaredProperty(propertyName); var elliePropertyType = ellieProperty?.PropertyType; var fieldId = propertySchema.FieldId; if (!string.IsNullOrEmpty(fieldId)) { if (string.IsNullOrEmpty(description) && descriptionRetriever != null) { try { description = descriptionRetriever(fieldId); } catch { } } var fieldInfo = new StandardFieldInfo(fieldId, $"{currentPath}.{propertyName}") { Description = description }; fieldInfo.NonSerializedFormat = GetFormat(propertySchema); if (extendedFieldInfo) { fieldInfo.Format = fieldInfo.NonSerializedFormat; fieldInfo.Options = GetOptions(propertySchema); fieldInfo.ReadOnly = propertySchema.ReadOnly == true; } fields.Add(fieldId, fieldInfo); } else if (propertySchema.Type == PropertySchemaType.Entity && entityTypes.TryGetValue(propertySchema.EntityType !, out var nestedEntitySchema)) { if (currentPath != "Loan.CurrentApplication" || propertyName != "ATRQMBorrower") { entityTypes.Remove(propertySchema.EntityType !); if (ellieType?.Name == "LoanContract" && propertyName == "CurrentApplication") { elliePropertyType = ellieType.GetTypeInfo().GetDeclaredProperty("Applications").PropertyType.GetTypeInfo().ImplementedInterfaces.First(i => i.Name == "IEnumerable`1").GenericTypeArguments[0]; } else if (ellieType != null && elliePropertyType == null) { output?.WriteLine($"Did not get ellie type for {currentPath}.{propertyName} of type {propertySchema.EntityType.Value}"); } PopulateFieldMappings(propertySchema.EntityType !, $"{currentPath}.{propertyName}", elliePropertyType, nestedEntitySchema, entitySchema, entityTypes, fields, fieldPatterns, extendedFieldInfo, action, descriptionRetriever, output); } }
internal static void PopulateFieldMappings(string entityName, string currentPath, Type ellieType, EntitySchema entitySchema, EntitySchema previousEntitySchema, Dictionary <string, EntitySchema> entityTypes, Dictionary <string, StandardFieldInfo> fields, Dictionary <string, StandardFieldInfo> fieldPatterns, bool extendedFieldInfo, PopulateFieldMappingsAction action, Func <string, string> descriptionRetriever, TextWriter output) { var requiredProperties = new HashSet <string>(); var serializeWholeList = false; var properties = entitySchema.Properties; foreach (var pair in properties) { var propertyName = pair.Key; var propertySchema = pair.Value; var description = propertySchema.Description; var ellieProperty = ellieType?.GetTypeInfo().GetDeclaredProperty(propertyName); var elliePropertyType = ellieProperty?.PropertyType; var fieldId = propertySchema.FieldId; if (!string.IsNullOrEmpty(fieldId)) { if (string.IsNullOrEmpty(description) && descriptionRetriever != null) { try { description = descriptionRetriever(fieldId); } catch { } } var fieldInfo = new StandardFieldInfo { FieldId = fieldId, ModelPath = $"{currentPath}.{propertyName}", Description = description }; fieldInfo.NonSerializedFormat = GetFormat(propertySchema); if (extendedFieldInfo) { fieldInfo.Format = fieldInfo.NonSerializedFormat; fieldInfo.Options = GetOptions(propertySchema); fieldInfo.ReadOnly = propertySchema.ReadOnly == true; } fields.Add(fieldId, fieldInfo); } else if (propertySchema.Type == PropertySchemaType.Entity && entityTypes.TryGetValue(propertySchema.EntityType, out var nestedEntitySchema)) { if (currentPath != "Loan.CurrentApplication" || propertyName != "ATRQMBorrower") { entityTypes.Remove(propertySchema.EntityType); if (ellieType?.Name == "LoanContract" && propertyName == "CurrentApplication") { elliePropertyType = ellieType.GetTypeInfo().GetDeclaredProperty("Applications").PropertyType.GetTypeInfo().ImplementedInterfaces.First(i => i.Name == "IEnumerable`1").GenericTypeArguments[0]; } else if (ellieType != null && elliePropertyType == null) { output?.WriteLine($"Did not get ellie type for {currentPath}.{propertyName} of type {propertySchema.EntityType.Value}"); } PopulateFieldMappings(propertySchema.EntityType, $"{currentPath}.{propertyName}", elliePropertyType, nestedEntitySchema, entitySchema, entityTypes, fields, fieldPatterns, extendedFieldInfo, action, descriptionRetriever, output); } } else if ((propertySchema.Type == PropertySchemaType.List || propertySchema.Type == PropertySchemaType.Set) && entityTypes.TryGetValue(propertySchema.ElementType, out var elementEntitySchema)) { if (currentPath != "Loan" || propertyName != "Applications") { entityTypes.Remove(propertySchema.ElementType); if (ellieProperty != null) { elliePropertyType = elliePropertyType.GetTypeInfo().ImplementedInterfaces.First(i => i.Name == "IEnumerable`1").GenericTypeArguments[0]; } else if (ellieType != null) { output?.WriteLine($"Did not get ellie type for {currentPath}.{propertyName} of type {propertySchema.ElementType.Value}"); } PopulateFieldMappings(propertySchema.ElementType, $"{currentPath}.{propertyName}", elliePropertyType, elementEntitySchema, entitySchema, entityTypes, fields, fieldPatterns, extendedFieldInfo, action, descriptionRetriever, output); } } else { if (propertySchema.FieldInstances != null) { foreach (var fieldInstancePair in propertySchema.FieldInstances) { fieldId = fieldInstancePair.Key; if (descriptionRetriever != null) { try { description = descriptionRetriever(fieldId); } catch { } } string modelPath = null; if (fieldInstancePair.Value.Count != 1) { output?.WriteLine($"There must be just one field instance value for {fieldId}"); } var fieldInstancePath = fieldInstancePair.Value[0]; if (fieldInstancePath == "Borrower" || fieldInstancePath == "Coborrower") { modelPath = $"{currentPath.Substring(0, currentPath.LastIndexOf('.'))}.{fieldInstancePath}.{propertyName}"; } else { var firstUnderscore = fieldInstancePath.IndexOf('_'); var secondUnderscore = fieldInstancePath.IndexOf('_', firstUnderscore + 1); var listPropertyName = fieldInstancePath.Substring(firstUnderscore + 1, secondUnderscore - firstUnderscore - 1); var listPropertySchema = previousEntitySchema.Properties[listPropertyName]; Instance instance = null; if (listPropertySchema.Instances?.TryGetValue(fieldInstancePath, out instance) == true) { switch (instance) { case IntListInstance intListInstance: if (intListInstance.Count != 1) { output?.WriteLine($"There must be just one int list instance value for {fieldInstancePath}"); } serializeWholeList = true; modelPath = $"{currentPath}[{intListInstance[0]}].{propertyName}"; break; case StringListInstance stringListInstance: var index = 0; foreach (var s in stringListInstance) { var keyPropertyName = listPropertySchema.KeyProperties[index]; requiredProperties.Add(keyPropertyName); var property = properties[keyPropertyName]; var allowedValues = property.AllowedValues; if (allowedValues == null) { allowedValues = new List <FieldOption>(); property.AllowedValues = allowedValues; } var option = new FieldOption(s); if (!allowedValues.Contains(option)) { allowedValues.Add(option); } ++index; } modelPath = $"{currentPath}[({string.Join(" && ", stringListInstance.Select((s, i) => Tuple.Create(s, i)).Where(t => !string.IsNullOrEmpty(t.Item1)).OrderBy(t => listPropertySchema.KeyProperties[t.Item2]).Select(t => $"{listPropertySchema.KeyProperties[t.Item2]} == '{t.Item1}'"))})].{propertyName}"; break; case StringDictionaryInstance stringDictionaryInstance: foreach (var p in stringDictionaryInstance) { var keyPropertyName = p.Key; requiredProperties.Add(keyPropertyName); var property = properties[keyPropertyName]; var allowedValues = property.AllowedValues; if (allowedValues == null) { allowedValues = new List <FieldOption>(); property.AllowedValues = allowedValues; } var option = new FieldOption(p.Value); if (!allowedValues.Contains(option)) { allowedValues.Add(option); } } modelPath = $"{currentPath}[({string.Join(" && ", stringDictionaryInstance.OrderBy(p => p.Key).Select(p => $"{p.Key} == '{p.Value}'"))})].{propertyName}"; break; default: output?.WriteLine($"Bad instance type for {fieldInstancePath}"); break; } } else { serializeWholeList = true; var colonIndex = fieldInstancePath.LastIndexOf(':'); var index = 0; InstancePattern instancePattern = null; if (colonIndex < 0 || !int.TryParse(fieldInstancePath.Substring(colonIndex + 1), NumberStyles.None, null, out index) || listPropertySchema.InstancePatterns?.TryGetValue(fieldInstancePath.Substring(0, colonIndex), out instancePattern) != true) { output?.WriteLine($"[{fieldId}]: {fieldInstancePath}"); } if (instancePattern.Match != null) { foreach (var p in instancePattern.Match) { var keyPropertyName = p.Key; requiredProperties.Add(keyPropertyName); var property = properties[keyPropertyName]; var allowedValues = property.AllowedValues; if (allowedValues == null) { allowedValues = new List <FieldOption>(); property.AllowedValues = allowedValues; } var option = new FieldOption(p.Value); if (!allowedValues.Contains(option)) { allowedValues.Add(option); } } } modelPath = $"{currentPath.Substring(0, currentPath.LastIndexOf('.'))}.{listPropertyName}{(instancePattern.Match != null ? $"[({string.Join(" && ", instancePattern.Match.OrderBy(p => p.Key).Select(p => $"{p.Key} == '{p.Value}'"))})]" : string.Empty)}[{index}].{propertyName}"; } } var fieldInfo = new StandardFieldInfo { FieldId = fieldId, Description = description, ModelPath = modelPath }; fieldInfo.NonSerializedFormat = GetFormat(propertySchema); if (extendedFieldInfo) { fieldInfo.Format = fieldInfo.NonSerializedFormat; fieldInfo.Options = GetOptions(propertySchema); fieldInfo.ReadOnly = propertySchema.ReadOnly == true; } fields.Add(fieldId, fieldInfo); } } if (propertySchema.FieldPatterns != null) { var i = 1; foreach (var fieldPatternPair in propertySchema.FieldPatterns) { var fieldPattern = fieldPatternPair.Key; if (fieldPattern != "URLAROLNN06" && !fieldPattern.StartsWith("CUSTNN")) { serializeWholeList = true; if (fieldPatternPair.Value.Count != 1) { output?.WriteLine($"There must be just one field pattern value for {fieldPattern}"); } var fieldPatternPath = fieldPatternPair.Value[0]; var firstUnderscore = fieldPatternPath.IndexOf('_'); var secondUnderscore = fieldPatternPath.IndexOf('_', firstUnderscore + 1); var listPropertyName = fieldPatternPath.Substring(firstUnderscore + 1, secondUnderscore - firstUnderscore - 1); var listPropertySchema = previousEntitySchema.Properties[listPropertyName]; var instancePattern = listPropertySchema.InstancePatterns[fieldPatternPath]; if (instancePattern.Match != null) { foreach (var p in instancePattern.Match) { var keyPropertyName = p.Key; requiredProperties.Add(keyPropertyName); var property = properties[keyPropertyName]; var allowedValues = property.AllowedValues; if (allowedValues == null) { allowedValues = new List <FieldOption>(); property.AllowedValues = allowedValues; } var option = new FieldOption(p.Value); if (!allowedValues.Contains(option)) { allowedValues.Add(option); } } } fieldId = fieldPattern.StartsWith("NBOCNB") ? fieldPattern.Replace("NBOCNB", "NBOC{0:00}") : fieldPattern.Replace("NN", "{0:00}"); if (descriptionRetriever != null) { try { description = descriptionRetriever(string.Format(fieldId, 1)); description = description.Replace(" #11", " #{0}").Replace(" #1", " #{0}"); } catch { } } string modelPath; if (fieldPatternPath == "Application_Assets_NN") { modelPath = $"Loan.CurrentApplication.Assets[(VodIndex == '{{0}}')]{(propertySchema.FieldPatterns.Count == 4 ? $"[{i}]" : string.Empty)}.{propertyName}"; requiredProperties.Add(nameof(Asset.VodIndex)); } else { modelPath = $"{currentPath.Substring(0, currentPath.LastIndexOf('.'))}.{listPropertyName}{(instancePattern.Match != null ? $"[({string.Join(" && ", instancePattern.Match.OrderBy(p => p.Key).Select(p => $"{p.Key} == '{p.Value}'"))})]" : string.Empty)}[{{0}}].{propertyName}"; } var fieldInfo = new StandardFieldInfo { FieldId = fieldId, Description = description, ModelPath = modelPath }; fieldInfo.NonSerializedFormat = GetFormat(propertySchema); if (extendedFieldInfo) { fieldInfo.Format = fieldInfo.NonSerializedFormat; fieldInfo.Options = GetOptions(propertySchema); fieldInfo.ReadOnly = propertySchema.ReadOnly == true; } fieldPatterns.Add(fieldId, fieldInfo); } ++i; } } } } action?.Invoke(entityName, ellieType, entitySchema, requiredProperties, serializeWholeList); }