using System; using System.Collections.Generic; using System.Data; using System.Linq; namespace InABox.Core { public enum ImportMappingType { Import, Export } public static class ImportFactory { private static readonly List _definitions = new List(); public static ImportDefinition[] Definitions => _definitions.ToArray(); private static Dictionary? _generators; private static IImportMappingGenerator? GetGenerator(Type type) { _generators ??= CoreUtils.TypeList( AppDomain.CurrentDomain.GetAssemblies(), myType => myType.IsClass && !myType.IsAbstract && !myType.IsGenericType && myType.HasInterface(typeof(IImportMappingGenerator<>)) ).ToDictionary(x => x.GetInterfaceDefinition(typeof(IImportMappingGenerator<>))!.GenericTypeArguments[0], x => x); if(_generators.TryGetValue(type, out var generatorType)) { return Activator.CreateInstance(generatorType) as IImportMappingGenerator; } else { return null; } } public static List GenerateMappings(Type t, List mappings, ImportMappingType importType) { var generator = GetGenerator(t); if(generator is null) { return mappings; } else { return generator.GenerateMappings(mappings, importType); } } public static IEnumerable ExtractMappings(Type type, ImportMappingType Import) { var results = new List(); var props = DatabaseSchema.Properties(type) .OrderBy(x => x.Page, Comparer.Create((x, y) => { var result = x.CompareTo(y); if(result == 0) { return 0; } else if(x.Equals("")) { return -1; } else if(y.Equals("")) { return 1; } return result; })) .ThenBy(x => x.PropertySequence()); //var keys = CoreUtils.PropertyList(type, x => true, true).Keys.ToArray(); foreach (var prop in props) { if (prop.Editor != null && !(prop.Editor is NullEditor) && (!prop.IsCalculated || Import == ImportMappingType.Export)) { var bOK = true; var bKey = prop.Editor is UniqueCodeEditor; var lookup = ImportLookupType.None; if (Import == ImportMappingType.Import) { var comps = prop.Name.Split('.'); if (comps.Length > 1) { if (prop.HasParentEntityLink()) { bOK = false; if (prop.Editor is CodeEditor && prop.Parent!.IsEntityLink && !prop.Parent.HasParentEntityLink()) { lookup = ImportLookupType.Restrict; bOK = true; } } } } if (bOK) results.Add(new ImportMapping { Property = prop.Name, Field = "", Constant = "", Lookup = lookup, Key = bKey }); } } return GenerateMappings(type, results, Import); } private static bool IsNestedEntityLink(Type type, string property) { if (String.IsNullOrWhiteSpace(property)) return false; var parent = string.Join(".", property.Split('.').Reverse().Skip(1).Reverse()); if (!string.IsNullOrEmpty(parent)) { var parentprop = CoreUtils.GetProperty(type, parent); if (parentprop.PropertyType.GetInterfaces().Contains(typeof(IEntityLink))) return true; return IsNestedEntityLink(type,parent); } return false; } public static void Register(Type type, string description, string filter) { if (!_definitions.Any(x => x.Type.Equals(type))) _definitions.Add(new ImportDefinition(type, description, filter)); } private static int[] ExtractColumnWidths(string widths) { if (string.IsNullOrWhiteSpace(widths)) return new[] { 1024 }; try { return widths.Split(',').Select(int.Parse).ToArray(); } catch { return new[] { 1024 }; } } public static IImporter Create(ImportDefinition definition, Type type, Importer importer) { var iimporter = definition.Type.MakeGenericType(type); var result = (Activator.CreateInstance(iimporter) as IImporter)!; if (result is IFixedWidthImporter fixedImporter) fixedImporter.ColumnWidths = ExtractColumnWidths(importer.ColumnWidths); if (result is ISettingsImporter settingsImporter) { if (!importer.Settings.IsNullOrWhiteSpace()) { var settings = Serialization.Deserialize(settingsImporter.SettingsType, importer.Settings); if (settings != null) { settingsImporter.SetSettings(settings); } } } result.HasHeader = importer.HasHeader; result.HeaderRow = Math.Max(1, importer.HeaderRows); return result; } //public static IImporter Create(ImportDefinition definition) where T : new() //{ // var importer = definition.Type.MakeGenericType(typeof(T)); // var result = Activator.CreateInstance(importer) as IImporter; // return result; //} } }