public static bool IsUpToDate(string emPath, string country) { EMPath pathHandler = new EMPath(emPath); return(TransformerCommon.IsFileUpToDate(pathHandler.GetCountryFilePath(country, true), pathHandler.GetCountryFolderPath(country), out string hash1) && TransformerCommon.IsFileUpToDate(pathHandler.GetEM2DataConfigFilePath(country), pathHandler.GetCountryFolderPath(country), out string hash2)); }
/// <summary> /// reads the EM2 variables file and transfers it to EM3 style /// creates the config folder, if it does not exist, and overwrites any existing variables file /// note: the intended usage is "single variables transformation" /// the EM3All class is responsible for complete EM-content transformation (using the EM3Variables.Write functions) /// </summary> /// <param name="emPath"> EuromodFiles folder (containing EM2-files in XMLParam and (will contain) EM3-files in EM3Translation\XMLParam) </param> /// <param name="errors"> critical and non-critical erros during the transformation-process, empty structure for no errors </param> public static bool Transform(string emPath, out List <string> errors) { errors = new List <string>(); EMPath pathHandler = new EMPath(emPath); try { DirectoryInfo di = Directory.CreateDirectory(pathHandler.GetFolderConfig()); if (TransformerCommon.IsFileUpToDate(pathHandler.GetVarFilePath(em2: true), di.FullName, out string hashCode)) { return(true); } // read EM2-file EM2Variables.Content content = EM2Variables.Read(pathHandler.GetFolderConfig(em2: true), out List <string> rErrors); if (content == null) { errors = rErrors; return(false); } // transfer to EM3-structure bool success = Write(content, emPath, out List <string> wErrors); errors.AddRange(wErrors); if (success && errors.Count == 0) { TransformerCommon.WriteUpToDate(pathHandler.GetVarFilePath(em2: true), di.FullName, hashCode); } return(success); } catch (Exception exception) { errors.Add($"Variables: {exception.Message}"); return(false); } }
/// <summary> /// transfers a global file (for ex-rates, hicp, glo-switches) into EM3 style and creates the EM3 file /// note: this class is only responsible for writing /// EM2->EM3 adaptations are accomplished by a call to the EM23Adapt class (see AdaptX in the concrete functions above) /// also note: the function (respectively the concrete versions, see above) /// is not intended to be used "stand-alone", but by EM3Global.Transform and EM3All.Write /// </summary> /// <param name="content"> content of global file as read by EM2Global.Read </param> /// <param name="fileName"> full path of EM3 global-file (i.e. the file to write) </param> /// <param name="errors"> critical and non-critical erros during the write-process, empty structure for no errors </param> private static bool Write(List <List <MultiProp> > content, string fileName, string tag, out List <string> errors) { errors = new List <string>(); XmlWriter writer; try { using (writer = XmlWriter.Create(fileName, TransformerCommon.GetXmlWriterSettings())) { writer.WriteStartElement(TransformerCommon.ROOT_ELEMENT); writer.WriteStartElement(TAGS.Enclosure(tag)); // e.g. <HICP> foreach (List <MultiProp> item in content) { writer.WriteStartElement(tag); foreach (var prop in item) { TransformerCommon.TranslateAndWriteElement(writer, prop.tag, prop.content, tag); } writer.WriteEndElement(); } writer.WriteEndElement(); // e.g. </HICPs> writer.WriteEndElement(); // ROOT_ELEMENT } return(true); } catch (Exception exception) { errors.Add($"{fileName}: {exception.Message}"); return(false); } }
/// <summary> /// reads a country's EM2 country- and dataconfig-XML-files and transfers them to EM3 style /// creates the country folder, if it does not exist, and overwrites any existing country file /// note: the intended usage is "single country transformation" /// the EM3All class is responsible for complete EM-content transformation (using the EM3Country.Write function) /// </summary> /// <param name="emPath"> EuromodFiles folder (containing EM2-files in XMLParam and (will contain) EM3-files in EM3Translation\XMLParam) </param> /// <param name="country"> short-name of country </param> /// <param name="errors"> critical and non-critical erros during the transformation-process, empty structure for no errors </param> public static bool Transform(string emPath, string country, out List <string> errors) { errors = new List <string>(); EMPath pathHandler = new EMPath(emPath); string em2CountryFile = string.Empty, em2DataFile = string.Empty; try { DirectoryInfo di = Directory.CreateDirectory(pathHandler.GetCountryFolderPath(country)); // read EM2-files em2CountryFile = pathHandler.GetCountryFilePath(country: country, em2: true); em2DataFile = pathHandler.GetEM2DataConfigFilePath(country); bool up2D1 = TransformerCommon.IsFileUpToDate(em2CountryFile, pathHandler.GetCountryFolderPath(country), out string hash1); bool up2D2 = TransformerCommon.IsFileUpToDate(em2DataFile, pathHandler.GetCountryFolderPath(country), out string hash2); if (up2D1 && up2D2) { return(true); // do not combine in one if, to make sure that both hash-files (for country and dataconfig) are generated } EM2Country.Content ctryContent = EM2Country.Read(em2CountryFile, out List <string> cErrors); EM2Data.Content dataContent = EM2Data.Read(em2DataFile, out List <string> dErrors); // need the global file with policy-switches for proper transformation of local policy switches List <List <MultiProp> > extensions = EM2Global.ReadSwitchPol(pathHandler.GetFolderConfig(em2: true), out List <string> gErrors); errors.AddRange(cErrors); errors.AddRange(dErrors); errors.AddRange(gErrors); if (ctryContent == null || dataContent == null || extensions == null) { return(false); } // write EM3-file (includes EM2->EM3 adaptations, via EM23Adapt class) string em3CountryFile = pathHandler.GetCountryFilePath(country); bool success = Write(ctryContent, dataContent, extensions, em3CountryFile, out List <string> wErrors); errors.AddRange(wErrors); if (success && errors.Count == 0) { TransformerCommon.WriteUpToDate(em2CountryFile, pathHandler.GetCountryFolderPath(country), hash1); TransformerCommon.WriteUpToDate(em2DataFile, pathHandler.GetCountryFolderPath(country), hash2); } return(success); } catch (Exception exception) { errors.Add($"{country}: {exception.Message}"); return(false); } }
/// <summary> /// transfers the EM2 variables file into EM3 style and creates the respective EM3 file /// note: this class is only responsible for writing, EM2->EM3 adaptations are accomplished by a call to the EM23Adapt class /// also note: the function is not intended to be used "stand-alone", but by EM3Variables.Transform and EM3All.Write /// </summary> /// <param name="content"> content of variables-file as read by EM2Variables.Read </param> /// <param name="emPath"> EuromodFiles folder (containing EM2-files in XMLParam and (will contain) EM3-files in EM3Translation\XMLParam) </param> /// <param name="errors"> critical and non-critical erros during the write-process, empty structure for no errors </param> public static bool Write(EM2Variables.Content content, string emPath, out List <string> errors) { errors = new List <string>(); XmlWriter writer; try { (new EM23Adapt()).AdaptVar(content); // adapt from EM2 style to EM3 style using (writer = XmlWriter.Create(new EMPath(emPath).GetVarFilePath(), TransformerCommon.GetXmlWriterSettings())) { writer.WriteStartElement(TransformerCommon.ROOT_ELEMENT); WriteList(TAGS.VAR, content.variables); WriteList(TAGS.ACTYPE, content.acroTypes); WriteList(TAGS.ACLEVEL, content.acroLevels); WriteList(TAGS.ACRO, content.acros); WriteList(TAGS.CAT, content.acroCategories); writer.WriteEndElement(); return(true); } } catch (Exception exception) { errors.Add($"Variables: {exception.Message}"); return(false); } void WriteList(string tag, List <Dictionary <string, string> > items) { writer.WriteStartElement(TAGS.Enclosure(tag)); foreach (var item in items) { writer.WriteStartElement(tag); foreach (var p in item) { TransformerCommon.TranslateAndWriteElement(writer, p.Key, p.Value, tag); } writer.WriteEndElement(); } writer.WriteEndElement(); } }
/// <summary> /// reads an AddOn's EM2 country-XML-files and transfers it to EM3 style /// creates the AddOn folder, if it does not exist, and overwrites any existing country AddOn /// note: the intended usage is "single AddOn transformation" /// the EM3All class is responsible for complete EM-content transformation (using the EM3Country.Write function) /// </summary> /// <param name="emPath"> EuromodFiles folder (containing EM2-files in XMLParam and (will contain) EM3-files in EM3Translation\XMLParam) </param> /// <param name="addOn"> short-name of AddOn </param> /// <param name="errors"> critical and non-critical erros during the transformation-process, empty structure for no errors </param> public static bool TransformAddOn(string emPath, string addOn, out List <string> errors) { errors = new List <string>(); EMPath pathHandler = new EMPath(emPath); try { DirectoryInfo di = Directory.CreateDirectory(pathHandler.GetAddOnFolderPath(addOn)); // read EM2-files string em2AddOnFile = pathHandler.GetAddOnFilePath(addOn: addOn, em2: true); if (TransformerCommon.IsFileUpToDate(em2AddOnFile, pathHandler.GetAddOnFolderPath(addOn), out string hashCode)) { return(true); } EM2Country.Content addOnContent = EM2Country.Read(em2AddOnFile, out errors); if (addOnContent == null) { return(false); } // write EM3-file (includes EM2->EM3 adaptations, via EM23Adapt class) string em3AddOnFile = pathHandler.GetAddOnFilePath(addOn); bool success = Write(addOnContent, null, new List <List <MultiProp> >(), em3AddOnFile, out List <string> wErrors); errors.AddRange(wErrors); if (success && errors.Count == 0) { TransformerCommon.WriteUpToDate(em2AddOnFile, pathHandler.GetAddOnFolderPath(addOn), hashCode); } return(success); } catch (Exception exception) { errors.Add($"{addOn}: {exception.Message}"); return(false); } }
/// <summary> /// transfers a country's EM2 country- and data-config-content into EM3 style and creates the EM3 country-file /// note: this class is only responsible for writing, EM2->EM3 adaptations are accomplished by a call to the EM23Adapt class /// also note: does not create the country folder /// i.e. the function is not intended to be used "stand-alone", but by EM3.Transform/AddOn and EM3All.Write /// </summary> /// <param name="ctryContent"> content of country-XML-file as read by EM2Country.Read </param> /// <param name="dataContent"> content of country-dataconfig-XML-file as read by EM2Data.Read </param> /// <param name="extensionInfo"> content of global extension-XML-file (necessary for EM2->EM3 adaptation) </param> /// <param name="fileName"> full path of EM3 country-XML-file (i.e. the file to write) </param> /// <param name="errors"> critical and non-critical erros during the write-process, empty structure for no errors </param> public static bool Write(EM2Country.Content ctryContent, EM2Data.Content dataContent, List <List <MultiProp> > extensionInfo, string fileName, out List <string> errors) { errors = new List <string>(); XmlWriter writer; // declare here to be able to use it in sub-functions try { // "summarised" EM2->EM3 adaptation process (new EM23Adapt()).AdaptCountry(ctryContent, dataContent, extensionInfo, out errors); using (writer = XmlWriter.Create(fileName, TransformerCommon.GetXmlWriterSettings())) { writer.WriteStartElement(TransformerCommon.ROOT_ELEMENT); // COUNTRY WriteItem(TAGS.COUNTRY, ctryContent.general); // SYSTEMS writer.WriteStartElement(TAGS.Enclosure(TAGS.SYS)); foreach (var sys in ctryContent.systems.Values) { WriteItem(TAGS.SYS, sys); } writer.WriteEndElement(); // POLICIES writer.WriteStartElement(TAGS.Enclosure(TAGS.POL)); foreach (var pol in ctryContent.policies.Values) { WriteItem(TAGS.POL, pol); } writer.WriteEndElement(); // REFERENCE POLICIES writer.WriteStartElement(TAGS.Enclosure(TAGS.REFPOL)); foreach (var refPol in ctryContent.referencePolicies) { writer.WriteStartElement(TAGS.REFPOL); TransformerCommon.TranslateAndWriteElement(writer, TAGS.ID, refPol.Key, TAGS.REFPOL); TransformerCommon.TranslateAndWriteElement(writer, TAGS.REFPOL_ID, refPol.Value, TAGS.REFPOL); writer.WriteEndElement(); } writer.WriteEndElement(); // FUNCTIONS writer.WriteStartElement(TAGS.Enclosure(TAGS.FUN)); foreach (var fun in ctryContent.functions.Values) { WriteItem(TAGS.FUN, fun); } writer.WriteEndElement(); // PARAMETERS writer.WriteStartElement(TAGS.Enclosure(TAGS.PAR)); foreach (var par in ctryContent.parameters.Values) { WriteItem(TAGS.PAR, par); } writer.WriteEndElement(); // SYS-POL-ITEMS writer.WriteStartElement(TAGS.Enclosure(TAGS.SYS_POL)); foreach (var syspol in ctryContent.sysPol) { WriteSysItem(TAGS.SYS_POL, TAGS.POL_ID, TAGS.SWITCH, syspol); } writer.WriteEndElement(); // SYS-FUNC-ITEMS writer.WriteStartElement(TAGS.Enclosure(TAGS.SYS_FUN)); foreach (var sysfun in ctryContent.sysFun) { WriteSysItem(TAGS.SYS_FUN, TAGS.FUN_ID, TAGS.SWITCH, sysfun); } writer.WriteEndElement(); // SYS-PAR-ITEMS writer.WriteStartElement(TAGS.Enclosure(TAGS.SYS_PAR)); foreach (var syspar in ctryContent.sysPar) { WriteSysItem(TAGS.SYS_PAR, TAGS.PAR_ID, TAGS.VALUE, syspar); } writer.WriteEndElement(); // BREAK HERE FOR ADD-ONS !!! the rest only concerns countries if (dataContent == null) { return(true); } // ------------------------------------------------------------------- // UPRATING INDICES - PROPERTIES (name, description, ...) writer.WriteStartElement(TAGS.Enclosure(TAGS.UPIND)); foreach (var upInd in ctryContent.upInd.Values) { WriteItem(TAGS.UPIND, upInd); } writer.WriteEndElement(); // UPRATING INDICES - VALUES PER YEAR writer.WriteStartElement(TAGS.Enclosure(TAGS.UPIND_YEAR)); foreach (var upIndVal in ctryContent.upIndVal) { writer.WriteStartElement(TAGS.UPIND_YEAR); WriteProperties(upIndVal, TAGS.UPIND_YEAR); writer.WriteEndElement(); } writer.WriteEndElement(); // DATASETS writer.WriteStartElement(TAGS.Enclosure(TAGS.DATA)); foreach (var data in dataContent.dataSets.Values) { writer.WriteStartElement(TAGS.DATA); TransformerCommon.TranslateAndWriteElement(writer, TAGS.ID, data.id, TAGS.DATA); TransformerCommon.TranslateAndWriteElement(writer, TAGS.NAME, data.name, TAGS.DATA); WriteProperties(data.properties, TAGS.DATA); writer.WriteEndElement(); } writer.WriteEndElement(); // SYS-DATA-ITEMS writer.WriteStartElement(TAGS.Enclosure(TAGS.SYS_DATA)); foreach (var ds in dataContent.sysData) { writer.WriteStartElement(TAGS.SYS_DATA); TransformerCommon.TranslateAndWriteElement(writer, TAGS.DATA_ID, ds.dataID, TAGS.SYS_DATA); TransformerCommon.TranslateAndWriteElement(writer, TAGS.SYS_ID, ds.sysID, TAGS.SYS_DATA); WriteProperties(ds.properties, TAGS.SYS_DATA); writer.WriteEndElement(); } writer.WriteEndElement(); // EXTENSIONS // extensions themself writer.WriteStartElement(TAGS.Enclosure(TAGS.LOCAL_EXTENSION)); foreach (var ext in dataContent.localExtensions) { WriteItem(TAGS.LOCAL_EXTENSION, ext); } writer.WriteEndElement(); // extensions' policies writer.WriteStartElement(TAGS.Enclosure(TAGS.EXTENSION_POL)); foreach (var ep in ctryContent.extensionPol) { writer.WriteStartElement(TAGS.EXTENSION_POL); TransformerCommon.TranslateAndWriteElement(writer, TAGS.EXTENSION_ID, ep.Item1, TAGS.EXTENSION_POL); TransformerCommon.TranslateAndWriteElement(writer, TAGS.POL_ID, ep.Item2, TAGS.EXTENSION_POL); TransformerCommon.TranslateAndWriteElement(writer, TAGS.EXENTSION_BASEOFF, ep.Item3, TAGS.EXTENSION_POL); writer.WriteEndElement(); } writer.WriteEndElement(); // extensions' functions writer.WriteStartElement(TAGS.Enclosure(TAGS.EXTENSION_FUN)); foreach (var fp in ctryContent.extensionFun) { writer.WriteStartElement(TAGS.EXTENSION_FUN); TransformerCommon.TranslateAndWriteElement(writer, TAGS.EXTENSION_ID, fp.Item1, TAGS.EXTENSION_FUN); TransformerCommon.TranslateAndWriteElement(writer, TAGS.FUN_ID, fp.Item2, TAGS.EXTENSION_FUN); TransformerCommon.TranslateAndWriteElement(writer, TAGS.EXENTSION_BASEOFF, fp.Item3, TAGS.EXTENSION_FUN); writer.WriteEndElement(); } writer.WriteEndElement(); // extensions' parameters writer.WriteStartElement(TAGS.Enclosure(TAGS.EXTENSION_PAR)); foreach (var ep in ctryContent.extensionPar) { writer.WriteStartElement(TAGS.EXTENSION_PAR); TransformerCommon.TranslateAndWriteElement(writer, TAGS.EXTENSION_ID, ep.Item1, TAGS.EXTENSION_PAR); TransformerCommon.TranslateAndWriteElement(writer, TAGS.PAR_ID, ep.Item2, TAGS.EXTENSION_PAR); TransformerCommon.TranslateAndWriteElement(writer, TAGS.EXENTSION_BASEOFF, ep.Item3, TAGS.EXTENSION_PAR); writer.WriteEndElement(); } writer.WriteEndElement(); // extensions' switches writer.WriteStartElement(TAGS.Enclosure(TAGS.EXTENSION_SWITCH)); foreach (var sw in dataContent.policySwitches) { writer.WriteStartElement(TAGS.EXTENSION_SWITCH); TransformerCommon.TranslateAndWriteElement(writer, TAGS.EXTENSION_ID, sw.switchPolID, TAGS.EXTENSION_SWITCH); TransformerCommon.TranslateAndWriteElement(writer, TAGS.SYS_ID, sw.sysID, TAGS.EXTENSION_SWITCH); TransformerCommon.TranslateAndWriteElement(writer, TAGS.DATA_ID, sw.dataID, TAGS.EXTENSION_SWITCH); TransformerCommon.TranslateAndWriteElement(writer, TAGS.VALUE, sw.value, TAGS.EXTENSION_SWITCH); writer.WriteEndElement(); } writer.WriteEndElement(); // LOOKGROUPS // groups themself writer.WriteStartElement(TAGS.Enclosure(TAGS.LOOKGROUP)); foreach (var lg in ctryContent.lookGroup.Values) { WriteItem(TAGS.LOOKGROUP, lg); } writer.WriteEndElement(); // groups' policies writer.WriteStartElement(TAGS.Enclosure(TAGS.LOOKGROUP_POL)); foreach (var lgp in ctryContent.lookGroupPol) { writer.WriteStartElement(TAGS.LOOKGROUP_POL); TransformerCommon.TranslateAndWriteElement(writer, TAGS.LOOKGROUP_ID, lgp.Item1, TAGS.LOOKGROUP_POL); TransformerCommon.TranslateAndWriteElement(writer, TAGS.POL_ID, lgp.Item2, TAGS.LOOKGROUP_POL); writer.WriteEndElement(); } writer.WriteEndElement(); // groups' functions writer.WriteStartElement(TAGS.Enclosure(TAGS.LOOKGROUP_FUN)); foreach (var lgf in ctryContent.lookGroupFun) { writer.WriteStartElement(TAGS.LOOKGROUP_FUN); TransformerCommon.TranslateAndWriteElement(writer, TAGS.LOOKGROUP_ID, lgf.Item1, TAGS.LOOKGROUP_FUN); TransformerCommon.TranslateAndWriteElement(writer, TAGS.FUN_ID, lgf.Item2, TAGS.LOOKGROUP_FUN); writer.WriteEndElement(); } writer.WriteEndElement(); // groups' parameters writer.WriteStartElement(TAGS.Enclosure(TAGS.LOOKGROUP_PAR)); foreach (var lgp in ctryContent.lookGroupPar) { writer.WriteStartElement(TAGS.LOOKGROUP_PAR); TransformerCommon.TranslateAndWriteElement(writer, TAGS.LOOKGROUP_ID, lgp.Item1, TAGS.LOOKGROUP_PAR); TransformerCommon.TranslateAndWriteElement(writer, TAGS.PAR_ID, lgp.Item2, TAGS.LOOKGROUP_PAR); writer.WriteEndElement(); } writer.WriteEndElement(); // INDIRECT TAX - PROPERTIES (name, comment, ...) writer.WriteStartElement(TAGS.Enclosure(TAGS.INDTAX)); foreach (var indTax in ctryContent.indTax.Values) { WriteItem(TAGS.INDTAX, indTax); } writer.WriteEndElement(); // INDIRECT TAX - VALUES PER YEAR writer.WriteStartElement(TAGS.Enclosure(TAGS.INDTAX_YEAR)); foreach (var indTaxVal in ctryContent.indTaxVal) { writer.WriteStartElement(TAGS.INDTAX_YEAR); WriteProperties(indTaxVal, TAGS.INDTAX_YEAR); writer.WriteEndElement(); } writer.WriteEndElement(); writer.WriteEndElement(); // ROOT_ELEMENT return(true); } } catch (Exception exception) { errors.Add($"{ctryContent.general.name}: {exception.Message}"); return(false); } void WriteItem(string tag, EM2Item item) { writer.WriteStartElement(tag); if (item.id != null) { TransformerCommon.TranslateAndWriteElement(writer, TAGS.ID, item.id, tag); } if (item.name != null) { TransformerCommon.TranslateAndWriteElement(writer, TAGS.NAME, item.name, tag); } WriteProperties(item.properties, tag); writer.WriteEndElement(); } void WriteProperties(Dictionary <string, string> properties, string tag) { foreach (var p in properties) { if (!string.IsNullOrEmpty(p.Value)) { TransformerCommon.TranslateAndWriteElement(writer, p.Key, p.Value, tag); } } } void WriteSysItem(string mainTag, string itemTag, string valTag, EM2Country.SysItem sysItem) { writer.WriteStartElement(mainTag); TransformerCommon.TranslateAndWriteElement(writer, TAGS.SYS_ID, sysItem.sysID, mainTag); TransformerCommon.TranslateAndWriteElement(writer, itemTag, sysItem.itemID, mainTag); TransformerCommon.TranslateAndWriteElement(writer, TAGS.ORDER, sysItem.order, mainTag); TransformerCommon.TranslateAndWriteElement(writer, valTag, sysItem.value, mainTag); writer.WriteEndElement(); } }
/// <summary> note: this is a private function, exclusively called by EM3All.Transform, just for reasons of clearer arrangement </summary> private static bool Write(EM2All.Content content, string emPath, out List <string> errors, Action <string> report = null, CancellationTokenSource cancelSrc = null) { List <string> _errors = new List <string>(); object errWriteLock = new object(); ParallelOptions parallelOptions = new ParallelOptions(); if (cancelSrc != null) { parallelOptions.CancellationToken = cancelSrc.Token; } try { EMPath pathHandler = new EMPath(emPath); // WRITE COUNTRIES IN PARALLEL Parallel.ForEach(content.countries, parallelOptions, country => { parallelOptions.CancellationToken.ThrowIfCancellationRequested(); string countryName = country.country.general.properties[EM2TAGS.SHORTNAME]; DirectoryInfo di = Directory.CreateDirectory(pathHandler.GetCountryFolderPath(countryName)); bool success = EM3Country.Write(country.country, country.data, content.switchPol, pathHandler.GetCountryFilePath(countryName), out List <string> cErrors); if (cErrors.Count > 0) { lock (errWriteLock) { _errors.AddRange(cErrors); } } ReportSuccess(countryName, success, cErrors.Count); if (success && cErrors.Count == 0) // produce up2Date-files { TransformerCommon.WriteUpToDate(pathHandler.GetCountryFilePath(countryName, true), pathHandler.GetCountryFolderPath(countryName)); TransformerCommon.WriteUpToDate(pathHandler.GetEM2DataConfigFilePath(countryName), pathHandler.GetCountryFolderPath(countryName)); } }); // the rest is written sequentially (parallel would be unnecessary overhead) // WRITE ADD-ONS foreach (var addOn in content.addOns) { string addOnName = addOn.general.properties[EM2TAGS.SHORTNAME]; DirectoryInfo di = Directory.CreateDirectory(pathHandler.GetAddOnFolderPath(addOnName)); bool success = EM3Country.Write(addOn, null, content.switchPol, pathHandler.GetAddOnFilePath(addOnName), out List <string> aoErrors); if (aoErrors.Count > 0) { _errors.AddRange(aoErrors); } ReportSuccess(addOnName, success, aoErrors.Count); // produce up2Date-file if (success && aoErrors.Count == 0) { TransformerCommon.WriteUpToDate(pathHandler.GetAddOnFilePath(addOnName, true), pathHandler.GetAddOnFolderPath(addOnName)); } } // WRITE GLOBAL FILES if (!Directory.Exists(pathHandler.GetFolderConfig())) { Directory.CreateDirectory(pathHandler.GetFolderConfig()); } bool erSuccess = EM3Global.WriteExRates(content.exRates, emPath, out List <string> erErrors); ReportSuccess("Exchangerates", erSuccess, erErrors.Count); _errors.AddRange(erErrors); bool hicSuccess = EM3Global.WriteHICP(content.hicp, emPath, out List <string> hicErrors); ReportSuccess("HICP", hicSuccess, hicErrors.Count); _errors.AddRange(hicErrors); bool gsSuccess = EM3Global.WriteExtensions(content.switchPol, emPath, out List <string> gsErrors); ReportSuccess("Extensions", gsSuccess, gsErrors.Count); _errors.AddRange(gsErrors); // WRITE VARIABLES bool varSuccess = EM3Variables.Write(content.varConfig, emPath, out List <string> vErrors); ReportSuccess("Variables", varSuccess, vErrors.Count); _errors.AddRange(vErrors); if (varSuccess && vErrors.Count == 0) { TransformerCommon.WriteUpToDate(pathHandler.GetVarFilePath(true), pathHandler.GetFolderConfig()); // produce up2Date-file } return(true); } catch (OperationCanceledException) { report($"Writing {emPath} cancelled!"); return(true); } catch (Exception exception) { lock (errWriteLock) { _errors.Add(exception.Message); } return(false); } finally { errors = _errors; } void ReportSuccess(string what, bool success, int cntErrors) { if (success) { report($"Finished writing {what} with " + $"{(cntErrors == 0 ? "success" : $"{cntErrors} errors") }"); }