private static string GetSysInfo(string sysIdentifier, Dictionary <string, Dictionary <string, string> > syss, ExeXml.Country country, out string warning) { warning = null; string sysId = GetIdByIdOrName(sysIdentifier, syss, true); // search system by id or name (throws exeception if not found) Dictionary <string, string> sys = syss[sysId]; country.sys.id = sysId; country.sys.name = sys.GetOrEmpty(TAGS.NAME); country.sys.headDefInc = sys.GetOrEmpty(TAGS.HEAD_DEF_INC); country.sys.year = sys.GetOrEmpty(TAGS.YEAR); // is important for uprating factors, therefore warn if (country.sys.year == string.Empty) { warning = $"system year (<{TAGS.YEAR}>) not found"; } if (sys.TryGetValue(TAGS.CURRENCY_OUTPUT, out string curOut)) { country.sys.isOutputEuro = DefPar.Value.IsEuro(curOut); } if (sys.TryGetValue(TAGS.CURRENCY_PARAM, out string curPar)) { country.sys.areParamEuro = DefPar.Value.IsEuro(curPar); } return(sysId); }
private static void GetUpIndInfo(Dictionary <string, Dictionary <string, string> > upInds, Dictionary <string, Dictionary <string, string> > upIndYears, ExeXml.Country country) { foreach (Dictionary <string, string> ui in upIndYears.Values) // loop over <UPIND_YEARs> { if (ui.ContainsKey(TAGS.YEAR)) { string upIndId = ui.GetOrEmpty(TAGS.UPIND_ID); string sVal = ui.GetOrEmpty(TAGS.VALUE); if (upIndId == string.Empty || sVal == string.Empty || !double.TryParse(EM_Helpers.AdaptDecimalSign(sVal), out double val)) { continue; } string facName = null; // get the name of the factor from <UPINDs> if (upInds.ContainsKey(upIndId) && upInds[upIndId].ContainsKey(TAGS.NAME)) { facName = upInds[upIndId][TAGS.NAME]; } // Store all uprate indices if (!country.upFacs.ContainsKey(facName)) // If uprating factor name does not exist, create a new entry { country.upFacs.Add(facName, new ExeXml.UpIndDict()); } country.upFacs[facName].SetYear(ui[TAGS.YEAR], val); } } }
private static string GetDataInfo(string dataIdentifier, Dictionary <string, Dictionary <string, string> > datas, ExeXml.Country country, out string warning) { warning = null; string dataId = GetIdByIdOrName(dataIdentifier, datas, false); if (dataId == null) // note: this only happens if a search by name fails (failed search by id throws exception) { // and allows a command-line call with a "not-registered" dataset country.data.Name = dataIdentifier; warning = $"no description (year, currency, ...) for dataset {dataId} found"; return(string.Empty); } Dictionary <string, string> data = datas[dataId]; country.data.Name = data.GetOrEmpty(TAGS.NAME); country.data.year = data.GetOrEmpty(TAGS.YEAR_INC); // do not warn if empty, because e.g. training-data has no income-year if (data.TryGetValue(TAGS.CURRENCY_DATA, out string curOut)) { country.data.isEuro = DefPar.Value.IsEuro(curOut); } if (data.TryGetValue(TAGS.USE_COMMON_DEFAULT, out string ucd)) { country.data.useCommonDefault = DefPar.Value.IsYes(ucd); } if (data.TryGetValue(TAGS.READ_X_VARIABLES, out string xvar)) { country.data.readXVar = DefPar.Value.IsYes(xvar); } if (data.TryGetValue(TAGS.FILEPATH_DATA, out string specialPath)) { country.data.specialPath = specialPath; } if (data.TryGetValue(TAGS.LIST_STRING_OUTVAR, out string listStringOutVar)) { country.data.listStringOutVar = listStringOutVar; } if (data.TryGetValue(TAGS.INDIRECT_TAX_TABLE_YEAR, out string indirectTaxTableYear)) { country.data.indirectTaxTableYear = indirectTaxTableYear; } return(dataId); }
private static bool GetIndTaxInfo(Dictionary <string, Dictionary <string, string> > indTaxes, Dictionary <string, Dictionary <string, string> > indTaxYears, ExeXml.Country country) { if (string.IsNullOrEmpty(country.data.indirectTaxTableYear)) { return(true); } string relevantYear = country.data.indirectTaxTableYear.Trim().ToLower(); foreach (Dictionary <string, string> it in indTaxYears.Values) // loop over <INDTAX_YEARs> { if (it.GetOrEmpty(TAGS.YEAR) != relevantYear) { continue; } string indTaxId = it.GetOrEmpty(TAGS.INDTAX_ID); string sVal = it.GetOrEmpty(TAGS.VALUE).Trim(); if (indTaxId == string.Empty || sVal == string.Empty || sVal == DefPar.Value.NA) { continue; } double pct = sVal.EndsWith("%") ? 0.01 : 1; if (!double.TryParse(EM_Helpers.AdaptDecimalSign(sVal.Replace("%", "")), out double val)) { continue; } string indTaxName = null; // get the name of the factor from <INDTAXs> if (indTaxes.ContainsKey(indTaxId) && indTaxes[indTaxId].ContainsKey(TAGS.NAME)) { indTaxName = indTaxes[indTaxId][TAGS.NAME]; } country.indTaxes.AddOrReplace(indTaxName, val * pct); } return(country.indTaxes.Count > 0); }
private static void GetExtensionInfo(string sysId, string dataId, Dictionary <string, Dictionary <string, string> > extSwitch, Dictionary <string, Dictionary <string, string> > localExt, Dictionary <string, Dictionary <string, string> > extPol, Dictionary <string, Dictionary <string, string> > extFun, Dictionary <string, Dictionary <string, string> > extPar, ExeXml.Country country) { foreach (Dictionary <string, string> ep in extPol.Values) { string extId = ep.GetOrEmpty(TAGS.EXTENSION_ID); if (!country.extensions.ContainsKey(extId)) { country.extensions.Add(extId, new ExeXml.Extension()); } string polId = ep.GetOrEmpty(TAGS.POL_ID); string baseOff = ep.GetOrEmpty(TAGS.EXENTSION_BASEOFF); country.extensions[extId].polIds.Add(polId, baseOff == "true"); } foreach (Dictionary <string, string> ef in extFun.Values) { string extId = ef.GetOrEmpty(TAGS.EXTENSION_ID); if (!country.extensions.ContainsKey(extId)) { country.extensions.Add(extId, new ExeXml.Extension()); } string funId = ef.GetOrEmpty(TAGS.FUN_ID); string baseOff = ef.GetOrEmpty(TAGS.EXENTSION_BASEOFF); country.extensions[extId].funIds.Add(funId, baseOff == "true"); } foreach (Dictionary <string, string> ep in extPar.Values) { string extId = ep.GetOrEmpty(TAGS.EXTENSION_ID); if (!country.extensions.ContainsKey(extId)) { country.extensions.Add(extId, new ExeXml.Extension()); } string parId = ep.GetOrEmpty(TAGS.PAR_ID); string baseOff = ep.GetOrEmpty(TAGS.EXENTSION_BASEOFF); country.extensions[extId].parIds.Add(parId, baseOff == "true"); } foreach (Dictionary <string, string> es in extSwitch.Values) // loop over <EXTENSION_SWITCHs> { string extId = es.GetOrEmpty(TAGS.EXTENSION_ID); if (!country.extensions.ContainsKey(extId) || es.GetOrEmpty(TAGS.SYS_ID) != sysId || es.GetOrEmpty(TAGS.DATA_ID) != dataId) { continue; } country.extensions[extId].on = DefPar.Value.IsOn(es.GetOrEmpty(TAGS.VALUE)); if (localExt.ContainsKey(extId)) // the names are only set for local extensions (as they are defined in the country file) { // they stay empty for global extension (this is in fact only relevant for function AddOn_ExtensionSwitch) localExt[extId].TryGetValue(TAGS.NAME, out country.extensions[extId].localLongName); localExt[extId].TryGetValue(TAGS.SHORT_NAME, out country.extensions[extId].localShortName); } } }
/// <summary> /// reads the relevant content of a country file into an ExeXml.Country structure (see parameters and ExeXml.Country wrt 'relevant') /// IMPORTANT NOTES: /// - error-reporting: /// - everything that does not at least allow analysing the info throws an exception (e.g. file not found, system not found, ...) /// - other errors are reported via the communicator - if they still allow running the programme via isWarning=true /// - "relaxed" error handling: unlikely errors (which are actually only possible by manual manipulation of the xml-file) /// are ignored without comment, if they do not prohibit the run (if things still work - so what?) /// - polices and functions switched to n/a are not read /// </summary> /// <param name="path"> full path to the country-xml-file </param> /// <param name="sysIdentifier"> id or name of system, only info belonging to this system is read, e.g. only relevant uprating indices </param> /// <param name="dataIdentifier"> id or name, only info belonging to this dataset is read, e.g. only relevant uprating indices </param> /// <param name="ignorePrivate"> if true, private elements are ignored by the reader </param> /// <param name="readComment"> if false (default), comments are not read (as the executable does not need them) </param> public static ExeXml.Country ReadCountry(string path, string sysIdentifier, string dataIdentifier, bool ignorePrivate, Communicator communicator, bool readComment = false) { try { ExeXml.Country country = new ExeXml.Country(); // first read the xlm-file into simple property/value dictionaries ... Dictionary <string, Dictionary <string, string> > ctry, syss, pols, refPols, funs, pars, sysPols, sysFuns, sysPars, upInds, upIndYears, datas, sysDatas, extSwitch, localExt, extPol, extFun, extPar, indTaxes, indTaxYears; using (StreamReader sr = new StreamReader(path, Encoding.UTF8)) using (XmlReader reader = XmlReader.Create(sr)) { ctry = XmlHelpers.GetXmlGroupItems(reader: reader, tag: TAGS.COUNTRY, hasId: false, singleItem: true); syss = XmlHelpers.GetXmlGroupItems(reader: reader, tag: TAGS.SYS); pols = XmlHelpers.GetXmlGroupItems(reader: reader, tag: TAGS.POL); refPols = XmlHelpers.GetXmlGroupItems(reader: reader, tag: TAGS.REFPOL); funs = XmlHelpers.GetXmlGroupItems(reader: reader, tag: TAGS.FUN); pars = XmlHelpers.GetXmlGroupItems(reader: reader, tag: TAGS.PAR, hasId: false); sysPols = XmlHelpers.GetXmlGroupItems(reader: reader, tag: TAGS.SYS_POL, hasId: false); sysFuns = XmlHelpers.GetXmlGroupItems(reader: reader, tag: TAGS.SYS_FUN, hasId: false); sysPars = XmlHelpers.GetXmlGroupItems(reader: reader, tag: TAGS.SYS_PAR, hasId: false); upInds = XmlHelpers.GetXmlGroupItems(reader: reader, tag: TAGS.UPIND); upIndYears = XmlHelpers.GetXmlGroupItems(reader: reader, tag: TAGS.UPIND_YEAR, hasId: false); datas = XmlHelpers.GetXmlGroupItems(reader: reader, tag: TAGS.DATA); sysDatas = XmlHelpers.GetXmlGroupItems(reader: reader, tag: TAGS.SYS_DATA, hasId: false); localExt = XmlHelpers.GetXmlGroupItems(reader: reader, tag: TAGS.LOCAL_EXTENSION); extPol = XmlHelpers.GetXmlGroupItems(reader: reader, tag: TAGS.EXTENSION_POL, hasId: false); extFun = XmlHelpers.GetXmlGroupItems(reader: reader, tag: TAGS.EXTENSION_FUN, hasId: false); extPar = XmlHelpers.GetXmlGroupItems(reader: reader, tag: TAGS.EXTENSION_PAR, hasId: false); extSwitch = XmlHelpers.GetXmlGroupItems(reader: reader, tag: TAGS.EXTENSION_SWITCH, hasId: false); indTaxes = XmlHelpers.GetXmlGroupItems(reader: reader, tag: TAGS.INDTAX); indTaxYears = XmlHelpers.GetXmlGroupItems(reader: reader, tag: TAGS.INDTAX_YEAR, hasId: false); } // ... then analyse the info: GetCountryInfo(country.cao, ctry); // note that sys-id can be actually the system's id (guid) or the system's name ... string sysId = GetSysInfo(sysIdentifier, syss, country, out string sysWarning); if (sysWarning != null) { ReportError(communicator, path, sysWarning, false); } // if no data was defined, try to get the best match if (string.IsNullOrEmpty(dataIdentifier)) { foreach (Dictionary <string, string> sysdata in sysDatas.Values) { if (sysdata[TAGS.SYS_ID] == sysId && sysdata[TAGS.BEST_MATCH].Equals("yes", StringComparison.InvariantCultureIgnoreCase)) { dataIdentifier = sysdata[TAGS.DATA_ID]; break; } } // if still no data, then issue error if (string.IsNullOrEmpty(dataIdentifier)) { ReportError(communicator, path, "No dataset provided and no best match was found for this system.", true); } } // ... note that dataIdentifier can be actually the data's id (guid) or the data's name ... string dataId = GetDataInfo(dataIdentifier, datas, country, out string dataWarning); if (dataWarning != null) { ReportError(communicator, path, dataWarning, false); } GetPolInfo(sysId, pols, sysPols, refPols, ignorePrivate, country.cao, out List <string> polErrors, readComment); foreach (string polError in polErrors) { ReportError(communicator, path, polError); } GetFunInfo(sysId, funs, sysFuns, refPols, ignorePrivate, country.cao, out List <string> funErrors, readComment); foreach (string funError in funErrors) { ReportError(communicator, path, funError); } GetParInfo(sysId, pars, sysPars, ignorePrivate, country.cao, out List <string> parErrors, readComment); foreach (string parError in parErrors) { ReportError(communicator, path, parError); } GetUpIndInfo(upInds, upIndYears, country); GetExtensionInfo(sysId, dataId, extSwitch, localExt, extPol, extFun, extPar, country); if (!GetIndTaxInfo(indTaxes, indTaxYears, country)) { ReportError(communicator, path, $"No values for year {country.data.indirectTaxTableYear} found in Indirect Taxes Table"); } return(country); } catch (Exception exception) { throw new Exception($"Failure reading file {path}{Environment.NewLine}{exception.Message}"); } }