package hirondelle.movies.edit;
import java.util.*;
import java.io.*;
import java.util.regex.Pattern;
import java.util.logging.Logger;
import hirondelle.movies.util.Util;
import java.math.BigDecimal;
import hirondelle.movies.exception.InvalidInputException;
import hirondelle.movies.main.MainWindow;
public final class MovieDAO {
public void shutdown() {
fLogger.fine("Saving all miovie records to file.");
String fileContents = buildFileContents();
writeStringToFile(fileContents);
}
void add(Movie aMovie) {
String id = nextId();
aMovie.setId(id.toString());
fTable.put(id, aMovie);
}
void change(Movie aMovie) {
fTable.put(aMovie.getId(), aMovie);
}
List<Movie> list() {
List<Movie> result = new ArrayList<Movie>(fTable.values());
Collections.sort(result);
return result;
}
void delete(String aMovieId) {
fTable.remove(aMovieId);
}
private static final Map<String, Movie> fTable = new LinkedHashMap<String, Movie>();
private static int fNextId = 0;
private static final String MOVIES_FILE_NAME = "movie_list_for_";
private static final String ENCODING = "UTF-8";
private static final String DELIMITER = "|";
private static final String NULL = "NULL";
private static final Logger fLogger = Util.getLogger(MovieDAO.class);
static {
readInMovieFileUponStartup();
fLogger.config("Number of movies read in from file: " + fTable.size());
}
private static void readInMovieFileUponStartup() {
File file = new File(getMovieFileName());
fLogger.fine("Reading movies from file :" + file.getAbsolutePath());
String line = "";
Scanner scanner = null;
try {
scanner = new Scanner(file);
while (scanner.hasNextLine()) {
line = scanner.nextLine();
if (Util.textHasContent(line)) {
parseLine(line);
}
}
}
catch (FileNotFoundException ex) {
fLogger.config("Movies file not present. Will be created when the app closes.");
}
catch (InvalidInputException ex) {
fLogger.severe("Movies file: date-viewed field not in expected format: " + line);
}
catch (InputMismatchException ex) {
fLogger.severe("Movies file: Not in expected format: " + line);
}
catch (NoSuchElementException ex) {
fLogger.severe("Movies file: Not in expected format: " + line);
}
finally {
if (scanner != null) scanner.close();
}
}
private static void parseLine(String aLine) throws InvalidInputException {
Scanner scanner = new Scanner(aLine);
scanner.useDelimiter(Pattern.quote(DELIMITER));
scanner.useLocale(Locale.US);
if (scanner.hasNext()) {
String title = scanner.next();
Date viewed = Util.parseDate(maybeNull(scanner.next()), "Date Viewed");
BigDecimal rating = Util.parseBigDecimal(maybeNull(scanner.next()), "Rating");
String comment = maybeNull(scanner.next());
Movie movie = new Movie(nextId().toString(), title, viewed, rating, comment);
fTable.put(movie.getId(), movie);
}
scanner.close();
}
private static String nextId() {
++fNextId;
return String.valueOf(fNextId);
}
private void appendTo(StringBuilder aText, Object aField, String aAppend) {
if (Util.textHasContent(Util.format(aField))) {
aText.append(Util.format(aField));
}
else {
aText.append(NULL);
}
aText.append(aAppend);
}
private static String maybeNull(String aText) {
return NULL.equals(aText) ? null : aText;
}
private static String getMovieFileName() {
return MOVIES_FILE_NAME + MainWindow.getInstance().getUserName().toLowerCase(Locale.ENGLISH) + ".txt";
}
private String buildFileContents() {
String NEW_LINE = System.getProperty("line.separator");
StringBuilder result = new StringBuilder();
for (Movie movie : fTable.values()) {
appendTo(result, movie.getTitle(), DELIMITER);
appendTo(result, movie.getDateViewed(), DELIMITER);
appendTo(result, movie.getRating(), DELIMITER);
appendTo(result, movie.getComment(), NEW_LINE);
}
return result.toString();
}
private void writeStringToFile(String aFileContents) {
Writer output = null;
try {
FileOutputStream fos = new FileOutputStream(getMovieFileName());
OutputStreamWriter out = new OutputStreamWriter(fos, ENCODING);
output = new BufferedWriter(out);
output.write(aFileContents);
}
catch (FileNotFoundException ex) {
fLogger.severe("Cannot find movies.txt file.");
}
catch (UnsupportedEncodingException ex) {
fLogger.severe("System does not support UTF-8 encoding.");
}
catch (IOException ex) {
fLogger.severe("Problem while saving movies.txt file.");
}
finally {
if (output != null) {
try {
output.close();
}
catch (IOException ex) {
fLogger.severe("Cannot close stream.");
}
}
}
}
}