Author: chris.laprun(a)jboss.com
Date: 2010-03-19 11:50:46 -0400 (Fri, 19 Mar 2010)
New Revision: 2314
Modified:
components/common/trunk/common/src/main/java/org/gatein/common/text/TextTools.java
components/common/trunk/common/src/test/java/org/gatein/common/StringTestCase.java
Log:
- Rewrote TextTools.replaceBoundedString implementation so that we can also do partial
matching in case the suffix is specified as optional.
- Added test cases.
Modified:
components/common/trunk/common/src/main/java/org/gatein/common/text/TextTools.java
===================================================================
---
components/common/trunk/common/src/main/java/org/gatein/common/text/TextTools.java 2010-03-19
15:23:35 UTC (rev 2313)
+++
components/common/trunk/common/src/main/java/org/gatein/common/text/TextTools.java 2010-03-19
15:50:46 UTC (rev 2314)
@@ -100,25 +100,45 @@
*/
public static String replaceAllInstancesOfBoundedString(String initial, String prefix,
String suffix, String replacement)
{
- return replaceBoundedString(initial, prefix, suffix, replacement, true, false);
+ return replaceBoundedString(initial, prefix, suffix, replacement, true, false,
false);
}
+ public static String replaceAllInstancesOfBoundedString(String initial, String prefix,
String suffix, StringReplacementGenerator generator)
+ {
+ return replaceBoundedString(initial, prefix, suffix, generator, true, false,
false);
+ }
+
public static String replaceBoundedString(String initial, String prefix, String
suffix, String replacement,
boolean replaceIfBoundedStringEmpty, boolean
keepBoundaries)
{
ParameterValidation.throwIllegalArgExceptionIfNull(replacement,
"replacement");
return replaceBoundedString(initial, prefix, suffix, new
ConstantStringReplacementGenerator(replacement),
- replaceIfBoundedStringEmpty, keepBoundaries);
+ replaceIfBoundedStringEmpty, keepBoundaries, false);
}
+ public static String replaceBoundedString(String initial, String prefix, String
suffix, String replacement,
+ boolean replaceIfBoundedStringEmpty, boolean
keepBoundaries, boolean suffixIsOptional)
+ {
+ ParameterValidation.throwIllegalArgExceptionIfNull(replacement,
"replacement");
+ return replaceBoundedString(initial, prefix, suffix, new
ConstantStringReplacementGenerator(replacement),
+ replaceIfBoundedStringEmpty, keepBoundaries, suffixIsOptional);
+ }
+
+ public static String replaceBoundedString(String initial, String prefix, String
suffix, StringReplacementGenerator generator,
+ boolean replaceIfBoundedStringEmpty, boolean
keepBoundaries)
+ {
+ return replaceBoundedString(initial, prefix, suffix, generator,
replaceIfBoundedStringEmpty, keepBoundaries, false);
+ }
+
/**
* Replace instances of Strings delimited by the given prefix and suffix (hence,
bounded) by a replacement String
* computed by the specified StringReplacementGenerator based on the current bounded
String match. It is possible to
* specify whether the substitution will happen only if the delimited String is
non-empty by setting
* <code>replaceIfBoundedStringEmpty</code> to
<code>false</code>. It is also possible to keep the boundaries (prefix
- * and suffix) after the substitution by setting
<code>keepBoundaries</code> to <code>true</code>.
- * <p/>
- * See org.gatein.common.StringTestCase.testReplaceBoundedString() for usage details.
+ * and suffix) after the substitution by setting
<code>keepBoundaries</code> to <code>true</code>. <br/> Note
that it
+ * is possible to specify that the suffix is optional, in which case, the prefix will
be passed on to the specified
+ * StringReplacementGenerator and be replaced. <br/> See
org.gatein.common.StringTestCase.testReplaceBoundedString()
+ * for usage details.
*
* @param initial the String in which we want to replace bounded
Strings
* @param prefix the prefix used identify the beginning of the
String targeted for replacement
@@ -129,10 +149,11 @@
* of the replacement String between the prefix and
suffix)
* @param keepBoundaries <code>true</code> to keep the prefix
and suffix markers in the resulting
* String
+ * @param suffixIsOptional whether or not the suffix is optional
* @return a String where the Strings marked by prefix and suffix have been replaced
by replacement
*/
- public static String replaceBoundedString(String initial, String prefix, String
suffix, StringReplacementGenerator generator,
- boolean replaceIfBoundedStringEmpty, boolean
keepBoundaries)
+ public static String replaceBoundedString(final String initial, final String prefix,
final String suffix, final StringReplacementGenerator generator,
+ final boolean replaceIfBoundedStringEmpty,
final boolean keepBoundaries, final boolean suffixIsOptional)
{
if (ParameterValidation.isNullOrEmpty(initial))
{
@@ -142,39 +163,110 @@
ParameterValidation.throwIllegalArgExceptionIfNull(generator,
"StringReplacementGenerator");
ParameterValidation.throwIllegalArgExceptionIfNullOrEmpty(prefix,
"prefix", "Tools.replaceBoundedString");
- ParameterValidation.throwIllegalArgExceptionIfNullOrEmpty(suffix,
"suffix", "Tools.replaceBoundedString");
- StringBuffer tmp = new StringBuffer(initial);
+ StringBuilder tmp = new StringBuilder(initial);
int prefixIndex = tmp.indexOf(prefix);
- int suffixLength = suffix.length();
- int prefixLength = prefix.length();
+ final int prefixLength = prefix.length();
+ boolean suffixAbsent = suffix == null;
+ // nothing to do if didn't ask for an optional suffix and we have one and
it's not present in our string
+ if (!suffixIsOptional && suffix != null && tmp.indexOf(suffix) ==
-1)
+ {
+ return initial;
+ }
+
+ // loop as long as we can find an instance of prefix in the String
while (prefixIndex != -1)
{
- int suffixIndex = tmp.indexOf(suffix, prefixIndex);
+ int suffixIndex;
+ if (suffixAbsent)
+ {
+ // replace prefix with replacement
+ if (keepBoundaries)
+ {
+ // just insert replacement for prefix
+ tmp.insert(prefixIndex + prefixLength, generator.getReplacementFor(prefix,
prefix, suffix));
+ }
+ else
+ {
+ // delete prefix then insert remplacement instead
+ tmp.delete(prefixIndex, prefixIndex + prefixLength);
+ tmp.insert(prefixIndex, generator.getReplacementFor(prefix, prefix,
suffix));
+ }
- if (suffixIndex != -1)
+ // new lookup starting position
+ prefixIndex = tmp.indexOf(prefix, prefixIndex + prefixLength);
+ }
+ else
{
- // we don't care about empty bounded strings or prefix and suffix
don't delimit an empty String => replace!
- if (replaceIfBoundedStringEmpty || suffixIndex != prefixIndex +
prefixLength)
+ // look for suffix
+ suffixIndex = tmp.indexOf(suffix, prefixIndex);
+
+ if (suffixIndex == -1)
{
- String match;
- if (keepBoundaries)
+ // we haven't found suffix in the rest of the String so don't look
for it again
+ suffixAbsent = true;
+ continue;
+ }
+ else
+ {
+ if (suffixIsOptional)
{
- match = tmp.substring(prefixIndex + prefixLength, suffixIndex);
- tmp.delete(prefixIndex + prefixLength, suffixIndex);
- tmp.insert(prefixIndex + prefixLength,
generator.getReplacementFor(match));
+ // if suffix is optional, look for potential next prefix instance that
we'd need to replace
+ int nextPrefixIndex = tmp.indexOf(prefix, prefixIndex + prefixLength);
+
+ if (nextPrefixIndex != -1 && nextPrefixIndex <=
suffixIndex)
+ {
+ // we've found an in-between prefix, use it as the suffix for
the current match
+ // delete prefix then insert remplacement instead
+ tmp.delete(prefixIndex, prefixIndex + prefixLength);
+ String replacement = generator.getReplacementFor(prefix, prefix,
suffix);
+ tmp.insert(prefixIndex, replacement);
+
+ prefixIndex = nextPrefixIndex - prefixLength +
replacement.length();
+ continue;
+ }
}
- else
+
+ // we don't care about empty bounded strings or prefix and suffix
don't delimit an empty String => replace!
+ if (replaceIfBoundedStringEmpty || suffixIndex != prefixIndex +
prefixLength)
{
- match = tmp.substring(prefixIndex, suffixIndex + suffixLength);
- tmp.delete(prefixIndex, suffixIndex + suffixLength);
- tmp.insert(prefixIndex, generator.getReplacementFor(match));
+ String match = tmp.substring(prefixIndex + prefixLength, suffixIndex);
+ if (keepBoundaries)
+ {
+ if (suffix != null)
+ {
+ // delete only match
+ tmp.delete(prefixIndex + prefixLength, suffixIndex);
+ }
+ else
+ {
+ // delete nothing
+ }
+ tmp.insert(prefixIndex + prefixLength,
generator.getReplacementFor(match, prefix, suffix));
+ }
+ else
+ {
+ int suffixLength = suffix != null ? suffix.length() : 0;
+
+ if (suffix != null)
+ {
+ // if we have a suffix, delete everything between start of prefix
and end of suffix
+ tmp.delete(prefixIndex, suffixIndex + suffixLength);
+ }
+ else
+ {
+ // only delete prefix
+ tmp.delete(prefixIndex, prefixIndex + prefixLength);
+ }
+ tmp.insert(prefixIndex, generator.getReplacementFor(match, prefix,
suffix));
+ }
}
}
+
+ prefixIndex = tmp.indexOf(prefix, prefixIndex + prefixLength);
+
}
-
- prefixIndex = tmp.indexOf(prefix, prefixIndex + prefixLength);
}
return tmp.toString();
@@ -182,7 +274,7 @@
public static interface StringReplacementGenerator
{
- String getReplacementFor(String match);
+ String getReplacementFor(String match, String prefix, String suffix);
}
public static class ConstantStringReplacementGenerator implements
StringReplacementGenerator
@@ -194,7 +286,7 @@
this.replacement = replacement;
}
- public String getReplacementFor(String match)
+ public String getReplacementFor(String match, String prefix, String suffix)
{
return replacement;
}
Modified:
components/common/trunk/common/src/test/java/org/gatein/common/StringTestCase.java
===================================================================
---
components/common/trunk/common/src/test/java/org/gatein/common/StringTestCase.java 2010-03-19
15:23:35 UTC (rev 2313)
+++
components/common/trunk/common/src/test/java/org/gatein/common/StringTestCase.java 2010-03-19
15:50:46 UTC (rev 2314)
@@ -31,6 +31,10 @@
*/
public class StringTestCase extends TestCase
{
+ private static final String REPLACEMENT = "REPLACEMENT";
+ private static final String PREFIX = "PREFIX";
+ private static final String SUFFIX = "SUF";
+ private static final TestStringReplacementGenerator DEF_GEN = new
TestStringReplacementGenerator(REPLACEMENT);
public StringTestCase(String name)
{
@@ -46,15 +50,102 @@
assertEquals("_defg_defg_", TextTools.replace("_abc_abc_",
"abc", "defg"));
}
- public void testReplaceBoundedString()
+ public void testReplaceAllInstancesOfBoundedString()
{
- assertEquals("",
TextTools.replaceAllInstancesOfBoundedString("", "PREFIX",
"SUFFIX", "REPLACEMENT"));
- assertEquals("REPLACEMENT",
TextTools.replaceAllInstancesOfBoundedString("PREFIXSUFFIX", "PREFIX",
"SUFFIX", "REPLACEMENT"));
- assertEquals("PREFIXSUFFIX",
TextTools.replaceBoundedString("PREFIXSUFFIX", "PREFIX",
"SUFFIX", "REPLACEMENT", false, true));
- assertEquals("PREFIXSUFFIX",
TextTools.replaceBoundedString("PREFIXSUFFIX", "PREFIX",
"SUFFIX", "REPLACEMENT", false, false));
- assertEquals("aaaaREPLACEMENTccccc",
TextTools.replaceAllInstancesOfBoundedString("aaaaPREFIXbbbbbSUFFIXccccc",
"PREFIX", "SUFFIX", "REPLACEMENT"));
- assertEquals("aaaPREFIXbbbbSUFF",
TextTools.replaceAllInstancesOfBoundedString("aaaPREFIXbbbbSUFF",
"PREFIX", "SUFFIX", "REPLACEMENT"));
+ assertEquals("",
TextTools.replaceAllInstancesOfBoundedString("", PREFIX, SUFFIX, REPLACEMENT));
+ assertEquals("",
TextTools.replaceAllInstancesOfBoundedString("", PREFIX, "",
REPLACEMENT));
+ assertEquals("",
TextTools.replaceAllInstancesOfBoundedString("", "", "",
REPLACEMENT));
+
+ DEF_GEN.setExpectedMatch("");
+ assertEquals(REPLACEMENT,
TextTools.replaceAllInstancesOfBoundedString("PREFIXSUF", PREFIX, SUFFIX,
DEF_GEN));
+
+ DEF_GEN.setExpectedMatch("bbbbb");
+ assertEquals("aaaaREPLACEMENTccccc",
TextTools.replaceAllInstancesOfBoundedString("aaaaPREFIXbbbbbSUFccccc", PREFIX,
SUFFIX, DEF_GEN));
+
+ DEF_GEN.setExpectedMatch(null);
+ assertEquals("aaaPREFIXbbbbSUFF",
TextTools.replaceAllInstancesOfBoundedString("aaaPREFIXbbbbSUFF", PREFIX,
"SUFFI", DEF_GEN));
assertEquals("aRcccReeeR",
TextTools.replaceAllInstancesOfBoundedString("aPbbScccPdSeeePS", "P",
"S", "R"));
- assertEquals("PSaPScccReeePS",
TextTools.replaceBoundedString("PSaPScccPdSeeePS", "P", "S",
"R", false, false));
}
+
+ public void testReplaceBoundedString()
+ {
+ replaceBoundedString(false);
+ replaceBoundedString(true);
+ }
+
+ private void replaceBoundedString(boolean suffixIsOptional)
+ {
+ buildTestWithDefaults(PREFIX + SUFFIX, PREFIX + SUFFIX, false, true,
suffixIsOptional, "");
+ buildTestWithDefaults(PREFIX + SUFFIX, PREFIX + SUFFIX, false, false,
suffixIsOptional, "");
+ buildTestWithDefaults(REPLACEMENT, PREFIX + SUFFIX, true, false, suffixIsOptional,
"");
+ buildTestWithDefaults(PREFIX + REPLACEMENT + SUFFIX, PREFIX + SUFFIX, true, true,
suffixIsOptional, "");
+ buildTest(PREFIX + SUFFIX, PREFIX + SUFFIX, "", PREFIX, SUFFIX, false,
false, suffixIsOptional, "");
+ buildTest("PSaPScccReeePS", "PSaPScccPdSeeePS", "R",
"P", "S", false, false, suffixIsOptional, "d");
+ }
+
+ private void buildTestWithDefaults(String expected, String initial, boolean
replaceIfBoundedStringEmpty, boolean keepBoundaries, boolean suffixIsOptional, String...
expectedMatches)
+ {
+ buildTest(expected, initial, null, PREFIX, SUFFIX, replaceIfBoundedStringEmpty,
keepBoundaries, suffixIsOptional, expectedMatches);
+ }
+
+ private void buildTest(String expected, String initial, String replacement, String
prefix, String suffix, boolean replaceIfBoundedStringEmpty, boolean keepBoundaries,
boolean suffixIsOptional, String... expectedMatches)
+ {
+ if (replacement == null)
+ {
+ replacement = REPLACEMENT;
+ }
+ TestStringReplacementGenerator gen = new
TestStringReplacementGenerator(replacement);
+ gen.setExpectedMatch(expectedMatches);
+
+ assertEquals(expected, TextTools.replaceBoundedString(initial, prefix, suffix, gen,
replaceIfBoundedStringEmpty, keepBoundaries, suffixIsOptional));
+ }
+
+ public void testReplaceStringsWithNullSuffix()
+ {
+ replaceStringsWithOptionalSuffix(false, null);
+ replaceStringsWithOptionalSuffix(true, null);
+ }
+
+ private void replaceStringsWithOptionalSuffix(boolean suffixIsOptional, String
suffix)
+ {
+ buildTest(REPLACEMENT + "blah", PREFIX + "blah", REPLACEMENT,
PREFIX, suffix, false, false, suffixIsOptional, PREFIX);
+ buildTest(PREFIX + REPLACEMENT + "blah", PREFIX + "blah",
REPLACEMENT, PREFIX, suffix, false, true, suffixIsOptional, PREFIX);
+ buildTest(REPLACEMENT + "blah", PREFIX + "blah", REPLACEMENT,
PREFIX, suffix, true, false, suffixIsOptional, PREFIX);
+ buildTest(REPLACEMENT, PREFIX, REPLACEMENT, PREFIX, suffix, true, false,
suffixIsOptional, PREFIX);
+ }
+
+ public void testReplaceStringsWithOptionalSuffix()
+ {
+ replaceStringsWithOptionalSuffix(true, SUFFIX);
+ buildTest(REPLACEMENT + "blah" + REPLACEMENT + "foo", PREFIX +
"blah" + PREFIX + "replaced" + SUFFIX + "foo", REPLACEMENT,
PREFIX, SUFFIX, false, false, true, PREFIX, "replaced");
+ buildTest(REPLACEMENT + "blah" + PREFIX + REPLACEMENT + SUFFIX +
"foo", PREFIX + "blah" + PREFIX + "replaced" + SUFFIX +
"foo", REPLACEMENT, PREFIX, SUFFIX, false, true, true, PREFIX,
"replaced");
+ }
+
+ static class TestStringReplacementGenerator implements
TextTools.StringReplacementGenerator
+ {
+ private String replacement;
+ private String[] expectedMatch;
+ private int invocationCount;
+
+ TestStringReplacementGenerator(String replacement)
+ {
+ this.replacement = replacement;
+ }
+
+ public void setExpectedMatch(String... expectedMatch)
+ {
+ this.expectedMatch = expectedMatch;
+ this.invocationCount = 0;
+ }
+
+ public String getReplacementFor(String match, String prefix, String suffix)
+ {
+ if (expectedMatch == null)
+ {
+ fail("getReplacementFor shouldn't have been called");
+ }
+ assertEquals("'" + expectedMatch[invocationCount++] +
"'", "'" + match + "'");
+ return replacement;
+ }
+ }
}