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.util;
022    
023    import csheets.core.Address;
024    import csheets.core.formula.Expression;
025    import csheets.core.formula.Reference;
026    import csheets.core.formula.lang.CellReference;
027    
028    /**
029     * An expression visitor that transposes the references in an expression.
030     * The visitor is used for copying and moving formulas between cells.
031     * @author Einar Pehrson
032     */
033    public class ReferenceTransposer extends ExpressionBuilder {
034    
035            /** The number of columns to transpose the formula */
036            private int columns;
037    
038            /** The number of rows to transpose the formula */
039            private int rows;
040    
041            /**
042             * Creates a new reference fetcher.
043             * @param columns the number of columns to transpose formulae
044             * @param rows the number of rows to transpose formulae
045             */
046            public ReferenceTransposer(int columns, int rows) {
047                    this.columns = columns;
048                    this.rows = rows;
049            }
050    
051            /**
052             * Returns a transposed copy of the given expression.
053             * @param expression the expression to rebuild
054             * @return the transposed expression
055             */
056            public Expression getExpression(Expression expression) {
057                    return (Expression)expression.accept(this);
058            }
059    
060            /**
061             * Transposes the reference.
062             * @param reference the reference to visit
063             */
064            public Expression visitReference(Reference reference) {
065                    if (reference instanceof CellReference) {
066                            // Fetches reference and address
067                            CellReference cellRef = (CellReference)reference;
068                            Address address = cellRef.getCell().getAddress();
069    
070                            // Transposes column index
071                            int newColumn = address.getColumn();
072                            if (!cellRef.isColumnAbsolute())
073                                    newColumn += columns;
074    
075                            // Transposes row index
076                            int newRow = address.getRow();
077                            if (!cellRef.isRowAbsolute())
078                                    newRow += rows;
079    
080                            // Returns new reference
081                            return new CellReference(
082                                    cellRef.getCell().getSpreadsheet().getCell(
083                                            new Address(newColumn, newRow)),
084                                    cellRef.isColumnAbsolute(),
085                                    cellRef.isRowAbsolute()
086                            );
087                    } else
088                            return super.visitReference(reference);
089            }
090    }