Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package TaskHiso;
- import java.io.File;
- import java.io.FileNotFoundException;
- import java.io.InvalidObjectException;
- import java.util.*;
- /**
- * A test class for the task
- * IMPORTANT! The 'throws' keyword followed by an exception class that can be
- * seen in the methods below indicates that this method throws the
- * responsibility of catching the exception to the next method in the stack
- * until the main method is reached
- * If the main method has 'throws' after the signature, this exception
- * will never be catched if it is thrown (which is NOT RECOMMENDED)
- * Our main method here throws InterruptedException just not to add
- * one more try-catch, so it doesn't make the code look even more complex
- * All exceptions are catched in the main method as can be seen below
- * The big data structure 'peopleDict' is that complex in order to connect
- * all objects semantically
- */
- public class AreaTest
- {
- // 'final' indicates a constant; file paths are usually separated like this
- private static final String INPUT_PEOPLE = "D://workspace//people.txt";
- private static final String INPUT_POINTS = "D://workspace//polygons.txt";
- public static void main(String[] args) throws InterruptedException
- {
- TaxAgency agency = new TaxAgency();
- // This is the shell of the big dictionary object
- HashMap<Person, HashMap<Area, HashMap<Polygon, ArrayList<Point2D>>>> peopleDict = null;
- // The try-catch-finally is a mechanism used to litteraly catch and handle
- // numerous different kinds of runtime and non-runtime errors that can
- // during the program's lifespan (put simple: a mechanism for handling
- // system errors, user input errors etc.). Inside of the try block is
- // the portion of code that's expected to throw an exception
- try
- {
- // Static methods don't need an object to be attached to and usually
- // such methods provide more of an abstract type of logic
- // For example, initialization of all the people from the file is an
- // abstract logic because the method cares about instantiating
- // some classes, it doesn't care about what classes they are or
- // why are they the way they are etc.
- agency.setPeople(initializePeople(INPUT_PEOPLE)); // initializing the list in Agency class
- peopleDict = readCoordinates(INPUT_POINTS, agency);
- polygonValidityChecker(agency.getPeople());
- } catch (FileNotFoundException fnf)
- // The catch blocks define the type of error as a parameter
- // of that specific exception's class
- {
- System.err.println("File not found\n"); // it's up to the programmer what's inside the catch
- } catch (InvalidObjectException ioex)
- {
- ioex.getCause();
- }
- // A 'finally' staement can be put after the last 'catch' and the code between it's curly
- // brackets will always be executed regardless of wheter or not an exception is catched
- // For instance, you will most probably always see closing of scanners in 'finally'
- // Using the interface Map.Entry to iterate through the nested Map structures
- for (Map.Entry<Person, HashMap<Area, HashMap<Polygon, ArrayList<Point2D>>>> entry :
- peopleDict.entrySet())
- {
- for (Map.Entry<Area, HashMap<Polygon, ArrayList<Point2D>>> entry2 :
- entry.getValue().entrySet())
- {
- // Suspending the current thread multiple times in order to properly
- // visualize the error messages (correct output placement)
- Thread.sleep(100);
- // Using 'instanceof' to check if an object is an instance of a specific class
- if (entry2.getKey() instanceof FieldArea)
- System.out.println("\nArea ID " + entry2.getKey().getId() + ": FieldArea [Polygon ID " +
- entry2.getKey().getPolygon().getId() + "]");
- else if (entry2.getKey() instanceof ForestArea)
- System.out.println("\nArea ID " + entry2.getKey().getId() + ": ForestArea [Polygon ID " +
- entry2.getKey().getPolygon().getId() + "]");
- else if (entry2.getKey() instanceof UrbanArea)
- System.out.println("\nArea ID " + entry2.getKey().getId() + ": UrbanArea [Polygon ID " +
- entry2.getKey().getPolygon().getId() + "]");
- for (Map.Entry<Polygon, ArrayList<Point2D>> entry3 :
- entry2.getValue().entrySet())
- {
- // Saving calculated area inside the Area class
- double area = entry3.getKey().calculateArea();
- entry2.getKey().setArea(area);
- Thread.sleep(100);
- // Using Map.Entry we now have access to each pair
- // key-value in the nested structures
- Person currentPerson = entry.getKey();
- System.out.printf("\n%s's money prior to tax collecting: %.2f",
- currentPerson.getName(),
- currentPerson.getAllMoneyInBank());
- // If NOT
- if (!agency.collectTax(currentPerson))
- {
- Thread.sleep(100);
- double remaining = currentPerson.getTotalTaxes() -
- currentPerson.getPaidTaxes();
- System.err.printf("\nRemaining taxes to pay: %.2f\n", remaining);
- // Interrupting the current iteration because there's no point in
- // executing the rest of the method's code when the person has no money
- // ! Another way of achieving the same would be to add an 'else' clause
- // and put the code below inside of it !
- System.err.println("Person has insufficient funds!");
- break;
- }
- System.out.printf("\n%s's money after tax collecting: %.2f",
- entry.getKey().getName(),
- entry.getKey().getAllMoneyInBank());
- System.out.printf("\nTotal taxes paid: %.2f\n",
- entry.getKey().getPaidTaxes());
- }
- }
- }
- }
- /**
- * A method that reads area and polygon IDs + coordinate points of the polygon
- * The method creates semantic connections between all objects and lists
- * @param inputFile - the input .txt file
- * @param agency - the global TaxAgency object
- * @return - the complex HashMap data structure
- * @throws FileNotFoundException to be catched in main
- */
- private static HashMap<Person, HashMap<Area, HashMap<Polygon,
- ArrayList<Point2D>>>> readCoordinates(String inputFile, TaxAgency agency)
- throws FileNotFoundException
- {
- Scanner input = new Scanner(new File(inputFile));
- ArrayList<Person> people = initializePeople(INPUT_PEOPLE);
- HashMap<Person, HashMap<Area, HashMap<Polygon, ArrayList<Point2D>>>> peopleDict =
- new HashMap<Person, HashMap<Area, HashMap<Polygon, ArrayList<Point2D>>>>();
- // An index counter to keep track of the current line number
- int listIndex = 0;
- // While the input file has next character (or next byte)
- while (input.hasNext())
- {
- // Fixing the index when last person is reached to avoid OutOfBoundsException
- if (listIndex == people.size())
- --listIndex;
- // Retrieving the current line and chopping it
- // in order to split the data
- String line = input.nextLine();
- String[] splitted = line.split("->");
- String[] splittedPoints = splitted[2].split(";");
- // Using the factory to generate an object
- Area nextArea = Area.areaFactory(splitted[0],
- splittedPoints.length);
- Polygon nextPolygon = new Polygon(splitted[1]);
- // Setting the polygon relation in Area class
- nextArea.setPolygon(nextPolygon);
- ArrayList<Point2D> pointsList = new ArrayList<Point2D>();
- // Adding all coordinate points that belong to the current polygon
- for (int i = 0; i < nextArea.numSides(); i++)
- {
- String[] xy = splittedPoints[i].split(" ");
- pointsList.add(new Point2D(Double.parseDouble(xy[0]),
- Double.parseDouble(xy[1])));
- }
- // Adding one last point which is the same as the first one
- // Needed for the area calculation formula
- pointsList.add(new Point2D(pointsList.get(0).x,
- pointsList.get(0).y));
- // Setting the coordinate points for the array in the Polygon class
- nextPolygon.setPoints(pointsList);
- // Adding the generated Area object to the array in the Person class
- Person nextPerson = people.get(listIndex);
- nextPerson.setAgency(agency);
- nextPerson.addArea(nextArea);
- // If a person has at least one own area,
- // set the public boolean hasAreas to true
- if (nextPerson.getOwnAreas().size() > 0)
- nextPerson.hasAreas = true;
- // Adding objects to the data structure in the TaxAgency class
- agency.getPeople().add(nextPerson);
- agency.getPeople().get(listIndex).getOwnAreas().add(nextArea);
- // The following lines are just putting all of the above together
- // Forming the complex data structure
- HashMap<Polygon, ArrayList<Point2D>> pointsHash =
- new HashMap<Polygon, ArrayList<Point2D>>();
- pointsHash.put(nextPolygon, pointsList);
- HashMap<Area, HashMap<Polygon, ArrayList<Point2D>>> areaHash =
- new HashMap<Area, HashMap<Polygon, ArrayList<Point2D>>>();
- areaHash.put(nextArea, pointsHash);
- peopleDict.put(nextPerson, areaHash);
- // Incrementing the index in order to proceed to next person
- listIndex++;
- }
- // Scanners should always be closed when not needed anymore
- // This prevents memory leaks from the stream
- // IMPORTANT! Scanners should never be closed inside a loop
- if (input != null)
- input.close();
- return peopleDict;
- }
- /**
- * A method that reads the data for the people, generates objects and puts them in a data structure
- * @param inputFile - the input .txt file
- * @return - an ArrayList of all created Person objects
- * @throws FileNotFoundException to be catched in main
- */
- private static ArrayList<Person> initializePeople(String inputFile)
- throws FileNotFoundException
- {
- Scanner input = new Scanner(new File(inputFile));
- ArrayList<Person> people = new ArrayList<Person>();
- while (input.hasNext())
- {
- String[] splitted = input.nextLine().split(";");
- String[] addressSplit = splitted[3].split(" ");
- Address address = new Address(addressSplit[0],
- Integer.parseInt(addressSplit[1]), // parsing is a way to cast to
- addressSplit[2], addressSplit[3]); // other types of data which are
- people.add(new Person(splitted[0], splitted[1], // otherwise unable to be casted to
- splitted[2], address,
- Double.parseDouble(splitted[4]),
- Double.parseDouble(splitted[5])));
- }
- if (input != null)
- input.close();
- return people;
- }
- /**
- * A method that checks if the current polygon has at least 2 sides
- * @param people - the input list of all Person objects
- * @throws InvalidObjectException to be catched in main
- */
- private static void polygonValidityChecker(ArrayList<Person> people)
- throws InvalidObjectException
- {
- for (int i = 0; i < people.size(); i++)
- {
- // Retrieving areas for each person
- ArrayList<Area> areas = people.get(i).getOwnAreas();
- for (int j = 0; j < areas.size(); j++)
- {
- // If polygon is valid, proceed to next iteration
- if (areas.get(j).numSides() > 2)
- continue;
- else // if not, throw an exception
- throw new InvalidObjectException("The polygon with index " + j +
- " related to person with id " + people.get(i).getName() +
- " must have at least 3 sides!\n");
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement