-
Notifications
You must be signed in to change notification settings - Fork 214
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Improve validation error messages for unknown property and json mappi…
…ng exceptions Signed-off-by: Taylor Gray <[email protected]>
- Loading branch information
1 parent
80b766a
commit 16aea47
Showing
8 changed files
with
360 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
91 changes: 91 additions & 0 deletions
91
...work/src/main/java/org/opensearch/dataprepper/plugin/PluginConfigurationErrorHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
package org.opensearch.dataprepper.plugin; | ||
|
||
import com.fasterxml.jackson.databind.JsonMappingException; | ||
import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException; | ||
import org.apache.commons.text.similarity.LevenshteinDistance; | ||
import org.opensearch.dataprepper.model.configuration.PluginSetting; | ||
import org.opensearch.dataprepper.model.plugin.InvalidPluginConfigurationException; | ||
|
||
import javax.inject.Inject; | ||
import javax.inject.Named; | ||
import java.util.List; | ||
import java.util.Optional; | ||
import java.util.stream.Collectors; | ||
|
||
@Named | ||
public class PluginConfigurationErrorHandler { | ||
|
||
static final String UNRECOGNIZED_PROPERTY_EXCEPTION_FORMAT = "Parameter \"%s\" for plugin \"%s\" does not exist. Available options include %s."; | ||
static final String JSON_MAPPING_EXCEPTION_FORMAT = "Parameter \"%s\" for plugin \"%s\" is invalid: %s"; | ||
static final String GENERIC_PLUGIN_EXCEPTION_FORMAT = "Plugin \"%s\" is invalid: %s"; | ||
|
||
static final Integer MIN_DISTANCE_TO_RECOMMEND_PROPERTY = 3; | ||
|
||
private final LevenshteinDistance levenshteinDistance; | ||
|
||
@Inject | ||
public PluginConfigurationErrorHandler(final LevenshteinDistance levenshteinDistance) { | ||
this.levenshteinDistance = levenshteinDistance; | ||
} | ||
|
||
public void handleException(final PluginSetting pluginSetting, final Exception e) { | ||
if (e.getCause() instanceof UnrecognizedPropertyException) { | ||
handleUnrecognizedPropertyException((UnrecognizedPropertyException) e.getCause(), pluginSetting); | ||
} else if (e.getCause() instanceof JsonMappingException) { | ||
handleJsonMappingException((JsonMappingException) e.getCause(), pluginSetting); | ||
} | ||
|
||
throw new InvalidPluginConfigurationException( | ||
String.format(GENERIC_PLUGIN_EXCEPTION_FORMAT, pluginSetting.getName(), e.getMessage())); | ||
} | ||
|
||
private void handleJsonMappingException(final JsonMappingException e, final PluginSetting pluginSetting) { | ||
final String parameterPath = getParameterPath(e.getPath()); | ||
|
||
final String errorMessage = String.format(JSON_MAPPING_EXCEPTION_FORMAT, | ||
parameterPath, pluginSetting.getName(), e.getOriginalMessage()); | ||
|
||
throw new InvalidPluginConfigurationException(errorMessage); | ||
} | ||
|
||
private void handleUnrecognizedPropertyException(final UnrecognizedPropertyException e, final PluginSetting pluginSetting) { | ||
String errorMessage = String.format(UNRECOGNIZED_PROPERTY_EXCEPTION_FORMAT, | ||
getParameterPath(e.getPath()), | ||
pluginSetting.getName(), | ||
e.getKnownPropertyIds()); | ||
|
||
final Optional<String> closestRecommendation = getClosestField(e); | ||
|
||
if (closestRecommendation.isPresent()) { | ||
errorMessage += " Did you mean \"" + closestRecommendation.get() + "\"?"; | ||
} | ||
|
||
throw new InvalidPluginConfigurationException(errorMessage); | ||
} | ||
|
||
private Optional<String> getClosestField(final UnrecognizedPropertyException e) { | ||
String closestMatch = null; | ||
int smallestDistance = Integer.MAX_VALUE; | ||
|
||
for (final String field : e.getKnownPropertyIds().stream().map(Object::toString).collect(Collectors.toList())) { | ||
int distance = levenshteinDistance.apply(e.getPropertyName(), field); | ||
|
||
if (distance < smallestDistance) { | ||
smallestDistance = distance; | ||
closestMatch = field; | ||
} | ||
} | ||
|
||
if (smallestDistance <= MIN_DISTANCE_TO_RECOMMEND_PROPERTY) { | ||
return Optional.ofNullable(closestMatch); | ||
} | ||
|
||
return Optional.empty(); | ||
} | ||
|
||
private String getParameterPath(final List<JsonMappingException.Reference> path) { | ||
return path.stream() | ||
.map(JsonMappingException.Reference::getFieldName) | ||
.collect(Collectors.joining(".")); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.