Advertisement
Guest User

Untitled

a guest
Jan 17th, 2018
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 12.99 KB | None | 0 0
  1. package TaskHiso;
  2.  
  3. import java.io.File;
  4. import java.io.FileNotFoundException;
  5. import java.io.InvalidObjectException;
  6. import java.util.*;
  7.  
  8. /**
  9.  * A test class for the task
  10.  * IMPORTANT! The 'throws' keyword followed by an exception class that can be
  11.  * seen in the methods below indicates that this method throws the
  12.  * responsibility of catching the exception to the next method in the stack
  13.  * until the main method is reached
  14.  * If the main method has 'throws' after the signature, this exception
  15.  * will never be catched if it is thrown (which is NOT RECOMMENDED)
  16.  * Our main method here throws InterruptedException just not to add
  17.  * one more try-catch, so it doesn't make the code look even more complex
  18.  * All exceptions are catched in the main method as can be seen below
  19.  * The big data structure 'peopleDict' is that complex in order to connect
  20.  * all objects semantically
  21.  */
  22. public class AreaTest
  23. {
  24.     // 'final' indicates a constant; file paths are usually separated like this
  25.     private static final String INPUT_PEOPLE = "D://workspace//people.txt";
  26.     private static final String INPUT_POINTS = "D://workspace//polygons.txt";
  27.  
  28.     public static void main(String[] args) throws InterruptedException
  29.     {
  30.         TaxAgency agency = new TaxAgency();
  31.         // This is the shell of the big dictionary object
  32.         HashMap<Person, HashMap<Area, HashMap<Polygon, ArrayList<Point2D>>>> peopleDict = null;
  33.  
  34.         // The try-catch-finally is a mechanism used to litteraly catch and handle
  35.         // numerous different kinds of runtime and non-runtime errors that can
  36.         // during the program's lifespan (put simple: a mechanism for handling
  37.         // system errors, user input errors etc.). Inside of the try block is
  38.         // the portion of code that's expected to throw an exception
  39.         try
  40.         {
  41.             // Static methods don't need an object to be attached to and usually
  42.             // such methods provide more of an abstract type of logic
  43.             // For example, initialization of all the people from the file is an
  44.             // abstract logic because the method cares about instantiating
  45.             // some classes, it doesn't care about what classes they are or
  46.             // why are they the way they are etc.
  47.             agency.setPeople(initializePeople(INPUT_PEOPLE)); // initializing the list in Agency class
  48.             peopleDict = readCoordinates(INPUT_POINTS, agency);
  49.             polygonValidityChecker(agency.getPeople());
  50.         } catch (FileNotFoundException fnf)
  51.                 // The catch blocks define the type of error as a parameter
  52.                 // of that specific exception's class
  53.         {
  54.             System.err.println("File not found\n"); // it's up to the programmer what's inside the catch
  55.         } catch (InvalidObjectException ioex)
  56.         {
  57.             ioex.getCause();
  58.         }
  59.  
  60.         // A 'finally' staement can be put after the last 'catch' and the code between it's curly
  61.         // brackets will always be executed regardless of wheter or not an exception is catched
  62.         // For instance, you will most probably always see closing of scanners in 'finally'
  63.  
  64.         // Using the interface Map.Entry to iterate through the nested Map structures
  65.         for (Map.Entry<Person, HashMap<Area, HashMap<Polygon, ArrayList<Point2D>>>> entry :
  66.                 peopleDict.entrySet())
  67.         {
  68.             for (Map.Entry<Area, HashMap<Polygon, ArrayList<Point2D>>> entry2 :
  69.                     entry.getValue().entrySet())
  70.             {
  71.                 // Suspending the current thread multiple times in order to properly
  72.                 // visualize the error messages (correct output placement)
  73.                 Thread.sleep(100);
  74.                 // Using 'instanceof' to check if an object is an instance of a specific class
  75.                 if (entry2.getKey() instanceof FieldArea)
  76.                     System.out.println("\nArea ID " + entry2.getKey().getId() + ": FieldArea [Polygon ID " +
  77.                             entry2.getKey().getPolygon().getId() + "]");
  78.                 else if (entry2.getKey() instanceof ForestArea)
  79.                     System.out.println("\nArea ID " + entry2.getKey().getId() + ": ForestArea [Polygon ID " +
  80.                             entry2.getKey().getPolygon().getId() + "]");
  81.                 else if (entry2.getKey() instanceof UrbanArea)
  82.                     System.out.println("\nArea ID " + entry2.getKey().getId() + ": UrbanArea [Polygon ID " +
  83.                             entry2.getKey().getPolygon().getId() + "]");
  84.  
  85.                 for (Map.Entry<Polygon, ArrayList<Point2D>> entry3 :
  86.                         entry2.getValue().entrySet())
  87.                 {
  88.                     // Saving calculated area inside the Area class
  89.                     double area = entry3.getKey().calculateArea();
  90.                     entry2.getKey().setArea(area);
  91.  
  92.                     Thread.sleep(100);
  93.                     // Using Map.Entry we now have access to each pair
  94.                     // key-value in the nested structures
  95.                     Person currentPerson = entry.getKey();
  96.                     System.out.printf("\n%s's money prior to tax collecting: %.2f",
  97.                             currentPerson.getName(),
  98.                             currentPerson.getAllMoneyInBank());
  99.  
  100.                     // If NOT
  101.                     if (!agency.collectTax(currentPerson))
  102.                     {
  103.                         Thread.sleep(100);
  104.                         double remaining = currentPerson.getTotalTaxes() -
  105.                                 currentPerson.getPaidTaxes();
  106.                         System.err.printf("\nRemaining taxes to pay: %.2f\n", remaining);
  107.                         // Interrupting the current iteration because there's no point in
  108.                         // executing the rest of the method's code when the person has no money
  109.                         // ! Another way of achieving the same would be to add an 'else' clause
  110.                         // and put the code below inside of it !
  111.                         System.err.println("Person has insufficient funds!");
  112.                         break;
  113.                     }
  114.  
  115.                     System.out.printf("\n%s's money after tax collecting: %.2f",
  116.                             entry.getKey().getName(),
  117.                             entry.getKey().getAllMoneyInBank());
  118.                     System.out.printf("\nTotal taxes paid: %.2f\n",
  119.                             entry.getKey().getPaidTaxes());
  120.                 }
  121.             }
  122.         }
  123.     }
  124.  
  125.     /**
  126.      * A method that reads area and polygon IDs + coordinate points of the polygon
  127.      * The method creates semantic connections between all objects and lists
  128.      * @param inputFile - the input .txt file
  129.      * @param agency - the global TaxAgency object
  130.      * @return - the complex HashMap data structure
  131.      * @throws FileNotFoundException to be catched in main
  132.      */
  133.     private static HashMap<Person, HashMap<Area, HashMap<Polygon,
  134.             ArrayList<Point2D>>>> readCoordinates(String inputFile, TaxAgency agency)
  135.             throws FileNotFoundException
  136.     {
  137.         Scanner input = new Scanner(new File(inputFile));
  138.         ArrayList<Person> people = initializePeople(INPUT_PEOPLE);
  139.         HashMap<Person, HashMap<Area, HashMap<Polygon, ArrayList<Point2D>>>> peopleDict =
  140.                 new HashMap<Person, HashMap<Area, HashMap<Polygon, ArrayList<Point2D>>>>();
  141.         // An index counter to keep track of the current line number
  142.         int listIndex = 0;
  143.  
  144.         // While the input file has next character (or next byte)
  145.         while (input.hasNext())
  146.         {
  147.             // Fixing the index when last person is reached to avoid OutOfBoundsException
  148.             if (listIndex == people.size())
  149.                 --listIndex;
  150.  
  151.             // Retrieving the current line and chopping it
  152.             // in order to split the data
  153.             String line = input.nextLine();
  154.             String[] splitted = line.split("->");
  155.             String[] splittedPoints = splitted[2].split(";");
  156.  
  157.             // Using the factory to generate an object
  158.             Area nextArea = Area.areaFactory(splitted[0],
  159.                     splittedPoints.length);
  160.             Polygon nextPolygon = new Polygon(splitted[1]);
  161.             // Setting the polygon relation in Area class
  162.             nextArea.setPolygon(nextPolygon);
  163.  
  164.             ArrayList<Point2D> pointsList = new ArrayList<Point2D>();
  165.  
  166.             // Adding all coordinate points that belong to the current polygon
  167.             for (int i = 0; i < nextArea.numSides(); i++)
  168.             {
  169.                String[] xy = splittedPoints[i].split(" ");
  170.                pointsList.add(new Point2D(Double.parseDouble(xy[0]),
  171.                        Double.parseDouble(xy[1])));
  172.             }
  173.             // Adding one last point which is the same as the first one
  174.             // Needed for the area calculation formula
  175.             pointsList.add(new Point2D(pointsList.get(0).x,
  176.                     pointsList.get(0).y));
  177.  
  178.             // Setting the coordinate points for the array in the Polygon class
  179.             nextPolygon.setPoints(pointsList);
  180.  
  181.             // Adding the generated Area object to the array in the Person class
  182.             Person nextPerson = people.get(listIndex);
  183.             nextPerson.setAgency(agency);
  184.             nextPerson.addArea(nextArea);
  185.  
  186.             // If a person has at least one own area,
  187.             // set the public boolean hasAreas to true
  188.             if (nextPerson.getOwnAreas().size() > 0)
  189.                 nextPerson.hasAreas = true;
  190.  
  191.             // Adding objects to the data structure in the TaxAgency class
  192.             agency.getPeople().add(nextPerson);
  193.             agency.getPeople().get(listIndex).getOwnAreas().add(nextArea);
  194.  
  195.             // The following lines are just putting all of the above together
  196.             // Forming the complex data structure
  197.             HashMap<Polygon, ArrayList<Point2D>> pointsHash =
  198.                     new HashMap<Polygon, ArrayList<Point2D>>();
  199.             pointsHash.put(nextPolygon, pointsList);
  200.             HashMap<Area, HashMap<Polygon, ArrayList<Point2D>>> areaHash =
  201.                     new HashMap<Area, HashMap<Polygon, ArrayList<Point2D>>>();
  202.  
  203.             areaHash.put(nextArea, pointsHash);
  204.             peopleDict.put(nextPerson, areaHash);
  205.  
  206.             // Incrementing the index in order to proceed to next person
  207.             listIndex++;
  208.         }
  209.  
  210.         // Scanners should always be closed when not needed anymore
  211.         // This prevents memory leaks from the stream
  212.         // IMPORTANT! Scanners should never be closed inside a loop
  213.         if (input != null)
  214.             input.close();
  215.         return peopleDict;
  216.     }
  217.  
  218.     /**
  219.      * A method that reads the data for the people, generates objects and puts them in a data structure
  220.      * @param inputFile - the input .txt file
  221.      * @return - an ArrayList of all created Person objects
  222.      * @throws FileNotFoundException to be catched in main
  223.      */
  224.     private static ArrayList<Person> initializePeople(String inputFile)
  225.             throws FileNotFoundException
  226.     {
  227.         Scanner input = new Scanner(new File(inputFile));
  228.         ArrayList<Person> people = new ArrayList<Person>();
  229.  
  230.         while (input.hasNext())
  231.         {
  232.             String[] splitted = input.nextLine().split(";");
  233.             String[] addressSplit = splitted[3].split(" ");
  234.             Address address = new Address(addressSplit[0],
  235.                     Integer.parseInt(addressSplit[1]),      // parsing is a way to cast to
  236.                     addressSplit[2], addressSplit[3]);      // other types of data which are
  237.             people.add(new Person(splitted[0], splitted[1], // otherwise unable to be casted to
  238.                     splitted[2], address,
  239.                     Double.parseDouble(splitted[4]),
  240.                     Double.parseDouble(splitted[5])));
  241.         }
  242.  
  243.         if (input != null)
  244.             input.close();
  245.         return people;
  246.     }
  247.  
  248.     /**
  249.      * A method that checks if the current polygon has at least 2 sides
  250.      * @param people - the input list of all Person objects
  251.      * @throws InvalidObjectException to be catched in main
  252.      */
  253.     private static void polygonValidityChecker(ArrayList<Person> people)
  254.             throws InvalidObjectException
  255.     {
  256.         for (int i = 0; i < people.size(); i++)
  257.         {
  258.             // Retrieving areas for each person
  259.             ArrayList<Area> areas = people.get(i).getOwnAreas();
  260.             for (int j = 0; j < areas.size(); j++)
  261.             {
  262.                 // If polygon is valid, proceed to next iteration
  263.                 if (areas.get(j).numSides() > 2)
  264.                     continue;
  265.                 else // if not, throw an exception
  266.                     throw new InvalidObjectException("The polygon with index " + j +
  267.                             " related to person with id " + people.get(i).getName() +
  268.                             " must have at least 3 sides!\n");
  269.             }
  270.         }
  271.     }
  272. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement