Refactor Highlighting and add Formatting frameworks for future Extension API
This commit is contained in:
parent
197c06b227
commit
e7537e339d
12 changed files with 246 additions and 107 deletions
|
@ -17,9 +17,10 @@
|
|||
package com.rohitawate.everest.controllers;
|
||||
|
||||
import com.rohitawate.everest.controllers.codearea.EverestCodeArea;
|
||||
import com.rohitawate.everest.controllers.codearea.EverestCodeArea.HighlightMode;
|
||||
import com.rohitawate.everest.controllers.codearea.highlighters.HighlighterFactory;
|
||||
import com.rohitawate.everest.controllers.state.ComposerState;
|
||||
import com.rohitawate.everest.controllers.state.FieldState;
|
||||
import com.rohitawate.everest.format.FormatterFactory;
|
||||
import com.rohitawate.everest.misc.Services;
|
||||
import com.rohitawate.everest.misc.ThemeManager;
|
||||
import javafx.fxml.FXML;
|
||||
|
@ -71,21 +72,20 @@ public class BodyTabController implements Initializable {
|
|||
|
||||
rawInputTypeBox.valueProperty().addListener(change -> {
|
||||
String type = rawInputTypeBox.getValue();
|
||||
HighlightMode mode;
|
||||
switch (type) {
|
||||
case "JSON":
|
||||
mode = HighlightMode.JSON;
|
||||
break;
|
||||
case "XML":
|
||||
mode = HighlightMode.XML;
|
||||
break;
|
||||
case "HTML":
|
||||
mode = HighlightMode.HTML;
|
||||
break;
|
||||
default:
|
||||
mode = HighlightMode.PLAIN;
|
||||
|
||||
if (type.equals("JSON")) {
|
||||
try {
|
||||
rawInputArea.setText(rawInputArea.getText(),
|
||||
FormatterFactory.getHighlighter(type),
|
||||
HighlighterFactory.getHighlighter(type));
|
||||
} catch (IOException e) {
|
||||
Services.loggingService.logWarning("Response could not be parsed.", e, LocalDateTime.now());
|
||||
}
|
||||
rawInputArea.setMode(mode);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
rawInputArea.setHighlighter(HighlighterFactory.getHighlighter(type));
|
||||
});
|
||||
|
||||
try {
|
||||
|
@ -185,25 +185,10 @@ public class BodyTabController implements Initializable {
|
|||
}
|
||||
|
||||
private void setRawTab(ComposerState state) {
|
||||
HighlightMode mode;
|
||||
|
||||
if (state.rawBodyType != null && state.rawBody != null) {
|
||||
switch (state.rawBodyType) {
|
||||
case "JSON":
|
||||
mode = HighlightMode.JSON;
|
||||
break;
|
||||
case "XML":
|
||||
mode = HighlightMode.XML;
|
||||
break;
|
||||
case "HTML":
|
||||
mode = HighlightMode.HTML;
|
||||
break;
|
||||
default:
|
||||
mode = HighlightMode.PLAIN;
|
||||
}
|
||||
rawInputArea.setText(state.rawBody, mode);
|
||||
rawInputArea.setText(state.rawBody, HighlighterFactory.getHighlighter(state.rawBodyType));
|
||||
} else {
|
||||
rawInputArea.setText("", HighlightMode.PLAIN);
|
||||
rawInputArea.setHighlighter(HighlighterFactory.getHighlighter("PLAIN TEXT"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,18 +15,17 @@
|
|||
*/
|
||||
package com.rohitawate.everest.controllers;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.jfoenix.controls.JFXButton;
|
||||
import com.jfoenix.controls.JFXProgressBar;
|
||||
import com.jfoenix.controls.JFXSnackbar;
|
||||
import com.rohitawate.everest.controllers.codearea.EverestCodeArea;
|
||||
import com.rohitawate.everest.controllers.codearea.EverestCodeArea.HighlightMode;
|
||||
import com.rohitawate.everest.controllers.codearea.highlighters.HighlighterFactory;
|
||||
import com.rohitawate.everest.controllers.state.ComposerState;
|
||||
import com.rohitawate.everest.controllers.state.DashboardState;
|
||||
import com.rohitawate.everest.controllers.state.FieldState;
|
||||
import com.rohitawate.everest.exceptions.RedirectException;
|
||||
import com.rohitawate.everest.exceptions.UnreliableResponseException;
|
||||
import com.rohitawate.everest.misc.EverestUtilities;
|
||||
import com.rohitawate.everest.format.FormatterFactory;
|
||||
import com.rohitawate.everest.misc.Services;
|
||||
import com.rohitawate.everest.misc.ThemeManager;
|
||||
import com.rohitawate.everest.models.requests.DELETERequest;
|
||||
|
@ -175,26 +174,20 @@ public class DashboardController implements Initializable {
|
|||
|
||||
responseTypeBox.valueProperty().addListener(change -> {
|
||||
String type = responseTypeBox.getValue();
|
||||
HighlightMode mode;
|
||||
switch (type) {
|
||||
case "JSON":
|
||||
|
||||
if (type.equals("JSON")) {
|
||||
try {
|
||||
JsonNode node = EverestUtilities.jsonMapper.readTree(responseArea.getText());
|
||||
responseArea.setText(EverestUtilities.jsonMapper.writeValueAsString(node), HighlightMode.JSON);
|
||||
responseArea.setText(responseArea.getText(),
|
||||
FormatterFactory.getHighlighter(type),
|
||||
HighlighterFactory.getHighlighter(type));
|
||||
} catch (IOException e) {
|
||||
Services.loggingService.logWarning("Response could not be parsed.", e, LocalDateTime.now());
|
||||
}
|
||||
|
||||
return;
|
||||
case "XML":
|
||||
mode = HighlightMode.XML;
|
||||
break;
|
||||
case "HTML":
|
||||
mode = HighlightMode.XML;
|
||||
break;
|
||||
default:
|
||||
mode = HighlightMode.PLAIN;
|
||||
}
|
||||
responseArea.setMode(mode);
|
||||
|
||||
responseArea.setHighlighter(HighlighterFactory.getHighlighter(type));
|
||||
});
|
||||
|
||||
visualizer = new Visualizer();
|
||||
|
@ -444,25 +437,22 @@ public class DashboardController implements Initializable {
|
|||
visualizer.clear();
|
||||
|
||||
try {
|
||||
String simplifiedContentType;
|
||||
if (contentType != null) {
|
||||
// Selects only the part preceding the ';', skipping the character encoding
|
||||
contentType = contentType.split(";")[0];
|
||||
|
||||
switch (contentType.toLowerCase()) {
|
||||
case "application/json":
|
||||
responseTypeBox.setValue("JSON");
|
||||
JsonNode node = EverestUtilities.jsonMapper.readTree(body);
|
||||
responseArea.setText(EverestUtilities.jsonMapper.writeValueAsString(node), HighlightMode.JSON);
|
||||
simplifiedContentType = "JSON";
|
||||
visualizerTab.setDisable(false);
|
||||
visualizer.populate(node);
|
||||
visualizer.populate(body);
|
||||
break;
|
||||
case "application/xml":
|
||||
responseTypeBox.setValue("XML");
|
||||
responseArea.setText(body, HighlightMode.XML);
|
||||
simplifiedContentType = "XML";
|
||||
break;
|
||||
case "text/html":
|
||||
responseTypeBox.setValue("HTML");
|
||||
responseArea.setText(body, HighlightMode.HTML);
|
||||
simplifiedContentType = "HTML";
|
||||
if (Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
|
||||
snackbar.show("Open link in browser?", "YES", 5000, e -> {
|
||||
snackbar.close();
|
||||
|
@ -477,19 +467,24 @@ public class DashboardController implements Initializable {
|
|||
}
|
||||
break;
|
||||
default:
|
||||
responseTypeBox.setValue("PLAIN TEXT");
|
||||
responseArea.setText(body, HighlightMode.PLAIN);
|
||||
simplifiedContentType = "PLAIN TEXT";
|
||||
}
|
||||
} else {
|
||||
responseTypeBox.setValue("PLAIN");
|
||||
responseArea.setText("No body found in the response.", HighlightMode.PLAIN);
|
||||
simplifiedContentType = "PLAIN TEXT";
|
||||
}
|
||||
|
||||
responseArea.setText(body,
|
||||
FormatterFactory.getHighlighter(simplifiedContentType),
|
||||
HighlighterFactory.getHighlighter(simplifiedContentType));
|
||||
|
||||
responseTypeBox.setValue(simplifiedContentType);
|
||||
} catch (Exception e) {
|
||||
snackbar.show("Response could not be parsed.", 5000);
|
||||
Services.loggingService.logSevere("Response could not be parsed.", e, LocalDateTime.now());
|
||||
showLayer(ResponseLayer.ERROR);
|
||||
String errorMessage = "Response could not be parsed.";
|
||||
snackbar.show(errorMessage, 5000);
|
||||
Services.loggingService.logSevere(errorMessage, e, LocalDateTime.now());
|
||||
errorTitle.setText("Parsing Error");
|
||||
errorDetails.setText("Everest could not parse the response.");
|
||||
errorDetails.setText(errorMessage);
|
||||
showLayer(ResponseLayer.ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,9 +17,11 @@
|
|||
package com.rohitawate.everest.controllers;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.rohitawate.everest.misc.EverestUtilities;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.layout.HBox;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
@ -37,8 +39,9 @@ class Visualizer extends ScrollPane {
|
|||
setFitToWidth(true);
|
||||
}
|
||||
|
||||
void populate(JsonNode node) {
|
||||
this.populate(new TreeItem<>(), "root", node);
|
||||
void populate(String body) throws IOException {
|
||||
JsonNode tree = EverestUtilities.jsonMapper.readTree(body);
|
||||
this.populate(new TreeItem<>(), "root", tree);
|
||||
}
|
||||
|
||||
private void populate(TreeItem<HBox> rootItem, String rootName, JsonNode root) {
|
||||
|
|
|
@ -17,63 +17,62 @@
|
|||
package com.rohitawate.everest.controllers.codearea;
|
||||
|
||||
import com.rohitawate.everest.controllers.codearea.highlighters.Highlighter;
|
||||
import com.rohitawate.everest.controllers.codearea.highlighters.JSONHighlighter;
|
||||
import com.rohitawate.everest.controllers.codearea.highlighters.PlaintextHighlighter;
|
||||
import com.rohitawate.everest.controllers.codearea.highlighters.XMLHighlighter;
|
||||
import com.rohitawate.everest.format.Formatter;
|
||||
import com.rohitawate.everest.settings.Settings;
|
||||
import javafx.geometry.Insets;
|
||||
import org.fxmisc.richtext.CodeArea;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
|
||||
public class EverestCodeArea extends CodeArea {
|
||||
public enum HighlightMode {
|
||||
JSON, XML, HTML, PLAIN
|
||||
}
|
||||
|
||||
private Highlighter highlighter;
|
||||
|
||||
private static JSONHighlighter jsonHighlighter;
|
||||
private static XMLHighlighter xmlHighlighter;
|
||||
private static PlaintextHighlighter plaintextHighlighter;
|
||||
|
||||
public EverestCodeArea() {
|
||||
this.getStylesheets().add(getClass().getResource("/css/syntax/Moondust.css").toString());
|
||||
this.getStyleClass().add("everest-code-area");
|
||||
this.setWrapText(Settings.editorWrapText);
|
||||
this.setPadding(new Insets(5));
|
||||
|
||||
jsonHighlighter = new JSONHighlighter();
|
||||
xmlHighlighter = new XMLHighlighter();
|
||||
plaintextHighlighter = new PlaintextHighlighter();
|
||||
|
||||
setMode(HighlightMode.PLAIN);
|
||||
|
||||
this.multiPlainChanges()
|
||||
.successionEnds(Duration.ofMillis(1))
|
||||
.subscribe(ignore -> this.setStyleSpans(0, highlighter.computeHighlighting(getText())));
|
||||
.subscribe(ignore -> highlight());
|
||||
}
|
||||
|
||||
public void setMode(HighlightMode mode) {
|
||||
switch (mode) {
|
||||
case JSON:
|
||||
highlighter = jsonHighlighter;
|
||||
break;
|
||||
case XML:
|
||||
case HTML:
|
||||
highlighter = xmlHighlighter;
|
||||
break;
|
||||
default:
|
||||
highlighter = plaintextHighlighter;
|
||||
}
|
||||
|
||||
// Re-computes the highlighting for the new mode
|
||||
private void highlight() {
|
||||
this.setStyleSpans(0, highlighter.computeHighlighting(getText()));
|
||||
}
|
||||
|
||||
public void setText(String text, HighlightMode mode) {
|
||||
public void setHighlighter(Highlighter highlighter) {
|
||||
this.highlighter = highlighter;
|
||||
|
||||
// Re-computes the highlighting using the new Highlighter
|
||||
this.highlight();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the text and then computes the highlighting.
|
||||
*/
|
||||
public void setText(String text, Highlighter highlighter) {
|
||||
clear();
|
||||
appendText(text);
|
||||
setMode(mode);
|
||||
setHighlighter(highlighter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the text with the provided Formatter if it is not null,
|
||||
* sets the text and then computes the highlighting.
|
||||
*
|
||||
* @throws IOException If the formatter fails to format the text given a syntactic error.
|
||||
*/
|
||||
public void setText(String text, Formatter formatter, Highlighter highlighter) throws IOException {
|
||||
clear();
|
||||
String formattedText = text;
|
||||
|
||||
if (formatter != null)
|
||||
formattedText = formatter.format(text);
|
||||
|
||||
appendText(formattedText);
|
||||
setHighlighter(highlighter);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,15 @@ import org.fxmisc.richtext.model.StyleSpans;
|
|||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Highlights strings in various data formats.
|
||||
*/
|
||||
public interface Highlighter {
|
||||
/**
|
||||
* Returns the StyleSpans needed for highlighting the given text which
|
||||
* can then be used by EverestCodeArea.
|
||||
*
|
||||
* @param text The string to highlight
|
||||
*/
|
||||
StyleSpans<Collection<String>> computeHighlighting(String text);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
package com.rohitawate.everest.controllers.codearea.highlighters;
|
||||
|
||||
import com.rohitawate.everest.exceptions.DuplicateHighlighterException;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Provides Highlighters for computing syntax highlighting
|
||||
* of specific data formats.
|
||||
* <p>
|
||||
* Everest, by default, comes with Highlighters for JSON, XML (HTML uses the same) and PLAIN TEXT.
|
||||
*/
|
||||
public class HighlighterFactory {
|
||||
private static HashMap<String, Highlighter> highlighters;
|
||||
|
||||
static {
|
||||
highlighters = new HashMap<>();
|
||||
highlighters.put("JSON", new JSONHighlighter());
|
||||
|
||||
XMLHighlighter xmlHighlighter = new XMLHighlighter();
|
||||
highlighters.put("XML", xmlHighlighter);
|
||||
highlighters.put("HTML", xmlHighlighter);
|
||||
|
||||
highlighters.put("PLAIN TEXT", new PlaintextHighlighter());
|
||||
}
|
||||
|
||||
public static Highlighter getHighlighter(String name) {
|
||||
return highlighters.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provisional method for the future Extension API which will enable
|
||||
* developers to write and load custom Highlighters.
|
||||
*
|
||||
* @param name The display name for the Highlighter.
|
||||
* @param highlighter The Highlighter object
|
||||
* @throws DuplicateHighlighterException If a Highlighter is already loaded by Everest with the same name.
|
||||
*/
|
||||
public static void addHighlighter(String name, Highlighter highlighter)
|
||||
throws DuplicateHighlighterException {
|
||||
if (highlighters.containsKey(name)) {
|
||||
throw new DuplicateHighlighterException("Highlighter already exists for the following type: " + name);
|
||||
}
|
||||
|
||||
highlighters.put(name, highlighter);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package com.rohitawate.everest.exceptions;
|
||||
|
||||
public class DuplicateFormatterException extends Exception {
|
||||
public DuplicateFormatterException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package com.rohitawate.everest.exceptions;
|
||||
|
||||
public class DuplicateHighlighterException extends Exception {
|
||||
public DuplicateHighlighterException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
16
src/main/java/com/rohitawate/everest/format/Formatter.java
Normal file
16
src/main/java/com/rohitawate/everest/format/Formatter.java
Normal file
|
@ -0,0 +1,16 @@
|
|||
package com.rohitawate.everest.format;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Formats strings in various data formats.
|
||||
*/
|
||||
public interface Formatter {
|
||||
/**
|
||||
* Returns a string formatted appropriate to the data format.
|
||||
*
|
||||
* @param unformatted The unformatted string
|
||||
* @throws IOException If the Formatter fails to format the given string.
|
||||
*/
|
||||
String format(String unformatted) throws IOException;
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package com.rohitawate.everest.format;
|
||||
|
||||
import com.rohitawate.everest.exceptions.DuplicateFormatterException;
|
||||
import com.rohitawate.everest.exceptions.DuplicateHighlighterException;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Provides Formatters for formatting strings of specific data formats.
|
||||
* <p>
|
||||
* Everest, by default, comes with a Formatter for JSON.
|
||||
*/
|
||||
public class FormatterFactory {
|
||||
private static HashMap<String, Formatter> formatters;
|
||||
|
||||
static {
|
||||
formatters = new HashMap<>();
|
||||
formatters.put("JSON", new JSONFormatter());
|
||||
}
|
||||
|
||||
public static Formatter getHighlighter(String type) {
|
||||
return formatters.get(type);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Provisional method for the future Extension API which will enable
|
||||
* developers to write and load custom Formatters.
|
||||
*
|
||||
* @param name The display name for the Formatter.
|
||||
* @param formatter The Formatter object.
|
||||
* @throws DuplicateHighlighterException If a Formatter is already loaded by Everest with the same name.
|
||||
*/
|
||||
public static void addFormatter(String name, Formatter formatter)
|
||||
throws DuplicateFormatterException {
|
||||
if (formatters.containsKey(name)) {
|
||||
throw new DuplicateFormatterException("Formatter already exists for the following type: " + name);
|
||||
}
|
||||
|
||||
formatters.put(name, formatter);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package com.rohitawate.everest.format;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Formats JSON strings using Jackson's ObjectMapper.
|
||||
*/
|
||||
public class JSONFormatter implements Formatter {
|
||||
private static ObjectMapper mapper;
|
||||
|
||||
JSONFormatter() {
|
||||
mapper = new ObjectMapper();
|
||||
mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String format(String unformatted) throws IOException {
|
||||
JsonNode tree = mapper.readTree(unformatted);
|
||||
return mapper.writeValueAsString(tree);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getClass().getCanonicalName();
|
||||
}
|
||||
}
|
|
@ -50,7 +50,6 @@ public class RequestManagersPool {
|
|||
GETRequestManager newManager = new GETRequestManager();
|
||||
getManagers.add(newManager);
|
||||
|
||||
System.out.println(getManagers.size());
|
||||
return newManager;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue