मैंने एक उपयोग / सहायक वर्ग (jdk 8 का उपयोग करके) भी बनाया है जो एक स्ट्रिंग को चर की घटनाओं को बदल सकता है।
इस उद्देश्य के लिए मैंने मिलानकर्ता "परिशिष्ट" विधि का उपयोग किया जो सभी प्रतिस्थापन और केवल एक प्रारूप स्ट्रिंग के प्रभावित भागों पर लूप करता है।
सहायक वर्ग वर्तमान में अच्छी तरह से javadoc प्रलेखित नहीं है। मैं इसे भविष्य में बदल दूंगा;) वैसे भी मैंने सबसे महत्वपूर्ण लाइनों पर टिप्पणी की (मुझे उम्मीद है)।
public class FormatHelper {
//Prefix and suffix for the enclosing variable name in the format string.
//Replace the default values with any you need.
public static final String DEFAULT_PREFIX = "${";
public static final String DEFAULT_SUFFIX = "}";
//Define dynamic function what happens if a key is not found.
//Replace the defualt exception with any "unchecked" exception type you need or any other behavior.
public static final BiFunction<String, String, String> DEFAULT_NO_KEY_FUNCTION =
(fullMatch, variableName) -> {
throw new RuntimeException(String.format("Key: %s for variable %s not found.",
variableName,
fullMatch));
};
private final Pattern variablePattern;
private final Map<String, String> values;
private final BiFunction<String, String, String> noKeyFunction;
private final String prefix;
private final String suffix;
public FormatHelper(Map<String, String> values) {
this(DEFAULT_NO_KEY_FUNCTION, values);
}
public FormatHelper(
BiFunction<String, String, String> noKeyFunction, Map<String, String> values) {
this(DEFAULT_PREFIX, DEFAULT_SUFFIX, noKeyFunction, values);
}
public FormatHelper(String prefix, String suffix, Map<String, String> values) {
this(prefix, suffix, DEFAULT_NO_KEY_FUNCTION, values);
}
public FormatHelper(
String prefix,
String suffix,
BiFunction<String, String, String> noKeyFunction,
Map<String, String> values) {
this.prefix = prefix;
this.suffix = suffix;
this.values = values;
this.noKeyFunction = noKeyFunction;
//Create the Pattern and quote the prefix and suffix so that the regex don't interpret special chars.
//The variable name is a "\w+" in an extra capture group.
variablePattern = Pattern.compile(Pattern.quote(prefix) + "(\\w+)" + Pattern.quote(suffix));
}
public static String format(CharSequence format, Map<String, String> values) {
return new FormatHelper(values).format(format);
}
public static String format(
CharSequence format,
BiFunction<String, String, String> noKeyFunction,
Map<String, String> values) {
return new FormatHelper(noKeyFunction, values).format(format);
}
public static String format(
String prefix, String suffix, CharSequence format, Map<String, String> values) {
return new FormatHelper(prefix, suffix, values).format(format);
}
public static String format(
String prefix,
String suffix,
BiFunction<String, String, String> noKeyFunction,
CharSequence format,
Map<String, String> values) {
return new FormatHelper(prefix, suffix, noKeyFunction, values).format(format);
}
public String format(CharSequence format) {
//Create matcher based on the init pattern for variable names.
Matcher matcher = variablePattern.matcher(format);
//This buffer will hold all parts of the formatted finished string.
StringBuffer formatBuffer = new StringBuffer();
//loop while the matcher finds another variable (prefix -> name <- suffix) match
while (matcher.find()) {
//The root capture group with the full match e.g ${variableName}
String fullMatch = matcher.group();
//The capture group for the variable name resulting from "(\w+)" e.g. variableName
String variableName = matcher.group(1);
//Get the value in our Map so the Key is the used variable name in our "format" string. The associated value will replace the variable.
//If key is missing (absent) call the noKeyFunction with parameters "fullMatch" and "variableName" else return the value.
String value = values.computeIfAbsent(variableName, key -> noKeyFunction.apply(fullMatch, key));
//Escape the Map value because the "appendReplacement" method interprets the $ and \ as special chars.
String escapedValue = Matcher.quoteReplacement(value);
//The "appendReplacement" method replaces the current "full" match (e.g. ${variableName}) with the value from the "values" Map.
//The replaced part of the "format" string is appended to the StringBuffer "formatBuffer".
matcher.appendReplacement(formatBuffer, escapedValue);
}
//The "appendTail" method appends the last part of the "format" String which has no regex match.
//That means if e.g. our "format" string has no matches the whole untouched "format" string is appended to the StringBuffer "formatBuffer".
//Further more the method return the buffer.
return matcher.appendTail(formatBuffer)
.toString();
}
public String getPrefix() {
return prefix;
}
public String getSuffix() {
return suffix;
}
public Map<String, String> getValues() {
return values;
}
}
आप मानों (या प्रत्यय उपसर्ग या noKeyFunction) के साथ एक विशिष्ट मानचित्र के लिए एक वर्ग उदाहरण बना सकते हैं:
Map<String, String> values = new HashMap<>();
values.put("firstName", "Peter");
values.put("lastName", "Parker");
FormatHelper formatHelper = new FormatHelper(values);
formatHelper.format("${firstName} ${lastName} is Spiderman!");
// Result: "Peter Parker is Spiderman!"
// Next format:
formatHelper.format("Does ${firstName} ${lastName} works as photographer?");
//Result: "Does Peter Parker works as photographer?"
इसके अलावा, आप परिभाषित कर सकते हैं कि क्या होता है यदि मानों की एक कुंजी गायब है (मानचित्र में दोनों प्रकार से गलत चर नाम या मानचित्र में गायब कुंजी) में काम करता है। डिफ़ॉल्ट व्यवहार एक अनियंत्रित अपवाद है (अनियंत्रित क्योंकि मैं डिफ़ॉल्ट jdk8 फ़ंक्शन का उपयोग करता हूं, जो कि कैंट हैंडल के अपवाद की जाँच नहीं करता है जैसे कि:
Map<String, String> map = new HashMap<>();
map.put("firstName", "Peter");
map.put("lastName", "Parker");
FormatHelper formatHelper = new FormatHelper(map);
formatHelper.format("${missingName} ${lastName} is Spiderman!");
//Result: RuntimeException: Key: missingName for variable ${missingName} not found.
आप कंस्ट्रक्टर कॉल में एक कस्टम व्यवहार को परिभाषित कर सकते हैं जैसे:
Map<String, String> values = new HashMap<>();
values.put("firstName", "Peter");
values.put("lastName", "Parker");
FormatHelper formatHelper = new FormatHelper(fullMatch, variableName) -> variableName.equals("missingName") ? "John": "SOMETHING_WRONG", values);
formatHelper.format("${missingName} ${lastName} is Spiderman!");
// Result: "John Parker is Spiderman!"
या इसे डिफ़ॉल्ट पर वापस भेजें कोई महत्वपूर्ण व्यवहार नहीं:
...
FormatHelper formatHelper = new FormatHelper((fullMatch, variableName) -> variableName.equals("missingName") ? "John" :
FormatHelper.DEFAULT_NO_KEY_FUNCTION.apply(fullMatch,
variableName), map);
...
बेहतर हैंडलिंग के लिए स्थैतिक विधि निरूपण जैसे:
Map<String, String> values = new HashMap<>();
values.put("firstName", "Peter");
values.put("lastName", "Parker");
FormatHelper.format("${firstName} ${lastName} is Spiderman!", map);
// Result: "Peter Parker is Spiderman!"