4 deleted 1 character in body; edited title
source | link

Object orientation and Java style for Spreadsheet with reverse Polish equation solving

Here is the cell class Cell class:

Object orientation and Java style for Spreadsheet

Here is the cell class

Spreadsheet with reverse Polish equation solving

Here is the Cell class:

    Tweeted twitter.com/#!/StackCodeReview/status/168522568570114049
3 edited title
| link

Object orientation and Java style for Spreadsheet

2 deleted 175 characters in body
source | link
/**
 * This class encapsulates a single cell within a spreadsheet.
 */
public class Cell {

    private SpreadSheet spreadsheet; // spreadsheet to which cell belongs,
                                        // necessary for resolving cell
                                        // references
    private String expression; // expression within cell in reverse Polish
                                // notation
    private double value; // numerical value of evaluating expression
    private boolean valueValid; // whether a valid value has been found so
                                // far. This will change from false to true
                                // once all cell references have been
                                // resolved, provided that there are no
                                // circular references

    /**
     * Constructor for a cell belonging to a particular spreadsheet.
     *
     * @param spreadsheet
     *            SpreadSheet to which Cell belongs.
     * @param expression
     *            expression within cell.
     */
    public Cell(SpreadSheet spreadsheet, String expression) {
        this.spreadsheet = spreadsheet;
        this.expression = expression;
    }

    /**
     * Evaluates expression within a cell. Expression must be in reverse Polish
     * notation.
     *
     * @throws InvalidOperatorException
     *             if cell expression contains an invalid operator.
     * @throws InvalidValueException
     *             if cell expression contains a reference to a cell that does
     *             not currently have a valid value.
     */
    public void evaluate() throws InvalidOperatorException {
        if (!valueValid) { // prevent reevaluation of cells that have valid
                            // values
            try {
                // create stack containing termterms in expression
                Deque<String> expressionStack = new ArrayDeque<String>(
                        Arrays.asList(expression.split("\\s")));
                value = evaluateRpn(expressionStack);
                valueValid = true;
            } catch (UnresolvedReferenceException e) {
                // no action is necessary if a reference is unresolved, since it
                // may be resolved at a later iteration during the solution of
                // the spreadsheet
            }
        }
    }

    /**
     * Get value of a cell. This is the numerical value resulting from
     * evaluating the cell's expression.
     *
     * @return numerical value resulting from evaluating cell's expression.
     * @throws InvalidValueException
     *             if a valid value is not currently available.
     */
    public double getValue() throws InvalidValueException {
        if (isValueValid()) {
            return value;
        } else {
            throw new InvalidValueException();
        }
    }

    /**
     * Check if a valid numerical value has been evaluated for the cell. This
     * will be true when evaluate() is called on the cell and all of the cell
     * references in the cell's expression can be resolved.
     *
     * @return whether cell value is valid.
     */
    public boolean isValueValid() {
        return valueValid;
    }

    /**
     * Evaluate an expression contained within an ExpressionStack.
     *
     * @param expressionStack
     *            an expression represented as a stack of individual terms.
     * @return evaluation of expression
     * @throws InvalidOperatorException
     * @throws UnresolvedReferenceException
     * @throws InvalidValueException
     */
    private double evaluateRpn(Deque<String> expressionStack)
            throws InvalidOperatorException, UnresolvedReferenceException {
        String term = expressionStack.removeLast();
        if (isCellReference(term)) {
            // if last term in expression is a cell reference then resolve it
            return resolveCellReference(term);
        } else {
            double x, y;
            try {
                // if last term in expression is double then return it
                x = Double.parseDouble(term);
            } catch (NumberFormatException e) {
                // otherwise last term is an operator, evaluate operands and
                // apply operator
                y = evaluateRpn(expressionStack);
                x = evaluateRpn(expressionStack);
                x = applyOperator(x, y, term);
            }
            return x;
        }
    }

    /**
     * Apply operator to operands x and y.
     *
     * @param x
     *            first operand.
     * @param y
     *            second operand.
     * @param operator
     * @return result of operation
     * @throws InvalidOperatorException
     */
    private double applyOperator(double x, double y, String operator)
            throws InvalidOperatorException {
        if (operator.equals("+"))
            return x + y;
        else if (operator.equals("-"))
            return x - y;
        else if (operator.equals("*"))
            return x *= y;
        else if (operator.equals("/"))
            return x / y;
        else
            throw new InvalidOperatorException(operator);
    }

    /**
     * Resolve a reference to another cell within the spreadsheet. If the other
     * cell has a valid value, then the value will be returned, otherwise an
     * UnresolvedReferenceException will be thrown.
     *
     * @param reference
     *            reference to another cell in the spreadsheet.
     * @return value of referenced cell.
     * @throws UnresolvedReferenceException
     * @throws InvalidValueException
     */
    private double resolveCellReference(String reference)
            throws UnresolvedReferenceException {
        int col = reference.charAt(0) - 'A';
        int row = Integer.parseInt(reference.substring(1)) - 1;
        Cell referencedCell = spreadsheet.getCell(row, col);
        try {
            return referencedCell.getValue();
        } catch (InvalidValueException e) {
            throw new UnresolvedReferenceException();
        }
    }

    /**
     * Determine whether a term in an expression is a reference to another cell.
     *
     * @param term
     * @return whether term is a cell reference.
     */
    private boolean isCellReference(String term) {
        return Character.isLetter(term.charAt(0));
    }

    /**
     * Thrown to indicate than an invalid operator is specified in cell
     * expression.
     */
    public class InvalidOperatorException extends Exception {

        private static final long serialVersionUID = 1L;
        private String operator;

        public InvalidOperatorException(String operator) {
            this.operator = operator;
        }

        public String toString() {
            return "Invalid operator " + operator;
        }

    }

    /**
     * Thrown to indicate that a cell reference cannot be resolved. This occurs
     * if a valid value is not currently available for the referenced cell.
     */
    public class UnresolvedReferenceException extends Exception {

        private static final long serialVersionUID = 1L;

    }

    /**
     * Thrown to indicate that getValue() was called on a cell with a value that
     * is currently invalid.
     */
    public class InvalidValueException extends Exception {

        private static final long serialVersionUID = 1L;

    }

}
/**
 * This class encapsulates a single cell within a spreadsheet.
 */
public class Cell {

    private SpreadSheet spreadsheet; // spreadsheet to which cell belongs,
                                        // necessary for resolving cell
                                        // references
    private String expression; // expression within cell in reverse Polish
                                // notation
    private double value; // numerical value of evaluating expression
    private boolean valueValid; // whether a valid value has been found so
                                // far. This will change from false to true
                                // once all cell references have been
                                // resolved, provided that there are no
                                // circular references

    /**
     * Constructor for a cell belonging to a particular spreadsheet.
     *
     * @param spreadsheet
     *            SpreadSheet to which Cell belongs.
     * @param expression
     *            expression within cell.
     */
    public Cell(SpreadSheet spreadsheet, String expression) {
        this.spreadsheet = spreadsheet;
        this.expression = expression;
    }

    /**
     * Evaluates expression within a cell. Expression must be in reverse Polish
     * notation.
     *
     * @throws InvalidOperatorException
     *             if cell expression contains an invalid operator.
     * @throws InvalidValueException
     *             if cell expression contains a reference to a cell that does
     *             not currently have a valid value.
     */
    public void evaluate() throws InvalidOperatorException {
        if (!valueValid) { // prevent reevaluation of cells that have valid
                            // values
            try {
                // create stack containing term in expression
                Deque<String> expressionStack = new ArrayDeque<String>(
                        Arrays.asList(expression.split("\\s")));
                value = evaluateRpn(expressionStack);
                valueValid = true;
            } catch (UnresolvedReferenceException e) {
                // no action is necessary if a reference is unresolved, since it
                // may be resolved at a later iteration during the solution of
                // the spreadsheet
            }
        }
    }

    /**
     * Get value of a cell. This is the numerical value resulting from
     * evaluating the cell's expression.
     *
     * @return numerical value resulting from evaluating cell's expression.
     * @throws InvalidValueException
     *             if a valid value is not currently available.
     */
    public double getValue() throws InvalidValueException {
        if (isValueValid()) {
            return value;
        } else {
            throw new InvalidValueException();
        }
    }

    /**
     * Check if a valid numerical value has been evaluated for the cell. This
     * will be true when evaluate() is called on the cell and all of the cell
     * references in the cell's expression can be resolved.
     *
     * @return whether cell value is valid.
     */
    public boolean isValueValid() {
        return valueValid;
    }

    /**
     * Evaluate an expression contained within an ExpressionStack.
     *
     * @param expressionStack
     *            an expression represented as a stack of individual terms.
     * @return evaluation of expression
     * @throws InvalidOperatorException
     * @throws UnresolvedReferenceException
     * @throws InvalidValueException
     */
    private double evaluateRpn(Deque<String> expressionStack)
            throws InvalidOperatorException, UnresolvedReferenceException {
        String term = expressionStack.removeLast();
        if (isCellReference(term)) {
            // if last term in expression is a cell reference then resolve it
            return resolveCellReference(term);
        } else {
            double x, y;
            try {
                // if last term in expression is double then return it
                x = Double.parseDouble(term);
            } catch (NumberFormatException e) {
                // otherwise last term is an operator, evaluate operands and
                // apply operator
                y = evaluateRpn(expressionStack);
                x = evaluateRpn(expressionStack);
                x = applyOperator(x, y, term);
            }
            return x;
        }
    }

    /**
     * Apply operator to operands x and y.
     *
     * @param x
     *            first operand.
     * @param y
     *            second operand.
     * @param operator
     * @return result of operation
     * @throws InvalidOperatorException
     */
    private double applyOperator(double x, double y, String operator)
            throws InvalidOperatorException {
        if (operator.equals("+"))
            return x + y;
        else if (operator.equals("-"))
            return x - y;
        else if (operator.equals("*"))
            return x *= y;
        else if (operator.equals("/"))
            return x / y;
        else
            throw new InvalidOperatorException(operator);
    }

    /**
     * Resolve a reference to another cell within the spreadsheet. If the other
     * cell has a valid value, then the value will be returned, otherwise an
     * UnresolvedReferenceException will be thrown.
     *
     * @param reference
     *            reference to another cell in the spreadsheet.
     * @return value of referenced cell.
     * @throws UnresolvedReferenceException
     * @throws InvalidValueException
     */
    private double resolveCellReference(String reference)
            throws UnresolvedReferenceException {
        int col = reference.charAt(0) - 'A';
        int row = Integer.parseInt(reference.substring(1)) - 1;
        Cell referencedCell = spreadsheet.getCell(row, col);
        try {
            return referencedCell.getValue();
        } catch (InvalidValueException e) {
            throw new UnresolvedReferenceException();
        }
    }

    /**
     * Determine whether a term in an expression is a reference to another cell.
     *
     * @param term
     * @return whether term is a cell reference.
     */
    private boolean isCellReference(String term) {
        return Character.isLetter(term.charAt(0));
    }

    /**
     * Thrown to indicate than an invalid operator is specified in cell
     * expression.
     */
    public class InvalidOperatorException extends Exception {

        private static final long serialVersionUID = 1L;
        private String operator;

        public InvalidOperatorException(String operator) {
            this.operator = operator;
        }

        public String toString() {
            return "Invalid operator " + operator;
        }

    }

    /**
     * Thrown to indicate that a cell reference cannot be resolved. This occurs
     * if a valid value is not currently available for the referenced cell.
     */
    public class UnresolvedReferenceException extends Exception {

        private static final long serialVersionUID = 1L;

    }

    /**
     * Thrown to indicate that getValue() was called on a cell with a value that
     * is currently invalid.
     */
    public class InvalidValueException extends Exception {

        private static final long serialVersionUID = 1L;

    }

}
/**
 * This class encapsulates a single cell within a spreadsheet.
 */
public class Cell {

    private SpreadSheet spreadsheet; // spreadsheet to which cell belongs,
                                        // necessary for resolving cell
                                        // references
    private String expression; // expression within cell in reverse Polish
                                // notation
    private double value; // numerical value of evaluating expression
    private boolean valueValid; // whether a valid value has been found so
                                // far. This will change from false to true
                                // once all cell references have been
                                // resolved, provided that there are no
                                // circular references

    /**
     * Constructor for a cell belonging to a particular spreadsheet.
     *
     * @param spreadsheet
     *            SpreadSheet to which Cell belongs.
     * @param expression
     *            expression within cell.
     */
    public Cell(SpreadSheet spreadsheet, String expression) {
        this.spreadsheet = spreadsheet;
        this.expression = expression;
    }

    /**
     * Evaluates expression within a cell. Expression must be in reverse Polish
     * notation.
     *
     * @throws InvalidOperatorException
     *             if cell expression contains an invalid operator.
     */
    public void evaluate() throws InvalidOperatorException {
        if (!valueValid) { // prevent reevaluation of cells that have valid
                            // values
            try {
                // create stack containing terms in expression
                Deque<String> expressionStack = new ArrayDeque<String>(
                        Arrays.asList(expression.split("\\s")));
                value = evaluateRpn(expressionStack);
                valueValid = true;
            } catch (UnresolvedReferenceException e) {
                // no action is necessary if a reference is unresolved, since it
                // may be resolved at a later iteration during the solution of
                // the spreadsheet
            }
        }
    }

    /**
     * Get value of a cell. This is the numerical value resulting from
     * evaluating the cell's expression.
     *
     * @return numerical value resulting from evaluating cell's expression.
     * @throws InvalidValueException
     *             if a valid value is not currently available.
     */
    public double getValue() throws InvalidValueException {
        if (isValueValid()) {
            return value;
        } else {
            throw new InvalidValueException();
        }
    }

    /**
     * Check if a valid numerical value has been evaluated for the cell. This
     * will be true when evaluate() is called on the cell and all of the cell
     * references in the cell's expression can be resolved.
     *
     * @return whether cell value is valid.
     */
    public boolean isValueValid() {
        return valueValid;
    }

    /**
     * Evaluate an expression contained within an ExpressionStack.
     *
     * @param expressionStack
     *            an expression represented as a stack of individual terms.
     * @return evaluation of expression
     * @throws InvalidOperatorException
     * @throws UnresolvedReferenceException
     */
    private double evaluateRpn(Deque<String> expressionStack)
            throws InvalidOperatorException, UnresolvedReferenceException {
        String term = expressionStack.removeLast();
        if (isCellReference(term)) {
            // if last term in expression is a cell reference then resolve it
            return resolveCellReference(term);
        } else {
            double x, y;
            try {
                // if last term in expression is double then return it
                x = Double.parseDouble(term);
            } catch (NumberFormatException e) {
                // otherwise last term is an operator, evaluate operands and
                // apply operator
                y = evaluateRpn(expressionStack);
                x = evaluateRpn(expressionStack);
                x = applyOperator(x, y, term);
            }
            return x;
        }
    }

    /**
     * Apply operator to operands x and y.
     *
     * @param x
     *            first operand.
     * @param y
     *            second operand.
     * @param operator
     * @return result of operation
     * @throws InvalidOperatorException
     */
    private double applyOperator(double x, double y, String operator)
            throws InvalidOperatorException {
        if (operator.equals("+"))
            return x + y;
        else if (operator.equals("-"))
            return x - y;
        else if (operator.equals("*"))
            return x *= y;
        else if (operator.equals("/"))
            return x / y;
        else
            throw new InvalidOperatorException(operator);
    }

    /**
     * Resolve a reference to another cell within the spreadsheet. If the other
     * cell has a valid value, then the value will be returned, otherwise an
     * UnresolvedReferenceException will be thrown.
     *
     * @param reference
     *            reference to another cell in the spreadsheet.
     * @return value of referenced cell.
     * @throws UnresolvedReferenceException
     */
    private double resolveCellReference(String reference)
            throws UnresolvedReferenceException {
        int col = reference.charAt(0) - 'A';
        int row = Integer.parseInt(reference.substring(1)) - 1;
        Cell referencedCell = spreadsheet.getCell(row, col);
        try {
            return referencedCell.getValue();
        } catch (InvalidValueException e) {
            throw new UnresolvedReferenceException();
        }
    }

    /**
     * Determine whether a term in an expression is a reference to another cell.
     *
     * @param term
     * @return whether term is a cell reference.
     */
    private boolean isCellReference(String term) {
        return Character.isLetter(term.charAt(0));
    }

    /**
     * Thrown to indicate than an invalid operator is specified in cell
     * expression.
     */
    public class InvalidOperatorException extends Exception {

        private static final long serialVersionUID = 1L;
        private String operator;

        public InvalidOperatorException(String operator) {
            this.operator = operator;
        }

        public String toString() {
            return "Invalid operator " + operator;
        }

    }

    /**
     * Thrown to indicate that a cell reference cannot be resolved. This occurs
     * if a valid value is not currently available for the referenced cell.
     */
    public class UnresolvedReferenceException extends Exception {

        private static final long serialVersionUID = 1L;

    }

    /**
     * Thrown to indicate that getValue() was called on a cell with a value that
     * is currently invalid.
     */
    public class InvalidValueException extends Exception {

        private static final long serialVersionUID = 1L;

    }

}
1
source | link