Java tutorial
/* * 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; } }