package apes.models;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import apes.views.ApesError;
/**
* Generic class for classes that works against a configuration file.
*
* @author Johan Andersson (johandy@student.chalmers.se)
*/
public abstract class ApesConfiguration
{
/**
* The configuration file.
*/
private File configurationFile;
/**
* The default regex to use when parsing the configuration file.
*/
private String regex = "^([a-z_]+)\\s*=\\s*([\"]?)(.*)\\2$";
/**
* The map that contains all options.
*/
protected Map<String, String> options;
public ApesConfiguration()
{
options = new TreeMap<String, String>();
String configurationFolderPath = System.getProperty("user.home") + File.separator + ".apes";
String configurationFileName = getConfigurationFileName();
// Make sure folders and files exists.
String validPath = getConfigurationFolderPath(configurationFolderPath);
String validFile = getConfigurationFileName(validPath, configurationFileName);
configurationFile = new File(validFile);
}
/**
* Creates the configuration folder if it does not exists already.
*
* @param configurationFolderPath Path to the configuration folder.
* @return The absolute path to the configuration folder.
*/
private String getConfigurationFolderPath(String configurationFolderPath)
{
File directory = new File(configurationFolderPath);
// Create folder if it does not exist.
if(!directory.isDirectory())
{
directory.mkdir();
}
return directory.getAbsolutePath();
}
/**
* Creates the configuration file if it does not exists already.
*
* @param configurationFolderPath The absolute path to the configuration
* folder.
* @param configurationFileName The name of the configuration file.
* @return The absolute path to the configuration file.
*/
public String getConfigurationFileName(String configurationFolderPath, String configurationFileName)
{
File file = new File(configurationFolderPath, configurationFileName);
// Create file if it does not exist.
if(!file.exists())
{
try
{
file.createNewFile();
}
catch(IOException e)
{
ApesError.couldNotCreateConfigurationFile();
}
}
return file.getAbsolutePath();
}
/**
* Parses the configuration file.
*/
public void parse()
{
try
{
Scanner scanner = new Scanner(configurationFile);
Pattern pattern = Pattern.compile(regex);
Matcher matcher;
String line;
// Go through all lines in configuration file.
while(scanner.hasNextLine())
{
line = scanner.nextLine();
matcher = pattern.matcher(line);
// If line matches an option.
if(matcher.matches())
{
// Call match in subclass.
match(line, matcher);
}
}
scanner.close();
}
catch(FileNotFoundException e)
{
e.printStackTrace();
}
}
/**
* Save the configuration file.
*/
public void save()
{
try
{
// Read in the whole file. This must be done because a file can
// not be written to while read from.
// NOTE: This can be done with RandomAccessFile
List<String> lines = new ArrayList<String>();
Scanner scanner = new Scanner(configurationFile);
while(scanner.hasNextLine())
{
lines.add(scanner.nextLine());
}
scanner.close();
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(configurationFile)));
Set<String> added = new HashSet<String>();
Pattern pattern = Pattern.compile(regex);
Matcher matcher;
String key;
for(String line : lines)
{
matcher = pattern.matcher(line);
if(matcher.matches())
{
key = matcher.group(1);
out.write(toOption(key));
added.add(key);
}
else
{
out.write(line);
}
out.println();
}
// Add options that where not in the file already.
for(String option : options.keySet())
{
if(!added.contains(option))
{
out.write(toOption(option));
out.println();
}
}
out.close();
}
catch(FileNotFoundException e)
{
e.printStackTrace();
}
catch(IOException e)
{
e.printStackTrace();
}
}
/**
* Returns a string of an option.
*
* @param key The key option.
* @return The option as a string (key = value).
*/
private String toOption(String key)
{
return key + " = " + options.get(key);
}
/**
* Sets the regexp to use when parsing.
*
* @param regex The regex.
*/
public void setRegex(String regex)
{
this.regex = regex;
}
/**
* Returns all options.
*
* @return All options.
*/
public Map<String, String> getOptions()
{
return options;
}
/**
* Sets the options.
*
* @param options The options.
*/
public void setOptions(Map<String, String> options)
{
this.options = options;
}
/**
* When parsing the file and a match is found, this method is called. If the
* regex has been changed, it is most likely that this method should be
* overridden in the subclass.
*
* @param line The line that matches.
* @param matcher The matcher.
*/
public void match(String line, Matcher matcher)
{
options.put(matcher.group(1), matcher.group(3));
}
/**
* Returns the configuration file name.
*
* @return The file name.
*/
public abstract String getConfigurationFileName();
}