Honestly, I don't like the idea of ββtype definition using parser exceptions. I would build a template for each format and list all of them to check if a given line matches one of them.
This is similar to how the Scanner class works, but it is rather complicated. It is difficult to write regular expressions that should cover all possible cases.
But if regular expressions are prepared, the algorithm is simple:
public class Main { private final Map<String, String> patterns = Map.of( "Integer", integerPattern() ); public String getDataType(String input) { for (Map.Entry<String, String> entry : patterns.entrySet()) { if (Pattern.matches(entry.getValue(), input)) { return entry.getKey(); } } return "Unknown"; } }
Here's the interesting part - integerPattern() example. I took it from Scanner and simplified it a bit:
private String integerPattern() { String radixDigits = "0123456789abcdefghijklmnopqrstuvwxyz".substring(0, 10); String digit = "((?i)[" + radixDigits + "]|\\p{javaDigit})"; String groupedNumeral = "(" + "[\\p{javaDigit}&&[^0]]" + digit + "?" + digit + "?(" + "\\," + digit + digit + digit + ")+)"; String numeral = "((" + digit + "++)|" + groupedNumeral + ")"; String javaStyleInteger = "([-+]?(" + numeral + "))"; String negativeInteger = "\\-" + numeral + ""; String positiveInteger = "" + numeral + ""; return "(" + javaStyleInteger + ")|(" + positiveInteger + ")|(" + negativeInteger + ")"; }
I am sure you can google all regular expressions or find them here.
But what if there is an βeasierβ solution or you just don't want to use a regex approach?
You can mix different methods by entering Map<String, Predicate<String>> :
class Main { private final Map<String, Predicate<String>> predicates = Map.of( "Integer", this::isInteger, "JSON", this::isJSON ); public String getDataType(String input) { for (Map.Entry<String, Predicate<String>> predicate : predicates.entrySet()) { if (predicate.getValue().test(input)) { return predicate.getKey(); } } return "Unknown"; } private boolean isJSON(String input) { return LibraryClass.isJSON(input); } private boolean isInteger(String input) { try { Integer.valueOf(input); } catch (NumberFormatException e) { return false; } return true; } }
I believe that it is more readable, it reduces the level of nesting and encapsulates various logic in separate methods.