Created new class DashboardState to better abstract the application state and added recovery of POST/PUT requests' body

This commit is contained in:
Rohit Awate 2018-02-15 12:16:23 +05:30
parent b3ffa5ecd4
commit a97a6c633c
11 changed files with 244 additions and 77 deletions

View file

@ -1,9 +0,0 @@
{
"responseAreaFont": "Liberation Mono",
"responseAreaFontSize": "18",
"connectionTimeOutEnable": "false",
"connectionTimeOut": "10000",
"connectionReadTimeOutEnable": "false",
"connectionReadTimeOut": "30000",
"theme": null
}

View file

@ -16,22 +16,21 @@
package com.rohitawate.restaurant.homewindow;
import com.rohitawate.restaurant.models.DashboardState;
import com.rohitawate.restaurant.models.requests.DataDispatchRequest;
import com.rohitawate.restaurant.util.themes.ThemeManager;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Tab;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.control.*;
import javafx.stage.FileChooser;
import javafx.stage.Window;
import javax.ws.rs.core.MediaType;
import java.io.IOException;
import java.net.URL;
import java.util.Map;
import java.util.ResourceBundle;
/*
@ -40,6 +39,8 @@ import java.util.ResourceBundle;
URL encoded and Form tabs have special FXMLs.
*/
public class BodyTabController implements Initializable {
@FXML
private TabPane bodyTabPane;
@FXML
private ComboBox<String> rawInputTypeBox;
@FXML
@ -101,7 +102,6 @@ public class BodyTabController implements Initializable {
} else if (formTab.isSelected()) {
request.setStringTuples(formDataTabController.getStringTuples());
request.setFileTuples(formDataTabController.getFileTuples());
request.setContentType(MediaType.MULTIPART_FORM_DATA);
} else if (binaryTab.isSelected()) {
request.setBody(filePathField.getText());
@ -126,4 +126,48 @@ public class BodyTabController implements Initializable {
}
filePathField.setText(filePath);
}
public void setState(DashboardState dashboardState) {
switch (dashboardState.getContentType()) {
case MediaType.TEXT_PLAIN:
rawInputArea.setText(dashboardState.getBody());
rawInputTypeBox.getSelectionModel().select("PLAIN TEXT");
bodyTabPane.getSelectionModel().select(rawTab);
break;
case MediaType.APPLICATION_JSON:
rawInputArea.setText(dashboardState.getBody());
rawInputTypeBox.getSelectionModel().select("JSON");
bodyTabPane.getSelectionModel().select(rawTab);
break;
case MediaType.APPLICATION_XML:
rawInputArea.setText(dashboardState.getBody());
rawInputTypeBox.getSelectionModel().select("XML");
bodyTabPane.getSelectionModel().select(rawTab);
break;
case MediaType.TEXT_HTML:
rawInputArea.setText(dashboardState.getBody());
rawInputTypeBox.getSelectionModel().select("HTML");
bodyTabPane.getSelectionModel().select(rawTab);
break;
case MediaType.MULTIPART_FORM_DATA:
// For file tuples
for (Map.Entry entry : dashboardState.getFileTuples().entrySet())
formDataTabController.addFileField(entry.getKey().toString(), entry.getValue().toString());
// For string tuples
for (Map.Entry entry : dashboardState.getStringTuples().entrySet())
formDataTabController.addStringField(entry.getKey().toString(), entry.getValue().toString());
bodyTabPane.getSelectionModel().select(formTab);
break;
case MediaType.APPLICATION_OCTET_STREAM:
filePathField.setText(dashboardState.getBody());
bodyTabPane.getSelectionModel().select(binaryTab);
break;
case MediaType.APPLICATION_FORM_URLENCODED:
for (Map.Entry entry : dashboardState.getStringTuples().entrySet())
urlTabController.addField(entry.getKey().toString(), entry.getValue().toString());
bodyTabPane.getSelectionModel().select(urlTab);
break;
}
}
}

View file

@ -18,10 +18,10 @@ package com.rohitawate.restaurant.homewindow;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXSnackbar;
import com.rohitawate.restaurant.exceptions.UnreliableResponseException;
import com.rohitawate.restaurant.models.DashboardState;
import com.rohitawate.restaurant.models.requests.DELETERequest;
import com.rohitawate.restaurant.models.requests.DataDispatchRequest;
import com.rohitawate.restaurant.models.requests.GETRequest;
import com.rohitawate.restaurant.models.requests.RestaurantRequest;
import com.rohitawate.restaurant.models.responses.RestaurantResponse;
import com.rohitawate.restaurant.requestsmanager.DELETERequestManager;
import com.rohitawate.restaurant.requestsmanager.DataDispatchRequestManager;
@ -46,10 +46,7 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.*;
public class DashboardController implements Initializable {
@FXML
@ -103,13 +100,13 @@ public class DashboardController implements Initializable {
IOE.printStackTrace();
}
// Select GET by default
httpMethodBox.getSelectionModel().select("GET");
responseBox.getChildren().remove(0);
promptLayer.setVisible(true);
httpMethodBox.getItems().addAll(httpMethods);
// Selects GET by default
httpMethodBox.getSelectionModel().select(0);
paramsControllers = new ArrayList<>();
appendedParams = new ArrayList<>();
addParamField(); // Adds a blank param field
@ -200,7 +197,7 @@ public class DashboardController implements Initializable {
}
DataDispatchRequest dataDispatchRequest =
(DataDispatchRequest) bodyTabController.getBasicRequest(httpMethodBox.getValue());
bodyTabController.getBasicRequest(httpMethodBox.getValue());
dataDispatchRequest.setTarget(addressField.getText());
dataDispatchRequest.setHeaders(headerTabController.getHeaders());
@ -343,12 +340,43 @@ public class DashboardController implements Initializable {
}
}
private HashMap<String, String> getParams() {
HashMap<String, String> params = new HashMap<>();
for (StringKeyValueFieldController controller : paramsControllers)
params.put(controller.getHeader().getKey(), controller.getHeader().getValue());
return params;
}
@FXML
private void addParamField() {
addParamField("", "");
}
// Adds a new URL-parameter field
private void addParamField(String key, String value) {
/*
Re-uses previous field if it is empty,
else loads a new one.
*/
if (paramsControllers.size() > 0) {
StringKeyValueFieldController previousController = paramsControllers.get(paramsControllers.size() - 1);
if (previousController.isKeyFieldEmtpy() &&
previousController.isValueFieldEmpty()) {
previousController.setKeyField(key);
previousController.setValueField(value);
return;
}
}
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/homewindow/StringKeyValueField.fxml"));
Parent headerField = loader.load();
StringKeyValueFieldController controller = loader.getController();
controller.setKeyField(key);
controller.setValueField(value);
paramsControllers.add(controller);
paramsBox.getChildren().add(headerField);
} catch (IOException e) {
@ -360,34 +388,55 @@ public class DashboardController implements Initializable {
return addressField.textProperty();
}
// Returns the current state of the Dashboard
public RestaurantRequest getState() {
/**
* Returns the current state of the Dashboard
*
* @return DashboardState - Current state of the Dashboard
*/
public DashboardState getState() {
DashboardState dashboardState = null;
try {
switch (httpMethodBox.getValue()) {
case "GET":
GETRequest getRequest = new GETRequest(addressField.getText());
getRequest.setHeaders(headerTabController.getHeaders());
return getRequest;
case "POST":
case "PUT":
DataDispatchRequest dataDispatchRequest = bodyTabController.getBasicRequest(httpMethodBox.getValue());
dataDispatchRequest.setHeaders(headerTabController.getHeaders());
return dataDispatchRequest;
case "DELETE":
DELETERequest deleteRequest = new DELETERequest(addressField.getText());
deleteRequest.setHeaders(headerTabController.getHeaders());
return deleteRequest;
dashboardState = new DashboardState(bodyTabController.getBasicRequest(httpMethodBox.getValue()));
dashboardState.setHeaders(headerTabController.getHeaders());
break;
default:
// For GET, DELETE requests
dashboardState = new DashboardState();
}
dashboardState.setTarget(addressField.getText());
dashboardState.setHttpMethod(httpMethodBox.getValue());
dashboardState.setHeaders(headerTabController.getHeaders());
dashboardState.setParams(getParams());
} catch (MalformedURLException MURLE) {
System.out.println("Dashboard state was saved with a malformed URL.");
}
return null;
return dashboardState;
}
public void setState(RestaurantRequest request) {
addressField.setText(request.getTarget().toString());
/**
* Sets the Dashboard to the given application state.
*
* @param dashboardState - State of the dashboard
*/
public void setState(DashboardState dashboardState) {
if (dashboardState.getTarget() != null)
addressField.setText(dashboardState.getTarget().toString());
for (Map.Entry entry : request.getHeaders().entrySet())
headerTabController.addHeader(entry.getKey().toString(), entry.getValue().toString());
httpMethodBox.getSelectionModel().select(dashboardState.getHttpMethod());
if (dashboardState.getHeaders() != null)
for (Map.Entry entry : dashboardState.getHeaders().entrySet())
headerTabController.addHeader(entry.getKey().toString(), entry.getValue().toString());
if (dashboardState.getParams() != null)
for (Map.Entry entry : dashboardState.getParams().entrySet())
addParamField(entry.getKey().toString(), entry.getValue().toString());
if (httpMethodBox.getValue().equals("POST") || httpMethodBox.getValue().equals("PUT"))
bodyTabController.setState(dashboardState);
}
}

View file

@ -89,4 +89,12 @@ public class FileKeyValueFieldController implements Initializable {
public boolean isChecked() {
return checkBox.isSelected();
}
public void setFileKeyField(String key) {
fileKeyField.setText(key);
}
public void setFileValueField(String value) {
fileValueField.setText(value);
}
}

View file

@ -48,11 +48,17 @@ public class FormDataTabController implements Initializable {
@FXML
private void addFileField() {
addFileField("", "");
}
public void addFileField(String key, String value) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/homewindow/FileKeyValueField.fxml"));
Parent headerField = loader.load();
ThemeManager.setTheme(headerField);
FileKeyValueFieldController controller = loader.getController();
controller.setFileKeyField(key);
controller.setFileValueField(value);
fileControllers.add(controller);
headersBox.getChildren().add(headerField);
} catch (IOException e) {
@ -62,10 +68,16 @@ public class FormDataTabController implements Initializable {
@FXML
private void addStringField() {
addStringField("", "");
}
public void addStringField(String key, String value) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/homewindow/StringKeyValueField.fxml"));
Parent headerField = loader.load();
StringKeyValueFieldController controller = loader.getController();
controller.setKeyField(key);
controller.setValueField(value);
stringControllers.add(controller);
headersBox.getChildren().add(headerField);
} catch (IOException e) {

View file

@ -16,7 +16,7 @@
package com.rohitawate.restaurant.homewindow;
import com.rohitawate.restaurant.models.requests.RestaurantRequest;
import com.rohitawate.restaurant.models.DashboardState;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.fxml.FXML;
@ -63,14 +63,14 @@ public class HomeWindowController implements Initializable {
addTab(null);
}
private void addTab(RestaurantRequest request) {
private void addTab(DashboardState dashboardState) {
try {
Tab newTab = new Tab();
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/homewindow/Dashboard.fxml"));
Parent dashboard = loader.load();
DashboardController controller = loader.getController();
if (request != null)
controller.setState(request);
if (dashboardState != null)
controller.setState(dashboardState);
newTab.setContent(dashboard);
newTab.textProperty().bind(Bindings
.when(controller.getAddressProperty().isNotEmpty())
@ -89,11 +89,11 @@ public class HomeWindowController implements Initializable {
}
private void saveState() {
List<RestaurantRequest> states = new ArrayList<>();
List<DashboardState> dashboardStates = new ArrayList<>();
// Get the states of all the tabs
for (DashboardController controller : controllers)
states.add(controller.getState());
dashboardStates.add(controller.getState());
try {
File configFolder = new File("config/");
@ -102,8 +102,9 @@ public class HomeWindowController implements Initializable {
OutputStream fileStream = new FileOutputStream("config/restaurant.state");
ObjectOutputStream objectStream = new ObjectOutputStream(fileStream);
objectStream.writeObject(states);
objectStream.writeObject(dashboardStates);
objectStream.close();
fileStream.close();
System.out.println("Application state saved successfully.");
} catch (IOException e) {
System.out.println("Failed to save the application's state:");
@ -116,24 +117,26 @@ public class HomeWindowController implements Initializable {
InputStream fileStream = new FileInputStream("config/restaurant.state");
ObjectInputStream objectStream = new ObjectInputStream(fileStream);
System.out.print("Application state file found. Recovering state... ");
System.out.println("Application state file found. Recovering state... ");
List<RestaurantRequest> states = (List<RestaurantRequest>) objectStream.readObject();
List<DashboardState> dashboardStates = (List<DashboardState>) objectStream.readObject();
objectStream.close();
fileStream.close();
if (states.size() > 0) {
for (RestaurantRequest request : states)
addTab(request);
if (dashboardStates.size() > 0) {
for (DashboardState dashboardState : dashboardStates)
addTab(dashboardState);
} else {
addTab();
}
} catch (FileNotFoundException e) {
System.out.print("Application state file not found. Loading default state... ");
System.out.println("Application state file not found. Loading default state... ");
addTab();
} catch (IOException | ClassNotFoundException e) {
System.out.print("Application state file is possibly corrupted. Could not recover the state.\nLoading default state... ");
System.out.println("Application state file is possibly corrupted. Could not recover the state.\nLoading default state... ");
addTab();
} finally {
System.out.println("Successful");
System.out.println("Application loaded.");
}
}
}

View file

@ -44,11 +44,17 @@ public class URLTabController implements Initializable {
@FXML
private void addField() {
addField("", "");
}
public void addField(String key, String value) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/homewindow/StringKeyValueField.fxml"));
Parent parent = loader.load();
ThemeManager.setTheme(parent);
StringKeyValueFieldController controller = loader.getController();
controller.setKeyField(key);
controller.setValueField(value);
controllers.add(controller);
fieldsBox.getChildren().add(parent);
} catch (IOException e) {

View file

@ -0,0 +1,62 @@
/*
* Copyright 2018 Rohit Awate.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.rohitawate.restaurant.models;
import com.rohitawate.restaurant.models.requests.DataDispatchRequest;
import java.io.Serializable;
import java.util.HashMap;
/**
* Convenience class to abstract the state of the application.
*/
public class DashboardState extends DataDispatchRequest implements Serializable {
private HashMap<String, String> params;
private String httpMethod;
public DashboardState() {
}
/*
Special copy constructor to instantiate DashboardState from
BodyTabController's getBasicRequest()
*/
public DashboardState(DataDispatchRequest dataDispatchRequest) {
super();
this.setHttpMethod(dataDispatchRequest.getRequestType());
this.setBody(dataDispatchRequest.getBody());
this.setContentType(dataDispatchRequest.getContentType());
this.setStringTuples(dataDispatchRequest.getStringTuples());
this.setFileTuples(dataDispatchRequest.getFileTuples());
}
public void setParams(HashMap<String, String> params) {
this.params = params;
}
public HashMap<String, String> getParams() {
return params;
}
public void setHttpMethod(String httpMethod) {
this.httpMethod = httpMethod;
}
public String getHttpMethod() {
return httpMethod;
}
}

View file

@ -16,38 +16,26 @@
package com.rohitawate.restaurant.models.requests;
import java.net.MalformedURLException;
import java.net.URL;
import java.io.Serializable;
import java.util.HashMap;
/**
* Represents HTTP requests which contain data viz. POST and PUT.
*/
public class DataDispatchRequest extends RestaurantRequest {
public class DataDispatchRequest extends RestaurantRequest implements Serializable {
private String requestType;
private String body;
private String contentType;
private HashMap<String, String> stringTuples;
private HashMap<String, String> fileTuples;
public DataDispatchRequest() {
}
public DataDispatchRequest(String requestType) {
this.requestType = requestType;
}
public DataDispatchRequest(URL target, String requestType) {
super(target);
this.requestType = requestType;
}
public DataDispatchRequest(String target, String requestType) throws MalformedURLException {
super(target);
this.requestType = requestType;
}
public void setTarget(String target) throws MalformedURLException {
this.target = new URL(target);
}
public String getBody() {
return body;
}

View file

@ -22,7 +22,7 @@ import java.net.URL;
import java.util.HashMap;
public abstract class RestaurantRequest implements Serializable {
URL target;
private URL target;
private HashMap<String, String> headers;
RestaurantRequest() {
@ -36,8 +36,12 @@ public abstract class RestaurantRequest implements Serializable {
this.target = target;
}
public void setTarget(String target) throws MalformedURLException {
this.target = new URL(target);
}
public URL getTarget() {
return target;
return this.target;
}
public void addHeader(String key, String value) {

View file

@ -60,9 +60,9 @@ public class SettingsLoader implements Runnable {
Settings.theme = JSONUtils.trimString(nodes.get("theme").toString());
} catch (Exception E) {
System.out.print("Settings file not found. Loading default values... ");
System.out.println("Settings file not found. Loading default values... ");
} finally {
System.out.println("Successful");
System.out.println("Settings loaded.");
}
}
}