package org.skymaps;
import java.io.BufferedReader;
import java.io.File;
import java.io.FilenameFilter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Vector;
import java.util.TreeSet;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
* The StarSearch
Java program performs a search for data entries
* conerning certain stars in text files in /smeidc/sk0/equ
. The
* entries that are located are outputted to text (.txt) files, one for each
* star per camera and mode, in the directory of the user's choice.
*
* The text files that are searched should contain data concerning stars
* removed from sky maps. This program is meant to be a convenience utility
* for locating and collating data concerning these removed stars.
*
*
* StarSearch
is meant to be called in the following manner (from
* a console):
*
*
* % java -cp /zshare/smei/java/common org.skymaps.StarSearch [Options]
* star_name_1[:star_name_2:star_name_3:...]
*
*
* Note that there may be a BASH alias for this program, such as
* starsearch
.
*
*
* Options
* The following command-line options are allowed:
*
*
*
* -cs
* - Instructs
StarSearch
to perform a case-sensitive search.
* This would force the program to match only those entries with star
* names that are case-sensitively identical to the stars the user
* specifies. By default, the search is case-insensitive.
* -dest=dest_directory
* - Directs
StarSearch
to write text files to
* dest_directory
. This must be a valid directory, either
* absolute or relative, and it must have write permissions enabled.
* If this option is not specified, then the default write directory
* is the user's current directory (the directory from which
* StarSearch
is called).
* -file=star_name_file
* - Instructs
StarSearch
to parse the given file,
* star_name_file
, for additional star names. The star
* names must be organized one per line in the specified file. Two or
* more star names that appear on one line will collectively be treated
* as one star name (which is obviously not desirable). Blank lines are
* ignored. The default action should this option not be specified is
* to only read in star names from the star name list at the command
* prompt. This option may be specified more than once if more than
* one star name file is to be supplied to StarSearch
. This
* option can also be used in conjunction with the star name list
* following the options.
* -rdir=root_directory
* - Directs
StarSearch
to begin its search in
* root_directory
. It will then descend into its
* subdirectories, which are specified in the initialization XML file
* (more on this below), to search for text files to process. If this
* option is not specified, then the default starting directory is
* /smeidc/sky0/equ
.
*
*
*
* If illegal or malformed command-line options are entered by the user, then
* the program indicates the error and terminates normally.
*
*
* Star Name List
* The list following the options is a colon separated list of star names. The
* star names can have spaces within them, but they must be separated by
* colons to be considered distinct. Star names cannot be repeated. If one
* or more star names are repeated, then an error is generated.
*
*
* The following is a list of examples of possible uses of options and star
* lists:
*
*
*
* % java StarSearch
* - Prints the usage message and exits.
* % java StarSearch HD 29763
* - Searches for the star
HD 29763
in the default search
* directory's subdirectories and outputs the resulting text files to the
* user's current directory.
* % java StarSearch -cs -rdir=/some/fake/directory
* -dest=/another/fake/directory hd 29763
* - Searches for the star
hd 29763
(case-sensitive) in the
* subdirectories of /some/fake/directory
and outputs the
* resulting text files to /another/fake/directory
.
* % java StarSearch HD 29763:V* zet Tau : HD 74442
* - Searches for the stars
HD 29763
,
* V* zet Tau
, and HD 74442
in the default
* search directory's subdirectories and outputs the resulting text
* files to the user's current directory.
* % java StarSearch hd 29763::v* zet tau:::: HD 74442:
*
* - Same as the previous example
* % java StarSearch -file=starnames.txt hd 29763::v* zet tau::::
* HD 74442:
* - Same as the previous example, except that additional star names
* are inputted from the text file
starnames.txt
.
*
*
*
* Format of Inputted Text Files
* When StarSearch
descends into a subdirectory, it searches only
* within text (.txt) files that have filenames in the format
* c(1+2+3)pnt_YYYY_DOY_HHMMSS.txt
(case-insensitive), where
* YYYY is the year, DOY is the day of the year, and HHMMSS is the hour,
* minutes, and seconds of the date (this date should be in standard SMEI
* format). Examples include c2pnt_2006_057_135219.txt
,
* C3PnT_2004_158_094551.TXT
, and
* c1PNT_2005_041_160854.tXt
.
*
*
* All inputted text files should have the same format. The first line is
* a whitespace-separated list of column titles that describe the entries in
* their respective columns, followed by lines containing entries for different
* stars. The first entry should be the name of the star (11 characters long
* maximum), and this name is compared against the names of the stars provided
* by the user. If the names match, then the entire line is copied to its
* respective output text file (depending on the name of the star to which it
* matches). Examples of properly formatted input text files can be found
* within the subdirectories of /smeidc/sky0/equ
.
*
*
* Format of Outputted Text Files
* The format of the outputted text files is identical to that of the
* inputted text files, including the column title header line (the first
* line of the inputted text files). The entries are sorted chronologically
* by the date stored in each entry (the date has the standard SMEI format
* YYYY_DOY_HHMMSS and is at character offset 54 (zero-based) from the
* beginning of the line by default). Outputted file names have the filename
* format starname_c(1+2+3)(e+s).txt
, where (1+2+3)
* is the camera number and (e+s)
is the camera mode, either
* e
ngineering mode or s
cientific mode.
*
*
* The XML Initialization File
* When StarSearch
is run, its initialization file
* starsearchinit.xml
is parsed. This file should be located
* in the same directory as StarSearch
and has a corresponding
* DTD file named starsearchinit.dtd
. The initialization file
* contains various kinds of information, but StarSearch
only
* parses information within the
* <Directories></Directories>
tag pair. This
* holds entries corresponding to the subdirectories searched by
* StarSearch
, including the relative path of the subdirectory
* from the starting search directory, the camera number it corresponds to
* (either 1
, 2
, or 3
), and the
* mode of the camera (either e
for engineering mode or
* s
for scientific mode). Subdirectories can be added or
* removed by adding new Directory
entries or removing them,
* respectively. However, if the initialization file is modified, then it
* must conform to its corresponding DTD, or unpredictable
* errors may result.
*
*
* @author Jordan T. Vaughan
* @version 1.1
* @see StarFormat
*/
public class StarSearch {
/**
* The default starting search directory
*/
public static final String DEFAULT_ROOT_DIR = "/smeidc/sky0/equ";
/**
* The default output directory for writing text files
*/
public static final String DEFAULT_OUTPUT_DIR = "./";
private static final String RDIR_OPTION = "-rdir=";
private static final String CS_OPTION = "-cs";
private static final String DEST_OPTION = "-dest=";
private static final String FILE_OPTION = "-file=";
/**
* The path and name of the XML initialization file (which should be in
* the same directory as the StarSearch .class file). Modify this value
* (that is, recompile the code with a new value) if the directory of
* the initialization file should change.
*/
public static final String INI_FILE = "/zshare/smei/java/common/org/" +
"skymaps/starsearchinit.xml";
/**
* The size of the star name field on a line of input text (the character
* offset is zero by default)
*/
public static final int STAR_NAME_FIELD_SIZE = 11;
/**
* The character offset of the date entry in a line of input text
*/
public static final int DATE_OFFSET = 54;
/**
* The size of the date field, in characters
*/
public static final int DATE_SIZE = 15;
/**
* The starting method of the StarSearch
program. The
* command-line arguments are first parsed and checked for errors, then
* the search is conducted.
*
* @param args An array of command-line argument strings.
* @since 1.0
*/
public static void main(String[] args) {
// Relevant local variables.
File rootDirectory = null;
File destDirectory = null;
boolean isCaseInsensitive = true;
Vector starNameFiles = new Vector();
TreeSet starTree = new TreeSet();
HashMap> entryMap = null;
Vector directories = new Vector();
// Are there any arguments?
if(args.length == 0) {
printUsageMessage();
return;
}
// Parse command-line options.
int counter = 0;
while(counter < args.length && args[counter].charAt(0) == '-') {
if(args[counter].length() >= RDIR_OPTION.length() &&
args[counter].substring(0, RDIR_OPTION.length()).
equalsIgnoreCase(RDIR_OPTION)) {
// Setting the root directory for the search.
if(rootDirectory != null) {
System.out.println("ERROR: Root directory specified more" +
" than once. Aborting.\n");
return;
}
args[counter] = args[counter].substring(RDIR_OPTION.length());
if(args[counter].length() == 0) {
System.out.println("ERROR: No root search directory " +
"given. Aborting.\n");
return;
}
rootDirectory = new File(args[counter]);
if(!rootDirectory.exists()) {
System.out.println("ERROR: Given directory does not " +
"exist -- " + args[counter] + "\n");
return;
}
if(!rootDirectory.isDirectory()) {
System.out.println("ERROR: Given directory is not a " +
"directory -- " + args[counter] + "\n");
return;
}
}
else if(args[counter].equalsIgnoreCase(CS_OPTION)) {
// Setting the search to case-sensitive mode.
if(!isCaseInsensitive) {
System.out.println("ERROR: Case-sensitive search " +
"specified more than once. Aborting.\n");
return;
}
isCaseInsensitive = false;
}
else if(args[counter].length() >= DEST_OPTION.length() &&
args[counter].substring(0, DEST_OPTION.length()).
equalsIgnoreCase(DEST_OPTION)) {
// Setting the destination directory for writing search
// results.
if(destDirectory != null) {
System.out.println("ERROR: Output directory specified " +
"more than once. Aborting.\n");
return;
}
args[counter] = args[counter].substring(DEST_OPTION.length());
if(args[counter].length() == 0) {
System.out.println("ERROR: No output directory given. " +
"Aborting.\n");
return;
}
destDirectory = new File(args[counter]);
if(!destDirectory.exists()) {
System.out.println("ERROR: Given directory does not " +
"exist -- " + args[counter] + "\n");
return;
}
if(!destDirectory.isDirectory()) {
System.out.println("ERROR: Given directory is not a " +
"directory -- " + args[counter] + "\n");
return;
}
}
else if(args[counter].length() >= FILE_OPTION.length() &&
args[counter].substring(0, FILE_OPTION.length()).
equalsIgnoreCase(FILE_OPTION)) {
// Reading in a file containing star names.
args[counter] = args[counter].substring(FILE_OPTION.length());
if(args[counter].length() == 0) {
System.out.println("ERROR: No star name file given. " +
"Aborting.\n");
return;
}
File starNameFile = new File(args[counter]);
if(!starNameFile.exists()) {
System.out.println("ERROR: Given star name file does not "+
"exist -- " + args[counter] + "\n");
return;
}
if(!starNameFile.isFile()) {
System.out.println("ERROR: Given star name file is not a "+
"file -- " + args[counter] + "\n");
return;
}
starNameFiles.add(starNameFile);
}
else {
// Unrecognized command-line option. Display an error message.
System.out.println("ERROR: Unrecognized option -- " +
args[counter] + "\n");
return;
}
// Increment the counter argument.
counter++;
}
// Create default directories if they were not already specified by
// the user via the command line.
if(rootDirectory == null) {
rootDirectory = new File(DEFAULT_ROOT_DIR);
if(!rootDirectory.exists()) {
System.out.println("FATAL ERROR: Default root directory " +
DEFAULT_ROOT_DIR + " does not exist.\nAborting.\n");
return;
}
if(!rootDirectory.isDirectory()) {
System.out.println("FATAL ERROR: Default root directory " +
DEFAULT_ROOT_DIR + " is not a directory.\n" +
"Aborting.\n");
return;
}
}
if(destDirectory == null) {
destDirectory = new File(DEFAULT_OUTPUT_DIR);
if(!destDirectory.exists()) {
System.out.println("FATAL ERROR: Default output directory " +
DEFAULT_OUTPUT_DIR + " does not exist.\nAborting.\n");
return;
}
if(!destDirectory.isDirectory()) {
System.out.println("FATAL ERROR: Default output directory " +
DEFAULT_OUTPUT_DIR + " is not a directory.\n" +
"Aborting.\n");
return;
}
}
// Parse star names.
StringBuilder constructedStarName = new StringBuilder();
while(counter < args.length) {
// Continue to build the current star name as a String. If a
// colon is encountered, finish the current star name building and
// add it to our collection of star names.
while(args[counter].indexOf(':') != -1) {
constructedStarName.append(args[counter].substring(0,
args[counter].indexOf(':')));
args[counter] = args[counter].substring(
args[counter].indexOf(':') + 1);
if(constructedStarName.length() != 0) {
if(!(isCaseInsensitive ?
starTree.add(constructedStarName.toString().
toLowerCase().trim()):
starTree.add(constructedStarName.toString().trim()))) {
System.out.println("ERROR: Duplicate star name given" +
" -- " + constructedStarName.toString() + "\n");
return;
}
constructedStarName.setLength(0);
}
}
constructedStarName.append(args[counter] + " ");
counter++;
}
// Handle leftover star name characters, if they exist.
if(constructedStarName.length() != 0) {
if(!(isCaseInsensitive ?
starTree.add(constructedStarName.toString().toLowerCase().
trim()) :
starTree.add(constructedStarName.toString().trim()))) {
System.out.println("ERROR: Duplicate star name given -- " +
constructedStarName.toString() + "\n");
return;
}
constructedStarName.setLength(0);
}
// If any star name files were given, read them in.
for(File starNameFile: starNameFiles) {
try {
BufferedReader reader = new BufferedReader(new FileReader(
starNameFile));
String line = reader.readLine().trim();
while(line != null) {
if(line.length() > 0) {
if(!(isCaseInsensitive ?
starTree.add(line.toLowerCase()) :
starTree.add(line))) {
System.out.println("ERROR: Duplicate star name " +
"given -- " + line + "\n");
return;
}
}
line = reader.readLine();
}
reader.close();
}
catch(FileNotFoundException e) {
// This should not occur.
System.out.println("ERROR: File " + starNameFile +
" does not exist. Skipping.");
}
catch(IOException e) {
System.out.println("ERROR: An IO error occurred while reading"+
" from the file " + starNameFile + "\nSkipping.");
}
}
// Do we have any stars to search for?
if(starTree.size() == 0) {
System.out.println("ERROR: No star names given.");
printUsageMessage();
return;
}
/* Now that we have all the star names parsed, do the search.
* Open the initialization file, parse the XML tree (while validating),
* and retrieve the subdirectories that we will search.
*/
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(true);
factory.setIgnoringComments(true);
DocumentBuilder builder = null;
try {
builder = factory.newDocumentBuilder();
}
catch(ParserConfigurationException e) {
System.out.println("FATAL ERROR: Unable to instantiate an XML " +
"parser to parse the\ninitialization file. Aborting.\n");
return;
}
Document rootNode = null;
try {
rootNode = builder.parse(new File(INI_FILE));
}
catch(IOException e) {
System.out.println("ERROR: An IO error occured while attempting " +
"to read the initialization file.\nAborting.\n");
return;
}
catch(SAXException e) {
System.out.println("ERROR: The initialization file is not a " +
"well-formed XML file, or it\ndoes not conform to the " +
"specifications provided in the associated DTD. Aborting.\n");
return;
}
// Read the Directory entries.
NodeList directoryList = ((Element)rootNode.getDocumentElement().
getElementsByTagName("Directories").item(0)).
getElementsByTagName("Directory");
for(counter = 0; counter < directoryList.getLength(); counter++) {
Element directory = (Element)directoryList.item(counter);
try {
directories.add(new StarDirectory(
directory.getAttribute("name"),
Integer.parseInt(directory.getAttribute("camera")),
directory.getAttribute("mode")));
}
catch(NumberFormatException e) {
System.out.println("ERROR: Initialization file contains a " +
"Directory entry with an\ninvalid camera number. " +
"Aborting.\n");
return;
}
catch(IllegalArgumentException e) {
System.out.println("ERROR: Initialization file contains an " +
"invalid Directory entry. The error follows:\n");
e.printStackTrace();
return;
}
}
// Inform the user of what kind of search we're performing.
System.out.print("\nPerforming a search for the stars\n ");
for(String star: starTree) {
System.out.print(star + " ");
}
System.out.print("\nfrom the base directory " +
rootDirectory.getAbsolutePath() + " in the subdirectories\n ");
for(counter = 0; counter < directories.size(); counter++) {
System.out.print(directories.get(counter).getName() + " ");
}
System.out.println("\nThe output directory is " +
destDirectory.getAbsolutePath() + " and the search will be " +
(isCaseInsensitive ? "case-insensitive.\n" : "case-sensitive.\n"));
/* Descend into the relevant subdirectories and search the files for
* entries.
*/
for(counter = 0; counter < directories.size(); counter++) {
File directory = new File(rootDirectory,
directories.get(counter).getName());
String header = null;
/* Does the directory exist within the starting directory? If not,
* skip it.
*/
if(!directory.exists() || !directory.isDirectory()) {
System.out.println(directory.getAbsolutePath() + " cannot be" +
" found or is not a file. Skipping...");
continue;
}
/* Retrieve all files in the directory and create a new HashMap for
* the star entries found within the files. Then iterate through
* the files and search them for the star entries we are looking
* for.
*/
File[] files = directory.listFiles(new StarFilenameFilter());
if(files == null) {
System.out.println("ERROR: An IO error occurred while " +
"attempting to access the\nfiles in subdirectory " +
directory.getName() + ". Skipping...");
continue;
}
entryMap = new HashMap>();
System.out.println("Searching subdirectory " +
directories.get(counter).getName() + " (" + files.length +
" files)");
for(int j = 0; j < files.length; j++) {
BufferedReader reader = null;
try {
/* Create the new file reader (buffered) and retrieve the
* column titles (the "header") from the file.
*/
reader = new BufferedReader(new FileReader(files[j]));
header = reader.readLine();
if(header == null) {
reader.close();
continue;
}
/* Are we working with the new-style headers (starting with
* semicolons) or the old-style headers (only one line of text
* with the column titles on it)?
*/
if(header.charAt(0) == ';') {
boolean nullLine = false;
do {
header = reader.readLine();
if(header == null) {
nullLine = true;
break;
}
} while(header.charAt(0) == ';');
if(nullLine) {
continue;
}
}
else {
header = reader.readLine();
}
/* Read each line and check to see if it belongs to a star
* we are looking for.
*/
String line = header;
while(line != null) {
String starName = null;
try {
starName = line.substring(0, STAR_NAME_FIELD_SIZE).
trim();
}
catch(ArrayIndexOutOfBoundsException e) {
continue;
}
/* Does the current line contain an entry for a star
* we are looking for? Do the checking in a case-
* sensitive or case-insensitive manner depending on
* what the user desires.
*/
if((isCaseInsensitive ?
starTree.contains(starName.toLowerCase()) :
starTree.contains(starName))) {
String lowercaseForm = starName.toLowerCase();
if(entryMap.containsKey(lowercaseForm)) {
TreeSet oldSet =
entryMap.get(lowercaseForm);
oldSet.add(new StarEntry(line,
line.substring(DATE_OFFSET,
DATE_OFFSET + DATE_SIZE)));
entryMap.put(lowercaseForm, oldSet);
}
else {
TreeSet newSet =
new TreeSet();
newSet.add(new StarEntry(line,
line.substring(DATE_OFFSET,
DATE_OFFSET + DATE_SIZE)));
entryMap.put(starName.toLowerCase(),
newSet);
}
}
line = reader.readLine();
}
reader.close();
}
catch(FileNotFoundException e) {
System.out.println("ERROR: This error should not occur, " +
"but the file " + files[j].getAbsolutePath() +
" does not exist. Skipping.");
continue;
}
catch(IOException e) {
System.out.println("ERROR: A general I/O error occurred " +
"while attempting to read the file " +
files[j].getAbsolutePath() + ". Aborting.");
return;
}
}
/* Now that the entry map has been filled with entries from this
* directory, write the entries to files in the output directory.
*/
for(String starName: entryMap.keySet()) {
StringBuilder outputFilename = new StringBuilder();
/* Begin with the name of the star with illegal filename
* characters removed.
*/
for(int j = 0; j < starName.length(); j++) {
char character = starName.charAt(j);
if(character == ' ' || character == '\t') {
outputFilename.append('_');
}
else if(character == '*') {
outputFilename.append('^');
}
else {
outputFilename.append(character);
}
}
/* Append the rest of the filename and open a write stream to
* it.
*/
outputFilename.append("_c" +
directories.get(counter).getCamera() +
directories.get(counter).getMode() +
StarFilenameFilter.FILE_EXTENSION);
PrintWriter writer = null;
try {
writer = new PrintWriter(new File(
destDirectory, outputFilename.toString()));
}
catch(FileNotFoundException e) {
System.out.println("ERROR: Cannot write results to the " +
"file " + outputFilename.toString() + ". Skipping.");
continue;
}
// Write the header and all entries for this star.
writer.println(header);
for(StarEntry entry: entryMap.get(starName)) {
writer.println(entry.lineOfEntries);
}
writer.close();
// Tell the user that the file was written.
System.out.println(" Wrote file: " +
outputFilename.toString());
}
}
// All done!
System.out.println("\nDone!");
}
/**
* Displays a usage message to the user on standard output. This should
* only be displayed if an error occurs.
*
* @since 1.0
*/
public static void printUsageMessage() {
System.out.print(
"Usage:\n" +
" % starsearch [Options] star_name_1[:star_name_2:" +
"star_name_3:...]\n\n" +
"Options:\n" +
" -cs Make star name search case sensitive" +
" [default is\n" +
" case-insensitive]\n" +
" -dest=dest_directory Directory where outputted text files" +
" will be written\n" +
" [default is " + DEFAULT_OUTPUT_DIR +
"]\n" +
" -file=star_name_file Specifies a text file containing " +
"star names,\n" +
" one on each line in the file. This " +
"option may be\n" +
" specified more than once (duplicate " +
"star names\n" +
" not allowed).\n" +
" -rdir=root_directory Base directory for the search, whose "+
"subdirectories\n" +
" are searched for files [default=" +
DEFAULT_ROOT_DIR + "]\n\n" +
"Examples:\n" +
" starsearch HD 29763\n" +
" Searches for the star named HD 29763 in the default\n" +
" search directory (" + DEFAULT_ROOT_DIR + ") and outputs\n" +
" the results of the search to " + DEFAULT_OUTPUT_DIR +
"/HD_29763.txt\n" +
" starsearch HD 29763:V* zet tau\n" +
" Searches the for stars named HD 29763 and V* zet tau in\n" +
" the default search directory and outputs the results to\n" +
" HD_29763.txt and V^_zet_tau.txt in the default output\n" +
" directory.\n" +
" starsearch -rdir=/smeidb -cs -dest=/home/soft/temp HD 29763\n"+
" Searches for HD 29763 (case-sensitive) starting in\n" +
" /smeidb and writing the results to " +
"/home/soft/temp/HD_29763.txt\n\n" +
"Note Concerning Star Names:\n" +
" Although any colon-separated list of star names can be\n" +
" given, spaces and asterisks (*) in star names will be\n" +
" replaced with underscores (_) and carats (^), respectfully,\n"+
" in output file names. No other characters are transformed." +
"\n\n");
System.out.println(" Star files have titles of the form " +
"c(1+2+3)pnt_YYYY_DOY_HHMMSS.txt,\n" +
" and the output files have the form starname_c(1+2+3)(e+" +
"s).txt.");
}
/* Represents a subdirectory from the starting search directory. This is
* used to store information about the subdirectory that is read in from
* the XML initialization file, such as the subdirectory's name, its
* corresponding camera number (either 1, 2, or 3), and its corresponding
* camera mode (either "e" for engineering mode or "s" for scientific
* mode). The method names are self-explanatory.
*
* @author Jordan T. Vaughan
* @since 1.0
*/
private static class StarDirectory {
public static final String MODE_E = "e";
public static final String MODE_S = "s";
private String name;
private int camera;
private String mode;
public StarDirectory() {
name = "";
camera = 1;
mode = MODE_E;
}
public StarDirectory(String name, int camera, String mode) {
this.name = name;
if(camera < 1 || camera > 3) {
throw new IllegalArgumentException("Invalid camera number " +
"for Directory entry: " + camera);
}
this.camera = camera;
if(!(mode.equals(MODE_E) || mode.equals(MODE_S))) {
throw new IllegalArgumentException("Invalid camera mode for " +
"Directory entry: " + mode);
}
this.mode = mode;
}
public int getCamera() {
return camera;
}
public String getMode() {
return mode;
}
public String getName() {
return name;
}
public void setCamera(int camera) {
if(camera < 1 || camera > 3) {
throw new IllegalArgumentException("Invalid camera number " +
"for Directory entry: " + camera);
}
this.camera = camera;
}
public void setMode(String mode) {
if(!(mode.equals(MODE_E) || mode.equals(MODE_S))) {
throw new IllegalArgumentException("Invalid camera mode for " +
"Directory entry: " + mode);
}
this.mode = mode;
}
public void setName(String name) {
if(name == null) {
throw new NullPointerException();
}
this.name = name;
}
}
/* Represents a line from an inputted text file corresponding to a certain
* star name. This is used to store lines of entries as strings and for
* sorting by date in sorting data structures. The methods are self-
* explanatory.
*
* @author Jordan T. Vaughan
* @since 1.0
*/
private static class StarEntry implements Comparable {
public String lineOfEntries;
public String date;
public StarEntry(String lineOfEntries, String date) {
this.lineOfEntries = lineOfEntries;
this.date = date;
}
public int compareTo(StarEntry o) {
return date.compareTo(o.date);
}
}
/**
* Filename filter used to determine which files in a given subdirectory
* are valid as input text files. The format for these files is given
* in the class documentation for StarSearch
. The methods
* are self-explanatory.
*
* @author Jordan T. Vaughan
* @since 1.0
*/
private static class StarFilenameFilter implements FilenameFilter {
public static final String CAMERA1_FILE_PREFIX = "c1pnt_";
public static final String CAMERA2_FILE_PREFIX = "c2pnt_";
public static final String CAMERA3_FILE_PREFIX = "c3pnt_";
public static final String FILE_EXTENSION = ".txt";
public StarFilenameFilter() { }
public boolean accept(File dir, String name) {
if(name == null || name.length() == 0) {
return false;
}
String prefix = name.substring(0, CAMERA1_FILE_PREFIX.length());
if(!(prefix.equalsIgnoreCase(CAMERA1_FILE_PREFIX) ||
prefix.equalsIgnoreCase(CAMERA2_FILE_PREFIX) ||
prefix.equalsIgnoreCase(CAMERA3_FILE_PREFIX))) {
return false;
}
if(!java.util.regex.Pattern.matches(
"\\d\\d\\d\\d_\\d\\d\\d_\\d\\d\\d\\d\\d\\d",
name.substring(CAMERA1_FILE_PREFIX.length(),
name.length() - FILE_EXTENSION.length()))) {
return false;
}
if(!name.substring(name.length() - FILE_EXTENSION.length()).
equalsIgnoreCase(FILE_EXTENSION)) {
return false;
}
return true;
}
}
}