cloudlens.engine.CLBuilder.java Source code

Java tutorial

Introduction

Here is the source code for cloudlens.engine.CLBuilder.java

Source

/*
 *  This file is part of the CloudLens project.
 *
 * Copyright omitted for blind review
 *
 * 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 cloudlens.engine;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;

import cloudlens.block.BlockObject;
import cloudlens.parser.ASTAfter;
import cloudlens.parser.ASTBlock;
import cloudlens.parser.ASTDeclaration;
import cloudlens.parser.ASTElement;
import cloudlens.parser.ASTLens;
import cloudlens.parser.ASTMatch;
import cloudlens.parser.ASTProcess;
import cloudlens.parser.ASTRun;

public class CLBuilder {
    private static boolean blockGuard = false;
    private static List<CLElement> nextList = new ArrayList<>();
    private static List<PipelineStage> pipeline = new ArrayList<>();

    public static void reset() {
        blockGuard = false;
        nextList = new ArrayList<>();
        pipeline = new ArrayList<>();
    }

    private static String header(List<ASTElement> astElements) {
        String header = "";
        for (final ASTElement e : astElements) {
            switch (e.type) {
            case Declaration:
                header += "var " + ((ASTDeclaration) e).name + ";";
                break;
            case Lens:
                header += "var " + ((ASTLens) e).name + ";";
                break;
            default:
                break;
            }
        }
        return header;
    }

    public static String compileTop(List<ASTElement> astElements) {
        String code = header(astElements);
        code += "function (){ " + compile(astElements) + "}";
        return code;
    }

    public static String compile(List<ASTElement> astElements) {
        String code = "return [";
        String closing = "]";
        for (final ASTElement e : astElements) {
            switch (e.type) {
            case Declaration:
                final ASTDeclaration declSec = (ASTDeclaration) e;
                code += " function () {" + declSec.body + "; return [";
                closing = " ]}" + closing;
                break;
            case Lens:
                code += "function () {" + compile((ASTLens) e) + "; return [";
                closing = " ]}" + closing;
                break;
            case Run:
                final ASTRun runSec = (ASTRun) e;
                code += "function () { var run = " + runSec.name + ".closure(" + runSec.args + "); run.ast = "
                        + runSec.name + ".ast; return run},";
                break;
            case Block:
                final ASTBlock blockSec = (ASTBlock) e;
                code += " function () {" + blockSec.script + "; return [";
                closing = "]}" + closing;
                break;
            case Process:
                final ASTProcess processSec = (ASTProcess) e;
                code += processSec.script + ",";
                break;
            case After:
                final ASTAfter afterSec = (ASTAfter) e;
                code += afterSec.script + ",";
                break;
            case Match:
                final ASTMatch match = (ASTMatch) e;
                code += "function (){ return [" + StringUtils.join(match.rules, ',') + "]},";
                break;
            case Source:
                code += "{},";
                break;
            }
        }
        return code += closing;
    }

    public static String compile(ASTLens lens) {
        final List<String> logArgs = new ArrayList<>(lens.args);
        logArgs.add("log");
        final String funArgs = StringUtils.join(logArgs, ',');
        final String args = StringUtils.join(lens.args, ',');
        String code = "";
        code += lens.name + " = function(" + funArgs + "){return CL.run(" + lens.name + ", [" + args + "], log) };";
        code += lens.name + ".closure = function (";
        if (!lens.args.isEmpty()) {
            code += "jsArray){";
            for (int i = 0; i < lens.args.size(); i++) {
                code += "var " + lens.args.get(i) + " = jsArray[" + i + "];";
            }
        } else {
            code += "){";
        }
        code += header(lens.astElements);
        code += compile(lens.astElements) + "};";
        code += lens.name + ".ast = CLDEV__LENS__;";
        return code;
    }

    public static void spawn(CLElement element, List<ASTElement> astElements) {
        if (!astElements.isEmpty()) {
            final ASTElement e = astElements.get(0);
            final List<ASTElement> astTail = astElements.subList(1, astElements.size());
            switch (e.type) {
            case Declaration:
            case Block:
            case Lens:
                final CLElement dbl = new CLElement(e);
                element.children.add(dbl);
                spawn(dbl, astTail);
                break;
            case Process:
            case After:
            case Run:
            case Match:
            case Source:
                final CLElement srgmrs = new CLElement(e);
                element.children.add(srgmrs);
                spawn(element, astTail);
                break;
            }
        }
    }

    private static List<CLElement> getElements(List<CLElement> elements) {
        final List<CLElement> res = new ArrayList<>();
        int i = 0;
        while (i < elements.size() && !blockGuard) {
            final CLElement child = elements.get(i++);
            switch (child.ast.type) {
            case Block:
                res.add(child);
                blockGuard = true;
                break;
            case Process:
            case After:
            case Match:
            case Source:
                res.add(child);
                break;
            case Run:
                final CLElement run = child;
                final List<CLElement> runElements = getElements(run.children);
                res.addAll(runElements);
                break;
            case Declaration:
            case Lens:
                final CLElement dl = child;
                final List<CLElement> lensElements = getElements(dl.children);
                res.addAll(lensElements);
                break;
            }
        }
        nextList.addAll(elements.subList(i, elements.size()));
        return res;
    }

    private static List<CLElement> extractElements(List<CLElement> elements) {
        elements.addAll(nextList);
        nextList = new ArrayList<>();
        blockGuard = false;
        return getElements(elements);
    }

    private static void populate(CL cl, CLElement element, BlockObject closures) {
        for (int i = 0; i < closures.size(); i++) {
            final CLElement child = element.children.get(i);
            final BlockObject closure = closures.get(i);
            switch (child.ast.type) {
            case Block:
            case Process:
            case After:
            case Match:
            case Source:
                final CLElement bsgmrs = child;
                bsgmrs.closure = closure;
                break;
            case Declaration:
                final CLElement decl = child;
                decl.closure = closure;
                final BlockObject declClosures = closure.call();
                populate(cl, decl, declClosures);
                break;
            case Lens:
                final CLElement lens = child;
                lens.closure = closure;
                cl.engine.bind("CLDEV__LENS__", lens.lens());
                final BlockObject lensClosures = closure.call();
                populate(cl, lens, lensClosures);
                break;
            case Run:
                final CLElement run = child;
                run.closure = closure;
                final BlockObject runClosures = closure.call();
                final ASTLens runLens = (ASTLens) runClosures.get("ast").asAst();
                spawn(run, runLens.astElements);
                populate(cl, run, runClosures);
                break;
            }
        }
    }

    private static void addRuntimePipeline(List<RuntimeElement> runtimeElements) {
        if (!pipeline.isEmpty()) {
            runtimeElements.add(new RuntimePipeline(pipeline));
            pipeline = new ArrayList<>();
        }
    }

    public static List<RuntimeElement> build(CL cl, CLElement element, BlockObject closures) {
        populate(cl, element, closures);
        final List<RuntimeElement> runtimes = new ArrayList<>();
        final List<CLElement> elements = extractElements(element.children);
        for (final CLElement child : elements) {
            switch (child.ast.type) {
            case Block:
                addRuntimePipeline(runtimes);
                final RuntimeBlock block = new RuntimeBlock(child);
                runtimes.add(block);
                break;
            case Source:
                addRuntimePipeline(runtimes);
                final RuntimeSource source = new RuntimeSource(child);
                runtimes.add(source);
                break;
            case Process:
                final PipelineStage process = new PipelineStageProcess(child);
                pipeline.add(process);
                break;
            case After:
                final PipelineStage after = new PipelineStageAfter(child);
                pipeline.add(after);
                break;
            case Match:
                final PipelineStage match = new PipelineStageMatch(child);
                pipeline.add(match);
                break;
            case Declaration:
            case Lens:
            case Run:
                throw new CLException("Runtime Error!");

            }
        }
        addRuntimePipeline(runtimes);
        return runtimes;
    }

}