package com.elsealabs.xshot.file;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import com.elsea.stone.property.PropertyPool;
import com.elsea.stone.property.PropertyPoolReader;
import com.elsea.stone.property.PropertyPoolWriter;
/**
* FileSystem
*
* Holds information about locations of important directories and
* files relevant to the program. It also holds helper methods for
* directory and file repair and first time setup.
*
* @author Connor M. Elsea
*/
public class FileSystem {
public static enum OS
{
WINDOWS, OSX, LINUX
}
private OS osType;
private String osName;
private String userPath;
/**
* The paths that can be returned by this class' accessor methods
* are bound by the PATH enumeration to eliminate the use of magic
* String for retrieving paths from the hash map.
*/
public static enum PATH
{
PROGRAM_DIR,
STONE_FILE,
SAVE_DEFAULT_DIR
}
private HashMap<String, File> files;
private File location_programDir;
private File location_stoneFile;
private File location_saveDefaultDir;
/**
* When a file system check is performed, issues that are found
* are added to the array list of issues. The type of the issues
* are bound by the ISSUE enumeration.
*/
public static enum ISSUE
{
MISSING_PROGRAM_DIR,
MISSING_SAVE_DIR,
MISSING_STONE,
MALFORMED_STONE
}
private ArrayList<ISSUE> issues;
/**
* Various data held by the File System object.
*/
private PropertyPool pool;
/**
* Runs all the needed methods for starting up the program and
* loading the initial data.
*/
public void run()
{
loadPaths();
check();
fix();
}
/**
* Checks for various problems and if they are present, their
* corresponding issue to the arrray list. Loads in Stone data
* if it is present and not malformed.
*/
public void check()
{
System.out.println("File System: Checking for issues.");
if (issues == null) issues = new ArrayList<ISSUE>();
else issues.clear();
if (!getPath(PATH.PROGRAM_DIR).exists())
{
issues.add(ISSUE.MISSING_PROGRAM_DIR);
}
if (!getPath(PATH.SAVE_DEFAULT_DIR).exists())
{
issues.add(ISSUE.MISSING_SAVE_DIR);
}
if (!getPath(PATH.STONE_FILE).exists())
{
issues.add(ISSUE.MISSING_STONE);
}
else
{
PropertyPoolReader reader = new PropertyPoolReader();
// reader.read(...) returns a boolean indicating whether or not the reader
// read in the data correctly. If the data was read in corerctly, set the
// read in pool as a member of the File System class. If not, add the
// malformed stone issue to the issue array list.
if (reader.read(getPath(PATH.STONE_FILE)))
{
pool = reader.getPropertyPool();
if (pool.search().getGroup("locations") == null)
{
issues.add(ISSUE.MISSING_STONE);
}
}
else
{
issues.add(ISSUE.MALFORMED_STONE);
}
}
}
/**
* Fixes errors if they are present.
*/
public void fix()
{
System.out.println("File System: Attempting to fix any issues");
if (!issues.isEmpty())
{
if (issues.contains(ISSUE.MISSING_PROGRAM_DIR))
{
fix_MissingProgramDir();
}
if (issues.contains(ISSUE.MISSING_SAVE_DIR))
{
fix_MissingSaveDir();
}
if (issues.contains(ISSUE.MISSING_STONE))
{
fix_MissingStone();
}
if (issues.contains(ISSUE.MALFORMED_STONE))
{
fix_MalformedStone();
}
issues.clear();
}
}
public void fix_MissingProgramDir()
{
System.out.println("Resolve: Attempting to fix missing program directory.");
try
{
Files.createDirectories(getPath(PATH.PROGRAM_DIR).toPath());
}
catch (IOException e)
{
e.printStackTrace();
}
}
public void fix_MissingSaveDir()
{
System.out.println("Resolve: Attempting to fix missing save directory.");
// TODO: Ask user for new save directory.
System.err.println("Error: Missing Save Directory. Cannot fix in current build.");
}
public void fix_MissingStone()
{
System.out.println("Resolve: Attempting to fix missing Stone file.");
// Get default path generated by File System and put it into
// the Stone template. They can change it in the future, but
// this is just setting up defaults.
String defaultSave = getPath(FileSystem.PATH.SAVE_DEFAULT_DIR).getAbsolutePath();
// Create the Property Pool and fill it with the defaults.
pool = new PropertyPool();
pool
.group("file")
.group("locations")
.group("location")
.property("name", "Pictures")
.property("path", defaultSave)
.property("default", "true")
.end()
.end()
.end()
.group("actions")
.property("autoCopy", "true")
.end()
;
// Write the Property Pool to the file system
PropertyPoolWriter writer = new PropertyPoolWriter();
if (writer.write(pool, getPath(PATH.STONE_FILE)))
{
System.out.println("Resolve: Wrote Stone file correctly");
}
else
{
System.err.println("Fatal Error: Failed to write Stone file.");
}
}
public void fix_MalformedStone()
{
System.out.println("Resolve: Attempting to fix malformed stone file.");
System.err.println("Errror: Cannot fix malformed stone file.");
}
/**
* Determine the operating system and generate the paths needed by this
* program, some of which differ between each operating system.
*/
public void loadPaths()
{
System.out.println("File System: Determining paths.");
files = new HashMap<String, File>();
osName = System.getProperty("os.name").toLowerCase();
userPath = System.getProperty("user.home");
if (osName.contains("windows"))
{
osType = OS.WINDOWS;
location_programDir = new File(System.getenv("APPDATA") + "\\Capshot");
location_saveDefaultDir = new File(userPath + "\\Pictures");
location_stoneFile = new File(System.getenv("APPDATA") + "\\Capshot\\stone.xml");
}
else if (osName.contains("mac"))
{
osType = OS.OSX;
location_programDir = new File(getUserPath() + "/Library/Application Support/Capshot");
}
else if (osName.contains("nix") || osName.contains("nux"))
{
osType = OS.LINUX;
location_programDir = new File(getUserPath() + "/Capshot");
}
else
{
osType = OS.WINDOWS;
System.err.println("Error: Could not determine OS from os.name = \"" + osName + "\"");
System.err.println("Warning: Defaulting OS to WINDOWS.");
}
System.out.println("File System: Program directory " + location_programDir.getAbsolutePath());
location_stoneFile = new File(location_programDir.getAbsolutePath() + "\\settings.xml");
}
/**
* Return the File object for the specified pre-defined location
*
* @param path The pre-defined location
* @return The file object for the specified pre-defined location
*/
public File getPath(PATH path)
{
switch (path)
{
case PROGRAM_DIR:
return location_programDir;
case STONE_FILE:
return location_stoneFile;
case SAVE_DEFAULT_DIR:
return location_saveDefaultDir;
default:
throw new IllegalArgumentException();
}
}
public OS getOsType() {
return osType;
}
public String getOsName() {
return osName;
}
public String getUserPath() {
return userPath;
}
}