Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / ndp / fx / src / DataEntity / System / Data / Map / ViewGeneration / Structures / CaseStatement.cs / 2 / 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
- AsyncCompletedEventArgs.cs
- CodeParameterDeclarationExpressionCollection.cs
- storepermissionattribute.cs
- AttributeCollection.cs
- ReadContentAsBinaryHelper.cs
- Pkcs7Recipient.cs
- SQLByteStorage.cs
- DataSourceView.cs
- XmlnsDictionary.cs
- DuplexChannelBinder.cs
- BindingExpressionUncommonField.cs
- HostingEnvironmentException.cs
- SQLCharsStorage.cs
- PointLight.cs
- BinaryFormatter.cs
- LineBreakRecord.cs
- WindowsStatic.cs
- OleDbStruct.cs
- XamlWrappingReader.cs
- TreeNodeMouseHoverEvent.cs
- COM2Properties.cs
- FormViewCommandEventArgs.cs
- ProtectedUri.cs
- DiagnosticTraceSource.cs
- ConfigurationStrings.cs
- util.cs
- AutoGeneratedField.cs
- FontUnitConverter.cs
- HtmlTable.cs
- MultiView.cs
- RoleManagerModule.cs
- MergeLocalizationDirectives.cs
- PreviewPageInfo.cs
- DetailsViewCommandEventArgs.cs
- Visual3D.cs
- SmtpFailedRecipientsException.cs
- HttpVersion.cs
- InternalCache.cs
- TemplatePartAttribute.cs
- FilterFactory.cs
- ProcessModuleCollection.cs
- EventMappingSettingsCollection.cs
- PerformanceCounterCategory.cs
- DefaultBinder.cs
- CodeAttributeDeclaration.cs
- ConnectionsZoneAutoFormat.cs
- SoapObjectInfo.cs
- FormsAuthenticationUserCollection.cs
- MorphHelper.cs
- SqlParameterizer.cs
- InvalidCastException.cs
- DBSqlParserColumn.cs
- FileLogRecordHeader.cs
- XmlSchemaComplexContent.cs
- PreservationFileReader.cs
- Helper.cs
- SqlTransaction.cs
- DataChangedEventManager.cs
- DataBindEngine.cs
- CircleEase.cs
- FrameworkEventSource.cs
- UnicodeEncoding.cs
- hresults.cs
- RangeValuePattern.cs
- VisualStates.cs
- ClaimTypeElementCollection.cs
- HighContrastHelper.cs
- COM2FontConverter.cs
- ListViewGroupItemCollection.cs
- ListBase.cs
- LicenseContext.cs
- ConnectionConsumerAttribute.cs
- SqlTypeSystemProvider.cs
- UnescapedXmlDiagnosticData.cs
- ConfigXmlAttribute.cs
- GcHandle.cs
- StateFinalizationDesigner.cs
- PeerObject.cs
- DesignerSerializationOptionsAttribute.cs
- DynamicMethod.cs
- MdImport.cs
- FlowDocumentScrollViewer.cs
- ConfigurationManagerInternalFactory.cs
- IntegerValidatorAttribute.cs
- Message.cs
- PersonalizationAdministration.cs
- remotingproxy.cs
- Clause.cs
- ImpersonationOption.cs
- Crc32Helper.cs
- BamlLocalizerErrorNotifyEventArgs.cs
- IItemContainerGenerator.cs
- TextFormatterContext.cs
- LaxModeSecurityHeaderElementInferenceEngine.cs
- ColorAnimationUsingKeyFrames.cs
- AnnotationResourceCollection.cs
- WebHeaderCollection.cs
- Marshal.cs
- GenericTextProperties.cs
- unsafenativemethodsother.cs