Search code examples
javadictionaryfloyd-warshalltransitive-closure

How to start off from these details


I already have a skeleton of what I need for the program as far as the methods I was told I would need. However, other than that I am having trouble figuring out how to start coding this program. The details are as follows. I'm not asking to have my program done for me, literally I'm just confused on how to start. I know I need to read in user input to get the text file, we use scanner at my college, but I don't know if that needs to be in the constructor, in main, or in a different method.

  1. Accepts a single command line parameter - namely, a text file that contains a line delimited list of pairs of strings. These pairs of String will represent edges in a dependence graph. For example, a line that reads:A.java B.java represents a dependence edge from A.java to B.java. A file representing the graph above might look like: Main.java A.java A.java B.java

  2. Maps each of the Strings read from the file to unique integer identifiers. This mapping will make it easy to turn a file name into an array index.

  3. Maps each of the unique integer identifiers (from above) back to the original String.

  4. Computes the adjacency matrix representing the dependences between the Strings.

  5. Performs a transitive closure operation on the adjacency matrix to produce a new closure matrix that represents transitive dependences between the strings. A simple approach to performing this operation is the Floyd-Warshall algorithm - you may want to do some research on this topic.

  6. Your output must follow the format illustrated by the example output file on the course website. On the course website is an example input file and the corresponding output file. Your output must have the same format at this example. The goal is to have the output information in an attractive, readable format that makes clear that each of the methods listed below works correctly.

  7. Methods with private field return types such as getNameIdMap, getIdNameMap, getRoots, etc. rather than returning a mutable portion of the inner state of our class that a copy (clone) of that map, list should be returned. This way the caller gets a fully usable object (for example, list or map) without being able to affect the inner state of the class.

Your program should also provide the following methods:

  1. public Map getNameIdMap() - returns a mapping from String to unique integer identifier. The integer identifier represents the index into the adjacency and closure matrices for the given String. Note: In Python the return value must be a dictionary with pairs with the keys being strings and the values being ints.

  2. public Map getIdNameMap() - returns a mapping from unique integer identifier back to the original string. Note: In Python the return value must be a dictionary with pairs with the keys being ints and the values being strings.

  3. public int[][] getDependenceGraph() - returns the adjacency matrix representing dependences between files.

  4. public int[][] getTransitiveDependenceGraph() - return the dependence graph after the transitive closure operation is applied.

  5. public List getRoots() - returns a list of Strings that correspond to files upon which no other files depend (e.g., Main in the example above). Note: In Python the return value is also a list of strings.

  6. public List getLeaves() - returns a list of Strings that correspond to files that depend upon no other files (e.g., B in the example above). Note: In Python the return value is also a list of strings.

  7. public void removeLeaf(String leaf) - removes a leaf from both the adjacency and transitive closure matrices. This means that if X depends on Y and Y is the leaf being removed, X's dependence upon Y is also eliminated. This may or may not make X a new leaf. Consider using a special number (i.e., other than 0 and 1) in the matrix to indicate that the file has been logically removed.

  8. public List firewall(String node) - computes the "class firewall" of the specified file. In software engineering, the class firewall concept states that when maintenance is performed on a system, only changed classes and classes affected by a change need to be re-tested. Note: In Python the return value is also a list of strings. For this method, you should retest classes that are affected indirectly as well as directly. For example, if class A depends on class B and class B depends on class C and you change class C, then you should retest classes A and B.

  9. public void printParallelGroups() - Assuming that we wanted to parallelize the compilation of the files, we would need to identify files that would not trigger the compilation of other files; these are the leaves in the dependency graph. This method identifies files that could be compiled in parallel, print that list of files, and remove them from the graph. The method should repeat this process until all files have been "compiled".


Solution

  • I have come across similar situations many a times while starting to write some piece of code. I think, you have a pretty good idea of your problem. You can make a sample text file ( even on a piece of paper ) with 2-3 values and try to think more about how you want things to be. You know that there need to be a main method that takes your file name. You can use a scanner in the main or in constructor or in any other method. This depends on the design you use. If you want a very basic program you can declare it in the main method and go ahead. But I suggest you should use another method to take input from the file, something like readInputFromText(), where you declare a local scanner object. You can ofcourse do this in other ways too. Some basic rules I follow are :

    1. Have separate methods for each task. To open a file, I have a fileOpener, to close it, I have another method etc. Each method is supposed to do a single task only. All functions related to file will be put in a single class say, FileUtil. This is a utility task and not your main task, so you keep all these util classes, like FileUtilities, StringUtilities, DatabaseUtilites etc. in a Util package.

      1. Good naming strategies and following conventions.

      2. Using a build tool like Maven or Ant.

      3. Doing documentation and proper testing.

    I don't know if it really answers your question in someway. But keep these in mind and start off your program. Test at each stage and make a primary version. Keep the improvements for subsequent versions.

    If you have specific questions, a big community is waiting for you :)

    Best wishes.