public bool Execute(WonkaProduct poNewTrxRecord) { bool bResult = false; var RulesEngine = moEthEngineInit.Engine.RulesEngine; // Validate that the .NET implementation and the rules markup are both working properly WonkaBizRuleTreeReport Report = RulesEngine.Validate(poNewTrxRecord); if (Report.OverallRuleTreeResult == ERR_CD.CD_SUCCESS) { bResult = true; } else if (Report.GetRuleSetFailureCount() > 0) { bResult = false; // NOTE: Notification about the error should be returned } else { bResult = false; } return(bResult); }
public static string GetErrors(this WonkaBizRuleTreeReport report) { var ErrorReport = new StringBuilder(); foreach (var ReportNode in report.GetRuleSetSevereFailures()) { if (ReportNode.RuleResults.Count > 0) { foreach (var RuleReportNode in ReportNode.RuleResults) { if (ErrorReport.Length > 0) { ErrorReport.Append("\n"); } ErrorReport.Append(RuleReportNode.VerboseError.Replace("/", "")); } } else { ErrorReport.Append(ReportNode.ErrorDescription); } } return(ErrorReport.ToString()); }
public static async Task <string> PublishReportToIpfs(this WonkaBizRuleTreeReport poReport, string psIpfsFilePath, IpfsService poIpfsService, bool pbPinFlag = true, string psIpfsGateway = CONST_INFURA_IPFS_API_GATEWAY_URL) { string sIpfsHash = ""; string sReport = ""; // NOTE: Not yet ready // sReport = poReport.SerializeToXml(); sReport = poReport.GetErrors(); if (String.IsNullOrEmpty(psIpfsFilePath)) { psIpfsFilePath = "testreport"; } if (String.IsNullOrEmpty(sReport)) { throw new Exception("ERROR! No report to be serialized."); } var IpfsNode = await poIpfsService.AddTextAsync(psIpfsGateway, sReport, psIpfsFilePath, pbPinFlag).ConfigureAwait(false); sIpfsHash = IpfsNode.Hash.ToString(); return(sIpfsHash); }
/// <summary> /// /// This method will execute the RuleTree collection of a Grove, invoking each one either on the chain or off the chain. /// All of the invocations will be assembled and then returned in a report about the execution of the Grove. /// /// NOTE: UNDER CONSTRUCTION /// /// <param name="poGrove">The Grove that we are looking to execute, especially its pool of RuleTree members</param> /// <returns>The report that will hold the aggregated reports about the execution of each Grove member</returns> /// </summary> public static async Task <WonkaBizGroveReport> ExecuteAsync(this WonkaBizGrove poGrove, Wonka.Eth.Init.WonkaEthEngineInitialization poEngineInitData) { if (poGrove.RuleTreeMembers.Count == 0) { throw new WonkaEthException("ERROR! Execute() cannot be invoked for Grove(" + poGrove.GroveDesc + ") when it has no members."); } if (poEngineInitData == null) { throw new WonkaEthException("ERROR! Cannot invoke the Grove(" + poGrove.GroveDesc + ") since the EthEngineInit data provided is empty."); } var GroveReport = new WonkaBizGroveReport(poGrove); foreach (WonkaBizRulesEngine RuleTreeMember in poGrove.RuleTreeMembers) { if (poGrove.ExecuteRuleTreesOnChain.Contains(RuleTreeMember)) { var OnChainReport = new Wonka.Eth.Extensions.RuleTreeReport(); // NOTE: We assume here that that the Wonka contract instance (mentioned within 'poEngineInitData') and certain RuleTrees of 'poGrove' // exist on the chain - maybe we should check that fact? string sTrxHash = await RuleTreeMember.ExecuteOnChainAsync(poEngineInitData, OnChainReport).ConfigureAwait(false); GroveReport.RuleTreeReports[RuleTreeMember.DetermineRuleTreeChainID()] = OnChainReport; } else { var OffChainReport = new WonkaBizRuleTreeReport(); WonkaProduct CurrValues = new WonkaProduct(); bool bResult = await CurrValues.PopulateWithDataFromChainAsync(RuleTreeMember.RefEnvHandle, RuleTreeMember.SourceMap, poEngineInitData.Web3HttpUrl).ConfigureAwait(false); OffChainReport = RuleTreeMember.Validate(CurrValues); GroveReport.RuleTreeReports[RuleTreeMember.DetermineRuleTreeChainID()] = OffChainReport; } if (poGrove.ExecutionBreakpointDelegate != null) { poGrove.ExecutionBreakpointDelegate.Invoke(poGrove, RuleTreeMember); } if ((GroveReport.GetTotalGasUsed() >= poGrove.MaxGasCostAllowed) && (poGrove.MaxGasCostExceededDelegate != null)) { poGrove.MaxGasCostExceededDelegate.Invoke(poGrove, RuleTreeMember); } } GroveReport.EndTime = DateTime.Now; return(GroveReport); }
/// <summary> /// /// This method will begin the evaluation of a RuleTree when applied to both the incoming and current Product /// records. /// /// <param name="poRootRuleSet">The root RuleSet of the RuleTree whose rules are being applied against the provided records</param> /// <param name="poIncomingProduct">The incoming Product record</param> /// <param name="poCurrentProduct">The current Product record (i.e., in the database)</param> /// <param name="poRuleTreeReport">The report that will contain all evaluations of RuleSets in the RuleTree</param> /// <returns>Indicates whether or not the RuleSet evaluated to a success</returns> /// </summary> public static bool MediateRuleTreeExecution(WonkaBizRuleSet poRootRuleSet, WonkaProduct poIncomingProduct, WonkaProduct poCurrentProduct, WonkaBizRuleTreeReport poRuleTreeReport) { bool bRuleTreeResult = true; bRuleTreeResult = MediateRuleSetExecution(poRootRuleSet, poIncomingProduct, poCurrentProduct, poRuleTreeReport); // NOTE: Should we do anything else here? return(bRuleTreeResult); }
/// <summary> /// /// This method will: /// /// 1.) Grab the current product by retrieving it through the invocation of th delegate /// 2.) Validate the incoming product (and possibly the current product) using the RuleTree initialized in the constructor /// /// <param name="poIncomingProduct">The product that we are attempting to validate</param> /// <returns>Contains a detailed report of the RuleTree's application to the provided product</returns> /// </summary> public WonkaBizRuleTreeReport Validate(WonkaProduct poIncomingProduct) { WonkaRefEnvironment WonkaRefEnv = WonkaRefEnvironment.GetInstance(); Dictionary <string, string> ProductKeys = GetProductKeys(poIncomingProduct); if (poIncomingProduct == null) { throw new WonkaBizRuleException("ERROR! Provided incoming product is null!"); } if ((TransactionState != null) && !TransactionState.IsTransactionConfirmed()) { throw new WonkaBizPermissionsException("ERROR! Pending transaction has not yet been confirmed!", TransactionState); } WonkaBizRuleTreeReport RuleTreeReport = new WonkaBizRuleTreeReport(); try { if (GetCurrentProductDelegate != null) { CurrentProductOnDB = GetCurrentProductDelegate.Invoke(ProductKeys); } else { CurrentProductOnDB = new WonkaProduct(); } WonkaBizRuleMediator.MediateRuleTreeExecution(RuleTreeRoot, poIncomingProduct, CurrentProductOnDB, RuleTreeReport); /* * NOTE: Do we need anything like this method * * if (PostApplicationDelegate != null) * PostApplicationDelegate.Invoke(poIncomingProduct, CurrentProductOnDB); */ } finally { if (TransactionState != null) { TransactionState.ClearPendingTransaction(); } } RuleTreeReport.EndTime = DateTime.Now; return(RuleTreeReport); }
public override WonkaBizRuleTreeReport SimulateValidate(AccountUpdateCommand poCommand) { /** ** NOTE: Since the Ethereum engine does not currently support record notation as specified in the markup ** (where O.* indicates existing records in the blockchain, N.* indicates new records about to be fed into the blockchain, etc.), ** we don't need to actually get an old product from anywhere **/ moRulesEngine.GetCurrentProductDelegate = GetEmptyProduct; WonkaProduct NewProduct = GetWonkaProductViaReflection(poCommand); WonkaBizRuleTreeReport Report = moRulesEngine.Validate(NewProduct); return(Report); }
/// <summary> /// /// This method will apply the Rules of the RuleSet to either one or both of the incoming Product record /// and the current Product record. The collective result of those applied Rules will then determine /// whether or not the RuleSet was evaluated as a success. /// /// <param name="poTargetRuleSet">The RuleSet whose rules are being applied against the provided records</param> /// <param name="poIncomingProduct">The incoming Product record</param> /// <param name="poCurrentProduct">The current Product record (i.e., in the database)</param> /// <param name="poRuleTreeReport">The report that will contain all evaluations of RuleSets in the RuleTree</param> /// <param name="poRuleSetErrorMessage">The buffer that will contain an error message if the 'poTargetRuleSet' fails</param> /// <returns>Indicates whether or not the RuleSet evaluated to a success</returns> /// </summary> private static bool MediateRulesExecution(WonkaBizRuleSet poTargetRuleSet, WonkaProduct poIncomingProduct, WonkaProduct poCurrentProduct, WonkaBizRuleTreeReport poRuleTreeReport, StringBuilder poRuleSetErrorMessage) { bool bRuleSetResult = true; StringBuilder RuleErrorMsgBuilder = new StringBuilder(); List <bool> RuleResultList = new List <bool>(); foreach (WonkaBizRule TempRule in poTargetRuleSet.EvaluativeRules) { bool bRuleResult = true; string sRuleResult = string.Empty; string sFinalRuleErrMsg = string.Empty; RuleErrorMsgBuilder.Clear(); bRuleResult = TempRule.Execute(poIncomingProduct, poCurrentProduct, RuleErrorMsgBuilder); if (TempRule.IsPassive) { if (TempRule.NotOperator) { bRuleResult = !bRuleResult; } } RuleResultList.Add(bRuleResult); if (bRuleResult) { poRuleSetErrorMessage.Append("SUCCESS"); } else { var RuleSetReport = poRuleTreeReport.FindRuleSetReport(poTargetRuleSet.RuleSetId, true); if (RuleSetReport != null) { if (poTargetRuleSet.ErrorSeverity == RULE_SET_ERR_LVL.ERR_LVL_SEVERE) { sRuleResult = "SEVERE"; RuleSetReport.SevereFailureCount++; } else { sRuleResult = "WARNING"; RuleSetReport.WarningFailureCount++; } } sFinalRuleErrMsg = RuleErrorMsgBuilder.ToString() + " / " + poTargetRuleSet.CustomFailureMsg; } poRuleTreeReport.ArchiveRuleExecution(TempRule, bRuleResult ? ERR_CD.CD_SUCCESS : ERR_CD.CD_FAILURE, sRuleResult, sFinalRuleErrMsg); } // Calculate the final outcome of the RuleSet if (RuleResultList.Count > 0) { bRuleSetResult = RuleResultList[0]; foreach (bool bTempRuleResult in RuleResultList) { if (poTargetRuleSet.RulesEvalOperator == RULE_OP.OP_AND) { bRuleSetResult = bRuleSetResult && bTempRuleResult; } else if (poTargetRuleSet.RulesEvalOperator == RULE_OP.OP_OR) { bRuleSetResult = bRuleSetResult || bTempRuleResult; } else { bRuleSetResult = bRuleSetResult && bTempRuleResult; } } } // Only apply the assertive rules if the evaluative rules are applied successfully if (bRuleSetResult && (poTargetRuleSet.AssertiveRules.Count() > 0)) { foreach (WonkaBizRule TempRule in poTargetRuleSet.AssertiveRules) { bool bRuleResult = true; string sRuleResult = string.Empty; string sFinalRuleErrMsg = string.Empty; RuleErrorMsgBuilder.Clear(); bRuleResult = TempRule.Execute(poIncomingProduct, poCurrentProduct, RuleErrorMsgBuilder); RuleResultList.Add(bRuleResult); poRuleSetErrorMessage.Append("SUCCESS"); poRuleTreeReport.ArchiveRuleExecution(TempRule, bRuleResult ? ERR_CD.CD_SUCCESS : ERR_CD.CD_FAILURE, sRuleResult, sFinalRuleErrMsg); } } return(bRuleSetResult); }
/// <summary> /// /// This method helps to direct the navigation of a branch within the RuleTree. If the rules of 'poTargetRuleSet' /// evaluate to a success when applied to the records, then we will continue to traverse the branch by enumerating /// through the child branches that sprout from this node (i.e., by calling this method again recursively). If not, /// we will stop the traversal here and return back to the parent node of 'poTargetRuleSet'. /// /// <param name="poTargetRuleSet">The RuleSet whose rules are being applied against the provided records</param> /// <param name="poIncomingProduct">The incoming Product record</param> /// <param name="poCurrentProduct">The current Product record (i.e., in the database)</param> /// <param name="poRuleTreeReport">The report that will contain all evaluations of RuleSets in the RuleTree</param> /// <returns>Indicates whether or not the RuleSet evaluated to a success</returns> /// </summary> private static bool MediateRuleSetExecution(WonkaBizRuleSet poTargetRuleSet, WonkaProduct poIncomingProduct, WonkaProduct poCurrentProduct, WonkaBizRuleTreeReport poRuleTreeReport) { bool bTotalRuleSetResult = true; bool bTempRulesResult = true; bool bTempRuleSetResult = true; bool bTraverseChildren = true; string sGeneralRuleSetError = "ERROR! One of the rules failed."; StringBuilder RuleSetErrorBuilder = new StringBuilder(); poRuleTreeReport.LastRuleSetExecuted = poTargetRuleSet; /* * GOOD PLACE FOR TESTING * * if (!String.IsNullOrEmpty(poTargetRuleSet.Description)) * { * if (poTargetRuleSet.Description.Contains("Test RuleSet")) * { * int x = 1; * } * } */ bTempRulesResult = MediateRulesExecution(poTargetRuleSet, poIncomingProduct, poCurrentProduct, poRuleTreeReport, RuleSetErrorBuilder); if (bTempRulesResult) { poRuleTreeReport.SetRuleSetStatus(poTargetRuleSet.RuleSetId, poTargetRuleSet.Description, poTargetRuleSet.CustomId, ERR_CD.CD_SUCCESS); } else { poRuleTreeReport.SetRuleSetStatus(poTargetRuleSet.RuleSetId, poTargetRuleSet.Description, poTargetRuleSet.CustomId, ERR_CD.CD_FAILURE); var TargetRuleSetReport = poRuleTreeReport.FindRuleSetReport(poTargetRuleSet.RuleSetId); if ((TargetRuleSetReport.SevereFailureCount > 0) || (TargetRuleSetReport.WarningFailureCount > 0)) { poRuleTreeReport.AddResultSetFailure(poTargetRuleSet, ERR_CD.CD_FAILURE, sGeneralRuleSetError); } bTraverseChildren = false; } if (!bTraverseChildren) { // We should return here, preventing the recursion that will further traverse the branches of the RuleTree return(bTotalRuleSetResult); } foreach (WonkaBizRuleSet ChildRuleSet in poTargetRuleSet.ChildRuleSets) { bTempRuleSetResult = MediateRuleSetExecution(ChildRuleSet, poIncomingProduct, poCurrentProduct, poRuleTreeReport); if (!bTempRuleSetResult) { // NOTE: Currently, this condition will never happen...but at some point, should it? } } return(bTotalRuleSetResult); }