Package com.asakusafw.compiler.flow.processor

Source Code of com.asakusafw.compiler.flow.processor.MasterKindFlowAnalyzer

/**
* Copyright 2011-2014 Asakusa Framework Team.
*
* 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 com.asakusafw.compiler.flow.processor;

import java.util.List;

import com.asakusafw.compiler.common.Precondition;
import com.asakusafw.compiler.flow.FlowElementProcessor.DataObjectMirror;
import com.asakusafw.compiler.flow.FlowElementProcessor.ListBufferMirror;
import com.asakusafw.compiler.flow.RendezvousProcessor;
import com.asakusafw.utils.collections.Lists;
import com.asakusafw.utils.java.model.syntax.Expression;
import com.asakusafw.utils.java.model.syntax.InfixOperator;
import com.asakusafw.utils.java.model.syntax.ModelFactory;
import com.asakusafw.utils.java.model.syntax.SimpleName;
import com.asakusafw.utils.java.model.syntax.Statement;
import com.asakusafw.utils.java.model.util.ExpressionBuilder;
import com.asakusafw.utils.java.model.util.Models;
import com.asakusafw.vocabulary.flow.graph.FlowElementPortDescription;
import com.asakusafw.vocabulary.flow.graph.OperatorDescription;
import com.asakusafw.vocabulary.flow.graph.OperatorHelper;
import com.asakusafw.vocabulary.flow.processor.InputBuffer;

/**
* {@code Master*}系の演算子を解析する。
*/
public class MasterKindFlowAnalyzer {

    // FIXME 現在のところ、ソート順序がマスタ、トランザクション、と言うようになっていることが前提

    private Expression hasMasterExpresion;

    private Expression getMasterExpression;

    private Expression getCheckedMasterExpression;

    /**
     * インスタンスを生成する。
     * @param context 文脈オブジェクト
     * @throws IllegalArgumentException 引数に{@code null}が指定された場合
     */
    public MasterKindFlowAnalyzer(RendezvousProcessor.Context context) {
        Precondition.checkMustNotBeNull(context, "context"); //$NON-NLS-1$
        OperatorHelper selector = context.getOperatorDescription().getAttribute(OperatorHelper.class);
        if (selector == null) {
            processMasterFirst(context);
        } else {
            processMasterSelection(context, selector);
        }
    }

    /**
     * マスタデータが存在するか確認するための式を返す。
     * @return マスタデータが存在するか確認するための式
     */
    public Expression getHasMasterExpresion() {
        return hasMasterExpresion;
    }

    /**
     * マスタデータを取得するための式を返す。
     * <p>
     * ただし、{@link #getHasMasterExpresion()}が{@code false}をあらわす場合、
     * この式の内容は不定である。
     * </p>
     * @return マスタデータを取得するための式
     */
    public Expression getGetRawMasterExpression() {
        return getMasterExpression;
    }

    /**
     * マスタデータを取得するための式を返す。
     * <p>
     * ただし、{@link #getHasMasterExpresion()}が{@code false}をあらわす場合、
     * この式は常に{@code null}をあらわす。
     * </p>
     * @return マスタデータを取得するための式
     */
    public Expression getGetCheckedMasterExpression() {
        return getCheckedMasterExpression;
    }

    private void processMasterFirst(RendezvousProcessor.Context context) {
        assert context != null;
        ModelFactory f = context.getModelFactory();
        OperatorDescription desc = context.getOperatorDescription();
        FlowElementPortDescription master = desc.getInputPorts().get(0);

        Expression hasMaster = context.createField(boolean.class, "sawMaster");
        DataObjectMirror masterCache = context.createModelCache(master.getDataType());
        context.addBegin(new ExpressionBuilder(f, hasMaster)
            .assignFrom(Models.toLiteral(f, false))
            .toStatement());
        context.addProcess(master, f.newIfStatement(
                new ExpressionBuilder(f, hasMaster)
                    .apply(InfixOperator.EQUALS, Models.toLiteral(f, false))
                    .toExpression(),
                f.newBlock(new Statement[] {
                        masterCache.createSet(context.getProcessInput(master)),
                        new ExpressionBuilder(f, hasMaster)
                            .assignFrom(Models.toLiteral(f, true))
                            .toStatement()
                }),
                null));

        this.hasMasterExpresion = hasMaster;
        this.getMasterExpression = masterCache.get();
        this.getCheckedMasterExpression = f.newConditionalExpression(
                hasMasterExpresion,
                getMasterExpression,
                Models.toNullLiteral(f));
    }

    private void processMasterSelection(
            RendezvousProcessor.Context context,
            OperatorHelper selector) {
        assert context != null;
        assert selector != null;
        ModelFactory f = context.getModelFactory();
        OperatorDescription desc = context.getOperatorDescription();
        FlowElementPortDescription master = desc.getInputPorts().get(0);
        FlowElementPortDescription tx = desc.getInputPorts().get(1);

        ListBufferMirror list = context.createListBuffer(master.getDataType(), InputBuffer.EXPAND);
        context.addBegin(list.createBegin());
        Expression proc = context.getProcessInput(master);
        context.addProcess(master, list.createAdvance(proc));
        context.addEnd(list.createEnd());

        List<Expression> arguments = Lists.create();
        arguments.add(list.get());
        arguments.add(context.getProcessInput(tx));
        for (OperatorDescription.Parameter param : desc.getParameters()) {
            arguments.add(Models.toLiteral(f, param.getValue()));
        }
        assert selector.getParameterTypes().size() <= arguments.size();
        if (selector.getParameterTypes().size() <= arguments.size()) {
            arguments = arguments.subList(0, selector.getParameterTypes().size());
        }

        context.addProcess(tx, list.createEnd());
        Expression impl = context.createImplementation();
        SimpleName selected = context.createName("selected");
        context.addProcess(tx, new ExpressionBuilder(f, impl)
            .method(selector.getName(), arguments)
            .toLocalVariableDeclaration(
                    context.convert(master.getDataType()),
                    selected));

        context.addEnd(list.createShrink());

        this.hasMasterExpresion = new ExpressionBuilder(f, selected)
            .apply(InfixOperator.NOT_EQUALS, Models.toNullLiteral(f))
            .toExpression();
        this.getMasterExpression = selected;
        this.getCheckedMasterExpression = selected;
    }
}
TOP

Related Classes of com.asakusafw.compiler.flow.processor.MasterKindFlowAnalyzer

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.