Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DataEntity / System / Data / Query / InternalTrees / RuleProcessor.cs / 3 / RuleProcessor.cs
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// @owner [....], [....]
//---------------------------------------------------------------------
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 Dictionary m_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))
{
return subTreeRoot;
}
// 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;
}
subTreeRoot = newSubTreeRoot;
}
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)
{
}
///
/// 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 [....], [....]
//---------------------------------------------------------------------
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 Dictionary m_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))
{
return subTreeRoot;
}
// 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;
}
subTreeRoot = newSubTreeRoot;
}
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)
{
}
///
/// 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
- SessionStateUtil.cs
- AnimationStorage.cs
- SmtpReplyReaderFactory.cs
- OperationPickerDialog.cs
- Registry.cs
- PackageProperties.cs
- SapiAttributeParser.cs
- LinkUtilities.cs
- PropertyCollection.cs
- ImageIndexConverter.cs
- ArgumentNullException.cs
- CopyOnWriteList.cs
- CompilerScopeManager.cs
- TypeNameConverter.cs
- TransactionManager.cs
- StringSource.cs
- SoapIgnoreAttribute.cs
- DataObject.cs
- CssStyleCollection.cs
- DocumentCollection.cs
- namescope.cs
- BaseServiceProvider.cs
- UnaryNode.cs
- MatrixTransform3D.cs
- XmlHierarchicalEnumerable.cs
- StructuredCompositeActivityDesigner.cs
- FileAuthorizationModule.cs
- TypeExtensionConverter.cs
- TraversalRequest.cs
- Control.cs
- SchemaReference.cs
- selecteditemcollection.cs
- PathFigureCollection.cs
- CancelEventArgs.cs
- TraceEventCache.cs
- ColorDialog.cs
- PbrsForward.cs
- NullRuntimeConfig.cs
- ProcessHostFactoryHelper.cs
- SqlCommand.cs
- BindToObject.cs
- BuildResultCache.cs
- InstanceContextMode.cs
- IdnElement.cs
- TargetParameterCountException.cs
- mactripleDES.cs
- COM2ComponentEditor.cs
- MetadataItemEmitter.cs
- HGlobalSafeHandle.cs
- XmlSchemaComplexContent.cs
- Function.cs
- EntityAdapter.cs
- PanelDesigner.cs
- ConnectionManagementElement.cs
- XDRSchema.cs
- DynamicRenderer.cs
- HotCommands.cs
- HierarchicalDataTemplate.cs
- WorkflowInstanceExtensionProvider.cs
- EdmRelationshipRoleAttribute.cs
- MainMenu.cs
- HttpProxyTransportBindingElement.cs
- SpeechSeg.cs
- WebControlAdapter.cs
- CacheEntry.cs
- Win32MouseDevice.cs
- DragEvent.cs
- HtmlTableRowCollection.cs
- MetabaseServerConfig.cs
- EntityKeyElement.cs
- PeerToPeerException.cs
- PostBackOptions.cs
- SocketException.cs
- TemplateBindingExpressionConverter.cs
- ColorTransformHelper.cs
- GraphicsContext.cs
- validation.cs
- DirtyTextRange.cs
- PageParserFilter.cs
- SrgsElementList.cs
- Pair.cs
- Int32Storage.cs
- CheckBoxField.cs
- DuplicateMessageDetector.cs
- ProfessionalColorTable.cs
- ColumnPropertiesGroup.cs
- Int64Storage.cs
- ISFClipboardData.cs
- HtmlInputImage.cs
- GenericUriParser.cs
- LocatorPartList.cs
- SystemResourceHost.cs
- InheritedPropertyDescriptor.cs
- ApplicationServiceHelper.cs
- GeneralTransform3DTo2D.cs
- CredentialCache.cs
- CopyAttributesAction.cs
- CodeAttributeDeclarationCollection.cs
- TableItemProviderWrapper.cs
- EventSetterHandlerConverter.cs