Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Query / InternalTrees / RuleProcessor.cs / 1305376 / RuleProcessor.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; using System.Diagnostics; namespace System.Data.Query.InternalTrees { #region RuleProcessor ////// The RuleProcessor helps apply a set of rules to a query tree /// internal class RuleProcessor { #region private state ////// A lookup table for rules. /// The lookup table is an array indexed by OpType and each entry has a list of rules. /// private Dictionarym_processedNodeMap; #endregion #region constructors /// /// Initializes a new RuleProcessor /// internal RuleProcessor() { // Build up the accelerator tables m_processedNodeMap = new Dictionary(); } #endregion #region private methods private static bool ApplyRulesToNode(RuleProcessingContext context, ReadOnlyCollection > rules, Node currentNode, out Node newNode) { newNode = currentNode; // Apply any pre-rule delegates context.PreProcess(currentNode); foreach (Rule r in rules[(int)currentNode.Op.OpType]) { if (!r.Match(currentNode)) { continue; } // Did the rule modify the subtree? if (r.Apply(context, currentNode, out newNode)) { // The node has changed; don't try to apply any more rules context.PostProcess(newNode, r); return true; } else { Debug.Assert(newNode == currentNode, "Liar! This rule should have returned 'true'"); } } context.PostProcess(currentNode, null); return false; } /// /// Apply rules to the current subtree in a bottom-up fashion. /// /// Current rule processing context /// The look-up table with the rules to be applied /// Current subtree /// Parent node /// Index of this child within the parent ///the result of the transformation private Node ApplyRulesToSubtree(RuleProcessingContext context, ReadOnlyCollection> rules, Node subTreeRoot, Node parent, int childIndexInParent) { int loopCount = 0; Dictionary localProcessedMap = new Dictionary (); SubTreeId subTreeId; while (true) { // Am I looping forever Debug.Assert(loopCount < 12, "endless loops?"); loopCount++; // // We may need to update state regardless of whether this subTree has // changed after it has been processed last. For example, it may be // affected by transformation in its siblings due to external references. // context.PreProcessSubTree(subTreeRoot); subTreeId = new SubTreeId(context, subTreeRoot, parent, childIndexInParent); // Have I seen this subtree already? Just return, if so if (m_processedNodeMap.ContainsKey(subTreeId)) { break; } // Avoid endless loops here - avoid cycles of 2 or more if (localProcessedMap.ContainsKey(subTreeId)) { // mark this subtree as processed m_processedNodeMap[subTreeId] = subTreeId; break; } // Keep track of this one localProcessedMap[subTreeId] = subTreeId; // Walk my children for (int i = 0; i < subTreeRoot.Children.Count; i++) { subTreeRoot.Children[i] = ApplyRulesToSubtree(context, rules, subTreeRoot.Children[i], subTreeRoot, i); } // Apply rules to myself. If no transformations were performed, // then mark this subtree as processed, and break out Node newSubTreeRoot; if (!ApplyRulesToNode(context, rules, subTreeRoot, out newSubTreeRoot)) { Debug.Assert(subTreeRoot == newSubTreeRoot); // mark this subtree as processed m_processedNodeMap[subTreeId] = subTreeId; break; } context.PostProcessSubTree(subTreeRoot); subTreeRoot = newSubTreeRoot; } context.PostProcessSubTree(subTreeRoot); return subTreeRoot; } #endregion #region public methods /// /// Apply a set of rules to the subtree /// /// Rule processing context /// current subtree ///transformed subtree internal Node ApplyRulesToSubtree(RuleProcessingContext context, ReadOnlyCollection> rules, Node subTreeRoot) { return ApplyRulesToSubtree(context, rules, subTreeRoot, null, 0); } #endregion } #endregion #region SubTreeId internal class SubTreeId { #region private state public Node m_subTreeRoot; private int m_hashCode; private Node m_parent; private int m_parentHashCode; private int m_childIndex; #endregion #region constructors internal SubTreeId(RuleProcessingContext context, Node node, Node parent, int childIndex) { m_subTreeRoot = node; m_parent = parent; m_childIndex = childIndex; m_hashCode = context.GetHashCode(node); m_parentHashCode = parent == null ? 0 : context.GetHashCode(parent); } #endregion #region public surface public override int GetHashCode() { return m_hashCode; } public override bool Equals(object obj) { SubTreeId other = obj as SubTreeId; return ((other != null) && (m_hashCode == other.m_hashCode) && ((other.m_subTreeRoot == this.m_subTreeRoot) || ((other.m_parent == this.m_parent) && (other.m_childIndex == this.m_childIndex)))); } #endregion } #endregion #region RuleProcessingContext /// /// Delegate that describes the processing /// /// RuleProcessing context /// Node to process internal delegate void OpDelegate(RuleProcessingContext context, Node node); ////// A RuleProcessingContext encapsulates information needed by various rules to process /// the query tree. /// internal abstract class RuleProcessingContext { #region public surface internal Command Command { get { return m_command; } } ////// Callback function to be applied to a node before any rules are applied /// /// the node internal virtual void PreProcess(Node node) { } ////// Callback function to be applied to the subtree rooted at the given /// node before any rules are applied /// /// the node that is the root of the subtree internal virtual void PreProcessSubTree(Node node) { } ////// Callback function to be applied on a node after a rule has been applied /// that has modified the node /// /// current node /// the rule that modified the node internal virtual void PostProcess(Node node, Rule rule) { } ////// Callback function to be applied to the subtree rooted at the given /// node after any rules are applied /// /// the node that is the root of the subtree internal virtual void PostProcessSubTree(Node node) { } ////// Get the hashcode for this node - to ensure that we don't loop forever /// /// current node ///int hashcode internal virtual int GetHashCode(Node node) { return node.GetHashCode(); } #endregion #region constructors internal RuleProcessingContext(Command command) { m_command = command; } #endregion #region private state private Command m_command; #endregion } #endregion } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; using System.Diagnostics; namespace System.Data.Query.InternalTrees { #region RuleProcessor ////// The RuleProcessor helps apply a set of rules to a query tree /// internal class RuleProcessor { #region private state ////// A lookup table for rules. /// The lookup table is an array indexed by OpType and each entry has a list of rules. /// private Dictionarym_processedNodeMap; #endregion #region constructors /// /// Initializes a new RuleProcessor /// internal RuleProcessor() { // Build up the accelerator tables m_processedNodeMap = new Dictionary(); } #endregion #region private methods private static bool ApplyRulesToNode(RuleProcessingContext context, ReadOnlyCollection > rules, Node currentNode, out Node newNode) { newNode = currentNode; // Apply any pre-rule delegates context.PreProcess(currentNode); foreach (Rule r in rules[(int)currentNode.Op.OpType]) { if (!r.Match(currentNode)) { continue; } // Did the rule modify the subtree? if (r.Apply(context, currentNode, out newNode)) { // The node has changed; don't try to apply any more rules context.PostProcess(newNode, r); return true; } else { Debug.Assert(newNode == currentNode, "Liar! This rule should have returned 'true'"); } } context.PostProcess(currentNode, null); return false; } /// /// Apply rules to the current subtree in a bottom-up fashion. /// /// Current rule processing context /// The look-up table with the rules to be applied /// Current subtree /// Parent node /// Index of this child within the parent ///the result of the transformation private Node ApplyRulesToSubtree(RuleProcessingContext context, ReadOnlyCollection> rules, Node subTreeRoot, Node parent, int childIndexInParent) { int loopCount = 0; Dictionary localProcessedMap = new Dictionary (); SubTreeId subTreeId; while (true) { // Am I looping forever Debug.Assert(loopCount < 12, "endless loops?"); loopCount++; // // We may need to update state regardless of whether this subTree has // changed after it has been processed last. For example, it may be // affected by transformation in its siblings due to external references. // context.PreProcessSubTree(subTreeRoot); subTreeId = new SubTreeId(context, subTreeRoot, parent, childIndexInParent); // Have I seen this subtree already? Just return, if so if (m_processedNodeMap.ContainsKey(subTreeId)) { break; } // Avoid endless loops here - avoid cycles of 2 or more if (localProcessedMap.ContainsKey(subTreeId)) { // mark this subtree as processed m_processedNodeMap[subTreeId] = subTreeId; break; } // Keep track of this one localProcessedMap[subTreeId] = subTreeId; // Walk my children for (int i = 0; i < subTreeRoot.Children.Count; i++) { subTreeRoot.Children[i] = ApplyRulesToSubtree(context, rules, subTreeRoot.Children[i], subTreeRoot, i); } // Apply rules to myself. If no transformations were performed, // then mark this subtree as processed, and break out Node newSubTreeRoot; if (!ApplyRulesToNode(context, rules, subTreeRoot, out newSubTreeRoot)) { Debug.Assert(subTreeRoot == newSubTreeRoot); // mark this subtree as processed m_processedNodeMap[subTreeId] = subTreeId; break; } context.PostProcessSubTree(subTreeRoot); subTreeRoot = newSubTreeRoot; } context.PostProcessSubTree(subTreeRoot); return subTreeRoot; } #endregion #region public methods /// /// Apply a set of rules to the subtree /// /// Rule processing context /// current subtree ///transformed subtree internal Node ApplyRulesToSubtree(RuleProcessingContext context, ReadOnlyCollection> rules, Node subTreeRoot) { return ApplyRulesToSubtree(context, rules, subTreeRoot, null, 0); } #endregion } #endregion #region SubTreeId internal class SubTreeId { #region private state public Node m_subTreeRoot; private int m_hashCode; private Node m_parent; private int m_parentHashCode; private int m_childIndex; #endregion #region constructors internal SubTreeId(RuleProcessingContext context, Node node, Node parent, int childIndex) { m_subTreeRoot = node; m_parent = parent; m_childIndex = childIndex; m_hashCode = context.GetHashCode(node); m_parentHashCode = parent == null ? 0 : context.GetHashCode(parent); } #endregion #region public surface public override int GetHashCode() { return m_hashCode; } public override bool Equals(object obj) { SubTreeId other = obj as SubTreeId; return ((other != null) && (m_hashCode == other.m_hashCode) && ((other.m_subTreeRoot == this.m_subTreeRoot) || ((other.m_parent == this.m_parent) && (other.m_childIndex == this.m_childIndex)))); } #endregion } #endregion #region RuleProcessingContext /// /// Delegate that describes the processing /// /// RuleProcessing context /// Node to process internal delegate void OpDelegate(RuleProcessingContext context, Node node); ////// A RuleProcessingContext encapsulates information needed by various rules to process /// the query tree. /// internal abstract class RuleProcessingContext { #region public surface internal Command Command { get { return m_command; } } ////// Callback function to be applied to a node before any rules are applied /// /// the node internal virtual void PreProcess(Node node) { } ////// Callback function to be applied to the subtree rooted at the given /// node before any rules are applied /// /// the node that is the root of the subtree internal virtual void PreProcessSubTree(Node node) { } ////// Callback function to be applied on a node after a rule has been applied /// that has modified the node /// /// current node /// the rule that modified the node internal virtual void PostProcess(Node node, Rule rule) { } ////// Callback function to be applied to the subtree rooted at the given /// node after any rules are applied /// /// the node that is the root of the subtree internal virtual void PostProcessSubTree(Node node) { } ////// Get the hashcode for this node - to ensure that we don't loop forever /// /// current node ///int hashcode internal virtual int GetHashCode(Node node) { return node.GetHashCode(); } #endregion #region constructors internal RuleProcessingContext(Command command) { m_command = command; } #endregion #region private state private Command m_command; #endregion } #endregion } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- OlePropertyStructs.cs
- MaskedTextProvider.cs
- CryptoStream.cs
- MsmqIntegrationChannelFactory.cs
- InlineCollection.cs
- ControlCollection.cs
- AsnEncodedData.cs
- TraceXPathNavigator.cs
- HtmlElement.cs
- DependencyProperty.cs
- QilInvokeEarlyBound.cs
- WebBrowserUriTypeConverter.cs
- DoubleAnimationUsingPath.cs
- TargetParameterCountException.cs
- InputDevice.cs
- xml.cs
- ObjectStateFormatter.cs
- OleDbWrapper.cs
- SecurityDocument.cs
- ScrollBarRenderer.cs
- HtmlInputFile.cs
- ServicePointManager.cs
- RepeatBehaviorConverter.cs
- SimpleLine.cs
- TemplateComponentConnector.cs
- SimpleTextLine.cs
- XmlTextReader.cs
- SoapMessage.cs
- WindowsSpinner.cs
- PersonalizationStateInfoCollection.cs
- WeakEventTable.cs
- SearchForVirtualItemEventArgs.cs
- UserControl.cs
- DataGrid.cs
- DrawingContextDrawingContextWalker.cs
- BufferedGraphics.cs
- DateTimeOffset.cs
- XmlSchemaRedefine.cs
- Empty.cs
- ReadOnlyHierarchicalDataSourceView.cs
- ControlCommandSet.cs
- MouseActionValueSerializer.cs
- MsmqOutputSessionChannel.cs
- ToolStripItemImageRenderEventArgs.cs
- WebPartAuthorizationEventArgs.cs
- WindowsBrush.cs
- BounceEase.cs
- BitmapFrameEncode.cs
- FixedSOMFixedBlock.cs
- GetReadStreamResult.cs
- MaskInputRejectedEventArgs.cs
- DataListAutoFormat.cs
- TemplateParser.cs
- WpfXamlMember.cs
- XslAstAnalyzer.cs
- X509CertificateStore.cs
- Menu.cs
- ReverseComparer.cs
- RectAnimationBase.cs
- GeometryConverter.cs
- SettingsContext.cs
- QilChoice.cs
- TrustManagerPromptUI.cs
- SystemWebSectionGroup.cs
- CircleHotSpot.cs
- Marshal.cs
- _ListenerRequestStream.cs
- HttpServerVarsCollection.cs
- OneToOneMappingSerializer.cs
- CompilationUnit.cs
- IgnorePropertiesAttribute.cs
- XPathScanner.cs
- StyleModeStack.cs
- PrintEvent.cs
- GroupDescription.cs
- EditorZone.cs
- DataSourceGroupCollection.cs
- COM2TypeInfoProcessor.cs
- GeometryHitTestParameters.cs
- DataViewSettingCollection.cs
- VisualStyleRenderer.cs
- CodeVariableReferenceExpression.cs
- ExecutionEngineException.cs
- RowBinding.cs
- PeerNameRecord.cs
- AppDomainShutdownMonitor.cs
- TrimSurroundingWhitespaceAttribute.cs
- KeyInstance.cs
- ApplicationDirectoryMembershipCondition.cs
- XmlUtilWriter.cs
- FilteredSchemaElementLookUpTable.cs
- CookieParameter.cs
- GradientBrush.cs
- JournalNavigationScope.cs
- ReadOnlyMetadataCollection.cs
- AggregateException.cs
- AssociationSetMetadata.cs
- IndexedString.cs
- DesignParameter.cs
- StubHelpers.cs