package edu.kit.pse.ws2013.routekit.controllers;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import edu.kit.pse.ws2013.routekit.map.StreetMap;
import edu.kit.pse.ws2013.routekit.models.ProfileMapCombination;
import edu.kit.pse.ws2013.routekit.models.ProgressListener;
import edu.kit.pse.ws2013.routekit.models.ProgressReporter;
import edu.kit.pse.ws2013.routekit.profiles.Profile;
import edu.kit.pse.ws2013.routekit.util.DummyProgressReporter;
import edu.kit.pse.ws2013.routekit.util.FileUtil;
/**
* Is the user interface and {@link ProgressListener} for command line
* interaction.
*/
public class CLI implements ProgressListener, Runnable {
protected ManagementActions actions;
public CLI(String[] args) {
try {
final MapManager mapManager;
final ProfileManager profileManager;
final ProfileMapManager profileMapManager;
if (args.length == 0) {
actions = ManagementActions.noActions;
return;
} else if (args.length == 1
&& (args[0].equals("-h") || args[0].equals("--help")
|| args[0].equals("--usage") || args[0]
.equals("--version"))) {
// these options don’t need the ProfileMapManager, skip init
mapManager = null;
profileManager = null;
profileMapManager = null;
} else {
try {
ProfileMapManager.init(FileUtil.getRootDir(),
new DummyProgressReporter());
mapManager = MapManager.getInstance();
profileManager = ProfileManager.getInstance();
profileMapManager = ProfileMapManager.getInstance();
} catch (IOException e) {
e.printStackTrace();
actions = ManagementActions.noActions;
return;
}
}
final Set<FutureMap> newOrUpdatedMaps = new HashSet<>();
final Set<StreetMap> deletedMaps = new HashSet<>();
final Set<ProfileMapCombination> deletedPrecalculations = new HashSet<>();
final Set<ProfileMapCombination> newPrecalculations = new HashSet<>();
for (int i = 0; i < args.length; i++) {
final String arg = args[i];
switch (arg) {
case "-h":
case "--help":
case "--usage":
case "--version": {
if (arg.equalsIgnoreCase("--version")) {
System.out.println("routeKIT version 1.0.0");
} else {
for (String line : new String[] {
"routeKIT: Programm zur Routenplanung und -berechnung.",
"",
"Optionen:",
"",
" --help",
" --usage",
" Gibt diesen Hilfetext aus.",
" --version",
" Gibt die Version von routeKIT aus.",
" --import <Name> <Datei>",
" --import-map <Name> <Datei>",
" Importiert eine Karte aus einer OSM-Datei.",
" --update <Name> <Datei>",
" --update-map <Name> <Datei>",
" Aktualisiert eine Karte aus einer OSM-Datei.",
" --delete-map <Name>",
" Löscht eine Karte.",
" --select <Kartenname> <Profilname>",
" Wählt eine Kombination aus.",
" --delete-precalculation <Kartenname> <Profilname>",
" Löscht eine Vorberechnung.",
" --precalculate <Kartenname> <Profilname>",
" Führt eine Vorberechnung durch.", "",
"Dieses Programm ist nicht aptitude." }) {
System.out.println(line);
}
}
actions = ManagementActions.noActions;
return;
}
case "--import":
case "--import-map":
case "--update":
case "--update-map": {
checkOptionCount(args, i, arg, 2);
String name = args[++i];
String file = args[++i];
if (!FileUtil.checkMapName(name)) {
System.err.println("Ungültiger Kartenname: " + name);
actions = ManagementActions.noActions;
throw new Error();
}
StreetMap existingMap = findMap(mapManager, name,
arg.startsWith("--update"));
if (arg.startsWith("--import") && existingMap != null) {
System.err.println("Kartenname bereits vergeben: "
+ name);
actions = ManagementActions.noActions;
throw new Error();
}
newOrUpdatedMaps.add(new FutureMap(name, new File(file)));
break;
}
case "--select": {
checkOptionCount(args, i, arg, 2);
String mapName = args[++i];
String profileName = args[++i];
StreetMap map = findMap(mapManager, mapName, true);
Profile profile = findProfile(profileManager, profileName);
ProfileMapManager.getInstance().selectProfileAndMap(
profile, map);
break;
}
case "--delete-map": {
checkOptionCount(args, i, arg, 1);
String name = args[++i];
StreetMap deletedMap = null;
deletedMap = findMap(mapManager, name, true);
deletedMaps.add(deletedMap);
break;
}
case "--delete-precalculation": {
checkOptionCount(args, i, arg, 2);
String mapName = args[++i];
String profileName = args[++i];
StreetMap map = findMap(mapManager, mapName, true);
Profile profile = findProfile(profileManager, profileName);
ProfileMapCombination combination = profileMapManager
.getPrecalculation(profile, map);
if (combination == null) {
System.err
.println("Keine Vorberechnung für diese Kombination: "
+ mapName + " + " + profileName);
actions = ManagementActions.noActions;
throw new Error();
}
deletedPrecalculations.add(combination);
break;
}
case "--precalculate": {
checkOptionCount(args, i, arg, 2);
String mapName = args[++i];
String profileName = args[++i];
StreetMap map = findMap(mapManager, mapName, true);
Profile profile = findProfile(profileManager, profileName);
ProfileMapCombination combination = profileMapManager
.getPrecalculation(profile, map);
if (combination != null) {
deletedPrecalculations.add(combination);
}
newPrecalculations.add(new ProfileMapCombination(map,
profile));
break;
}
}
}
actions = new ManagementActions(newOrUpdatedMaps, deletedMaps,
deletedPrecalculations, newPrecalculations);
} catch (Error r) {
// No-op, syntax error
}
}
private void checkOptionCount(String[] args, int i, final String arg,
int needed) throws Error {
if (args.length <= i + needed) {
System.err.println("Nicht genug Argumente für Option " + arg + "!");
actions = ManagementActions.noActions;
throw new Error();
}
}
private Profile findProfile(final ProfileManager profileManager,
String profileName) throws Error {
Profile profile = null;
for (Profile existingProfile : profileManager.getProfiles()) {
if (existingProfile.getName().equalsIgnoreCase(profileName)) {
profile = existingProfile;
break;
}
}
if (profile == null) {
System.err.println("Kein Profil mit diesem Namen: " + profileName);
actions = ManagementActions.noActions;
throw new Error();
}
return profile;
}
private StreetMap findMap(final MapManager mapManager, String mapName,
boolean require) throws Error {
StreetMap map = null;
for (StreetMap existingMap : mapManager.getMaps()) {
if (existingMap.getName().equalsIgnoreCase(mapName)) {
map = existingMap;
break;
}
}
if (map == null && require) {
System.err.println("Keine Karte mit diesem Namen: " + mapName);
actions = ManagementActions.noActions;
throw new Error();
}
return map;
}
@Override
public void run() {
if (actions != ManagementActions.noActions) {
actions.execute(null, new ProgressReporter(this,
"Führe Änderungen aus"));
}
}
@Override
public void startRoot(String name) {
}
@Override
public void beginTask(String name) {
System.out.println(name);
}
float last = -1;
@Override
public void progress(float progress, String name) {
if (progress - last > 0.001f) {
System.out.println(Math.floor(progress * 1000) / 10f + ": " + name);
last = progress;
}
}
@Override
public void endTask(String name) {
}
@Override
public void finishRoot(String name) {
}
}