Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright 2014 Davor Sauer
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   * http://www.apache.org/licenses/LICENSE-2.0
   *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 package org.jdice.calc;
 
Abstract class that concrete calculator extends

Parameters:
<CALC>
Author(s):
Davor Sauer <davor.sauer@gmail.com>
 
 public abstract class AbstractCalculator<CALC> {

    
Detect changes in equation
 
     private CList infix = new CList(new CListListener() {
         @Override
         public void change() {
              = true;
         }
     });
     private boolean isInfixChanged = true;
     private CList postfix = new CList();
     private Num lastCalculatedValue;
     private LinkedList<StringcalculationSteps;
 
     private Properties properties;
     private static boolean isImplOpRegistered = false;
 
     private AbstractCalculator<CALC> parentCalc;
     private AbstractCalculator<CALC> childCalc;
     private boolean isBind = false;
     private boolean isUnbind = false;
 
     //
     // Constructor's
     //
     public AbstractCalculator() {
     }

    
Register implemented operation and functions by subclass
 
     private void registerImplmentedOperation() {
         if ( == false) {
             Object o = getThis();
             Class thisClass = o.getClass();
 
             // superclass interfaces
             Class[] declared = thisClass.getSuperclass().getInterfaces();
             for (Class declare : declared) {
                 registerImplmentedOperation(declare);
             }
 
             // subclass interfaces
             declared = thisClass.getInterfaces();
             for (Class declare : declared) {
                 registerImplmentedOperation(declare);
             }
              = true;
         }
     }

    
Register defined operation or function class to global cache

Parameters:
declare
 
     private void registerImplmentedOperation(Class declare) {
         Class c = LinkOperation.getOperation(declare);
         if (c == null && declare.isAnnotationPresent(Implementation.class)) {
             Implementation impl = (Implementationdeclare.getAnnotation(Implementation.class);
             if (impl != null)
                 c = impl.implementatio();
             LinkOperation.link(declarec);
         }
 
         if (c != null) {
            if (Operator.class.isAssignableFrom(c))
                Cache.registerOperator(c);
            if (Function.class.isAssignableFrom(c))
                Cache.registerFunction(c);
        }
    }

    
Return reference of subclass

Returns:
    protected abstract CALC getThis();

    
Constructor

Parameters:
value can be any object than Num can work with
    public AbstractCalculator(Object value) {
        Num cValue = new Num();
        cValue.set(value);
        .add(cValue);
    }
    public AbstractCalculator(Num value) {
        .add(value);
    }
    public AbstractCalculator(String value) {
        Num cValue = new Num(value);
        .add(cValue);
    }
    public AbstractCalculator(String valuechar decimalSeparator) {
        Num cValue = new Num(valuedecimalSeparator);
        .add(cValue);
    }


    
Provide custom Operator or Function inside scope of this instance, that can be used during equation parsing. With registration of custom operation it's possible to override existing default operation implementation. Because during calculation API first scan scoped (registered) operation and after that default operation implementation inside Cache

Parameters:
operationClass
Returns:
    public CALC register(Class<? extends OperationoperationClass) {
        if ( == null)
             = new OperationRegister();
        if (Operator.class.isAssignableFrom(operationClass))
            .registerOperator(operationClass.asSubclass(Operator.class));
        if (Function.class.isAssignableFrom(operationClass))
            .registerFunction(operationClass.asSubclass(Function.class));
        return getThis();
    }

    
List registered local scoped operations.

Returns:
        return this.;
    }
    //
    // APPEND VALUE
    //

    
Append value to equation

Parameters:
value
Returns:
    public CALC val(short value) {
        .add(new Num(value));
        return getThis();
    }

    
Append value to equation

Parameters:
value
Returns:
    public CALC val(int value) {
        .add(new Num(value));
        return getThis();
    }

    
Append value to equation

Parameters:
value
Returns:
    public CALC val(long value) {
        .add(new Num(value));
        return getThis();
    }

    
Append value to equation

Parameters:
value
Returns:
    public CALC val(float value) {
        .add(new Num(value));
        return getThis();
    }

    
Append value to equation

Parameters:
value
Returns:
    public CALC val(double value) {
        .add(new Num(value));
        return getThis();
    }

    
Append value to equation

Parameters:
value
Returns:
    public CALC val(Object value) {
        .add(new Num(value));
        return getThis();
    }

    
Append value to equation

Parameters:
value custom type value
converter class for convert custom type to Num
Returns:
    public CALC val(Object valueClass<? extends NumConverterconverter) {
        .add(new Num(valueconverter));
        return getThis();
    }

    
Append String value to equation that will be parsed to Num

Parameters:
value
Returns:
    public CALC val(String value) {
        .add(new Num(value));
        return getThis();
    }

    
Append String value to equation that will be parsed to Num with defined decimal separator

Parameters:
value String representation of number
decimalSeparator used in string representation of number
Returns:
    public CALC val(String valuechar decimalSeparator) {
        .add(new Num(valuedecimalSeparator));
        return getThis();
    }

    
Append value to equation

Parameters:
value
Returns:
    public CALC val(Num value) {
        .add(value);
        return getThis();
    }

    
Copy calculator equation into this equation within brackets

Parameters:
equation
Returns:
:
    public CALC append(AbstractCalculator equation) {
        return append(equationtrue);
    }

    
Copy equation from given calculator into this equation within or without brackets

Parameters:
equation
withinBrackets
Returns:
    public CALC append(AbstractCalculator equationboolean withinBrackets) {
        append(equation.infixwithinBrackets);
        return getThis();
    }

    
Copy infix equation into this equation within or without brackets

Parameters:
infix
withinBrackets
Returns:
    public CALC append(CList infixboolean withinBrackets) {
        if (withinBrackets)
            this..add(.);
        Iterator<Objectit = infix.iterator();
        while (it.hasNext()) {
            Object o = it.next();
            if (o instanceof Num) {
                this..add((Numo);
            }
            else if (o instanceof Operator) {
                this..add((Operatoro);
            }
            else if (o instanceof FunctionData) {
                this..add((FunctionDatao);
            }
            else if (o instanceof Function) {
                this..add((Functiono);
            }
            else if (o instanceof Bracket) {
                this..add((Bracketo);
            }
        }
        if (withinBrackets)
            this..add(.);
        return getThis();
    }

    
Append operator to equation

Parameters:
operator
Returns:
    public CALC append(Class<? extends Operatoroperator) {
        .add(operator);
        return getThis();
    }

    
Append operator and number to equation

Parameters:
operator
value
Returns:
    public CALC append(Class<? extends OperatoroperatorObject value) {
        return append(operatornew Num(value));
    }

    
Append operator and parsed String value with custom decimal separator used in String representation of value

Parameters:
operator
value
decimalSeparator
Returns:
    public CALC append(Class<? extends OperatoroperatorString valuechar decimalSeparator) {
        return append(operatornew Num(valuedecimalSeparator));
    }

    
Append operator and number to equation

Parameters:
operator
value
Returns:
    public CALC append(Class<? extends OperatoroperatorNum value) {
        .add(Cache.getOperator(operator));
        .add(value);
        return getThis();
    }

    
Append function with value to equation.
e.g. Abs.class, -5 => abs(-5)

Parameters:
function
values can accept any object that Num can work with
Returns:
See also:
Function
    public CALC append(Class<? extends FunctionfunctionObject... values) {
        Function fn = Cache.getFunction(function);
        FunctionData fd = new FunctionData(fnvalues);
        this..addFunction(fd);
        return getThis();
    }

    
Parse and append given equation to existing equation

Parameters:
equation
Returns:
Throws:
java.text.ParseException
    public CALC parse(String equationthrows ParseException {
        append(Infix.parseInfix(getProperties(), equation), false);
        return getThis();
    }

    
Parse and append given equation to existing equation

Parameters:
equation
Returns:
Throws:
java.text.ParseException
:
    public CALC parse(String equationObject... valuesthrows ParseException {
        append(Infix.parseInfix(getProperties(), equationvalues), false);
        return getThis();
    }
    //
    // BRACKET'S
    //
    
Open bracket

Returns:
    public CALC ob() {
        .add(.);
        return getThis();
    }

    
Open bracket

Returns:
    public CALC openBracket() {
        .add(.);
        return getThis();
    }


    
Open bracket and add value after. e.g. (5

Parameters:
value
Returns:
    public CALC openBracket(short value) {
        .add(.new Num(value));
        return getThis();
    }

    
Open bracket and add value after. e.g. (5

Parameters:
value
Returns:
    public CALC openBracket(int value) {
        .add(.new Num(value));
        return getThis();
    }

    
Open bracket and add value after. e.g. (5

Parameters:
value
Returns:
    public CALC openBracket(long value) {
        .add(.new Num(value));
        return getThis();
    }

    
Open bracket and add value after. e.g. (5

Parameters:
value
Returns:
    public CALC openBracket(float value) {
        .add(.new Num(value));
        return getThis();
    }

    
Open bracket and add value after. e.g. (5

Parameters:
value
Returns:
    public CALC openBracket(double value) {
        .add(.new Num(value));
        return getThis();
    }

    
Open bracket and add value after. e.g. (5

Parameters:
value
Returns:
    public CALC openBracket(Object value) {
        .add(.new Num(value));
        return getThis();
    }

    
Open bracket and add value after. e.g. (5

Parameters:
value
Returns:
    public CALC openBracket(String value) {
        .add(.new Num(value));
        return getThis();
    }

    
Open bracket and add value after. e.g. (5

Parameters:
value
Returns:
    public CALC openBracket(String valuechar decimalSeparator) {
        .add(.new Num(valuedecimalSeparator));
        return getThis();
    }

    
Open bracket and add value after. e.g. (5

Parameters:
value
Returns:
    public CALC openBracket(Num value) {
        .add(.value);
        return getThis();
    }
    // ---------------
    
Close bracket

Returns:
    public CALC cb() {
        .add(.);
        return getThis();
    }

    
Close bracket

Returns:
    public CALC closeBracket() {
        .add(.);
        return getThis();
    }

    
Get defined properties

Returns:
    public Properties getProperties() {
        if ( == null)
             = new Properties();
        return ;
    }

    
Set proeprties

Parameters:
properties
Returns:
    public CALC setProperties(Properties properties) {
        this. = properties;
        return getThis();
    }

    
Set scale for entire equation

Parameters:
scale
Returns:
    public CALC setScale(Integer scale) {
        getProperties().setScale(scale);
        return getThis();
    }

    
Get scale mode used throughout equation

Returns:
    public Integer getScale() {
        return getProperties().getScale();
    }

    
Set rounding mode for entire equation

Parameters:
roundingMode
Returns:
    public CALC setRoundingMode(Rounding roundingMode) {
        getProperties().setRoundingMode(roundingMode);
        return getThis();
    }

    
Get rounding mode used throughout equation

Returns:
    public Rounding getRoundingMode() {
        return getProperties().getRoundingMode();
    }

    
Set decimal separator for entire equation

Parameters:
decimalSeparator
Returns:
    public CALC setDecimalSeparator(char decimalSeparator) {
        getProperties().setInputDecimalSeparator(decimalSeparator);
        getProperties().setOutputDecimalSeparator(decimalSeparator);
        return getThis();
    }

    
Get decimal separator used throughout equation

Returns:
    public char getDecimalSeparator() {
        return getProperties().getInputDecimalSeparator();
    }

    
Set number grouping separator for entire equation

Parameters:
decimalSeparator
Returns:
    public CALC setGroupingSeparator(char decimalSeparator) {
        getProperties().setGroupingSeparator(decimalSeparator);
        return getThis();
    }

    
Get grouping separator used throughout equation

Returns:
    public char getGroupingSeparator() {
        return getProperties().getGroupingSeparator();
    }
    //
    // LOGIC
    //

    
String representation of equation that will be parsed

Parameters:
equation
Returns:
Throws:
java.text.ParseException
See also:
parse(java.lang.String)
    public CALC equation(String equationthrows ParseException {
         = Infix.parseInfix(getProperties(), equation);
        return getThis();
    }

    
String representation of equation that will be parsed with unknown variables. It is possible to define name of Num with Num.setName(java.lang.String) then name will be matched with name of unknown variable. Otherwise unknown variable will be matched by declared order.
e.g. X + 5 - (2 * X - Y)

Parameters:
equation
values for unknown variables
Returns:
Throws:
java.text.ParseException
    public CALC equation(String equationNum... valuesthrows ParseException {
         = Infix.parseInfix(getProperties(), equationvalues);
        return getThis();
    }

    
Calculate prepared equation

    public Num calc() {
        return calculate();
    }

    
Calculate prepared equation and convert to object of given class

    public <T> T calc(Class<T> toClass) {
    	Num calc = calculate();
    	return (T)calc.toObject(toClass);
    }

    
Calculate prepared equation

    public Num calculate() {
        return calculate(falsefalse);
    }

    
Calculate equation and track calculation steps accessible with getCalculationSteps()

Returns:
    public Num calcWithSteps(boolean showDetails) {
        return calculate(trueshowDetails);
    }

    
Calculate equation

Parameters:
trackSteps
showDetails
Returns:
    private Num calculate(boolean trackStepsboolean showDetails) {
        unbind();
        prepareForNewCalculation();
        Postfix pc = convertToPostfix();
        Num cv = pc.calculate(thistrackStepsshowDetails);
         = cv.clone();
        return cv;
    }

    
Bind another Calculator class functionalities to equation. Way to combine two different implementation of calculators

Parameters:
clazz
Returns:
    public <T extends AbstractCalculator> T bind(Class<T> clazz) {
        T childCalc = null;
        try {
            childCalc = clazz.newInstance();
        }
        catch (Exception e) {
            throw new CalculatorException(e);
        }
        if (childCalc instanceof AbstractCalculator) {
            // find last child from root
            AbstractCalculator<CALC> bParent = this;
            while (bParent != null) {
                if (bParent.childCalc != null)
                    bParent = bParent.childCalc;
                else
                    break;
            }
            ((AbstractCalculatorchildCalc). = bParent;
            ((AbstractCalculatorchildCalc). = true;
            bParent.childCalc = childCalc;
        }
        else {
            throw new CalculatorException("Use only Calculator class subclases"new IllegalArgumentException());
        }
        return childCalc;
    }
    // /**
    // * Return to functionalities provided by original Calculator object
    // * @return
    // * @
    // */
    // private CALC unbind() {
    // if (parentCalc != null) {
    // parentCalc.append(this, false);
    // this.isUnbind = true;
    // return (CALC) parentCalc;
    // }
    // else if (this.childCalc != null)
    // return (CALC)unbindAll(this);
    // else
    // return (CALC) this;
    // }

    
Unbind binded calculator

Returns:
    private CALC unbind() {
        if ( != null)
            unbindAll(this);
        return (CALC) this;
    }

    
Unbind all binded calculators

Parameters:
undbindFrom
Returns:
    private CALC unbindAll(AbstractCalculator<CALC> undbindFrom) {
        // find root and first child
        AbstractCalculator root = undbindFrom.parentCalc != null ? undbindFrom.parentCalc : undbindFrom;
        AbstractCalculator child = root.childCalc;
        while (root != null) {
            AbstractCalculator tmpParent = root.parentCalc;
            if (tmpParent == null)
                break;
            else
                root = tmpParent;
            child = root.childCalc;
        }
        // undbind all from root to last child
        while (child != null) {
            if (child.isUnbind == false)
                root.append(childfalse);
            child.isUnbind = true;
            child = child.childCalc// new unbind child
        }
        return (CALC) undbindFrom;
    }

    
Convert defined equation to postfix String

Returns:
    public String getPostfix() {
        unbind();
        convertToPostfix();
        return Infix.printInfix(this.);
    }

    
Convert infix to postfix Conversion is made only first time or after any change in structure of infix equation

Returns:
    private Postfix convertToPostfix() {
        Postfix pc = new Postfix();
        if ( == null || .size() == 0 || ) {
            pc.toPostfix();
             = pc.getPostfix();
             = false;
        }
        return pc;
    }

    
Get infix (common arithmetic and logical formula notation) representation of given equation

Returns:
See also:
getPostfix()
    public String getInfix() {
        unbind();
        return toString();
    }

    
Provide infix list for this calculator.

Parameters:
infix
Returns:
    CALC setInfix(CList infix) {
        this. = infix;
        return getThis();
    }

    
To check whether the calculation is made according to a formula

Returns:
See also:
getCalculated()
    public boolean isCalculated() {
        if ( != null)
            return true;
        else
            return false;
    }

    
Return result copy of last calculated equation

Returns:
See also:
isCalculated()
    public Num getCalculated() {
        if ( != null)
            return .clone();
        else
            return null;
    }

    
Reset result and calculation steps of previous calculation
    private void prepareForNewCalculation() {
         = null;
        this. = null;
    }
    final void setSteps(LinkedList<StringcalculationSteps) {
        this. = calculationSteps;
    }

    
Check if calculation steps are remembered during calculation.

Returns:
See also:
getCalculationSteps()
    public boolean hasCalculationSteps() {
        return  != null ? true : false;
    }

    
Get calculation steps if calculation is initiated with calcWithSteps(boolean)

Returns:
See also:
        return ;
    }
    @Override
    public String toString() {
        return Infix.printInfix(this.);
    }
New to GrepCode? Check out our FAQ X