Skip to content

Instantly share code, notes, and snippets.

@tarot
Last active August 29, 2015 14:24
Show Gist options
  • Select an option

  • Save tarot/9e07fa851e648635990f to your computer and use it in GitHub Desktop.

Select an option

Save tarot/9e07fa851e648635990f to your computer and use it in GitHub Desktop.
JavaScript style String::replace for Apex (Salesforce)
public class Strings {
public interface Replacer {
String apply(String match, String[] p, Integer offset, String str);
}
public static String replaceFirst(String str, String regExp, Replacer replacement) {
return replaceFirst(str, Pattern.compile(regExp), replacement);
}
public static String replaceFirst(String str, Pattern p, Replacer replacement) {
Matcher m = p.matcher(str);
if (m.find()) {
String sub = replacement.apply(m.group(), groupToList(m), m.start(), str);
return str.substring(0, m.start()) + sub + str.substring(m.end());
}
return str;
}
public static String replaceAll(String str, String regExp, Replacer replacement) {
return replaceAll(str, Pattern.compile(regExp), replacement);
}
public static String replaceAll(String str, Pattern p, Replacer replacement) {
String[] joiner = new String[] {};
Matcher m = p.matcher(str);
Integer tail = 0;
for (; m.find(); tail = m.end()) {
joiner.add(str.substring(tail, m.start()));
joiner.add(replacement.apply(m.group(), groupToList(m), m.start(), str));
}
joiner.add(str.substring(tail));
return String.join(joiner, '');
}
private static String[] groupToList(Matcher m) {
String[] groups = new String[] {};
for (Integer i = 1, n = m.groupCount(); i <= n; ++i) {
groups.add(m.group(i));
}
return groups;
}
}
@IsTest
private class StringsTest {
class ShouldNotCalledReplacer implements Strings.Replacer {
public String apply(String match, String[] p, Integer offset, String str) {
System.assert(false);
return null;
}
}
@IsTest
static void testReplaceFirstNotMatched() {
Strings.Replacer replacer = new ShouldNotCalledReplacer();
String actual = Strings.replaceFirst('abc', '[A-Z]', replacer);
system.assertEquals('abc', actual);
}
@IsTest
static void testReplaceAllNotMatched() {
Strings.Replacer replacer = new ShouldNotCalledReplacer();
String actual = Strings.replaceAll('abc', '[A-Z]', replacer);
system.assertEquals('abc', actual);
}
@IsTest
static void testReplaceFirstWithGroup() {
Strings.Replacer replacer = new TestReplaceFirstWithGroupReplacer();
String actual = Strings.replaceFirst('---ABCabc___XYZxyz---', '[A-Z]+([a-z]+)(\\d*)(_|-)', replacer);
system.assertEquals('---(abc, , _)__XYZxyz---', actual);
}
class TestReplaceFirstWithGroupReplacer implements Strings.Replacer {
public String apply(String match, String[] p, Integer offset, String str) {
system.assertEquals('ABCabc_', match);
system.assertEquals(new String[] { 'abc', '', '_' }, p);
system.assertEquals(3, offset);
system.assertEquals('---ABCabc___XYZxyz---', str);
return '(' + String.join(p, ', ') + ')';
}
}
@IsTest
static void testReplaceFirstWithoutGroup() {
Strings.Replacer replacer = new TestReplaceFirstWithoutGroupReplacer();
String actual = Strings.replaceFirst('abc def', '[a-z]+', replacer);
system.assertEquals('ABC def', actual);
}
class TestReplaceFirstWithoutGroupReplacer implements Strings.Replacer {
public String apply(String match, String[] p, Integer offset, String str) {
system.assertEquals('abc', match);
system.assertEquals(new String[] {}, p);
system.assertEquals(0, offset);
system.assertEquals('abc def', str);
return match.toUpperCase();
}
}
@IsTest
static void testReplaceAllWithGroup() {
Strings.Replacer replacer = new TestReplaceAllWithGroupReplacer();
String actual = Strings.replaceAll('---ABCabc___XYZxyz---', '[A-Z]+([a-z]+)(\\d*)(_|-)', replacer);
system.assertEquals('---(abc, , _)__(xyz, , -)--', actual);
}
class TestReplaceAllWithGroupReplacer implements Strings.Replacer {
Integer callCount = 0;
public String apply(String match, String[] p, Integer offset, String str) {
if (callCount == 0) {
system.assertEquals('ABCabc_', match);
system.assertEquals(new String[] { 'abc', '', '_' }, p);
system.assertEquals(3, offset);
system.assertEquals('---ABCabc___XYZxyz---', str);
} else {
system.assertEquals('XYZxyz-', match);
system.assertEquals(new String[] { 'xyz', '', '-' }, p);
system.assertEquals(12, offset);
system.assertEquals('---ABCabc___XYZxyz---', str);
}
callCount++;
return '(' + String.join(p, ', ') + ')';
}
}
@IsTest
static void testReplaceAllWithoutGroup() {
Strings.Replacer replacer = new TestReplaceAllWithoutGroupReplacer();
String actual = Strings.replaceAll('abc def', '[a-z]+', replacer);
system.assertEquals('ABC DEF', actual);
}
class TestReplaceAllWithoutGroupReplacer implements Strings.Replacer {
Integer callCount = 0;
public String apply(String match, String[] p, Integer offset, String str) {
if (callCount == 0) {
system.assertEquals('abc', match);
system.assertEquals(new String[] {}, p);
system.assertEquals(0, offset);
system.assertEquals('abc def', str);
} else {
system.assertEquals('def', match);
system.assertEquals(new String[] {}, p);
system.assertEquals(4, offset);
system.assertEquals('abc def', str);
}
callCount++;
return match.toUpperCase();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment