Skip to content

Commit

Permalink
[Enhancement kbss-cvut/termit-ui#505] Introduce support for parametri…
Browse files Browse the repository at this point in the history
…zed localized messages in errors.

Any TermIt exception can now carry a messageId for localized message on the frontend as well as a map of parameters for the message. Parameters are sent to the frontend in the ErrorInfo as values map.
  • Loading branch information
lukaskabc authored and ledsoft committed Sep 13, 2024
1 parent dd6aff5 commit ff53cfc
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 25 deletions.
59 changes: 51 additions & 8 deletions src/main/java/cz/cvut/kbss/termit/exception/TermItException.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@
*/
package cz.cvut.kbss.termit.exception;

import cz.cvut.kbss.termit.util.Utils;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;

import java.util.HashMap;
import java.util.Map;

/**
* Application-specific exception.
* <p>
Expand All @@ -25,40 +32,76 @@
public class TermItException extends RuntimeException {

/**
* Identifier of localized frontend message.
* Error message identifier.
* <p>
* This identifier can be used by the UI to display a corresponding localized error message.
*/
protected String messageId;

/**
* Exception related information
*/
private String messageId;
protected final Map<String, String> parameters = new HashMap<>();

protected TermItException() {
messageId = null;
}

public TermItException(String message) {
super(message);
messageId = null;
}

public TermItException(String message, Throwable cause) {
super(message, cause);
this.messageId = null;
}

public TermItException(Throwable cause) {
super(cause);
this.messageId = null;
}

public TermItException(String message, String messageId) {
super(message);
this.messageId = messageId;
}

public TermItException(String message, Throwable cause) {
public TermItException(String message, Throwable cause, String messageId) {
super(message, cause);
this.messageId = messageId;
}

public TermItException(String message, String messageId, Throwable cause) {
public TermItException(String message, Throwable cause, String messageId, @NonNull Map<String, String> parameters) {
super(message, cause);
this.messageId = messageId;
addParameters(parameters);
}

public TermItException(Throwable cause) {
super(cause);
public TermItException addParameters(@NonNull Map<String, String> parameters) {
this.parameters.putAll(parameters);
return this;
}

public TermItException addParameter(@NonNull String key, @NonNull String value) {
this.parameters.put(key, value);
return this;
}

@Nullable
public String getMessageId() {
return messageId;
}

public void setMessageId(String messageId) {
this.messageId = messageId;
public Map<String, String> getParameters() {
return parameters;
}

@Override
public String toString() {
String params = Utils.mapToString(parameters);
return super.toString() +
(messageId == null ? "" : ", messageId=" + messageId) +
(params.isBlank() ? "" : ", parameters=" + params);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,15 @@
*/
public class VocabularyImportException extends TermItException {

private final String messageId;

public VocabularyImportException(String message) {
super(message);
this.messageId = null;
}

public VocabularyImportException(String message, String messageId) {
super(message);
this.messageId = messageId;
super(message, messageId);
}

public VocabularyImportException(String message, Throwable cause) {
super(message, cause);
this.messageId = null;
}

public String getMessageId() {
return messageId;
}
}
42 changes: 41 additions & 1 deletion src/main/java/cz/cvut/kbss/termit/rest/handler/ErrorInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,34 @@
*/
package cz.cvut.kbss.termit.rest.handler;

import cz.cvut.kbss.termit.util.Utils;

import java.util.Map;

/**
* Contains information about an error and can be sent to client as JSON to let him know what is wrong.
*/
public class ErrorInfo {

/**
* Readable message describing the error
*/
private String message;

/**
* Error message identifier.
* <p>
* This identifier can be used by the UI to display a corresponding localized error message.
*/
private String messageId;

private String requestUri;

/**
* Parameters for translatable message identified by {@link #messageId}
*/
private Map<String, String> values;

public ErrorInfo() {
}

Expand Down Expand Up @@ -66,9 +83,17 @@ public void setRequestUri(String requestUri) {
this.requestUri = requestUri;
}

public Map<String, String> getValues() {
return values;
}

public void setValues(Map<String, String> parameters) {
this.values = parameters;
}

@Override
public String toString() {
return "ErrorInfo{" + requestUri + ", messageId=" + messageId + ", message='" + message + "'}";
return "ErrorInfo{" + requestUri + ", messageId=" + messageId + ", message='" + message + "', parameters='"+ Utils.mapToString(values) +"'}";
}

/**
Expand Down Expand Up @@ -101,4 +126,19 @@ public static ErrorInfo createWithMessageAndMessageId(String message, String mes
errorInfo.setMessageId(messageId);
return errorInfo;
}

public static ErrorInfo createParametrized(String messageId, String requestUri, Map<String, String> values) {
final ErrorInfo errorInfo = new ErrorInfo(requestUri);
errorInfo.setMessageId(messageId);
errorInfo.setValues(values);
return errorInfo;
}

public static ErrorInfo createParametrizedWithMessage(String message, String messageId, String requestUri, Map<String, String> values) {
final ErrorInfo errorInfo = new ErrorInfo(requestUri);
errorInfo.setMessage(message);
errorInfo.setMessageId(messageId);
errorInfo.setValues(values);
return errorInfo;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ private static ErrorInfo errorInfo(HttpServletRequest request, Throwable e) {
}

private static ErrorInfo errorInfo(HttpServletRequest request, TermItException e) {
return ErrorInfo.createWithMessageAndMessageId(e.getMessage(), e.getMessageId(), request.getRequestURI());
return ErrorInfo.createParametrizedWithMessage(e.getMessage(), e.getMessageId(), request.getRequestURI(), e.getParameters());
}

@ExceptionHandler(PersistenceException.class)
Expand Down Expand Up @@ -191,9 +191,7 @@ public ResponseEntity<ErrorInfo> unsupportedAssetOperationException(HttpServletR
public ResponseEntity<ErrorInfo> vocabularyImportException(HttpServletRequest request,
VocabularyImportException e) {
logException(e, request);
return new ResponseEntity<>(
ErrorInfo.createWithMessageAndMessageId(e.getMessage(), e.getMessageId(), request.getRequestURI()),
HttpStatus.CONFLICT);
return new ResponseEntity<>(errorInfo(request, e), HttpStatus.CONFLICT);
}

@ExceptionHandler
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,10 @@ public Vocabulary importVocabulary(ImportConfiguration config, ImportInput data)
lang);
if (existingUri.isPresent() && !existingUri.get().equals(t.getUri())) {
throw new VocabularyImportException(
"Vocabulary already contains a term with label '" + value + "' with a different identifier than the imported one.");
"Vocabulary already contains a term with label '" + value + "' with a different identifier than the imported one.",
"error.vocabulary.import.excel.labelWithDifferentIdentifierExists")
.addParameter("label", value)
.addParameter("existingUri", Utils.uriToString(existingUri.get()));
}
}))
.filter(t -> termService.exists(t.getUri())).forEach(t -> {
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/cz/cvut/kbss/termit/util/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
Expand Down Expand Up @@ -398,4 +399,18 @@ public static void pruneBlankTranslations(MultilingualString str) {
}
str.getValue().entrySet().removeIf(e -> e.getValue().isBlank());
}

/**
* Converts the map into a string
* @return Empty string when the map is {@code null}, otherwise the String in format
* {@code {key=value, key=value}}
*/
public static <A, B> String mapToString(Map<A, B> map) {
if (map == null) {
return "";
}
return map.keySet().stream()
.map(key -> key + "=" + map.get(key))
.collect(Collectors.joining(", ", "{", "}"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ private static ErrorInfo errorInfo(Message<?> message, Throwable e) {
}

private static ErrorInfo errorInfo(Message<?> message, TermItException e) {
return ErrorInfo.createWithMessageAndMessageId(e.getMessage(), e.getMessageId(), destination(message));
return ErrorInfo.createParametrizedWithMessage(e.getMessage(), e.getMessageId(), destination(message), e.getParameters());
}

@MessageExceptionHandler
Expand Down

0 comments on commit ff53cfc

Please sign in to comment.