Skip to content

Commit dcbf16a

Browse files
authored
Rewrite logic for block quotes when using JAVAMSGFORMAT_ALL (#139)
* using double single quote in message format * adding more edge cases for resource filter
1 parent 2fa4474 commit dcbf16a

3 files changed

Lines changed: 38 additions & 54 deletions

File tree

gp-res-filter/src/main/java/com/ibm/g11n/pipeline/resfilter/impl/JavaPropertiesResource.java

Lines changed: 25 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
import java.util.List;
3737
import java.util.Map;
3838
import java.util.Properties;
39+
import java.util.regex.Matcher;
40+
import java.util.regex.Pattern;
3941

4042
import com.ibm.g11n.pipeline.resfilter.FilterOptions;
4143
import com.ibm.g11n.pipeline.resfilter.LanguageBundle;
@@ -74,6 +76,7 @@ public enum MessagePatternEscape {
7476

7577
private final Encoding enc;
7678
private final MessagePatternEscape msgPatEsc;
79+
private static final Pattern quoteWithBracePattern = Pattern.compile("\\'\\'\\{[^}\\s]+}\\'\\'");
7780

7881
public JavaPropertiesResource(Encoding enc, MessagePatternEscape msgPatEsc){
7982
this.enc = enc;
@@ -874,65 +877,29 @@ public static String ConvertSingleQuote(String inputStr, MessagePatternEscape ms
874877
* developer's -> developer''s
875878
*/
876879

877-
StringBuilder outputBuf = new StringBuilder();
878-
879-
String[] quotedArr = inputStr.split("'");
880-
// Split the sentence into string array based on single quote
881-
// For each element of the array,
882-
// if the element begins with a expression {.*
883-
// then check the following elements of the array to determine where the expression ends with }
884-
// if the expression ends on the same element, then it means that the content within {.*}
885-
// doesn't contain any single quotes, and hence the expression can be easily appended/prepended with ''
886-
// Use single ' to append array elements between { and }
887-
// Use single ' to append on either end to wrap quoted {.*}, where the content inside { and } is having quotes.
888-
// This is still an incomplete fix, due to inconsistency in upload/download. However it handles most of the basic cases.
889-
outputBuf.append(quotedArr[0]);
890-
boolean doDoubleQuote = true;
891-
for (int i = 1; i < quotedArr.length; i++) {
892-
String interimStr = "";
893-
if (quotedArr[i].startsWith("{")) {
894-
if (quotedArr[i].endsWith("}")) {
895-
outputBuf.append("''").append(quotedArr[i]);
896-
if (i == quotedArr.length - 1) { // terminal element which ends with }'
897-
outputBuf.append("''");
898-
}
899-
continue;
900-
}
901-
doDoubleQuote = false;
902-
interimStr = quotedArr[i];
903-
int j = i + 1;
904-
// look whether there is an ending "}" in the subsequent elements
905-
for (;j < quotedArr.length && !quotedArr[j].endsWith("}"); j++) {
906-
// any element in this range will be appended with single quote.
907-
// we don't want to corrupt the pattern inside {}
908-
interimStr = interimStr + "'" + quotedArr[j];
909-
}
910-
i = Math.min (j, quotedArr.length);
911-
if (i < quotedArr.length) {
912-
outputBuf.append("'").append(interimStr).append("'").append(quotedArr[j]);
913-
if (i == quotedArr.length - 1 && inputStr.endsWith("'")) {
914-
outputBuf.append("'");
915-
}
916-
} else {
917-
outputBuf.append("'").append(interimStr);
918-
}
880+
String output = inputStr.replaceAll("'", "''");// replace each occurence of single quote with double single during export
881+
StringBuilder finalOutput = new StringBuilder();
882+
int prevStart = 0;
883+
Matcher m = quoteWithBracePattern.matcher(output); // check for pattern like ''{..}'' - see the variable declaration for exact pattern
884+
while (m.find()) { //
885+
String subStr = output.substring(m.start(), m.end()); // isolate such a pattern in the output string
886+
finalOutput.append(output.substring(prevStart, m.start())); // append the substring that precedes such an occurence in the output to final output
887+
if (!isMessagePatternCompatible(subStr)) { // check if the expression of the form ''{..}'' is a valid message pattern/java message format
888+
finalOutput.append(subStr.replaceAll("''", "'")); // if not a valid expression, restore the expression with single quote
919889
} else {
920-
if (doDoubleQuote) {
921-
outputBuf.append("''").append(quotedArr[i]);
922-
} else {
923-
outputBuf.append("'").append(quotedArr[i]);
924-
doDoubleQuote = true;
925-
}
890+
finalOutput.append(subStr);// retain the modified expression with double single quote
926891
}
892+
prevStart = m.end();
927893
}
928-
929-
// Falling back to input string, if the operations yielded a non message compatible string
930-
if (!isMessagePatternCompatible(outputBuf.toString())) {
931-
System.out.println(outputBuf.toString() + " is not message pattern compatible");
894+
finalOutput.append(output.substring(prevStart, output.length())); // append any remaining substring in output
895+
896+
// Falling back to input string, if the operations yield a non message compatible string
897+
if (!isMessagePatternCompatible(finalOutput.toString())) {
898+
System.out.println(finalOutput + " is not message pattern/java message format compatible");
932899
return inputStr;
933900
}
934901

935-
return outputBuf.toString();
902+
return finalOutput.toString();
936903
}
937904

938905

@@ -950,6 +917,11 @@ public static boolean isMessagePatternCompatible(String inputStr) {
950917
// just returns the input string.
951918
return false;
952919
}
920+
try {
921+
java.text.MessageFormat.format(inputStr, (Object[]) null);
922+
} catch (Exception e) {
923+
return false;
924+
}
953925
return true;
954926
}
955927

gp-res-filter/src/test/java/com/ibm/g11n/pipeline/resfilter/impl/JavaPropertiesResourceTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,12 @@ public class JavaPropertiesResourceTest {
171171
bundleBuilder.addResourceString("N","length must be between '{min} and '{max}",14);
172172
bundleBuilder.addResourceString("O","Password should not contain:#.-_'().",15);
173173
bundleBuilder.addResourceString("P","[\\p'{'L'}'\\uFF65]", 16);
174+
bundleBuilder.addResourceString("Q","value must be '{min}",17);
175+
bundleBuilder.addResourceString("R","'",18);
176+
bundleBuilder.addResourceString("S","",19);
177+
bundleBuilder.addResourceString("T","'test'",20);
178+
bundleBuilder.addResourceString("U","'value' should not contain '",21);
179+
bundleBuilder.addResourceString("V","Don't use symbols like +-?.'",22);
174180
WRITE_BUNDLE_ALL = bundleBuilder.build();
175181
}
176182

gp-res-filter/src/test/resource/resfilter/properties/write-output-all.properties

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,10 @@ L = '{' is ok to use
1414
M = The name ''{0}'' is already in use.
1515
N = length must be between '{min} and '{max}
1616
O = Password should not contain\:\#.-_''().
17-
P = [\\p'{'L'}'\\uFF65]
17+
P = [\\p'{'L'}'\\uFF65]
18+
Q = value must be '{min}
19+
R = ''
20+
S =
21+
T = ''test''
22+
U = ''value'' should not contain ''
23+
V = Don''t use symbols like +-?.''

0 commit comments

Comments
 (0)