예제 #1
0
        public WonkaProduct GetNewProduct()
        {
            WonkaRefEnvironment WkaRefEnv               = WonkaRefEnvironment.GetInstance();
            WonkaRefAttr        NewSalesTransSeqAttr    = WkaRefEnv.GetAttributeByAttrName("NewSalesTransSeq");
            WonkaRefAttr        NewSaleEANAttr          = WkaRefEnv.GetAttributeByAttrName("NewSaleEAN");
            WonkaRefAttr        NewSaleVATRateDenomAttr = WkaRefEnv.GetAttributeByAttrName("NewSaleVATRateDenom");
            WonkaRefAttr        NewSaleItemTypeAttr     = WkaRefEnv.GetAttributeByAttrName("NewSaleItemType");
            WonkaRefAttr        CountryOfSaleAttr       = WkaRefEnv.GetAttributeByAttrName("CountryOfSale");
            WonkaRefAttr        NewSalePriceAttr        = WkaRefEnv.GetAttributeByAttrName("NewSalePrice");
            WonkaRefAttr        PrevSellTaxAmountAttr   = WkaRefEnv.GetAttributeByAttrName("PrevSellTaxAmount");
            WonkaRefAttr        NewSellTaxAmountAttr    = WkaRefEnv.GetAttributeByAttrName("NewSellTaxAmount");
            WonkaRefAttr        NewVATAmountForHMRCAttr = WkaRefEnv.GetAttributeByAttrName("NewVATAmountForHMRC");

            WonkaProduct NewProduct = new WonkaProduct();

            NewProduct.SetAttribute(NewSalesTransSeqAttr, "123456789");
            NewProduct.SetAttribute(NewSaleEANAttr, "9781234567890");
            NewProduct.SetAttribute(NewSaleVATRateDenomAttr, "2");
            NewProduct.SetAttribute(NewSaleItemTypeAttr, "Widget");
            NewProduct.SetAttribute(CountryOfSaleAttr, "UK");
            NewProduct.SetAttribute(NewSalePriceAttr, "200");
            NewProduct.SetAttribute(PrevSellTaxAmountAttr, "5");
            NewProduct.SetAttribute(NewSellTaxAmountAttr, "0");
            NewProduct.SetAttribute(NewVATAmountForHMRCAttr, "0");

            return(NewProduct);
        }
예제 #2
0
        public void Execute()
        {
            WonkaRefEnvironment RefEnv =
                WonkaRefEnvironment.CreateInstance(false, moMetadataSource);

            WonkaRefAttr AccountStsAttr = RefEnv.GetAttributeByAttrName("AccountStatus");

            WonkaProduct NewProduct = GetNewProduct();

            string sStatusValueBefore = GetAttributeValue(NewProduct, AccountStsAttr);

            /*
             * NOT YET READY
             *
             * // Cue the rules engine
             * WonkaBreRulesEngine RulesEngine =
             *  new WonkaBreRulesEngine(CONST_SIMPLE_RULES_FILEPATH, moMetadataSource);
             *
             * RulesEngine.GetCurrentProductDelegate = GetOldProduct;
             *
             * WonkaBre.Reporting.WonkaBreRuleTreeReport Report = RulesEngine.Validate(NewProduct);
             *
             * string sStatusValueAfter = GetAttributeValue(NewProduct, AccountStsAttr);
             *
             * if (Report.GetRuleSetFailureCount() > 0)
             * {
             *  throw new Exception("Oh heavens to Betsy! Something bad happened!");
             * }
             */
        }
예제 #3
0
        public RuleTreeReport ExecuteWithReport(WonkaBizRulesEngine poRulesEngine, bool pbValidateWithinTransaction)
        {
            WonkaRefEnvironment RefEnv = WonkaRefEnvironment.GetInstance();

            WonkaRefAttr CurrValueAttr  = RefEnv.GetAttributeByAttrName("AccountCurrValue");
            WonkaRefAttr ReviewFlagAttr = RefEnv.GetAttributeByAttrName("AuditReviewFlag");

            Dictionary <string, string> PrdKeys = new Dictionary <string, string>();

            var contract      = GetContract();
            var senderAddress = moEthEngineInit.EthSenderAddress;

            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);

                WonkaProduct OrchContractCurrValues =
                    poRulesEngine.AssembleCurrentProductFromChainSources(new Dictionary <string, string>(), CONST_ONLINE_TEST_CHAIN_URL);

                // Before invoking the RuleTree, the storage contract should have Review Flag as "" and CurrVal as "999"
                string sFlagBeforeOrchestrationAssignment  = RetrieveValueMethod(FlagSource, ReviewFlagAttr.AttrName);
                string sValueBeforeOrchestrationAssignment = RetrieveValueMethod(CurrValSource, CurrValueAttr.AttrName);

                var EthRuleTreeReport = new Wonka.Eth.Extensions.RuleTreeReport();
                poRulesEngine.ExecuteOnChain(moEthEngineInit, EthRuleTreeReport);

                // After invoking the RuleTree, the storage contract should have Review Flag as "???" and CurrVal as "1014"
                string sFlagAfterOrchestrationAssignment  = RetrieveValueMethod(FlagSource, ReviewFlagAttr.AttrName);
                string sValueAfterOrchestrationAssignment = RetrieveValueMethod(CurrValSource, CurrValueAttr.AttrName);

                ruleTreeReport = executeGetLastReportFunction.CallDeserializingToObjectAsync <RuleTreeReport>().Result;
            }
            else
            {
                ruleTreeReport = executeWithReportFunction.CallDeserializingToObjectAsync <RuleTreeReport>(senderAddress).Result;
            }

            return(ruleTreeReport);
        }
        public string RetrieveValueMethod(WonkaBre.RuleTree.WonkaBreSource poTargetSource, string psAttrName)
        {
            WonkaRefEnvironment WkaRefEnv = WonkaRefEnvironment.GetInstance();

            WonkaRefAttr TargetAttr = WkaRefEnv.GetAttributeByAttrName(psAttrName);

            return(moProduct.GetAttributeValue(TargetAttr));
        }
        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;

            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"
                string sFlagBeforeOrchestrationAssignment = await RetrieveValueMethodAsync(FlagSource, ReviewFlagAttr.AttrName).ConfigureAwait(false);

                string sValueBeforeOrchestrationAssignment = await RetrieveValueMethodAsync(CurrValSource, CurrValueAttr.AttrName).ConfigureAwait(false);

                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"
                string sFlagAfterOrchestrationAssignment = await RetrieveValueMethodAsync(FlagSource, ReviewFlagAttr.AttrName).ConfigureAwait(false);

                string sValueAfterOrchestrationAssignment = await RetrieveValueMethodAsync(CurrValSource, CurrValueAttr.AttrName).ConfigureAwait(false);

                ruleTreeReport =
                    await executeGetLastReportFunction.CallDeserializingToObjectAsync <RuleTreeReport>().ConfigureAwait(false);
            }
            else
            {
                ruleTreeReport =
                    await executeWithReportFunction.CallDeserializingToObjectAsync <RuleTreeReport>(senderAddress).ConfigureAwait(false);
            }

            return(ruleTreeReport);
        }
예제 #6
0
        public Dictionary <PropertyInfo, WonkaRefAttr> GetPropertyMap()
        {
            WonkaRefEnvironment RefEnv = WonkaRefEnvironment.GetInstance();

            Dictionary <PropertyInfo, WonkaRefAttr> PropertyMap = new Dictionary <PropertyInfo, WonkaRefAttr>();

            foreach (PropertyInfo Prop in GetProperties())
            {
                if (Prop.Name == "NewSalesTrxSeq")
                {
                    PropertyMap[Prop] = RefEnv.GetAttributeByAttrName("NewSalesTransSeq");
                }
                else if (Prop.Name == "NewSaleVATRateDenom")
                {
                    PropertyMap[Prop] = RefEnv.GetAttributeByAttrName("NewSaleVATRateDenom");
                }
                else if (Prop.Name == "NewSaleItemType")
                {
                    PropertyMap[Prop] = RefEnv.GetAttributeByAttrName("NewSaleItemType");
                }
                else if (Prop.Name == "CountryOfSale")
                {
                    PropertyMap[Prop] = RefEnv.GetAttributeByAttrName("CountryOfSale");
                }
                else if (Prop.Name == "NewSalePrice")
                {
                    PropertyMap[Prop] = RefEnv.GetAttributeByAttrName("NewSalePrice");
                }
                else if (Prop.Name == "PrevSellTaxAmt")
                {
                    PropertyMap[Prop] = RefEnv.GetAttributeByAttrName("PrevSellTaxAmount");
                }
                else if (Prop.Name == "NewSellTaxAmt")
                {
                    PropertyMap[Prop] = RefEnv.GetAttributeByAttrName("NewSellTaxAmount");
                }
                else if (Prop.Name == "NewVATAmtForHMRC")
                {
                    PropertyMap[Prop] = RefEnv.GetAttributeByAttrName("NewVATAmountForHMRC");
                }
                else if (Prop.Name == "NewSaleEAN")
                {
                    PropertyMap[Prop] = RefEnv.GetAttributeByAttrName("NewSaleEAN");
                }
            }

            return(PropertyMap);
        }
예제 #7
0
        public RuleTreeReport ExecuteWithReport(WonkaBreRulesEngine poRulesEngine, bool pbValidateWithinTransaction, WonkaBreSource poFlagSource)
        {
            WonkaRefEnvironment RefEnv = WonkaRefEnvironment.GetInstance();

            WonkaRefAttr CurrValueAttr  = RefEnv.GetAttributeByAttrName("AccountCurrValue");
            WonkaRefAttr ReviewFlagAttr = RefEnv.GetAttributeByAttrName("AuditReviewFlag");

            Dictionary <string, string> PrdKeys = new Dictionary <string, string>();

            var contract = GetContract();

            var executeWithReportFunction = contract.GetFunction(CONST_CONTRACT_FUNCTION_EXEC_RPT);

            RuleTreeReport ruleTreeReport = null;

            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(1000000);

                WonkaProduct OrchContractCurrValues = poRulesEngine.AssembleCurrentProduct(new Dictionary <string, string>());

                string sFlagBeforeOrchestrationAssignment  = RetrieveValueMethod(poFlagSource, ReviewFlagAttr.AttrName);
                string sValueBeforeOrchestrationAssignment = RetrieveValueMethod(poFlagSource, CurrValueAttr.AttrName);

                var receiptAddAttribute = executeWithReportFunction.SendTransactionAsync(msSenderAddress, gas, null, msSenderAddress).Result;

                string sFlagAfterOrchestrationAssignment  = RetrieveValueMethod(poFlagSource, ReviewFlagAttr.AttrName);
                string sValueAfterOrchestrationAssignment = RetrieveValueMethod(poFlagSource, CurrValueAttr.AttrName);

                ruleTreeReport = executeGetLastReportFunction.CallDeserializingToObjectAsync <RuleTreeReport>().Result;
            }
            else
            {
                ruleTreeReport = executeWithReportFunction.CallDeserializingToObjectAsync <RuleTreeReport>(msSenderAddress).Result;
            }

            return(ruleTreeReport);
        }
예제 #8
0
        public Dictionary <PropertyInfo, WonkaRefAttr> GetPropertyMap()
        {
            WonkaRefEnvironment RefEnv = WonkaRefEnvironment.GetInstance();

            Dictionary <PropertyInfo, WonkaRefAttr> PropertyMap = new Dictionary <PropertyInfo, WonkaRefAttr>();

            foreach (PropertyInfo Prop in GetProperties())
            {
                if (Prop.Name == "AccountId")
                {
                    PropertyMap[Prop] = RefEnv.GetAttributeByAttrName("BankAccountID");
                }
                else if (Prop.Name == "AccountName")
                {
                    PropertyMap[Prop] = RefEnv.GetAttributeByAttrName("BankAccountName");
                }
            }

            return(PropertyMap);
        }
예제 #9
0
        private WonkaProduct AssembleProduct(Dictionary <string, string> poAttrData)
        {
            var NewProduct = new Wonka.Product.WonkaProduct();

            foreach (string sTmpAttrName in poAttrData.Keys)
            {
                WonkaRefAttr TargetAttr = refEnvHandle.GetAttributeByAttrName(sTmpAttrName);

                NewProduct.SetAttribute(TargetAttr, poAttrData[sTmpAttrName]);
            }

            return(NewProduct);
        }
예제 #10
0
        public void Execute()
        {
            // Using the metadata source, we create an instance of a defined data domain
            WonkaRefEnvironment RefEnv = WonkaRefEnvironment.GetInstance();

            // To test whether the data domain has been created, we plan on retrieving the value
            // of the "AccountStatus" Attribute
            WonkaRefAttr AccountStsAttr = RefEnv.GetAttributeByAttrName("AccountStatus");

            // Creating an instance of the rules engine using our rules and the metadata
            WonkaBreRulesEngine RulesEngine =
                new WonkaBreRulesEngine(new StringBuilder(msRulesContents), moMetadataSource);

            // Gets a predefined data record that will be our analog for new data coming into the system
            WonkaProduct NewProduct = GetNewProduct();

            // Check that the data has been populated correctly on the "new" record - also, we will use
            // it later for comparison purposes
            string sStatusValueBefore = GetAttributeValue(NewProduct, AccountStsAttr);

            // Since the rules can reference values from different records (like O.Price for the existing
            // record's price and N.Price for the new record's price), we need to provide the delegate
            // that can pull the existing (i.e., old) record from the blockchain using a key
            RulesEngine.GetCurrentProductDelegate = GetOldProduct;

            // Validate the new record using our rules engine and its initialized RuleTree
            WonkaBre.Reporting.WonkaBreRuleTreeReport Report = RulesEngine.Validate(NewProduct);

            // Now retrieve the AccountStatus value and see if the rules have altered it (which should
            // not be the case)
            string sStatusValueAfter = GetAttributeValue(NewProduct, AccountStsAttr);

            // We will evaluate whether or not any failures of the rules were detected during the engine's execution
            if (Report.OverallRuleTreeResult == ERR_CD.CD_SUCCESS)
            {
                // If successful, we will write the record back into the contract on the blockchain
                Serialize(NewProduct);
            }
            else if (Report.GetRuleSetFailureCount() > 0)
            {
                throw new Exception("Oh heavens to Betsy! Something bad happened!");
            }
            else
            {
                throw new Exception("What in the world is happening?!");
            }
        }
예제 #11
0
        public bool Execute()
        {
            // Using the metadata source, we create an instance of a defined data domain
            WonkaRefEnvironment RefEnv = WonkaRefEnvironment.GetInstance();

            // To test whether the data domain has been created, we plan on retrieving the value
            // of the "AccountStatus" Attribute
            WonkaRefAttr AccountStsAttr = RefEnv.GetAttributeByAttrName("AccountStatus");

            // This collection represents the product key(s) for the record being sought - for now,
            // we do not need to specify one
            Dictionary <string, string> PrdKeys = new Dictionary <string, string>();

            // Gets a predefined data record that will be our analog for new data coming into the system
            WonkaProduct NewProduct = GetNewProduct();

            // Check that the data has been populated correctly on the "new" record - also, we will use
            // it later for comparison purposes
            string sStatusValueBefore = GetAttributeValue(NewProduct, AccountStsAttr);

            // Write the product to the contract, which will then be used by the rules engine on the
            // blockchain during the engine's execution
            SerializeProduct(NewProduct);

            /**
            ** Now execute the rules engine on the blockchain.
            **
            ** NOTE: We are only issuing a call() now when we execute the rules engine,
            **       since we are only looking to validate here.  However, there is a chance
            **       that sendTransaction() might be used in the future because we wish for
            **       the rules engine to alter the record.  In that case, we might want to
            **       pull back the record afterwards with a subsequent function call, in order
            **       to examine the record here.
            **/
            bool bProductIsValid = ExecuteRulesEngineOnTheBlockchain();

            // Now we pull back the product from the blockchain
            WonkaProduct ProductOnBlockchain = GetBlockchainRecord(PrdKeys);

            // Now retrieve the AccountStatus value and see if the rules have altered it
            string sStatusValueAfter = GetAttributeValue(NewProduct, AccountStsAttr);

            return(bProductIsValid);
        }
예제 #12
0
        public WonkaSimpleNethereumTest(string psSenderAddress, string psPassword, string psContractAddress)
        {
            msSenderAddress   = psSenderAddress;
            msPassword        = psPassword;
            msContractAddress = psContractAddress;

            // Create an instance of the class that will provide us with PmdRefAttributes (i.e., the data domain)
            // that define our data records
            moMetadataSource = new WonkaMetadataTestSource();

            var TmpAssembly = Assembly.GetExecutingAssembly();

            // Read the ABI of the Ethereum contract which holds our old (i.e., existing) data record
            using (var AbiReader = new StreamReader(TmpAssembly.GetManifestResourceStream("WonkaSystem.TestData.WonkaEngine.abi")))
            {
                msAbiWonka = AbiReader.ReadToEnd();
            }

            // Read the bytecodes of the Ethereum contract which holds our old (i.e., existing) data record
            using (var ByteCodeReader = new StreamReader(TmpAssembly.GetManifestResourceStream("WonkaSystem.TestData.WonkaEngine.bin")))
            {
                msByteCodeWonka = ByteCodeReader.ReadToEnd();
            }

            // Read the XML markup that lists the business rules
            using (var RulesReader = new StreamReader(TmpAssembly.GetManifestResourceStream("WonkaSystem.TestData.SimpleAccountCheck.xml")))
            {
                msRulesContents = RulesReader.ReadToEnd();
            }

            // Using the metadata source, we create an instance of a defined data domain
            WonkaRefEnvironment WonkaRefEnv =
                WonkaRefEnvironment.CreateInstance(false, moMetadataSource);

            WonkaRefAttr AccountIDAttr       = WonkaRefEnv.GetAttributeByAttrName("BankAccountID");
            WonkaRefAttr AccountNameAttr     = WonkaRefEnv.GetAttributeByAttrName("BankAccountName");
            WonkaRefAttr AccountStsAttr      = WonkaRefEnv.GetAttributeByAttrName("AccountStatus");
            WonkaRefAttr AccountCurrValAttr  = WonkaRefEnv.GetAttributeByAttrName("AccountCurrValue");
            WonkaRefAttr AccountTypeAttr     = WonkaRefEnv.GetAttributeByAttrName("AccountType");
            WonkaRefAttr AccountCurrencyAttr = WonkaRefEnv.GetAttributeByAttrName("AccountCurrency");

            // We create a target list of the Attributes of the old (i.e., existing) record that currently exists on the blockchain
            // and which we want to pull back during the engine's execution
            moTargetAttrList = new List <WonkaRefAttr>();

            moTargetAttrList =
                new List <WonkaRefAttr>()
            {
                AccountIDAttr, AccountNameAttr, AccountStsAttr, AccountCurrValAttr, AccountTypeAttr, AccountCurrencyAttr
            };
        }
예제 #13
0
        private void WonkaRibbon_Load(object sender, RibbonUIEventArgs e)
        {
            refEnvHandle =
                WonkaRefEnvironment.CreateInstance(false, metadataSource);

            WonkaRefAttr AccountIDAttr       = refEnvHandle.GetAttributeByAttrName("BankAccountID");
            WonkaRefAttr AccountNameAttr     = refEnvHandle.GetAttributeByAttrName("BankAccountName");
            WonkaRefAttr AccountStsAttr      = refEnvHandle.GetAttributeByAttrName("AccountStatus");
            WonkaRefAttr AccountCurrValAttr  = refEnvHandle.GetAttributeByAttrName("AccountCurrValue");
            WonkaRefAttr AccountTypeAttr     = refEnvHandle.GetAttributeByAttrName("AccountType");
            WonkaRefAttr AccountCurrencyAttr = refEnvHandle.GetAttributeByAttrName("AccountCurrency");
            WonkaRefAttr RvwFlagAttr         = refEnvHandle.GetAttributeByAttrName("AuditReviewFlag");
            WonkaRefAttr CreationDtAttr      = refEnvHandle.GetAttributeByAttrName("CreationDt");

            using (var client = new System.Net.Http.HttpClient())
            {
                wonkaRules = client.GetStringAsync(currRulesUrl).Result;
            }

            rulesEngine =
                new WonkaBizRulesEngine(new StringBuilder(wonkaRules));
        }
예제 #14
0
        public RuleTreeReport ExecuteWithReport()
        {
            WonkaRefEnvironment RefEnv = WonkaRefEnvironment.GetInstance();

            WonkaRefAttr AccountStsAttr = RefEnv.GetAttributeByAttrName("AccountStatus");

            Dictionary <string, string> PrdKeys = new Dictionary <string, string>();

            WonkaProduct NewProduct = GetNewProduct();

            // Write the product to the contract, so that we can validate the product
            // using the ruletree that has already been written to the blockchain
            SerializeProduct(NewProduct);

            var contract = GetContract();

            var executeWithReportFunction = contract.GetFunction(CONST_CONTRACT_FUNCTION_EXEC_RPT);

            var ruleTreeReport = executeWithReportFunction.CallDeserializingToObjectAsync <RuleTreeReport>(msSenderAddress).Result;

            return(ruleTreeReport);
        }
예제 #15
0
        public void Execute()
        {
            // Using the metadata source, we create an instance of a defined data domain
            WonkaRefEnvironment RefEnv =
                WonkaRefEnvironment.CreateInstance(false, moMetadataSource);

            // To test whether the data domain has been created, we pull back one attribute
            WonkaRefAttr AccountStsAttr = RefEnv.GetAttributeByAttrName("AccountStatus");

            // Creating an instance of the rules engine using our rules and the metadata
            WonkaBreRulesEngine RulesEngine =
                new WonkaBreRulesEngine(new StringBuilder(msRulesContents), moMetadataSource);

            // Gets a predefined data record that will be our analog for new data coming into the system
            WonkaProduct NewProduct = GetNewProduct();

            // Check that the data has been populated correctly on the "new" record
            string sStatusValueBefore = GetAttributeValue(NewProduct, AccountStsAttr);

            // Since the rules can reference values from different records (like O.Price for the existing
            // record's price and N.Price for the new record's price), we need to provide the delegate
            // that can pull the existing (i.e., old) record using a key
            RulesEngine.GetCurrentProductDelegate = GetOldProduct;

            // Validate the new record using our rules engine and its initialized RuleTree
            WonkaBre.Reporting.WonkaBreRuleTreeReport Report = RulesEngine.Validate(NewProduct);

            // Now retrieve the AccountStatus value and see if the rules have altered it (which should
            // not be the case)
            string sStatusValueAfter = GetAttributeValue(NewProduct, AccountStsAttr);

            if (Report.GetRuleSetFailureCount() > 0)
            {
                throw new Exception("Oh heavens to Betsy! Something bad happened!");
            }
        }
예제 #16
0
        public WonkaProduct GetNewProduct()
        {
            WonkaRefEnvironment WkaRefEnv           = WonkaRefEnvironment.GetInstance();
            WonkaRefAttr        AccountIDAttr       = WkaRefEnv.GetAttributeByAttrName("BankAccountID");
            WonkaRefAttr        AccountNameAttr     = WkaRefEnv.GetAttributeByAttrName("BankAccountName");
            WonkaRefAttr        AccountStsAttr      = WkaRefEnv.GetAttributeByAttrName("AccountStatus");
            WonkaRefAttr        AccountCurrValAttr  = WkaRefEnv.GetAttributeByAttrName("AccountCurrValue");
            WonkaRefAttr        AccountTypeAttr     = WkaRefEnv.GetAttributeByAttrName("AccountType");
            WonkaRefAttr        AccountCurrencyAttr = WkaRefEnv.GetAttributeByAttrName("AccountCurrency");
            WonkaRefAttr        ReviewFlagAttr      = WkaRefEnv.GetAttributeByAttrName("AuditReviewFlag");

            WonkaProduct NewProduct = new WonkaProduct();

            NewProduct.SetAttribute(AccountIDAttr, "1234567890");
            NewProduct.SetAttribute(AccountNameAttr, "JohnSmithFirstCheckingAccount");
            NewProduct.SetAttribute(AccountStsAttr, "ACT");
            NewProduct.SetAttribute(AccountCurrValAttr, "101.00");
            NewProduct.SetAttribute(AccountCurrencyAttr, "USD");
            NewProduct.SetAttribute(ReviewFlagAttr, "N");
            NewProduct.SetAttribute(AccountTypeAttr, "Checking");
            // NewProduct.SetAttribute(AccountTypeAttr,     "CompletelyBogusTypeThatWillCauseAnError");

            return(NewProduct);
        }
예제 #17
0
        public WonkaProduct GetOldProduct(Dictionary <string, string> poProductKeys)
        {
            WonkaRefEnvironment WkaRefEnv           = WonkaRefEnvironment.GetInstance();
            WonkaRefAttr        AccountIDAttr       = WkaRefEnv.GetAttributeByAttrName("BankAccountID");
            WonkaRefAttr        AccountNameAttr     = WkaRefEnv.GetAttributeByAttrName("BankAccountName");
            WonkaRefAttr        AccountStsAttr      = WkaRefEnv.GetAttributeByAttrName("AccountStatus");
            WonkaRefAttr        AccountCurrValAttr  = WkaRefEnv.GetAttributeByAttrName("AccountCurrValue");
            WonkaRefAttr        AccountTypeAttr     = WkaRefEnv.GetAttributeByAttrName("AccountType");
            WonkaRefAttr        AccountCurrencyAttr = WkaRefEnv.GetAttributeByAttrName("AccountCurrency");

            WonkaProduct OldProduct = new WonkaProduct();

            SetAttribute(OldProduct, AccountIDAttr, "1234567890");
            SetAttribute(OldProduct, AccountNameAttr, "JohnSmithFirstCheckingAccount");
            // SetAttribute(OldProduct, AccountStsAttr,      "ACT");
            SetAttribute(OldProduct, AccountStsAttr, "OOS");
            SetAttribute(OldProduct, AccountCurrValAttr, "100.00");
            SetAttribute(OldProduct, AccountCurrencyAttr, "USD");
            SetAttribute(OldProduct, AccountTypeAttr, "Checking");

            return(OldProduct);
        }
예제 #18
0
        public static void AddNewNethereumRule(this WonkaBizRuleSet poRuleSet,
                                               WonkaRefEnvironment poRefEnv,
                                               string psAddRuleDesc,
                                               string psAddRuleTargetAttr,
                                               string psAddRuleTypeNum,
                                               string psAddRuleEthAddress,
                                               string psAddRuleValue1,
                                               string psAddRuleValue2)
        {
            if (String.IsNullOrEmpty(psAddRuleTypeNum))
            {
                psAddRuleTypeNum = "1";
            }

            int nRuleTypeNum = Int32.Parse(psAddRuleTypeNum);

            WonkaBizRule NewRule = null;

            WonkaRefAttr targetAttr = poRefEnv.GetAttributeByAttrName(psAddRuleTargetAttr);

            if ((nRuleTypeNum == 1) | (nRuleTypeNum == 2) || (nRuleTypeNum == 5))
            {
                if (targetAttr.IsNumeric || targetAttr.IsDecimal)
                {
                    throw new DataException("ERROR!  Cannot perform offered Nethereum rules on a numeric value.");
                }

                if (String.IsNullOrEmpty(psAddRuleEthAddress))
                {
                    psAddRuleEthAddress = BlazorAppNethereumExtensions.CONST_ETH_FNDTN_EOA_ADDRESS;
                }
            }

            if (nRuleTypeNum == 1)
            {
                if (targetAttr.AttrName != "AccountStatus")
                {
                    throw new Exception("ERROR!  Cannot add BALANCE_WITHIN_RANGE rule with any attribute target other than AccountStatus.");
                }

                WonkaBizSource DummySource =
                    new WonkaBizSource("EF_EOA", psAddRuleEthAddress, "", "", "", "", "", null);

                CustomOperatorRule CustomOpRule =
                    new CustomOperatorRule(mnRuleCounter++,
                                           TARGET_RECORD.TRID_NEW_RECORD,
                                           targetAttr.AttrId,
                                           "BALANCE_WITHIN_RANGE",
                                           BlazorAppNethereumExtensions.CheckBalanceIsWithinRange,
                                           DummySource);

                CustomOpRule.AddDomainValue(psAddRuleEthAddress, true, TARGET_RECORD.TRID_NONE);
                CustomOpRule.AddDomainValue(psAddRuleValue1, true, TARGET_RECORD.TRID_NONE);
                CustomOpRule.AddDomainValue(psAddRuleValue2, true, TARGET_RECORD.TRID_NONE);

                NewRule = CustomOpRule;
            }
            else if (nRuleTypeNum == 2)
            {
                if (targetAttr.AttrName != "AuditReviewFlag")
                {
                    throw new Exception("ERROR!  Cannot add ANY_EVENTS_IN_BLOCK_RANGE rule with any attribute target other than AuditReviewFlag.");
                }

                WonkaBizSource DummySource =
                    new WonkaBizSource("ERC20", psAddRuleEthAddress, "", "", "", "", "", null);

                CustomOperatorRule CustomOpRule =
                    new CustomOperatorRule(mnRuleCounter++,
                                           TARGET_RECORD.TRID_NEW_RECORD,
                                           targetAttr.AttrId,
                                           "ANY_EVENTS_IN_BLOCK_RANGE",
                                           BlazorAppNethereumExtensions.AnyEventsInBlockRange,
                                           DummySource);

                if (String.IsNullOrEmpty(psAddRuleValue1))
                {
                    psAddRuleValue1 = "8450678";
                }

                if (String.IsNullOrEmpty(psAddRuleValue2))
                {
                    psAddRuleValue2 = "8450698";
                }

                CustomOpRule.AddDomainValue(psAddRuleEthAddress, true, TARGET_RECORD.TRID_NONE);
                CustomOpRule.AddDomainValue(psAddRuleValue1, true, TARGET_RECORD.TRID_NONE);
                CustomOpRule.AddDomainValue(psAddRuleValue2, true, TARGET_RECORD.TRID_NONE);

                NewRule = CustomOpRule;
            }
            else if (nRuleTypeNum == 3)
            {
                if (!targetAttr.IsNumeric && !targetAttr.IsDecimal)
                {
                    throw new DataException("ERROR!  Cannot perform arithmetic limit on a non-numeric value.");
                }

                WonkaBizSource DummySource =
                    new WonkaBizSource("ERC20", psAddRuleEthAddress, "", "", "", "", "", null);

                CustomOperatorRule CustomOpRule =
                    new CustomOperatorRule(mnRuleCounter++,
                                           TARGET_RECORD.TRID_NEW_RECORD,
                                           targetAttr.AttrId,
                                           "GET_ERC20_BALANCE",
                                           BlazorAppNethereumExtensions.GetERC20Balance,
                                           DummySource);

                CustomOpRule.AddDomainValue(psAddRuleEthAddress, true, TARGET_RECORD.TRID_NONE);
                CustomOpRule.AddDomainValue(psAddRuleValue1, true, TARGET_RECORD.TRID_NONE);

                NewRule = CustomOpRule;
            }
            else if (nRuleTypeNum == 4)
            {
                if (!targetAttr.IsNumeric && !targetAttr.IsDecimal)
                {
                    throw new DataException("ERROR!  Cannot perform arithmetic limit on a non-numeric value.");
                }

                WonkaBizSource DummySource =
                    new WonkaBizSource("ContractName", psAddRuleEthAddress, "", "", "", "", "", null);

                CustomOperatorRule CustomOpRule =
                    new CustomOperatorRule(mnRuleCounter++,
                                           TARGET_RECORD.TRID_NEW_RECORD,
                                           targetAttr.AttrId,
                                           "CALL_SIMPLE_CONTRACT_METHOD",
                                           BlazorAppNethereumExtensions.GetContractSimpleMethodValue,
                                           DummySource);

                var sAltConfigIpfsUrl = psAddRuleValue1;
                var sFunctionName     = psAddRuleValue2;

                if (String.IsNullOrEmpty(sAltConfigIpfsUrl))
                {
                    sAltConfigIpfsUrl = BlazorAppNethereumExtensions.CONST_INFURA_IPFS_GATEWAY_URL + "/QmYDp4ocbF1AVSuY1zBhXa6P4c2oaPkHi2jaSE3HU6bQnQ";
                }

                using (var client = new System.Net.Http.HttpClient())
                {
                    var sConfigDataXml = client.GetStringAsync(sAltConfigIpfsUrl).Result;

                    var configData = ReadConfigXml(sConfigDataXml);

                    if (!String.IsNullOrEmpty(configData.HostUrl))
                    {
                        CustomOpRule.AddDomainValue(configData.HostUrl, true, TARGET_RECORD.TRID_NONE);
                    }
                    else
                    {
                        CustomOpRule.AddDomainValue(BlazorAppNethereumExtensions.CONST_TEST_INFURA_URL, true, TARGET_RECORD.TRID_NONE);
                    }

                    CustomOpRule.AddDomainValue(configData.ContractABI, true, TARGET_RECORD.TRID_NONE);

                    if (!String.IsNullOrEmpty(psAddRuleEthAddress))
                    {
                        CustomOpRule.AddDomainValue(psAddRuleEthAddress, true, TARGET_RECORD.TRID_NONE);
                    }
                    else
                    {
                        CustomOpRule.AddDomainValue(configData.ContractAddress, true, TARGET_RECORD.TRID_NONE);
                    }

                    CustomOpRule.AddDomainValue(sFunctionName, true, TARGET_RECORD.TRID_NONE);

                    NewRule = CustomOpRule;
                }
            }
            else if (nRuleTypeNum == 5)
            {
                if (targetAttr.AttrName != "AccountStatus")
                {
                    throw new Exception("ERROR!  Cannot add V rule with any attribute target other than AccountStatus.");
                }

                WonkaBizSource DummySource =
                    new WonkaBizSource("ContractName", psAddRuleEthAddress, "", "", "", "", "", null);

                CustomOperatorRule CustomOpRule =
                    new CustomOperatorRule(mnRuleCounter++,
                                           TARGET_RECORD.TRID_NEW_RECORD,
                                           targetAttr.AttrId,
                                           "VALIDATE_SIGNATURE",
                                           BlazorAppNethereumExtensions.DetermineStatusByValidatingSignature,
                                           DummySource);

                var sAttrTarget = psAddRuleValue1;
                var sSignature  = psAddRuleValue2;

                var TargetAttr = poRefEnv.GetAttributeByAttrName(sAttrTarget);
                if (TargetAttr == null)
                {
                    throw new Exception("ERROR!  Cannot add rule since attribute(" + sAttrTarget + ") does not exist!");
                }

                CustomOpRule.AddDomainValue(psAddRuleEthAddress, true, TARGET_RECORD.TRID_NONE);
                CustomOpRule.AddDomainValue(sAttrTarget, false, TARGET_RECORD.TRID_NEW_RECORD);
                CustomOpRule.AddDomainValue(sSignature, true, TARGET_RECORD.TRID_NONE);

                NewRule = CustomOpRule;
            }

            if (NewRule != null)
            {
                if (!String.IsNullOrEmpty(psAddRuleDesc))
                {
                    NewRule.DescRuleId = psAddRuleDesc;
                }

                poRuleSet.AddRule(NewRule);
            }
        }
예제 #19
0
        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;
            }

            RulesEngine.SetDefaultStdOps(msPassword);

            // 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?!");
                }
            }
        }
        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);
        }
예제 #21
0
        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?!");
                }
            }
        }
예제 #22
0
        public static void AddNewRule(this WonkaBizRuleSet poRuleSet,
                                      WonkaRefEnvironment poRefEnv,
                                      string psAddRuleDesc,
                                      string psAddRuleTargetAttr,
                                      string psAddRuleTypeNum,
                                      string psAddRuleValue1,
                                      string psAddRuleValue2,
                                      bool pbAddRuleNotOp = false)
        {
            int nRuleTypeNum = Int32.Parse(psAddRuleTypeNum);

            WonkaBizRule NewRule = null;

            WonkaRefAttr targetAttr = poRefEnv.GetAttributeByAttrName(psAddRuleTargetAttr);

            if (nRuleTypeNum == 1)
            {
                if (!targetAttr.IsNumeric && !targetAttr.IsDecimal)
                {
                    throw new DataException("ERROR!  Cannot perform arithmetic limit on a non-numeric value.");
                }

                double dMinVal = 0;
                double dMaxVal = 0;

                Double.TryParse(psAddRuleValue1, out dMinVal);
                Double.TryParse(psAddRuleValue2, out dMaxVal);

                NewRule =
                    new ArithmeticLimitRule(mnRuleCounter++, TARGET_RECORD.TRID_NEW_RECORD, targetAttr.AttrId, dMinVal, dMaxVal);
            }
            else if (nRuleTypeNum == 2)
            {
                /*
                 * NOTE: Will handle ArithmeticRule later
                 * string[] asParamArray = new string[0];
                 */
            }
            else if (nRuleTypeNum == 3)
            {
                if (!String.IsNullOrEmpty(psAddRuleValue1))
                {
                    NewRule =
                        new AssignmentRule(mnRuleCounter++, TARGET_RECORD.TRID_NEW_RECORD, targetAttr.AttrId, psAddRuleValue1);
                }
            }
            else if (nRuleTypeNum == 4)
            {
                /*
                 * NOTE: Will handle CustomOperatorRule later
                 */
            }
            else if (nRuleTypeNum == 5)
            {
                if (!targetAttr.IsDate)
                {
                    throw new DataException("ERROR!  Cannot perform date limit on a non-date value.");
                }

                if ((!String.IsNullOrEmpty(psAddRuleValue1)) || (!String.IsNullOrEmpty(psAddRuleValue2)))
                {
                    DateTime dtMinTime = DateTime.MinValue;
                    DateTime dtMaxTime = DateTime.MaxValue;

                    if (!String.IsNullOrEmpty(psAddRuleValue1))
                    {
                        DateTime.TryParse(psAddRuleValue1, out dtMinTime);
                    }

                    if (!String.IsNullOrEmpty(psAddRuleValue2))
                    {
                        DateTime.TryParse(psAddRuleValue2, out dtMaxTime);
                    }

                    var DtLimitRule =
                        new DateLimitRule(mnRuleCounter++)
                    {
                        MinValue = dtMinTime, MaxValue = dtMaxTime, TargetAttribute = targetAttr
                    };

                    NewRule = DtLimitRule;
                }
            }
            else if (nRuleTypeNum == 6)
            {
                if ((!String.IsNullOrEmpty(psAddRuleValue1)) || (!String.IsNullOrEmpty(psAddRuleValue2)))
                {
                    HashSet <string> RuleDomain = new HashSet <string>();

                    if (!String.IsNullOrEmpty(psAddRuleValue1))
                    {
                        if (psAddRuleValue1.Contains(","))
                        {
                            var DomainVals = psAddRuleValue1.Split(new char[1] {
                                ','
                            });
                            DomainVals.ToList().ForEach(x => DomainVals.Append(x));
                        }
                        else
                        {
                            RuleDomain.Add(psAddRuleValue1);
                        }
                    }

                    if (!String.IsNullOrEmpty(psAddRuleValue2))
                    {
                        if (psAddRuleValue2.Contains(","))
                        {
                            var DomainVals = psAddRuleValue2.Split(new char[1] {
                                ','
                            });
                            DomainVals.ToList().ForEach(x => DomainVals.Append(x));
                        }
                        else
                        {
                            RuleDomain.Add(psAddRuleValue2);
                        }
                    }

                    var DmnRule =
                        new DomainRule(mnRuleCounter++, TARGET_RECORD.TRID_NEW_RECORD, targetAttr.AttrId, false);

                    DmnRule.DomainCache = RuleDomain;

                    foreach (string sTmpValue in RuleDomain)
                    {
                        DmnRule.DomainValueProps.Add(sTmpValue, new WonkaBizRuleValueProps()
                        {
                            IsLiteralValue = true
                        });
                    }

                    NewRule = DmnRule;
                }
            }
            else if (nRuleTypeNum == 7)
            {
                NewRule = new PopulatedRule(mnRuleCounter++, TARGET_RECORD.TRID_NEW_RECORD, targetAttr.AttrId);
            }

            if (NewRule != null)
            {
                if (!String.IsNullOrEmpty(psAddRuleDesc))
                {
                    NewRule.DescRuleId = psAddRuleDesc;
                }

                NewRule.ParentRuleSetId = poRuleSet.RuleSetId;
                NewRule.NotOperator     = pbAddRuleNotOp;

                poRuleSet.AddRule(NewRule);
            }
        }
예제 #23
0
        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);
        }
예제 #24
0
        public WonkaSimpleCustomOpsTest(string psSenderAddress, string psPassword, string psContractAddress, bool pbSerializeMetadataToBlockchain = true)
        {
            msSenderAddress   = psSenderAddress;
            msPassword        = psPassword;
            msContractAddress = psContractAddress;

            // Create an instance of the class that will provide us with PmdRefAttributes (i.e., the data domain)
            // that define our data record
            moMetadataSource = new WonkaMetadataVATSource();

            var TmpAssembly = Assembly.GetExecutingAssembly();

            // Read the ABI of the Ethereum contract for the Wonka rules engine
            using (var AbiReader = new StreamReader(TmpAssembly.GetManifestResourceStream("WonkaSystem.TestData.WonkaEngine.abi")))
            {
                msAbiWonka = AbiReader.ReadToEnd();
            }

            // Read the bytecodes of the Ethereum contract for the Wonka rules engine
            using (var ByteCodeReader = new StreamReader(TmpAssembly.GetManifestResourceStream("WonkaSystem.TestData.WonkaEngine.bin")))
            {
                msByteCodeWonka = ByteCodeReader.ReadToEnd();
            }

            // Read the ABI of the Ethereum contract that will demonstrate both our Custom Operator functionality and our Orchestration functionality
            using (var AbiReader = new StreamReader(TmpAssembly.GetManifestResourceStream("WonkaSystem.TestData.OrchTest.abi")))
            {
                msAbiOrchTest = AbiReader.ReadToEnd();
            }

            // Read the bytecodes of the Ethereum contract that will hold our data record and provide Custom Operator functionality
            using (var ByteCodeReader = new StreamReader(TmpAssembly.GetManifestResourceStream("WonkaSystem.TestData.OrchTest.bin")))
            {
                msByteCodeOrchTest = ByteCodeReader.ReadToEnd();
            }

            // Read the XML markup that lists the business rules
            using (var RulesReader = new StreamReader(TmpAssembly.GetManifestResourceStream("WonkaSystem.TestData.VATCalculationExample.xml")))
            {
                msRulesContents = RulesReader.ReadToEnd();
            }

            // Using the metadata source, we create an instance of a defined data domain
            WonkaRefEnvironment WonkaRefEnv =
                WonkaRefEnvironment.CreateInstance(false, moMetadataSource);

            WonkaRefAttr NewSalesTransSeqAttr    = WonkaRefEnv.GetAttributeByAttrName("NewSalesTransSeq");
            WonkaRefAttr NewSaleVATRateDenomAttr = WonkaRefEnv.GetAttributeByAttrName("NewSaleVATRateDenom");
            WonkaRefAttr NewSaleItemTypeAttr     = WonkaRefEnv.GetAttributeByAttrName("NewSaleItemType");
            WonkaRefAttr CountryOfSaleAttr       = WonkaRefEnv.GetAttributeByAttrName("CountryOfSale");
            WonkaRefAttr NewSalePriceAttr        = WonkaRefEnv.GetAttributeByAttrName("NewSalePrice");
            WonkaRefAttr PrevSellTaxAmountAttr   = WonkaRefEnv.GetAttributeByAttrName("PrevSellTaxAmount");
            WonkaRefAttr NewSellTaxAmountAttr    = WonkaRefEnv.GetAttributeByAttrName("NewSellTaxAmount");
            WonkaRefAttr NewVATAmountForHMRCAttr = WonkaRefEnv.GetAttributeByAttrName("NewVATAmountForHMRC");
            WonkaRefAttr NewSaleEANAttr          = WonkaRefEnv.GetAttributeByAttrName("NewSaleEAN");

            // We create a target list of the Attributes of the old (i.e., existing) record that currently exists on the blockchain
            // and which we want to pull back during the engine's execution
            moTargetAttrList = new List <WonkaRefAttr>();

            moTargetAttrList =
                new List <WonkaRefAttr>()
            {
                NewSalesTransSeqAttr, NewSaleVATRateDenomAttr, NewSaleItemTypeAttr,
                CountryOfSaleAttr, NewSalePriceAttr, PrevSellTaxAmountAttr,
                NewSellTaxAmountAttr, NewVATAmountForHMRCAttr, NewSaleEANAttr
            };

            if (pbSerializeMetadataToBlockchain)
            {
                SerializeMetadataToBlockchain();
            }
        }
예제 #25
0
        public WonkaSimpleOrchestrationTest(string psSenderAddress, string psPassword, string psContractAddress, bool pbSerializeMetadataToBlockchain = true)
        {
            msSenderAddress   = psSenderAddress;
            msPassword        = psPassword;
            msContractAddress = psContractAddress;

            // Create an instance of the class that will provide us with PmdRefAttributes (i.e., the data domain)
            // that define our data record
            moMetadataSource = new WonkaMetadataTestSource();

            var TmpAssembly = Assembly.GetExecutingAssembly();

            // Read the ABI of the Ethereum contract for the Wonka rules engine
            using (var AbiReader = new StreamReader(TmpAssembly.GetManifestResourceStream("WonkaSystem.TestData.WonkaEngine.abi")))
            {
                msAbiWonka = AbiReader.ReadToEnd();
            }

            // Read the bytecodes of the Ethereum contract for the Wonka rules engine
            using (var ByteCodeReader = new StreamReader(TmpAssembly.GetManifestResourceStream("WonkaSystem.TestData.WonkaEngine.bin")))
            {
                msByteCodeWonka = ByteCodeReader.ReadToEnd();
            }

            // Read the ABI of the Ethereum contract that will demonstrate our Orchestration functionality by getting/setting Attribute values
            using (var AbiReader = new StreamReader(TmpAssembly.GetManifestResourceStream("WonkaSystem.TestData.OrchTest.abi")))
            {
                msAbiOrchTest = AbiReader.ReadToEnd();
            }

            // Read the bytecodes of the Ethereum contract that will hold our data record
            using (var ByteCodeReader = new StreamReader(TmpAssembly.GetManifestResourceStream("WonkaSystem.TestData.OrchTest.bin")))
            {
                msByteCodeOrchTest = ByteCodeReader.ReadToEnd();
            }

            // Read the XML markup that lists the business rules
            using (var RulesReader = new StreamReader(TmpAssembly.GetManifestResourceStream("WonkaSystem.TestData.SimpleAccountCheck.xml")))
            {
                msRulesContents = RulesReader.ReadToEnd();
            }

            // Using the metadata source, we create an instance of a defined data domain
            WonkaRefEnvironment WonkaRefEnv =
                WonkaRefEnvironment.CreateInstance(false, moMetadataSource);

            WonkaRefAttr AccountIDAttr       = WonkaRefEnv.GetAttributeByAttrName("BankAccountID");
            WonkaRefAttr AccountNameAttr     = WonkaRefEnv.GetAttributeByAttrName("BankAccountName");
            WonkaRefAttr AccountStsAttr      = WonkaRefEnv.GetAttributeByAttrName("AccountStatus");
            WonkaRefAttr AccountCurrValAttr  = WonkaRefEnv.GetAttributeByAttrName("AccountCurrValue");
            WonkaRefAttr AccountTypeAttr     = WonkaRefEnv.GetAttributeByAttrName("AccountType");
            WonkaRefAttr AccountCurrencyAttr = WonkaRefEnv.GetAttributeByAttrName("AccountCurrency");
            WonkaRefAttr RvwFlagAttr         = WonkaRefEnv.GetAttributeByAttrName("AuditReviewFlag");
            WonkaRefAttr CreationDtAttr      = WonkaRefEnv.GetAttributeByAttrName("CreationDt");

            // We create a target list of the Attributes of the old (i.e., existing) record that currently exists on the blockchain
            // and which we want to pull back during the engine's execution
            moTargetAttrList = new List <WonkaRefAttr>();

            moTargetAttrList =
                new List <WonkaRefAttr>()
            {
                AccountIDAttr, AccountNameAttr, AccountStsAttr, AccountCurrValAttr, AccountTypeAttr, AccountCurrencyAttr, RvwFlagAttr, CreationDtAttr
            };

            // Serialize the data domain to the blockchain
            if (pbSerializeMetadataToBlockchain)
            {
                SerializeMetadataToBlockchain();
            }
        }
예제 #26
0
        public void Execute()
        {
            // Using the metadata source, we create an instance of a defined data domain
            WonkaRefEnvironment RefEnv =
                WonkaRefEnvironment.CreateInstance(false, moMetadataSource);

            var sWeb3Url       = "https://mainnet.infura.io/v3/7238211010344719ad14a89db874158c";
            var sSenderAddress = "0x12890D2cce102216644c59daE5baed380d84830c";
            var sPassword      = "******";
            var sERC20Address  = "0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2";

            // To test whether the data domain has been created, we pull back one attribute
            WonkaRefAttr AccountStsAttr   = RefEnv.GetAttributeByAttrName("AccountStatus");
            WonkaRefAttr AuditRvwFlagAttr = RefEnv.GetAttributeByAttrName("AuditReviewFlag");

            Dictionary <string, WonkaBizSource> SourceMap = new Dictionary <string, WonkaBizSource>();

            /*
             * WonkaBizSource DefaultSource =
             *  new WonkaBizSource(sContractSourceId, msSenderAddress, msPassword, sContractAddress, sContractAbi, sOrchGetterMethod, sOrchSetterMethod, RetrieveValueMethod);
             */

            WonkaBizSource DefaultSource =
                new WonkaBizSource("", "", "", "", null);

            // 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 RefEnv.AttrCache)
            {
                SourceMap[TempAttr.AttrName] = DefaultSource;
            }

            var WonkaEthEngInit =
                new WonkaEthEngineInitialization()
            {
                EthSenderAddress      = sSenderAddress,
                EthPassword           = sPassword,
                ERC20ContractAddress  = sERC20Address,
                ERC721ContractAddress = "",
                Web3HttpUrl           = sWeb3Url
            };

            // Creating an instance of the rules engine using our rules and the metadata
            WonkaBizRulesEngine RulesEngine =
                new WonkaEthRulesEngine(new StringBuilder(msRulesContents), SourceMap, WonkaEthEngInit, moMetadataSource);

            // Gets a predefined data record that will be our analog for new data coming into the system
            WonkaProduct NewProduct = GetNewProduct();

            // Check that the data has been populated correctly on the "new" record
            string sStatusValueBefore = GetAttributeValue(NewProduct, AccountStsAttr);

            // RulesEngine.GetCurrentProductDelegate = GetOldProduct;

            // Validate the new record using our rules engine and its initialized RuleTree
            Wonka.BizRulesEngine.Reporting.WonkaBizRuleTreeReport Report = RulesEngine.Validate(NewProduct);

            // Now retrieve the AccountStatus value and see if the rules have altered it (which should
            // not be the case)
            string sStatusValueAfter  = GetAttributeValue(NewProduct, AccountStsAttr);
            string sAuditRvwFlagAfter = GetAttributeValue(NewProduct, AuditRvwFlagAttr);

            if (Report.GetRuleSetFailureCount() > 0)
            {
                throw new Exception("Oh heavens to Betsy! Something bad happened!");
            }
        }