package edu.kit.pse.ws2013.routekit.controllers;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import edu.kit.pse.ws2013.routekit.models.ProfileMapCombination;
import edu.kit.pse.ws2013.routekit.profiles.Profile;
import edu.kit.pse.ws2013.routekit.util.FileUtil;
/**
* Manages the profiles and saves/loads them to/from disk.
*/
public class ProfileManager {
private static ProfileManager instance;
private final File root;
private final Map<Profile, File> profiles;
private final Map<String, Profile> profilesByName;
private ProfileManager(File root) throws FileNotFoundException, IOException {
this.root = root;
this.profiles = new HashMap<>();
this.profilesByName = new HashMap<>();
for (File f : root.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".profile");
}
})) {
addProfile(Profile.load(f), f);
}
addProfile(Profile.defaultCar, null);
addProfile(Profile.defaultTruck, null);
}
private void addProfile(Profile p, File f) {
profiles.put(p, f);
profilesByName.put(p.getName(), p);
}
private void removeProfile(Profile p) {
profiles.remove(p);
profilesByName.remove(p.getName());
}
/**
* Deletes all precalculations ({@link ProfileMapCombination
* ProfileMapCombinations} in the {@link ProfileMapManager}) with the same
* profile name as {@code profile}.
*/
private void deletePrecalculations(Profile profile) {
final String name = profile.getName();
for (ProfileMapCombination precalculation : new HashSet<>(
ProfileMapManager.getInstance().getPrecalculations())) {
if (name.equals(precalculation.getProfile().getName())) {
ProfileMapManager.getInstance().deletePrecalculation(
precalculation);
}
}
}
/**
* Removes the given profile from the internal list,
* {@link ProfileMapManager#deletePrecalculation(ProfileMapCombination)
* deletes} all its precalculations and deletes it from disk.
*
* @param profile
* The profile that shall be deleted.
*/
public void deleteProfile(Profile profile) {
if (profile.isDefault()) {
throw new IllegalArgumentException(
"Can’t delete a default profile!");
}
if (!profiles.containsKey(profile)) {
return;
}
profiles.get(profile).delete();
deletePrecalculations(profile);
removeProfile(profile);
ProfileMapManager.getInstance().checkIfCurrentStillExists();
try {
ProfileMapManager.getInstance().rewriteIndex();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Adds the given profile to the internal list and saves it on disk. Any
* existing precalculations for a profile of the same name are deleted.
*
* @param profile
* The profile that shall be saved.
* @throws IOException
* @throws IllegalArgumentException
* If the profile name is {@link #checkProfileName(String)
* invalid} or if the profile is a {@link Profile#isDefault()
* default} profile.
*/
public void saveProfile(Profile profile) throws IOException {
if (profile.isDefault()) {
throw new IllegalArgumentException("Can’t save a default profile!");
}
Profile existing = profilesByName.get(profile.getName());
if (existing == null) {
if (!checkProfileName(profile.getName())) {
throw new IllegalArgumentException("Invalid profile name!");
}
} else {
if (existing.equals(profile)) {
return;
}
deleteProfile(existing);
}
File f = profiles.get(existing);
if (f == null) {
f = new File(root, profile.getName() + ".profile");
f.createNewFile();
}
profile.save(f);
addProfile(profile, f);
}
/**
* Returns all profiles in the internal list.
*
* @return All profiles.
*/
public Set<Profile> getProfiles() {
return profiles.keySet();
}
/**
* Returns {@code true} iff the given name is a valid name for a new
* profile.
*
* @param name
* The profile name.
* @return {@code true} if {@code name} can be used as the name of a new
* profile, {@code false} otherwise.
* @see FileUtil#checkProfileName(String)
*/
public boolean checkProfileName(String name) {
if (!FileUtil.checkProfileName(name)) {
return false;
}
for (String s : profilesByName.keySet()) {
if (name.equalsIgnoreCase(s)) {
return false;
}
}
return true;
}
/**
* Initializes the {@link ProfileManager}.
*
* @param rootDirectory
* The directory that contains all profiles.
*
* @throws IllegalStateException
* If the ProfileManager is already initialized.
*/
public static void init(File rootDirectory) throws IOException {
if (instance != null) {
throw new IllegalStateException("Already initialized!");
}
instance = new ProfileManager(rootDirectory);
}
/**
* Returns the {@link ProfileManager} instance. This is only allowed if the
* ProfileManager was previously {@link #init(File) initialized}.
*
* @return The ProfileManager instance.
* @throws IllegalStateException
* If the ProfileManager is uninitialized.
*/
public static ProfileManager getInstance() {
if (instance == null) {
throw new IllegalStateException("Not yet initialized!");
}
return instance;
}
}