Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Map / ViewGeneration / Structures / CaseStatement.cs / 1305376 / 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 MemberProjectedSlot) { return true; } foreach (WhenThen whenThen in m_clauses) { if (whenThen.Value is MemberProjectedSlot) { 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; ConstantProjectedSlot constantSlot = slot as ConstantProjectedSlot; 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) { ConstantProjectedSlot constantSlot = clause.Value as ConstantProjectedSlot; // 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 ConstantProjectedSlot(Constant.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)) { ConstantProjectedSlot typeConstantSlot = projectedSlot as ConstantProjectedSlot; 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 MemberProjectedSlot || slot is AliasedSlot || slot is ConstantProjectedSlot, "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
- ExpandCollapseProviderWrapper.cs
- WebControlAdapter.cs
- ActivityDesignerHelper.cs
- UserControlParser.cs
- SelectionWordBreaker.cs
- StrokeNodeEnumerator.cs
- MenuEventArgs.cs
- StringKeyFrameCollection.cs
- DefaultProxySection.cs
- Switch.cs
- DesignTimeHTMLTextWriter.cs
- IntPtr.cs
- ReversePositionQuery.cs
- QilStrConcatenator.cs
- documentsequencetextview.cs
- Point4D.cs
- SimpleType.cs
- WebScriptClientGenerator.cs
- IsolatedStorageFile.cs
- Image.cs
- XmlUnspecifiedAttribute.cs
- LogicalChannelCollection.cs
- ModelItem.cs
- WebEvents.cs
- TypeReference.cs
- Mouse.cs
- FieldNameLookup.cs
- UndoUnit.cs
- TextSelection.cs
- OptimizedTemplateContentHelper.cs
- FillBehavior.cs
- WaitForChangedResult.cs
- TextEndOfParagraph.cs
- SoapConverter.cs
- DataGridViewTextBoxColumn.cs
- CalendarDesigner.cs
- InstallerTypeAttribute.cs
- Documentation.cs
- CodeTypeOfExpression.cs
- DataGridViewAccessibleObject.cs
- ReflectionUtil.cs
- HintTextConverter.cs
- PrintDialog.cs
- DataGridCommandEventArgs.cs
- AgileSafeNativeMemoryHandle.cs
- DispatcherEventArgs.cs
- Column.cs
- Span.cs
- FtpCachePolicyElement.cs
- JavaScriptString.cs
- DBDataPermission.cs
- VectorValueSerializer.cs
- SingleConverter.cs
- WebPermission.cs
- Mouse.cs
- CollectionExtensions.cs
- ControlCollection.cs
- RestHandlerFactory.cs
- AppSettingsReader.cs
- CategoryNameCollection.cs
- PenLineCapValidation.cs
- SqlDependencyUtils.cs
- BaseProcessProtocolHandler.cs
- TextEffect.cs
- ReadOnlyHierarchicalDataSource.cs
- ChtmlTextWriter.cs
- ArglessEventHandlerProxy.cs
- WindowHelperService.cs
- NonSerializedAttribute.cs
- MSAAEventDispatcher.cs
- CompressStream.cs
- CaseInsensitiveHashCodeProvider.cs
- ScrollableControl.cs
- versioninfo.cs
- ReflectionServiceProvider.cs
- AggregatePushdown.cs
- GridItemProviderWrapper.cs
- XmlUtil.cs
- ExpressionBuilderContext.cs
- HandlerBase.cs
- Mappings.cs
- SpellerError.cs
- CommandCollectionEditor.cs
- DiagnosticTraceRecords.cs
- ObjectStateManagerMetadata.cs
- XNodeNavigator.cs
- LinqDataSourceSelectEventArgs.cs
- StackBuilderSink.cs
- DeclaredTypeElementCollection.cs
- Ray3DHitTestResult.cs
- WebPartCatalogCloseVerb.cs
- Boolean.cs
- UserValidatedEventArgs.cs
- MetabaseServerConfig.cs
- ValidationHelper.cs
- entitydatasourceentitysetnameconverter.cs
- ApplicationHost.cs
- PathGradientBrush.cs
- Decoder.cs
- AsymmetricAlgorithm.cs