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
- SiteMap.cs
- DebugView.cs
- ProjectionCamera.cs
- OrderingQueryOperator.cs
- StronglyTypedResourceBuilder.cs
- ContainsRowNumberChecker.cs
- SQLInt32Storage.cs
- TraceContext.cs
- MulticastNotSupportedException.cs
- FormViewDeleteEventArgs.cs
- ResourceManagerWrapper.cs
- FormsIdentity.cs
- SrgsNameValueTag.cs
- FtpCachePolicyElement.cs
- ConfigurationSettings.cs
- Int16Animation.cs
- PageSetupDialog.cs
- OverrideMode.cs
- XmlSerializerNamespaces.cs
- ProcessHostFactoryHelper.cs
- CollectionChange.cs
- Table.cs
- CharacterBufferReference.cs
- ToolZoneDesigner.cs
- AnnotationStore.cs
- PolyBezierSegment.cs
- webproxy.cs
- RegisteredExpandoAttribute.cs
- _KerberosClient.cs
- ColumnResizeUndoUnit.cs
- FixedDocument.cs
- FormParameter.cs
- FragmentNavigationEventArgs.cs
- CachedCompositeFamily.cs
- Constraint.cs
- SafeHandle.cs
- Page.cs
- DataGridState.cs
- Helpers.cs
- CompositeFontInfo.cs
- CompositeFontFamily.cs
- UnmanagedMemoryStream.cs
- DataGridViewLinkCell.cs
- RNGCryptoServiceProvider.cs
- TdsParserSessionPool.cs
- D3DImage.cs
- CFGGrammar.cs
- TextEditorSpelling.cs
- CommandSet.cs
- SchemaNames.cs
- VersionedStreamOwner.cs
- BinaryObjectWriter.cs
- Emitter.cs
- TextServicesProperty.cs
- DecoderExceptionFallback.cs
- CompleteWizardStep.cs
- Terminate.cs
- XamlReader.cs
- ServiceProviders.cs
- WebPartAuthorizationEventArgs.cs
- Clause.cs
- TextEditorSelection.cs
- SoapProtocolReflector.cs
- DefaultValueMapping.cs
- MatrixTransform3D.cs
- BorderGapMaskConverter.cs
- AbstractSvcMapFileLoader.cs
- XmlNodeChangedEventArgs.cs
- MultidimensionalArrayItemReference.cs
- TextOutput.cs
- WebPartDeleteVerb.cs
- XamlParser.cs
- RangeEnumerable.cs
- DataRelationPropertyDescriptor.cs
- DependencyPropertyChangedEventArgs.cs
- SchemaImporterExtensionsSection.cs
- WhitespaceRuleLookup.cs
- DataGridViewSelectedCellCollection.cs
- TablePattern.cs
- ChannelServices.cs
- sqlnorm.cs
- PanelStyle.cs
- Point3DKeyFrameCollection.cs
- Visual.cs
- DiscreteKeyFrames.cs
- TextEncodedRawTextWriter.cs
- ListCommandEventArgs.cs
- TextTreeInsertUndoUnit.cs
- DefaultValueAttribute.cs
- EntityConnectionStringBuilder.cs
- WinEventWrap.cs
- Composition.cs
- SqlConnectionString.cs
- AudioFileOut.cs
- SchemaCollectionPreprocessor.cs
- MailAddressCollection.cs
- TransactionsSectionGroup.cs
- _SingleItemRequestCache.cs
- DefaultAssemblyResolver.cs
- FunctionGenerator.cs