Code development platform for open source projects from the European Union institutions :large_blue_circle: EU Login authentication by SMS has been phased out. To see alternatives please check here

Skip to content
Snippets Groups Projects
Commit 6ce9d76a authored by Stefanos Doumpoulakis's avatar Stefanos Doumpoulakis
Browse files

feat #726: XML converter tool for older VECTO jobs

A tool that takes older (urn:tugraz:ivt:VectoAPI:DeclarationDefinitions
v1.0, v2.0, v2.1, v2.2.1) VECTO jobs and converts them to a newer
version (v2.4), so they can be simulated by the current version of
VECTO.
parent 393dc8c6
No related branches found
No related tags found
No related merge requests found
Showing
with 2008 additions and 2 deletions
......@@ -37,6 +37,8 @@
<Net48VectoCommandLine Include="$(SolutionDir)VectoConsole\bin\Release\net48\*.dll*"/>
<Net48VectoMultistep Include="$(SolutionDir)VECTO3GUI2020\bin\Release\net48\*.exe*"/>
<Net48VectoMultistep Include="$(SolutionDir)VECTO3GUI2020\bin\Release\net48\*.dll*"/>
<Net48XMLConverterCmdLine Include="$(SolutionDir)XMLConverterCmdLine\bin\Release\net48\*.exe*"/>
<Net48XMLConverterCmdLine Include="$(SolutionDir)XMLConverterCmdLine\bin\Release\net48\*.dll*"/>
</ItemGroup>
<!--MockupDeploy-->
......@@ -59,6 +61,7 @@
<Copy SourceFiles="@(Net48HashingTool)" DestinationFolder="$(DeployPath)net48"/>
<Copy SourceFiles="@(Net48VectoMultistep)" DestinationFolder="$(DeployPath)net48"/>
<Copy SourceFiles="@(Net48VECTO)" DestinationFolder="$(DeployPath)net48"/>
<Copy SourceFiles="@(Net48XMLConverterCmdLine)" DestinationFolder="$(DeployPath)net48"/>
<ItemGroup Condition="'$(Configuration)'=='Deploy'">
<!-- All files for net6.0 -->
......@@ -69,6 +72,9 @@
<VectoCommandLine Include="$(SolutionDir)VectoConsole\bin\Release\net6.0\vectocmd.*" Exclude="*.dev.json"/>
<VectoCommandLine Include="$(SolutionDir)VectoConsole\bin\Release\net6.0\*.dll"/>
<VectoCommandLineRuntimes Include="$(SolutionDir)VectoConsole\bin\Release\net6.0\runtimes\**\*.*"/>
<XMLConverterCmdLine Include="$(SolutionDir)XMLConverterCmdLine\bin\Release\net6.0\XMLConverterCmdLine.*" Exclude="*.dev.json"/>
<XMLConverterCmdLine Include="$(SolutionDir)XMLConverterCmdLine\bin\Release\net6.0\*.dll"/>
<XMLConverterCmdLineRuntimes Include="$(SolutionDir)XMLConverterCmdLine\bin\Release\net6.0\runtimes\**\*.*"/>
<HashingTool Include="$(SolutionDir)HashingCmd\bin\Release\net6.0\hashingcmd.*" Exclude="*.dev.json"/>
<HashingTool Include="$(SolutionDir)HashingCmd\bin\Release\net6.0\*.dll"/>
<HashingToolRuntimes Include="$(SolutionDir)HashingCmd\bin\Release\net6.0-windows\runtimes\**\*.*"/>
......@@ -109,6 +115,8 @@
<Copy SourceFiles="@(VectoMultistepRuntimes)" DestinationFiles="@(VectoMultistepRuntimes->'$(DeployPath)net60\runtimes\%(RecursiveDir)%(Filename)%(Extension)')"/>
<Copy SourceFiles="@(VectoCommandLineRuntimes)" DestinationFiles="@(VectoCommandLineRuntimes->'$(DeployPath)net60\runtimes\%(RecursiveDir)%(Filename)%(Extension)')"/>
<Copy SourceFiles="@(VectoRuntimes)" DestinationFiles="@(VectoRuntimes->'$(DeployPath)net60\runtimes\%(RecursiveDir)%(Filename)%(Extension)')"/>
<Copy SourceFiles="@(XMLConverterCmdLine)" DestinationFolder="$(DeployPath)net60"/>
<Copy SourceFiles="@(XMLConverterCmdLineRuntimes)" DestinationFiles="@(XMLConverterCmdLineRuntimes->'$(DeployPath)net60\runtimes\%(RecursiveDir)%(Filename)%(Extension)')"/>
<ItemGroup Condition="'$(Configuration)'=='Deploy'">
<!-- All files for the VECTO starters -->
......@@ -117,6 +125,7 @@
<VectoStart Include="$(SolutionDir)Tools\HashingCmdStart\bin\Release\net48\hashingcmd.exe" />
<VectoStart Include="$(SolutionDir)Tools\HashingToolStart\bin\Release\net48\HashingTool.exe" />
<VectoStart Include="$(SolutionDir)Tools\VECTOConsoleStart\bin\Release\net48\vectocmd.exe" />
<VectoStart Include="$(SolutionDir)Tools\XMLConverterCmdLineStart\bin\Release\net48\XMLConverterCmdLine.exe" />
</ItemGroup>
<ItemGroup Condition="'$(Configuration)'=='MockupDeploy'">
<!-- All files for the VECTO starters -->
......
namespace TUGraz.VECTO
{
class Program
{
static void Main(string[] args)
{
StarterHelper.StartVECTO(args, true);
}
}
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<AssemblyName>XMLConverterCmdLine</AssemblyName>
<RootNamespace>TUGraz.VECTO</RootNamespace>
<TargetFramework>net48</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\VECTOStart\StarterHelper.cs" Link="StarterHelper.cs" />
</ItemGroup>
</Project>
......@@ -103,7 +103,17 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "VectoMockup", "VectoMockup"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VectoMockupTest", "VectoMockup\VectoMockupTest\VectoMockupTest.csproj", "{EC0D4019-BBE6-431C-90E1-BD4AAEC0BF88}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VectoCommonTests", "VectoCommon\VectoCommonTests\VectoCommonTests.csproj", "{57FB17D2-F715-4FDF-9BC1-0820D36D5650}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VectoCommonTests", "VectoCommon\VectoCommonTests\VectoCommonTests.csproj", "{57FB17D2-F715-4FDF-9BC1-0820D36D5650}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "XMLConverter", "XMLConverter", "{C1DAC201-B65B-4C48-8520-A366B5736830}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "XMLConverterLibrary", "XMLConverterLibrary\XMLConverterLibrary.csproj", "{090025B2-15F8-4C0C-916C-8E65AE4F64BA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "XMLConverterLibraryTests", "XMLConverterLibraryTests\XMLConverterLibraryTests.csproj", "{CE4A3D7D-33D6-4552-8542-335B5B8C0552}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "XMLConverterCmdLine", "XMLConverterCmdLine\XMLConverterCmdLine.csproj", "{1F146056-ADCE-4845-80F6-9BA7F3EAC449}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XMLConverterCmdLineStart", "Tools\XMLConverterCmdLineStart\XMLConverterCmdLineStart.csproj", "{DE50CAEF-6282-476D-A09B-AD16D6F2476F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
......@@ -407,6 +417,53 @@ Global
{57FB17D2-F715-4FDF-9BC1-0820D36D5650}.MockupRelease|Any CPU.Build.0 = Release|Any CPU
{57FB17D2-F715-4FDF-9BC1-0820D36D5650}.Release|Any CPU.ActiveCfg = Release|Any CPU
{57FB17D2-F715-4FDF-9BC1-0820D36D5650}.Release|Any CPU.Build.0 = Release|Any CPU
{090025B2-15F8-4C0C-916C-8E65AE4F64BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{090025B2-15F8-4C0C-916C-8E65AE4F64BA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{090025B2-15F8-4C0C-916C-8E65AE4F64BA}.Deploy|Any CPU.ActiveCfg = Release|Any CPU
{090025B2-15F8-4C0C-916C-8E65AE4F64BA}.Deploy|Any CPU.Build.0 = Release|Any CPU
{090025B2-15F8-4C0C-916C-8E65AE4F64BA}.MockupDebug|Any CPU.ActiveCfg = Debug|Any CPU
{090025B2-15F8-4C0C-916C-8E65AE4F64BA}.MockupDebug|Any CPU.Build.0 = Debug|Any CPU
{090025B2-15F8-4C0C-916C-8E65AE4F64BA}.MockupDeploy|Any CPU.ActiveCfg = Debug|Any CPU
{090025B2-15F8-4C0C-916C-8E65AE4F64BA}.MockupDeploy|Any CPU.Build.0 = Debug|Any CPU
{090025B2-15F8-4C0C-916C-8E65AE4F64BA}.MockupRelease|Any CPU.ActiveCfg = Release|Any CPU
{090025B2-15F8-4C0C-916C-8E65AE4F64BA}.MockupRelease|Any CPU.Build.0 = Release|Any CPU
{090025B2-15F8-4C0C-916C-8E65AE4F64BA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{090025B2-15F8-4C0C-916C-8E65AE4F64BA}.Release|Any CPU.Build.0 = Release|Any CPU
{CE4A3D7D-33D6-4552-8542-335B5B8C0552}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CE4A3D7D-33D6-4552-8542-335B5B8C0552}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CE4A3D7D-33D6-4552-8542-335B5B8C0552}.Deploy|Any CPU.ActiveCfg = Debug|Any CPU
{CE4A3D7D-33D6-4552-8542-335B5B8C0552}.MockupDebug|Any CPU.ActiveCfg = Debug|Any CPU
{CE4A3D7D-33D6-4552-8542-335B5B8C0552}.MockupDebug|Any CPU.Build.0 = Debug|Any CPU
{CE4A3D7D-33D6-4552-8542-335B5B8C0552}.MockupDeploy|Any CPU.ActiveCfg = Debug|Any CPU
{CE4A3D7D-33D6-4552-8542-335B5B8C0552}.MockupDeploy|Any CPU.Build.0 = Debug|Any CPU
{CE4A3D7D-33D6-4552-8542-335B5B8C0552}.MockupRelease|Any CPU.ActiveCfg = Release|Any CPU
{CE4A3D7D-33D6-4552-8542-335B5B8C0552}.MockupRelease|Any CPU.Build.0 = Release|Any CPU
{CE4A3D7D-33D6-4552-8542-335B5B8C0552}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CE4A3D7D-33D6-4552-8542-335B5B8C0552}.Release|Any CPU.Build.0 = Release|Any CPU
{1F146056-ADCE-4845-80F6-9BA7F3EAC449}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1F146056-ADCE-4845-80F6-9BA7F3EAC449}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1F146056-ADCE-4845-80F6-9BA7F3EAC449}.Deploy|Any CPU.ActiveCfg = Release|Any CPU
{1F146056-ADCE-4845-80F6-9BA7F3EAC449}.Deploy|Any CPU.Build.0 = Release|Any CPU
{1F146056-ADCE-4845-80F6-9BA7F3EAC449}.MockupDebug|Any CPU.ActiveCfg = Debug|Any CPU
{1F146056-ADCE-4845-80F6-9BA7F3EAC449}.MockupDebug|Any CPU.Build.0 = Debug|Any CPU
{1F146056-ADCE-4845-80F6-9BA7F3EAC449}.MockupDeploy|Any CPU.ActiveCfg = Debug|Any CPU
{1F146056-ADCE-4845-80F6-9BA7F3EAC449}.MockupDeploy|Any CPU.Build.0 = Debug|Any CPU
{1F146056-ADCE-4845-80F6-9BA7F3EAC449}.MockupRelease|Any CPU.ActiveCfg = Release|Any CPU
{1F146056-ADCE-4845-80F6-9BA7F3EAC449}.MockupRelease|Any CPU.Build.0 = Release|Any CPU
{1F146056-ADCE-4845-80F6-9BA7F3EAC449}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1F146056-ADCE-4845-80F6-9BA7F3EAC449}.Release|Any CPU.Build.0 = Release|Any CPU
{DE50CAEF-6282-476D-A09B-AD16D6F2476F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DE50CAEF-6282-476D-A09B-AD16D6F2476F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DE50CAEF-6282-476D-A09B-AD16D6F2476F}.Deploy|Any CPU.ActiveCfg = Release|Any CPU
{DE50CAEF-6282-476D-A09B-AD16D6F2476F}.Deploy|Any CPU.Build.0 = Release|Any CPU
{DE50CAEF-6282-476D-A09B-AD16D6F2476F}.MockupDebug|Any CPU.ActiveCfg = Debug|Any CPU
{DE50CAEF-6282-476D-A09B-AD16D6F2476F}.MockupDebug|Any CPU.Build.0 = Debug|Any CPU
{DE50CAEF-6282-476D-A09B-AD16D6F2476F}.MockupDeploy|Any CPU.ActiveCfg = Debug|Any CPU
{DE50CAEF-6282-476D-A09B-AD16D6F2476F}.MockupDeploy|Any CPU.Build.0 = Debug|Any CPU
{DE50CAEF-6282-476D-A09B-AD16D6F2476F}.MockupRelease|Any CPU.ActiveCfg = Release|Any CPU
{DE50CAEF-6282-476D-A09B-AD16D6F2476F}.MockupRelease|Any CPU.Build.0 = Release|Any CPU
{DE50CAEF-6282-476D-A09B-AD16D6F2476F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DE50CAEF-6282-476D-A09B-AD16D6F2476F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
......@@ -431,6 +488,10 @@ Global
{D78AD145-DD1F-45E7-89DA-4BF58F8F2D3E} = {351FF7E8-B56B-445E-8E98-A61E07C990DA}
{EC0D4019-BBE6-431C-90E1-BD4AAEC0BF88} = {927F1B17-8075-4185-A324-92971D2FB020}
{57FB17D2-F715-4FDF-9BC1-0820D36D5650} = {73A5BF70-6168-456F-95E5-A1402BFA488C}
{090025B2-15F8-4C0C-916C-8E65AE4F64BA} = {C1DAC201-B65B-4C48-8520-A366B5736830}
{CE4A3D7D-33D6-4552-8542-335B5B8C0552} = {C1DAC201-B65B-4C48-8520-A366B5736830}
{1F146056-ADCE-4845-80F6-9BA7F3EAC449} = {C1DAC201-B65B-4C48-8520-A366B5736830}
{DE50CAEF-6282-476D-A09B-AD16D6F2476F} = {351FF7E8-B56B-445E-8E98-A61E07C990DA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B38F3172-132E-43F7-9C4B-5FDC3A28C051}
......
using Castle.Core.Internal;
using ErrorOr;
using ShellProgressBar;
using System;
using System.Reflection;
using TUGraz.VectoCommon.Utils;
using TUGraz.VectoCore.Utils;
using XMLConverterLibrary;
using System.Collections.Generic;
using System.Linq;
using System.IO;
namespace XMLConverterCmdLine
{
internal class Program
{
private static List<IXMLConverter> _xmlConverters;
private static string _targetVersion;
private static bool _verbose;
private const int SUCCESS_CODE = 0;
private const int FAILURE_CODE = 1;
private const string EXECUTABLE = "XMLConverterCmdLine.exe";
private const string HELP_OPTION = "-h";
private const string LIST_OPTION = "-l";
private const string TARGET_OPTION = "--version";
private const string VERBOSE_OPTION = "-v";
private static readonly string Usage = $@"
Usage:
{EXECUTABLE} [{HELP_OPTION}] [{LIST_OPTION}] [{VERBOSE_OPTION}] [{TARGET_OPTION}='vX.Y'] INPUT.xml
{EXECUTABLE} [{HELP_OPTION}] [{LIST_OPTION}] [{VERBOSE_OPTION}] [{TARGET_OPTION}='vX.Y'] INPUT_FOLDER
";
private static readonly string Help = $@"
Command-line Interface for the XML Converter tool.
Synopsis:
{EXECUTABLE} [{HELP_OPTION}] [{LIST_OPTION}] [{VERBOSE_OPTION}] [{TARGET_OPTION}='vX.Y'] INPUT.xml
{EXECUTABLE} [{HELP_OPTION}] [{LIST_OPTION}] [{VERBOSE_OPTION}] [{TARGET_OPTION}='vX.Y'] INPUT_FOLDER
Description:
This tool converts XML VECTO files from one version to another.
For jobs/vehicles 'version' refers to the version of the vehicle which is defined
in namespace urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:vX.Y.
The converted XML file will be placed inside a folder named '{XMLFileWriter.OUTPUT_FOLDER}',
located inside the parent folder of the original XML file.
INPUT.xml: An XML VECTO file (e.g. a job file).
INPUT_FOLDER: A folder containing VECTO files in XML format.
{TARGET_OPTION}: Target version
{LIST_OPTION}: List available conversions
{HELP_OPTION}: Displays this help text
{VERBOSE_OPTION}: Verbose mode, displays a message for each XML file successfully converted
Examples:
{EXECUTABLE} {TARGET_OPTION}='v2.4' my_job.xml
{EXECUTABLE} {VERBOSE_OPTION} {TARGET_OPTION}='v2.4' my_folder_containing_xml_jobs
{EXECUTABLE} {LIST_OPTION}
{EXECUTABLE} {HELP_OPTION}
";
static Program()
{
var jobConverter = new XMLConverter(
new XMLFileReader(),
new XMLJobConverterFactory(),
new XMLFileWriter()
);
_xmlConverters = new List<IXMLConverter>() { jobConverter };
_targetVersion = "";
_verbose = false;
}
static int Main(string[] args)
{
try
{
if (args.Length == 0)
{
WriteErrorLine(Usage, ConsoleColor.Gray);
return FAILURE_CODE;
}
if (args.AsEnumerable().Contains(HELP_OPTION))
{
ShowVersionInformation();
WriteLine(Help);
return SUCCESS_CODE;
}
if (args.AsEnumerable().Contains(LIST_OPTION))
{
PrintAvailableConversions();
return SUCCESS_CODE;
}
if (args.AsEnumerable().Contains(VERBOSE_OPTION))
{
_verbose = true;
}
if (args.AsEnumerable().Count(x => x.StartsWith($"{TARGET_OPTION}=")) == 0)
{
WriteErrorLine($"No target version specified! Use {TARGET_OPTION}='vX.Y' to specify target version.", ConsoleColor.Red);
return FAILURE_CODE;
}
if (!ParseTargetVersion(args))
{
WriteErrorLine($"'{_targetVersion}' is not a valid target version!");
return FAILURE_CODE;
}
var parseInputFileResult = ParseInputFile(args);
if (parseInputFileResult.IsError)
{
WriteErrorLine(string.Join(Environment.NewLine, parseInputFileResult.Errors.Select(x => x.Description)));
return FAILURE_CODE;
}
var resultMsgs = ExecuteConversions(parseInputFileResult.Value);
resultMsgs.ForEach(x => { Console.WriteLine(x); });
}
catch (Exception e)
{
WriteErrorLine(e.Message);
Environment.ExitCode = (Environment.ExitCode != SUCCESS_CODE) ? Environment.ExitCode : FAILURE_CODE;
}
return Environment.ExitCode;
}
private static List<string> ExecuteConversions(string file)
{
var converter = _xmlConverters.Where(x => (x.DocumentType == XmlDocumentType.DeclarationJobData)
&& x.SupportedConversions.Any(y => y.Item2 == _targetVersion)).First();
var resultMsgs = new List<string>();
var xmlFiles = (File.GetAttributes(file).HasFlag(FileAttributes.Directory)
? Directory.GetFiles(file, "*.xml", SearchOption.AllDirectories)
: new string[] { file })
.ToList()
.Where(x => !x.Contains(XMLFileWriter.OUTPUT_FOLDER));
ProgressBar progressBar = new ProgressBar(xmlFiles.Count(), "files processed", new ProgressBarOptions { ProgressBarOnBottom = true });
foreach (var item in xmlFiles)
{
var conversionResult = converter.Convert(item, _targetVersion);
progressBar.Tick();
if (conversionResult.IsError)
{
resultMsgs.Add($"{item}: ERROR: " + string.Join(Environment.NewLine, conversionResult.Errors.Select(x => x.Description)));
}
else
{
if (_verbose)
{
resultMsgs.Add($"{item}: converted!");
}
}
}
progressBar.Dispose();
return resultMsgs;
}
private static bool ParseTargetVersion(string[] args)
{
var target = args.Find(x => x.StartsWith(TARGET_OPTION));
_targetVersion = target.Substring(target.IndexOf('=') + 1).Trim().Trim('\'');
var validVersions = _xmlConverters
.Select(x => x.SupportedConversions.Select(y => y.Item2)).Aggregate((c, d) => c.Concat(d)).Distinct();
return validVersions.Contains(_targetVersion);
}
private static ErrorOr<string> ParseInputFile(string[] args)
{
var fileList = args.Where(x => !x.StartsWith(TARGET_OPTION) && (x != VERBOSE_OPTION)).ToList();
if (fileList.Count == 0)
{
return Error.NotFound(description: $"No file or folder specified for conversion!");
}
var file = fileList.First();
if (!File.Exists(file) && !Directory.Exists(file))
{
return Error.NotFound(description: $"File/folder '{file}' does not exist!");
}
bool isFolder = File.GetAttributes(file).HasFlag(FileAttributes.Directory);
if (!isFolder && Path.GetExtension(file) != ".xml")
{
return Error.Validation(description: $"File '{file}' is not XML!");
}
return file;
}
private static void PrintAvailableConversions()
{
Console.WriteLine("");
Console.WriteLine("Available Conversions");
Console.WriteLine("---------------------");
_xmlConverters.ForEach(x =>
{
Console.WriteLine($"Type: {GetUserFriendlyTypeDescription(x.DocumentType)}");
foreach (var item in x.SupportedConversions)
{
Console.WriteLine($"\t{item.Item1} -> {item.Item2}");
}
Console.WriteLine("");
});
}
private static string GetUserFriendlyTypeDescription(XmlDocumentType type)
{
if (type == XmlDocumentType.DeclarationJobData)
{
var line1 = $"VECTO Job XML [root element: 'VectoInputDeclaration', child element: 'Vehicle']";
var line2 = $"The 'Vehicle' element may also contain sub-elements whose type is defined in ";
var line3 = $"{XMLDefinitions.DECLARATION_NAMESPACE} v2.2, v2.3, and v2.5.";
var line4 = $"\nThe following conversions are supported for 'Vehicle' defined in {XMLDefinitions.DECLARATION_NAMESPACE}:";
return $"{line1}\n{line2}\n{line3}\n{line4}";
}
else
{
return type.ToString();
}
}
private static void ShowVersionInformation()
{
WriteLine($@"XMLConverterCmdLine: {Assembly.GetExecutingAssembly().GetName().Version}");
WriteLine($@"VectoCore: {VectoSimulationCore.VersionNumber}");
}
private static void WriteErrorLine(string message, ConsoleColor foregroundColor = ConsoleColor.Red)
{
Console.ForegroundColor = foregroundColor;
Console.Error.WriteLine(message);
Console.ResetColor();
}
private static void WriteLine(string message, ConsoleColor foregroundColor = ConsoleColor.Gray)
{
Console.ForegroundColor = foregroundColor;
Console.WriteLine(message);
Console.ResetColor();
}
}
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net48;net6.0</TargetFrameworks>
<Configurations>Debug;Release</Configurations>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ShellProgressBar" Version="5.2.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\XMLConverterLibrary\XMLConverterLibrary.csproj" />
</ItemGroup>
</Project>
using ErrorOr;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TUGraz.VectoCore.Utils;
namespace XMLConverterLibrary
{
public interface IXMLConverter
{
IEnumerable<Tuple<string, string>> SupportedConversions { get; }
XmlDocumentType DocumentType { get; }
ErrorOr<string> Convert(string xmlFile, string toVersion);
}
}
using ErrorOr;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TUGraz.VectoCore.Utils;
namespace XMLConverterLibrary
{
public interface IXMLConverterFactory
{
ErrorOr<IXMLEntityConverter> GetConverter(string fromVersion, string toVersion);
XmlDocumentType DocumentType { get; }
IEnumerable<Tuple<string, string>> SupportedConversions { get; }
}
}
using ErrorOr;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace XMLConverterLibrary
{
public interface IXMLEntityConverter
{
ErrorOr<XDocument> Convert(XDocument source);
}
}
using ErrorOr;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using TUGraz.VectoCore.Utils;
namespace XMLConverterLibrary
{
public interface IXMLFileReader
{
ErrorOr<XDocument> Read(string xmlFile, XmlDocumentType documentType);
}
}
using ErrorOr;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using TUGraz.VectoCore.Utils;
namespace XMLConverterLibrary
{
public interface IXMLFileWriter
{
ErrorOr<string> Write(XDocument document, XmlDocumentType documentType, string filePath);
string CreateOutputFilePath(string inputFilePath);
}
}
using ErrorOr;
using System;
using System.Collections.Generic;
using System.Xml.Linq;
using TUGraz.VectoCore.Utils;
namespace XMLConverterLibrary
{
public class XMLConverter : IXMLConverter
{
private readonly IXMLFileReader _xmlFileReader;
private readonly IXMLConverterFactory _xmlConverterFactory;
private readonly IXMLFileWriter _xmlFileWriter;
public XMLConverter(
IXMLFileReader xmlFileReader,
IXMLConverterFactory xmlConverterFactory,
IXMLFileWriter xmlFileWriter)
{
_xmlFileReader = xmlFileReader;
_xmlConverterFactory = xmlConverterFactory;
_xmlFileWriter = xmlFileWriter;
}
public XmlDocumentType DocumentType => _xmlConverterFactory.DocumentType;
public IEnumerable<Tuple<string, string>> SupportedConversions => _xmlConverterFactory.SupportedConversions;
public ErrorOr<string> Convert(string xmlFile, string toVersion)
{
var readResult = _xmlFileReader.Read(xmlFile, _xmlConverterFactory.DocumentType);
if (readResult.IsError) {
return readResult.Errors;
}
var convertResult = Convert(readResult.Value, toVersion);
if (convertResult.IsError) {
return convertResult.Errors;
}
var outputPath = _xmlFileWriter.CreateOutputFilePath(xmlFile);
var writeResult = _xmlFileWriter.Write(convertResult.Value, _xmlConverterFactory.DocumentType, outputPath);
return writeResult;
}
private ErrorOr<XDocument> Convert(XDocument source, string toVersion)
{
string fromVersion = XMLUtils.GetVersion(source, _xmlConverterFactory.DocumentType);
ErrorOr<IXMLEntityConverter> getConverterResult = _xmlConverterFactory.GetConverter(fromVersion, toVersion);
if (getConverterResult.IsError) {
return getConverterResult.Errors;
}
try {
return getConverterResult.Value.Convert(source);
}
catch (Exception ex) {
return Error.Failure(description: $"XMLConverter: {ex.Message}");
}
}
}
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net6.0;net48</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<InternalsVisibleTo Include="XMLConverterLibraryTests" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="ErrorOr" Version="2.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\VectoCore\VectoCore\VectoCore.csproj" />
</ItemGroup>
</Project>
using ErrorOr;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using TUGraz.VectoCore.Utils;
namespace XMLConverterLibrary
{
public class XMLFileReader : IXMLFileReader
{
public ErrorOr<XDocument> Read(string xmlFile, XmlDocumentType documentType)
{
if (!File.Exists(xmlFile)) {
return Error.NotFound(description: $"XMLFileReader: file not found: {xmlFile}");
}
var validateResult = XMLUtils.ValidateXML(xmlFile, documentType);
if (validateResult.IsError) {
return validateResult.Errors;
}
return XDocument.Load(xmlFile);
}
}
}
using ErrorOr;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using TUGraz.VectoCore.Utils;
namespace XMLConverterLibrary
{
public class XMLFileWriter : IXMLFileWriter
{
public const string OUTPUT_FOLDER = "XMLConverter_Output";
public ErrorOr<string> Write(XDocument document, XmlDocumentType documentType, string filePath)
{
try {
Directory.CreateDirectory(Path.GetDirectoryName(filePath));
}
catch (Exception ex) {
return Error.Failure(description: ex.Message);
}
document.Save(filePath);
var validateResult = XMLUtils.ValidateXML(filePath, documentType);
if (validateResult.IsError) {
return validateResult.Errors;
}
return filePath;
}
public string CreateOutputFilePath(string inputFilePath)
{
var directory = Path.GetDirectoryName(inputFilePath);
var filename = Path.GetFileName(inputFilePath);
return Path.Combine(Path.Combine(directory, OUTPUT_FOLDER), filename);
}
}
}
using ErrorOr;
using System;
using System.Collections.Generic;
using System.Linq;
using TUGraz.VectoCommon.Utils;
using TUGraz.VectoCore.Utils;
namespace XMLConverterLibrary
{
public class XMLJobConverterFactory : IXMLConverterFactory
{
private static readonly List<AbstractXMLJobConverter> _converters;
static XMLJobConverterFactory()
{
_converters = new List<AbstractXMLJobConverter> {
new XMLJobConverter_v1_0_To_v_2_4(),
new XMLJobConverter_v2_0_To_v2_4(),
new XMLJobConverter_v2_1_To_v2_4(),
new XMLJobConverter_v2_2_1_To_v2_4()
};
}
public IEnumerable<Tuple<string, string>> SupportedConversions =>
_converters.Select(x => new Tuple<string, string>(x.SourceVersion, x.TargetVersion));
public ErrorOr<IXMLEntityConverter> GetConverter(string fromVersion, string toVersion)
{
var converter = _converters.Find(x => (x.SourceVersion == fromVersion) && (x.TargetVersion == toVersion));
if (converter == null) {
return Error.NotFound(
description: $"XMLJobConverterFactory: converter from <{fromVersion}> to <{toVersion}> not found!");
}
return converter;
}
public XmlDocumentType DocumentType => XmlDocumentType.DeclarationJobData;
}
}
using ErrorOr;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using System.Xml.XPath;
using TUGraz.VectoCommon.Resources;
using TUGraz.VectoCore.OutputData.XML;
namespace XMLConverterLibrary
{
public abstract class AbstractXMLJobConverter : IXMLEntityConverter
{
protected const string CREATED_BY = "Created by the VECTO XML Converter tool";
public ErrorOr<XDocument> Convert(XDocument source)
{
var sourceVersion = XMLUtils.GetJobVersion(source);
if (sourceVersion != SourceVersion)
{
return Error.Validation(
description: $"XMLJobConverter: source job version ({sourceVersion}) should be {SourceVersion}");
}
var target = ConvertWithoutVersionValidation(source);
var targetVersion = XMLUtils.GetJobVersion(target);
if (targetVersion != TargetVersion)
{
return Error.Validation(
description: $"XMLJobConverter: target job version ({targetVersion}) should be {TargetVersion}");
}
return target;
}
public abstract string SourceVersion { get; }
public abstract string TargetVersion { get; }
public XNamespace TargetNamespace => $"{XMLDeclarationNamespaces.DeclarationDefinition}:{TargetVersion}";
protected XDocument ConvertWithoutVersionValidation(XDocument doc)
{
ConvertRootElement(doc);
var isExempted = IsVehicleExempted(doc);
ConvertVehicleBase(doc, isExempted);
return isExempted ? ConvertExemptedVehicle(doc) : ConvertNonExemptedVehicle(doc);
}
protected virtual XDocument ConvertExemptedVehicle(XDocument doc)
{
XMLUtils.AddElementAfter(doc, "Vehicle/ChassisConfiguration", "AxleConfiguration", CalculateAxleConfiguration(doc));
XMLUtils.AddElementAfter(doc, "Vehicle/ZeroEmissionVehicle", "SleeperCab", "true");
AddSumNetPower(doc);
AddExemptedTech(doc);
return doc;
}
private void AddExemptedTech(XDocument doc)
{
var exemptedTech = GetExemptedTech(doc);
XMLUtils.DeleteElement(doc, "Vehicle/HybridElectricHDV");
XMLUtils.DeleteElement(doc, "Vehicle/DualFuelVehicle");
XMLUtils.AddElementAfter(doc, "Vehicle/SumNetPower", "Technology", exemptedTech);
}
private string GetExemptedTech(XDocument doc)
{
var hevNode = doc.XPathSelectElement(XMLUtils.QueryLocalName("HybridElectricHDV"));
bool.TryParse(hevNode?.Value, out bool isHEV);
if (isHEV)
{
return "HEV Article 9 exempted";
}
var dualNode = doc.XPathSelectElement(XMLUtils.QueryLocalName("DualFuelVehicle"));
bool.TryParse(dualNode?.Value, out bool isDualFuel);
if (isDualFuel)
{
return "Dual fuel vehicle Article 9 exempted";
}
return "Other technology Article 9 exempted";
}
private void AddSumNetPower(XDocument doc)
{
var sumNetPower = CalculateSumNetPower(doc);
XMLUtils.DeleteElement(doc, "Vehicle/MaxNetPower1");
XMLUtils.DeleteElement(doc, "Vehicle/MaxNetPower2");
XMLUtils.AddElementAfter(doc, "Vehicle/SleeperCab", "SumNetPower", sumNetPower.ToString());
}
private int CalculateSumNetPower(XDocument doc)
{
var power1Node = doc.XPathSelectElement(XMLUtils.QueryLocalName("MaxNetPower1"));
int power1 = 0;
if (power1Node != null)
{
int.TryParse(power1Node.Value, out power1);
}
var power2Node = doc.XPathSelectElement(XMLUtils.QueryLocalName("MaxNetPower2"));
int power2 = 0;
if (power2Node != null)
{
int.TryParse(power2Node.Value, out power2);
}
return power1 + power2;
}
protected void ConvertEngine(XDocument doc)
{
string version = SelectVersion(doc.XPathSelectElement(XMLUtils.QueryLocalName("Engine/Data".Split('/'))));
XMLUtils.SetElementsType(doc, "Engine/Data", "EngineDataDeclarationType");
XMLUtils.SetElementsNamespace(doc, "Engine/Data", XMLUtils.V2_0);
XMLUtils.SetElementsDescendantsNamespace(doc, "Engine/Data", version);
XMLUtils.SetElementsAttribute(doc, "Engine/Data", "xmlns", $"{XMLDeclarationNamespaces.DeclarationDefinition}:{version}");
XMLUtils.SetElementsNamespace(doc, "Engine/Signature", XMLUtils.V2_0);
}
protected void ConvertGearbox(XDocument doc)
{
XMLUtils.SetElementsType(doc, "Gearbox/Data", "GearboxDataDeclarationType");
XMLUtils.SetElementsNamespace(doc, "Gearbox/Data", XMLUtils.V2_0);
XMLUtils.SetElementsDescendantsNamespace(doc, "Gearbox/Data", XMLUtils.V2_0);
XMLUtils.SetElementsAttribute(doc, "Gearbox/Data", "xmlns", $"{XMLDeclarationNamespaces.DeclarationDefinition}:{XMLUtils.V2_0}");
XMLUtils.SetElementsType(doc, "Gearbox/Data/Gears", "GearsDeclarationType");
XMLUtils.SetElementsNamespace(doc, "Gearbox/Signature", XMLUtils.V2_0);
}
protected void ConvertRetarder(XDocument doc)
{
XMLUtils.SetElementsType(doc, "Retarder/Data", "RetarderDataDeclarationType");
XMLUtils.SetElementsNamespace(doc, "Retarder/Data", XMLUtils.V2_0);
XMLUtils.SetElementsDescendantsNamespace(doc, "Retarder/Data", XMLUtils.V2_0);
XMLUtils.SetElementsAttribute(doc, "Retarder/Data", "xmlns", $"{XMLDeclarationNamespaces.DeclarationDefinition}:{XMLUtils.V2_0}");
XMLUtils.SetElementsNamespace(doc, "Retarder/Signature", XMLUtils.V2_0);
}
protected void ConvertAxlegear(XDocument doc)
{
XMLUtils.SetElementsType(doc, "Axlegear/Data", "AxlegearDataDeclarationType");
XMLUtils.SetElementsNamespace(doc, "Axlegear/Data", XMLUtils.V2_0);
XMLUtils.SetElementsDescendantsNamespace(doc, "Axlegear/Data", XMLUtils.V2_0);
XMLUtils.SetElementsAttribute(doc, "Axlegear/Data", "xmlns", $"{XMLDeclarationNamespaces.DeclarationDefinition}:{XMLUtils.V2_0}");
XMLUtils.SetElementsNamespace(doc, "Axlegear/Signature", XMLUtils.V2_0);
}
protected void ConvertAxleWheels(XDocument doc)
{
XMLUtils.SetElementsType(doc, "AxleWheels/Data", "AxleWheelsDataDeclarationType");
XMLUtils.SetElementsNamespace(doc, "AxleWheels/Data", XMLUtils.V2_0);
XMLUtils.SetElementsDescendantsNamespace(doc, "AxleWheels/Data", XMLUtils.V2_0);
XMLUtils.SetElementsAttribute(doc, "AxleWheels/Data", "xmlns", $"{XMLDeclarationNamespaces.DeclarationDefinition}:{XMLUtils.V2_0}");
XMLUtils.SetElementsType(doc, "AxleWheels/Data/Axles/Axle", "AxleDataDeclarationType");
XMLUtils.SetElementsNamespace(doc, "AxleWheels/Signature", XMLUtils.V2_0);
ConvertTyres(doc);
}
protected void ConvertTyres(XDocument doc)
{
XMLUtils.SetElementsType(doc, "Tyre/Data", "TyreDataDeclarationType");
var nodes = doc.XPathSelectElements(XMLUtils.QueryLocalName("Tyre/Data".Split('/')));
foreach (var node in nodes)
{
var tyreVersion = SelectVersion(node);
node.SetAttributeValue("xmlns", $"{XMLDeclarationNamespaces.DeclarationDefinition}:{tyreVersion}");
XMLUtils.SetElementDescendantsNamespace(node, tyreVersion);
}
}
protected string SelectVersion(XElement node)
{
List<string> versions = new List<string>() { XMLUtils.V2_0 };
var nsnVersion = node.Name.NamespaceName.Split(':').Last();
if (nsnVersion != TargetVersion)
{
versions.Add(nsnVersion);
}
var defnsVersion = node.GetDefaultNamespace().NamespaceName.Split(':').Last();
if (defnsVersion != TargetVersion)
{
versions.Add(defnsVersion);
}
return versions.OrderByDescending(x => x).First();
}
protected void ConvertAuxiliaries(XDocument doc)
{
XMLUtils.SetElementsAttribute(doc, "Auxiliaries", "xmlns", null);
XMLUtils.SetElementsType(doc, "Auxiliaries", null);
XMLUtils.SetElementsType(doc, "Auxiliaries/Data", "AUX_Conventional_LorryDataType");
XMLUtils.SetElementsAttribute(doc, "Auxiliaries/Data/SteeringPump/Technology", "axleNumber", "1");
}
protected void ConvertAirDrag(XDocument doc)
{
XMLUtils.SetElementsType(doc, "AirDrag/Data", "AirDragDataDeclarationType");
XMLUtils.SetElementsNamespace(doc, "AirDrag/Data", XMLUtils.V2_0);
XMLUtils.SetElementsDescendantsNamespace(doc, "AirDrag/Data", XMLUtils.V2_0);
XMLUtils.SetElementsAttribute(doc, "AirDrag/Data", "xmlns", $"{XMLDeclarationNamespaces.DeclarationDefinition}:{XMLUtils.V2_0}");
XMLUtils.SetElementsNamespace(doc, "AirDrag/Signature", XMLUtils.V2_0);
}
protected void ConvertTorqueLimits(XDocument doc)
{
XMLUtils.SetElementsType(doc, "Vehicle/TorqueLimits", "TorqueLimitsType");
XMLUtils.SetElementsNamespace(doc, "Vehicle/TorqueLimits", XMLUtils.V2_4);
XMLUtils.SetElementsDescendantsNamespace(doc, "Vehicle/TorqueLimits", XMLUtils.V2_0);
XMLUtils.SetElementsAttribute(doc, "Vehicle/TorqueLimits", "xmlns", $"{XMLDeclarationNamespaces.DeclarationDefinition}:{XMLUtils.V2_0}");
}
protected virtual void ConvertTorqueConverter(XDocument doc)
{
XMLUtils.SetElementsType(doc, "TorqueConverter/Data", "TorqueConverterDataDeclarationType");
XMLUtils.SetElementsNamespace(doc, "TorqueConverter/Data", XMLUtils.V2_0);
XMLUtils.SetElementsDescendantsNamespace(doc, "TorqueConverter/Data", XMLUtils.V2_0);
XMLUtils.SetElementsAttribute(doc, "TorqueConverter/Data", "xmlns", $"{XMLDeclarationNamespaces.DeclarationDefinition}:{XMLUtils.V2_0}");
XMLUtils.SetElementsNamespace(doc, "TorqueConverter/Signature", XMLUtils.V2_0);
}
protected void ConvertAngleDrive(XDocument doc)
{
XMLUtils.SetElementsType(doc, "Angledrive/Data", "AngledriveDataDeclarationType");
XMLUtils.SetElementsNamespace(doc, "Angledrive/Data", XMLUtils.V2_0);
XMLUtils.SetElementsDescendantsNamespace(doc, "Angledrive/Data", XMLUtils.V2_0);
XMLUtils.SetElementsAttribute(doc, "Angledrive/Data", "xmlns", $"{XMLDeclarationNamespaces.DeclarationDefinition}:{XMLUtils.V2_0}");
XMLUtils.SetElementsNamespace(doc, "Angledrive/Signature", XMLUtils.V2_0);
}
protected void SetDefaultNamespace(XDocument doc)
{
doc.Root.Attribute("xmlns")?.Remove();
doc.Root.Name = XMLDeclarationNamespaces.Tns_v20 + doc.Root.Name.LocalName;
doc.Root.SetAttributeValue("xmlns", $"{XMLDeclarationNamespaces.DeclarationDefinition}:{TargetVersion}");
}
protected void RemoveSchemaLocation(XDocument doc)
{
doc.Root.Attribute(XMLDeclarationNamespaces.Xsi + XMLNames.SchemaLocation)?.Remove();
}
protected virtual void AddNamespaces(XDocument doc)
{
doc.Root.SetAttributeValue(XNamespace.Xmlns + XMLUtils.V2_0, $"{XMLDeclarationNamespaces.DeclarationDefinition}:{XMLUtils.V2_0}");
doc.Root.SetAttributeValue(XNamespace.Xmlns + XMLUtils.V2_4, $"{XMLDeclarationNamespaces.DeclarationDefinition}:{XMLUtils.V2_4}");
}
protected bool IsVehicleExempted(XDocument doc)
{
var componentsNode = doc.XPathSelectElement(XMLUtils.QueryLocalName("Vehicle", "Components"));
return componentsNode == null;
}
protected virtual XDocument ConvertNonExemptedVehicle(XDocument doc)
{
XMLUtils.SetElementsType(doc, "Vehicle/PTO", "PTOType");
XMLUtils.SetElementsAttribute(doc, "Vehicle/PTO", "xmlns", null);
XMLUtils.SetElementsType(doc, "Vehicle/ADAS", "ADAS_Conventional_Type");
XMLUtils.SetElementsType(doc, "Vehicle/Components", "Components_Conventional_LorryType");
ConvertEngine(doc);
ConvertGearbox(doc);
ConvertRetarder(doc);
ConvertAxlegear(doc);
ConvertAxleWheels(doc);
ConvertAuxiliaries(doc);
ConvertAirDrag(doc);
ConvertTorqueLimits(doc);
ConvertTorqueConverter(doc);
ConvertAngleDrive(doc);
return doc;
}
protected virtual void ConvertRootElement(XDocument doc)
{
ChangeValueOfSchemaVersionAttribute(doc);
SetDefaultNamespace(doc);
SetNamespaceTNS(doc);
AddNamespaces(doc);
RemoveSchemaLocation(doc);
AddSourceComment(doc);
}
protected void AddSourceComment(XDocument doc)
{
doc.Root.AddBeforeSelf(new XComment(CREATED_BY));
}
protected void ChangeValueOfSchemaVersionAttribute(XDocument doc)
{
doc.Root.SetAttributeValue("schemaVersion", "2.0");
}
protected void SetNamespaceTNS(XDocument doc)
{
doc.Root.SetAttributeValue(XNamespace.Xmlns + "tns", XMLDeclarationNamespaces.Tns_v20);
}
protected void ConvertVehicleBase(XDocument doc, bool isExempted)
{
XMLUtils.SetElementsNamespace(doc, "Vehicle", XMLUtils.V2_0);
XMLUtils.SetElementsType(
doc,
"Vehicle",
isExempted
? "Vehicle_Exempted_HeavyLorryDeclarationType"
: "Vehicle_Conventional_HeavyLorryDeclarationType"
);
XMLUtils.SetElementsDescendantsNamespace(doc, "Vehicle", TargetVersion);
XMLUtils.SetElementsAttribute(doc, "Vehicle", "xmlns", null);
XMLUtils.SetElementName(doc, "Vehicle/LegislativeClass", "LegislativeCategory", TargetNamespace);
XMLUtils.SetElementName(doc, "Vehicle/VehicleCategory", "ChassisConfiguration", TargetNamespace);
XMLUtils.FixElementValue(doc, "ChassisConfiguration");
XMLUtils.SetElementName(doc, "Vehicle/CurbMassChassis", "CorrectedActualMass", TargetNamespace);
XMLUtils.SetElementName(doc, "Vehicle/GrossVehicleMass", "TechnicalPermissibleMaximumLadenMass", TargetNamespace);
XMLUtils.AddElementAfter(doc, "Vehicle/ChassisConfiguration", "AxleConfiguration", CalculateAxleConfiguration(doc));
}
protected string CalculateAxleConfiguration(XDocument doc)
{
var axles = XMLUtils.GetElements(doc, "AxleWheels/Data/Axles/Axle");
var drivenAxlesCount = axles.Count(x => x.XPathSelectElement(XMLUtils.QueryLocalName("AxleType")).Value == "VehicleDriven");
return (axles.Count() > 0) ? $"{axles.Count() * 2}x{drivenAxlesCount * 2}" : "4x2";
}
}
public class XMLJobConverter_v1_0_To_v_2_4 : AbstractXMLJobConverter
{
public override string SourceVersion => XMLUtils.V1_0;
public override string TargetVersion => XMLUtils.V2_4;
protected override void ConvertTorqueConverter(XDocument doc)
{
XMLUtils.MoveElementUp(doc, "Gearbox/TorqueConverter");
base.ConvertTorqueConverter(doc);
}
}
public class XMLJobConverter_v2_0_To_v2_4 : AbstractXMLJobConverter
{
public override string SourceVersion => XMLUtils.V2_0;
public override string TargetVersion => XMLUtils.V2_4;
protected override XDocument ConvertNonExemptedVehicle(XDocument doc)
{
base.ConvertNonExemptedVehicle(doc);
XMLUtils.AddElementAfter(doc, "Vehicle/PTO", "ZeroEmissionVehicle", "false");
XMLUtils.AddElementAfter(doc, "Vehicle/ZeroEmissionVehicle", "VocationalVehicle", "false");
XMLUtils.AddElementAfter(doc, "Vehicle/VocationalVehicle", "SleeperCab", "true");
AddADAS(doc);
return doc;
}
private void AddADAS(XDocument doc)
{
var added = XMLUtils.AddElementAfter(doc, "Vehicle/SleeperCab", "ADAS", "");
if (!added)
{
return;
}
XMLUtils.SetElementsType(doc, "Vehicle/ADAS", "ADAS_Conventional_Type");
XMLUtils.AddElementTo(doc, "Vehicle/ADAS", "EngineStopStart", "false");
XMLUtils.AddElementTo(doc, "Vehicle/ADAS", "EcoRollWithoutEngineStop", "false");
XMLUtils.AddElementTo(doc, "Vehicle/ADAS", "EcoRollWithEngineStop", "false");
XMLUtils.AddElementTo(doc, "Vehicle/ADAS", "PredictiveCruiseControl", "none");
}
}
public class XMLJobConverter_v2_1_To_v2_4 : AbstractXMLJobConverter
{
public override string SourceVersion => XMLUtils.V2_1;
public override string TargetVersion => XMLUtils.V2_4;
protected override void AddNamespaces(XDocument doc)
{
base.AddNamespaces(doc);
doc.Root.SetAttributeValue(XNamespace.Xmlns + SourceVersion, $"{XMLDeclarationNamespaces.DeclarationDefinition}:{SourceVersion}");
}
}
public class XMLJobConverter_v2_2_1_To_v2_4 : AbstractXMLJobConverter
{
public override string SourceVersion => XMLUtils.V2_2_1;
public override string TargetVersion => XMLUtils.V2_4;
protected override void AddNamespaces(XDocument doc)
{
base.AddNamespaces(doc);
doc.Root.SetAttributeValue(XNamespace.Xmlns + SourceVersion, $"{XMLDeclarationNamespaces.DeclarationDefinition}:{SourceVersion}");
}
}
}
using ErrorOr;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Xml.XPath;
using TUGraz.VectoCommon.Resources;
using TUGraz.VectoCommon.Utils;
using TUGraz.VectoCore.OutputData.XML;
using TUGraz.VectoCore.Utils;
namespace XMLConverterLibrary
{
public static class XMLUtils
{
private static readonly Dictionary<XmlDocumentType, Func<XDocument, string>> _versionGetters;
private static readonly Dictionary<string, Dictionary<string, string>> _valueFixes;
public const string V1_0 = "v1.0";
public const string V2_0 = "v2.0";
public const string V2_1 = "v2.1";
public const string V2_2 = "v2.2";
public const string V2_2_1 = "v2.2.1";
public const string V2_3 = "v2.3";
public const string V2_4 = "v2.4";
public const string V2_5 = "v2.5";
static XMLUtils()
{
_versionGetters = new Dictionary<XmlDocumentType, Func<XDocument, string>>() {
{ XmlDocumentType.DeclarationJobData, GetJobVersion }
};
_valueFixes = new Dictionary<string, Dictionary<string, string>>() {
{
"ChassisConfiguration", new Dictionary<string, string>() {
{ "Rigid Truck", "Rigid Lorry" }
}
}
};
}
public static string QueryLocalName(params string[] nodePath)
{
return "./" + string.Join("",
nodePath.Where(x => x != null).Select(x => $"/*[local-name()='{x}']").ToArray());
}
public static string GetVersion(XDocument doc, XmlDocumentType documentType)
{
return _versionGetters.ContainsKey(documentType) ? _versionGetters[documentType](doc) : null;
}
public static string GetJobVersion(XDocument doc)
{
var vehicleNode = doc.XPathSelectElement(QueryLocalName("Vehicle"));
if (vehicleNode == null)
{
return null;
}
var nameVersion = vehicleNode.Name.NamespaceName.Split(':').Last();
var defaultNamespaceVersion = vehicleNode.GetDefaultNamespace().NamespaceName.Split(':').Last();
return (new List<string>() { nameVersion, defaultNamespaceVersion }).OrderByDescending(x => x).First();
}
public static ErrorOr<bool> ValidateXML(string xmlFile, XmlDocumentType documentType)
{
try {
var xmlReader = System.Xml.XmlReader.Create(xmlFile);
var validator = new XMLValidator(xmlReader);
bool isValid = validator.ValidateXML(documentType);
if (!isValid) {
return Error.Failure(description: $"ValidateXML: {validator.ValidationError}");
}
}
catch (Exception ex) {
return Error.Failure(description: $"ValidateXML: {ex.Message}");
}
return true;
}
public static void SetElementName(XDocument doc, string elementPath, string name, XNamespace xs)
{
var node = doc.XPathSelectElement(QueryLocalName(elementPath.Split('/')));
if (node == null)
{
return;
}
node.Name = xs + name;
}
public static void FixElementValue(XDocument doc, string element)
{
var node = doc.XPathSelectElement(QueryLocalName(element));
if (node == null)
{
return;
}
if (_valueFixes.ContainsKey(element) && _valueFixes[element].ContainsKey(node.Value))
{
node.Value = _valueFixes[element][node.Value];
}
}
public static IEnumerable<XElement> GetElements(XDocument doc, string elementPath)
{
return doc.XPathSelectElements(QueryLocalName(elementPath.Split('/')));
}
public static void SetElementsDescendantsNamespace(XDocument doc, string elementPath, string version)
{
var nodes = doc.XPathSelectElements(QueryLocalName(elementPath.Split('/')));
XNamespace xs = $"{XMLDeclarationNamespaces.DeclarationDefinition}:{version}";
foreach (var node in nodes)
{
foreach (var item in node.Descendants())
{
if (item.Name.NamespaceName.StartsWith(XMLDeclarationNamespaces.DeclarationDefinition))
{
item.Name = xs + item.Name.LocalName;
}
}
}
}
public static void SetElementDescendantsNamespace(XElement node, string version)
{
XNamespace xs = $"{XMLDeclarationNamespaces.DeclarationDefinition}:{version}";
foreach (var item in node.Descendants())
{
if (item.Name.NamespaceName.StartsWith(XMLDeclarationNamespaces.DeclarationDefinition))
{
item.Name = xs + item.Name.LocalName;
}
}
}
public static void DeleteElement(XDocument doc, string elementPath)
{
var node = doc.XPathSelectElement(QueryLocalName(elementPath.Split('/')));
node?.Remove();
}
public static void AddElementTo(XDocument doc, string parent, string name, string value)
{
var node = doc.XPathSelectElement(QueryLocalName(name));
if (node != null)
{
return;
}
var parentNode = doc.XPathSelectElement(QueryLocalName(parent.Split('/')));
parentNode.Add(new XElement(parentNode.Name.Namespace + name, value));
}
public static bool AddElementAfter(XDocument doc, string previous, string name, string value)
{
var node = doc.XPathSelectElement(QueryLocalName(name));
if (node != null)
{
return false;
}
var previousNode = doc.XPathSelectElement(QueryLocalName(previous.Split('/')));
if (previousNode == null)
{
return false;
}
previousNode.AddAfterSelf(new XElement(previousNode.Name.Namespace + name, value));
return true;
}
public static void MoveElementUp(XDocument doc, string elementPath)
{
var node = doc.XPathSelectElement(QueryLocalName(elementPath.Split('/')));
if (node == null)
{
return;
}
var parent = node.Parent;
node.Remove();
parent.AddAfterSelf(node);
}
public static void SetElementsNamespace(XDocument doc, string elementPath, string prefix)
{
var nodes = doc.XPathSelectElements(QueryLocalName(elementPath.Split('/')));
foreach (var node in nodes)
{
XNamespace xnsPrefix = doc.Root.GetNamespaceOfPrefix(prefix);
node.Name = xnsPrefix + node.Name.LocalName;
}
}
public static void SetElementsAttribute(XDocument doc, string elementPath, XName attr, string value)
{
var nodes = doc.XPathSelectElements(QueryLocalName(elementPath.Split('/')));
foreach (var node in nodes)
{
node.SetAttributeValue(attr, value);
}
}
public static void SetElementsType(XDocument doc, string elementPath, string type)
{
SetElementsAttribute(doc, elementPath, XMLDeclarationNamespaces.Xsi + XMLNames.XSIType, type);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XMLConverterLibraryTests
{
internal class InputData
{
public const string V1_0 = "TestData/Vehicles/SchemaVersion1.0";
public const string EXEMPTED_V1_0 = $"{V1_0}/vecto_vehicle-exempted-sample.xml";
public const string EXEMPTED_MISSING_OPTIONAL_V1_0 = $"{V1_0}/vecto_vehicle-exempted-sample_MissingOptional.xml";
public const string CLASS_5_V1_0 = $"{V1_0}/Tractor_4x2_vehicle-class-5_5_t_0.xml";
public const string CLASS_5_MISSING_OPTIONAL_V1_0 = $"{V1_0}/Tractor_4x2_vehicle-class-5_5_t_0_MissingOptional.xml";
public const string NEW_PARAMS_V1_0 = $"{V1_0}/vecto_vehicle-new_parameters-sample.xml";
public const string LNG_V1_0 = $"{V1_0}/vecto_vehicle-sample_LNG.xml";
public const string SAMPLE_V1_0 = $"{V1_0}/vecto_vehicle-sample.xml";
public const string SAMPLE_AT_V1_0 = $"{V1_0}/vecto_vehicle-sample_AT.xml";
public const string CERT_OPTIONS_V1_0 = $"{V1_0}/vecto_vehicle-sample_certificationOptions.xml";
public const string SAMPLE_FULL_V1_0 = $"{V1_0}/vecto_vehicle-sample_FULL.xml";
public const string SAMPLE_FULL_UPD_V1_0 = $"{V1_0}/vecto_vehicle-sample_FULL_updated.xml";
public const string SAMPLE_NO_AIRDRAG_V1_0 = $"{V1_0}/vecto_vehicle-sample_noAirdrag.xml";
public const string SAMPLE_NO_TORQUE_LIMITS_V1_0 = $"{V1_0}/vecto_vehicle-sample_torqueLimits.xml";
public const string V2_0 = "TestData/Vehicles/SchemaVersion2.0";
public const string CLASS_5_V2_0 = $"{V2_0}/Tractor_4x2_vehicle-class-5_5_t_0.xml";
public const string MISSING_OPTIONALS_V2_0 = $"{V2_0}/vecto_vehicle_MissingOptionals.xml";
public const string COMPONENTS_V2_0 = $"{V2_0}/vecto_vehicle-components_1.0.xml";
public const string NEW_PARAMS_V2_0 = $"{V2_0}/vecto_vehicle-new_parameters-sample.xml";
public const string LNG_V2_0 = $"{V2_0}/vecto_vehicle-sample_LNG.xml";
public const string V2_1 = "TestData/Vehicles/SchemaVersion2.1";
public const string CLASS_5_V2_1 = $"{V2_1}/Tractor_4x2_vehicle-class-5_5_t_0.xml";
public const string EXEMPTED_V2_1 = $"{V2_1}/vecto_vehicle-exempted-sample.xml";
public const string EXEMPTED_MISSING_OPTIONAL_V2_1 = $"{V2_1}/vecto_vehicle-exempted_MissingOptional.xml";
public const string NEW_PARAMS_V2_1 = $"{V2_1}/vecto_vehicle-new_parameters-sample.xml";
public const string LNG_V2_1 = $"{V2_1}/vecto_vehicle-sample_LNG.xml";
public const string TYRE_25_V2_1 = $"{V2_1}/vecto_vehicle-tyre25.xml";
public const string V2_2 = "TestData/Vehicles/SchemaVersion2.2";
public const string CLASS_5_V2_2 = $"{V2_2}/Tractor_4x2_vehicle-class-5_5_t_0.xml";
public const string LNG_V2_2 = $"{V2_2}/vecto_vehicle-sample_LNG.xml";
public const string V2_2_1 = "TestData/Vehicles/SchemaVersion2.2.1";
public const string EXEMPTED_V2_2_1 = $"{V2_2_1}/vecto_vehicle-exempted-sample.xml";
public const string EXEMPTED_MISSING_OPTIONAL_V2_2_1 = $"{V2_2_1}/vecto_vehicle-exempted-sample_MissingOptional.xml";
public const string V2_3 = "TestData/Vehicles/SchemaVersion2.3";
public const string DUAL_MODE_DUAL_FUEL_V2_3 = $"{V2_3}/vehicle_sampleDualModeDualFuel.xml";
public const string DUAL_MODE_DUAL_FUEL_WHR_V2_3 = $"{V2_3}/vehicle_sampleDualModeDualFuel_WHR.xml";
public const string SINGLE_MODE_DUAL_FUEL_V2_3 = $"{V2_3}/vehicle_sampleSingleModeDualFuel.xml";
public const string SINGLE_MODE_DUAL_FUEL_WHR_V2_3 = $"{V2_3}/vehicle_sampleSingleModeDualFuel_WHR.xml";
public const string SINGLE_MODE_SINGLE_FUEL_WHR_V2_3 = $"{V2_3}/vehicle_sampleSingleModeSingleFuel_WHR.xml";
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment