error export implemented and message on error side bar includes column name

This commit is contained in:
2016-08-10 23:41:47 +02:00
parent 7472c66823
commit e6742a4e30
12 changed files with 182 additions and 8 deletions

View File

@@ -1,5 +1,5 @@
group 'ninja.javafx' group 'ninja.javafx'
version '0.6-SNAPSHOT' version '0.7-SNAPSHOT'
apply plugin: 'java' apply plugin: 'java'
apply plugin: 'groovy' apply plugin: 'groovy'

View File

@@ -0,0 +1,71 @@
package ninja.javafx.smartcsv.export;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import ninja.javafx.smartcsv.fx.table.model.CSVModel;
import ninja.javafx.smartcsv.validation.ValidationError;
import java.io.File;
import java.io.StringWriter;
import java.nio.file.Files;
import java.util.ResourceBundle;
import static java.text.MessageFormat.format;
import static ninja.javafx.smartcsv.fx.util.I18nValidationUtil.getI18nValidatioMessage;
/**
* this class exports the error messages into a log file
*/
@org.springframework.stereotype.Service
public class ErrorExport extends Service {
private CSVModel model;
private File file;
private ResourceBundle resourceBundle;
private String csvFilename;
public void setCsvFilename(String csvFilename) {
this.csvFilename = csvFilename;
}
public void setResourceBundle(ResourceBundle resourceBundle) {
this.resourceBundle = resourceBundle;
}
public void setModel(CSVModel model) {
this.model = model;
}
public void setFile(File file) {
this.file = file;
}
@Override
protected Task createTask() {
return new Task() {
@Override
protected Void call() throws Exception {
try {
StringWriter log = new StringWriter();
log.append(
format(resourceBundle.getString("log.header.message"),
csvFilename,
Integer.toString(model.getValidationError().size()))).append("\n\n");
for (ValidationError error:model.getValidationError()) {
log.append(
format(resourceBundle.getString("log.message"),
error.getLineNumber().toString(),
error.getColumn(),
getI18nValidatioMessage(resourceBundle, error))).append("\n");
}
Files.write(file.toPath(), log.toString().getBytes());
} catch (Throwable ex) {
ex.printStackTrace();
}
return null;
}
};
}
}

View File

@@ -26,6 +26,7 @@
package ninja.javafx.smartcsv.fx; package ninja.javafx.smartcsv.fx;
import javafx.beans.binding.Bindings;
import javafx.collections.ListChangeListener; import javafx.collections.ListChangeListener;
import javafx.collections.WeakListChangeListener; import javafx.collections.WeakListChangeListener;
import javafx.concurrent.WorkerStateEvent; import javafx.concurrent.WorkerStateEvent;
@@ -39,6 +40,7 @@ import javafx.scene.layout.BorderPane;
import javafx.stage.FileChooser; import javafx.stage.FileChooser;
import ninja.javafx.smartcsv.csv.CSVFileReader; import ninja.javafx.smartcsv.csv.CSVFileReader;
import ninja.javafx.smartcsv.csv.CSVFileWriter; import ninja.javafx.smartcsv.csv.CSVFileWriter;
import ninja.javafx.smartcsv.export.ErrorExport;
import ninja.javafx.smartcsv.files.FileStorage; import ninja.javafx.smartcsv.files.FileStorage;
import ninja.javafx.smartcsv.fx.about.AboutController; import ninja.javafx.smartcsv.fx.about.AboutController;
import ninja.javafx.smartcsv.fx.list.ErrorSideBar; import ninja.javafx.smartcsv.fx.list.ErrorSideBar;
@@ -95,6 +97,9 @@ public class SmartCSVController extends FXMLController {
public static final String CSV_FILTER_EXTENSION = "*.csv"; public static final String CSV_FILTER_EXTENSION = "*.csv";
public static final String JSON_FILTER_TEXT = "JSON files (*.json)"; public static final String JSON_FILTER_TEXT = "JSON files (*.json)";
public static final String JSON_FILTER_EXTENSION = "*.json"; public static final String JSON_FILTER_EXTENSION = "*.json";
public static final String EXPORT_LOG_FILTER_TEXT = "Error log files (*.log)";
public static final String EXPORT_LOG_FILTER_EXTENSION = "*.log";
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// injections // injections
@@ -115,6 +120,9 @@ public class SmartCSVController extends FXMLController {
@Autowired @Autowired
private SaveFileService saveFileService; private SaveFileService saveFileService;
@Autowired
private ErrorExport errorExport;
@FXML @FXML
private BorderPane applicationPane; private BorderPane applicationPane;
@@ -157,6 +165,9 @@ public class SmartCSVController extends FXMLController {
@FXML @FXML
private MenuItem gotoLineMenuItem; private MenuItem gotoLineMenuItem;
@FXML
private MenuItem exportMenuItem;
@FXML @FXML
private Button saveButton; private Button saveButton;
@@ -181,6 +192,9 @@ public class SmartCSVController extends FXMLController {
@FXML @FXML
private Button addRowButton; private Button addRowButton;
@FXML
private Button exportButton;
@FXML @FXML
private Label currentLineNumber; private Label currentLineNumber;
@@ -370,6 +384,26 @@ public class SmartCSVController extends FXMLController {
} }
} }
@FXML
public void export(ActionEvent actionEvent) {
final FileChooser fileChooser = new FileChooser();
//Set extension filter
final FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter(EXPORT_LOG_FILTER_TEXT, EXPORT_LOG_FILTER_EXTENSION);
fileChooser.getExtensionFilters().add(extFilter);
fileChooser.setTitle("Save");
//Show open file dialog
File file = fileChooser.showSaveDialog(applicationPane.getScene().getWindow());
if (file != null) {
errorExport.setCsvFilename(currentCsvFile.getFile().getName());
errorExport.setModel(currentCsvFile.getContent());
errorExport.setFile(file);
errorExport.setResourceBundle(resourceBundle);
errorExport.restart();
}
}
public boolean canExit() { public boolean canExit() {
boolean canExit = true; boolean canExit = true;
if (currentCsvFile.getContent() != null && currentCsvFile.isFileChanged()) { if (currentCsvFile.getContent() != null && currentCsvFile.isFileChanged()) {
@@ -552,6 +586,8 @@ public class SmartCSVController extends FXMLController {
* Creates new table view and add the new content * Creates new table view and add the new content
*/ */
private void resetContent() { private void resetContent() {
resetExportButtons();
if (currentCsvFile.getContent() != null) { if (currentCsvFile.getContent() != null) {
currentCsvFile.getContent().getValidationError().addListener(weakErrorListListener); currentCsvFile.getContent().getValidationError().addListener(weakErrorListListener);
currentCsvFile.getContent().setValidationConfiguration(currentConfigFile.getContent()); currentCsvFile.getContent().setValidationConfiguration(currentConfigFile.getContent());
@@ -575,9 +611,22 @@ public class SmartCSVController extends FXMLController {
setRightAnchor(tableView, 0.0); setRightAnchor(tableView, 0.0);
tableWrapper.getChildren().setAll(tableView); tableWrapper.getChildren().setAll(tableView);
errorSideBar.setModel(currentCsvFile.getContent()); errorSideBar.setModel(currentCsvFile.getContent());
binExportButtons();
} }
} }
private void binExportButtons() {
exportButton.disableProperty().bind(Bindings.isEmpty(currentCsvFile.getContent().getValidationError()));
exportMenuItem.disableProperty().bind(Bindings.isEmpty(currentCsvFile.getContent().getValidationError()));
}
private void resetExportButtons() {
exportButton.disableProperty().unbind();
exportMenuItem.disableProperty().unbind();
exportButton.disableProperty().setValue(true);
exportMenuItem.disableProperty().setValue(true);
}
/** /**
* Adds a column with the given name to the tableview * Adds a column with the given name to the tableview
* @param header name of the column header * @param header name of the column header

View File

@@ -48,7 +48,7 @@ import java.util.ResourceBundle;
import static javafx.geometry.Pos.CENTER; import static javafx.geometry.Pos.CENTER;
import static ninja.javafx.smartcsv.fx.util.ColorConstants.ERROR_COLOR; import static ninja.javafx.smartcsv.fx.util.ColorConstants.ERROR_COLOR;
import static ninja.javafx.smartcsv.fx.util.ColorConstants.OK_COLOR; import static ninja.javafx.smartcsv.fx.util.ColorConstants.OK_COLOR;
import static ninja.javafx.smartcsv.fx.util.I18nValidationUtil.getI18nValidatioMessage; import static ninja.javafx.smartcsv.fx.util.I18nValidationUtil.getI18nValidatioMessageWithColumn;
/** /**
* clickable side bar with error markers * clickable side bar with error markers
@@ -158,7 +158,7 @@ public class ErrorSideBar extends Region {
errorMarker.setStyle("-fx-background-color: " + ERROR_COLOR); errorMarker.setStyle("-fx-background-color: " + ERROR_COLOR);
errorMarker.setOnMouseClicked(event -> selectedValidationError.setValue(error)); errorMarker.setOnMouseClicked(event -> selectedValidationError.setValue(error));
errorMarker.setOnMouseEntered(event -> { errorMarker.setOnMouseEntered(event -> {
popOver.setContentNode(popupContent(getI18nValidatioMessage(resourceBundle, error))); popOver.setContentNode(popupContent(getI18nValidatioMessageWithColumn(resourceBundle, error)));
popOver.show(errorMarker, -16); popOver.show(errorMarker, -16);
}); });
return errorMarker; return errorMarker;

View File

@@ -54,11 +54,20 @@ public class I18nValidationUtil {
return ""; return "";
} }
public static String getI18nValidatioMessageWithColumn(ResourceBundle resourceBundle, ValidationError error) {
return getI18nValidatioMessage(resourceBundle, error, resourceBundle.getString("column") + " " + error.getColumn() + " : ");
}
public static String getI18nValidatioMessage(ResourceBundle resourceBundle, ValidationError error) { public static String getI18nValidatioMessage(ResourceBundle resourceBundle, ValidationError error) {
return getI18nValidatioMessage(resourceBundle, error, "");
}
private static String getI18nValidatioMessage(ResourceBundle resourceBundle, ValidationError error, String prefix) {
List<ValidationMessage> validationMessages = error.getMessages(); List<ValidationMessage> validationMessages = error.getMessages();
StringWriter message = new StringWriter(); StringWriter message = new StringWriter();
for (ValidationMessage validationMessage: validationMessages) { for (ValidationMessage validationMessage: validationMessages) {
message.append(prefix);
if (resourceBundle.containsKey(validationMessage.getKey())) { if (resourceBundle.containsKey(validationMessage.getKey())) {
String resourceText = resourceBundle.getString(validationMessage.getKey()); String resourceText = resourceBundle.getString(validationMessage.getKey());
if (validationMessage.getParameters().length > 0) { if (validationMessage.getParameters().length > 0) {

View File

@@ -38,6 +38,7 @@ public class ValidationError {
private List<ValidationMessage> messages = new ArrayList<>(); private List<ValidationMessage> messages = new ArrayList<>();
private Integer lineNumber; private Integer lineNumber;
private String column = "";
private ValidationError(Integer lineNumber) { private ValidationError(Integer lineNumber) {
this.lineNumber = lineNumber; this.lineNumber = lineNumber;
@@ -51,10 +52,19 @@ public class ValidationError {
return new ValidationError(-1); return new ValidationError(-1);
} }
public ValidationError column(String column) {
this.column = column;
return this;
}
public Integer getLineNumber() { public Integer getLineNumber() {
return lineNumber; return lineNumber;
} }
public String getColumn() {
return column;
}
public List<ValidationMessage> getMessages() { public List<ValidationMessage> getMessages() {
return messages; return messages;
} }

View File

@@ -86,7 +86,7 @@ public class Validator {
public ValidationError isValid(Integer row, String column, String value) { public ValidationError isValid(Integer row, String column, String value) {
ValidationError result = null; ValidationError result = null;
if (hasConfig()) { if (hasConfig()) {
ValidationError error = ValidationError.withLineNumber(row); ValidationError error = ValidationError.withLineNumber(row).column(column);
Map<Validation.Type, Validation> validationMap = columnValidationMap.get(column); Map<Validation.Type, Validation> validationMap = columnValidationMap.get(column);
if (validationMap != null) { if (validationMap != null) {
for (Validation validation: validationMap.values()) { for (Validation validation: validationMap.values()) {

View File

@@ -1,5 +1,5 @@
application.name = SmartCSV.fx application.name = SmartCSV.fx
application.version = 0.6 application.version = 0.7
# fxml views # fxml views
fxml.smartcvs.view = /ninja/javafx/smartcsv/fx/smartcsv.fxml fxml.smartcvs.view = /ninja/javafx/smartcsv/fx/smartcsv.fxml

View File

@@ -82,9 +82,14 @@
.goto-icon { .goto-icon {
-glyph-name: "SUBDIRECTORY_ARROW_RIGHT"; -glyph-name: "SUBDIRECTORY_ARROW_RIGHT";
-glyph-size: 16px; -glyph-size: 16px;
} }
.export-icon {
-glyph-name: "BUG";
-glyph-size: 16px;
}
/* toolbar customization based on http://fxexperience.com/2012/02/customized-segmented-toolbar-buttons/ */ /* toolbar customization based on http://fxexperience.com/2012/02/customized-segmented-toolbar-buttons/ */
#background { #background {
@@ -149,6 +154,11 @@
-fx-fill: white; -fx-fill: white;
} }
.tool-bar .export-icon {
-glyph-size: 16px;
-fx-fill: white;
}
.segmented-button-bar .button { .segmented-button-bar .button {
-fx-background-color: -fx-background-color:
-darkest-black, -darkest-black,

View File

@@ -78,6 +78,11 @@
<MaterialDesignIconView styleClass="preferences-icon" /> <MaterialDesignIconView styleClass="preferences-icon" />
</graphic> </graphic>
</MenuItem> </MenuItem>
<MenuItem fx:id="exportMenuItem" disable="true" mnemonicParsing="false" onAction="#export" text="%menu.export">
<graphic>
<MaterialDesignIconView styleClass="export-icon" />
</graphic>
</MenuItem>
<SeparatorMenuItem mnemonicParsing="false" /> <SeparatorMenuItem mnemonicParsing="false" />
<MenuItem mnemonicParsing="false" onAction="#close" text="%menu.close"> <MenuItem mnemonicParsing="false" onAction="#close" text="%menu.close">
<graphic> <graphic>
@@ -229,6 +234,14 @@
<MaterialDesignIconView styleClass="preferences-icon" /> <MaterialDesignIconView styleClass="preferences-icon" />
</graphic> </graphic>
</Button> </Button>
<Button fx:id="exportButton" disable="true" mnemonicParsing="false" onAction="#export">
<tooltip>
<Tooltip text="%menu.export" />
</tooltip>
<graphic>
<MaterialDesignIconView styleClass="export-icon" />
</graphic>
</Button>
<Button mnemonicParsing="false" onAction="#close" styleClass="last"> <Button mnemonicParsing="false" onAction="#close" styleClass="last">
<tooltip> <tooltip>
<Tooltip text="%menu.close" /> <Tooltip text="%menu.close" />

View File

@@ -14,6 +14,7 @@ menu.preferences = Preferences
menu.delete.row = Delete row menu.delete.row = Delete row
menu.add.row = Add row menu.add.row = Add row
menu.goto.line = Goto line menu.goto.line = Goto line
menu.export = Export error log
title.validation.errors = Validation Errors: title.validation.errors = Validation Errors:
@@ -78,4 +79,9 @@ dialog.validation.rules.title = Validation rules
dialog.validation.rules.header = Validation rules of column "{0}" dialog.validation.rules.header = Validation rules of column "{0}"
context.menu.edit.column.rules = Edit rules context.menu.edit.column.rules = Edit rules
lineNumber = Selected line: lineNumber = Selected line:
log.header.message = {0} has {1} errors
log.message = row {0} column {1} : {2}
column = column

View File

@@ -23,6 +23,7 @@ menu.preferences = Einstellungen
menu.delete.row = Zeile l\u00f6schen menu.delete.row = Zeile l\u00f6schen
menu.add.row = Zeile hinzuf\u00fcgen menu.add.row = Zeile hinzuf\u00fcgen
menu.goto.line = Springe zur Zeile menu.goto.line = Springe zur Zeile
menu.export = Export Fehlerdatei
title.validation.errors = Fehler in der Datei: title.validation.errors = Fehler in der Datei:
@@ -88,4 +89,9 @@ dialog.validation.rules.header = Pr\u00fcfregeln f\u00fcr die Spalte "{0}"
context.menu.edit.column.rules = Pr\u00fcfregeln bearbeiten context.menu.edit.column.rules = Pr\u00fcfregeln bearbeiten
lineNumber = Ausgew\u00e4hlte Zeile: lineNumber = Ausgew\u00e4hlte Zeile:
log.header.message = {0} hat {1} Fehler
log.message = Zeile {0} Spalte {1} : {2}
column = Spalte