/// <summary> /// try to identify parameters and, if valid, generate the respective ParXXX and put into respective lists (see above) /// </summary> private void ClassifyParameters(Dictionary <string, ExeXml.Par> xmlParList, DefinitionAdmin.Fun funDef) { int dummyGroupNumber = -9999; // this is for placeholder-parameters, see below foreach (var xmlPar in xmlParList) { Description parDescription = new Description(description, xmlPar.Value, xmlPar.Key); string xmlParName = xmlPar.Value.Name; // first check if it is an 'ordinary' parameter ... DefinitionAdmin.Par parDef = funDef.GetParDef(xmlParName); if (parDef != null) { string officialParName = funDef.GetOfficalParName(xmlParName); // is (in contrast to xmlParName) case-sensitive and // corresponds to constants as defined in Common-library // generate parameter ... ParBase par = GeneratePar(xmlPar, parDef, parDescription); // ... and put it into the list it belongs too ... if (parDef.isFootnote) // ... footnote-list { if (GetGroupNumber(xmlPar.Value, parDescription, out int dummy)) { if (!footnotePar.ContainsKey(xmlPar.Value.Group)) { footnotePar.Add(xmlPar.Value.Group, new Dictionary <string, ParBase>()); } if (!footnotePar[xmlPar.Value.Group].ContainsKey(officialParName)) { footnotePar[xmlPar.Value.Group].Add(officialParName, par); } else { ReportDoubleDef(parDescription); } } } else if (parDef.maxCount == 1) // ... unique-parameter-list { if (!uniquePar.ContainsKey(officialParName)) { uniquePar.Add(officialParName, par); if (infoStore.runConfig.warnAboutUselessGroups && !string.IsNullOrEmpty(xmlPar.Value.Group)) { ReportUselessGroup(parDescription); } } else { ReportDoubleDef(parDescription); } } else // ... non-unique-parameter-list { if (!nonUniquePar.ContainsKey(officialParName)) { nonUniquePar.Add(officialParName, new List <ParBase>()); } nonUniquePar[officialParName].Add(par); if (infoStore.runConfig.warnAboutUselessGroups && !string.IsNullOrEmpty(xmlPar.Value.Group)) { ReportUselessGroup(parDescription); } } continue; } // ... if not successuful, check if it is a group parameter ... parDef = funDef.GetGroupParDef(xmlParName, out string groupName); if (parDef != null) { if (GetGroupNumber(xmlPar.Value, parDescription, out int groupNo)) { // generate parameter ... ParBase par = GeneratePar(xmlPar, parDef, parDescription); // ... and put it into group-parameter-list if (!groupPar.ContainsKey(groupName)) { groupPar.Add(groupName, new SortedList <int, List <ParBase> >()); } if (!groupPar[groupName].ContainsKey(groupNo)) { groupPar[groupName].Add(groupNo, new List <ParBase>()); } if (parDef.maxCount > 1 || GetUniqueGroupPar <ParBase>(xmlPar.Value.Name, groupPar[groupName][groupNo]) == null) { groupPar[groupName][groupNo].Add(par); } else { ReportDoubleDef(parDescription); } } continue; } // ... if still not successful, it could still be placehoder parameter ... if (funDef.AllowsForPlaceholders()) { parDef = funDef.GetPlaceholderDef(out string phGroupName); ParBase par = GeneratePar(xmlPar, parDef, parDescription, true); if (phGroupName == null) // non-group placeholder, as e.g. in SetDefault, DefIL { if (!placeholderPar.TryAdd(xmlParName, par)) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, message = $" {parDescription.Get()}: {xmlParName} double definition (is ignored)" }); } } else // group placeholder, as e.g. in DefVar (PH, IsGlobal, IsMonetary), Uprate (PH, FactorCond) { GetGroupNumber(xmlPar.Value, parDescription, // note that this returns a dummy-group if the user didn't indicate one out int groupNo, true); // as placeholders only actually need a group if they are "further specified" (e.g. uprating-factors: factor_condition) if (!groupPar.ContainsKey(phGroupName)) { groupPar.Add(phGroupName, new SortedList <int, List <ParBase> >()); } if (!groupPar[phGroupName].ContainsKey(groupNo)) { groupPar[phGroupName].Add(groupNo, new List <ParBase>()); } groupPar[phGroupName][groupNo].Add(par); } continue; } // ... now we give up infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, message = $" {parDescription.Get()}: unknown parameter" }); } if (infoStore.runConfig.warnAboutUselessGroups) { foreach (var groupType in groupPar) { if (groupType.Key.ToLower() == DefPar.SchedCalc.Band_XXX.ToLower()) { continue; } foreach (var group in groupType.Value) { if (group.Key >= 0 && group.Value.Count == 1) { ReportUselessGroup(group.Value[0].description); } } } } // internal function for generating parameters ParBase GeneratePar(KeyValuePair <string, ExeXml.Par> xmlPar, DefinitionAdmin.Par parDef, Description parDescription, bool isPlaceholder = false) { ParBase par; switch (parDef.valueType) { case DefPar.PAR_TYPE.FORMULA: par = new ParFormula(infoStore); break; case DefPar.PAR_TYPE.CONDITION: par = new ParCond(infoStore); break; case DefPar.PAR_TYPE.BOOLEAN: par = new ParBool(infoStore); break; case DefPar.PAR_TYPE.NUMBER: par = new ParNumber(infoStore); break; case DefPar.PAR_TYPE.TEXT: par = new ParBase(infoStore); break; case DefPar.PAR_TYPE.VAR: par = new ParVar(infoStore); break; case DefPar.PAR_TYPE.OUTVAR: par = new ParOutVar(infoStore); break; case DefPar.PAR_TYPE.IL: par = new ParIL(infoStore); break; case DefPar.PAR_TYPE.TU: par = new ParTU(infoStore); break; case DefPar.PAR_TYPE.VARorIL: par = new ParVarIL(infoStore); break; case DefPar.PAR_TYPE.CATEG: par = new ParCateg(infoStore, parDef.categValues); break; case DefPar.PAR_TYPE.PLACEHOLDER: par = new ParBase(infoStore); break; default: throw new Exception($"Not yet properly implemented parameter value type {parDef.valueType}"); } par.description = parDescription; par.xmlValue = xmlPar.Value.val; par.description.isPlaceholder = isPlaceholder; return(par); } bool GetGroupNumber(ExeXml.Par p, Description parDescription, out int groupNumber, bool allowDummy = false) { groupNumber = dummyGroupNumber++; // placeholders (e.g.uprating factors) only actually need a group if (string.IsNullOrEmpty(p.Group)) // if they are "further specified" (e.g.factor_condition) { if (allowDummy) { return(true); } infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $" {parDescription.Get()}: missing group" }); return(false); } if (int.TryParse(p.Group, out groupNumber)) { return(true); } infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $" {parDescription.Get()}: invalid group {p.Group} (must be an integer number)" }); return(false); } void ReportDoubleDef(Description parDescription) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $" {parDescription.Get()}: defined more than once" }); } void ReportUselessGroup(Description parDescription) { if (parDescription.GetFunName() != DefFun.Store) // add a special exception for Store, as it has its own reporting { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = true, message = $" {parDescription.Get()}: group has no use" }); } } }
/// <summary> check for compulsory parameters </summary> private void CheckForCompleteness(Dictionary <string, ExeXml.Par> xmlParList, DefinitionAdmin.Fun funDef) { // check if compulsory non-group parameters are available foreach (var p in funDef.GetParList()) { string parName = p.Key; DefinitionAdmin.Par parDef = p.Value; if (parDef.minCount == 0) { continue; // optional parameter (e.g. Allocate's Share_Between) } // (note that footnote-parameters are always optional) bool found = false; if (parDef.maxCount == 1) // check for unique compulsory parameter (e.g. ArithOp's Formula) { if (GetUniquePar <ParBase>(parName) != null) { found = true; } else // could still be available as substitute (e.g. output_var not available, but output_add_var) { foreach (string substitute in parDef.substitutes) { if (GetUniquePar <ParBase>(substitute) != null) { found = true; break; } } ; } } if (parDef.maxCount > 1) // check for non-unique parameter, where at least one must be defined (e.g. SetDefault's Dataset) { if (GetNonUniquePar <ParBase>(parName).Count > 0) { found = true; } else // unlikely, but could still be available as substitute { foreach (string substitute in parDef.substitutes) { if (GetNonUniquePar <ParBase>(substitute).Count > 0) { found = true; break; } } ; } } if (!found) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $" {description.Get()}: compulsory parameter {parName} is missing" }); } } // check if compulsory groups, and compulsory parameter within groups are available foreach (var groupDef in funDef.GetGroupParList()) { if (groupDef.minCount > 0) // check for compulsory group, e.g. BenCalc's Comp_X-group { if (!groupPar.ContainsKey(groupDef.groupName)) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $" {description.Get()}: compulsory group {groupDef.groupName} is missing" }); } } // whether or not the group is compulsory it can (if existent) ask for completeness, i.e. have compulsory parts if (!groupPar.ContainsKey(groupDef.groupName)) { continue; // no such group exists } foreach (var p in groupDef.par) // loop over the group-definition's parameters (e.g. Comp_Cond, Comp_perTU, Comp_LowLim, ...) { string parName = p.Key; DefinitionAdmin.Par parDef = p.Value; if (parDef.minCount == 0) { continue; // optional parameter (e.g. Comp_LowLim) } // check for compulsory parameter (e.g. Comp_Cond) foreach (var g in GetParGroups(groupDef.groupName)) // loop over all existent groups { // (e.g. all components of an actual BenCalc) int groupNo = g.Key; List <ParBase> groupPar = g.Value; int found = 0; if (parDef.maxCount == 1) // check for unique compulsory group-parameter (e.g. BenCalc's Comp_Cond) { if (GetUniqueGroupPar <ParBase>(parName, groupPar) != null) { ++found; } foreach (string substitute in parDef.substitutes) { if (GetUniqueGroupPar <ParBase>(substitute.ToLower(), groupPar) != null) { ++found; } } if (found > 1) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $" {description.Get()}: double definition of group-parameter {parName} (group {groupNo})" }); } } if (parDef.maxCount > 1) // check for non-unique compulsory group-parameter (e.g. Uprate's AggVarPart) { if (GetNonUniqueGroupPar <ParBase>(parName, groupPar).Count > 0) { ++found; } foreach (string substitute in parDef.substitutes) { if (GetNonUniqueGroupPar <ParBase>(substitute.ToLower(), groupPar).Count > 0) { ++found; } } } if (found == 0) { infoStore.communicator.ReportError(new Communicator.ErrorInfo() { isWarning = false, message = $" {description.Get()}: compulsory group-parameter {parName} (group {groupNo}) is missing" }); } } } } }
void AddParameters() { //analyse all AddOn_Par functions foreach (CountryConfig.FunctionRow function_AddOnParameters in _addOnCountryConfigFacade.GetFunctionRowsBySystemIDAndFunctionName(_addOnSystemRow.ID, DefFun.AddOn_Par)) { if (function_AddOnParameters.Switch.ToLower() != DefPar.Value.ON.ToLower()) { continue; } //assess which parameters are to be merged and into which function by interpreting the AddOnPar-function's parameters CountryConfig.ParameterRow parameter_InsertFunctionID = _addOnCountryConfigFacade.GetParameterRowByName(function_AddOnParameters.ID, DefPar.AddOn_Par.Insert_Func); if (parameter_InsertFunctionID == null) { _errorMessages += ImportExportHelper.GenerateErrorMessage(function_AddOnParameters, "Compulsory parameter '" + DefPar.AddOn_Par.Insert_Func + "' not defined."); continue; } //search for the function where parameters are to be added in the just generated (copied) system CountryConfig.FunctionRow addOnParameters_InsertFunction = _mergeCountryConfigFacade.GetFunctionRowByID(parameter_InsertFunctionID.Value); if (addOnParameters_InsertFunction == null) //take account of 'symbolic' identifier, e.g. output_std_sl_#3 { addOnParameters_InsertFunction = ImportExportHelper.GetFunctionRowBySymbolicID(parameter_InsertFunctionID.Value, _mergeCountryConfigFacade, _mergeSystemRow.ID); } if (addOnParameters_InsertFunction == null) { _errorMessages += ImportExportHelper.GenerateErrorMessage(function_AddOnParameters, "Unknown function '" + parameter_InsertFunctionID.Value + "'."); continue; } //if everything is ok, insert the parameters (all other parameters than insert_func in AddOn_Par) into the function foreach (CountryConfig.ParameterRow addOnParameters_ParameterNameAndValue in function_AddOnParameters.GetParameterRows()) { if (addOnParameters_ParameterNameAndValue.Name.ToLower() == DefPar.AddOn_Par.Insert_Func.ToLower()) { continue; } DefinitionAdmin.Par parDef = DefinitionAdmin.GetParDefinition(addOnParameters_InsertFunction.Name, addOnParameters_ParameterNameAndValue.Name, false); if (parDef == null) { _errorMessages += ImportExportHelper.GenerateErrorMessage(function_AddOnParameters, "Function '" + addOnParameters_InsertFunction.Name + "' does not allow for parameter '" + addOnParameters_ParameterNameAndValue.Name + "'."); continue; } //add parameter, however if a respective parameter with value n/a exists, it can be used //this is even necessary for single parameters (which may only exist once) if an add-on is added more than once (i.e. there is already the n/a parameter of the first adding-on) CountryConfig.ParameterRow parameterRow = null; List <CountryConfig.ParameterRow> parameterList = (from pR in addOnParameters_InsertFunction.GetParameterRows() where pR.Name.ToLower() == addOnParameters_ParameterNameAndValue.Name.ToLower() && pR.Group == addOnParameters_ParameterNameAndValue.Group && pR.Value == DefPar.Value.NA select pR).ToList(); if (parameterList.Count != 0) { parameterRow = parameterList.First(); } if (parameterRow == null) { parameterRow = CountryConfigFacade.AddParameterRowAtTail(addOnParameters_InsertFunction, addOnParameters_ParameterNameAndValue.Name, parDef); } if (parameterRow.Name.ToLower() == DefinitionAdmin.ParTypeToString(DefPar.PAR_TYPE.PLACEHOLDER).ToLower()) { parameterRow.Name = addOnParameters_ParameterNameAndValue.Name; //for adding parameters e.g. to function DefIL } parameterRow.Value = addOnParameters_ParameterNameAndValue.Value; parameterRow.Comment = addOnParameters_ParameterNameAndValue.Comment; ImportExportHelper.ReplaceCountrySymbol(parameterRow, _mergeCountryConfigFacade.GetCountryShortName()); //replace all incidents of =cc= by country symbol } } }
void btnApply_Click(object sender, EventArgs e) { List <DataGridViewRow> selectedRows = GetSelectedRows(); if (selectedRows.Count == 0) { return; } ActionGroup actionGroup = new ActionGroup(); List <KeyValuePair <string, string> > conflictParameters = new List <KeyValuePair <string, string> >(); //helper list for dedecting conflicts à la comp_perElig[grp1]/comp_perTU[grp1] foreach (DataGridViewRow selectedRow in selectedRows) { string countAsString = selectedRow.Cells[colCount.Index].Value == null ? "0" : selectedRow.Cells[colCount.Index].Value.ToString(); uint count = (countAsString != string.Empty && EM_Helpers.IsNonNegInteger(countAsString)) ? Convert.ToUInt32(countAsString) : 1; var gon = selectedRow.Cells[colGroupNo.Index].Value; string groupOrNo = gon == null? string.Empty : gon.ToString(); string initialGroupOrNo = groupOrNo; string substitute = selectedRow.Cells[colReplaces.Index].Value.ToString(); if (substitute != string.Empty) { actionGroup.AddAction(new ChangeParameterNameAction((selectedRow.Tag as AddParameterTag)._parameterNode, selectedRow.Cells[colParameter.Index].Value.ToString())); continue; } for (uint index = 0; index < count; ++index) { DefinitionAdmin.Par parDef = (selectedRow.Tag as AddParameterTag)._parDef; DefinitionAdmin.ParGroup parGroup = (selectedRow.Tag as AddParameterTag)._parGroup; string parName = (selectedRow.Tag as AddParameterTag)._parName; if (parDef.maxCount == 1 && (parGroup == null || parGroup.maxCount == 1) && count > 1) { count = 1; //if parameter is "single" make sure it is only added once! } if (groupOrNo != string.Empty) //group- or footnote-parameter { if (EM_Helpers.IsNonNegInteger(groupOrNo)) { groupOrNo = (EM_Helpers.SaveConvertToInt(initialGroupOrNo) + index).ToString(); } if (CountryConfigFacade.DoesParameterExist(_displayedFunctionRow, parName, groupOrNo)) {//may happen if user changes group or footnote number manually UserInfoHandler.ShowError($"Parameter {parName} with Grp/No {groupOrNo} already exists. " + "Please consider Grp/No and/or whether there is a conflict parameter."); return; } } if (parDef.substitutes.Count > 0) { foreach (string conflictPar in parDef.substitutes) { if (conflictParameters.Contains(new KeyValuePair <string, string>(conflictPar.ToLower(), groupOrNo))) {//trying to add e.g. comp_perElig and comp_perTU with same group or output_var and output_add_var string groupMessage = groupOrNo != string.Empty ? " with identical group " + groupOrNo : string.Empty; UserInfoHandler.ShowError($"Cannot add parameter {parName} and parameter {conflictPar} {groupMessage}, as they are subsitudes."); return; } } conflictParameters.Add(new KeyValuePair <string, string>(parName.ToLower(), groupOrNo)); } if ((_focusedNode.Tag as BaseTreeListTag).GetDefaultParameterRow() == null) { //if the dialog was opened via the function context menu, parameters are added at the end of the function //thus they can be added simply one after the other, without changing the order ... actionGroup.AddAction(new AddParameterAction(_focusedNode, parName, parDef, groupOrNo)); } else { //if the dialog was opened via the parameter context menu, parameters are added after the selected parameter //thus they have to be added in reverted order to keep the given order actionGroup.InsertAction(0, new AddParameterAction(_focusedNode, parName, parDef, groupOrNo)); } } } _inApplyAction = true; TreeListNode functionNode = (_focusedNode.Tag as BaseTreeListTag).GetDefaultParameterRow() == null ? _focusedNode : _focusedNode.ParentNode; EM_UI_MainForm mainForm = EM_AppContext.Instance.GetCountryMainForm(_displayedFunctionRow.PolicyRow.SystemRow.CountryRow.ShortName); mainForm.PerformAction(actionGroup, true, false, functionNode); //performance optimisation Aug 13: update only the concerned function instead of the whole tree _inApplyAction = false; UpdateContent(functionNode); }
internal void UpdateContent(TreeListNode focusedNode) { try { if (_inApplyAction) { return; } _displayedFunctionRow = null; _focusedNode = focusedNode; //needed to know where to put the parameters within the function if (_focusedNode != null && _focusedNode.Tag != null) { _displayedFunctionRow = (_focusedNode.Tag as BaseTreeListTag).GetDefaultFunctionRow(); //selected function or function where selected parameter is part of (null if policy selelcted) } ClearContent(); //empty controls and activate/deactivate corresponding to whether a function is selected in the tree or not if (_displayedFunctionRow == null) { return; //no function selected in tree } lblFunction.Text = _displayedFunctionRow.Name + " (order: " + _displayedFunctionRow.Order + ") in policy " + _displayedFunctionRow.PolicyRow.Name; Dictionary <string, string> groupList = new Dictionary <string, string>(); //helper list for group parameters foreach (AddParameterTag apt in GetFullParList(_displayedFunctionRow.Name)) { string parName = apt._parName; DefinitionAdmin.Par parDef = apt._parDef; string groupName = apt._parGroup == null ? string.Empty : apt._parGroup.groupName; bool isGroup = apt._parGroup != null; //parameter belongs/doesn't belong to a group; does: comp_Cond, comp_perTU bool isSingle = parDef.maxCount == 1; //parameter can/cannot be used more than once; can: DefOuput/Var, cannot: TAX_UNIT bool isFootnote = parDef.isFootnote; //parameter is/isn't a footnote parameter; is: #_UpLim, #_Amount bool isConflict = parDef.substitutes.Count > 0; //parameter has/hasn't a Substitute; has: Output_Var / Output_Add_Var bool isIn = false; //parameter isn't ... foreach (CountryConfig.ParameterRow countryConfigParameterRow in _displayedFunctionRow.GetParameterRows()) { if (countryConfigParameterRow.Name.ToLower() == parName.ToLower()) { isIn = true; //.. is already used in the function break; } } string subsitude = string.Empty; string groupOrNo = string.Empty; string count = string.Empty; if (isSingle && !isGroup && !isFootnote && isIn) { continue; //parameter is already used (and multi use is not possible) } if (!isSingle || isGroup || isFootnote) { count = "1"; //as default multiple useable parameter is added once } if (isGroup) //group parameter, e.g. comp_Cond, comp_perTU { //propse the likely group identifier, i.e. the next available number if (groupList.Keys.Contains(groupName.ToLower())) { groupOrNo = groupList[groupName.ToLower()]; //for all group parameters of the same group the same group identifier is proposed } else { int maxGroup = GetMaxGroupUsedByFunction(_displayedFunctionRow, groupName) + 1; groupOrNo = maxGroup.ToString(); groupList.Add(groupName.ToLower(), groupOrNo); } } if (isFootnote) //footnote parameter, e.g. #_UpLim, #_Amount { //propse the likely footnote identifier, i.e. the next available number groupOrNo = (CountryConfigFacade.GetMaxFootnoteUsedByFunction(_displayedFunctionRow, parName) + 1).ToString(); } if (isConflict && !isGroup) {//if e.g. output_var is already used, still show output_add_var, but put out_var in substitute column TreeListNode functionNode = ((focusedNode.Tag as BaseTreeListTag).GetDefaultParameterRow() == null) ? focusedNode : focusedNode.ParentNode; foreach (TreeListNode parameterNode in functionNode.Nodes) { string parameterName = parameterNode.GetDisplayText(TreeListBuilder._policyColumnName); foreach (string conflictPar in parDef.substitutes) { if (parameterName.ToLower() == conflictPar.ToLower()) { subsitude = parameterName; apt._parameterNode = parameterNode; break; } } if (subsitude != string.Empty) { break; } } } int index = dgvParameter.Rows.Add(false, parName, subsitude, groupOrNo, count, parDef.description); dgvParameter.Rows[index].Tag = apt; } ShowHideRows(); dgvParameter.Select(); } catch (Exception exception) { UserInfoHandler.ShowException(exception); } }
//returns the footnote parameters which need to be added when a formula was changed //e.g. formula contains 'Amount#4711' (and did not contain that before the change): footnote parameter #Amount with group 4711 must be added internal static Dictionary <KeyValuePair <string, string>, DefinitionAdmin.Par> GetFootnoteParametersToAdd(TreeListNode node, ref string formulaText) { Dictionary <KeyValuePair <string, string>, DefinitionAdmin.Par> footnoteParametersToAdd = new Dictionary <KeyValuePair <string, string>, //name and group of new footnote parameter DefinitionAdmin.Par>(); //definition (from config file) of new parameter int nextFootnote = TreeListManager.GetNextAvailableFootnoteCounter(node.ParentNode); string functionName = node.ParentNode.GetDisplayText(TreeListBuilder._policyColumnName); //search for Amount#xi (i.e Amount#x1, Amount#x2, etc.) for (int indexLabelAmount = formulaText.ToLower().IndexOf(DefPar.Value.AMOUNT.ToLower() + "#x"), indexNonDigit; indexLabelAmount >= 0; indexLabelAmount = formulaText.ToLower().IndexOf(DefPar.Value.AMOUNT.ToLower() + "#x")) { for (indexNonDigit = indexLabelAmount + DefPar.Value.AMOUNT.Length + 2; indexNonDigit < formulaText.Length && EM_Helpers.IsDigit(formulaText.ElementAt(indexNonDigit)); ++indexNonDigit) { ; //search first non digit after Amount#x } string parameterName = "#_" + DefPar.Value.AMOUNT; //#_Amount DefinitionAdmin.Par parDef = DefinitionAdmin.GetParDefinition(functionName, parameterName); KeyValuePair <string, string> parameterNameAndGroup = new KeyValuePair <string, string>(parameterName, nextFootnote.ToString()); footnoteParametersToAdd.Add(parameterNameAndGroup, parDef); //put parameter into list of footnote parameters which need to be generated string toReplace = SubstringFromTo(formulaText, indexLabelAmount, indexNonDigit - 1); //Amount#xi (e.g. Amount#x1) string replaceBy = DefPar.Value.AMOUNT + "#" + nextFootnote.ToString(); //Amount#f (e.g. Amount#x3) formulaText = formulaText.Replace(toReplace, replaceBy); //replace all occurrences (there might be more than one) ++nextFootnote; } //search for #xi[_yyy] (i.e. #x1[_Level], #x2[_Level], #x1[_UpLim], etc.) for (int indexPlaceholder = formulaText.IndexOf("[_"); indexPlaceholder >= 0; indexPlaceholder = formulaText.IndexOf("[_")) { int iStart = formulaText.Substring(0, indexPlaceholder).LastIndexOf("#x"); int iEnd = formulaText.Substring(indexPlaceholder).IndexOf("]") + indexPlaceholder; if (iStart >= 0 && iEnd >= 0 && EM_Helpers.IsNonNegInteger(SubstringFromTo(formulaText, iStart + 2, indexPlaceholder - 1))) { string parameterName = "#" + SubstringFromTo(formulaText, indexPlaceholder + 1, iEnd - 1); //#_yyy (e.g. #_Level) DefinitionAdmin.Fun funDef = DefinitionAdmin.GetFunDefinition(functionName, false); // check if function allows for this footnote if (funDef != null && (from p in funDef.GetParList() where p.Value.isFootnote && p.Key.ToLower() == parameterName.ToLower() select p).Count() > 0) { DefinitionAdmin.Par parDef = DefinitionAdmin.GetParDefinition(functionName, parameterName); KeyValuePair <string, string> parameterNameAndGroup = new KeyValuePair <string, string>(parameterName, nextFootnote.ToString()); footnoteParametersToAdd.Add(parameterNameAndGroup, parDef); //put parameter into list of footnote parameters which need to be generated string toReplace = SubstringFromTo(formulaText, iStart, iEnd); //#xi_yyy (e.g. #x1[_Level]) string replaceBy = "#" + nextFootnote.ToString(); //#f_yyy (e.g. #4) formulaText = formulaText.Replace(toReplace, replaceBy); //replace all occurrences (there might be more than one) ++nextFootnote; } else { break; //should not happen (though can), but to avoid infinite loop } } else { break; //should not happen (though can), but to avoid infinite loop } } //search for query#x (e.g. isNtoMchild#x) for (int indexPlaceholder = formulaText.IndexOf("#x"); indexPlaceholder >= 0; indexPlaceholder = formulaText.IndexOf("#x")) { string theQuery = string.Empty; foreach (string queryName in DefinitionAdmin.GetQueryNamesAndDesc().Keys) { string potQueryName = SubstringFromTo(formulaText, indexPlaceholder - (queryName.Length - 2), indexPlaceholder + 1).ToLower(); if (potQueryName == queryName.ToLower()) { theQuery = queryName; break; } } if (theQuery == string.Empty) { formulaText = formulaText.Substring(0, indexPlaceholder) + "#°" + formulaText.Substring(indexPlaceholder + 2); //no query found, replace #x preliminary by #° (change back below) } else //add all parameters of the query { Dictionary <string, DefinitionAdmin.Par> queryParameters = new Dictionary <string, DefinitionAdmin.Par>(); DefinitionAdmin.GetQueryDefinition(theQuery, out DefinitionAdmin.Query queryDef, out string dummy, false); if (queryDef != null) { queryParameters = queryDef.par; } List <string> alreadyCoveredByAlias = new List <string>(); // avoid adding e.g. #_income as well as #_info foreach (var q in queryParameters) { string queryParName = q.Key; DefinitionAdmin.Par queryParDef = q.Value; if (alreadyCoveredByAlias.Contains(queryParName)) { continue; } footnoteParametersToAdd.Add(new KeyValuePair <string, string>(queryParName, nextFootnote.ToString()), queryParDef); //put parameter into list of footnote parameters which need to be generated alreadyCoveredByAlias.AddRange(queryParDef.substitutes); } formulaText = formulaText.Substring(0, indexPlaceholder) + "#" + nextFootnote.ToString() + formulaText.Substring(indexPlaceholder + 2); //replace #x by #f (e.g. #x by #5) ++nextFootnote; } } formulaText = formulaText.Replace("#°", "#x"); return(footnoteParametersToAdd); }
internal override void PerformAction() { TreeListNode policyNode = _senderNode; if (_senderNode.ParentNode != null) { policyNode = _senderNode.ParentNode; } int newFunctionNodeIndex = -1; List <CountryConfig.FunctionRow> newFunctionRows = new List <CountryConfig.FunctionRow>(); foreach (CountryConfig.PolicyRow policyRow in (policyNode.Tag as PolicyTreeListTag).GetPolicyRows()) //loop over systems { CountryConfig.FunctionRow newFunctionRow = null; //(1) add function //if the sender node is a policy node: insert as last function ('Add Function' was called from policy node or 'Add Function After' was called from last function node in policy) if (_senderNode == policyNode) { newFunctionRow = CountryConfigFacade.AddFunctionRowAtTail(_functionName, policyRow, // the switch of a function inside an extension-policy cannot be changed, therefore add as on (otherwise one would need to remove the policy from the extension to be able to change the switch to on) ExtensionAndGroupManager.ShowExtensionSwitchEditor(policyRow) ? DefPar.Value.ON : DefPar.Value.NA); } //if the sender node is a function node: insert before ('Add Function Before' was called from function node) else { CountryConfig.FunctionRow neighbourFunction = (_senderNode.Tag as FunctionTreeListTag).GetFunctionRowOfSystem(policyRow.SystemRow.ID); newFunctionRow = CountryConfigFacade.AddFunctionRow(_functionName, neighbourFunction, true, ExtensionAndGroupManager.ShowExtensionSwitchEditor(policyRow) ? DefPar.Value.ON : DefPar.Value.NA); // see comment above newFunctionNodeIndex = _mainForm.treeList.GetNodeIndex(_senderNode); } _addedFunctionsIDs.Add(newFunctionRow.ID); //(2) add compulsory parameters DefinitionAdmin.Fun fun = DefinitionAdmin.GetFunDefinition(_functionName, false); if (fun != null) { for (short doCommon = 0; doCommon < 2; ++doCommon) // add function-specific parameters before common { foreach (var p in fun.GetParList()) { AddPar(p, false); } foreach (var pg in fun.GetGroupParList()) { if (pg.minCount > 0) { foreach (var p in pg.par) { AddPar(p, true); } } } void AddPar(KeyValuePair <string, DefinitionAdmin.Par> p, bool group) { string parName = p.Key.ToUpper() == DefPar.PAR_TYPE.PLACEHOLDER.ToString().ToUpper() ? DefinitionAdmin.ParTypeToString(DefPar.PAR_TYPE.PLACEHOLDER) : p.Key; DefinitionAdmin.Par parDef = p.Value; if (parDef.minCount > 0 && ((doCommon == 0 && !parDef.isCommon) || (doCommon == 1 && parDef.isCommon))) { CountryConfigFacade.AddParameterRowAtTail(newFunctionRow, parName, parDef, group ? "1" : string.Empty); } } } } newFunctionRows.Add(newFunctionRow); } _mainForm.GetTreeListBuilder().InsertFunctionNode(newFunctionRows, policyNode, newFunctionNodeIndex); }