Package com.asakusafw.compiler.flow.processor

Source Code of com.asakusafw.compiler.flow.processor.SummarizeFlowProcessor$Prologue

/**
* 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.lang.reflect.Type;
import java.text.MessageFormat;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import com.asakusafw.compiler.common.Precondition;
import com.asakusafw.compiler.common.TargetOperator;
import com.asakusafw.compiler.flow.DataClass;
import com.asakusafw.compiler.flow.DataClass.Property;
import com.asakusafw.compiler.flow.LinePartProcessor;
import com.asakusafw.compiler.flow.RendezvousProcessor;
import com.asakusafw.compiler.flow.ShuffleDescription;
import com.asakusafw.runtime.util.TypeUtil;
import com.asakusafw.utils.collections.Lists;
import com.asakusafw.utils.collections.Maps;
import com.asakusafw.utils.java.model.syntax.Expression;
import com.asakusafw.utils.java.model.syntax.ModelFactory;
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.FlowElementDescription;
import com.asakusafw.vocabulary.flow.graph.FlowElementPortDescription;
import com.asakusafw.vocabulary.flow.graph.ShuffleKey;
import com.asakusafw.vocabulary.flow.processor.PartialAggregation;
import com.asakusafw.vocabulary.model.Summarized;
import com.asakusafw.vocabulary.model.Summarized.Aggregator;
import com.asakusafw.vocabulary.operator.Summarize;

/**
* {@link Summarize 単純集計演算子}を処理する。
*/
@TargetOperator(Summarize.class)
public class SummarizeFlowProcessor extends RendezvousProcessor {

    @Override
    public ShuffleDescription getShuffleDescription(
            FlowElementDescription element,
            FlowElementPortDescription port) {
        FlowElementPortDescription output = element.getOutputPorts().get(Summarize.ID_OUTPUT);
        LinePartProcessor line = new Prologue(port.getDataType(), output.getDataType());
        line.initialize(getEnvironment());
        return new ShuffleDescription(
                output.getDataType(),
                rebuildShuffleKey(output, port),
                line);
    }

    private ShuffleKey rebuildShuffleKey(FlowElementPortDescription output, FlowElementPortDescription input) {
        assert output != null;
        assert input != null;
        Summarized summarized = TypeUtil.erase(output.getDataType()).getAnnotation(Summarized.class);
        if (summarized == null) {
            throw new IllegalStateException(MessageFormat.format(
                    "Internal Error: {0} does not declared in {1} ({2})",
                    Summarized.class.getSimpleName(),
                    output.getDataType(),
                    output));
        }

        Map<String, String> mapping = Maps.create();
        for (Summarized.Folding folding : summarized.term().foldings()) {
            if (folding.aggregator() == Aggregator.ANY) {
                mapping.put(folding.source(), folding.destination());
            }
        }
        List<String> remapped = Lists.create();
        for (String original : input.getShuffleKey().getGroupProperties()) {
            String target = mapping.get(original);
            if (target == null) {
                throw new IllegalStateException(MessageFormat.format(
                        "Internal Error: Grouping key mismatched (output={0}, grouping={1}, mapping={2})",
                        output.getDataType(),
                        input.getShuffleKey(),
                        mapping));
            }
            remapped.add(target);
        }
        return new ShuffleKey(remapped, Collections.<ShuffleKey.Order>emptyList());
    }

    @Override
    public void emitRendezvous(Context context) {
        ModelFactory f = context.getModelFactory();

        FlowElementPortDescription input = context.getInputPort(Summarize.ID_INPUT);
        FlowElementPortDescription output = context.getOutputPort(Summarize.ID_OUTPUT);

        Expression init = context.createField(boolean.class, "initialized");
        context.addBegin(new ExpressionBuilder(f, init)
            .assignFrom(Models.toLiteral(f, false))
            .toStatement());

        DataObjectMirror cache = context.createModelCache(output.getDataType());

        List<Statement> combine = Lists.create();
        DataClass outputType = getEnvironment().getDataClasses().load(output.getDataType());
        Summarized summarized = TypeUtil.erase(output.getDataType()).getAnnotation(Summarized.class);
        for (Summarized.Folding folding : summarized.term().foldings()) {
            if (folding.aggregator() == Aggregator.ANY) {
                continue;
            }
            combine.add(createAddSummarizeFor(context, folding, outputType, cache.get()));
        }
        context.addProcess(input, f.newIfStatement(
                init,
                f.newBlock(combine),
                f.newBlock(
                        cache.createSet(context.getProcessInput(input)),
                        new ExpressionBuilder(f, init)
                            .assignFrom(Models.toLiteral(f, true))
                            .toStatement())));

        ResultMirror result = context.getOutput(output);
        context.addEnd(result.createAdd(cache.get()));
    }

    private Statement createAddSummarizeFor(
            Context context,
            Summarized.Folding folding,
            DataClass summarizing,
            Expression outputCache) {
        assert context != null;
        assert folding != null;
        assert summarizing != null;
        assert outputCache != null;
        Property property = summarizing.findProperty(folding.destination());
        Expression input = context.getProcessInput(context.getInputPort(Summarize.ID_INPUT));
        ModelFactory f = context.getModelFactory();
        // TODO for only DMDL
        switch (folding.aggregator()) {
        case MAX:
            return new ExpressionBuilder(f, property.createGetter(outputCache))
                .method("max", property.createGetter(input))
                .toStatement();
        case MIN:
            return new ExpressionBuilder(f, property.createGetter(outputCache))
                .method("min", property.createGetter(input))
                .toStatement();
        case SUM:
        case COUNT:
            return new ExpressionBuilder(f, property.createGetter(outputCache))
                .method("add", property.createGetter(input))
                .toStatement();
        default:
            throw new AssertionError();
        }
    }

    @Override
    public boolean isPartial(FlowElementDescription description) {
        Precondition.checkMustNotBeNull(description, "description"); //$NON-NLS-1$
        PartialAggregation partial = description.getAttribute(PartialAggregation.class);
        if (partial == PartialAggregation.PARTIAL) {
            return true;
        } else if (partial == PartialAggregation.TOTAL) {
            return false;
        }
        return getEnvironment().getOptions().isEnableCombiner();
    }

    static class Prologue extends LinePartProcessor {

        private final Type inputType;

        private final Type outputType;

        Prologue(Type inputType, Type outputType) {
            assert inputType != null;
            assert outputType != null;
            this.inputType = inputType;
            this.outputType = outputType;
        }

        @Override
        public void emitLinePart(Context context) {
            Summarized summarized = TypeUtil.erase(outputType).getAnnotation(Summarized.class);
            DataObjectMirror cache = context.createModelCache(outputType);
            DataClass inputData = getEnvironment().getDataClasses().load(inputType);
            DataClass outputData = getEnvironment().getDataClasses().load(outputType);
            for (Summarized.Folding folding : summarized.term().foldings()) {
                context.add(createStartSummarizeFor(context, folding, inputData, outputData, cache.get()));
            }
            context.setOutput(cache.get());
        }

        private Statement createStartSummarizeFor(
                Context context,
                Summarized.Folding folding,
                DataClass input,
                DataClass output,
                Expression outputCache) {
            Property source = input.findProperty(folding.source());
            Property destination = output.findProperty(folding.destination());
            ModelFactory f = context.getModelFactory();
            // TODO for only DMDL
            switch (folding.aggregator()) {
            case ANY:
                return destination.createSetter(
                        outputCache,
                        source.createGetter(context.getInput()));
            case MAX:
            case MIN:
            case SUM:
                return new ExpressionBuilder(f, destination.createGetter(outputCache))
                    .method("modify", new ExpressionBuilder(f, source.createGetter(context.getInput()))
                        .method("get")
                        .toExpression())
                    .toStatement();
            case COUNT:
                return new ExpressionBuilder(f, destination.createGetter(outputCache))
                    .method("modify", Models.toLiteral(f, 1L))
                    .toStatement();
            default:
                throw new AssertionError();
            }
        }
    }
}
TOP

Related Classes of com.asakusafw.compiler.flow.processor.SummarizeFlowProcessor$Prologue

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.