diff --git a/src/ApiTestFile.java b/src/ApiTestFile.java index 2982ea7..50b2180 100644 --- a/src/ApiTestFile.java +++ b/src/ApiTestFile.java @@ -8,19 +8,19 @@ public class ApiTestFile { - private static final String API_URL = "https://api.translink.ca/rttiapi/v1/stops/55612?"; + private static final String PARTIAL_API_URL = "OpenDataAPI/api/V1"; public static void getStopInformation() { OkHttpClient client = new OkHttpClient().newBuilder() .build(); HttpUrl httpUrl = new HttpUrl.Builder() - .scheme("https") - .host("api.translink.ca") - .addPathSegment("rttiapi") - .addPathSegment("v1") - .addPathSegment("stops") - .addPathSegment("55612?") - .addQueryParameter("apikey", System.getenv("API_KEY")) + .scheme("http") + .host("api.openmetrolinx.com") + .addPathSegment(PARTIAL_API_URL) + .addPathSegment("Stop") + .addPathSegment("Details") + .addPathSegment("UN") //getting station information for UN, which denotes Union Station + .addQueryParameter("key", System.getenv("API_KEY")) .build(); Request request = new Request.Builder() diff --git a/src/app/Main.java b/src/app/Main.java index 8eb52a8..f11a4d9 100644 --- a/src/app/Main.java +++ b/src/app/Main.java @@ -1,9 +1,12 @@ package app; -import data_access.FileStationDataAccessObject; +import data_access.text_file.FileStationDataAccessObject; +import data_access.API.GOStationApiClass; import entity.StationFactory; import interface_adapter.search.SearchViewModel; import interface_adapter.ViewManagerModel; +import interface_adapter.show_incoming_vehicles.ShowIncomingVehiclesState; +import interface_adapter.show_incoming_vehicles.ShowIncomingVehiclesViewModel; import interface_adapter.station_info.StationInfoViewModel; import view.SearchPanelView; import view.StationInfoView; @@ -38,6 +41,8 @@ public static void main(String[] args) { // be observed by the Views. SearchViewModel searchViewModel = new SearchViewModel(); StationInfoViewModel stationInfoViewModel = new StationInfoViewModel(); + ShowIncomingVehiclesViewModel showIncomingVehiclesViewModel = new ShowIncomingVehiclesViewModel(); + // Creating a DAO called stationDataAccessObject by reading from file revisedStopData.txt, with the creation of the object being done by StationFactory() // Note: This process is wrapped in a try-catch block since it is possible that the code throws out an IOException (occurs when the txt file being read does not exist) @@ -47,7 +52,7 @@ public static void main(String[] args) { // TODO [Implementation question]: Is there suppose to be NO ARGUMENT for the StationFactory() instance passed inside? FileStationDataAccessObject stationDataAccessObject; try { - stationDataAccessObject = new FileStationDataAccessObject("./revisedStopData.txt", new StationFactory()); + stationDataAccessObject = new FileStationDataAccessObject("./revisedStopData.txt", new StationFactory(), new GOStationApiClass()); } catch (IOException e) { throw new RuntimeException(e); } @@ -58,7 +63,7 @@ public static void main(String[] args) { // Creating an instance of StationInfoView. Note: Although this view should have its own use case, for now, since we are NOT displaying other data besides the station name, there is no useCaseFactory for this case // This View is only linked to transition from the SearchPanelView (once the other use case are integrated into this view, this will NO LONGER be the case) - StationInfoView stationInfoView = new StationInfoView(stationInfoViewModel); + StationInfoView stationInfoView = StationInfoUseCaseFactory.create(viewManagerModel, stationInfoViewModel, stationDataAccessObject, showIncomingVehiclesViewModel); views.add(stationInfoView, stationInfoView.viewName); // When initially booting up the application, the stationPanel is the 1st panel displayed to viewers. diff --git a/src/app/SearchUseCaseFactory.java b/src/app/SearchUseCaseFactory.java index b271f3f..ed4d3f8 100644 --- a/src/app/SearchUseCaseFactory.java +++ b/src/app/SearchUseCaseFactory.java @@ -46,9 +46,11 @@ private static SearchController createSearchUseCase( // Notice how we pass this method's parameters to the Presenter. SearchOutputBoundary searchOutputBoundary = new SearchPresenter(searchViewModel, stationInfoViewModel, viewManagerModel); + // TODO [Implementation question]: No need to use an instance of SearchUseCaseFactory right? + SearchInputBoundary searchInteractor = new SearchInteractor( searchDataAccessObject, searchOutputBoundary); return new SearchController(searchInteractor); } -} \ No newline at end of file +} diff --git a/src/app/StationInfoUseCaseFactory.java b/src/app/StationInfoUseCaseFactory.java new file mode 100644 index 0000000..0620657 --- /dev/null +++ b/src/app/StationInfoUseCaseFactory.java @@ -0,0 +1,54 @@ +package app; + +import interface_adapter.ViewManagerModel; +import interface_adapter.show_incoming_vehicles.ShowIncomingVehiclesViewModel; +import interface_adapter.station_info.StationInfoController; +import interface_adapter.station_info.StationInfoPresenter; +import interface_adapter.station_info.StationInfoViewModel; +import use_case.StationInfo.StationInfoDataAccessInterface; +import use_case.StationInfo.StationInfoInputBoundary; +import use_case.StationInfo.StationInfoInteractor; +import use_case.StationInfo.StationInfoOutputBoundary; +import view.StationInfoView; + +import javax.swing.*; +import java.io.IOException; + +public class StationInfoUseCaseFactory { + + /** Prevent instantiation. */ + private StationInfoUseCaseFactory() {} + + public static StationInfoView create( + ViewManagerModel viewManagerModel, + StationInfoViewModel stationInfoViewModel, + StationInfoDataAccessInterface stationInfoDataAccessObject, + ShowIncomingVehiclesViewModel showIncomingVehiclesViewModel) { + + try { + StationInfoController stationInfoController = createStationInfoUseCase(viewManagerModel, + stationInfoViewModel, stationInfoDataAccessObject, showIncomingVehiclesViewModel); + return new StationInfoView(stationInfoViewModel, stationInfoController); + } catch (IOException e) { + JOptionPane.showMessageDialog(null, "Could not open user data file."); + } + + return null; + } + + private static StationInfoController createStationInfoUseCase( + ViewManagerModel viewManagerModel, + StationInfoViewModel stationInfoViewModel, + StationInfoDataAccessInterface stationInfoDataAccessObject, + ShowIncomingVehiclesViewModel showIncomingVehiclesViewModel) throws IOException { + + // Notice how we pass this method's parameters to the Presenter. + StationInfoOutputBoundary stationInfoOutputBoundary = new StationInfoPresenter(stationInfoViewModel, + showIncomingVehiclesViewModel, viewManagerModel); + + StationInfoInputBoundary stationInfoInteractor = new StationInfoInteractor( + stationInfoDataAccessObject, stationInfoOutputBoundary); + + return new StationInfoController(stationInfoInteractor); + } +} diff --git a/src/data_access/API/GOStationApiClass.java b/src/data_access/API/GOStationApiClass.java new file mode 100644 index 0000000..eb025a2 --- /dev/null +++ b/src/data_access/API/GOStationApiClass.java @@ -0,0 +1,57 @@ +package data_access.API; + +import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class GOStationApiClass implements TrainApiInterface { + + private final String PARTIAL_API_URL = "OpenDataAPI/api/V1"; + public GOStationApiClass () { + } + public List retrieveStationAmenities(String stationId){ + OkHttpClient client = new OkHttpClient().newBuilder() + .build(); + HttpUrl httpUrl = new HttpUrl.Builder() + .scheme("http") + .host("api.openmetrolinx.com") + .addPathSegment(PARTIAL_API_URL) + .addPathSegment("Stop") + .addPathSegment("Details") + .addPathSegment(stationId) //getting station information for the station with the id denoted by stationId + .addQueryParameter("key", API_KEY) + .build(); + + Request request = new Request.Builder() + .url(httpUrl) + .addHeader("content-type", "application/json") + .build(); + try { + // TODO: Do we need additional error checking based on error codes in Metadata? + Response response = client.newCall(request).execute(); + String fullStopJsonData = response.body().string(); + JSONObject fullStopJsonObj = new JSONObject(fullStopJsonData); // This is where the metadata is located at + JSONObject stopJsonDataObj = fullStopJsonObj.getJSONObject("Stop"); + JSONArray amenitiesJsonArray = stopJsonDataObj.getJSONArray("Facilities"); + List amenitiesList = new ArrayList(); + for (int i = 0; i < amenitiesJsonArray.length(); i++) { + JSONObject currAmenitiesEntry = amenitiesJsonArray.getJSONObject(i); + amenitiesList.add(currAmenitiesEntry.getString("Description")); + //System.out.println(currAmenitiesEntry.getString("Description")); // For debugging purposes + } + return amenitiesList; + + } catch (IOException | JSONException e) { + throw new RuntimeException(e); + } + + } +} diff --git a/src/data_access/API/GOTrainsApiClass.java b/src/data_access/API/GOTrainsApiClass.java new file mode 100644 index 0000000..9b69592 --- /dev/null +++ b/src/data_access/API/GOTrainsApiClass.java @@ -0,0 +1,70 @@ +package data_access.API; + +import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class GOTrainsApiClass implements TrainApiInterface { + + private final String PARTIAL_API_URL = "OpenDataAPI/api/V1"; + public GOTrainsApiClass () { + } + + /** + * Searches for all trains and their information including ID and position. + * + * @param stationId ID of station for incoming trains + * @return API information + */ + public List retrieveTrains(String stationId){ + OkHttpClient client = new OkHttpClient().newBuilder() + .build(); + HttpUrl httpUrl = new HttpUrl.Builder() + .scheme("http") + .host("api.openmetrolinx.com") + .addPathSegment(PARTIAL_API_URL) + .addPathSegment("ServiceataGlance") + .addPathSegment("Trains") + .addPathSegment("All") + // TODO: may need for future + // .addPathSegment(stationId) //getting station information for the station with the id denoted by stationId + .addQueryParameter("key", API_KEY) + .build(); + + Request request = new Request.Builder() + .url(httpUrl) + .addHeader("content-type", "application/json") + .build(); + + /** + * Search for information + */ + try { + Response response = client.newCall(request).execute(); + String trainJsonData = response.body().string(); + JSONObject metaDataJsonObj = new JSONObject(trainJsonData); // This is where the Metadata is located at + JSONObject tripsJsonDataObj = metaDataJsonObj.getJSONObject("Trips"); + JSONArray tripJsonArray = tripsJsonDataObj.getJSONArray("Trip"); + List tripList = new ArrayList(); + for (int i = 0; i < tripJsonArray.length(); i++) { + JSONObject currTripEntry = tripJsonArray.getJSONObject(i); + tripList.add(currTripEntry.getString("id")); // left at "id" for now, to be changed to vehicle + //System.out.println(currAmenitiesEntry.getString("Description")); // For debugging purposes + System.out.println(httpUrl); + } + return tripList; // do not print this yet, wait for full change + + } catch (IOException | JSONException e) { + throw new RuntimeException(e); + } + + } +} diff --git a/src/data_access/API/GOVehicleApiClass.java b/src/data_access/API/GOVehicleApiClass.java new file mode 100644 index 0000000..1584602 --- /dev/null +++ b/src/data_access/API/GOVehicleApiClass.java @@ -0,0 +1,75 @@ +package data_access.API; + +import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import static data_access.API.TrainApiInterface.API_KEY; + +public class GOVehicleApiClass { + private final String PARTIAL_API_URL = "OpenDataAPI/api/V1"; + public GOVehicleApiClass() { + } + public List> retrieveVehicleInfo(String stationId){ + OkHttpClient client = new OkHttpClient().newBuilder() + .build(); + HttpUrl httpUrl = new HttpUrl.Builder() + .scheme("http") + .host("api.openmetrolinx.com") + .addPathSegment(PARTIAL_API_URL) + .addPathSegment("Stop") + .addPathSegment("NextService") + .addPathSegment(stationId) + .addQueryParameter("key", API_KEY) + .build(); + + Request request = new Request.Builder() + .url(httpUrl) + .addHeader("content-type", "application/json") + .build(); + try { + Response response = client.newCall(request).execute(); + String trainInfoJsonData = response.body().string(); + JSONObject headerPositionJsonObj = new JSONObject(trainInfoJsonData); // This is where the header is located at + + JSONObject stationServiceJsonObj = headerPositionJsonObj.getJSONObject("NextService"); + JSONArray vehiclesJsonArray = stationServiceJsonObj.getJSONArray("Lines"); + + List> vehiclesList = new ArrayList<>(); + for (int i = 0; i < vehiclesJsonArray.length(); i++) { + JSONObject currtripEntry = vehiclesJsonArray.getJSONObject(i); + List vehiclesInfoList = new ArrayList<>(); + vehiclesInfoList.add(currtripEntry.getString("LineCode")); // parent line id of the station + vehiclesInfoList.add(currtripEntry.getString("LineName")); // parent line full name + vehiclesInfoList.add(currtripEntry.getString("ServiceType")); + // indicates if vehicle is a train or a bus. Train is "T", Bus is "B" + vehiclesInfoList.add(currtripEntry.getString("DirectionName")); // Vehicle display name + vehiclesInfoList.add(currtripEntry.getString("ScheduledDepartureTime")); + // vehicle scheduled departure time from this station + vehiclesInfoList.add(currtripEntry.getString("ComputedDepartureTime")); + // vehicle actual departure time from this station + vehiclesInfoList.add(currtripEntry.getString("TripNumber")); + // We could calculate delay based on Computed Departure time and Scheduled departure time of a Certain Vehicle + + vehiclesList.add(vehiclesInfoList); //add trainInfoList in trainList + + System.out.println(vehiclesInfoList); // For debugging purposes + + System.out.println(httpUrl); + } + return vehiclesList; // do not print this yet, wait for full change + + } catch (IOException | JSONException e) { + throw new RuntimeException(e); + } + + } +} diff --git a/src/data_access/API/GOVehiclePositionApiClass.java b/src/data_access/API/GOVehiclePositionApiClass.java new file mode 100644 index 0000000..3ec2887 --- /dev/null +++ b/src/data_access/API/GOVehiclePositionApiClass.java @@ -0,0 +1,69 @@ +package data_access.API; + +import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class GOVehiclePositionApiClass implements TrainApiInterface { + + private final String PARTIAL_API_URL = "OpenDataAPI/api/V1"; + public GOVehiclePositionApiClass () { + } + + /** + * Searches for the current position of a train. + * + * @param stationId + * @return return the longitude and latitude + */ + public List retrieveVehiclePosition(String stationId){ + OkHttpClient client = new OkHttpClient().newBuilder() + .build(); + HttpUrl httpUrl = new HttpUrl.Builder() + .scheme("http") + .host("api.openmetrolinx.com") + .addPathSegment(PARTIAL_API_URL) + .addPathSegment("Gtfs") + .addPathSegment("Feed") + .addPathSegment("VehiclePosition") + .addPathSegment(stationId) //getting station information for the station with the id denoted by stationId + .addQueryParameter("key", API_KEY) + .build(); + + Request request = new Request.Builder() + .url(httpUrl) + .addHeader("content-type", "application/json") + .build(); + + /** + * Search for longitude and latitude + */ + try { + Response response = client.newCall(request).execute(); + String vehiclePositionJsonData = response.body().string(); + JSONObject headerPositionJsonObj = new JSONObject(vehiclePositionJsonData); // This is where the header is located at + // JSONObject vehiclePositionJsonDataObj = vehiclePositionJsonObj.getJSONObject("entity"); + JSONArray entityJsonArray = headerPositionJsonObj.getJSONArray("entity"); + List entityList = new ArrayList(); + for (int i = 0; i < entityJsonArray.length(); i++) { + JSONObject currEntityEntry = entityJsonArray.getJSONObject(i); + entityList.add(currEntityEntry.getString("id")); // left at "id" for now, to be changed to vehicle + //System.out.println(currAmenitiesEntry.getString("Description")); // For debugging purposes + System.out.println(httpUrl); + } + return entityList; // do not print this yet, wait for full change + + } catch (IOException | JSONException e) { + throw new RuntimeException(e); + } + + } +} diff --git a/src/data_access/API/TrainApiInterface.java b/src/data_access/API/TrainApiInterface.java new file mode 100644 index 0000000..6a41ebc --- /dev/null +++ b/src/data_access/API/TrainApiInterface.java @@ -0,0 +1,7 @@ +package data_access.API; + +public interface TrainApiInterface { + // This is an interface defining all the shared attributes and methods that all Api classes should have + //TODO: We might not need an Api interface since the 2 API we are using have little to no relationships with each other + String API_KEY = System.getenv("API_KEY"); +} diff --git a/src/data_access/FileStationDataAccessObject.java b/src/data_access/FileStationDataAccessObject.java index 60293f0..af1ee2f 100644 --- a/src/data_access/FileStationDataAccessObject.java +++ b/src/data_access/FileStationDataAccessObject.java @@ -1,7 +1,9 @@ package data_access; +import entity.Train; import entity.Vehicle; import entity.StationFactory; +import use_case.StationInfo.StationInfoDataAccessInterface; import use_case.search.SearchDataAccessInterface; import java.io.*; @@ -12,7 +14,7 @@ // We will name it as FileStationDataAccessObject for now. When we start to implement vehicles, we will change it as requires // We might need to create different DA0 java files based on what data we are pulling (station, train or bus) -public class FileStationDataAccessObject implements SearchDataAccessInterface { +public class FileStationDataAccessObject implements SearchDataAccessInterface, StationInfoDataAccessInterface { private final File stationTxtFile; private final Map stations = new HashMap<>(); private final StationFactory stationFactory; @@ -24,27 +26,28 @@ public FileStationDataAccessObject(String txtFilePath, StationFactory stationFac // Reading the provided txt file that has a path specified by attribute txtFilePath try(BufferedReader reader = new BufferedReader(new FileReader(stationTxtFile))){ - String line; - reader.readLine(); // call the readline() method once outside the loop as we do not want to read the first line of txt file, since that line contains just the headers. - while((line = reader.readLine()) != null) { + String line; + reader.readLine(); // call the readline() method once outside the loop as we do not want to read the first line of txt file, since that line contains just the headers. + while((line = reader.readLine()) != null) { - String[] parsedStationInfo = line.split(","); //splitting by "," since information in txt file is seperated by "," - String parsedStationName = parsedStationInfo[1]; - String parsedStationID = parsedStationInfo[0]; + String[] parsedStationInfo = line.split(","); //splitting by "," since information in txt file is seperated by "," + String parsedStationName = parsedStationInfo[1]; + String parsedStationID = parsedStationInfo[0]; - String parsedStationParentLine = parsedStationInfo[5]; - Float parsedStationLatitude = Float.valueOf(parsedStationInfo[2]); // converting string type to float object type. Through potential autoboxing, this float object type is converted to primitative type. - Float parsedStationLongtitude = Float.valueOf(parsedStationInfo[3]); + String parsedStationParentLine = parsedStationInfo[5]; + Float parsedStationLatitude = Float.valueOf(parsedStationInfo[2]); // TODO: Converting entry type to Float (object type), not the float primitative type + Float parsedStationLongtitude = Float.valueOf(parsedStationInfo[3]); - List parsedStationAmenities = new ArrayList(); //This is empty at the time of reading txt file, this will be populated through API calls - List parsedStationVehicles = new ArrayList(); //This is empty at the time of reading txt file, this will be populated through API calls + List parsedStationAmenities = new ArrayList(); //TODO: empty at the time of reading txt file, this will be populated through API calls + List parsedStationVehicles = new ArrayList(); //TODO: empty at the time of reading txt file, this will be populated through API calls - // For reference, here are the order of arguments in order to pass into stationFactory.create(): - //(name, stationId, parentLine, latitude, longitude, amenitiesList, incomingVehicles) - Station station = stationFactory.create(parsedStationName, parsedStationID, parsedStationParentLine, parsedStationLatitude, parsedStationLongtitude, parsedStationAmenities, parsedStationVehicles); + // For reference, here are the order of arguments in order to pass into stationFactory.create(): + //(name, stationId, parentLine, latitude, longitude, amenitiesList, incomingVehicles) + Station station = stationFactory.create(parsedStationName, parsedStationID, parsedStationParentLine, parsedStationLatitude, parsedStationLongtitude, parsedStationAmenities, parsedStationVehicles); - stations.put(parsedStationName, station); - } + stations.put(parsedStationName, station); + + } } } @Override @@ -53,6 +56,11 @@ public Station getStation (String inputStationName) { return stations.get(inputStationName); } + @Override + public String getStationId(String inputStationName) { + return stations.get(inputStationName).getId(); + } + @Override public String getStationParentLine(String inputStationName) { @@ -70,4 +78,5 @@ public boolean stationExist(String identifier){ // May need to resolve this by converting user input to lowercase -> then comparing to txt names (which will also be compared in lowercase form?) } + } diff --git a/src/data_access/text_file/FileStationDataAccessObject.java b/src/data_access/text_file/FileStationDataAccessObject.java new file mode 100644 index 0000000..f3925ed --- /dev/null +++ b/src/data_access/text_file/FileStationDataAccessObject.java @@ -0,0 +1,98 @@ +package data_access.text_file; + +import data_access.API.GOStationApiClass; +import entity.Train; +import entity.Vehicle; +import entity.StationFactory; +import use_case.StationInfo.StationInfoDataAccessInterface; +import use_case.search.SearchDataAccessInterface; + +import java.io.*; +import java.util.*; // resolves import for List and ArrayList +import java.util.HashMap; +import java.util.Map; +import entity.Station; + +// We will name it as FileStationDataAccessObject for now. When we start to implement vehicles, we will change it as requires +// We might need to create different DA0 java files based on what data we are pulling (station, train or bus) +public class FileStationDataAccessObject implements SearchDataAccessInterface, StationInfoDataAccessInterface { + private final File stationTxtFile; + private final Map stations = new HashMap<>(); + private final StationFactory stationFactory; + + private final GOStationApiClass goStationApiClass; + + public FileStationDataAccessObject(String txtFilePath, StationFactory stationFactory, GOStationApiClass goStationApiClass) throws IOException { + + this.stationFactory = stationFactory; + this.goStationApiClass = goStationApiClass; + stationTxtFile = new File(txtFilePath); + + // Reading the provided txt file that has a path specified by attribute txtFilePath + try(BufferedReader reader = new BufferedReader(new FileReader(stationTxtFile))){ + String line; + reader.readLine(); // call the readline() method once outside the loop as we do not want to read the first line of txt file, since that line contains just the headers. + while((line = reader.readLine()) != null) { + + String[] parsedStationInfo = line.split(","); //splitting by "," since information in txt file is seperated by "," + String parsedStationName = parsedStationInfo[1]; + String parsedStationID = parsedStationInfo[0]; + + String parsedStationParentLine = parsedStationInfo[5]; + Float parsedStationLatitude = Float.valueOf(parsedStationInfo[2]); // converting string type to float object type. Through potential autoboxing, this float object type is converted to primitative type. + Float parsedStationLongtitude = Float.valueOf(parsedStationInfo[3]); + + List parsedStationAmenities = new ArrayList(); //This is empty at the time of reading txt file, this will be populated through API calls + List parsedStationVehicles = new ArrayList(); //This is empty at the time of reading txt file, this will be populated through API calls + + // For reference, here are the order of arguments in order to pass into stationFactory.create(): + //(name, stationId, parentLine, latitude, longitude, amenitiesList, incomingVehicles) + Station station = stationFactory.create(parsedStationName, parsedStationID, parsedStationParentLine, parsedStationLatitude, parsedStationLongtitude, parsedStationAmenities, parsedStationVehicles); + + stations.put(parsedStationName, station); + } + } + } + @Override + public Station getStation (String inputStationName) { + Station incompleteStationObj = stations.get(inputStationName); + + // Assigning the Station obj's amenitiesList attribute to a valid value + List retrievedStationAmenities = getStationAmenities(inputStationName); + incompleteStationObj.setAmenitiesList(retrievedStationAmenities); + + //TODO: Do something similar for incomingVehicles? + + return stations.get(inputStationName); + } + + @Override + public String getStationId(String inputStationName) { + return (stations.get(inputStationName)).getId(); + } + + @Override + public String getStationParentLine(String inputStationName) { + + return (stations.get(inputStationName)).getParentLine(); + } + + public String getStationID (String inputStationName) { + + return (stations.get(inputStationName)).getId(); + } + + @Override + public List getStationAmenities(String inputStationName) { + //TODO: Need to save this information in the actual Station objects such that we don't duplicate API calls + String stationID = getStationID(inputStationName); + List stationAmenitiesList = goStationApiClass.retrieveStationAmenities(stationID); + return stationAmenitiesList; + } + + public boolean stationExist(String identifier){ + return stations.containsKey(identifier); //TODO: MASSIVE ASSUMPTION HERE THAT THE USER types input in correct casing + // May need to resolve this by converting user input to lowercase -> then comparing to txt names (which will also be compared in lowercase form?) + + } +} diff --git a/src/entity/Station.java b/src/entity/Station.java index 2bf9c48..7d42bec 100644 --- a/src/entity/Station.java +++ b/src/entity/Station.java @@ -8,8 +8,11 @@ public class Station implements StationInterface{ private final String parentLine; private final float latitude; private final float longitude; - private final List amenitiesList; - private final List incomingVehicles; + private List amenitiesList; //TODO: Due to this variable being assigned a valid value AFTER initial text file is read, we need to make this non-final. But this violates CAE? + + private final List incomingVehicles; + // used to be: private final List incomingVehicles; + // will change to the original one after implementing Vehicle class. /** * Requirement: stationId and name exist. @@ -22,7 +25,8 @@ public class Station implements StationInterface{ * @param incomingVehicles */ - Station(String name, String stationId, String parentLine, float latitude, float longitude, List amenitiesList, List incomingVehicles) { + Station(String name, String stationId, String parentLine, float latitude, float longitude, List amenitiesList, List incomingVehicles) { + //String name, String stationId, String parentLine, float latitude, float longitude, List amenitiesList, List incomingVehicles this.stationId = stationId; this.name = name; this.parentLine = parentLine; @@ -62,8 +66,15 @@ public List getAmenitiesList() { return amenitiesList; } + public void setAmenitiesList(List stationAmenitiesList) { + this.amenitiesList = stationAmenitiesList; + } + @Override - public List getIncomingVehicles() { + public List getIncomingVehicles() { return incomingVehicles; } +// public List getIncomingVehicles() { +// return incomingVehicles; +// } } \ No newline at end of file diff --git a/src/entity/StationFactory.java b/src/entity/StationFactory.java index fbc20e0..88bfc7f 100644 --- a/src/entity/StationFactory.java +++ b/src/entity/StationFactory.java @@ -4,16 +4,17 @@ public class StationFactory { /* - TODO: Review Notes about implementation: + Notes about implementation: - TODO: 1. Taking a look at the CAE homework (Week 3), the file CommonUserFactory implements an interface called UserFactory. + 1. Taking a look at the CAE homework (Week 3), the file CommonUserFactory implements an interface called UserFactory. Do we need something similar for ours? I suspect note since we will likely need to create 2 other factory classes TrainFactory and BusFactory/ - TODO: 2. I believe the intended purpose of StationFactory is to provide a create method that could "construct" instances of (in this case, Station) + 2. I believe the intended purpose of StationFactory is to provide a create method that could "construct" instances of (in this case, Station) without having us to call the actual Station class constructor. That way, we can keep the constructor as "default access" rather than making it "public" for files like FileStationDataAccessObject.java to use (making it public will break CAE principles). */ - public Station create (String name, String stationId, String parentLine, float latitude, float longitude, List amenitiesList, List incomingVehicles) { + public Station create (String name, String stationId, String parentLine, float latitude, float longitude, List amenitiesList, List incomingVehicles) { return new Station (name, stationId, parentLine, latitude, longitude, amenitiesList, incomingVehicles); } + } diff --git a/src/entity/StationInterface.java b/src/entity/StationInterface.java index bca8570..6682fc6 100644 --- a/src/entity/StationInterface.java +++ b/src/entity/StationInterface.java @@ -16,6 +16,6 @@ public interface StationInterface { List getAmenitiesList(); - List getIncomingVehicles(); + List getIncomingVehicles(); } diff --git a/src/entity/Train.java b/src/entity/Train.java index 0e7fc8d..4199723 100644 --- a/src/entity/Train.java +++ b/src/entity/Train.java @@ -1,2 +1,83 @@ -package entity;public class Train { +package entity; +public class Train implements TrainInterface{ + + private final String lineName; //parent line name + private final String lineNumber; //lineNumber = lineCode + private final String trainName; + // train display name + private final float latitude; + private final float longitude; + private final String scheduledTime; + private final String departureTime; + private final String tripNumber; + private final String delay; + + /** + * Requirement: Train name and trainNumber exist. + * Note: trainNumber is tripNumber in GOtrainApiClass + * @param lineName + * @param lineNumber + * @param trainName + * @param latitude + * @param longitude + * @param scheduledTime + * @param departureTime + * @param tripNumber + * @param delay + */ + Train(String lineName, String lineNumber, String trainName, float latitude, float longitude, + String scheduledTime, String departureTime, String tripNumber, String delay) { + this.lineName = lineName; + this.lineNumber = lineNumber; + this.trainName = trainName; + this.latitude = latitude; + this.longitude = longitude; + this.scheduledTime = scheduledTime; + this.departureTime = departureTime; + this.tripNumber = tripNumber; + this.delay = delay; + } + + @Override + public String getLineNumber() { + return lineNumber; + } + + @Override + public String getLineName() { + return lineName; + } + + @Override + public float getLatitude() { + return latitude; + } + + @Override + public float getLongitude() { + return longitude; + } + + @Override + public String getTrainName() { + return trainName; + } + + @Override + public String getScheduledTime() { + return scheduledTime; + } + + @Override + public String getDepartureTime() { + return departureTime; + } + + @Override + public String getTripNumber(){return tripNumber;} + + @Override + public String getDelay() { + return delay; + } } diff --git a/src/entity/TrainFactory.java b/src/entity/TrainFactory.java index f1d57f3..e2ae191 100644 --- a/src/entity/TrainFactory.java +++ b/src/entity/TrainFactory.java @@ -1,2 +1,15 @@ -package entity;public class TrainFactory { +package entity; + +import java.util.List; + +public class TrainFactory { + /** + * Provide a create method that could "construct" instances of Train without having us to call + * the actual Train class constructor. + **/ + public Train create (String lineName, String lineNumber, String trainName, float latitude, float longitude, + String scheduledTime, String departureTime, String tripNumber, String delay) { + return new Train (lineName, lineNumber, trainName, latitude, longitude, + scheduledTime, departureTime, tripNumber, delay); + } } diff --git a/src/entity/TrainInterface.java b/src/entity/TrainInterface.java new file mode 100644 index 0000000..3b1db75 --- /dev/null +++ b/src/entity/TrainInterface.java @@ -0,0 +1,19 @@ +package entity; + +public interface TrainInterface { + String getLineNumber(); + + String getLineName(); + + float getLatitude(); + + float getLongitude(); + + String getTrainName(); + + String getScheduledTime(); + String getDepartureTime(); + String getTripNumber(); + + String getDelay(); +} diff --git a/src/interface_adapter/search/SearchPresenter.java b/src/interface_adapter/search/SearchPresenter.java index 89b439c..ad6e9c9 100644 --- a/src/interface_adapter/search/SearchPresenter.java +++ b/src/interface_adapter/search/SearchPresenter.java @@ -19,27 +19,30 @@ public SearchPresenter(SearchViewModel searchViewModel, StationInfoViewModel sta public void prepareSuccessView(SearchOutputData response){ String retrieveStationName = response.getStationName(); - // TODO: Left NOTE FOR TESTING PURPOSES ONLY. Delete in final implementation - + // NOTE: FOR TESTING PURPOSES ONLY: // In the above, changing the arguments to String retrieveStationParentLine = response.getStationParentLine(); would display the Parent line of station // Step 1: Resetting the station error value in the searchState to be null (in case any failed search attempts came before this "successful" attempt) SearchState searchState = searchViewModel.getState(); searchState.setStateStationName(retrieveStationName); - + searchState.setStateStationError(null); + // TODO [Polish implementation...]: Explanation of the above line // This line sets the state's station error attribute value to null. // This happens ONLY IF the prepareSuccessView has been triggered // This is because should there be an error message stored in the state, we want to CLEAR THAT to display the success view - searchState.setStateStationError(null); + // CONFIRMED BY PROFESSOR: This implementation is fine // Step 2: Setting values in the SearchPanelView StationInfoState stationInfoState = stationInfoViewModel.getState(); stationInfoState.setStateStationName(retrieveStationName); - + //System.out.println("Station info state station name" + stationInfoState.getStateStationName()); //(For debugging purpose) stationInfoViewModel.firePropertyChanged(); viewManagerModel.setActiveView(stationInfoViewModel.getViewName()); viewManagerModel.firePropertyChanged(); + + //TODO #3: Do we need to call setState() methods in general? + } public void prepareFailView(String stationRetrievalError){ @@ -47,4 +50,5 @@ public void prepareFailView(String stationRetrievalError){ searchState.setStateStationError(stationRetrievalError); searchViewModel.firePropertyChanged(); } + } diff --git a/src/interface_adapter/search/SearchState.java b/src/interface_adapter/search/SearchState.java index 803c086..acefb69 100644 --- a/src/interface_adapter/search/SearchState.java +++ b/src/interface_adapter/search/SearchState.java @@ -4,8 +4,7 @@ public class SearchState { private String stationName; private String stationError; - //TODO: We will leave this "copy" constructor here for now (where we have one that "copies" state) - // If this is still unused at the end of the project, delete. + //TODO: Do we need to set up our constructors like this (where we have one that "copies" state) public SearchState(SearchState copy) { stationName = copy.stationName; stationError = copy.stationError; @@ -28,4 +27,6 @@ public String getStateStationError() { public void setStateStationError(String stationError) { this.stationError = stationError; } + + } diff --git a/src/interface_adapter/show_incoming_vehicles/ShowIncomingVehiclesState.java b/src/interface_adapter/show_incoming_vehicles/ShowIncomingVehiclesState.java index 905764a..46e5f84 100644 --- a/src/interface_adapter/show_incoming_vehicles/ShowIncomingVehiclesState.java +++ b/src/interface_adapter/show_incoming_vehicles/ShowIncomingVehiclesState.java @@ -1,4 +1,31 @@ package interface_adapter.show_incoming_vehicles; +import interface_adapter.station_info.StationInfoState; + +import java.util.List; + public class ShowIncomingVehiclesState { + private String stationName; + private List> incomingVehiclesInfo; //TODO: Tentative type for incomingVehiclesInfo + + //TODO: If this "copy" constructor is unused, delete in the final project implementation + public ShowIncomingVehiclesState(ShowIncomingVehiclesState copy) { + stationName = copy.stationName; + incomingVehiclesInfo = copy.incomingVehiclesInfo; + } + + public ShowIncomingVehiclesState() {} + + public String getStateStationName(){return stationName;} + + public void setStateStationName(String stationName) { + this.stationName = stationName; + } + + //TODO: This is a MOCK change to the state, where the incomingVehiclesList is converted to a string format + // Ideally, we want to seperate and print each entry + public List> getStateIncomingVehiclesList() {return incomingVehiclesInfo;} + public void setStateIncomingVehiclesList(List> incomingVehiclesInfoList){ + this.incomingVehiclesInfo = incomingVehiclesInfoList; + } } diff --git a/src/interface_adapter/show_incoming_vehicles/ShowIncomingVehiclesViewModel.java b/src/interface_adapter/show_incoming_vehicles/ShowIncomingVehiclesViewModel.java index 5d210ee..d513d25 100644 --- a/src/interface_adapter/show_incoming_vehicles/ShowIncomingVehiclesViewModel.java +++ b/src/interface_adapter/show_incoming_vehicles/ShowIncomingVehiclesViewModel.java @@ -1,4 +1,35 @@ package interface_adapter.show_incoming_vehicles; -public class ShowIncomingVehiclesViewModel { +import interface_adapter.ViewModel; +import interface_adapter.search.SearchState; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +public class ShowIncomingVehiclesViewModel extends ViewModel { + public final String TITLE_LABEL = "Station Incoming Vehicles View"; + + private ShowIncomingVehiclesState state = new ShowIncomingVehiclesState(); + + + public ShowIncomingVehiclesViewModel() {super("show_incoming_vehicles");} + + public void setState(ShowIncomingVehiclesState state) { + this.state = state; + } + + private final PropertyChangeSupport support = new PropertyChangeSupport(this); + + public void firePropertyChanged() { + support.firePropertyChange("state", null, this.state); + } + + @Override + public void addPropertyChangeListener(PropertyChangeListener listener) { + support.addPropertyChangeListener(listener); + } + + public ShowIncomingVehiclesState getState() { + return state; + } } diff --git a/src/interface_adapter/station_info/StationInfoController.java b/src/interface_adapter/station_info/StationInfoController.java new file mode 100644 index 0000000..38f03ad --- /dev/null +++ b/src/interface_adapter/station_info/StationInfoController.java @@ -0,0 +1,17 @@ +package interface_adapter.station_info; + +import use_case.StationInfo.StationInfoInputBoundary; +import use_case.StationInfo.StationInfoInputData; + +public class StationInfoController { + final StationInfoInputBoundary stationInfoUseCaseInteractor; + + public StationInfoController(StationInfoInputBoundary stationInfoUseCaseInteractor) { + this.stationInfoUseCaseInteractor = stationInfoUseCaseInteractor; + } + + public void execute(String stationName) { + StationInfoInputData stationInfoInputData = new StationInfoInputData(stationName); + stationInfoUseCaseInteractor.execute(stationInfoInputData); + } +} diff --git a/src/interface_adapter/station_info/StationInfoPresenter.java b/src/interface_adapter/station_info/StationInfoPresenter.java new file mode 100644 index 0000000..b065921 --- /dev/null +++ b/src/interface_adapter/station_info/StationInfoPresenter.java @@ -0,0 +1,37 @@ +package interface_adapter.station_info; + +import interface_adapter.ViewManagerModel; +import interface_adapter.show_incoming_vehicles.ShowIncomingVehiclesState; +import interface_adapter.show_incoming_vehicles.ShowIncomingVehiclesViewModel; +import use_case.StationInfo.StationInfoOutputBoundary; +import use_case.StationInfo.StationInfoOutputData; + +public class StationInfoPresenter implements StationInfoOutputBoundary { + private final StationInfoViewModel stationInfoViewModel; + private final ShowIncomingVehiclesViewModel showIncomingVehiclesViewModel; + private final ViewManagerModel viewManagerModel; + + public StationInfoPresenter(StationInfoViewModel stationInfoViewModel, + ShowIncomingVehiclesViewModel showIncomingVehiclesViewModel, + ViewManagerModel viewManagerModel) { + this.stationInfoViewModel = stationInfoViewModel; + this.showIncomingVehiclesViewModel = showIncomingVehiclesViewModel; + this.viewManagerModel = viewManagerModel; + } + @Override + public void prepareSuccessView(StationInfoOutputData response) { + StationInfoState stationInfoState = stationInfoViewModel.getState(); + stationInfoState.setStateStationName(response.getStationName()); + + // On success, switch to show incoming vehicles view. + + ShowIncomingVehiclesState showIncomingVehiclesState = showIncomingVehiclesViewModel.getState(); + showIncomingVehiclesState.setStateStationName(response.getStationName()); + showIncomingVehiclesState.setStateIncomingVehiclesList(response.getStationIncomingVehiclesInfo()); + this.showIncomingVehiclesViewModel.setState(showIncomingVehiclesState); + showIncomingVehiclesViewModel.firePropertyChanged(); + + viewManagerModel.setActiveView(showIncomingVehiclesViewModel.getViewName()); + viewManagerModel.firePropertyChanged(); + } +} diff --git a/src/interface_adapter/station_info/StationInfoState.java b/src/interface_adapter/station_info/StationInfoState.java index 27105e0..c0ea2fa 100644 --- a/src/interface_adapter/station_info/StationInfoState.java +++ b/src/interface_adapter/station_info/StationInfoState.java @@ -5,6 +5,7 @@ public class StationInfoState { //Purpose of class: Contains the information we need to have during the station info state (the state after successful user input is received) private String stationName; + private String stationAmenities; //TODO: Tentatively, it is a String type //TODO: If this "copy" constructor is unused, delete in the final project implementation public StationInfoState(StationInfoState copy) { @@ -22,4 +23,11 @@ public void setStateStationName(String stationName) { this.stationName = stationName; } + //TODO: This is a MOCK change to the state, where the stationAmenitiesList is converted to a string format + // Ideally, we want to seperate and print each entry + public String getStateStationAmenities() {return stationAmenities;} + public void setStateStationAmenities(String stationAmenities) { + this.stationAmenities = stationAmenities; + } + } diff --git a/src/interface_adapter/station_info/StationInfoViewModel.java b/src/interface_adapter/station_info/StationInfoViewModel.java index 36224d8..7eaeeb9 100644 --- a/src/interface_adapter/station_info/StationInfoViewModel.java +++ b/src/interface_adapter/station_info/StationInfoViewModel.java @@ -9,6 +9,8 @@ public class StationInfoViewModel extends ViewModel { public final String TITLE_LABEL = "Station Info View"; + public final String SHOW_INCOMING_VEHICLES_BUTTON_LABEL = "Show Incoming Vehicles"; + private StationInfoState state = new StationInfoState(); public StationInfoViewModel() { diff --git a/src/use_case/StationInfo/StationInfoDataAccessInterface.java b/src/use_case/StationInfo/StationInfoDataAccessInterface.java new file mode 100644 index 0000000..e0b91db --- /dev/null +++ b/src/use_case/StationInfo/StationInfoDataAccessInterface.java @@ -0,0 +1,11 @@ +package use_case.StationInfo; + +import entity.Station; + +public interface StationInfoDataAccessInterface { + + Station getStation(String inputStationName); + + String getStationId(String inputStationName); + // We might not need this since we could get station id from getStation(). +} diff --git a/src/use_case/StationInfo/StationInfoInputBoundary.java b/src/use_case/StationInfo/StationInfoInputBoundary.java new file mode 100644 index 0000000..f047318 --- /dev/null +++ b/src/use_case/StationInfo/StationInfoInputBoundary.java @@ -0,0 +1,5 @@ +package use_case.StationInfo; + +public interface StationInfoInputBoundary { + void execute(StationInfoInputData stationInfoInputData); +} diff --git a/src/use_case/StationInfo/StationInfoInputData.java b/src/use_case/StationInfo/StationInfoInputData.java new file mode 100644 index 0000000..e6343a3 --- /dev/null +++ b/src/use_case/StationInfo/StationInfoInputData.java @@ -0,0 +1,9 @@ +package use_case.StationInfo; + +public class StationInfoInputData { + final private String stationName; + + public StationInfoInputData(String stationName) {this.stationName = stationName;} + + String getStationName() {return stationName;} +} diff --git a/src/use_case/StationInfo/StationInfoInteractor.java b/src/use_case/StationInfo/StationInfoInteractor.java new file mode 100644 index 0000000..aca7df5 --- /dev/null +++ b/src/use_case/StationInfo/StationInfoInteractor.java @@ -0,0 +1,59 @@ +package use_case.StationInfo; + +import entity.Station; +import entity.Vehicle; +import entity.VehicleFactory; +import use_case.search.SearchOutputData; +import entity.Train; + +import java.util.ArrayList; +import java.util.List; + +public class StationInfoInteractor implements StationInfoInputBoundary{ + final StationInfoDataAccessInterface stationInfoDataAccessObject; + final StationInfoOutputBoundary stationInfoPresenter; + + //TODO: need to consider if we need vehicleFactory + public StationInfoInteractor(StationInfoDataAccessInterface stationInfoDataAccessInterface, + StationInfoOutputBoundary stationInfoOutputBoundary) { + this.stationInfoDataAccessObject = stationInfoDataAccessInterface; + this.stationInfoPresenter = stationInfoOutputBoundary; + } + + @Override + public void execute(StationInfoInputData stationInfoInputData) { + // Creating a Station object using the station factory based on the name that the user input + Station station = stationInfoDataAccessObject.getStation(stationInfoInputData.getStationName()); + + // Packaging key details from the above Station object into a SearchOutputData object + List incomingVehicles = station.getIncomingVehicles(); + // List will change into List after implementing Vehicle class. + List> incomingVehiclesInfo = new ArrayList<>(); + + // We want to show train display name, scheduled time, departure time and delay + for (int i = 0; i < incomingVehicles.size(); i++) { + List vehicleinfo = new ArrayList<>(); + String vehicleName = incomingVehicles.get(i).getTrainName(); + String vehicleScheduledTime = incomingVehicles.get(i).getScheduledTime(); + String vehicleDepartureTime = incomingVehicles.get(i).getDepartureTime(); + String vehicleDelay = incomingVehicles.get(i).getDelay(); + vehicleinfo.add(vehicleName); + vehicleinfo.add(vehicleScheduledTime); + vehicleinfo.add(vehicleDepartureTime); + vehicleinfo.add(vehicleDelay); + incomingVehiclesInfo.add(vehicleinfo); + } + +// String incomingVehicleListAsString; +// for (List i : incomingVehiclesInfo) { +// incomingVehicleListAsString = String.join("\n", i); +// } +// Do not need to convert to String + + StationInfoOutputData stationInfoOutputData = new StationInfoOutputData(station.getName(), incomingVehiclesInfo); + + // return the output data to the user + stationInfoPresenter.prepareSuccessView(stationInfoOutputData); + } + +} diff --git a/src/use_case/StationInfo/StationInfoOutputBoundary.java b/src/use_case/StationInfo/StationInfoOutputBoundary.java new file mode 100644 index 0000000..fcb2f66 --- /dev/null +++ b/src/use_case/StationInfo/StationInfoOutputBoundary.java @@ -0,0 +1,7 @@ +package use_case.StationInfo; + +public interface StationInfoOutputBoundary { + void prepareSuccessView(StationInfoOutputData stationInfoOutputData); + +// void parepareFailView(String error); // TODO: Implement later +} diff --git a/src/use_case/StationInfo/StationInfoOutputData.java b/src/use_case/StationInfo/StationInfoOutputData.java new file mode 100644 index 0000000..83e95fc --- /dev/null +++ b/src/use_case/StationInfo/StationInfoOutputData.java @@ -0,0 +1,23 @@ +package use_case.StationInfo; + +import java.util.List; + +public class StationInfoOutputData { + private final String stationName; + private final List> stationIncomingVehiclesInfo; + // the nested List is a list including parent line code, parent line name, vehicle type, + // vehicle display name, scheduled departure time, actual departure time, trip number and delay + + public StationInfoOutputData(String stationName, + List> stationIncomingVehiclesInfo) { + this.stationName = stationName; + this.stationIncomingVehiclesInfo = stationIncomingVehiclesInfo; + } + + public String getStationName() {return stationName;} + + public List> getStationIncomingVehiclesInfo() {return stationIncomingVehiclesInfo;} + + + +} diff --git a/src/use_case/search/SearchDataAccessInterface.java b/src/use_case/search/SearchDataAccessInterface.java index 3c70c0d..d9c6939 100644 --- a/src/use_case/search/SearchDataAccessInterface.java +++ b/src/use_case/search/SearchDataAccessInterface.java @@ -5,14 +5,13 @@ import java.util.List; public interface SearchDataAccessInterface { - // Method stationExist() added to check whether the station whose name the user inputs ACTUALLY exists in the data object - boolean stationExist(String identifier); - - // Getting Station object based on input station name for team use case - Station getStation(String inputStationName); + // new method added to check whether the station whose name the user inputs ACTUALLY exists in the data object + boolean stationExist(String identifier); + Station getStation(String inputStationName); // attempting to only get proper station name for base implementation of team use case // used to be: Station getStation(); above String getStationParentLine(String inputStationName); List getStationAmenities(String inputStationName); -} \ No newline at end of file + +} diff --git a/src/use_case/search/SearchInteractor.java b/src/use_case/search/SearchInteractor.java index 2939fb1..14753e1 100644 --- a/src/use_case/search/SearchInteractor.java +++ b/src/use_case/search/SearchInteractor.java @@ -1,6 +1,7 @@ package use_case.search; import entity.Station; +import java.util.List; public class SearchInteractor implements SearchInputBoundary { final SearchDataAccessInterface stationDataAccessObject; @@ -19,8 +20,10 @@ public void execute(SearchInputData searchInputData) { // Creating a Station object using the station factory based on the name that the user input Station station = stationDataAccessObject.getStation(searchInputData.getStationName()); - // Packaging key details from the above Station object into a SearchOutputData object - SearchOutputData searchOutputData = new SearchOutputData(station.getName(), station.getParentLine(), station.getAmenitiesList()); + // Packaging key details from the above Station object into a SearchOutputData object + List amenitiesList = station.getAmenitiesList(); + String amenitiesListAsString = String.join(", ", amenitiesList); + SearchOutputData searchOutputData = new SearchOutputData(station.getName(), station.getParentLine(), amenitiesListAsString); // return the output data to the user stationPresenter.prepareSuccessView(searchOutputData); diff --git a/src/use_case/search/SearchOutputData.java b/src/use_case/search/SearchOutputData.java index 99cb065..ec1b8e5 100644 --- a/src/use_case/search/SearchOutputData.java +++ b/src/use_case/search/SearchOutputData.java @@ -5,7 +5,7 @@ public class SearchOutputData { private final String stationName; private final String stationParentLine; - private final List stationAmenities; + private final String stationAmenities; //TODO: TEMP CHANGE TO STRING TYPE // After clicking "Find Info" button, the app directs us to Panel #2 // We still need to figure out Amenities output @@ -15,7 +15,7 @@ public class SearchOutputData { * @param stationParentLine * @param stationAmenities */ - public SearchOutputData(String stationName, String stationParentLine, List stationAmenities) { + public SearchOutputData(String stationName, String stationParentLine, String stationAmenities) { this.stationName = stationName; this.stationParentLine = stationParentLine; this.stationAmenities = stationAmenities; @@ -25,5 +25,5 @@ public SearchOutputData(String stationName, String stationParentLine, List getStationAmenities() {return stationAmenities;} + public String getStationAmenities() {return stationAmenities;} } diff --git a/src/view/SearchPanelView.java b/src/view/SearchPanelView.java index 3733533..90ada75 100644 --- a/src/view/SearchPanelView.java +++ b/src/view/SearchPanelView.java @@ -43,10 +43,9 @@ public SearchPanelView(SearchViewModel searchViewModel, SearchController searchC new ActionListener() { public void actionPerformed(ActionEvent evt) { if (evt.getSource().equals(submit)) { - // Lines 46 -47 fetches the current CORRECT user input from the text box... - // ... so that the correct, up-to-date user input is fetched from the search bar for processing in the controller. - SearchState currentStateOfInput = searchViewModel.getState(); - currentStateOfInput.setStateStationName(stationInputField.getText()); + //TODO: REVIEW PROPOSED CHANGE. Liens 46 -47 fetches the current CORRECT user input from the text box, so that the correct, up-to-date user input is fetched from the search bar for processing in the controller. + SearchState currentStateOfInput = searchViewModel.getState(); + currentStateOfInput.setStateStationName(stationInputField.getText()); SearchState currentState = searchViewModel.getState(); searchController.execute( @@ -99,4 +98,6 @@ else if (state.getStateStationName() != null) { } } -} \ No newline at end of file +} + + diff --git a/src/view/ShowIncomingVehiclesView.java b/src/view/ShowIncomingVehiclesView.java new file mode 100644 index 0000000..20329e4 --- /dev/null +++ b/src/view/ShowIncomingVehiclesView.java @@ -0,0 +1,53 @@ +package view; + +import interface_adapter.show_incoming_vehicles.ShowIncomingVehiclesState; +import interface_adapter.show_incoming_vehicles.ShowIncomingVehiclesViewModel; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +public class ShowIncomingVehiclesView extends JPanel implements ActionListener, PropertyChangeListener { + public final String viewName = "show_incoming_vehicles"; + private final ShowIncomingVehiclesViewModel showIncomingVehiclesViewModel; + JLabel stationName; + JLabel stationIncomingVehicles; + + public ShowIncomingVehiclesView(ShowIncomingVehiclesViewModel showIncomingVehiclesViewModel) { + this.showIncomingVehiclesViewModel = showIncomingVehiclesViewModel; + this.showIncomingVehiclesViewModel.addPropertyChangeListener(this); + + JLabel title = new JLabel("Incoming Vehicles Screen"); + title.setAlignmentX(Component.CENTER_ALIGNMENT); + + JLabel stationNameLabel = new JLabel("Station name: "); + stationName = new JLabel(); + + JLabel stationIncomingVehiclesLabel = new JLabel("Incoming Vehicles: "); + stationIncomingVehicles = new JLabel(); + + this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + this.add(title); + this.add(stationNameLabel); + this.add(stationName); + this.add(stationIncomingVehiclesLabel); + this.add(stationIncomingVehicles); + } + + @Override + public void actionPerformed(ActionEvent e) { + System.out.println("Click " + e.getActionCommand()); + } + @Override + public void propertyChange(PropertyChangeEvent evt) { + //System.out.println("Reached"); //Commented out for testing purposes + ShowIncomingVehiclesState state = (ShowIncomingVehiclesState) evt.getNewValue(); + stationName.setText(state.getStateStationName()); + stationIncomingVehicles.setText(state.getStateIncomingVehiclesList().toString()); + //TODO: Should we make incoming vehicles a String instead of a list? + } + +} diff --git a/src/view/StationInfoView.java b/src/view/StationInfoView.java index 7aa3d98..b14c10f 100644 --- a/src/view/StationInfoView.java +++ b/src/view/StationInfoView.java @@ -7,6 +7,7 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import interface_adapter.station_info.StationInfoController; import interface_adapter.station_info.StationInfoState; import interface_adapter.station_info.StationInfoViewModel; @@ -14,14 +15,16 @@ public class StationInfoView extends JPanel implements ActionListener, PropertyChangeListener{ public final String viewName = "stationInfo"; private final StationInfoViewModel stationInfoViewModel; - JLabel stationName; + final JButton show_incoming_vehicles; + private final StationInfoController stationInfoController; /** * A window with a title and a JButton. */ - public StationInfoView(StationInfoViewModel stationInfoViewModel) { + public StationInfoView(StationInfoViewModel stationInfoViewModel, StationInfoController stationInfoController) { this.stationInfoViewModel = stationInfoViewModel; + this.stationInfoController = stationInfoController; this.stationInfoViewModel.addPropertyChangeListener(this); JLabel title = new JLabel("Station info screen"); @@ -30,10 +33,31 @@ public StationInfoView(StationInfoViewModel stationInfoViewModel) { JLabel stationInfo = new JLabel("Station name: "); stationName = new JLabel(); + JPanel buttons = new JPanel(); + show_incoming_vehicles = new JButton(stationInfoViewModel.SHOW_INCOMING_VEHICLES_BUTTON_LABEL); + buttons.add(show_incoming_vehicles); + + show_incoming_vehicles.addActionListener( + // This creates an anonymous subclass of ActionListener and instantiates it. + new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (e.getSource().equals(show_incoming_vehicles)) { + StationInfoState currentState = stationInfoViewModel.getState(); + + StationInfoView.this.stationInfoController.execute( + currentState.getStateStationName() + ); + } + } + } + ); + this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); this.add(title); this.add(stationInfo); this.add(stationName); + this.add(buttons); } /** @@ -49,4 +73,5 @@ public void propertyChange(PropertyChangeEvent evt) { StationInfoState state = (StationInfoState) evt.getNewValue(); stationName.setText(state.getStateStationName()); } -} \ No newline at end of file + +} diff --git a/src/view/ViewManager.java b/src/view/ViewManager.java index 49940c0..7618ad4 100644 --- a/src/view/ViewManager.java +++ b/src/view/ViewManager.java @@ -26,4 +26,4 @@ public void propertyChange(PropertyChangeEvent evt) { cardLayout.show(views, viewModelName); } } -} \ No newline at end of file +} diff --git a/stopData.txt b/stopData.txt deleted file mode 100644 index 40e08be..0000000 Binary files a/stopData.txt and /dev/null differ diff --git a/target/classes/ApiTestFile.class b/target/classes/ApiTestFile.class index 464ffde..d2ef3cb 100644 Binary files a/target/classes/ApiTestFile.class and b/target/classes/ApiTestFile.class differ