OpenDataPhillyFinal / src / edu / upenn / cit594 / Main.java
Main.java
Raw
package edu.upenn.cit594;
import java.util.HashSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import edu.upenn.cit594.datamanagement.CovidReader;
import edu.upenn.cit594.datamanagement.PopulationsReader;
import edu.upenn.cit594.datamanagement.PropertiesReader;
import edu.upenn.cit594.logging.Logger;
import edu.upenn.cit594.processor.Processor;
import edu.upenn.cit594.ui.UserInterface;


public class Main {

    public static void main(String[] args) {
    	
    	//check invalid runtime args
    	int argsLength = args.length;
    	if (argsLength > 4 || argsLength < 0) {
    		System.out.println("Error in number of runtime arguments.");
    		return;
    	}
    	
    	//check invalid file formats ("--name=value”)
    	if (isValidFormat(args) == false) {
    		return;
    	}
		
		//Make an String[] Array of argsName (Ex: population, events, covid, properties, etc.)
		String[] argsNames = new String[argsLength];
		for (int i=0; i<argsLength; i++) {
			argsNames[i] = getFileName(args[i]);
		}	
    	
		//Initialize & set indexes
    	int covidIndex = -1;
    	int propertiesIndex = -1;
    	int populationIndex = -1;
    	int logIndex = -1;

		//Get the indexes for the arg names
    	for (int i = 0; i<argsNames.length; i++) {
    		if (argsNames[i].equals("population")) {
    			populationIndex = i;
    		} else if (argsNames[i].equals("log")) {
    			logIndex = i;
    		} else if (argsNames[i].equals("covid")) {
    			covidIndex = i;
    		} else if (argsNames[i].equals("properties")) {
    			propertiesIndex = i;
    		}
    	}
    	
    	//To log the command line arguments to the program (a single entry, with a space between each argument)
    	//formats the args for logging
    	String argsString = args[0];
    	for (int i=1; i < args.length; i++) {
    		argsString = argsString + " " + args[i] + " ";
    	}
    	
    	//store args into local variables if they exist
    	//get file value out of args (ex: population.csv, events.log, covid.json, properties.csv)
    	String populationFile = null;
		String logFile = null;
		String covidFile = null;
    	String propertiesFile = null;
    	
    	if (populationIndex != -1) {
    		populationFile = getFileValue(args[populationIndex]);
    	}
    	if (logIndex != -1) {
    		logFile = getFileValue(args[logIndex]);
    		
    		//Create logger and log program starting runtime arguments
        	Logger logger = Logger.getInstance();
    		//sets existing file to log, or makes a new one.
        	//if logger cannot be correctly initialized (e.g., the given log file cannot be opened for writing) then displays error and terminate
        	if (logger.setFile(logFile) == false) { return; }
        	
        	//Logs program arguments
        	//this needs to be adjusted to fit their formatting
        	logger.log(argsString);
        	
    	//If the log file name was not specified in the runtime arguments then the logger should write to standard error
    	} else {
    		Logger.logError("Error: log file name was not specified in runtime arguments.");
    		//Logger.logError(argsString); //optional
    	}
 
    	if (covidIndex != -1) {
    		covidFile = getFileValue(args[covidIndex]);
        	//check COVID data has proper filename extension (“csv” or “json”, case-insensitive).
        	if(!isValidCovidExtension(covidFile)) {
        		System.out.println("Error: " + covidFile + " does not have proper file extension of csv or json");
        		return;
        	}	
    	}
    	if (propertiesIndex != -1) {
        	propertiesFile = getFileValue(args[propertiesIndex]);
    	}
		//Check the name of an argument only contains one of the valid names in the string array below
		//If name of an argument is not a valid listed argument, then display error & terminate
		String[] validArgNames = {"population", "log", "covid", "properties"};		
		if (!isSubset(validArgNames, argsNames, validArgNames.length, argsNames.length)) {
			System.out.println("Error: the name of an argument is not valid.");
			return;
		}
	
		//If The name of an argument is used more than once then display error & terminate
		//Adding a duplicate element into a hashset returns false --> if so, then terminate
		HashSet<String> namesSet = new HashSet<String>();
		for (int i=0; i<argsLength; i++) {
			if(!namesSet.add(argsNames[i])) {
				System.out.println("Error: "+ argsNames[i] + " runtime argument is used more than once");
				return;
			}
		}
    
		//Make Reader Objects & Pass into Processor
		PopulationsReader populationsReader = null;
		CovidReader covidReader = null;
		PropertiesReader propertiesReader = null;
		
		if (populationFile != null) {
			populationsReader = new PopulationsReader(populationFile);
        	Logger.getInstance().log(populationFile);
        	
    	}
    	if (covidFile != null) {
    		String covidExtension = getCovidExtension(covidFile);
    		covidReader = Processor.createCovidReader(covidExtension, covidFile);
        		Logger.getInstance().log(covidFile);
    	}
    	if (propertiesFile != null) {
    		propertiesReader = new PropertiesReader(propertiesFile);
    		Logger.getInstance().log(propertiesFile);
    	}
		
		Processor processor = new Processor(populationsReader, propertiesReader, covidReader);				
    	
    	//TODO: Create UI and run
		UserInterface ui = new UserInterface(processor);
		ui.UIProcess(processor);
    	
    	
    }
    
    /**
     * Helper function that gets the file name out of the runtime argument
     * The 4 valid optional args: covid, properties, population, and log
     * @param arg
     * @return
     */
    private static String getFileName(String arg) {
    	String fileName = null;
    	String regex = "^--(?<name>.+?)=(?<value>.+)$";
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(arg);
		if(matcher.matches()) {
			fileName = matcher.group("name");
			
			//If the filename has a comma at the end, remove it.
			//if(filename.substring(filename.length()-1).equals(",")) {
			//	filename = filename.substring(0, filename.length()-1);
			//}
		}
    	return fileName.toLowerCase();
    }
    
    /**
     * Helper function that gets the file value out of the runtime argument
     * Ex: the .csv, .log, .json files
     * @param arg 
     * @return filename
     */
    private static String getFileValue(String arg) {
    	String fileValue = null;
    	String regex = "^--(?<name>.+?)=(?<value>.+)$";
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(arg);
		if(matcher.matches()) {
			fileValue = matcher.group("value");
			
			//If the filename has a comma at the end, remove it.
			if(fileValue.substring(fileValue.length()-1).equals(",")) {
				fileValue = fileValue.substring(0, fileValue.length()-1);
			}
		}
    	return fileValue.toLowerCase();
    }
    
    /**
     * Helper function that checks the a filename has a file extension of either "csv" or "json"
     * @param filename: name of covid file
     * @return True is has proper file extension, else false
     */
    private static boolean isValidCovidExtension(String filename) {
        //split string by period
    	String[] fileParts = filename.toLowerCase().split("\\.");
    	int numFileParts = fileParts.length;
       
    	//get the last string in array which should contain the extension
        String extension = fileParts[numFileParts-1];        
    	
        if (extension.equals("csv") || extension.equals("json")) {
            return true;
        } else {
            return false;
        }
    }
    
    /**
     * 
     * @param filename
     * @return
     */
    private static String getCovidExtension(String filename) {
       if (filename == null) {
    	   return null;
       }
    	
    	//split string by period
    	String[] fileParts = filename.split("\\.");
    	int numFileParts = fileParts.length;
       
    	//get the last string in array which should contain the extension
        String extension = fileParts[numFileParts-1];        
    	
        if (extension.equals("csv")) {
            return "csv";
        } else {
            return "json";
        }
    }
    
    
    /**
     * Helper function to check if any arguments to main do not match the form “--name=value”.
     * @param args: runtime arguments to main
     * @return false if they do not match, else true
     */
    private static boolean isValidFormat(String[] args) {
    	String regex = "^--(?<name>.+?)=(?<value>.+)$";
		Pattern pattern = Pattern.compile(regex);
		for (int i=0; i<args.length; i++) {
			Matcher m = pattern.matcher(args[i]);
			if (!m.find()) {
				System.out.println("Error: " + args[i] + " is not a valid file format.");
				return false;
			}
		}
		return true;
    }
    
    /**
     * tests is argNames is a subset of validArgNames
     * if not, then the name of an argument is not one of the names listed as valid
     * @param validArgNames
     * @param argNames
     * @param m
     * @param n
     * @return true if a subset, else false
     */
    private static boolean isSubset(String[] validArgNames, String[] argNames, int m, int n) {
    	int i = 0;
    	int j = 0;
    	for(i=0; i<n; i++) {
    		for (j = 0; j < m; j++) {
    			if (argNames[i].equals(validArgNames[j])) {
    				break;
    			}
    		}
    		//If above loop was not broken, then argNames[i] is not present in validArgNames[]
			if (j == m) {
				return false;
			}
    	}
    	//All elements in argNames are present in validArgNames
    	return true;
    	
    }
        
        
}