me.lukasczyk.busybox_preprocessor.core.Algorithm.java Source code

Java tutorial

Introduction

Here is the source code for me.lukasczyk.busybox_preprocessor.core.Algorithm.java

Source

/*
 * Copyright 2016 Stephan Lukasczyk
 *
 * 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 me.lukasczyk.busybox_preprocessor.core;

import com.google.common.base.Preconditions;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Multimap;

import me.lukasczyk.busybox_preprocessor.parser.XMLInterfaceParser;

import org.sosy_lab.common.ShutdownNotifier;
import org.sosy_lab.common.log.LogManager;
import org.xml.sax.SAXException;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.stream.Stream;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathExpressionException;

/** The main algorithm that runs the copying of the files. */
public class Algorithm {

    private final ShutdownNotifier shutdownNotifier;
    private final LogManager logManager;
    private final CommandLineArguments commandLineArguments;
    private final List<XMLInterfaceParser> interfaceParsers;

    /**
     * Create a new algorithm object.
     *
     * @param pShutdownNotifier A notifier for shutdown requests.
     * @param pLogManager The core logging manager of the project.
     * @param pCommandLineArguments The given command line arguments.
     */
    public Algorithm(final ShutdownNotifier pShutdownNotifier, final LogManager pLogManager,
            final CommandLineArguments pCommandLineArguments) {
        shutdownNotifier = pShutdownNotifier;
        logManager = pLogManager;
        checkCommandLineArguments(pCommandLineArguments);
        commandLineArguments = pCommandLineArguments;
        interfaceParsers = new ArrayList<>();
    }

    /**
     * Runs the algorithm.
     *
     * @throws InterruptedException In case of interruption by shutdown notifier
     */
    public void run() throws InterruptedException {
        final Path busyBoxFileList = Paths.get(commandLineArguments.getArgumentValue("rootPath"))
                .resolve(commandLineArguments.getArgumentValue("busyboxFileList"));

        try (Stream<String> lines = Files.lines(busyBoxFileList)) {
            for (String line : (Iterable<String>) lines::iterator) {
                shutdownNotifier.shutdownIfNecessary();
                interfaceParsers.add(XMLInterfaceParser.create(commandLineArguments.getArgumentValue("rootPath"),
                        commandLineArguments.getArgumentValue("busyboxFiles"), line));
            }
        } catch (IOException | SAXException | ParserConfigurationException | XPathExpressionException pE) {
            logManager.log(Level.WARNING, pE.getLocalizedMessage());
        }

        final Multimap<String, String> neededFilesPerFile = getNeededFilesPerFile();

        for (String destinationFileName : neededFilesPerFile.keySet()) {
            try (FileWriter fw = new FileWriter(Paths.get(commandLineArguments.getArgumentValue("rootPath"))
                    .resolve(commandLineArguments.getArgumentValue("busyboxFiles"))
                    .resolve(destinationFileName + ".include.info").toFile(), true);
                    BufferedWriter bw = new BufferedWriter(fw);
                    PrintWriter destination = new PrintWriter(bw)) {
                for (String sourceFileName : neededFilesPerFile.get(destinationFileName)) {
                    if (sourceFileName.equals("")) {
                        continue;
                    }

                    destination.println(sourceFileName);
                }
                logManager.log(Level.INFO, "Copied library functions to " + destinationFileName);
            } catch (IOException pE) {
                logManager.log(Level.WARNING, pE.getLocalizedMessage());
            }
        }
    }

    private void checkCommandLineArguments(final CommandLineArguments pCommandLineArguments) {
        Preconditions.checkArgument(pCommandLineArguments.containsKey("rootPath"));
        Preconditions.checkArgument(pCommandLineArguments.containsKey("busyboxFiles"));
        Preconditions.checkArgument(pCommandLineArguments.containsKey("busyboxFileList"));
    }

    /**
     * Returns a map of exported functions
     *
     * @return Map [function name -> file name]
     * @throws InterruptedException In case of interruption by shutdown notifier
     */
    private Map<String, String> getExportedFunctions() throws InterruptedException {
        final Map<String, String> output = new LinkedHashMap<>();

        for (XMLInterfaceParser parser : interfaceParsers) {
            shutdownNotifier.shutdownIfNecessary();
            parser.getOutputFunctions().stream().filter(function -> !function.getFunctionName().endsWith("main"))
                    .forEach(function -> output.put(function.getFunctionName(), parser.getFileName()));
        }

        return output;
    }

    /**
     * Returns a multi map of imported functions
     *
     * @return Multi map [file name -> function name]
     * @throws InterruptedException In case of interruption by shutdown notifier
     */
    private Multimap<String, String> getImportedFunctions() throws InterruptedException {
        final Multimap<String, String> output = LinkedListMultimap.create();

        for (XMLInterfaceParser parser : interfaceParsers) {
            shutdownNotifier.shutdownIfNecessary();
            parser.getInputFunctions()
                    .forEach(function -> output.put(parser.getFileName(), function.getFunctionName()));
        }

        return output;
    }

    /**
     * Returns a multi map of needed files per file
     *
     * @return Multi map [file needs files]
     * @throws InterruptedException In case of interruption by shutdown notifier
     */
    private Multimap<String, String> getNeededFilesPerFile() throws InterruptedException {
        final Map<String, String> exportedFunctions = getExportedFunctions();
        final Multimap<String, String> importedFunctions = getImportedFunctions();
        final Multimap<String, String> neededFilesPerFile = LinkedListMultimap.create();

        for (XMLInterfaceParser parser : interfaceParsers) {
            if (parser.getFileName().contains("lib")) {
                continue;
            }
            shutdownNotifier.shutdownIfNecessary();
            final Deque<String> waitList = new LinkedList<>();
            waitList.addAll(importedFunctions.get(parser.getFileName()));
            final List<String> visited = new LinkedList<>();
            final Set<String> fileNames = new LinkedHashSet<>();

            while (!waitList.isEmpty()) {
                final String function = waitList.poll();

                if (visited.contains(function)) {
                    continue;
                }

                visited.add(function);

                if (!exportedFunctions.containsKey(function)) {
                    continue;
                }

                final String fileName = exportedFunctions.get(function);

                if (!importedFunctions.containsKey(fileName)) {
                    continue;
                }

                shutdownNotifier.shutdownIfNecessary();

                fileNames.add(fileName);
                waitList.addAll(importedFunctions.get(fileName));
            }
            if (fileNames.size() > 0) {
                neededFilesPerFile.putAll(parser.getFileName(), fileNames);
            } else {
                neededFilesPerFile.put(parser.getFileName(), "");
            }
        }

        return neededFilesPerFile;
    }
}