/// <summary> Protected constructor to allow for data structure population /// * /// </summary> /// <param name="aId">The UID of the RuleResult /// </param> /// <param name="aFactory">The RuleFactory that create the RuleResult /// </param> /// <param name="aParams">A Map of the parameters /// </param> /// <param name="aStackLoc">The location on the stack of this RuleResult /// </param> /// <param name="aStep">The step within the rule /// /// </param> protected internal AbstractBRERuleMetaData(object aId, IBRERuleFactory aFactory, Hashtable aParams, int aStackLoc, object aStep) { id = aId; factory = aFactory; params_Renamed = aParams; stackLoc = aStackLoc; step = aStep; }
/// <summary> Protected constructor to allow for data structure population /// * /// </summary> /// <param name="aId">The UID of the RuleResult /// </param> /// <param name="aFactory">The RuleFactory that create the RuleResult /// </param> /// <param name="aParams">An IDictionary of the parameters /// </param> /// <param name="aStackLoc">The location on the stack of this RuleResult /// </param> /// <param name="aStep">The step within the rule /// /// </param> protected internal AbstractBRERuleMetaData(object aId, IBRERuleFactory aFactory, IDictionary aParams, int aStackLoc, object aStep) { id = aId; factory = aFactory; params_Renamed = aParams; stackLoc = aStackLoc; step = aStep; }
/// <summary> This method preloads all defined factories with the XML document. /// This is to catch any errors relating to class loading up front before we /// get to the real document parsing and business logic. /// <P> /// This does not support graceful degradation on purpose. /// If I can't get to a business rule, it should be understood /// that technically, in the end, the rules fail. /// </P> /// </summary> /// <param name="aNodeList">The List of Nodes to process /// </param> /// <returns> True if successful, False otherwise /// /// </returns> private bool LoadFactories(XPathNodeIterator aNodeList) { if (Logger.IsInferenceEngineInformation) { Logger.FlowEngineSource.TraceEvent(TraceEventType.Information, 0, "BRE Loading RuleFactories..."); } if (aNodeList != null) { try { while (aNodeList.MoveNext()) { string factory = aNodeList.Current.GetAttribute(RULE_ATTRS.FACTORY, String.Empty); if (factory != String.Empty) { string id = aNodeList.Current.GetAttribute(RULE_ATTRS.ID, String.Empty); if (Logger.IsFlowEngineVerbose) { Logger.FlowEngineSource.TraceEvent(TraceEventType.Verbose, 0, "Found Factory: " + factory + " Id: " + id); } if (Logger.IsFlowEngineVerbose) { Logger.FlowEngineSource.TraceEvent(TraceEventType.Verbose, 0, "Loading Factory: " + id); } object tmpClass = Reflection.ClassNew(factory, null); if (tmpClass is IBRERuleFactory) { IBRERuleFactory brf = (IBRERuleFactory)tmpClass; ruleContext.SetFactory(id, brf); if (Logger.IsFlowEngineVerbose) { Logger.FlowEngineSource.TraceEvent(TraceEventType.Verbose, 0, "BRE RuleFactory " + id + " loaded and added to RuleContext"); } } else { throw new BREException("Specified Rule Factory " + factory + " with id " + id + " not of type IBRERuleFactory"); } } } return(true); } catch (System.Exception e) { if (Logger.IsFlowEngineCritical) { Logger.FlowEngineSource.TraceData(TraceEventType.Critical, 0, e); } } } return(false); }
/// <summary> Sets a RuleFactory /// * /// </summary> /// <param name="aId">The UID of the RuleFactory /// </param> /// <param name="aFactory">The Factory /// /// </param> public virtual void SetFactory(object aId, IBRERuleFactory aFactory) { if (factories != null) { if (factories.Contains(aId)) { factories.Remove(aId); } factories.Add(aId, aFactory); } }
/// <summary> This method preloads all defined factories with the XML document. /// This is to catch any errors relating to class loading up front before we /// get to the real document parsing and business logic. /// <P> /// This does not support graceful degradation on purpose. /// If I can't get to a business rule, it should be understood /// that technically, in the end, the rules fail. /// </P> /// </summary> /// <param name="aNodeList">The List of Nodes to process /// </param> /// <returns> True if successful, False otherwise /// /// </returns> private bool LoadFactories(XPathNodeIterator aNodeList) { DispatchLog("BRE Loading RuleFactories...", LogEventImpl.INFO); if (aNodeList != null) { try { while (aNodeList.MoveNext()) { string factory = aNodeList.Current.GetAttribute(RULE_ATTRS.FACTORY, String.Empty); if (factory != String.Empty) { string id = aNodeList.Current.GetAttribute(RULE_ATTRS.ID, String.Empty); DispatchLog("Found Factory: " + factory + " Id: " + id, LogEventImpl.DEBUG); DispatchLog("Loading Factory: " + id, LogEventImpl.DEBUG); object tmpClass = Assembly.GetExecutingAssembly().CreateInstance(factory); if (tmpClass is IBRERuleFactory) { IBRERuleFactory brf = (IBRERuleFactory)tmpClass; ruleContext.SetFactory(id, brf); DispatchLog("BRE RuleFactory " + id + " loaded and added to RuleContext.", LogEventImpl.DEBUG); } else { throw new System.InvalidCastException("Specified Rule Factory " + factory + " with id " + id + " not of type BRERuleFactory"); } } } return(true); } catch (System.Exception e) { DispatchException(e, ExceptionEventImpl.FATAL); } } return(false); }
/// <summary> Creates a new instance of the object /// <P> /// This constructor makes a call to a protected constructor /// within AbstractBRERuleContext. This is another reason /// why this class in final, because this technically breaks /// encapsulation. For more info see:</P><P> /// <I>Effective Java</I> (first printing) by Joshua Bloch. /// Item 14, pg. 71 /// </P> /// * /// </summary> /// <param name="aId">The UID of the RuleResult /// </param> /// <param name="aFactory">The RuleFactory that create the RuleResult /// </param> /// <param name="aParams">A Map of the parameters /// </param> /// <param name="aStackLoc">The location on the stack of this RuleResult /// </param> /// <param name="aStep">The step within the rule /// /// </param> public BRERuleMetaDataImpl(object aId, IBRERuleFactory aFactory, Hashtable aParams, int aStackLoc, object aStep) : base(aId, aFactory, aParams, aStackLoc, aStep) { }
/// <summary> This methods processes the Rule nodes that may exist in the XML. /// <P> /// It executes as follows (this may not look so straightforward in the code...): /// <OL> /// <LI>Executes Factories executeRule()</LI> /// <LI>takes the result and puts it into a RuleResult object</LI> /// <LI>listeners.dispatches an error if it could not find the factory /// (See docs in code)</LI> /// <LI>Catches any exceptions from the executeRule() and makes it a /// RuleResult so it can be handled gracefully</LI> /// <LI>Adds the RuleResult to the CallStack</LI> /// <LI>listeners.dispatched the RuleResult to any listeners</LI> /// <LI>Adds the RuleResult to the RuleContext</LI> /// </OL> /// </P> /// </summary> /// <param name="id">The ID of the Rule /// </param> /// <param name="step">The current Step /// </param> /// <param name="aMap">The Parameters map /// </param> private void DoRule(object id, object step, Hashtable aMap) { int nextStackLoc = ruleContext.CallStack.Count; IBRERuleResult ruleResult = null; try { IBRERuleFactory factory = ruleContext.GetFactory(id); /* * I have to check for null because if the RuleContext * was passed in, an external reference exists and can be * modified at any time */ if (factory != null) { //setup metadata IBRERuleMetaData metaData = new BRERuleMetaDataImpl(id, factory, aMap, nextStackLoc, step); object result = factory.ExecuteRule(ruleContext, aMap, step); ruleResult = new BRERuleResultImpl(metaData, result); } else { /* * A WARN version of this error can occur when the * Factories are loaded. But if the developer passed in * a RuleContext, they can place the Factory into the * RuleContext still. If we get to this point it is now a full * blown error because if it is not in the RuleContext at this point and * it to late and can cause issues */ if (Logger.IsFlowEngineError) { Logger.FlowEngineSource.TraceData(TraceEventType.Error, 0, new BREException("Factory Id " + id + " defined, but not found in RuleContext")); } } } // This can occur internally in the RuleContext catch (System.InvalidCastException cce) { if (Logger.IsFlowEngineCritical) { Logger.FlowEngineSource.TraceData(TraceEventType.Critical, 0, new BREException("Object in RuleContext not of correct type. " + cce.ToString())); } } // Catch unknown exceptions in the factory itself catch (System.Exception e) { if (Logger.IsFlowEngineError) { Logger.FlowEngineSource.TraceData(TraceEventType.Error, 0, new BREException("Error when processing RuleFactory id: " + id, e)); } /* * Set the RuleResult to an exception so I can test for it in the If * Hey, technically it IS what it returned ;) * The factory can return null here, but that could have caused the * exception anyway..... */ IBRERuleMetaData metaData = new BRERuleMetaDataImpl(id, ruleContext.GetFactory(id), aMap, nextStackLoc, step); ruleResult = new BRERuleResultImpl(metaData, e); } ruleContext.CallStack.Push(ruleResult); // call listeners DispatchRuleResult(ruleResult); ruleContext.SetResult(id, ruleResult); }
/// <summary> Sets a RuleFactory /// * /// </summary> /// <param name="aId">The UID of the RuleFactory /// </param> /// <param name="aFactory">The Factory /// /// </param> public virtual void SetFactory(object aId, IBRERuleFactory aFactory) { if (factories != null) { if (factories.Contains(aId)) factories.Remove(aId); factories.Add(aId, aFactory); } }
/// <summary> Sets a RuleFactory /// * /// </summary> /// <param name="aId">The UID of the RuleFactory /// </param> /// <param name="aFactory">The Factory /// /// </param> public virtual void SetFactory(object aId, IBRERuleFactory aFactory) { if (factories != null) { factories[aId] = aFactory; } }