using System; using System.Collections.Generic; using Microsoft.AnalysisServices; using Amo=Microsoft.AnalysisServices; namespace BismNormalizer.TabularCompare.MultidimensionalMetadata { /// /// Abstraction of a tabular model perspective with properties and methods for comparison purposes. /// public class Perspective : ITabularObject { private TabularModel _parentTabularModel; private Microsoft.AnalysisServices.Perspective _amoPerspective; private string _objectDefinition; private string _substituteId; /// /// Initializes a new instance of the Perspective class using multiple parameters. /// /// TabularModel object that the perspective belongs to. /// Analysis Management Objects Perspective object abtstracted by the Perspective class. public Perspective(TabularModel parentTabularModel, Amo.Perspective amoPerspective) { _parentTabularModel = parentTabularModel; _amoPerspective = amoPerspective; _objectDefinition = ""; List perspectiveTableNames = new List(); // put in here to sort foreach (PerspectiveDimension perspectiveDimension in _amoPerspective.Dimensions) { perspectiveTableNames.Add(perspectiveDimension.Dimension.Name); } // now need to check if there are measures/KPIs where no other table objects are selected in the perspective - because if so won't have a .Dimension value foreach (PerspectiveCalculation perspectiveCalculation in _amoPerspective.Calculations) { string measureName = perspectiveCalculation.Name.Replace("[Measures].[", "").Replace("]", ""); if (_parentTabularModel.Measures.ContainsName(measureName) && !perspectiveTableNames.Contains(_parentTabularModel.Measures.FindByName(measureName).TableName)) { perspectiveTableNames.Add(_parentTabularModel.Measures.FindByName(measureName).TableName); } } foreach (PerspectiveKpi perspectiveKpi in _amoPerspective.Kpis) { string kpiName = perspectiveKpi.ToString(); if (_parentTabularModel.Kpis.ContainsName(kpiName) && !perspectiveTableNames.Contains(_parentTabularModel.Kpis.FindByName(kpiName).TableName)) { perspectiveTableNames.Add(_parentTabularModel.Kpis.FindByName(kpiName).TableName); } } perspectiveTableNames.Sort(); foreach (string perspectiveTableName in perspectiveTableNames) { _objectDefinition += perspectiveTableName + "\n"; // find the PerspectiveDimension again foreach (PerspectiveDimension perspectiveDimension in _amoPerspective.Dimensions) { if (perspectiveDimension.Dimension.Name == perspectiveTableName) { //Attributes List perspectiveAttributeNames = new List(); // put in here to sort foreach (PerspectiveAttribute perspectiveAttribute in perspectiveDimension.Attributes) { perspectiveAttributeNames.Add(perspectiveAttribute.Attribute.Name); } perspectiveAttributeNames.Sort(); foreach (string perspectiveAttributeName in perspectiveAttributeNames) { _objectDefinition += " " + perspectiveAttributeName + "\n"; } //Hierarchies List perspectiveHierarchyNames = new List(); // put in here to sort foreach (PerspectiveHierarchy perspectiveHierarchy in perspectiveDimension.Hierarchies) { perspectiveHierarchyNames.Add(perspectiveHierarchy.Hierarchy.Name); } perspectiveHierarchyNames.Sort(); foreach (string perspectiveHierarchyName in perspectiveHierarchyNames) { _objectDefinition += " " + perspectiveHierarchyName + "\n"; } } } //Measures List perspectiveMeasureNames = new List(); // put in here to sort foreach (PerspectiveCalculation perspectiveCalculation in _amoPerspective.Calculations) { string measureName = perspectiveCalculation.Name.Replace("[Measures].[", "").Replace("]", ""); if (_parentTabularModel.Measures.ContainsName(measureName) && _parentTabularModel.Measures.FindByName(measureName).TableName == perspectiveTableName) { perspectiveMeasureNames.Add(measureName); } } perspectiveMeasureNames.Sort(); foreach (string perspectiveCalculationName in perspectiveMeasureNames) { _objectDefinition += " " + perspectiveCalculationName + "\n"; } //KPIs List perspectiveKpiNames = new List(); // put in here to sort foreach (PerspectiveKpi perspectiveKpi in _amoPerspective.Kpis) { string kpiName = perspectiveKpi.ToString(); if (_parentTabularModel.Kpis.ContainsName(kpiName) && _parentTabularModel.Kpis.FindByName(kpiName).TableName == perspectiveTableName && !perspectiveMeasureNames.Contains(kpiName)) //last check in case already added as a measure { perspectiveKpiNames.Add(kpiName); } } perspectiveKpiNames.Sort(); foreach (string perspectiveCalculationName in perspectiveKpiNames) { _objectDefinition += " " + perspectiveCalculationName + "\n"; } } //Actions List perspectiveActionNames = new List(); // put in here to sort foreach (PerspectiveAction perspectiveAction in _amoPerspective.Actions) { if (perspectiveAction.ParentCube.Actions.Contains(perspectiveAction.ActionID)) //need this check or .Action returns error { string actionName = perspectiveAction.Action.Name; if (_parentTabularModel.Actions.ContainsName(actionName)) { perspectiveActionNames.Add(actionName); } } } perspectiveActionNames.Sort(); foreach (string perspectiveActionName in perspectiveActionNames) { _objectDefinition += "Action: " + perspectiveActionName + "\n"; } //if (_parentTabularModel.ComparisonInfo.OptionsInfo.OptionTranslations) //{ // _objectDefinition += "\nFormat & Visibility:\nPerspective Translations: "; // if (_amoPerspective.Translations.Count > 0) // { // _objectDefinition += "["; // foreach (Translation perspectiveTranslation in _amoPerspective.Translations) // { // _objectDefinition += CultureInfo.GetCultureInfo(perspectiveTranslation.Language).DisplayName + ": " + perspectiveTranslation.Caption + ", "; // } // _objectDefinition = _objectDefinition.Substring(0, _objectDefinition.Length - 2) + "]"; // } // if (_parentTabularModel.ComparisonInfo.OptionsInfo.OptionDisplayFolders) // { // _objectDefinition += ", Display Folder Translations: "; // if (_amoPerspective.Translations.Count > 0) // { // _objectDefinition += "["; // foreach (Translation perspectiveDisplayFolderTranslation in _amoPerspective.Translations) // { // _objectDefinition += CultureInfo.GetCultureInfo(perspectiveDisplayFolderTranslation.Language).DisplayName + ": " + perspectiveDisplayFolderTranslation.DisplayFolder + ", "; // } // _objectDefinition = _objectDefinition.Substring(0, _objectDefinition.Length - 2) + "]"; // } // } // _objectDefinition += "\n"; //} _objectDefinition += "\n"; } /// /// TabularModel object that the Perspective object belongs to. /// public TabularModel ParentTabularModel => _parentTabularModel; /// /// Analysis Management Objects Perspective object abtstracted by the Perspective class. /// public Amo.Perspective AmoPerspective => _amoPerspective; /// /// Name of the Perspective object. /// public string Name => _amoPerspective.Name; /// /// Long name of the Perspective object. /// public string LongName => _amoPerspective.Name; /// /// Id of the Perspective object. /// public string Id => _amoPerspective.ID; /// /// Object definition of the Perspective object. This is a simplified list of relevant attribute values for comparison; not the XMLA definition of the abstracted AMO object. /// public string ObjectDefinition => _objectDefinition; /// /// Substitute id of the Perspective object. /// public string SubstituteId { get { if (string.IsNullOrEmpty(_substituteId)) { return _amoPerspective.ID; } else { return _substituteId; } } set { _substituteId = value; } } public override string ToString() => this.GetType().FullName; /// /// Verifies whether another Perspective object's selections are included in this Perspective object. /// /// The other Perspective object to be verified. /// True if otherPerspective matches. False if does not match. public bool ContainsOtherPerspectiveSelections(Perspective otherPerspective) { bool everythingMatches = true; //Tables foreach (PerspectiveDimension otherDimension in otherPerspective.AmoPerspective.Dimensions) { bool foundDimensionMatch = false; foreach (PerspectiveDimension perspectiveDimension in _amoPerspective.Dimensions) { if (perspectiveDimension.Dimension.Name == otherDimension.Dimension.Name) { foundDimensionMatch = true; //Columns foreach (PerspectiveAttribute otherAttribute in otherDimension.Attributes) { bool foundAttributeMatch = false; foreach (PerspectiveAttribute perspectiveAttribute in perspectiveDimension.Attributes) { if (perspectiveAttribute.Attribute.Name == otherAttribute.Attribute.Name) { foundAttributeMatch = true; break; } } if (!foundAttributeMatch) { everythingMatches = false; break; } } //Hierarchies foreach (PerspectiveHierarchy otherHierarchy in otherDimension.Hierarchies) { bool foundHierarchyMatch = false; foreach (PerspectiveHierarchy perspectiveHierarchy in perspectiveDimension.Hierarchies) { if (perspectiveHierarchy.Hierarchy.Name == otherHierarchy.Hierarchy.Name) { foundHierarchyMatch = true; break; } } if (!foundHierarchyMatch) { everythingMatches = false; break; } } } if (!everythingMatches) break; } if (!foundDimensionMatch) { everythingMatches = false; break; } } if (everythingMatches) { //Measures foreach (PerspectiveCalculation otherCalculation in otherPerspective.AmoPerspective.Calculations) { string measureName = otherCalculation.Name.Replace("[Measures].[", "").Replace("]", ""); if (otherPerspective.ParentTabularModel.Measures.ContainsName(measureName)) // this if clause shouldn't be necessary, but it is { bool foundCalculationMatch = false; foreach (PerspectiveCalculation perspectiveCalculation in _amoPerspective.Calculations) { if (perspectiveCalculation.Name == otherCalculation.Name) { foundCalculationMatch = true; break; } } if (!foundCalculationMatch) { everythingMatches = false; break; } } } } if (everythingMatches) { //Kpis foreach (PerspectiveKpi otherKpi in otherPerspective.AmoPerspective.Kpis) { string KpiName = otherKpi.ToString(); if (otherPerspective.ParentTabularModel.Kpis.ContainsName(KpiName)) { bool foundKpiMatch = false; foreach (PerspectiveKpi perspectiveKpi in _amoPerspective.Kpis) { if (perspectiveKpi.ToString() == otherKpi.ToString()) { foundKpiMatch = true; break; } } if (!foundKpiMatch) { everythingMatches = false; break; } } } } if (everythingMatches) { //Actions foreach (PerspectiveAction otherAction in otherPerspective.AmoPerspective.Actions) { bool foundActionMatch = false; foreach (PerspectiveAction perspectiveAction in _amoPerspective.Actions) { if (perspectiveAction.ParentCube.Actions.Contains(perspectiveAction.ActionID) && otherAction.ParentCube.Actions.Contains(otherAction.ActionID) && //need this check or .Action returns error perspectiveAction.Action.Name == otherAction.Action.Name) { foundActionMatch = true; break; } } if (!foundActionMatch) { everythingMatches = false; break; } } } if (everythingMatches) { //Translations foreach (Translation otherTranslation in otherPerspective.AmoPerspective.Translations) { bool foundActionMatch = false; foreach (Translation perspectiveTranslation in _amoPerspective.Translations) { if (perspectiveTranslation.Language == otherTranslation.Language && perspectiveTranslation.Caption == otherTranslation.Caption) { foundActionMatch = true; break; } } if (!foundActionMatch) { everythingMatches = false; break; } } } return everythingMatches; } } }