private void ReadInfo(ExeXml.Fun fun, string funId, out Dictionary <string, Tuple <string, string> > changes, out ExeXml.Par parRunCond, out List <ExeXml.Par> parDatabaseName) { parRunCond = null; parDatabaseName = new List <ExeXml.Par>(); changes = new Dictionary <string, Tuple <string, string> >(); // key: group, value.item1: fun/pol-ident, value.item2: on/off foreach (var par in fun.pars.Values) { if (par.Name.ToLower() == DefPar.Common.Run_Cond.ToLower()) // Run_Cond = { xxx } { parRunCond = par; } else if (par.Name.ToLower() == DefQuery.Par.DataBasename.ToLower()) // #_DatabaseName is the only footnote-parameter possible { parDatabaseName.Add(par); // for global conditions (i.e. the Run_Cond) } else if (par.Name.ToLower() == DefPar.ChangeSwitch.PolFun.ToLower()) // PolFun = Guid / PolFun = policy-name { AddToChangeList(changes, par.Group, par.val, false, funId); } else if (par.Name.ToLower() == DefPar.ChangeSwitch.Switch_NewVal.ToLower()) // SwitchNewVal = on/off { AddToChangeList(changes, par.Group, par.val, true, funId); } else { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $"Change switch ({funId}): unknown parameter {par.Name}" }); } } if (parRunCond == null) { return; } // make sure that footnote-parameters (i.e. #_DatabasName) do not get into conflict with existing footnote-parameters (i.e. same group) List <int> replaceGroups = new List <int>(); foreach (ExeXml.Par parDB in parDatabaseName) { if (!int.TryParse(parDB.Group, out int g)) { continue; // ignore this rather unlikely case (just keep the strange group) } parDB.Group = GetNewGroup(g).ToString(); replaceGroups.Add(g); } replaceGroups.Sort(); replaceGroups.Reverse(); // avoid replacing ...#1...#12... with ...#9901...#99012... foreach (int group in replaceGroups) // and hope there is no #9 { parRunCond.val = parRunCond.val.Replace($"#{group}", $"#{GetNewGroup(group)}"); } int GetNewGroup(int group) { return(group + 9900); } }
private ExeXml.Fun CloneFun(ExeXml.Fun fun) { ExeXml.Fun clone = new ExeXml.Fun { Name = fun.Name, on = fun.on, order = fun.order }; foreach (ExeXml.Par par in fun.pars.Values) { ExeXml.Par clonePar = new ExeXml.Par() { Name = par.Name, Group = par.Group, order = par.order, val = par.val }; clone.pars.Add(Guid.NewGuid().ToString(), clonePar); } return(clone); }
internal Description(Description parDesc, string _queryName) { pol = parDesc.pol; fun = parDesc.fun; funID = parDesc.funID; par = parDesc.par; parID = parDesc.parID; queryName = _queryName; }
internal Description(Description funDesc, ExeXml.Par _par, string _parID = null) { pol = funDesc.pol; fun = funDesc.fun; funID = funDesc.funID; par = _par; parID = _parID; }
private void ApplyInfo(Dictionary <ExeXml.Fun, bool> switchInfo, ExeXml.Par switchFunRunCond, List <ExeXml.Par> switchFunDatabaseName) { foreach (var si in switchInfo) { ExeXml.Fun fun = si.Key; bool on = si.Value; // read-time change - simply change the switch as required if (switchFunRunCond == null) { fun.on = on; continue; } // run-time change: implement switch by editing or adding the function's RunCond var hasRunCond = from p in fun.pars.Values where p.Name.ToLower() == DefPar.Common.Run_Cond.ToLower() select p; // function does not yet have a RunCond: add a copy of the ChangeSwitch-RunCond if (hasRunCond == null || hasRunCond.Count() == 0) { if (fun.Name.ToLower() != DefFun.DefTu.ToLower() && // DefTU and DefIL do not accept a RunCond (does not make sense) fun.Name.ToLower() != DefFun.DefIl.ToLower()) // and it does no harm if these definitions exist { ExeXml.Par newRunCond = new ExeXml.Par() { Name = DefPar.Common.Run_Cond }; // function is currently on, switch off if RunCon is fulfilled // i.e. run as long as ChangeSwitch-RunCond is not fulfilled if (fun.on) { newRunCond.val = $"!({switchFunRunCond.val})"; } // function is currently off, switch on if RunCond is fulfilled // needs to be switched on, otherwise it is dropped by DropOff // but do not run until ChangeSwitch-RunCond is fulfilled else { fun.on = true; newRunCond.val = switchFunRunCond.val; } fun.pars.Add(Guid.NewGuid().ToString(), newRunCond); } } // function has a RunCond: merge with the ChangeSwitch-RunCond else { ExeXml.Par runCond = hasRunCond.First(); // function is currently on, switch off if RunCon is fulfilled // run if current RunCond is fulfilled and as long as ChangeSwitch-RunCond is not fulfilled if (fun.on) { runCond.val = $"!({switchFunRunCond.val}) & ({runCond.val})"; } // function is currently off, switch on if RunCond is fulfilled // needs to be switched on, otherwise it is dropped by DropOff // but do not run until ChangeSwitch-RunCond is fulfilled, but still also fulfill current RunCond else { fun.on = true; runCond.val = $"({switchFunRunCond.val}) & ({runCond.val})"; } } // transfer a possible #_DatabaseName-footnote from the switch-function to the function it is applied on foreach (ExeXml.Par dbName in switchFunDatabaseName) { fun.pars.Add(Guid.NewGuid().ToString(), dbName); } } }
private bool HandleBreak() { // CHECK IF THERE IS ANY BREAK FUNCTION ... string breakFunId = null; ExeXml.Fun breakFun = null; double breakFunOrder = double.MaxValue; Description funDesc = null; foreach (var pol in infoStore.country.cao.pols) { if (!pol.Value.on) { continue; } foreach (var fun in pol.Value.funs) { if (fun.Value.on && fun.Value.Name.ToLower() == DefFun.Break.ToLower()) { double o = GetOrder(pol.Value.order, fun.Value.order); if (o < breakFunOrder) // only consider 1stBreak in spine (if there are foolishly more) { breakFunId = fun.Key; breakFun = fun.Value; breakFunOrder = o; funDesc = new Description(pol.Value, breakFun, breakFunId); } } } } if (breakFun == null) { return(true); } // ... IF SO, CHECK PARAMETERS bool produceOutput = true, produceTUinfo = false; string outputFileName = string.Empty; foreach (var p in breakFun.pars) { string parID = p.Key; ExeXml.Par par = p.Value; if (par.val.ToLower() == DefPar.Value.NA) { continue; } Description parDesc = new Description(funDesc, par, parID); if (par.Name.ToLower() == DefPar.Break.ProduceOutput.ToLower() || par.Name.ToLower() == DefPar.Break.ProduceTUinfo.ToLower()) { bool produceX = false; if (par.val.ToLower() == DefPar.Value.YES) { produceX = true; } else if (par.val.ToLower() == DefPar.Value.NO) { produceX = false; } else { IssueErr(parDesc, "invalid value (must be yes or no)"); } if (par.Name.ToLower() == DefPar.Break.ProduceOutput.ToLower()) { produceOutput = produceX; } else { produceTUinfo = produceX; } } else if (par.Name.ToLower() == DefPar.Break.OutputFileName.ToLower()) { outputFileName = par.val; } else { IssueErr(parDesc, "unknown parameter"); } } if (produceOutput == false && produceTUinfo == true) { IssueErr(funDesc, "TUinfo can only be produced if output is produced (parameter is ignored)", true); } if (infoStore.communicator.errorCount > 0) { return(false); } // IMPLEMENT THE BREAK // - main task: switch off everything after the Break function // - and, if necessary, search for DefOutput that can provide the output-filename (if not set by parameter OutputFileName) // - and, if necessary, find all TU names double outputFunOrder = produceOutput && outputFileName == string.Empty ? double.MaxValue : -1; // the default for OutputFileName should be the first "normal" outputfile List <string> tuNames = new List <string>(); string indTUName = string.Empty; foreach (var pol in infoStore.country.cao.pols.Values) { if (!pol.on) { continue; } foreach (var fun in pol.funs.Values) { if (!fun.on) { continue; } double funOrder = GetOrder(pol.order, fun.order); if (funOrder > breakFunOrder) { fun.on = false; // switch off everything after the Break function } if (fun.Name.ToLower() == DefFun.DefOutput.ToLower() && funOrder < outputFunOrder && funOrder > breakFunOrder) // get the File paramter of the first DefOutput after the Break { var fn = from p in fun.pars.Values where p.Name.ToLower() == DefPar.DefOutput.File.ToLower() select p.val; if (fn.Count() > 0) { outputFileName = fn.First(); outputFunOrder = funOrder; } } // if necessary, find at least one individual TU for output function, or all (active) TUs if TUinfo should be produced if (!fun.on || !produceOutput || fun.Name.ToLower() != DefFun.DefTu.ToLower()) { continue; } var tuNamePar = from p in fun.pars.Values where p.Name.ToLower() == DefPar.DefTu.Name.ToLower() select p.val; var tuTypePar = from p in fun.pars.Values where p.Name.ToLower() == DefPar.DefTu.Type.ToLower() select p.val; if (tuNamePar.Count() == 0 || tuTypePar.Count() == 0) { continue; } if (produceTUinfo) { tuNames.Add(tuNamePar.First()); } if (indTUName == string.Empty && tuTypePar.First().ToUpper() == DefPar.Value.TUTYPE_IND) { indTUName = tuNamePar.First(); } } } // if necessary produce DefOutput function in redefining the Break function, which is not required anymore if (produceOutput == false) { breakFun.on = false; return(true); } if (outputFileName == string.Empty) { IssueErr(funDesc, "no name for the output file found"); return(false); } if (indTUName == string.Empty) { IssueErr(funDesc, "no DefTU with Type=IND found (required as DefOutput's TAX_UNIT)"); return(false); } int iGroup = 0, order = 0; breakFun.Name = DefFun.DefOutput; breakFun.pars.Clear(); breakFun.pars.Add(Guid.NewGuid().ToString(), new ExeXml.Par() { Name = DefPar.DefOutput.File, val = outputFileName, order = (++order).ToString() }); breakFun.pars.Add(Guid.NewGuid().ToString(), new ExeXml.Par() { Name = DefPar.DefOutput.VarGroup, val = "*", order = (++order).ToString() }); breakFun.pars.Add(Guid.NewGuid().ToString(), new ExeXml.Par() { Name = DefPar.DefOutput.ILGroup, val = "*", order = (++order).ToString() }); breakFun.pars.Add(Guid.NewGuid().ToString(), new ExeXml.Par() { Name = DefPar.Common.TAX_UNIT, val = indTUName, order = (++order).ToString() }); foreach (string tuName in tuNames) { string sGroup = (++iGroup).ToString(); breakFun.pars.Add(Guid.NewGuid().ToString(), new ExeXml.Par() { Name = DefPar.DefOutput.UnitInfo_TU, val = tuName, Group = sGroup, order = (++order).ToString() }); foreach (string uiId in new List <string> { DefPar.Value.UNITINFO_HEADID, DefPar.Value.UNITINFO_ISPARTNER, DefPar.Value.UNITINFO_ISDEPCHILD, DefPar.Value.UNITINFO_ISOWNCHILD, DefPar.Value.UNITINFO_ISOWNDEPCHILD, DefPar.Value.UNITINFO_ISDEPPARENT, DefPar.Value.UNITINFO_ISDEPRELATIVE, DefPar.Value.UNITINFO_ISLONEPARENT }) { breakFun.pars.Add(Guid.NewGuid().ToString(), new ExeXml.Par() { Name = DefPar.DefOutput.UnitInfo_Id, val = uiId, Group = sGroup, order = (++order).ToString() }); } } void IssueErr(Description d, string m, bool isW = false) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = isW, message = $"{d.Get()}: {m}" }); } return(true); }