/// <summary> reads the relevant content of a add-on file into an ExeXml.AddOn structure (see ReadCountry for IMPORTANT NOTES) </summary> /// <param name="path"> full path to the add-on-xml-file </param> /// <param name="addOnSysIdentifier"> id or name of add-on-system, only info belonging to this system is read </param> public static ExeXml.AddOn ReadAddOn(string path, string addOnSysIdentifier, Communicator communicator) { try { ExeXml.AddOn addOn = new ExeXml.AddOn(); // first read the xlm-file into simple property/value dictionaries ... Dictionary <string, Dictionary <string, string> > ctry, syss, pols, refPols, funs, pars, sysPols, sysFuns, sysPars; 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); } // ... then analyse the info: GetCountryInfo(addOn.cao, ctry); string addOnSysId = GetIdByIdOrName(addOnSysIdentifier, syss, true); // search system by id or name (throws exeception if not found) GetPolInfo(addOnSysId, pols, sysPols, refPols, false, addOn.cao, out List <string> polErrors); foreach (string polError in polErrors) { ReportError(communicator, path, polError); } GetFunInfo(addOnSysId, funs, sysFuns, refPols, false, addOn.cao, out List <string> funErrors); foreach (string funError in funErrors) { ReportError(communicator, path, funError); } GetParInfo(addOnSysId, pars, sysPars, false, addOn.cao, out List <string> parErrors); foreach (string parError in parErrors) { ReportError(communicator, path, parError); } // filter the add-on info out (for convenience, could actually also be done in the executable's add-on-handler) foreach (var pol in addOn.cao.pols) { if (!pol.Value.name.ToLower().StartsWith(ExeXml.AddOn.POL_AO_CONTROL.ToLower())) { continue; } addOn.polAOControl = pol.Value; foreach (var fun in pol.Value.funs) { if (fun.Value.Name.ToLower() != DefFun.AddOn_Applic.ToLower()) { continue; } foreach (var par in fun.Value.pars) { if (par.Value.Name.ToLower() == ExeXml.AddOn.PAR_APPLIC_SYS && par.Value.val != DefPar.Value.NA) { addOn.applicSys.Add(par.Value.val); } } pol.Value.funs.Remove(fun.Key); break; } addOn.cao.pols.Remove(pol.Key); break; } if (addOn.polAOControl == null) { throw new Exception($"Policy {ExeXml.AddOn.POL_AO_CONTROL}* not found"); } return(addOn); } catch (Exception exception) { throw new Exception($"Failure reading file {path}{Environment.NewLine}{exception.Message}"); } }
private static void GetParInfo(string sysId, Dictionary <string, Dictionary <string, string> > pars, Dictionary <string, Dictionary <string, string> > sysPars, bool ignorePrivate, ExeXml.CAO cao, out List <string> errors, bool readComment = false) { errors = new List <string>(); foreach (Dictionary <string, string> sp in sysPars.Values) // loop over <SYS_PARs> { if (sp.ContainsKey(TAGS.SYS_ID) && sp[TAGS.SYS_ID] == sysId) // consider only <SYS_PAR> with the appropriate <SYS_ID> { ExeXml.Par par = new ExeXml.Par(); string parId = sp.GetOrEmpty(TAGS.PAR_ID); if (parId == string.Empty) { continue; } if (!pars.ContainsKey(parId)) { errors.Add($"No <{TAGS.PAR}> corresponds to <{TAGS.SYS_PAR}> with <{TAGS.PAR_ID}> {parId}"); continue; } if (ignorePrivate) { string priv = pars[parId].GetOrEmpty(TAGS.PRIVATE); if (priv != null && priv == DefPar.Value.YES) { continue; // ignore if private } } //par.val = EM_Helpers.AdaptDecimalSign(XmlHelpers.RemoveCData(sp.GetOrEmpty(TAGS.VALUE))); par.val = XmlHelpers.RemoveCData(sp.GetOrEmpty(TAGS.VALUE)); if (par.val == DefPar.Value.NA) { continue; // ignore n/a } par.order = sp.GetOrEmpty(TAGS.ORDER); // get <Order> for error messages (otherwise irrelevant for executable) par.Name = pars[parId].GetOrEmpty(TAGS.NAME); // get Name, Group and FunId from <PARs> if (readComment) { par.comment = XmlHelpers.RemoveCData(pars[parId].GetOrEmpty(TAGS.COMMENT)); } string funId = pars[parId].GetOrEmpty(TAGS.FUN_ID); par.Group = pars[parId].GetOrEmpty(TAGS.GROUP); par.val = allowInnerWhitespace.Contains(par.Name.ToLower()) ? par.val.ToLower().Trim() : EM_Helpers.RemoveWhitespace(par.val.ToLower()); // assign the parameter to the corresponding function foreach (var pol in cao.pols) // note that 'TryAdd' is actually necessary for parameters of { if (pol.Value.funs.ContainsKey(funId)) // reference policies, because the policies actually contain the { pol.Value.funs[funId].pars.TryAdd(parId, par); // same functions, not just copies of the same functions } } } } }
public static Dictionary <string, bool> ReadVars(string path, Communicator communicator) { try { Dictionary <string, bool> content = new Dictionary <string, bool>(StringComparer.OrdinalIgnoreCase); using (StreamReader sr = new StreamReader(path, Encoding.UTF8)) using (XmlReader reader = XmlReader.Create(sr)) { foreach (var v in XmlHelpers.GetXmlGroupItems(reader: reader, tag: TAGS.VAR).Values) { if (!content.TryAdd(XmlHelpers.RemoveCData(v.GetOrEmpty(TAGS.NAME)), v.GetOrEmpty(TAGS.MONETARY) != "0")) { communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, message = $"{Path.GetFileName(path)}: double definition of variable {XmlHelpers.RemoveCData(v.GetOrEmpty(TAGS.NAME))} - second definition is ignored" }); } } } return(content); } catch (Exception exception) { throw new Exception($"Failure reading file {path}{Environment.NewLine}{exception.Message}"); } }
/// <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}"); } }
private static void GetPolInfo(string sysId, Dictionary <string, Dictionary <string, string> > pols, Dictionary <string, Dictionary <string, string> > sysPols, Dictionary <string, Dictionary <string, string> > refPols, bool ignorePrivate, ExeXml.CAO cao, out List <string> errors, bool readComment = false) { errors = new List <string>(); foreach (Dictionary <string, string> sp in sysPols.Values) // loop over <SYS_POLs> { if (sp.ContainsKey(TAGS.SYS_ID) && sp[TAGS.SYS_ID] == sysId) // consider only <SYS_POL> with the appropriate <SYS_ID> { ExeXml.Pol pol = new ExeXml.Pol(); string polId = sp.GetOrEmpty(TAGS.POL_ID); bool?on = DefPar.Value.IsOn(sp.GetOrEmpty(TAGS.SWITCH)); if (on == null) { continue; // ignore if switched to n/a } pol.on = on == true; pol.order = GetOrder(sp, out string orderError); if (orderError != null) { errors.Add(orderError); } if (polId == string.Empty) { continue; } string rPolId = polId; // reference policies: the info must come from the referenced pol, but the id from the reference if (refPols.ContainsKey(polId)) { rPolId = refPols[polId].GetOrEmpty(TAGS.REFPOL_ID); } if (pols.ContainsKey(rPolId)) { pol.name = pols[rPolId].GetOrEmpty(TAGS.NAME); // get policy-name from <POLs> if (readComment) { pol.comment = XmlHelpers.RemoveCData(pols[rPolId].GetOrEmpty(TAGS.COMMENT)); } if (ignorePrivate) { string priv = pols[rPolId].GetOrEmpty(TAGS.PRIVATE); if (priv != null && priv == DefPar.Value.YES) { continue; // ignore if private } } } cao.pols.Add(polId, pol); } } }