001 /*
002 * Copyright (c) 2005 Einar Pehrson <einar@pehrson.nu>.
003 *
004 * This file is part of
005 * CleanSheets - a spreadsheet application for the Java platform.
006 *
007 * CleanSheets is free software; you can redistribute it and/or modify
008 * it under the terms of the GNU General Public License as published by
009 * the Free Software Foundation; either version 2 of the License, or
010 * (at your option) any later version.
011 *
012 * CleanSheets is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015 * GNU General Public License for more details.
016 *
017 * You should have received a copy of the GNU General Public License
018 * along with CleanSheets; if not, write to the Free Software
019 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020 */
021 package csheets.core.formula;
022
023 import java.util.SortedSet;
024 import java.util.TreeSet;
025
026 import csheets.core.Cell;
027 import csheets.core.IllegalValueTypeException;
028 import csheets.core.Value;
029 import csheets.core.formula.util.CircularReferenceException;
030 import csheets.core.formula.util.CircularReferenceFinder;
031 import csheets.core.formula.util.ExpressionVisitor;
032 import csheets.core.formula.util.ExpressionVisitorException;
033 import csheets.core.formula.util.ReferenceFetcher;
034
035 /**
036 * A formula in a cell.
037 * @author Einar Pehrson
038 */
039 public class Formula implements Expression {
040
041 /** The unique version identifier used for serialization */
042 private static final long serialVersionUID = 7127589370042533160L;
043
044 /** The cell to which the formula belongs */
045 private Cell cell;
046
047 /** The expression of the formula */
048 private Expression expression;
049
050 /** Returns the references in the expression */
051 private SortedSet<Reference> references;
052
053 /**
054 * Creates a new formula.
055 * @param cell the cell to which the formula belongs
056 * @param expression the expression in the formula
057 */
058 public Formula(Cell cell, Expression expression) {
059 // Stores members
060 this.cell = cell;
061 this.expression = expression;
062 }
063
064 public Value evaluate() throws IllegalValueTypeException {
065 if (!hasCircularReference())
066 return expression.evaluate();
067 else
068 return new Value(new CircularReferenceException(this));
069 }
070
071 public Object accept(ExpressionVisitor visitor) {
072 return expression.accept(visitor);
073 }
074
075 /**
076 * Returns the cell to which the formula belongs.
077 * @return the cell to which the formula belongs
078 */
079 public Cell getCell() {
080 return cell;
081 }
082
083 /**
084 * Returns the expression in the formula.
085 * @return the expression in the formula
086 */
087 public Expression getExpression() {
088 return expression;
089 }
090
091 /**
092 * Returns the references in the expression.
093 * @return the references in the expression
094 */
095 public SortedSet<Reference> getReferences() {
096 if (references == null)
097 references = new ReferenceFetcher().getReferences(expression);
098 return new TreeSet<Reference>(references);
099 }
100
101 /**
102 * Checks if the given formula has any circular references.
103 * @throws CircularReferenceException if the formula contains any circular references
104 */
105 public boolean hasCircularReference() {
106 try {
107 new CircularReferenceFinder().check(this);
108 } catch (ExpressionVisitorException e) {
109 return true;
110 }
111 return false;
112 }
113
114 /**
115 * Returns a string representation of the formula.
116 * @return a string representation of the formula
117 */
118 public String toString() {
119 return expression.toString();
120 }
121 }