Package reportgen.math.complex

Source Code of reportgen.math.complex.MathExpressionComplex$MathExpressionListEx

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package reportgen.math.complex;

import reportgen.math.reference.operator.MathExpressionOperatorRef;
import reportgen.math.MathExpressionList;
import org.jdom.Element;
import reportgen.utils.ReportException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import reportgen.prototype.context.Context;
import reportgen.prototype.context.group.ContextGroup;
import reportgen.math.ContextFilter;
import reportgen.math.MathExpression;
import reportgen.math.MathExpressionOperand;
import reportgen.math.reference.operator.variants.binary.MathOperatorBinary;
import reportgen.prototype.UsedReportableType;
import reportgen.prototype.stream.SQLStream;

/**
* Составное математическое выражение состоит из одного
* или нескольких математических элементов.
* Все элементы должны быть разделены оператором.
* Все элементы в выражении должны быть одного типа.
*
* @author axe
*/
abstract public class MathExpressionComplex extends MathExpressionOperand
    implements ContextFilter {

    protected Stack<MathExpression> stack = new Stack<MathExpression>();

    protected final MathExpressionList children;

    public MathExpressionComplex(Context context) {
        super(context);
        children = new MathExpressionListEx();
    }

    public MathExpressionComplex(Element element, Context context) throws ReportException {
        super(element, context);
        this.children = new MathExpressionListEx(element, context, this);
    }

    /**
     *
     * @return
     */
    @Override
    protected void toXML(Element root) {
        children.toXML(root);
    }

    @Override
    public Context getChildContext(ContextGroup group) {
        return getParentContext();
    }

    public MathExpressionList getChildren() {
        return children;
    }

    public boolean isEmpty() {
        return children.size() == 0;
    }
    /**
     * Собирает все использованные свойства в запросе, для того что бы загрузить
     * для них данные из отчета
     * @param set
     */
    @Override
    public void buildUsedSet(UsedReportableType cls, Set set) {
        children.buildUsedSet(cls, set);
    }

    /**
     *
     * @param sql
     * @throws reportgen.ren.exception.ReportException
     */
    @Override
    public void appendToQuery(SQLStream sql, Map model) throws ReportException {
        children.appendToQuery(sql, model);
    }

    @Override
    public Class getCls() throws ReportException {
        if(isNeedRecalcStack()) {
            stack = buildStack();
        }
        Stack calcstack = (Stack) stack.clone();
        Class eax = ((MathExpressionOperand) calcstack.pop()).getCls();
        while (!calcstack.empty()) {
            Object express1 = calcstack.pop();
            Object express2 = calcstack.pop();
            if (express2 instanceof MathExpressionOperatorRef) {
                MathExpressionOperatorRef operator = (MathExpressionOperatorRef) express2;
                Class op2Class = getExpressionClass(express1);
                MathOperatorBinary opcode = (MathOperatorBinary) operator.getRef();
                eax = opcode.checkAvailiable(eax, op2Class);
            } else {
                MathExpressionOperatorRef operator = (MathExpressionOperatorRef) calcstack.pop();
                Class op1Class = getExpressionClass(express1);
                Class op2Class = getExpressionClass(express2);
                MathOperatorBinary opcode = (MathOperatorBinary) operator.getRef();
                Class res = opcode.checkAvailiable(op1Class, op2Class);
                calcstack.push(res);
            }
        }
        return eax;
    }

    /**
     *
     * @param constants
     * @return
     * @throws reportgen.ren.exception.ReportException
     */
    @Override
    public Object getValue(Map constants) throws ReportException {
        if(isNeedRecalcStack()) {
            stack = buildStack();
        }
        Stack calcstack = (Stack) stack.clone();
        Object eax = ((MathExpressionOperand) calcstack.pop()).getValue(constants);
        while (!calcstack.empty()) {
            Object express1 = calcstack.pop();
            Object express2 = calcstack.pop();
            if (express2 instanceof MathExpressionOperatorRef) {
                MathExpressionOperatorRef operator = (MathExpressionOperatorRef) express2;
                Object op2Value = getExpressionValue(express1, constants);
                MathOperatorBinary opcode = (MathOperatorBinary) operator.getRef();
                eax = opcode.getValue(eax, op2Value);
            } else {
                MathExpressionOperatorRef operator = (MathExpressionOperatorRef) calcstack.pop();
                Object op1Value = getExpressionValue(express1, constants);
                Object op2Value = getExpressionValue(express2, constants);
                MathOperatorBinary opcode = (MathOperatorBinary) operator.getRef();
                Object res = opcode.getValue(op1Value, op2Value);
                calcstack.push(res);
            }
        }

        return eax;
    }

    /**
     *
     * @throws reportgen.ren.exception.ReportException
     */
    protected Stack<MathExpression> buildStack() throws ReportException {
        ArrayList<MathExpression> elements = new ArrayList<MathExpression>();
        for(int i=0; i<children.size(); i++) {
            elements.add(children.get(i));
        }
        return buildStack(elements, 0, elements.size()-1, new Stack<MathExpression>());
    }

    /**
     *
     * @param entity
     * @return
     */
    @Override
    public final boolean isContain(Object object) {
        if(super.isContain(object)) {
            return true;
        }
        return children.isContain(object);
    }


    @Override
    public boolean containsMissingVariables() {
        return children.containsMissingVariables();
    }

    protected void clearStack() {
        stack.clear();
    }

    protected boolean isNeedRecalcStack() {
        return stack.isEmpty();
    }
    /**
     *
     * @return
     */
    @Override
    public String toString() {
        if (children.size() == 0) {
            return super.toString();
        }
        return children.toString();
    }

    /**
     *
     * @throws reportgen.ren.exception.ReportException
     */
    @Override
    public void validate() throws ReportException {
        super.validate();
        children.validate();
        getCls();
    }

   /**
     *
     * @param elem
     * @param stack
     * @return
     * @throws reportgen.ren.exception.ReportException
     */
    final protected Stack<MathExpression> buildStack(List<MathExpression> elem, int beg, int end,
            Stack<MathExpression> stack) throws ReportException {
        if(beg > end) {
            throw new ReportException("Пустое выражение");
        }
        //get min priority operand
        int pos = -1;
        int priority = Integer.MAX_VALUE;
        MathExpressionOperatorRef operator = null;
        for(int j=end; j>=beg; j--) {
            MathExpression element = elem.get(j);
            if(element instanceof MathExpressionOperatorRef) {
                MathExpressionOperatorRef iOperator = (MathExpressionOperatorRef) element;
                int prior = iOperator.getRef().getPriority();
                if(prior < priority) {
                    priority = prior;
                    pos = j;
                    operator = iOperator;
                }
            }
        }

        if(pos == -1) {
            if(end == beg) {
                //it allways be operand
                stack.add(elem.get(0));
                return stack;
            }

            throw new ReportException("Выражение составлено неверно, пропущен оператор");
        }

        if(pos == 0) {
            throw new ReportException("Перед оператором '" + operator + "' должен быть операнд");
        } else if(pos+1 == elem.size()) {
            throw new ReportException("После оператора '" + operator + "' должен быть операнд");
        }

        int leftOperandPos = pos-1;
        int rightOperandPos = pos+1;
        MathExpression leftOperand = elem.get(leftOperandPos);
        MathExpression rightOperand = elem.get(rightOperandPos);

        if(!(leftOperand instanceof MathExpressionOperand)) {
            throw new ReportException("Перед оператором '" + operator + "' должен быть операнд");
        } else if (!(rightOperand instanceof MathExpressionOperand)) {
            throw new ReportException("После оператора '" + operator + "' должен быть операнд");
        }

        stack.add(operator);

        //right part
        if(rightOperandPos == end) {
            stack.add(rightOperand);
        } else {
            stack = buildStack(elem, rightOperandPos, end, stack);
        }

        //left part
        if(leftOperandPos == beg) {
            stack.add(leftOperand);
        } else {
            stack = buildStack(elem, beg, leftOperandPos, stack);
        }

        return stack;
    }
    /**
     *
     * @param express
     * @return
     * @throws reportgen.ren.exception.ReportException
     */
    static private Class getExpressionClass(Object express) throws ReportException {
        if(express instanceof MathExpressionOperand) {
            MathExpressionOperand operand = (MathExpressionOperand) express;
            return operand.getCls();
        } else if(express instanceof Class) {
            return (Class) express;
        }
        throw new ReportException("Ожидается операнд: " + express);
    }

    /**
     *
     * @param express
     * @param constants
     * @return
     * @throws reportgen.ren.exception.ReportException
     */
    static private Object getExpressionValue(Object express, Map constants)
            throws ReportException {
        if(express instanceof MathExpressionOperand) {
            MathExpressionOperand operand = (MathExpressionOperand) express;
            return operand.getValue(constants);
        }
        return express;
    }



    private class MathExpressionListEx extends MathExpressionList {

        public MathExpressionListEx() {
        }

        public MathExpressionListEx(Element root, Context context, ContextFilter cf) throws ReportException {
            super(root, context, cf);
        }

        @Override
        protected void onAdd(MathExpression value) {
            super.onAdd(value);
            clearStack();
        }

        @Override
        protected void onRemove(MathExpression value) throws ReportException {
            super.onRemove(value);
            clearStack();
        }

        @Override
        protected void onMove() {
            super.onMove();
            clearStack();
        }
    }
}
TOP

Related Classes of reportgen.math.complex.MathExpressionComplex$MathExpressionListEx

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.