Example #1
0
        /// <summary>
        /// If name is null or invalid, throws an InvalidNameException.
        ///
        /// Otherwise, the contents of the named cell becomes number.  The method returns a
        /// set consisting of name plus the names of all other cells whose value depends,
        /// directly or indirectly, on the named cell.
        ///
        /// For example, if name is A1, B1 contains A1*2, and C1 contains B1+A1, the
        /// set {A1, B1, C1} is returned.
        /// </summary>
        protected override ISet <String> SetCellContents(String cell_name, double number)
        {
            string name = Normalize(cell_name);

            //checks if the name is null or invalid if so throws a new InvalidNameException();
            if (name == null || IsValid(name) == false)
            {
                throw new InvalidNameException();
            }
            //checks if the cell with the name has been set up, if so this sets the contents of the cell to the number passed in.
            if (spreadsheet.ContainsKey(name))
            {
                spreadsheet[name].set_contents(number);
            }
            //if the cell hasnt been set up this creates a new cell and sets its contents to the number passed in.
            else
            {
                spreadsheet.Add(name, new Cell(name, number, number));
            }
            //creates a hash set for the return ISet.
            ISet <string> depends = new HashSet <string> {
            };

            //looks through each item in the dependency graph and add them to the hash set to return.
            foreach (string item in GetCellsToRecalculate(name))
            {
                depends.Add(item);
            }
            List <string> dependency_fix = new List <string> {
            };

            spreadsheet[name].set_value(number);
            foreach (string value in dependency_graph.GetDependees(name))
            {
                dependency_fix.Add(value);
            }
            foreach (string key in dependency_fix)
            {
                dependency_graph.RemoveDependency(key, name);
            }
            IEnumerable <string> recalculate_cells = GetCellsToRecalculate(name);

            foreach (string cell in recalculate_cells)
            {
                if (!(cell == name))
                {
                    Formula value_of_formula = (Formula)GetCellContents(cell);
                    spreadsheet[cell].set_value(value_of_formula.Evaluate(Lookup));
                }
            }
            //returns the hash set with all the dependents of name.
            return(depends);
        }
Example #2
0
        /// <summary>
        /// Returns and enumeration without duplicates of all the direct dependents of
        /// the named cell.
        /// </summary>
        /// <param name="name">Cell to look for all direct dependents</param>
        /// <returns>An enumerable collection of direct dependents without duplicates.</returns>
        protected override IEnumerable <string> GetDirectDependents(string name)
        {
            if (name == null)
            {
                throw new ArgumentNullException();
            }

            name.isLegalVar();

            // Simply get the dependees from the graph.
            HashSet <string> DirectDependents = new HashSet <string>(Graph.GetDependees(name));

            return(DirectDependents);
        }
Example #3
0
        /// <summary>
        /// If the formula parameter is null, throws an ArgumentNullException.
        ///
        /// Otherwise, if name is null or invalid, throws an InvalidNameException.
        ///
        /// Otherwise, if changing the contents of the named cell to be the formula would cause a
        /// circular dependency, throws a CircularException.  (No change is made to the spreadsheet.)
        ///
        /// Otherwise, the contents of the named cell becomes formula.  The method returns a
        /// Set consisting of name plus the names of all other cells whose value depends,
        /// directly or indirectly, on the named cell.
        ///
        /// For example, if name is A1, B1 contains A1*2, and C1 contains B1+A1, the
        /// set {A1, B1, C1} is returned.
        /// </summary>
        protected override ISet <string> SetCellContents(string name, Formula formula)
        {
            IEnumerable <String> dependee_list = dependency_graph.GetDependees(name);

            dependency_graph.ReplaceDependees(name, formula.GetVariables());

            try
            {
                HashSet <String> all_dependees = new HashSet <String>(GetCellsToRecalculate(name));

                if (cell.ContainsKey(name))
                {
                    cell[name] = new Cell(formula, LookupValue);
                }
                else
                {
                    cell.Add(name, new Cell(formula, LookupValue));
                }

                return(all_dependees);
            }

            catch (CircularException)
            {
                dependency_graph.ReplaceDependees(name, dependee_list);
                throw new CircularException();
            }
        }
        // MODIFIED PROTECTION FOR PS5
        /// <summary>
        /// If formula parameter is null, throws an ArgumentNullException.
        ///
        /// Otherwise, if name is null or invalid, throws an InvalidNameException.
        ///
        /// Otherwise, if changing the contents of the named cell to be the formula would cause a
        /// circular dependency, throws a CircularException.
        ///
        /// Otherwise, the contents of the named cell becomes formula.  The method returns a
        /// Set consisting of name plus the names of all other cells whose value depends,
        /// directly or indirectly, on the named cell.
        ///
        /// For example, if name is A1, B1 contains A1*2, and C1 contains B1+A1, the
        /// set {A1, B1, C1} is returned.
        /// </summary>
        protected override ISet <String> SetCellContents(String name, Formula formula)
        {
            //backup the part of depGraph that will be modified
            HashSet <string> backupDependees = new HashSet <string>(depGraph.GetDependees(name));
            HashSet <string> dependents;

            //modify depGraph
            depGraph.ReplaceDependees(name, formula.GetVariables());

            //check for circular dependencies
            try
            {
                dependents = new HashSet <string>(GetCellsToRecalculate(name));
            }
            catch (CircularException exception)
            {
                //restore the backup in the chance a circular exception is thrown
                depGraph.ReplaceDependees(name, backupDependees);
                throw exception;
            }

            SetContents(name, formula);
            //recalculate potentially changed cells
            RecalculateCells(GetCellsToRecalculate(name));
            return(dependents);
        }
Example #5
0
        /// <summary>
        /// If the formula parameter is null, throws an ArgumentNullException.
        ///
        /// Otherwise, if name is null or invalid, throws an InvalidNameException.
        ///
        /// Otherwise, if changing the contents of the named cell to be the formula would cause a
        /// circular dependency, throws a CircularException.  (No change is made to the spreadsheet.)
        ///
        /// Otherwise, the contents of the named cell becomes formula.  The method returns a
        /// Set consisting of name plus the names of all other cells whose value depends,
        /// directly or indirectly, on the named cell.
        ///
        /// For example, if name is A1, B1 contains A1*2, and C1 contains B1+A1, the
        /// set {A1, B1, C1} is returned.
        /// </summary>
        protected override ISet <string> SetCellContents(string name, Formula formula)
        {
            IEnumerable <string> dependeesList1 = graph.GetDependees(name);

            graph.ReplaceDependees(name, formula.GetVariables());


            try
            {
                HashSet <string> dependeeslist2 = new HashSet <string>(GetCellsToRecalculate(name));

                Cell newCell = new Cell(formula, valueOfCell);
                if (spreadsheet.ContainsKey(name))
                {
                    spreadsheet[name] = newCell;
                }
                else
                {
                    spreadsheet.Add(name, newCell);
                }



                return(dependeeslist2);
            }
            catch (CircularException)
            {
                graph.ReplaceDependees(name, dependeesList1);
                throw new CircularException();
            }
        }
Example #6
0
 /// <summary>
 /// If name is null, throws an ArgumentNullException.
 ///
 /// Otherwise, if name isn't a valid cell name, throws an InvalidNameException.
 ///
 /// Otherwise, returns an enumeration, without duplicates, of the names of all cells whose
 /// values depend directly on the value of the named cell.  In other words, returns
 /// an enumeration, without duplicates, of the names of all cells that contain
 /// formulas containing name.
 ///
 /// For example, suppose that
 /// A1 contains 3
 /// B1 contains the formula A1 * A1
 /// C1 contains the formula B1 + A1
 /// D1 contains the formula B1 - C1
 /// The direct dependents of A1 are B1 and C1
 /// </summary>
 protected override IEnumerable <string> GetDirectDependents(string name)
 {
     if (name == null)
     {
         throw new ArgumentNullException();
     }
     return(dg.GetDependees(name));
 }
Example #7
0
        /// <summary>
        /// Called by the SetCellContents functions.
        /// Decides if a new cell needs to be made, adds it to the dictionary, then updates its contents.
        /// If the cell's contents are an empty string, removes it from the dictionary.
        /// </summary>
        private void AddCell(string name, object filler)
        {
            Cell tempCell;

            if (cells.TryGetValue(name, out tempCell))
            {
                if (filler.Equals(""))
                {
                    cells.Remove(name);
                }
                else
                {
                    tempCell.Contents = filler;
                }
                // Remove all old dependencies associated with this cell
                List <string> dependees = new List <string>();
                foreach (string dependee in dependencies.GetDependees(name))
                {
                    dependees.Add(dependee);
                }
                foreach (string dependee in dependees)
                {
                    dependencies.RemoveDependency(dependee, name);
                }
            }
            else if (!filler.Equals(""))
            {
                cells.Add(name, new Cell(filler));
            }
            if (filler.GetType().Equals(typeof(Formula)))
            {
                Formula formula = (Formula)filler;
                foreach (string str in formula.GetVariables())
                {
                    string dependee = str.ToUpper();
                    dependencies.AddDependency(dependee, name);
                }
            }

            // Assign values
            object oldValue = GetCellValue(name);

            DetermineCellValue(name);
            try
            {
                foreach (string toRecalc in GetCellsToRecalculate(name))
                {
                    DetermineCellValue(toRecalc);
                }
            }
            catch (CircularException e) // Reset to old value if the new formula results in a CircularException
            {
                AddCell(name, oldValue);
                throw e;
            }
            changed = true;
        }
Example #8
0
        /// <summary>
        /// If name is null, throws an ArgumentNullException.
        ///
        /// Otherwise, if name isn't a valid cell name, throws an InvalidNameException.
        ///
        /// Otherwise, returns an enumeration, without duplicates, of the names of all cells whose
        /// values depend directly on the value of the named cell.  In other words, returns
        /// an enumeration, without duplicates, of the names of all cells that contain
        /// formulas containing name.
        ///
        /// For example, suppose that
        /// A1 contains 3
        /// B1 contains the formula A1 * A1
        /// C1 contains the formula B1 + A1
        /// D1 contains the formula B1 - C1
        /// The direct dependents of A1 are B1 and C1
        /// </summary>
        protected override IEnumerable <String> GetDirectDependents(String name)
        {
            // checking if parameter name is null
            if (!(nameValidation(name)))
            {
                throw new ArgumentNullException();
            }

            // returning a IEnumerable of all the direct dependents of the given cell name
            return(DGSpreadsheet.GetDependees(name));
        }
Example #9
0
        //Helper method to remove the dependency of all variables that may have been in the cell
        private void removeDependencies(string name)
        {
            HashSet <string> set = new HashSet <string>(dg.GetDependees(name));

            foreach (string el in set)
            {
                dg.RemoveDependency(el, name);
            }
            cells.Remove(name);
            valueDictionary.Remove(name);
        }
Example #10
0
 /// <summary>
 /// If name is null, throws an ArgumentNullException.
 ///
 /// Otherwise, if name isn't a valid cell name, throws an InvalidNameException.
 ///
 /// Otherwise, returns an enumeration, without duplicates, of the names of all cells whose
 /// values depend directly on the value of the named cell.  In other words, returns
 /// an enumeration, without duplicates, of the names of all cells that contain
 /// formulas containing name.
 ///
 /// For example, suppose that
 /// A1 contains 3
 /// B1 contains the formula A1 * A1
 /// C1 contains the formula B1 + A1
 /// D1 contains the formula B1 - C1
 /// The direct dependents of A1 are B1 and C1
 /// </summary>
 /// <param name="name"></param>
 /// <returns></returns>
 protected override IEnumerable <string> GetDirectDependents(string name)
 {
     if (name.Equals(null))
     {
         throw new ArgumentNullException();
     }
     if (isValidName(name) == false)
     {
         throw new InvalidNameException();
     }
     return(d.GetDependees(name));
 }
Example #11
0
        protected override IEnumerable <string> GetDirectDependees(string name)
        {
            if (name == null)
            {
                throw new ArgumentNullException();
            }
            if (!ValidVariable(name))
            {
                throw new InvalidNameException();
            }

            return(dependencyGraph.GetDependees(Normalize(name)));
        }
Example #12
0
        /// <summary>
        /// Returns and enumeration without duplicates of all the direct dependents of
        /// the named cell.
        /// </summary>
        /// <param name="name">Cell to look for all direct dependents</param>
        /// <returns>An enumerable collection of direct dependents without duplicates.</returns>
        protected override IEnumerable <string> GetDirectDependents(string name)
        {
            if (name == null)
            {
                throw new ArgumentNullException();
            }

            name = ValidateNormalize(name);

            // Return the dependees from the graph.
            HashSet <string> DirectDependents = new HashSet <string>(Graph.GetDependees(name));

            return(DirectDependents);
        }
Example #13
0
 /// <summary>
 /// If name is null, throws an ArgumentNullException.
 ///
 /// Otherwise, if name isn't a valid cell name, throws an InvalidNameException.
 ///
 /// Otherwise, returns an enumeration, without duplicates, of the names of all cells whose
 /// values depend directly on the value of the named cell.  In other words, returns
 /// an enumeration, without duplicates, of the names of all cells that contain
 /// formulas containing name.
 ///
 /// For example, suppose that
 /// A1 contains 3
 /// B1 contains the formula A1 * A1
 /// C1 contains the formula B1 + A1
 /// D1 contains the formula B1 - C1
 /// The direct dependents of A1 are B1 and C1
 /// </summary>
 protected override IEnumerable <string> GetDirectDependents(string name)
 {
     if (name == null)
     {
         throw new ArgumentException();
     }
     if (checkName(name) == false)
     {
         throw new InvalidNameException();
     }
     else
     {
         HashSet <String> result = new HashSet <string>(graph.GetDependees(name));
         return(result);
     }
 }
Example #14
0
        /// <summary>
        /// If name is null, throws an ArgumentNullException.
        ///
        /// Otherwise, if name isn't a valid cell name, throws an InvalidNameException.
        ///
        /// Otherwise, returns an enumeration, without duplicates, of the names of all cells whose
        /// values depend directly on the value of the named cell.  In other words, returns
        /// an enumeration, without duplicates, of the names of all cells that contain
        /// formulas containing name.
        ///
        /// For example, suppose that
        /// A1 contains 3
        /// B1 contains the formula A1 * A1
        /// C1 contains the formula B1 + A1
        /// D1 contains the formula B1 - C1
        /// The direct dependents of A1 are B1 and C1
        /// </summary>
        protected override IEnumerable <string> GetDirectDependents(string name)
        {
            // Normalize name
            name = Normalizer(name);

            if (name == null || !(name.IsValidVariableName()))
            {
                throw new InvalidNameException();
            }
            else if (!(Validator(name)))
            {
                throw new InvalidNameException();
            }

            return(Graph.GetDependees(name));
        }
Example #15
0
        /// <summary>
        /// If name is null, throws an ArgumentNullException.
        ///
        /// Otherwise, if name isn't a valid cell name, throws an InvalidNameException.
        ///
        /// Otherwise, returns an enumeration, without duplicates, of the names of all cells whose
        /// values depend directly on the value of the named cell.  In other words, returns
        /// an enumeration, without duplicates, of the names of all cells that contain
        /// formulas containing name.
        ///
        /// For example, suppose that
        /// A1 contains 3
        /// B1 contains the formula A1 * A1
        /// C1 contains the formula B1 + A1
        /// D1 contains the formula B1 - C1
        /// The direct dependents of A1 are B1 and C1
        /// </summary>
        protected override IEnumerable <string> GetDirectDependents(string name)
        {
            HashSet <string> hs = new HashSet <string>();

            //if name is null we throw  Argumentnull Exception.
            if (name == null)
            {
                throw new ArgumentNullException();
            }
            //if name is not in corent format we throw invalidNameException.
            if (!Regex.IsMatch(name, @"^[a-zA-Z]+\d+$"))
            {
                throw new InvalidNameException();
            }

            return(DG.GetDependees(name));
        }
Example #16
0
        /// <summary>
        /// If the formula parameter is null, throws an ArgumentNullException.
        ///
        /// Otherwise, if name is null or invalid, throws an InvalidNameException.
        ///
        /// Otherwise, if changing the contents of the named cell to be the formula would cause a
        /// circular dependency, throws a CircularException.  (No change is made to the spreadsheet.)
        ///
        /// Otherwise, the contents of the named cell becomes formula.  The method returns a
        /// Set consisting of name plus the names of all other cells whose value depends,
        /// directly or indirectly, on the named cell.
        ///
        /// For example, if name is A1, B1 contains A1*2, and C1 contains B1+A1, the
        /// set {A1, B1, C1} is returned.
        protected override ISet <string> SetCellContents(string name, Formula formula)
        {
            if (formula == null)
            {
                throw new ArgumentNullException("A cell can't have a null value!);");
            }
            if (name == null || !ValidVariable(name))
            {
                throw new InvalidNameException();
            }
            string normalizedName = Normalize(name);

            //saving old dependees and contents in case a circular dependency is found
            List <string> oldDependees = new List <string>(dependencyGraph.GetDependees(normalizedName));

            cells.TryGetValue(normalizedName, out var oldContents);

            //dependees are replaced with dependees (variables) of new formula
            dependencyGraph.ReplaceDependees(normalizedName, formula.GetVariables());
            cells[normalizedName] = new Cell(normalizedName, formula, LookupCellValue);

            //a circular dependency is checked for, old dependees and content are kept if one is found
            try
            {
                //recalculating necessary cell values
                List <string> recalculatedCells = new List <string>(GetCellsToRecalculate(normalizedName));
                RecalculateCellValues(recalculatedCells);

                //successful return means spreadsheet is changed
                Changed = true;
                return(new HashSet <string>(recalculatedCells));
            }
            catch (CircularException)
            {
                if (oldContents != null)
                {
                    cells[normalizedName] = new Cell(normalizedName, oldContents.Contents, LookupCellValue);
                }
                else //if the cell was empty before setting to this invalid formula, leave it empty
                {
                    cells.Remove(normalizedName);
                }
                dependencyGraph.ReplaceDependees(normalizedName, oldDependees);
                throw;
            }
        }
Example #17
0
        /// <summary>
        /// returns direct dependents of name.
        /// If name is null. Throw ArgumentNullException()
        /// If name isnt a valid cell name. Throw an InvalidNameException.
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        protected override IEnumerable <string> GetDirectDependents(string name)
        {
            //if name parameter is null, throw ArgumentNullException
            if (name == null)
            {
                throw new ArgumentNullException();
            }

            name = Normalize(name);

            //if name isnt a valid variable name, throw InvalidNameException
            if (!isValidVariable(name))
            {
                throw new InvalidNameException();
            }

            //returns direct dependents of name.
            return(dependencies.GetDependees(name));
        }
Example #18
0
        /// <summary>
        /// If name is null, throws an ArgumentNullException.
        ///
        /// Otherwise, if name isn't a valid cell name, throws an InvalidNameException.
        ///
        /// Otherwise, returns an enumeration, without duplicates, of the names of all cells whose
        /// values depend directly on the value of the named cell.  In other words, returns
        /// an enumeration, without duplicates, of the names of all cells that contain
        /// formulas containing name.
        ///
        /// For example, suppose that
        /// A1 contains 3
        /// B1 contains the formula A1 * A1
        /// C1 contains the formula B1 + A1
        /// D1 contains the formula B1 - C1
        /// The direct dependents of A1 are B1 and C1
        ///
        /// </summary>
        /// <param name="name">cell name</param>
        /// <returns></returns>
        protected override IEnumerable <string> GetDirectDependents(string name)
        {
            // check it out, always.
            //if (name == null) { throw new ArgumentNullException(); }

            // In PS4, I used regax for check the name's validation.
            // However, we have delegate 'IsValid' function.
            // we can check the name using the delegate function
            //if (!IsValid(name)) { throw new InvalidNameException(); }

            // we have to normalize the name after checking all exceptions.
            string normalizedName = Normalize(name);

            // Now, we can get all dependees form PS2 DependencyGraph, so I declare DG
            IEnumerable <String> tempDG         = DG.GetDependees(name);
            HashSet <String>     dircDependents = new HashSet <string>(tempDG);

            return(dircDependents);
        }
        /// <summary>
        /// If name is null, throws an ArgumentNullException.
        ///
        /// Otherwise, if name isn't a valid cell name, throws an InvalidNameException.
        ///
        /// Otherwise, returns an enumeration, without duplicates, of the names of all cells whose
        /// values depend directly on the value of the named cell.  In other words, returns
        /// an enumeration, without duplicates, of the names of all cells that contain
        /// formulas containing name.
        ///
        /// For example, suppose that
        /// A1 contains 3
        /// B1 contains the formula A1 * A1
        /// C1 contains the formula B1 + A1
        /// D1 contains the formula B1 - C1
        /// The direct dependents of A1 are B1 and C1
        /// </summary>
        protected override IEnumerable <string> GetDirectDependents(string name)
        {
            // If name is null, throws an ArgumentNullException.
            if (name == null)
            {
                throw new ArgumentNullException();
            }

            // Otherwise, if name isn't a valid cell name, throws an InvalidNameException.
            else if (IsValidps4(name) == false)
            {
                throw new InvalidNameException();
            }

            // Otherwise, returns an enumeration, without duplicates, of the names of all cells whose
            // values depend directly on the value of the named cell.  In other words, returns
            // an enumeration, without duplicates, of the names of all cells that contain
            // formulas containing name.
            return(myDG.GetDependees(name));
        }
Example #20
0
        /// <summary>
        /// If the formula parameter is null, throws an ArgumentNullException.
        ///
        /// Otherwise, if name is null or invalid, throws an InvalidNameException.
        ///
        /// Otherwise, if changing the contents of the named cell to be the formula would cause a
        /// circular dependency, throws a CircularException, and no change is made to the spreadsheet.
        ///
        /// Otherwise, the contents of the named cell becomes formula.  The method returns a
        /// list consisting of name plus the names of all other cells whose value depends,
        /// directly or indirectly, on the named cell.
        ///
        /// For example, if name is A1, B1 contains A1*2, and C1 contains B1+A1, the
        /// list {A1, B1, C1} is returned.
        /// </summary>
        protected override IList <string> SetCellContents(string name, Formula formula)
        {
            if (formula is null)
            {
                throw new ArgumentNullException();
            }

            IEnumerable <string> oldDependencies = dependencies.GetDependees(name);
            List <string>        newDependencies = new List <string>();

            foreach (string x in formula.GetVariables())
            {
                newDependencies.Add(x);
            }
            dependencies.ReplaceDependees(name, newDependencies);

            List <string> listToReturn = new List <string>();

            try
            {
                listToReturn = getDependents(name);
            }
            catch
            {
                dependencies.ReplaceDependees(name, oldDependencies);
                throw new CircularException();
            }

            Changed = true;

            if (spreadSheetCells.TryGetValue(name, out Cell cell))
            {
                cell.setCellContents(formula);
                return(listToReturn);
            }
            else
            {
                spreadSheetCells.Add(name, new Cell(name, formula));
                return(listToReturn);
            }
        }
Example #21
0
        /// <summary>
        /// Updates a cell with the given contents.
        /// Updates formula dependencies where needed.
        /// </summary>
        /// <param name="name">The name of the cell to update.</param>
        /// <param name="contents">The new contents of the cell.</param>
        /// <returns>The cells which depend on the updated cell, either directly or indirectly.</returns>
        private ISet <string> UpdateCell(string name, object contents)
        {
            // Holds the cells which need to be recalculated.
            ISet <string> cellsToRecalculate;

            // Dependencies of formulas must be updated in the graph.
            if (contents is Formula formula)
            {
                // Keep track of the old dependees
                var oldDependees = _formulaCellDependencyGraph.GetDependees(name);

                // Replace the old dependees with the new dependees.
                _formulaCellDependencyGraph.ReplaceDependees(name, formula.GetVariables());

                // Check for a circular dependency.
                try
                {
                    cellsToRecalculate = new HashSet <string>(GetCellsToRecalculate(name));
                }
                catch (CircularException)
                {
                    // Restore old dependees upon a circular exception so that nothing is modified.
                    _formulaCellDependencyGraph.ReplaceDependees(name, oldDependees);
                    throw;
                }
            }
            else
            {
                // Clear any old dependees in the graph
                _formulaCellDependencyGraph.ReplaceDependees(name, new string[0]);

                // Find cells to re-calculate.
                cellsToRecalculate = new HashSet <string>(GetCellsToRecalculate(name));
            }

            if (contents is string text && text == "")
            {
                // If text is empty, the cell should be removed from the dictionary.
                _cells.Remove(name);
            }
Example #22
0
        /// <summary>
        /// If the formula parameter is null, throws an ArgumentNullException.
        ///
        /// Otherwise, if name is null or invalid, throws an InvalidNameException.
        ///
        /// Otherwise, if changing the contents of the named cell to be the formula would cause a
        /// circular dependency, throws a CircularException.  (No change is made to the spreadsheet.)
        ///
        /// Otherwise, the contents of the named cell becomes formula.  The method returns a
        /// Set consisting of name plus the names of all other cells whose value depends,
        /// directly or indirectly, on the named cell.
        ///
        /// For example, if name is A1, B1 contains A1*2, and C1 contains B1+A1, the
        /// set {A1, B1, C1} is returned.
        /// </summary>
        protected override ISet <String> SetCellContents(String name, Formula formula)
        {
            // Dead code due to requirements for SetContentsOfCell
            //if (ReferenceEquals(formula, null))
            //throw new ArgumentNullException();

            // Dead code due to requirements for SetContentsOfCell
            //(ReferenceEquals(name, null) || !(IsValidName(name)))
            //    throw new InvalidNameException();

            // temp variable to hold old dependents
            IEnumerable <String> old_dependees = dg.GetDependees(name);

            // replace the dependents of 'name' in the dependency graph with the variables in formula
            dg.ReplaceDependees(name, formula.GetVariables());

            try // check if the new depdendency graph creates a circular reference
            {
                // if there is no exception
                HashSet <String> all_dependees = new HashSet <String>(GetCellsToRecalculate(name));
                // create a new cell
                Cell cell = new Cell(formula, LookupValue);
                if (cells.ContainsKey(name))    // if it already contains that key
                {
                    cells[name] = cell;         // replace the key with the new value
                }
                else
                {
                    cells.Add(name, cell);      // otherwise add a new key for that value
                }
                return(all_dependees);
            }
            catch (CircularException e) // if an exception is caught, we want to keep the old dependents and not change the cell
            {
                dg.ReplaceDependees(name, old_dependees);
                throw new CircularException();
            }
        }
 /// <summary>
 /// A convenience method for invoking the other version of GetCellsToRecalculate
 /// with a singleton set of names.  See the other version for details.
 /// </summary>
 protected override IEnumerable <string> GetDirectDependents(string name)
 {
     return(dependency.GetDependees(name));
 }
Example #24
0
        /// <summary>
        /// Requires that all of the variables in formula are valid cell names.
        ///
        /// If name is null or invalid, throws an InvalidNameException.
        ///
        /// Otherwise, if changing the contents of the named cell to be the formula would cause a
        /// circular dependency, throws a CircularException.
        ///
        /// Otherwise, the contents of the named cell becomes formula.  The method returns a
        /// Set consisting of name plus the names of all other cells whose value depends,
        /// directly or indirectly, on the named cell.
        ///
        /// For example, if name is A1, B1 contains A1*2, and C1 contains B1+A1, the
        /// set {A1, B1, C1} is returned.
        /// </summary>
        protected override ISet <string> SetCellContents(string name, Formula formula)
        {
            if (!IsValidCellName(name, IsValid))
            {
                throw new InvalidNameException();
            }

            if (!Cells.ContainsKey(name))
            {
                Cells.Add(name, new Cell());
            }

            // Set consisting of variables in formula
            ISet <string> variables = formula.GetVariables();


            object oldVal     = Cells[name.ToUpper()].GetContent();
            bool   hadFormula = Cells[name.ToUpper()].hasFormula;

            Cells[name.ToUpper()].SetContent(formula);

            // Remove dependess that aren't there in the formula
            if (Graph.HasDependees(name))
            {
                foreach (string dependee in Graph.GetDependees(name).ToList())
                {
                    if (!variables.Contains(dependee))
                    {
                        Graph.RemoveDependency(dependee, name);
                    }
                }
            }

            // Add dependees that don't already exist
            foreach (string variable in variables)
            {
                Graph.AddDependency(variable, name);
            }


            ISet <string> changedSet = new HashSet <string>();

            changedSet = GetAllRelatedDependents(name);
            //            changedSet.Add(name);
            //            if (Graph.HasDependents(name))
            //            {
            //                foreach (string dependent in Graph.GetDependents(name))
            //                {
            //                    changedSet.Add(dependent);
            //                }
            //            }

            // To check for Circular Dependency
            try
            {
                GetCellsToRecalculate(changedSet);
            }
            catch (CircularException e)
            {
                Cells[name.ToUpper()].SetContent(oldVal);
                Cells[name.ToUpper()].hasFormula = hadFormula;
                throw e;
            }

            return(changedSet);
        }
Example #25
0
 protected override IEnumerable <String> GetDirectDependents(String name)
 {
     return(ssDep.GetDependees(name));
 }
Example #26
0
        /// <summary>
        /// Requires that all of the variables in formula are valid cell names.
        ///
        /// If name is null or invalid, throws an InvalidNameException.
        ///
        /// Otherwise, if changing the contents of the named cell to be the formula would cause a
        /// circular dependency, throws a CircularException.
        ///
        /// Otherwise, the contents of the named cell becomes formula.  The method returns a
        /// Set consisting of name plus the names of all other cells whose value depends,
        /// directly or indirectly, on the named cell.
        ///
        /// For example, if name is A1, B1 contains A1*2, and C1 contains B1+A1, the
        /// set {A1, B1, C1} is returned.
        /// </summary>
        protected override ISet <string> SetCellContents(string name, Formula formula)
        {
            // check if name is null or invalid
            if (!Regex.IsMatch(name, IsValid.ToString()) || ReferenceEquals(name, null) || !Regex.IsMatch(name, @"^[a-zA-Z_](?: [a-zA-Z_]|\d)*$"))
            {
                throw new InvalidNameException();
            }

            IEnumerable <String> dependees = dg.GetDependees(name);

            // replace dependents of name with the formula variables
            dg.ReplaceDependees(name, formula.GetVariables());

            //check if dependency graph produces circular dependency
            try
            {
                HashSet <String> hsDependees = new HashSet <String>(GetCellsToRecalculate(name));

                Cell cell = new Cell(formula);
                cell.value = formula;

                // if cell does not contain name, add new key for the value.
                // if it does contain name, then replace key with the value
                if (!cells.ContainsKey(name))
                {
                    cells.Add(name, new Cell(formula));
                }
                else
                {
                    cells[name] = new Cell(formula);
                }

                foreach (string values in new HashSet <String>(GetCellsToRecalculate(name)))
                {
                    if (!(cells[values].contents is Formula))
                    {
                        cell.value = formula.Evaluate((Lookup)LookupValue);
                    }
                    else
                    {
                        try
                        {
                            Formula f     = (Formula)cells[values].contents;
                            double  value = f.Evaluate((Lookup)LookupValue);
                            cells[values].value = value;
                        }
                        catch (Exception e)
                        {
                            cells[values].value = new FormulaError();
                        }
                    }
                }

                return(new HashSet <String>(GetCellsToRecalculate(name)));
            }
            // if exception is caught, keep old dependents
            catch (CircularException e)
            {
                dg.ReplaceDependees(name, dependees);
                throw new CircularException();
            }
        }
Example #27
0
        /// <summary>
        /// If text is null, throws an ArgumentNullException.
        ///
        /// Otherwise, if name is null or invalid, throws an InvalidNameException.
        ///
        /// Otherwise, the contents of the named cell becomes text.  The method returns a
        /// set consisting of name plus the names of all other cells whose value depends,
        /// directly or indirectly, on the named cell.
        ///
        /// For example, if name is A1, B1 contains A1*2, and C1 contains B1+A1, the
        /// set {A1, B1, C1} is returned.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="text"></param>
        /// <returns></returns>
        protected override ISet <string> SetCellContents(string name, string text)
        {
            var  ReturnSet     = new HashSet <string>();
            var  OldDependents = new List <string>();
            bool found         = false;

            if (text == null)
            {
                throw new ArgumentNullException();
            }

            //Looks through CellList for the cell called name.
            foreach (Cell cell in CellList)
            {
                if (cell.Name == name)
                {
                    // If the replacement text is an empty string we are emptying the cell, otherwise we are changing a cell to be used.
                    if (text != string.Empty)
                    {
                        foreach (string DependName in GetCellsToRecalculate(name))
                        {
                            ReturnSet.Add(DependName);
                        }

                        //Since we found that the cell already existed, replace the contents and replace any pre-exisiting dependents.
                        cell.Contents = text;
                        cell.Value    = text;

                        foreach (string dependent in Graph.GetDependents(name))
                        {
                            OldDependents.Add(dependent);
                        }
                        foreach (string t in OldDependents)
                        {
                            Graph.RemoveDependency(name, t);
                        }
                        found = true;
                        break;
                    }
                    else
                    {
                        //Example.
                        //A1 contains 3
                        //A2 contains 5
                        //A3 contains A1 + A2
                        //A4 contains A3*2
                        //Replacing A3 with an empty text should remove from the graph that it has dependees A1 and A2, but do nothing about A4.


                        foreach (string DependName in GetCellsToRecalculate(name))
                        {
                            ReturnSet.Add(DependName);
                        }

                        CellList.Remove(cell);
                        foreach (string dep in Graph.GetDependees(cell.Name))
                        {
                            Graph.RemoveDependency(cell.Name, dep);
                        }

                        found = true;
                        break;
                    }
                }
            }

            //If the name wasnt in the list already we can add it as a new cell.
            //Fix the value in the constructor later.
            if (found == false)
            {
                if (text != string.Empty)
                {
                    Cell newcell = new Cell(name, text, text);
                    CellList.Add(newcell);
                    foreach (string var in GetCellsToRecalculate(name))
                    {
                        ReturnSet.Add(var);
                    }
                }
            }
            Changed = true;
            return(ReturnSet);
        }
        protected override ISet <string> SetCellContents(string name, double number)
        {
            // If the cell already exists, remove it
            if (spreadsheetCells.ContainsKey(name))
            {
                spreadsheetCells.Remove(name);
            }

            // Create new cell
            Cell toBeAdded = new Cell();

            // Set cellName equal to name
            toBeAdded.cellName = name;
            // Set cellContents equal to number
            toBeAdded.cellContents = number;
            // Set cellValue equal to number
            toBeAdded.cellValue = number;
            // Set cellContentsType equal to double
            toBeAdded.cellContentsType = "double";

            // Add (name, cell) to our spreadsheetCells dictionary
            spreadsheetCells.Add(name, toBeAdded);

            // Get dependecies for return portion of method call
            HashSet <String> returnValues = new HashSet <String>();
            // Call GetCellsToRecalculate to get direct dependents
            IEnumerable dependents = GetCellsToRecalculate(name);

            foreach (String temp in dependents)
            {
                // Add direct dependents to returnValues
                returnValues.Add(temp);
            }

            // Call GetDependees on dependencies to get indirect dependents
            IEnumerable dependees = dependencies.GetDependees(name);

            foreach (String temp in dependees)
            {
                // Add indirect dependents to returnValues
                returnValues.Add(temp);
            }

            // Recalculate
            Cell recalculation;

            foreach (String depend in dependents)
            {
                if (spreadsheetCells.TryGetValue(depend, out recalculation))
                {
                    // Set value of cell
                    try
                    {
                        String equalPattern = @"^=";
                        String cellContents = recalculation.cellContents.ToString();
                        if (Regex.IsMatch(cellContents, equalPattern))
                        {
                            String  parsedContents = cellContents.Substring(1);
                            Formula f = new Formula(parsedContents);
                            recalculation.cellValue = f.Evaluate((x) => (double)GetCellValue(x));
                            //SetContentsOfCell(recalculation.cellName, recalculation.cellContents.ToString());
                        }
                    }
                    catch (InvalidCastException)
                    {
                        recalculation.cellValue = new FormulaError();
                    }
                    catch (FormulaEvaluationException)
                    {
                        recalculation.cellValue = new FormulaError();
                    }
                }
            }

            // Change changed to true since we made a change to the spreadsheet
            Changed = true;

            // Return
            return(returnValues);
        }