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 */ 021package csheets.core.formula; 022 023import java.util.SortedSet; 024import java.util.TreeSet; 025 026import csheets.core.Cell; 027import csheets.core.IllegalValueTypeException; 028import csheets.core.Value; 029import csheets.core.formula.util.CircularReferenceException; 030import csheets.core.formula.util.CircularReferenceFinder; 031import csheets.core.formula.util.ExpressionVisitor; 032import csheets.core.formula.util.ExpressionVisitorException; 033import csheets.core.formula.util.ReferenceFetcher; 034 035/** 036 * A formula in a cell. 037 * @author Einar Pehrson 038 */ 039public 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}