-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathApplication.java
More file actions
347 lines (312 loc) · 12.4 KB
/
Application.java
File metadata and controls
347 lines (312 loc) · 12.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
package client;
//region LIBRARIES USED
//Java Libraries:
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.OrientationRequested;
import javax.swing.*;
import java.awt.print.PrinterException;
import java.io.*;
import java.net.Socket;
import java.text.MessageFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
//Our Classes:
import data.*;
//endregion
/**
* @author Paul Johannes Aru
* @version 0.9
* @since 2021-03-15
*/
public class Application {
//region APPLICATION VARIABLES
private Socket socket;
private ObjectOutputStream packetOutputStream;
private ObjectInputStream packetInputStream;
private Interface guiWindow;
private List<Airport> launchData;
private Airport openAirport;
private List<Route> routeData;
private boolean editMode = false;
//endregion
// Empty Application Constructor:
private Application() {}
//region CONNECT TO SERVER
/**
* Establishes a Connection to the Server.
* <p>
* Attempts to Connect to the Server. Currently
* that is set to 127.0.0.1:2000 a.k.a. the local
* system.
*
* @return Whether a Connection was Established or not.
*/
private boolean connectServer() {
disconnectServer();
guiWindow.printLog(MessageType.STATUS,"Connecting to Server..");
// Connection Succeeded:
try {
socket = new Socket("127.0.0.1", 2000);
packetOutputStream = new ObjectOutputStream(socket.getOutputStream());
packetInputStream = new ObjectInputStream(socket.getInputStream());
guiWindow.printLog(MessageType.STATUS,"Server Connected");
return true;
// Connection Failed:
} catch (IOException ex) {
Logger.getLogger(Application.class.getName()).log(Level.SEVERE, null, ex);
guiWindow.printLog(MessageType.ERROR,ex.toString());
return false;
}
}
//endregion
//region DISCONNECT FROM SERVER
/**
* Disconnects from the Server.
* <p>
* Attempts to Disconnect from the Server.
*/
public void disconnectServer() {
if (socket != null) {
guiWindow.printLog(MessageType.STATUS,"Disconnecting from the Server..");
try {
socket.close();
} catch (IOException ex) {
Logger.getLogger(Application.class.getName()).log(Level.SEVERE, null, ex);
} finally {
socket = null;
}
}
}
//endregion
//region TALK TO SERVER
/**
* Send (& Receive) a Packet to (& from) the Server.
* <p>
* Sends a Packet that contains an instruction (and
* data) to the Server and receives a Packet (with
* information) in return.
*
* @param container A Packet object to be sent.
* @return A Packet object received in return.
*/
public Packet talkToServer(Packet container) {
Packet recievedContainer = null;
// Send Data:
guiWindow.printLog(MessageType.STATUS,"Sending to Server..");
try {
packetOutputStream.writeObject(container);
} catch (IOException e) {
Logger.getLogger(Application.class.getName()).log(Level.SEVERE, null, e);
}
// Receive Data:
guiWindow.printLog(MessageType.STATUS,"Waiting for Server..");
try {
recievedContainer = (Packet) packetInputStream.readObject();
guiWindow.printLog(MessageType.STATUS,"Received Response");
} catch (IOException e) {
guiWindow.printLog(MessageType.ERROR,"(IOException) " + e);
Logger.getLogger(Application.class.getName()).log(Level.SEVERE, null, e);
} catch (ClassNotFoundException e) {
guiWindow.printLog(MessageType.ERROR,"(ClassNotFoundException) " + e);
Logger.getLogger(Application.class.getName()).log(Level.SEVERE, null, e);
}
return recievedContainer;
}
//endregion
//region FIND AIRPORT
/**
* Check if an Airport Exists in the Database.
* <p>
* This Method Looks for the Given Airport from
* a List of Airports Pre-Fetched From the Server.
*
* @param category String Specifying the Search Category ("IATA Code"/"ICAO Code"/"Airport Name").
* @param searchTerm Airport Name or other Identifying Piece of Text.
* @return Whether a Match Was Found.
*/
public boolean matchAirport(String category, String searchTerm) {
if (category.equals(SearchCategories.IATA.toString()) && searchTerm.length()!=3) {
guiWindow.printLog(MessageType.FAILURE,"IATA Code Not 3 Characters Long");
return false;
} else if (category.equals(SearchCategories.ICAO.toString()) && searchTerm.length()!=4) {
guiWindow.printLog(MessageType.FAILURE,"ICAO Code Not 4 Characters Long");
return false;
}
for (int airport=0;airport<launchData.size();airport++) {
if ((category.equals(SearchCategories.NAME.toString()) && launchData.get(airport).getName().toLowerCase().equals(searchTerm.toLowerCase())) ||
(category.equals(SearchCategories.IATA.toString()) && new String(launchData.get(airport).getIATA()).equals(searchTerm.toUpperCase())) ||
(category.equals(SearchCategories.ICAO.toString()) && new String(launchData.get(airport).getICAO()).equals(searchTerm.toUpperCase()))) {
guiWindow.printLog(MessageType.SUCCESS,"Found " + launchData.get(airport).getName() + " Airport");
guiWindow.setAirportLabel("Welcome to " + launchData.get(airport).getName() + " Airport, [" +
new String(launchData.get(airport).getIATA()) + "], [" +
new String(launchData.get(airport).getICAO()) + "], Local Time: "+
(LocalDateTime.now().plusHours((long) launchData.get(airport).getUTCoffset()).format(DateTimeFormatter.ofPattern("HH:mm"))));
openAirport = launchData.get(airport);
return true;
}
}
guiWindow.printLog(MessageType.FAILURE,"Finding Search Term");
return false;
}
//endregion
//region REQUEST ROUTES
/**
* Request Routes for the Open Airport from the Server.
* <p>
* This Method Request A List of Routes for the
* Open Airport and Sends it onwards to the
* table in the GUI Window.
*/
public void requestRoutes() {
Packet request = new Packet(Command.FETCH_ROUTES);
request.sendNumber(openAirport.getID());
Packet response = talkToServer(request);
routeData = response.receiveRouteList();
guiWindow.tableDisplayRoutes(routeData);
if (response.receiveRouteList() != null) {
guiWindow.printLog(MessageType.SUCCESS,"Received Routes for "+openAirport.getName());
} else {
guiWindow.printLog(MessageType.FAILURE, "Receiving Routes for "+openAirport.getName());
}
}
//endregion
//region ADD A ROUTE
/**
* Add a New Route.
* <p>
* This Method Request an Available Route
* ID from the Server and Creates a new
* Route Object.
*/
public void addRoute() {
Packet request = new Packet(Command.FETCH_AVAILABLE_ROUTE_ID);
Packet response = talkToServer(request);
int newID = response.receiveNumber();
routeData.add(new Route(String.valueOf(newID)));
int tableRow = guiWindow.tableAddRow();
guiWindow.tableModifyValue(tableRow,0,String.valueOf(newID));
guiWindow.printLog(MessageType.SUCCESS,"Created Route "+newID);
}
//endregion
//region REMOVE A ROUTE
/**
* Delete a Route.
* <p>
* This Method Removes a Route Based on the
* Row Number that it is Stored/Displayed on.
* @param routeRow The Row Number that Contains the Route.
*/
public void removeRoute(int routeRow) {
guiWindow.tableRemoveRow(routeRow);
guiWindow.printLog(MessageType.SUCCESS,"Removed " + routeData.get(routeRow).getAirline().getName()+"'s " +routeData.get(routeRow).getConnectingAirport().getName() + " Route");
routeData.remove(routeRow);
}
//endregion
//region SYNCHRONISE ROUTES
/**
* Send Routes to the Server for Saving.
* <p>
* This Method Requests the Server to
* update it's database to match the
* clients route info.
*/
public void saveChanges() {
Packet dispatch = new Packet(Command.DISPATCH_CHANGES);
dispatch.sendRouteList(routeData);
dispatch.sendNumber(openAirport.getID());
Packet response = talkToServer(dispatch);
if (response.receiveCondition()) {
guiWindow.printLog(MessageType.SUCCESS,"Updated Routes in Server");
} else {
guiWindow.printLog(MessageType.FAILURE,"Updating Routes in Server");
}
}
//endregion
//region SEND ROUTES TO PRINTER
/**
* Send a Table to the Printer.
* <p>
* Given a JTable, this method sends
* the table to a printer.
*
* @param guiTable The Table that Is Sent to the Printer.
*/
public void printRoutes(JTable guiTable) {
PrintRequestAttributeSet set = new HashPrintRequestAttributeSet();
set.add(OrientationRequested.LANDSCAPE);
MessageFormat header = new MessageFormat("ATC Routes for " + openAirport.getName() + " at "+ (LocalDateTime.now().plusHours((long) openAirport.getUTCoffset())));
MessageFormat footer = new MessageFormat("IATA:["+new String(openAirport.getIATA())+"], ICAO:["+new String(openAirport.getICAO())+"]");
try {
guiTable.print(JTable.PrintMode.FIT_WIDTH, header, footer, false, set, false);
guiWindow.printLog(MessageType.SUCCESS,"Printed Open Routes");
} catch (PrinterException e) {
e.printStackTrace();
guiWindow.printLog(MessageType.ERROR,"(Printing) "+e);
}
}
//endregion
//region VARIABLE ACCESS METHODS
/**
* Returns Whether User is in Edit Mode.
*
* @return Whether Edit Mode is Active or Not.
*/
public boolean getEditMode() {return editMode;}
/**
* Modifies the Edit Mode.
*
* @param mode (True/False).
*/
public void setEditMode(boolean mode) {editMode = mode;}
/**
* Returns the Local List of Routes.
*
* @return A List of Route Objects.
*/
public List<Route> getAppData() {return routeData;}
/**
* Modifies the Local List of Routes.
*
* @param tableData A List of Route Objects.
*/
public void setAppData(List<Route> tableData) {routeData = tableData;}
//endregion
//region MAIN
@SuppressWarnings("CStyleArrayDeclaration")
public static void main(String args[]) {
//Create a New Application and GUI for it:
Application clientApplication = new Application();
clientApplication.guiWindow = new Interface(clientApplication);
//Connect to Server and Download Available Airports:
while (!clientApplication.connectServer()) {
clientApplication.guiWindow.printLog(MessageType.FAILURE,"Connection Failed, Retrying in 3...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
clientApplication.guiWindow.printLog(MessageType.FAILURE,"Connection Failed, Retrying in 2...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
clientApplication.guiWindow.printLog(MessageType.FAILURE,"Connection Failed, Retrying in 1...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
clientApplication.launchData = (clientApplication.talkToServer(new Packet(Command.FETCH_ALL_AIRPORTS))).receiveAirportList();
//Display the Available Airports and Enable Search:
clientApplication.guiWindow.tableDisplayAirports(clientApplication.launchData);
clientApplication.guiWindow.printLog(MessageType.SUCCESS,"Connected, Ready to Select an Airport");
clientApplication.guiWindow.enableSearchFeature(clientApplication);
}
//endregion
}