internal new static CalculationGroupTable CreateFromMetadata(Model parent, TOM.Table metadataObject)
        {
            if (metadataObject.GetSourceType() != TOM.PartitionSourceType.CalculationGroup)
            {
                throw new ArgumentException("Provided metadataObject is not a Calculation Group Table.");
            }

            // Generate a new LineageTag if an object with the provided lineage tag already exists:
            if (!string.IsNullOrEmpty(metadataObject.LineageTag))
            {
                if (parent.Handler.CompatibilityLevel < 1540)
                {
                    metadataObject.LineageTag = null;
                }
                else if (parent.MetadataObject.Tables.FindByLineageTag(metadataObject.LineageTag) != metadataObject)
                {
                    metadataObject.LineageTag = Guid.NewGuid().ToString();
                }
            }

            var obj = new CalculationGroupTable(metadataObject);

            parent.Tables.Add(obj);

            obj.Init();
            //obj.NameField = new CalculationGroupAttribute(obj.DataColumns.First());

            return(obj);
        }
Example #2
0
 protected override void Init()
 {
     if (!string.IsNullOrEmpty(ErrorMessage))
     {
         CalculationGroupTable.AddError(this);
     }
     base.Init();
 }
Example #3
0
        public CalculationGroupTable AddCalculationGroup(string name = null)
        {
            Handler.BeginUpdate("add calculation group");
            var t = CalculationGroupTable.CreateNew(this, name);

            Handler.EndUpdate();
            return(t);
        }
        public void MoveCalculationItem(CalculationItem item, CalculationGroupTable newCgt)
        {
            var name = item.Name;

            item.Delete();
            item.RenewMetadataObject();
            item.MetadataObject.Name = newCgt.CalculationItems.GetNewName(name);
            newCgt.CalculationItems.Add(item);
        }
 protected override void OnPropertyChanging(string propertyName, object newValue, ref bool undoable, ref bool cancel)
 {
     if (propertyName == Properties.ORDINAL)
     {
         // No automatic handling of Ordinal changes. We will handle it manually in the calculation group's FixItemOrder() method.
         cancel = true;
         this.MetadataObject.Ordinal = (int)newValue;
         CalculationGroupTable.FixItemOrder(this, (int)newValue);
     }
 }
Example #6
0
        public CalculationGroupTable AddCalculationGroup(string name = null)
        {
            Handler.BeginUpdate("add calculation group");
            var maxPrecedence = Model.CalculationGroups.Select(c => c.CalculationGroupPrecedence).DefaultIfEmpty(-1).Max();
            var t             = CalculationGroupTable.CreateNew(this, name);

            t.CalculationGroupPrecedence = maxPrecedence + 1;
            Handler.Tree.RebuildFolderCacheForTable(t);
            Handler.EndUpdate();
            return(t);
        }
        internal new static CalculationGroupTable CreateFromMetadata(Model parent, TOM.Table metadataObject)
        {
            if (metadataObject.GetSourceType() != TOM.PartitionSourceType.CalculationGroup)
            {
                throw new ArgumentException("Provided metadataObject is not a Calculation Group Table.");
            }
            var obj = new CalculationGroupTable(metadataObject);

            parent.Tables.Add(obj);

            obj.Init();
            //obj.NameField = new CalculationGroupAttribute(obj.DataColumns.First());

            return(obj);
        }
Example #8
0
        public CalculationGroupTable AddCalculationGroup(string name = null)
        {
            if (!Handler.PowerBIGovernance.AllowCreate(typeof(CalculationGroupTable)))
            {
                throw new PowerBIGovernanceException("Adding Calculation Groups to this Power BI model is not supported.");
            }

            Handler.BeginUpdate("add calculation group");
            var maxPrecedence = Model.CalculationGroups.Select(c => c.CalculationGroupPrecedence).DefaultIfEmpty(-1).Max();
            var t             = CalculationGroupTable.CreateNew(this, name);

            t.CalculationGroupPrecedence = maxPrecedence + 1;
            Handler.Tree.RebuildFolderCacheForTable(t);
            Handler.EndUpdate();
            return(t);
        }
        /// <summary>
        /// Inserts the specified list of objects into the model, at the optional destination. Objects that cannot
        /// be meaningfully inserted in the destination, will be inserted at the destination parent (recursively).
        /// If no suitable destination can be found, insertion will be ignored.
        /// Useful for drag-and-drop or copy-paste operations.
        /// </summary>
        /// <param name="objects"></param>
        /// <param name="destination"></param>
        public List <TabularObject> InsertObjects(ObjectJsonContainer objectContainer, ITabularNamedObject destination = null)
        {
            // Possible destinations:
            var destHier  = (destination as Level)?.Hierarchy ?? (destination as Hierarchy);
            var destTable = (destination as Folder)?.Table ?? (destination as Partition)?.Table ?? destHier?.Table ?? (destination as IFolderObject)?.Table ?? (destination as Table);
            var folder    = (destination as Folder)?.Path;

            bool    replaceTable             = false;
            string  replaceTableName         = "";
            JObject replaceTableJobj         = null;
            bool    replaceTableIsCalculated = false;

            // If the object container only holds a single object, and that object is a table, let's ask the user if they want to
            // replace the destination table with the table in the clipboard (unless of course it's the same table).
            if (destTable != null && objectContainer.Count == 1 && (objectContainer.Get <CalculatedTable>().Count() == 1 || objectContainer.Get <Table>().Count() == 1))
            {
                replaceTableIsCalculated = objectContainer.Get <CalculatedTable>().Any();
                replaceTableJobj         = objectContainer.Get <CalculatedTable>().FirstOrDefault() ?? objectContainer.Get <Table>().FirstOrDefault();
                replaceTableName         = replaceTableJobj["name"].ToString();

                // Check that the object came from a different instance, or that its another table:
                if (objectContainer.InstanceID != Handler.InstanceID || !destTable.Name.StartsWith(replaceTableName))
                {
                    var result = MessageBox.Show($"Do you want to replace table '{destTable.Name}' with table '{replaceTableName}' from the clipboard?\n\nExisting relationships will be kept, provided participating columns have the same name and data types in both the replaced and the inserted table.", "Replace existing table?", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Information);
                    if (result == DialogResult.Cancel)
                    {
                        return(new List <TabularObject>());
                    }
                    if (result == DialogResult.Yes)
                    {
                        replaceTable = true;
                    }
                }
            }

            Handler.BeginUpdate("Paste objects");

            var inserted = new List <TabularObject>();

            if (destHier != null)
            {
                // Levels can only be deserialized on a Hierarchy destination:
                foreach (var obj in objectContainer.Get <Level>())
                {
                    inserted.Add(Serializer.DeserializeLevel(obj, destHier));
                }
                destHier.CompactLevelOrdinals();
            }

            if (destTable?.GetType() == typeof(Table))
            {
                // DataColumns and Partitions can only be deserialized onto a Table destination (not CalculatedTable):
                foreach (var obj in objectContainer.Get <DataColumn>().OrderBy(obj => obj["sortByColumn"] == null ? 0 : 1))
                {
                    inserted.Add(Serializer.DeserializeDataColumn(obj, destTable));
                }
                foreach (var obj in objectContainer.Get <Partition>())
                {
                    inserted.Add(Serializer.DeserializePartition(obj, destTable));
                }
                foreach (var obj in objectContainer.Get <MPartition>())
                {
                    inserted.Add(Serializer.DeserializeMPartition(obj, destTable));
                }
            }

            if (destTable is Table)
            {
                // Measures, Hierarchies and CalculatedColumns can be deserialized onto a Table (or Table derived) destination:
                foreach (var obj in objectContainer.Get <CalculatedColumn>().OrderBy(obj => obj["sortByColumn"] == null ? 0 : 1))
                {
                    inserted.Add(Serializer.DeserializeCalculatedColumn(obj, destTable));
                }
                foreach (var obj in objectContainer.Get <Hierarchy>())
                {
                    inserted.Add(Serializer.DeserializeHierarchy(obj, destTable));
                }
                foreach (var obj in objectContainer.Get <Measure>())
                {
                    inserted.Add(Serializer.DeserializeMeasure(obj, destTable));
                }
            }

            // Replace an existing table with the one from the clipboard:
            if (replaceTable)
            {
                if (destTable.Name == replaceTableName)
                {
                    // Similarly named tables - disable formula fixup:
                    var fixupSetting = Handler.Settings.AutoFixup;
                    Handler.Settings.AutoFixup = false;
                    destTable.Name             = destTable.Name + '-' + Guid.NewGuid().ToString();
                    Handler.Settings.AutoFixup = true;
                }
                else
                {
                    // Differently named tables:
                    // First, let's rename the destTable to match the new table (fix-up will handle DAX references):
                    if (destTable.Name != replaceTableName)
                    {
                        destTable.Name = replaceTableName;
                    }

                    // Secondly, let's rename the table to be inserted (to avoid naming conflicts):
                    replaceTableJobj["name"] = replaceTableName + '-' + Guid.NewGuid().ToString();
                }

                // Insert the table:
                var newTable = replaceTableIsCalculated ?
                               Serializer.DeserializeCalculatedTable(replaceTableJobj, Handler.Model) :
                               Serializer.DeserializeTable(replaceTableJobj, Handler.Model);
                inserted.Add(newTable);

                // Update relationships to point to the inserted table:
                foreach (var rel in destTable.UsedInRelationships.ToList())
                {
                    if (rel.FromTable == destTable && newTable.Columns.Contains(rel.FromColumn.Name) && rel.FromColumn.DataType == newTable.Columns[rel.FromColumn.Name].DataType)
                    {
                        rel.FromColumn = newTable.Columns[rel.FromColumn.Name];
                    }
                    if (rel.ToTable == destTable && newTable.Columns.Contains(rel.ToColumn.Name) && rel.ToColumn.DataType == newTable.Columns[rel.ToColumn.Name].DataType)
                    {
                        rel.ToColumn = newTable.Columns[rel.ToColumn.Name];
                    }
                }

                // Delete original table:
                destTable.Delete();

                // Rename inserted table:
                newTable.Name = replaceTableName;
            }
            else
            {
                foreach (var obj in objectContainer.Get <CalculatedTable>())
                {
                    inserted.Add(Serializer.DeserializeCalculatedTable(obj, Handler.Model));
                }
                foreach (var obj in objectContainer.Get <Table>())
                {
                    inserted.Add(Serializer.DeserializeTable(obj, Handler.Model));
                }
            }

            foreach (var obj in objectContainer.Get <ModelRole>())
            {
                inserted.Add(Serializer.DeserializeModelRole(obj, Handler.Model));
            }
            foreach (var obj in objectContainer.Get <ProviderDataSource>())
            {
                inserted.Add(Serializer.DeserializeProviderDataSource(obj, Handler.Model));
            }
            foreach (var obj in objectContainer.Get <SingleColumnRelationship>())
            {
                inserted.Add(Serializer.DeserializeSingleColumnRelationship(obj, Handler.Model));
            }
            foreach (var obj in objectContainer.Get <Perspective>())
            {
                inserted.Add(Serializer.DeserializePerspective(obj, Handler.Model));
            }
            foreach (var obj in objectContainer.Get <Culture>())
            {
                inserted.Add(Serializer.DeserializeCulture(obj, Handler.Model));
            }

            if (Handler.CompatibilityLevel >= 1400)
            {
                foreach (var obj in objectContainer.Get <NamedExpression>())
                {
                    inserted.Add(Serializer.DeserializeNamedExpression(obj, Handler.Model));
                }
                foreach (var obj in objectContainer.Get <StructuredDataSource>())
                {
                    inserted.Add(Serializer.DeserializeStructuredDataSource(obj, Handler.Model));
                }
            }

            if (Handler.CompatibilityLevel >= 1470)
            {
                CalculationGroupTable destCalcGroup = destination is CalculationGroupTable cgt ? cgt :
                                                      (destination is CalculationItem ci ? ci.CalculationGroupTable : null);
                if (destCalcGroup != null)
                {
                    foreach (var obj in objectContainer.Get <CalculationItem>())
                    {
                        inserted.Add(Serializer.DeserializeCalculationItem(obj, destCalcGroup));
                    }
                }
                foreach (var obj in objectContainer.Get <CalculationGroupTable>())
                {
                    inserted.Add(Serializer.DeserializeCalculationGroupTable(obj, Handler.Model));
                }
            }

            foreach (var obj in inserted)
            {
                var tableObj = obj as Table;

                (obj as IInternalTranslatableObject)?.LoadTranslations(true);
                (obj as IInternalTabularPerspectiveObject)?.LoadPerspectives(true);
                if (tableObj != null)
                {
                    tableObj.LoadRLS();
                    Handler.Tree.RebuildFolderCacheForTable(tableObj);
                }

                if (!string.IsNullOrEmpty(folder) && obj is IFolderObject)
                {
                    (obj as IFolderObject).DisplayFolder = folder;
                }

                if (Handler.CompatibilityLevel >= 1400)
                {
                    if (tableObj != null)
                    {
                        tableObj.LoadOLS(true);
                    }
                    (obj as Column)?.LoadOLS();
                }

                (obj as IInternalAnnotationObject)?.ClearTabularEditorAnnotations();
            }

            Handler.EndUpdate();
            FormulaFixup.BuildDependencyTree();

            return(inserted);
        }
 public void AddCalcItemsToCalcGroup(IEnumerable <CalculationItem> items, CalculationGroupTable destination, int firstOrdinal = -1)
 {
 }