public async Task <bool> Execute(bool pbValidateTransaction = false) { bool bResult = false; var RefEnv = WonkaRefEnvironment.GetInstance(); var RulesEngine = moEthEngineInit.Engine.RulesEngine; var SourceMap = moEthEngineInit.Engine.SourceMap; WonkaRefAttr AccountStsAttr = RefEnv.GetAttributeByAttrName("AccountStatus"); WonkaRefAttr RvwFlagAttr = RefEnv.GetAttributeByAttrName("AuditReviewFlag"); // Gets a predefined data record that will be our analog for new data coming into the system // We are only using this record to test the .NET implementation WonkaProduct NewProduct = moProduct; string sStatusValueBefore = NewProduct.GetAttributeValue(AccountStsAttr); string sFlagValueBefore = NewProduct.GetAttributeValue(RvwFlagAttr); // Validate that the .NET implementation and the rules markup are both working properly Wonka.BizRulesEngine.Reporting.WonkaBizRuleTreeReport Report = RulesEngine.Validate(NewProduct); string sStatusValueAfter = NewProduct.GetAttributeValue(AccountStsAttr); string sFlagValueAfter = NewProduct.GetAttributeValue(RvwFlagAttr); if (Report.OverallRuleTreeResult == ERR_CD.CD_SUCCESS) { // NOTE: This should only be used for further testing // Serialize(NewProduct); } else if (Report.GetRuleSetFailureCount() > 0) { System.Console.WriteLine(".NET Engine says \"Oh heavens to Betsy! Something bad happened!\""); } else { System.Console.WriteLine(".NET Engine says \"What in the world is happening?\""); } // If a 'psOrchestrationTestAddress' value has been provided, it indicates that the user wishes // to use Orchestration if (!String.IsNullOrEmpty(moEthEngineInit.StorageContractAddress)) { /** ** Now execute the rules engine on the blockchain. ** ** NOTE: Based on the value of the argument 'pbValidateWithinTransaction', we will act accordingly - ** If set to 'true', we issue a call() when we execute the rules engine, since we are only ** looking to validate here. However, if the value if 'false', we issue a sendTransaction() ** so that we can attempts to set values (i.e., change the blockchain) will take effect. ** In that case, we might want to pull back the record afterwards with a subsequent function ** call, in order to examine the record here. ** **/ var BlockchainReport = await ExecuteWithReportAsync(RulesEngine, pbValidateTransaction).ConfigureAwait(false); if (BlockchainReport.NumberOfRuleFailures == 0) { // Indication of a success } else if (BlockchainReport.NumberOfRuleFailures > 0) { throw new Exception("Oh heavens to Betsy! Something bad happened!"); } else { throw new Exception("Seriously, what in the world is happening?!"); } } return(bResult); }
public void Execute(string psOrchestrationTestAddress = null, bool pbValidateWithinTransaction = false) { WonkaRefEnvironment RefEnv = WonkaRefEnvironment.GetInstance(); Dictionary <string, WonkaBizSource> SourceMap = new Dictionary <string, WonkaBizSource>(); string sDefaultSourceId = "S"; string sContractSourceId = sDefaultSourceId; string sContractAddress = ""; string sContractAbi = ""; string sOrchGetterMethod = ""; string sOrchSetterMethod = ""; // These values indicate the Custom Operator "INVOKE_VAT_LOOKUP" which has been used in the markup - // its implementation can be found in the method "lookupVATDenominator" string sCustomOpId = "INVOKE_VAT_LOOKUP"; string sCustomOpMethod = "lookupVATDenominator"; // If a 'psOrchestrationTestAddress' value has been provided, it indicates that the user wishes // to use Orchestration if (!String.IsNullOrEmpty(psOrchestrationTestAddress)) { sContractAddress = psOrchestrationTestAddress; sContractAbi = msAbiOrchTest; sOrchGetterMethod = "getAttrValueBytes32"; sOrchSetterMethod = "setAttrValueBytes32"; } else { sContractAddress = msContractAddress; sContractAbi = msAbiWonka; sOrchGetterMethod = "getValueOnRecord"; sOrchSetterMethod = ""; } WonkaBizSource DefaultSource = new WonkaBizSource(sContractSourceId, msSenderAddress, msPassword, sContractAddress, sContractAbi, sOrchGetterMethod, sOrchSetterMethod, RetrieveValueMethod); // Here a mapping is created, where each Attribute points to a specific contract and its "accessor" methods // - the class that contains this information (contract, accessors, etc.) is of the WonkaBreSource type foreach (WonkaRefAttr TempAttr in moTargetAttrList) { SourceMap[TempAttr.AttrName] = DefaultSource; } Dictionary <string, WonkaBizSource> CustomOpSourceMap = new Dictionary <string, WonkaBizSource>(); // Here a mapping is created, where each Custom Operator points to a specific contract and its "implementation" method // - the class that contains this information (contract, accessors, etc.) is of the WonkaBreSource type WonkaBizSource CustomOpSource = new WonkaBizSource(sCustomOpId, msSenderAddress, msPassword, sContractAddress, sContractAbi, LookupVATDenominator, sCustomOpMethod); CustomOpSourceMap[sCustomOpId] = CustomOpSource; // Creating an instance of the rules engine using our rules and the metadata WonkaBizRulesEngine RulesEngine = new WonkaBizRulesEngine(new StringBuilder(msRulesContents), SourceMap, CustomOpSourceMap, moMetadataSource, false); RulesEngine.DefaultSource = sDefaultSourceId; // The contract dictates that the RuleTree (and its other info, like the Orchestration and CU metadata) // is serialized to the blockchain before interacting with it SerializeRulesEngineToBlockchain(RulesEngine); WonkaRefAttr NewSellTaxAmountAttr = RefEnv.GetAttributeByAttrName("NewSellTaxAmount"); WonkaRefAttr NewVATAmountForHMRCAttr = RefEnv.GetAttributeByAttrName("NewVATAmountForHMRC"); // Gets a predefined data record that will be our analog for new data coming into the system // We are only using this record to test the .NET implementation WonkaProduct NewProduct = GetNewProduct(); string sSellAmtBefore = GetAttributeValue(NewProduct, NewSellTaxAmountAttr); string sVATAmtBefore = GetAttributeValue(NewProduct, NewVATAmountForHMRCAttr); /** ** Test the .NET side */ Wonka.BizRulesEngine.Reporting.WonkaBizRuleTreeReport Report = RulesEngine.Validate(NewProduct); string sSellAmtAfter = GetAttributeValue(NewProduct, NewSellTaxAmountAttr); string sVATAmtAfter = GetAttributeValue(NewProduct, NewVATAmountForHMRCAttr); if (Report.OverallRuleTreeResult == ERR_CD.CD_SUCCESS) { // NOTE: This should only be used for further testing // Serialize(NewProduct); } else if (Report.GetRuleSetFailureCount() > 0) { System.Console.WriteLine(".NET Engine says \"Oh heavens to Betsy! Something bad happened!\""); } else { System.Console.WriteLine(".NET Engine says \"What in the world is happening?\""); } // If a 'psOrchestrationTestAddress' value has been provided, it indicates that the user wishes // to use Orchestration if (!String.IsNullOrEmpty(psOrchestrationTestAddress)) { /** ** Now execute the rules engine on the blockchain, using both Orchestration to call accessors ** on other contract(s) and Custom Operators to invoke the "INVOKE_VAT_LOOKUP" operator ** (i.e., the "lookupVATDenominator()" method) implemented on a contract. ** ** NOTE: Based on the value of the argument 'pbValidateWithinTransaction', we will act accordingly - ** If set to 'true', we issue a call() when we execute the rules engine, since we are only ** looking to validate here. However, if the value if 'false', we issue a sendTransaction() ** so that we can attempts to set values (i.e., change the blockchain) will take effect. ** In that case, we might want to pull back the record afterwards with a subsequent function ** call, in order to examine the record here. ** **/ var BlockchainReport = ExecuteWithReport(RulesEngine, pbValidateWithinTransaction, SourceMap[NewSellTaxAmountAttr.AttrName], psOrchestrationTestAddress); if (BlockchainReport.NumberOfRuleFailures == 0) { // Indication of a success } else if (BlockchainReport.NumberOfRuleFailures > 0) { throw new Exception("Oh heavens to Betsy! Something bad happened!"); } else { throw new Exception("Seriously, what in the world is happening?!"); } } }
public RuleTreeReport ExecuteWithReport(WonkaBizRulesEngine poRulesEngine, bool pbValidateWithinTransaction, WonkaBizSource poSource, string psOrchestrationAddress) { WonkaRefEnvironment RefEnv = WonkaRefEnvironment.GetInstance(); WonkaRefAttr NewSellTaxAmountAttr = RefEnv.GetAttributeByAttrName("NewSellTaxAmount"); WonkaRefAttr NewVATAmountForHMRCAttr = RefEnv.GetAttributeByAttrName("NewVATAmountForHMRC"); WonkaRefAttr NewSalesTransSeqAttr = RefEnv.GetAttributeByAttrName("NewSalesTransSeq"); WonkaRefAttr NewSaleVATRateDenomAttr = RefEnv.GetAttributeByAttrName("NewSaleVATRateDenom"); WonkaRefAttr PrevSellTaxAmtAttr = RefEnv.GetAttributeByAttrName("PrevSellTaxAmount"); WonkaRefAttr NewSaleItemTypeAttr = RefEnv.GetAttributeByAttrName("NewSaleItemType"); WonkaRefAttr CountryOfSaleAttr = RefEnv.GetAttributeByAttrName("CountryOfSale"); bool bTestLookupMethod = true; Dictionary <string, string> PrdKeys = new Dictionary <string, string>(); var contract = GetContract(); var executeWithReportFunction = contract.GetFunction(CONST_CONTRACT_FUNCTION_EXEC_RPT); RuleTreeReport ruleTreeReport = null; if (bTestLookupMethod) { var contractOrchTest = GetContractOrchTest(psOrchestrationAddress); var gas = new Nethereum.Hex.HexTypes.HexBigInteger(1000000); var executeLookupFunction = contractOrchTest.GetFunction("lookupVATDenominator"); var lookupValue = executeLookupFunction.CallAsync <string>("Widget", "UK", "", "").Result; var getValOnRecordFunction = contract.GetFunction("getValueOnRecord"); var attrVal = getValOnRecordFunction.CallAsync <string>(poSource.SenderAddress, "NewSaleItemType").Result; } if (pbValidateWithinTransaction) { var executeGetLastReportFunction = contract.GetFunction(CONST_CONTRACT_FUNCTION_GET_LAST_RPT); // NOTE: Caused exception to be thrown // var gas = executeWithReportFunction.EstimateGasAsync(msSenderAddress).Result; var gas = new Nethereum.Hex.HexTypes.HexBigInteger(2000000); WonkaProduct OrchContractCurrValues = poRulesEngine.AssembleCurrentProduct(new Dictionary <string, string>()); string sNSTABeforeOrchestrationAssignment = RetrieveValueMethod(poSource, NewSellTaxAmountAttr.AttrName); string sNVABeforeOrchestrationAssignment = RetrieveValueMethod(poSource, NewVATAmountForHMRCAttr.AttrName); string sNSTSBeforeOrchestrationAssignment = RetrieveValueMethod(poSource, NewSalesTransSeqAttr.AttrName); string sNSVRDBeforeOrchestrationAssignment = RetrieveValueMethod(poSource, NewSaleVATRateDenomAttr.AttrName); string sPSTABeforeOrchestrationAssignment = RetrieveValueMethod(poSource, PrevSellTaxAmtAttr.AttrName); string sNSITDBeforeOrchestrationAssignment = RetrieveValueMethod(poSource, NewSaleItemTypeAttr.AttrName); string sCoSBeforeOrchestrationAssignment = RetrieveValueMethod(poSource, CountryOfSaleAttr.AttrName); var receiptAddAttribute = executeWithReportFunction.SendTransactionAsync(msSenderAddress, gas, null, msSenderAddress).Result; string sNSTAfterOrchestrationAssignment = RetrieveValueMethod(poSource, NewSellTaxAmountAttr.AttrName); string sNVAAfterOrchestrationAssignment = RetrieveValueMethod(poSource, NewVATAmountForHMRCAttr.AttrName); string sNSTSAfterOrchestrationAssignment = RetrieveValueMethod(poSource, NewSalesTransSeqAttr.AttrName); string sNSVRDAfterOrchestrationAssignment = RetrieveValueMethod(poSource, NewSaleVATRateDenomAttr.AttrName); string sPSTAAfterOrchestrationAssignment = RetrieveValueMethod(poSource, PrevSellTaxAmtAttr.AttrName); string sNSITDAfterOrchestrationAssignment = RetrieveValueMethod(poSource, NewSaleItemTypeAttr.AttrName); string sCoSAfterOrchestrationAssignment = RetrieveValueMethod(poSource, CountryOfSaleAttr.AttrName); ruleTreeReport = executeGetLastReportFunction.CallDeserializingToObjectAsync <RuleTreeReport>().Result; } else { ruleTreeReport = executeWithReportFunction.CallDeserializingToObjectAsync <RuleTreeReport>(msSenderAddress).Result; } return(ruleTreeReport); }
public async Task <RuleTreeReport> ExecuteWithReportAsync(WonkaBizRulesEngine poRulesEngine, bool pbValidateWithinTransaction) { WonkaRefEnvironment RefEnv = WonkaRefEnvironment.GetInstance(); WonkaRefAttr CurrValueAttr = RefEnv.GetAttributeByAttrName("AccountCurrValue"); WonkaRefAttr ReviewFlagAttr = RefEnv.GetAttributeByAttrName("AuditReviewFlag"); var contract = GetContract(); var senderAddress = moEthEngineInit.EthSenderAddress; string sFlagBeforeOrchestrationAssignment = ""; string sValueBeforeOrchestrationAssignment = ""; string sFlagAfterOrchestrationAssignment = ""; string sValueAfterOrchestrationAssignment = ""; var executeWithReportFunction = contract.GetFunction(CONST_CONTRACT_FUNCTION_EXEC_RPT); RuleTreeReport ruleTreeReport = null; if (pbValidateWithinTransaction) { var FlagSource = poRulesEngine.SourceMap[ReviewFlagAttr.AttrName]; var CurrValSource = poRulesEngine.SourceMap[CurrValueAttr.AttrName]; var executeGetLastReportFunction = contract.GetFunction(CONST_CONTRACT_FUNCTION_GET_LAST_RPT); // Before invoking the RuleTree, the storage contract should have Review Flag as "" and CurrVal as "999" sFlagBeforeOrchestrationAssignment = await RetrieveValueMethodAsync(FlagSource, ReviewFlagAttr.AttrName).ConfigureAwait(false); sValueBeforeOrchestrationAssignment = await RetrieveValueMethodAsync(CurrValSource, CurrValueAttr.AttrName).ConfigureAwait(false); System.Console.WriteLine("ExecuteWithReportAsync() -> Flag Before Assignment : (" + sFlagBeforeOrchestrationAssignment + ")"); System.Console.WriteLine("ExecuteWithReportAsync() -> Value Before Assignment : (" + sValueBeforeOrchestrationAssignment + ")"); var EthRuleTreeReport = new Wonka.Eth.Extensions.RuleTreeReport(); await poRulesEngine.ExecuteOnChainAsync(moEthEngineInit, EthRuleTreeReport).ConfigureAwait(false); // After invoking the RuleTree, the storage contract should have Review Flag as "???" and CurrVal as "1014" sFlagAfterOrchestrationAssignment = await RetrieveValueMethodAsync(FlagSource, ReviewFlagAttr.AttrName).ConfigureAwait(false); sValueAfterOrchestrationAssignment = await RetrieveValueMethodAsync(CurrValSource, CurrValueAttr.AttrName).ConfigureAwait(false); System.Console.WriteLine("ExecuteWithReportAsync() -> Flag After Assignment : (" + sFlagAfterOrchestrationAssignment + ")"); System.Console.WriteLine("ExecuteWithReportAsync() -> Value After Assignment : (" + sValueAfterOrchestrationAssignment + ")"); ruleTreeReport = await executeGetLastReportFunction.CallDeserializingToObjectAsync <RuleTreeReport>().ConfigureAwait(false); System.Console.WriteLine("ExecuteWithReportAsync() -> Flag After Assignment : (" + sFlagAfterOrchestrationAssignment + ")"); System.Console.WriteLine("ExecuteWithReportAsync() -> Value After Assignment : (" + sValueAfterOrchestrationAssignment + ")"); if (!String.IsNullOrEmpty(moEthEngineInit.ChronoLogContractAddress)) { var report = new Wonka.Eth.Extensions.RuleTreeReport() { NumberOfRuleFailures = ruleTreeReport.NumberOfRuleFailures , RuleIds = ruleTreeReport.RuleIds , RuleSetIds = ruleTreeReport.RuleSetIds }; var ChronoLogId = await poRulesEngine.StoreWonkaResultsAsync(moEthEngineInit , moProduct , report , CONST_INFURA_IPFS_GATEWAY_URL , CONST_INFURA_IPFS_WRITE_GATEWAY_URL , moEthEngineInit.ChronoLogContractAddress); } } else { ruleTreeReport = await executeWithReportFunction.CallDeserializingToObjectAsync <RuleTreeReport>(senderAddress).ConfigureAwait(false); } return(ruleTreeReport); }
/// <summary> /// /// This method will apply the arithmetic limit rule to either the incoming record or the current (i.e., database) /// record, using the other record as a reference. /// /// <param name="poTransactionRecord">The incoming record</param> /// <param name="poCurrentRecord">The current record (i.e., the already existing record)</param> /// <param name="poErrorMessage">The buffer that will contain an error message if the rule fails</param> /// <returns>Indicates whether or not the target product passed the rule successfully</returns> /// </summary> public override bool Execute(WonkaProduct poTransactionRecord, WonkaProduct poCurrentRecord, StringBuilder poErrorMessage) { bool bResult = false; WonkaProduct TargetRecord = null; WonkaRefEnvironment WonkaRefEnv = WonkaRefEnvironment.GetInstance(); if (RecordOfInterest == TARGET_RECORD.TRID_NEW_RECORD) { TargetRecord = poTransactionRecord; } else if (RecordOfInterest == TARGET_RECORD.TRID_OLD_RECORD) { TargetRecord = poCurrentRecord; } else { throw new Exception("ERROR! The target record is none!"); } string sTargetData = TargetRecord.GetPrimaryAttributeData(TargetAttribute.GroupId, TargetAttribute.AttrId); if (!string.IsNullOrEmpty(sTargetData)) { RefreshMinAndMax(poTransactionRecord, poCurrentRecord); try { double dTargetValue = Convert.ToDouble(sTargetData); if ((this.MaxValue >= dTargetValue) && (dTargetValue >= this.MinValue)) { bResult = true; } else { bResult = false; } if (poErrorMessage != null) { poErrorMessage.Clear(); poErrorMessage.Append(GetVerboseError(TargetRecord)); } } catch (Exception ex) { bResult = false; if (poErrorMessage != null) { poErrorMessage.Clear(); poErrorMessage.Append(ex.ToString()); } } } return(bResult); }
/// <summary> /// /// This method will apply the assignment rule to either the transaction record or the current (i.e., database) /// record, using the other record as a reference. /// /// <param name="poTransactionRecord">The incoming record</param> /// <param name="poCurrentRecord">The current record (i.e., in the database)</param> /// <param name="poErrorMessage">The buffer that will contain an error message if the rule fails</param> /// <returns>Indicates whether or not the target product passed the rule successfully</returns> /// </summary> public override bool Execute(WonkaProduct poTransactionRecord, WonkaProduct poCurrentRecord, StringBuilder poErrorMessage) { bool bResult = false; bool bAssignValue = true; int nAttrId = TargetAttribute.AttrId; int nGroupId = TargetAttribute.GroupId; WonkaProduct TargetRecord = null; WonkaRefEnvironment WonkaRefEnv = WonkaRefEnvironment.GetInstance(); if (poTransactionRecord == null) { throw new Exception("ERROR! The new Product is null."); } if (poCurrentRecord == null) { throw new Exception("ERROR! The old Product is null."); } if (RecordOfInterest == TARGET_RECORD.TRID_NEW_RECORD) { TargetRecord = poTransactionRecord; } else if (RecordOfInterest == TARGET_RECORD.TRID_OLD_RECORD) { TargetRecord = poCurrentRecord; } else { throw new Exception("ERROR! The target record is none!"); } if (DefaultAssignment) { WonkaPrdGroup TempProductGroup = null; if (RecordOfInterest == TARGET_RECORD.TRID_NEW_RECORD) { TempProductGroup = poTransactionRecord.GetProductGroup(nGroupId); } else { TempProductGroup = poCurrentRecord.GetProductGroup(nGroupId); } string sCurrentValue = ""; if (TempProductGroup.GetRowCount() > 0) { if (TempProductGroup[0].ContainsKey(nAttrId)) { sCurrentValue = TempProductGroup[0][nAttrId]; } } if (!String.IsNullOrEmpty(sCurrentValue)) { bAssignValue = false; } } if (bAssignValue) { RefreshAssignValue(poTransactionRecord, poCurrentRecord); WonkaPrdGroup TempProductGroup = null; if (RecordOfInterest == TARGET_RECORD.TRID_NEW_RECORD) { TempProductGroup = poTransactionRecord.GetProductGroup(nGroupId); } else { TempProductGroup = poCurrentRecord.GetProductGroup(nGroupId); } TempProductGroup[0][nAttrId] = AssignValue; } return(bResult); }
/// <summary> /// /// This method will iterate through all of the data in the contained groups and detect whether /// any of them are not valid according to the designated type for that Attribute. /// /// <param name="poErrors">The list to which we will add any errors concerning the validation of types</param> /// <returns>Indicates whether or not there any errors with validating types</returns> /// </summary> public bool ValidateTypes(List <WonkaProductError> poErrors) { WonkaRefEnvironment RefEnv = WonkaRefEnvironment.GetInstance(); bool bResult = true; foreach (int nGrpId in this.ProductGroups.Keys) { WonkaPrdGroup TempGroup = ProductGroups[nGrpId]; foreach (WonkaPrdGroupDataRow TempDataRow in TempGroup) { foreach (int nAttrId in TempDataRow.Keys) { string sAttrValue = TempDataRow[nAttrId]; if (!String.IsNullOrEmpty(sAttrValue)) { WonkaRefAttr TempAttr = RefEnv.GetAttributeByAttrId(nAttrId); if (TempAttr.IsDecimal) { try { Decimal dValue = Convert.ToDecimal(sAttrValue); } catch (Exception ex) { poErrors.Add(new WonkaProductError() { AttrName = TempAttr.AttrName, ErrorMessage = "ERROR! Value(" + sAttrValue + ") is not a valid decimal!" }); } } else if (TempAttr.IsNumeric) { try { long nValue = Convert.ToInt64(sAttrValue); } catch (Exception ex) { poErrors.Add(new WonkaProductError() { AttrName = TempAttr.AttrName, ErrorMessage = "ERROR! Value(" + sAttrValue + ") is not a valid number!" }); } } else if (TempAttr.IsDate) { try { DateTime dtValue = DateTime.Parse(sAttrValue); } catch (Exception ex) { poErrors.Add(new WonkaProductError() { AttrName = TempAttr.AttrName, ErrorMessage = "ERROR! Value(" + sAttrValue + ") is not a valid date!" }); } } } } } } return(bResult); }
public void Execute(string psOrchestrationTestAddress = null, bool pbValidateWithinTransaction = false) { WonkaRefEnvironment RefEnv = WonkaRefEnvironment.GetInstance(); Dictionary <string, WonkaBre.RuleTree.WonkaBreSource> SourceMap = new Dictionary <string, WonkaBre.RuleTree.WonkaBreSource>(); string sDefaultSource = "S"; string sContractSourceId = sDefaultSource; string sContractAddress = ""; string sContractAbi = ""; string sOrchGetterMethod = ""; string sOrchSetterMethod = ""; // If a 'psOrchestrationTestAddress' value has been provided, it indicates that the user wishes // to use Orchestration if (!String.IsNullOrEmpty(psOrchestrationTestAddress)) { // Here we set the values for Orchestration (like the target contract) and the implemented // methods that have the expected function signatures for getting/setting Attribute values sContractAddress = psOrchestrationTestAddress; sContractAbi = msAbiOrchTest; sOrchGetterMethod = "getAttrValueBytes32"; sOrchSetterMethod = "setAttrValueBytes32"; } else { sContractAddress = msContractAddress; sContractAbi = msAbiWonka; sOrchGetterMethod = "getValueOnRecord"; sOrchSetterMethod = ""; } // Here a mapping is created, where each Attribute points to a specific contract and its "accessor" methods // - the class that contains this information (contract, accessors, etc.) is of the WonkaBreSource type foreach (WonkaRefAttr TempAttr in moTargetAttrList) { WonkaBreSource TempSource = new WonkaBreSource(sContractSourceId, msSenderAddress, msPassword, sContractAddress, sContractAbi, sOrchGetterMethod, sOrchSetterMethod, RetrieveValueMethod); SourceMap[TempAttr.AttrName] = TempSource; } // Creating an instance of the rules engine using our rules and the metadata WonkaBreRulesEngine RulesEngine = null; if (psOrchestrationTestAddress == null) { RulesEngine = new WonkaBreRulesEngine(new StringBuilder(msRulesContents), moMetadataSource); } else { RulesEngine = new WonkaBreRulesEngine(new StringBuilder(msRulesContents), SourceMap, moMetadataSource); RulesEngine.DefaultSource = sDefaultSource; } // The contract dictates that the RuleTree (and its other info, like the Source mapping) is serialized // to the blockchain before interacting with it SerializeRulesEngineToBlockchain(RulesEngine); WonkaRefAttr AccountStsAttr = RefEnv.GetAttributeByAttrName("AccountStatus"); WonkaRefAttr RvwFlagAttr = RefEnv.GetAttributeByAttrName("AuditReviewFlag"); // Gets a predefined data record that will be our analog for new data coming into the system // We are only using this record to test the .NET implementation WonkaProduct NewProduct = GetNewProduct(); string sStatusValueBefore = GetAttributeValue(NewProduct, AccountStsAttr); string sFlagValueBefore = GetAttributeValue(NewProduct, RvwFlagAttr); // SerializeProductToBlockchain(NewProduct); // Validate that the .NET implementation and the rules markup are both working properly WonkaBre.Reporting.WonkaBreRuleTreeReport Report = RulesEngine.Validate(NewProduct); string sStatusValueAfter = GetAttributeValue(NewProduct, AccountStsAttr); string sFlagValueAfter = GetAttributeValue(NewProduct, RvwFlagAttr); if (Report.OverallRuleTreeResult == ERR_CD.CD_SUCCESS) { // NOTE: This should only be used for further testing // Serialize(NewProduct); } else if (Report.GetRuleSetFailureCount() > 0) { System.Console.WriteLine(".NET Engine says \"Oh heavens to Betsy! Something bad happened!\""); } else { System.Console.WriteLine(".NET Engine says \"What in the world is happening?\""); } // If a 'psOrchestrationTestAddress' value has been provided, it indicates that the user wishes // to use Orchestration if (!String.IsNullOrEmpty(psOrchestrationTestAddress)) { /** ** Now execute the rules engine on the blockchain. ** ** NOTE: Based on the value of the argument 'pbValidateWithinTransaction', we will act accordingly - ** If set to 'true', we issue a call() when we execute the rules engine, since we are only ** looking to validate here. However, if the value if 'false', we issue a sendTransaction() ** so that we can attempts to set values (i.e., change the blockchain) will take effect. ** In that case, we might want to pull back the record afterwards with a subsequent function ** call, in order to examine the record here. ** **/ var BlockchainReport = ExecuteWithReport(RulesEngine, pbValidateWithinTransaction, SourceMap[RvwFlagAttr.AttrName]); if (BlockchainReport.NumberOfRuleFailures == 0) { // Indication of a success } else if (BlockchainReport.NumberOfRuleFailures > 0) { throw new Exception("Oh heavens to Betsy! Something bad happened!"); } else { throw new Exception("Seriously, what in the world is happening?!"); } } }