Operation.java
package calculator.operations;
import java.util.ArrayList;
import java.util.List;
import calculator.Expression;
import calculator.IllegalConstruction;
import calculator.Notation;
import calculator.atoms.Atom;
import calculator.atoms.Complex;
import calculator.atoms.IntegerAtom;
import calculator.atoms.Rationnal;
import calculator.atoms.Real;
import visitor.Printer;
import visitor.Visitor;
/**
* Operation is an abstract class that represents arithmetic operations,
* which are a special kind of Expressions, just like numbers are.
*
* @see Expression
* @see Atom
*/
public abstract class Operation implements Expression {
/**
* The list of expressions passed as an argument to the arithmetic operation
*/
public List<Expression> args;
/**
* The character used to represent the arithmetic operation (e.g. "+", "*")
*/
protected String symbol;
/**
* The neutral element of the operation (e.g. 1 for *, 0 for +)
*/
protected int neutral;
/**
* To construct an operation with a list of expressions as arguments,
* as well as the Notation used to represent the operation.
*
* @param elist The list of expressions passed as argument to the arithmetic
* operation
* @throws IllegalConstruction Exception thrown if a null list of expressions is
* passed as argument
*/
protected /* constructor */ Operation(List<Expression> elist)
throws IllegalConstruction {
if (elist == null) {
throw new IllegalConstruction();
} else {
args = new ArrayList<>(elist);
}
}
/**
* getter method to return the number of arguments of an arithmetic operation.
*
* @return The number of arguments of the arithmetic operation.
*/
public List<Expression> getArgs() {
return args;
}
/**
* getter method to return the symbol of the arithmetic operation.
*
* @return The symbol of the arithmetic operation (e.g. "+", "-", "*", "/").
*/
public String getSymbol() {
return symbol;
}
/**
* Abstract method representing the actual binary arithmetic operation to
* compute on Reals
*
* @param r1 first Real of the binary operation
* @param r2 second Real of the binary operation
* @return result of computing the binary operation
*/
public abstract Real op(Real r1, Real r2);
/**
* Abstract method representing the actual binary arithmetic operation to
* compute on Complexes
*
* @param c1 first Complex of the binary operation
* @param c2 second Complex of the binary operation
* @return result of computing the binary operation
*/
public abstract Complex op(Complex c1, Complex c2);
/**
* Abstract method representing the actual binary arithmetic operation to
* compute on Integer
*
* @param i1 first Integer of the binary operation
* @param i2 second Integer of the binary operation
* @return result of computing the binary operation
*/
public abstract Atom op(IntegerAtom i1, IntegerAtom i2);
/**
* Abstract method representing the actual binary arithmetic operation to
* compute on Rationnals
*
* @param q1 first Rationnal of the binary operation
* @param q2 second Rationnal of the binary operation
* @return result of computing the binary operation
*/
public abstract Atom op(Rationnal q1, Rationnal q2);
/**
* Add more parameters to the existing list of parameters
*
* @param params The list of parameters to be added
*/
public void addMoreParams(List<Expression> params) {
args.addAll(params);
}
/**
* Accept method to implement the visitor design pattern to traverse arithmetic
* expressions.
* Each operation will delegate the visitor to each of its arguments
* expressions,
* and will then pass itself to the visitor object to get processed by the
* visitor object.
*
* @param v The visitor object
*/
public void accept(Visitor v) {
v.visit(this);
}
/**
* Convert the arithmetic operation into a String to allow it to be printed,
* using the default printer
*
* @return The String that is the result of the conversion.
*/
@Override
public final String toString() {
Printer p = new Printer();
this.accept(p);
return p.getResult();
}
/**
* Appeal to the visitor to convert the arithmetic operation into a String to
* allow it to be printed,
* using the notation n (prefix, infix or postfix) that is specified as a
* parameter.
*
* @param n The notation to be used for representing the operation (prefix,
* infix or postfix)
* @return The String that is the result of the conversion.
*/
public final String toString(Notation n) {
Printer p = new Printer(n);
this.accept(p);
return p.getResult();
}
/**
* Two operation objects are equal if their list of arguments is equal and they
* correspond to the same operation.
*
* @param o The object to compare with
* @return The result of the equality comparison
*/
@Override
public boolean equals(Object o) {
if (o == null)
return false; // No object should be equal to null
if (this == o)
return true; // If it's the same object, they're obviously equal
if (getClass() != o.getClass())
return false; // getClass() instead of instanceof() because an addition is not the same as a
// multiplication
Operation other = (Operation) o;
return this.args.equals(other.getArgs());
}
/**
* The method hashCode needs to be overridden it the equals method is
* overridden;
* otherwise there may be problems when you use your object in hashed
* collections
* such as HashMap, HashSet, LinkedHashSet.
*
* @return The result of computing the hash.
*/
@Override
public int hashCode() {
int result = 5;
int prime = 31;
result = prime * result + neutral;
result = prime * result + symbol.hashCode();
result = prime * result + args.hashCode();
return result;
}
}