/** * Reads query file and parses the queries. * * @requires querystream, outstream, are successfully initialized * @requires g to be already generated * @param queryStream file input stream of query file * @param outStream file output stream of output file * @param g * @effects writes results to output file */ private static void parseQuery(FileInputStream queryStream, FileOutputStream outStream, Graph g) { try { BufferedWriter output = new BufferedWriter(new OutputStreamWriter(outStream)); BufferedReader queryReader = new BufferedReader(new InputStreamReader(queryStream)); final int COMMAND_INDEX = 0; final int U1_INDEX = 1; final int U2_INDEX = 2; final String QUERY_ENDING = " ?"; Set<Set<String>> queries = new LinkedHashSet<Set<String>>(); String line; while ((line = queryReader.readLine()) != null) { // each query set contains two user id strings and a command // this also handles duplicate user ids with different commands Set<String> query = new LinkedHashSet<String>(); // a bit overkill, but eliminate any unnecessary whitespace if needed and replaces with // single space String[] columns = line.trim().replaceAll("\\s+", " ").split(" "); // first column is query // second column is user 1 // third column is user 2 String command = columns[COMMAND_INDEX]; String id1 = columns[U1_INDEX]; String id2 = columns[U2_INDEX]; query.add(id1); query.add(id2); query.add(command); // check if query ends with question mark (with leading space) and query is unique if (line.endsWith(QUERY_ENDING) && !queries.contains(query)) { queries.add(query); Vertex u1 = new Vertex(id1); Vertex u2 = new Vertex(id2); printResults(output, g, u1, u2, command); } } queryReader.close(); output.close(); // return new LinkedHashMap<List<Vertex>, String>(queries); } catch (Exception e) { // if something goes wrong throw new RuntimeException(e); } }
/** * Helper method for parseQuery. Writes the results of the queries to the output file. * * @param output initialized BufferedWriter for the output file * @param g initialized graph of edges and vertices * @param u1 one vertex used in commands * @param u2 another vertex used in commands * @param command command to execute */ private static void printResults( BufferedWriter output, Graph g, Vertex u1, Vertex u2, String command) { final String commonInfluencers = "commonInfluencers"; final String numRetweets = "numRetweets"; final String VERTEX_NOT_FOUND_ERROR = "ERROR: One or more vertices does not exist in the graph."; final String INVALID_COMMAND_ERROR = "\tError: invalid command "; final String PATH_NOT_FOUND_ERROR = "\tPath not found."; List<Vertex> allVertices = new ArrayList<Vertex>(g.getVertices()); try { output.write("query: " + command + " " + u1.toString() + " " + u2.toString()); output.newLine(); output.write("<result>"); output.newLine(); // check if vertices exist in graph if (!allVertices.contains(u1) || !allVertices.contains(u2)) { output.write(VERTEX_NOT_FOUND_ERROR); output.newLine(); output.write("</result>"); output.newLine(); output.newLine(); return; } // if query is commonInfluencers if (command.equals(commonInfluencers)) { List<Vertex> commonFollowers = new LinkedList<Vertex>(Algorithms.commonDownstreamVertices(g, u1, u2)); for (Vertex v : commonFollowers) { output.write("\t" + v.toString()); output.newLine(); } } // if query is numRetweets else if (command.equals(numRetweets)) { // note switch in u1 and u2; this is because tweets go upstream int distance = Algorithms.shortestDistance(g, u2, u1); if (distance == -1) { output.write(PATH_NOT_FOUND_ERROR); } else { // implicitly convert distance to string as printing out ints somehow didn't work output.write("" + distance); // System.out.println(distance); } output.newLine(); } else { output.write(INVALID_COMMAND_ERROR + command); output.newLine(); } output.write("</result>"); output.newLine(); output.newLine(); } catch (Exception e) { throw new RuntimeException(e); } }