From c28a0eaee034d7a8d55d034b14f97d2a14fb7fdf Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Sun, 11 Aug 2024 13:37:06 +0200 Subject: [PATCH] unified exporter & cli changes --- EDSSharp/Program.cs | 119 ++++++++++++++++++++------ Tests/CLITest.cs | 29 +++++++ libEDSsharp/CanOpenNodeExporter.cs | 18 +++- libEDSsharp/CanOpenNodeExporter_V4.cs | 18 +++- libEDSsharp/CanOpenXDD.cs | 23 ++++- libEDSsharp/CanOpenXDD_1_1.cs | 34 +++++++- libEDSsharp/DocumentationGenHtml.cs | 17 +++- libEDSsharp/DocumentationGenMarkup.cs | 17 +++- libEDSsharp/Filetypes.cs | 38 ++++++++ libEDSsharp/IFileExporter.cs | 75 ++++++++++++++++ libEDSsharp/NetworkPDOreport.cs | 13 ++- libEDSsharp/eds.cs | 20 ++++- 12 files changed, 388 insertions(+), 33 deletions(-) create mode 100644 libEDSsharp/Filetypes.cs create mode 100644 libEDSsharp/IFileExporter.cs diff --git a/EDSSharp/Program.cs b/EDSSharp/Program.cs index 674b5ab1..aae0e059 100644 --- a/EDSSharp/Program.cs +++ b/EDSSharp/Program.cs @@ -43,24 +43,25 @@ static void Main(string[] args) } - if (argskvp.ContainsKey("--type") && argskvp.ContainsKey("--infile") && argskvp.ContainsKey("--outfile")) + if (argskvp.ContainsKey("--infile") && argskvp.ContainsKey("--outfile")) { string infile = argskvp["--infile"]; string outfile = argskvp["--outfile"]; + string outtype = ""; + if (argskvp.ContainsKey("--type")) + { + outtype = argskvp["--type"]; + } - ExporterFactory.Exporter type = ExporterFactory.Exporter.CANOPENNODE_LEGACY; //sensible default - - if (argskvp["--type"].IndexOf("4") > 0) - type = ExporterFactory.Exporter.CANOPENNODE_V4; switch (Path.GetExtension(infile).ToLower()) { case ".xdd": - openXDDfile(infile, outfile,type); + openXDDfile(infile); break; case ".eds": - openEDSfile(infile, outfile,InfoSection.Filetype.File_EDS,type); + openEDSfile(infile); break; @@ -68,28 +69,47 @@ static void Main(string[] args) return; } + if(eds != null) + { + Export(outfile, outtype); + } } else { - Console.WriteLine("Usage EDSEditor --type [CanOpenNode|CanOpenNodeV4] --infile file.[xdd|eds] --outfile [CO_OD.c|OD]"); + PrintHelpText(); } } catch(Exception e) { Console.WriteLine(e.ToString()); + PrintHelpText(); } } - private static void openEDSfile(string infile, string outfile, InfoSection.Filetype ft, ExporterFactory.Exporter exporttype) + private static void openEDSfile(string infile) { eds.Loadfile(infile); + } - exportCOOD(outfile,exporttype); + private static void openXDDfile(string path) + { + CanOpenXDD_1_1 coxml_1_1 = new CanOpenXDD_1_1(); + eds = coxml_1_1.ReadXML(path); + if (eds == null) + { + CanOpenXDD coxml = new CanOpenXDD(); + eds = coxml.readXML(path); + + if (eds == null) + return; + } + + eds.projectFilename = path; } - private static void exportCOOD(string outpath,ExporterFactory.Exporter type) + private static void Export(string outpath, string outType) { outpath = Path.GetFullPath(outpath); @@ -99,10 +119,15 @@ private static void exportCOOD(string outpath,ExporterFactory.Exporter type) Warnings.warning_list.Clear(); - IExporter exporter = ExporterFactory.getExporter(type); - var filepath = Path.Combine(savePath, Path.GetFileNameWithoutExtension(outpath)); + var exporterDef = FindMatchingExporter(outpath, outType); - exporter.export(filepath, eds); + if(exporterDef == null) + { + throw new Exception("Unable to find matching exporter)"); + } + + var edss = new List { eds }; + exporterDef.Func(outpath, edss); foreach(string warning in Warnings.warning_list) { @@ -111,22 +136,68 @@ private static void exportCOOD(string outpath,ExporterFactory.Exporter type) } - private static void openXDDfile(string path, string outpath,ExporterFactory.Exporter exportertype) + static ExporterDiscriptor FindMatchingExporter(string outpath, string outType) { - CanOpenXDD_1_1 coxml_1_1 = new CanOpenXDD_1_1(); - eds = coxml_1_1.ReadXML(path); + //Find exporter(s) matching the file extension + var exporters = Filetypes.GetExporters(); - if (eds == null) + var outFiletype = Path.GetExtension(outpath); + var exporterMatchingFiletype = new List(); + foreach (var exporter in exporters) { - CanOpenXDD coxml = new CanOpenXDD(); - eds = coxml.readXML(path); + foreach (var type in exporter.Filetypes) + { + if (type == outFiletype) + { + exporterMatchingFiletype.Add(exporter); + break; + } + } + } - if (eds == null) - return; + if (exporterMatchingFiletype.Count == 1) + { + //If only one match we use that one. + return exporterMatchingFiletype[0]; } - eds.projectFilename = path; - exportCOOD(outpath,exportertype); + //If multiple or zero matches use type + foreach (var exporter in exporters) + { + if (exporter.Description.Replace(" ", null) == outType) + { + return exporter; + } + } + return null; + } + + static void PrintHelpText() + { + Console.WriteLine("Usage: EDSEditor --infile file.[xdd|eds] --outfile [valid output file] [OPTIONAL] --type [valid type]"); + Console.WriteLine("The output file format depends on --outfile extension and --type"); + Console.WriteLine("If --outfile extension matcher one exporter then --type IS NOT needed"); + Console.WriteLine("If --outfile extension matcher multiple exporter then --type IS needed"); + Console.WriteLine("If --outfile has no extension --type IS needed"); + Console.WriteLine("Exporters:"); + + var exporters = Filetypes.GetExporters(); + foreach (var exporter in exporters) + { + string filetypes = ""; + for (int i = 0; i < exporter.Filetypes.Length; i++) + { + filetypes += exporter.Filetypes[i]; + //add seperator char if multiple filetypes + if(i +1 != exporter.Filetypes.Length) + { + filetypes += ','; + } + } + + string description = $" {exporter.Description.Replace(" ",null)} [{filetypes}]"; + Console.WriteLine(description); + } } } } diff --git a/Tests/CLITest.cs b/Tests/CLITest.cs index 8bbdbae8..22b54aa0 100644 --- a/Tests/CLITest.cs +++ b/Tests/CLITest.cs @@ -8,6 +8,13 @@ public class CliTest : libEDSsharp.EDSsharp { string RunEDSSharp(string arguments) { + File.Delete("Legacy.c"); + File.Delete("Legacy.h"); + File.Delete("V4.c"); + File.Delete("V4.h"); + File.Delete("file.eds"); + File.Delete("file.xpd"); + Process p = new Process(); p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; @@ -33,5 +40,27 @@ public void XddToCanOpenNodeV4() string[] files = Directory.GetFiles(".", "V4.*"); Assert.Equal(2, files.Length); } + [Fact] + public void OnlySingleExporterByExtensionPossible() + { + RunEDSSharp("--infile minimal_project.xdd --outfile file.eds"); + string[] files = Directory.GetFiles(".", "file.eds"); + Assert.Single(files); + } + [Fact] + public void MultipleExporterByExtensionPossibleWithoutType() + { + //this should fail + RunEDSSharp("--infile minimal_project.xdd --outfile file.xpd"); + string[] files = Directory.GetFiles(".", "file.xpd"); + Assert.Empty(files); + } + [Fact] + public void MultipleExporterByExtensionPossibleWithType() + { + RunEDSSharp("--type CanOpenXPDv1.0 --infile minimal_project.xdd --outfile file.xpd"); + string[] files = Directory.GetFiles(".", "file.xpd"); + Assert.Single(files); + } } } diff --git a/libEDSsharp/CanOpenNodeExporter.cs b/libEDSsharp/CanOpenNodeExporter.cs index 5068277b..6ad71825 100644 --- a/libEDSsharp/CanOpenNodeExporter.cs +++ b/libEDSsharp/CanOpenNodeExporter.cs @@ -35,7 +35,7 @@ namespace libEDSsharp /// /// Export .c and .h files for CanOpenNode v1-3 /// - public class CanOpenNodeExporter : IExporter + public class CanOpenNodeExporter : IExporter, IFileExporter { private string folderpath; @@ -59,6 +59,22 @@ public class CanOpenNodeExporter : IExporter ODentry maxRXmappingsOD=null; ODentry maxTXmappingsOD=null; + /// + /// Fetches all the different fileexporter types the class supports + /// + /// List of the different exporters the class supports + public ExporterDiscriptor[] GetExporters() + { + return new ExporterDiscriptor[] + { + new ExporterDiscriptor("CanOpenNode", new string[] { ".h", ".c" }, ExporterDiscriptor.ExporterFlags.CanOpenNode, delegate (string filepath, List edss) + { + var e = new CanOpenNodeExporter(); + e.export(filepath, edss[0]); + }) + }; + } + /// /// Register names of index and subindex that need to have standard names to be able to work with CanOpenNode /// diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index 93c0e225..9be49583 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -31,7 +31,7 @@ namespace libEDSsharp /// /// Exporter for CanOpenNode_V4 /// - public class CanOpenNodeExporter_V4 : IExporter + public class CanOpenNodeExporter_V4 : IExporter, IFileExporter { private string odname; @@ -47,6 +47,22 @@ public class CanOpenNodeExporter_V4 : IExporter private Dictionary ODCnt; private Dictionary ODArrSize; + /// + /// Fetches all the different fileexporter types the class supports + /// + /// List of the different exporters the class supports + public ExporterDiscriptor[] GetExporters() + { + return new ExporterDiscriptor[] + { + new ExporterDiscriptor("CanOpenNodeV4", new string[] { ".h", ".c" }, ExporterDiscriptor.ExporterFlags.CanOpenNode, delegate (string filepath, List edss) + { + var e = new CanOpenNodeExporter_V4(); + e.export(filepath, edss[0]); + }) + }; + } + /// /// export the current data set in the CanOpen Node format V4 /// diff --git a/libEDSsharp/CanOpenXDD.cs b/libEDSsharp/CanOpenXDD.cs index 9dde28e2..29bb95c2 100644 --- a/libEDSsharp/CanOpenXDD.cs +++ b/libEDSsharp/CanOpenXDD.cs @@ -29,9 +29,30 @@ based heavily on the files CO_OD.h and CO_OD.c from CANopenNode which are namespace libEDSsharp { - public class CanOpenXDD + public class CanOpenXDD : IFileExporter { public ISO15745ProfileContainer dev; + + /// + /// Fetches all the different fileexporter types the class supports + /// + /// List of the different exporters the class supports + public ExporterDiscriptor[] GetExporters() + { + return new ExporterDiscriptor[] { + new ExporterDiscriptor("CanOpen XDD v1.0", new string[] { ".xdd" }, 0, delegate (string filepath, List edss) + { + var e = new CanOpenXDD(); + e.writeXML(filepath,edss[0]); + }), + new ExporterDiscriptor("CanOpen XPD v1.0", new string[] { ".xpd" }, ExporterDiscriptor.ExporterFlags.MultipleNodeSupport, delegate (string filepath, List edss) + { + var e = new CanOpenXDD(); + e.writeMultiXML(filepath,edss); + }) + }; + } + public EDSsharp readXML(string file) { diff --git a/libEDSsharp/CanOpenXDD_1_1.cs b/libEDSsharp/CanOpenXDD_1_1.cs index b663ae41..1e9fdd20 100644 --- a/libEDSsharp/CanOpenXDD_1_1.cs +++ b/libEDSsharp/CanOpenXDD_1_1.cs @@ -1,4 +1,4 @@ -/* +/* This file is part of libEDSsharp. libEDSsharp is free software: you can redistribute it and/or modify @@ -38,8 +38,38 @@ namespace libEDSsharp /// Convert to/from EDSsharp and CanOpenXDD v1.1, it uses the generated source file CanOpenXSD_1_1 /// /// - public class CanOpenXDD_1_1 + public class CanOpenXDD_1_1 : IFileExporter { + /// + /// Fetches all the different fileexporter types the class supports + /// + /// List of the different exporters the class supports + public ExporterDiscriptor[] GetExporters() + { + return new ExporterDiscriptor[] { + new ExporterDiscriptor("CanOpen XDD v1.1", new string[] { ".xdd" }, 0, delegate (string filepath, List edss) + { + var e = new CanOpenXDD_1_1(); + e.WriteXML(filepath,edss[0],false,false); + }), + new ExporterDiscriptor("CanOpen XDD v1.1 stripped", new string[] { ".xdd" }, 0, delegate (string filepath, List edss) + { + var e = new CanOpenXDD_1_1(); + e.WriteXML(filepath,edss[0],false,true); + }), + new ExporterDiscriptor("CanOpen XPD v1.1", new string[] { ".xpd" }, ExporterDiscriptor.ExporterFlags.MultipleNodeSupport, delegate (string filepath, List edss) + { + var e = new CanOpenXDD_1_1(); + //What is commissioned .xpd extension?? + e.WriteMultiXML(filepath,edss,false); + }), + new ExporterDiscriptor("CanOpen XDC v1.1", new string[] { ".xdc" }, 0, delegate (string filepath, List edss) + { + var e = new CanOpenXDD_1_1(); + e.WriteXML(filepath,edss[0],true,true); + }) + }; + } /// /// Read XDD file into EDSsharp object /// diff --git a/libEDSsharp/DocumentationGenHtml.cs b/libEDSsharp/DocumentationGenHtml.cs index a2717025..b325a745 100644 --- a/libEDSsharp/DocumentationGenHtml.cs +++ b/libEDSsharp/DocumentationGenHtml.cs @@ -27,10 +27,25 @@ namespace libEDSsharp /// /// Documentation generator /// - public class DocumentationGenHtml + public class DocumentationGenHtml : IFileExporter { StreamWriter file = null; + /// + /// Fetches all the different fileexporter types the class supports + /// + /// List of the different exporters the class supports + public ExporterDiscriptor[] GetExporters() + { + return new ExporterDiscriptor[] + { + new ExporterDiscriptor("Documentation HTML", new string[] { ".html" }, ExporterDiscriptor.ExporterFlags.Documentation, delegate (string filepath, List edss) + { + var e = new DocumentationGenMarkup(); + e.genmddoc(filepath, edss[0]); + }) + }; + } /// /// Generate html documentation /// diff --git a/libEDSsharp/DocumentationGenMarkup.cs b/libEDSsharp/DocumentationGenMarkup.cs index 1ef6084f..58c877fa 100644 --- a/libEDSsharp/DocumentationGenMarkup.cs +++ b/libEDSsharp/DocumentationGenMarkup.cs @@ -28,10 +28,25 @@ namespace libEDSsharp /// /// Documentation generator /// - public class DocumentationGenMarkup + public class DocumentationGenMarkup : IFileExporter { StreamWriter file = null; + /// + /// Fetches all the different fileexporter types the class supports + /// + /// List of the different exporters the class supports + public ExporterDiscriptor[] GetExporters() + { + return new ExporterDiscriptor[] + { + new ExporterDiscriptor("Documentation Markup", new string[] { ".md" }, ExporterDiscriptor.ExporterFlags.Documentation, delegate (string filepath, List edss) + { + var e = new DocumentationGenMarkup(); + e.genmddoc(filepath, edss[0]); + }) + }; + } /// /// Generate markup documentation /// diff --git a/libEDSsharp/Filetypes.cs b/libEDSsharp/Filetypes.cs new file mode 100644 index 00000000..21d9e571 --- /dev/null +++ b/libEDSsharp/Filetypes.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using static libEDSsharp.ExporterDiscriptor; + +namespace libEDSsharp +{ + /// + /// Unified interface to all filetypes supported by the library + /// + public class Filetypes + { + /// + /// Returns description of all the different filetypes that can be exported to + /// + /// optional filter to filter out different types of exporters + /// list of file exporter that matches the filter + public static ExporterDiscriptor[] GetExporters(ExporterFlags flags = 0) + { + var exporters = new List(); + foreach (Type mytype in System.Reflection.Assembly.GetExecutingAssembly().GetTypes() + .Where(mytype => mytype.GetInterfaces().Contains(typeof(IFileExporter)))) + { + var exporterClass = (IFileExporter)Activator.CreateInstance(mytype); + var classExporters = exporterClass.GetExporters(); + foreach (var exporter in classExporters) + { + if (((exporter.Flags & flags) > 0) || flags == 0) + { + exporters.Add(exporter); + } + + } + } + return exporters.ToArray(); + } + } +} diff --git a/libEDSsharp/IFileExporter.cs b/libEDSsharp/IFileExporter.cs new file mode 100644 index 00000000..8de93ac2 --- /dev/null +++ b/libEDSsharp/IFileExporter.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; + +namespace libEDSsharp +{ + /// + /// Includes all info about a exporter that is needed to show user and call it + /// + public class ExporterDiscriptor + { + /// + /// Export eds(s) to file(s) + /// + /// path path that should indicate where and what name the outputed file(s) should have + /// list of eds(s) not all support multiple edss, in that case use the first + public delegate void ExportFunc(string filepath, List edss); + [Flags] + public enum ExporterFlags + { + /// + /// True if exporter will expect multiple edss + /// + MultipleNodeSupport = 1, + /// + /// Documentation related + /// + Documentation = 2, + /// + /// CanOpenNode related + /// + CanOpenNode = 3, + } + /// + /// short human readable description + /// + public string Description { get; } + /// + /// What file extension the exported file(s) will have + /// + public string[] Filetypes { get; } + /// + /// Used to indicated different types of exporters + /// + public ExporterFlags Flags { get; } + /// + /// The function that is exporting to file + /// + public ExportFunc Func { get; } + /// + /// constructor that sets all the values + /// + /// short human readable description + /// What file extension the exported file(s) will have + /// Used to indicated different types of exporters + /// The function that is exporting to file + public ExporterDiscriptor(string description, string[] filetypes, ExporterFlags flags, ExportFunc func) + { + Description = description; + Filetypes = filetypes; + Flags = flags; + Func = func; + } + } + /// + /// Interface for exporters + /// + public interface IFileExporter + { + /// + /// Fetches all the different fileexporter types the class supports + /// + /// List of the different exporters the class supports + ExporterDiscriptor[] GetExporters(); + } +} diff --git a/libEDSsharp/NetworkPDOreport.cs b/libEDSsharp/NetworkPDOreport.cs index a7318011..59d62058 100644 --- a/libEDSsharp/NetworkPDOreport.cs +++ b/libEDSsharp/NetworkPDOreport.cs @@ -26,9 +26,20 @@ namespace libEDSsharp /// /// Generate a PDO network report /// - public class NetworkPDOreport + public class NetworkPDOreport : IFileExporter { + public ExporterDiscriptor[] GetExporters() + { + return new ExporterDiscriptor[] + { + new ExporterDiscriptor("Network PDO Report", new string[] { ".md" }, ExporterDiscriptor.ExporterFlags.Documentation | ExporterDiscriptor.ExporterFlags.MultipleNodeSupport, delegate (string filepath, List edss) + { + var e = new NetworkPDOreport(); + e.gennetpdodoc(filepath, edss); + }) + }; + } StreamWriter file = null; /// /// Generate a PDO network report diff --git a/libEDSsharp/eds.cs b/libEDSsharp/eds.cs index 5df21990..53dff248 100644 --- a/libEDSsharp/eds.cs +++ b/libEDSsharp/eds.cs @@ -1666,7 +1666,7 @@ public Module(UInt16 moduleindex) } - public partial class EDSsharp + public partial class EDSsharp : IFileExporter { public enum AccessType @@ -1758,6 +1758,24 @@ public bool Dirty public delegate void DataDirty(bool dirty, EDSsharp sender); public event DataDirty OnDataDirty; + /// + /// Fetches all the different fileexporter types the class supports + /// + /// List of the different exporters the class supports + public ExporterDiscriptor[] GetExporters() + { + return new ExporterDiscriptor[] { + new ExporterDiscriptor("Electronic Data Sheet", new string[] { ".eds" }, 0, delegate (string filepath, List eds) + { + eds[0].Savefile(filepath, InfoSection.Filetype.File_EDS); + }), + new ExporterDiscriptor("Device Configuration File", new string[] { ".dcf" }, 0, delegate (string filepath, List eds) + { + eds[0].Savefile(filepath, InfoSection.Filetype.File_DCF); + }) + }; + } + public EDSsharp() {