Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / DataEntity / System / Data / Map / ViewGeneration / Structures / CaseStatement.cs / 1 / CaseStatement.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System.Data.Common.Utils; using System.Linq; using System.Text; using System.Collections.Generic; using System.Data.Mapping.ViewGeneration.CqlGeneration; using System.Data.Metadata.Edm; using System.Diagnostics; namespace System.Data.Mapping.ViewGeneration.Structures { // effects: A class to denote a case statement // CASE // WHENTHEN // WHEN THEN // ... // ENDCASE internal class CaseStatement : InternalBase { #region Constructors /// /// effects: Creates a case statement for the field "memberPath" /// with no clauses /// internal CaseStatement(MemberPath memberPath) { m_memberPath = memberPath; m_clauses = new List(); } #endregion #region Fields private MemberPath m_memberPath; // The field private List m_clauses; // All the WHEN THENs private ProjectedSlot m_elseValue; // Value for the else clause #endregion #region Properties internal MemberPath MemberPath { get { return m_memberPath; } } // CHANGE_[....]_IMPROVE: This can actually be removed if we refactor // CqlGenerator a little bit more internal List Clauses { get { return m_clauses; } } internal ProjectedSlot ElseValue { get { return m_elseValue; } } #endregion #region Methods // effects: Converts all "relevant" ProjectedSlots in this (including // this) to aliased slots for CqlBlock "block". A slot type is // relevant if it is not a constant. "outputPath" is the output path // of this case statement in the final view internal CaseStatement MakeCaseWithAliasedSlots(CqlBlock block, MemberPath outputPath, int slotNum) { // Go through the whenthens and else and make a new case statement with // aliased slots as needed CaseStatement result = new CaseStatement(m_memberPath); foreach (WhenThen whenThen in m_clauses) { WhenThen newClause = whenThen.ReplaceWithAliasedSlot(block, outputPath, slotNum); result.m_clauses.Add(newClause); } if (m_elseValue != null) { result.m_elseValue = m_elseValue.MakeAliasedSlot(block, outputPath, slotNum); } return result; } // requires: condition has not been added to this // effects: Adds an expression of the form WHEN THEN // for this variable internal void AddWhenThen(BoolExpression condition, ProjectedSlot value) { // We should probably validate that the expression is not there? Debug.Assert(value != null); condition.ExpensiveSimplify(); m_clauses.Add(new WhenThen(condition, value)); } // effects: returns true if the case statement requires the value of the member // in THEN or ELSE internal bool DependsOnMemberValue { get { if (m_elseValue is JoinTreeSlot) { return true; } foreach (WhenThen whenThen in m_clauses) { if (whenThen.Value is JoinTreeSlot) { return true; } } return false; } } internal IEnumerable InstantiatedTypes { get { foreach (WhenThen whenThen in m_clauses) { EdmType type; if (TryGetInstantiatedType(whenThen.Value, out type)) { yield return type; } } EdmType elseType; if (TryGetInstantiatedType(m_elseValue, out elseType)) { yield return elseType; } } } private bool TryGetInstantiatedType(ProjectedSlot slot, out EdmType type) { type = null; ConstantSlot constantSlot = slot as ConstantSlot; if (constantSlot != null) { TypeConstant typeConstant = constantSlot.CellConstant as TypeConstant; if (typeConstant != null) { type = typeConstant.CdmType; return true; } } return false; } // effects: Simplifies the case statement so that unnecessary when // thens for nulls/undefined values are eliminated. Also, adds an // else clause if possible. internal void Simplify() { // TODDO_[....]_LOW: Make this call idempotent? Debug.Assert(m_elseValue == null, "Already been simplified -- call is not idempotent yet"); List clauses = new List (); // remove all WHEN clauses where the value gets set to "undefined" // We eliminate the last clause for now - we could determine the // "most complicated" WHEN clause and eliminate it bool eliminatedNullClauses = false; foreach (WhenThen clause in m_clauses) { ConstantSlot constantSlot = clause.Value as ConstantSlot; // If null or undefined, remove it if (constantSlot != null && (constantSlot.CellConstant.IsNull() || constantSlot.CellConstant.IsUndefined())) { eliminatedNullClauses = true; } else { clauses.Add(clause); if (clause.Condition.IsTrue) { // none of subsequent case statements will be evaluated - ignore them break; } } } if (eliminatedNullClauses && clauses.Count == 0) { // There is nothing left -- we should add a null as the value m_elseValue = new ConstantSlot(CellConstant.Null); } // If we eliminated some undefined or null clauses, we do not want an else clause if (clauses.Count > 0 && false == eliminatedNullClauses) { // turn the last WHEN clause into an ELSE int lastIndex = clauses.Count - 1; m_elseValue = clauses[lastIndex].Value; clauses.RemoveAt(lastIndex); } m_clauses = clauses; } // effects: Given a caseStatement, generates the CQL for // it. blockAlias is used whenever the value in the WHEN or THEN is not an aliased slot internal StringBuilder AsCql(StringBuilder builder, IEnumerable withStatements, string blockAlias, int indentLevel) { // If the variable is a relation end, we will gets it scope Extent, e.g., CPerson1 for an // the CPerson end of CPersonAddress1 StringUtil.IndentNewLine(builder, indentLevel + 1); if (Clauses.Count == 0) { // this is just a single ELSE: no condition at all CaseSlotValueAsCql(builder, ElseValue, MemberPath, blockAlias); AppendWithBlock(builder, withStatements, blockAlias, indentLevel, ElseValue); return builder; } // Generate the Case WHEN .. THEN ..., WHEN ... THEN ..., END builder.Append("CASE"); foreach (CaseStatement.WhenThen clause in Clauses) { StringUtil.IndentNewLine(builder, indentLevel + 2); builder.Append("WHEN "); clause.Condition.AsCql(builder, blockAlias); builder.Append(" THEN "); CaseSlotValueAsCql(builder, clause.Value, MemberPath, blockAlias); AppendWithBlock(builder, withStatements, blockAlias, indentLevel + 2, clause.Value); } if (ElseValue != null) { StringUtil.IndentNewLine(builder, indentLevel + 2); builder.Append("ELSE "); CaseSlotValueAsCql(builder, ElseValue, MemberPath, blockAlias); AppendWithBlock(builder, withStatements, blockAlias, indentLevel + 2, ElseValue); } StringUtil.IndentNewLine(builder, indentLevel + 1); builder.Append("END"); return builder; } private void AppendWithBlock(StringBuilder builder, IEnumerable withStatements, string blockAlias, int indentLevel, ProjectedSlot projectedSlot) { if ((withStatements != null) && (withStatements.Count() > 0)) { ConstantSlot typeConstantSlot = projectedSlot as ConstantSlot; if (typeConstantSlot != null) { TypeConstant typeConstant = typeConstantSlot.CellConstant as TypeConstant; if (typeConstant != null) { AppendWithBlock(builder, withStatements, typeConstant.CdmType, blockAlias, indentLevel); } else { Debug.Assert(false, "with block should be there for type constant only"); } } else { Debug.Assert(false, "with block should be there for type constant slot only"); } } } private void AppendWithBlock(StringBuilder builder, IEnumerable withStatements, EdmType fromType, string blockAlias, int indentLevel) { bool appendWithKeyword = true; foreach (WithStatement withStatement in withStatements) { //Add With statement for the types that participate in the association if (withStatement.EntityTypeForFromEnd.IsAssignableFrom(fromType)) { if (appendWithKeyword) { appendWithKeyword = false; builder.Append(" WITH "); } withStatement.AsCql(builder, blockAlias, indentLevel); } } } // requires: This method is called by CaseSlotValuetoCql and // slot is not a boolean slot // effects: Given a slot and its corresponding outputMember, modifies // builder to contain the slot value private static StringBuilder CaseSlotValueAsCql(StringBuilder builder, ProjectedSlot slot, MemberPath outputMember, string blockAlias) { // CHANGE_[....]_DESIGN: We will never have THEN as a boolean slot Debug.Assert(slot is JoinTreeSlot || slot is AliasedSlot || slot is ConstantSlot, "Case statement THEN can only have constants or members"); slot.AsCql(builder, outputMember, blockAlias, 1); return builder; } // Repeat of AsCql but don't have all the info internal override void ToCompactString(StringBuilder builder) { // We have to duplicate the functionality of AsCql here since // ToCompactString can get called at times when the THEN parts contain // Undefined values -- in that case, a Debug.Assert in CellConstant's AsCql // fires off builder.AppendLine("CASE"); foreach (WhenThen clause in m_clauses) { builder.Append(" WHEN "); clause.Condition.ToCompactString(builder); builder.Append(" THEN "); clause.Value.ToCompactString(builder); builder.AppendLine(); } if (m_elseValue != null) { builder.Append(" ELSE "); m_elseValue.ToCompactString(builder); builder.AppendLine(); } builder.Append("END AS "); m_memberPath.ToCompactString(builder); } #endregion // effects: A class that stores WHEN THEN internal class WhenThen : InternalBase { #region Constructor // effects: Creates WHEN THEN internal WhenThen(BoolExpression condition, ProjectedSlot value) { m_condition = condition; m_value = value; } #endregion #region Fields private BoolExpression m_condition; private ProjectedSlot m_value; #endregion #region Properties /// /// effects: Returns the when condition /// internal BoolExpression Condition { get { return m_condition; } } ////// effects: Returns the value for the when case /// internal ProjectedSlot Value { get { return m_value; } } #endregion #region String Methods internal WhenThen ReplaceWithAliasedSlot(CqlBlock block, MemberPath outputPath, int slotNum) { // Change the THEN part ProjectedSlot newValue = m_value.MakeAliasedSlot(block, outputPath, slotNum); return new WhenThen(m_condition, newValue); } internal override void ToCompactString(StringBuilder builder) { builder.Append("WHEN "); m_condition.ToCompactString(builder); builder.Append("THEN "); m_value.ToCompactString(builder); } #endregion } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System.Data.Common.Utils; using System.Linq; using System.Text; using System.Collections.Generic; using System.Data.Mapping.ViewGeneration.CqlGeneration; using System.Data.Metadata.Edm; using System.Diagnostics; namespace System.Data.Mapping.ViewGeneration.Structures { // effects: A class to denote a case statement // CASE // WHENTHEN // WHEN THEN // ... // ENDCASE internal class CaseStatement : InternalBase { #region Constructors /// /// effects: Creates a case statement for the field "memberPath" /// with no clauses /// internal CaseStatement(MemberPath memberPath) { m_memberPath = memberPath; m_clauses = new List(); } #endregion #region Fields private MemberPath m_memberPath; // The field private List m_clauses; // All the WHEN THENs private ProjectedSlot m_elseValue; // Value for the else clause #endregion #region Properties internal MemberPath MemberPath { get { return m_memberPath; } } // CHANGE_[....]_IMPROVE: This can actually be removed if we refactor // CqlGenerator a little bit more internal List Clauses { get { return m_clauses; } } internal ProjectedSlot ElseValue { get { return m_elseValue; } } #endregion #region Methods // effects: Converts all "relevant" ProjectedSlots in this (including // this) to aliased slots for CqlBlock "block". A slot type is // relevant if it is not a constant. "outputPath" is the output path // of this case statement in the final view internal CaseStatement MakeCaseWithAliasedSlots(CqlBlock block, MemberPath outputPath, int slotNum) { // Go through the whenthens and else and make a new case statement with // aliased slots as needed CaseStatement result = new CaseStatement(m_memberPath); foreach (WhenThen whenThen in m_clauses) { WhenThen newClause = whenThen.ReplaceWithAliasedSlot(block, outputPath, slotNum); result.m_clauses.Add(newClause); } if (m_elseValue != null) { result.m_elseValue = m_elseValue.MakeAliasedSlot(block, outputPath, slotNum); } return result; } // requires: condition has not been added to this // effects: Adds an expression of the form WHEN THEN // for this variable internal void AddWhenThen(BoolExpression condition, ProjectedSlot value) { // We should probably validate that the expression is not there? Debug.Assert(value != null); condition.ExpensiveSimplify(); m_clauses.Add(new WhenThen(condition, value)); } // effects: returns true if the case statement requires the value of the member // in THEN or ELSE internal bool DependsOnMemberValue { get { if (m_elseValue is JoinTreeSlot) { return true; } foreach (WhenThen whenThen in m_clauses) { if (whenThen.Value is JoinTreeSlot) { return true; } } return false; } } internal IEnumerable InstantiatedTypes { get { foreach (WhenThen whenThen in m_clauses) { EdmType type; if (TryGetInstantiatedType(whenThen.Value, out type)) { yield return type; } } EdmType elseType; if (TryGetInstantiatedType(m_elseValue, out elseType)) { yield return elseType; } } } private bool TryGetInstantiatedType(ProjectedSlot slot, out EdmType type) { type = null; ConstantSlot constantSlot = slot as ConstantSlot; if (constantSlot != null) { TypeConstant typeConstant = constantSlot.CellConstant as TypeConstant; if (typeConstant != null) { type = typeConstant.CdmType; return true; } } return false; } // effects: Simplifies the case statement so that unnecessary when // thens for nulls/undefined values are eliminated. Also, adds an // else clause if possible. internal void Simplify() { // TODDO_[....]_LOW: Make this call idempotent? Debug.Assert(m_elseValue == null, "Already been simplified -- call is not idempotent yet"); List clauses = new List (); // remove all WHEN clauses where the value gets set to "undefined" // We eliminate the last clause for now - we could determine the // "most complicated" WHEN clause and eliminate it bool eliminatedNullClauses = false; foreach (WhenThen clause in m_clauses) { ConstantSlot constantSlot = clause.Value as ConstantSlot; // If null or undefined, remove it if (constantSlot != null && (constantSlot.CellConstant.IsNull() || constantSlot.CellConstant.IsUndefined())) { eliminatedNullClauses = true; } else { clauses.Add(clause); if (clause.Condition.IsTrue) { // none of subsequent case statements will be evaluated - ignore them break; } } } if (eliminatedNullClauses && clauses.Count == 0) { // There is nothing left -- we should add a null as the value m_elseValue = new ConstantSlot(CellConstant.Null); } // If we eliminated some undefined or null clauses, we do not want an else clause if (clauses.Count > 0 && false == eliminatedNullClauses) { // turn the last WHEN clause into an ELSE int lastIndex = clauses.Count - 1; m_elseValue = clauses[lastIndex].Value; clauses.RemoveAt(lastIndex); } m_clauses = clauses; } // effects: Given a caseStatement, generates the CQL for // it. blockAlias is used whenever the value in the WHEN or THEN is not an aliased slot internal StringBuilder AsCql(StringBuilder builder, IEnumerable withStatements, string blockAlias, int indentLevel) { // If the variable is a relation end, we will gets it scope Extent, e.g., CPerson1 for an // the CPerson end of CPersonAddress1 StringUtil.IndentNewLine(builder, indentLevel + 1); if (Clauses.Count == 0) { // this is just a single ELSE: no condition at all CaseSlotValueAsCql(builder, ElseValue, MemberPath, blockAlias); AppendWithBlock(builder, withStatements, blockAlias, indentLevel, ElseValue); return builder; } // Generate the Case WHEN .. THEN ..., WHEN ... THEN ..., END builder.Append("CASE"); foreach (CaseStatement.WhenThen clause in Clauses) { StringUtil.IndentNewLine(builder, indentLevel + 2); builder.Append("WHEN "); clause.Condition.AsCql(builder, blockAlias); builder.Append(" THEN "); CaseSlotValueAsCql(builder, clause.Value, MemberPath, blockAlias); AppendWithBlock(builder, withStatements, blockAlias, indentLevel + 2, clause.Value); } if (ElseValue != null) { StringUtil.IndentNewLine(builder, indentLevel + 2); builder.Append("ELSE "); CaseSlotValueAsCql(builder, ElseValue, MemberPath, blockAlias); AppendWithBlock(builder, withStatements, blockAlias, indentLevel + 2, ElseValue); } StringUtil.IndentNewLine(builder, indentLevel + 1); builder.Append("END"); return builder; } private void AppendWithBlock(StringBuilder builder, IEnumerable withStatements, string blockAlias, int indentLevel, ProjectedSlot projectedSlot) { if ((withStatements != null) && (withStatements.Count() > 0)) { ConstantSlot typeConstantSlot = projectedSlot as ConstantSlot; if (typeConstantSlot != null) { TypeConstant typeConstant = typeConstantSlot.CellConstant as TypeConstant; if (typeConstant != null) { AppendWithBlock(builder, withStatements, typeConstant.CdmType, blockAlias, indentLevel); } else { Debug.Assert(false, "with block should be there for type constant only"); } } else { Debug.Assert(false, "with block should be there for type constant slot only"); } } } private void AppendWithBlock(StringBuilder builder, IEnumerable withStatements, EdmType fromType, string blockAlias, int indentLevel) { bool appendWithKeyword = true; foreach (WithStatement withStatement in withStatements) { //Add With statement for the types that participate in the association if (withStatement.EntityTypeForFromEnd.IsAssignableFrom(fromType)) { if (appendWithKeyword) { appendWithKeyword = false; builder.Append(" WITH "); } withStatement.AsCql(builder, blockAlias, indentLevel); } } } // requires: This method is called by CaseSlotValuetoCql and // slot is not a boolean slot // effects: Given a slot and its corresponding outputMember, modifies // builder to contain the slot value private static StringBuilder CaseSlotValueAsCql(StringBuilder builder, ProjectedSlot slot, MemberPath outputMember, string blockAlias) { // CHANGE_[....]_DESIGN: We will never have THEN as a boolean slot Debug.Assert(slot is JoinTreeSlot || slot is AliasedSlot || slot is ConstantSlot, "Case statement THEN can only have constants or members"); slot.AsCql(builder, outputMember, blockAlias, 1); return builder; } // Repeat of AsCql but don't have all the info internal override void ToCompactString(StringBuilder builder) { // We have to duplicate the functionality of AsCql here since // ToCompactString can get called at times when the THEN parts contain // Undefined values -- in that case, a Debug.Assert in CellConstant's AsCql // fires off builder.AppendLine("CASE"); foreach (WhenThen clause in m_clauses) { builder.Append(" WHEN "); clause.Condition.ToCompactString(builder); builder.Append(" THEN "); clause.Value.ToCompactString(builder); builder.AppendLine(); } if (m_elseValue != null) { builder.Append(" ELSE "); m_elseValue.ToCompactString(builder); builder.AppendLine(); } builder.Append("END AS "); m_memberPath.ToCompactString(builder); } #endregion // effects: A class that stores WHEN THEN internal class WhenThen : InternalBase { #region Constructor // effects: Creates WHEN THEN internal WhenThen(BoolExpression condition, ProjectedSlot value) { m_condition = condition; m_value = value; } #endregion #region Fields private BoolExpression m_condition; private ProjectedSlot m_value; #endregion #region Properties /// /// effects: Returns the when condition /// internal BoolExpression Condition { get { return m_condition; } } ////// effects: Returns the value for the when case /// internal ProjectedSlot Value { get { return m_value; } } #endregion #region String Methods internal WhenThen ReplaceWithAliasedSlot(CqlBlock block, MemberPath outputPath, int slotNum) { // Change the THEN part ProjectedSlot newValue = m_value.MakeAliasedSlot(block, outputPath, slotNum); return new WhenThen(m_condition, newValue); } internal override void ToCompactString(StringBuilder builder) { builder.Append("WHEN "); m_condition.ToCompactString(builder); builder.Append("THEN "); m_value.ToCompactString(builder); } #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
- RowVisual.cs
- ListControl.cs
- CanonicalFontFamilyReference.cs
- X509UI.cs
- _SSPISessionCache.cs
- ParserContext.cs
- RequestContext.cs
- GatewayIPAddressInformationCollection.cs
- UserControl.cs
- RoleService.cs
- DefaultTextStoreTextComposition.cs
- StylusDownEventArgs.cs
- ReadWriteObjectLock.cs
- InputReportEventArgs.cs
- TokenBasedSetEnumerator.cs
- AddInProcess.cs
- TimelineCollection.cs
- _Connection.cs
- SmtpNetworkElement.cs
- Int64Storage.cs
- XmlExpressionDumper.cs
- XmlMemberMapping.cs
- KeySpline.cs
- SharedPerformanceCounter.cs
- SqlDataSourceCommandEventArgs.cs
- SqlGenericUtil.cs
- ListViewTableRow.cs
- CodeNamespaceCollection.cs
- CodeBlockBuilder.cs
- PriorityRange.cs
- linebase.cs
- KnownIds.cs
- ArrangedElement.cs
- ClipboardData.cs
- KeyValuePairs.cs
- SolidColorBrush.cs
- XmlNavigatorFilter.cs
- BrowserTree.cs
- validationstate.cs
- Matrix.cs
- BitmapEffectOutputConnector.cs
- GPPOINTF.cs
- ToolStripPanelRenderEventArgs.cs
- BooleanToVisibilityConverter.cs
- ToolboxBitmapAttribute.cs
- SQLMoney.cs
- AtomContentProperty.cs
- SortedDictionary.cs
- BooleanConverter.cs
- MobileSysDescriptionAttribute.cs
- InternalTypeHelper.cs
- Inline.cs
- isolationinterop.cs
- DataRelation.cs
- UshortList2.cs
- ImageDesigner.cs
- RegexRunnerFactory.cs
- TextEditorThreadLocalStore.cs
- XsltArgumentList.cs
- SizeConverter.cs
- BooleanFunctions.cs
- ContravarianceAdapter.cs
- SqlCaseSimplifier.cs
- GradientStop.cs
- LineServicesCallbacks.cs
- TextBoxDesigner.cs
- InternalEnumValidator.cs
- Timeline.cs
- CacheVirtualItemsEvent.cs
- FontClient.cs
- ValuePattern.cs
- DiscoveryInnerClientManaged11.cs
- ProfileSection.cs
- ThreadLocal.cs
- TextElementCollection.cs
- XomlCompiler.cs
- SynchronizingStream.cs
- WebFormsRootDesigner.cs
- LocatorBase.cs
- NonParentingControl.cs
- PropertyMappingExceptionEventArgs.cs
- ConnectionPoint.cs
- SelectorAutomationPeer.cs
- FileLogRecordHeader.cs
- InternalEnumValidatorAttribute.cs
- FolderBrowserDialog.cs
- OleDbConnectionPoolGroupProviderInfo.cs
- Sql8ExpressionRewriter.cs
- RecognizedWordUnit.cs
- User.cs
- Span.cs
- NativeMethods.cs
- SqlMetaData.cs
- UInt64Storage.cs
- ContentType.cs
- FontSourceCollection.cs
- EncodingTable.cs
- PostBackOptions.cs
- ServiceModelEnhancedConfigurationElementCollection.cs
- ISAPIApplicationHost.cs