Esempio n. 1
0
        public static void BuildDependencyTree(IDaxDependantObject expressionObj)
        {
            ClearDependsOn(expressionObj);

            foreach (var prop in expressionObj.GetDAXProperties())
            {
                var dax = expressionObj.GetDAX(prop) ?? "";
                ParseExpression(dax, expressionObj, prop);
            }
        }
        public static IList <DaxToken> Tokenize(this IDaxDependantObject obj, DAXProperty property)
        {
            var result = new List <DaxToken>();
            var dax    = obj.GetDAX(property);

            if (string.IsNullOrEmpty(dax))
            {
                return(result);
            }
            var lexer = new DAXLexer(new DAXCharStream(obj.GetDAX(property), false));

            lexer.RemoveErrorListeners();
            var lexerTokens = lexer.GetAllTokens();

            for (int i = 0; i < lexerTokens.Count; i++)
            {
                result.Add(new DaxToken(lexerTokens[i], result, i));
            }

            return(result);
        }
Esempio n. 3
0
        internal void UpdateRef(IDaxObject renamedObj)
        {
            // This method is called on a DependsOnList, which belongs to a IDaxDependantObject. The argument is the IDaxObject which was typically renamed.
            // For example: The DependsOnList could be attached to a Measure [MyMeasure] with an expression such as: "COUNTROWS('MyTable')". If the name of
            // 'MyTable' was changed, this method would be called with 'MyTable' as the renamedObj and [MyMeasure] as Parent. It is then up to this method
            // to loop through all object references to 'MyTable' (see #1). As an IDaxDependantObject can have more than one DAX expression property, and an
            // object reference to 'MyTable' could exist in any of them, we must make sure to loop all the properties (#2)

            List <ObjectReference> depList;

            if (TryGetValue(renamedObj, out depList))   // #1 Get a list of object references for renamedObj
            {
                var orgDax = new string[DaxPropertyCount];
                var pos    = new int[DaxPropertyCount];
                var sbs    = new StringBuilder[DaxPropertyCount];

                foreach (var prop in Parent.GetDAXProperties())  // #2 Initialize a string buider and the original DAX for every DAX property on Parent
                {
                    var dax = Parent.GetDAX(prop);
                    if (dax != null)
                    {
                        sbs[(int)prop]    = new StringBuilder();
                        orgDax[(int)prop] = dax.Replace("\r", ""); // Carriage Returns are excluded when the dependency tree is built
                    }
                }

                // Loop through all dependencies:
                foreach (var dep in depList)
                {
                    var propIx = (int)dep.property;

                    var sb = sbs[propIx];

                    sb.Append(orgDax[propIx].Substring(pos[propIx], dep.from - pos[propIx]));
                    sb.Append(dep.fullyQualified ? renamedObj.DaxObjectFullName : renamedObj.DaxObjectName);
                    pos[propIx] = dep.to + 1;
                }

                // Finalize:
                foreach (var prop in Parent.GetDAXProperties())
                {
                    var propIx = (int)prop;

                    if (pos[propIx] > 0)
                    {
                        sbs[propIx].Append(orgDax[propIx].Substring(pos[propIx]));
                        Parent.SetDAX(prop, sbs[propIx].ToString());
                    }
                }
            }
        }
Esempio n. 4
0
        public static void BuildDependencyTree(IDaxDependantObject expressionObj)
        {
            foreach (var d in expressionObj.DependsOn.Keys)
            {
                d.ReferencedBy.Remove(expressionObj);
            }
            expressionObj.DependsOn.Clear();

            foreach (var prop in expressionObj.GetDAXProperties())
            {
                var dax = expressionObj.GetDAX(prop) ?? "";
                ParseExpression(dax, expressionObj, prop);
            }
        }
Esempio n. 5
0
        internal void UpdateRef(IDaxObject renamedObj)
        {
            List <ObjectReference> depList;

            if (TryGetValue(renamedObj, out depList))
            {
                var propertyCount = Enum.GetValues(typeof(DAXProperty)).Length;
                var pos           = new int[propertyCount];
                var sbs           = new StringBuilder[propertyCount];
                for (var i = 0; i < propertyCount; i++)
                {
                    sbs[i] = new StringBuilder();
                }

                // Loop through all dependencies:
                foreach (var dep in depList)
                {
                    var propIx = (int)dep.property;

                    var sb = sbs[propIx];

                    sb.Append(Parent.GetDAX(dep.property).Substring(pos[propIx], dep.from - pos[propIx]));
                    sb.Append(dep.fullyQualified ? renamedObj.DaxObjectFullName : renamedObj.DaxObjectName);
                    pos[propIx] = dep.to + 1;
                }

                // Finalize:
                for (var i = 0; i < propertyCount; i++)
                {
                    if (pos[i] > 0)
                    {
                        sbs[i].Append(Parent.GetDAX((DAXProperty)i).Substring(pos[i]));
                        Parent.SetDAX((DAXProperty)i, sbs[i].ToString());
                    }
                }
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Rebuilds the dependency tree for the provided object. If within a BeginUpdate / EndUpdate batch,
        /// this operation is postponed until the batch ends unless force is set to true.
        /// </summary>
        /// <param name="expressionObj"></param>
        /// <param name="force"></param>
        public static void BuildDependencyTree(IDaxDependantObject expressionObj, bool force = false)
        {
            if (Handler.EoB_PostponeOperations && !force)
            {
                Handler.EoB_RequireRebuildDependencyTree = true; return;
            }

            ClearDependsOn(expressionObj);

            foreach (var prop in expressionObj.GetDAXProperties())
            {
                var dax = expressionObj.GetDAX(prop) ?? "";
                ParseExpression(dax, expressionObj, prop);
            }
        }
Esempio n. 7
0
        private void FixUpTest(TabularModelHandler tmh, IDaxDependantObject obj, Utils.DAXProperty property, bool isFullyQualified, Table tableRef, IDaxObject objRef)
        {
            var baseExpression = obj.GetDAX(property);

            if (isFullyQualified)
            {
                Assert.AreEqual(2, obj.DependsOn.Count);

                Assert.AreSame(tableRef, obj.DependsOn[0]);
                var references = obj.DependsOn[tableRef];
                Assert.AreEqual(1, references.Count);
                Assert.AreEqual(property, references[0].property);
                Assert.IsTrue(references[0].fullyQualified);

                Assert.AreSame(objRef, obj.DependsOn[1]);
                references = obj.DependsOn[objRef];
                Assert.AreEqual(1, references.Count);
                Assert.AreEqual(property, references[0].property);
                Assert.IsTrue(references[0].fullyQualified);
            }
            else
            {
                Assert.AreEqual(1, obj.DependsOn.Count);

                Assert.AreSame(objRef, obj.DependsOn[0]);
                var references = obj.DependsOn[objRef];
                Assert.AreEqual(1, references.Count);
                Assert.AreEqual(property, references[0].property);
                Assert.IsFalse(references[0].fullyQualified);
            }

            var expression = baseExpression;

            var oldObjName = objRef.Name;

            objRef.Name = oldObjName + " Renamed";
            var expr1 = expression = expression.Replace(oldObjName, objRef.Name);

            Assert.AreEqual(expression, obj.GetDAX(property));

            var oldTableName = tableRef.Name;

            tableRef.Name = oldTableName + " Renamed";
            var expr2 = expression = expression.Replace(oldTableName, tableRef.Name);

            Assert.AreEqual(expression, obj.GetDAX(property));

            oldObjName  = objRef.Name;
            objRef.Name = "b b";
            var expr3 = expression = expression.Replace(oldObjName, objRef.Name);

            Assert.AreEqual(expression, obj.GetDAX(property));

            oldTableName  = tableRef.Name;
            tableRef.Name = "a a";
            var expr4 = expression = expression.Replace(oldTableName, tableRef.Name);

            Assert.AreEqual(expression, obj.GetDAX(property));

            tmh.UndoManager.Undo();
            Assert.AreEqual(expr3, obj.GetDAX(property));

            tmh.UndoManager.Undo();
            Assert.AreEqual(expr2, obj.GetDAX(property));

            tmh.UndoManager.Undo();
            Assert.AreEqual(expr1, obj.GetDAX(property));

            tmh.UndoManager.Undo();
            Assert.AreEqual(baseExpression, obj.GetDAX(property));
        }
Esempio n. 8
0
        public static void BuildDependencyTree(IDaxDependantObject expressionObj)
        {
            foreach (var d in expressionObj.DependsOn.Keys)
            {
                d.ReferencedBy.Remove(expressionObj);
            }
            expressionObj.DependsOn.Clear();

            foreach (var prop in expressionObj.GetDAXProperties())
            {
                var tokens = new DAXLexer(new AntlrInputStream(expressionObj.GetDAX(prop) ?? "")).GetAllTokens();

                IToken lastTableRef    = null;
                int    startTableIndex = 0;

                for (var i = 0; i < tokens.Count; i++)
                {
                    // TODO: This parsing could be used to check for invalid object references, for example to use in syntax highlighting or validation of expressions

                    var tok = tokens[i];
                    switch (tok.Type)
                    {
                    case DAXLexer.TABLE:
                    case DAXLexer.TABLE_OR_VARIABLE:
                        if (i < tokens.Count - 1 && tokens[i + 1].Type == DAXLexer.COLUMN_OR_MEASURE)
                        {
                            // Keep the token reference, as the next token should be column (fully qualified).
                            lastTableRef    = tok;
                            startTableIndex = tok.StartIndex;
                        }
                        else
                        {
                            // Table referenced directly, don't save the reference for the next token.
                            lastTableRef = null;
                        }

                        if (Model.Tables.Contains(tok.Text.NoQ(true)))
                        {
                            expressionObj.AddDep(Model.Tables[tok.Text.NoQ(true)], prop, tok.StartIndex, tok.StopIndex, true);
                        }
                        else
                        {
                            // Invalid reference (no table with that name) or possibly a variable or function ref
                        }
                        break;

                    case DAXLexer.COLUMN_OR_MEASURE:
                        // Referencing a table just before the object reference
                        if (lastTableRef != null)
                        {
                            var tableName = lastTableRef.Text.NoQ(true);
                            lastTableRef = null;
                            if (!Model.Tables.Contains(tableName))
                            {
                                return;                                        // Invalid reference (no table with that name)
                            }
                            var table = Model.Tables[tableName];
                            // Referencing a column on a specific table
                            if (table.Columns.Contains(tok.Text.NoQ()))
                            {
                                expressionObj.AddDep(table.Columns[tok.Text.NoQ()], prop, startTableIndex, tok.StopIndex, true);
                            }
                            // Referencing a measure on a specific table
                            else if (table.Measures.Contains(tok.Text.NoQ()))
                            {
                                expressionObj.AddDep(table.Measures[tok.Text.NoQ()], prop, startTableIndex, tok.StopIndex, true);
                            }
                        }
                        // No table reference before the object reference
                        else
                        {
                            var table = (expressionObj as ITabularTableObject)?.Table;
                            // Referencing a column without specifying a table (assume column in same table):
                            if (table != null && table.Columns.Contains(tok.Text.NoQ()))
                            {
                                expressionObj.AddDep(table.Columns[tok.Text.NoQ()], prop, tok.StartIndex, tok.StopIndex, false);
                            }
                            // Referencing a measure or column without specifying a table
                            else
                            {
                                Measure m = null;
                                if (table != null && table.Measures.Contains(tok.Text.NoQ()))
                                {
                                    m = table.Measures[tok.Text.NoQ()];
                                }
                                else
                                {
                                    m = Model.Tables.FirstOrDefault(t => t.Measures.Contains(tok.Text.NoQ()))?.Measures[tok.Text.NoQ()];
                                }

                                if (m != null)
                                {
                                    expressionObj.AddDep(m, prop, tok.StartIndex, tok.StopIndex, false);
                                }
                            }
                        }
                        break;

                    default:
                        lastTableRef = null;
                        break;
                    }
                }
            }
        }