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.lang;
022
023import java.util.SortedSet;
024import java.util.TreeSet;
025
026import csheets.core.Cell;
027import csheets.core.Value;
028import csheets.core.formula.BinaryOperation;
029import csheets.core.formula.Reference;
030import csheets.core.formula.util.ExpressionVisitor;
031import csheets.core.formula.util.ExpressionVisitorException;
032
033/**
034 * A binary reference operation in a formula.
035 * @author Einar Pehrson
036 */
037public class ReferenceOperation extends BinaryOperation implements Reference {
038
039        /** The unique version identifier used for serialization */
040        private static final long serialVersionUID = 1767227655524985408L;
041
042        /** The cells that constitute the range */
043        private SortedSet<Cell> cells;
044
045        /**
046         * Creates a new reference operation.
047         * @param leftOperand the left(first) operand
048         * @param operator the reference operator
049         * @param rightOperand the right(second) operand
050         */
051        public ReferenceOperation(Reference leftOperand, RangeReference operator, Reference rightOperand) {
052                super(leftOperand, operator, rightOperand);
053        }
054
055        public SortedSet<Cell> getCells() {
056                if (cells == null) {
057                        cells = new TreeSet<Cell>();
058                        Cell[][] range = getOperator().getCells(getLeftOperand(), getRightOperand());
059                        for (int row = 0; row < range.length; row++)
060                                for (int column = 0; column < range[row].length; column++)
061                                        cells.add(range[row][column]);
062                }
063                return cells;
064        }
065
066        public RangeReference getOperator() {
067                return (RangeReference)operator;
068        }
069
070        public Reference getLeftOperand() {
071                return (Reference)super.getLeftOperand();
072        }
073
074        public Reference getRightOperand() {
075                return (Reference)super.getRightOperand();
076        }
077
078        public Value evaluate() {
079                return getOperator().applyTo(getLeftOperand(), getRightOperand());
080        }
081
082        public Object accept(ExpressionVisitor visitor) throws ExpressionVisitorException {
083                return visitor.visitReference(this);
084        }
085
086        public int compareTo(Reference reference) {
087                Cell otherCell = reference.getCells().first();
088                int firstDiff = getCells().first().compareTo(otherCell);
089                if (firstDiff != 0)
090                        return firstDiff;
091                else
092                        if (reference instanceof CellReference)
093                                return 1;
094                        else
095                                return getCells().last().compareTo(reference.getCells().last());
096        }
097}