Skip to content

Commit

Permalink
Merge pull request #435 from markdingram/master
Browse files Browse the repository at this point in the history
Make Inflector more amenable to thread safety.
  • Loading branch information
joelittlejohn committed Oct 26, 2015
2 parents b3980f4 + af457da commit f399f9c
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ public class Inflector {
private static final Pattern UNDERSCORE_PATTERN_1 = Pattern.compile("([A-Z]+)([A-Z][a-z])");
private static final Pattern UNDERSCORE_PATTERN_2 = Pattern.compile("([a-z\\d])([A-Z])");

private static List<RuleAndReplacement> plurals = new ArrayList<RuleAndReplacement>();
private static List<RuleAndReplacement> singulars = new ArrayList<RuleAndReplacement>();
private static List<String> uncountables = new ArrayList<String>();
private List<RuleAndReplacement> plurals = new ArrayList<RuleAndReplacement>();
private List<RuleAndReplacement> singulars = new ArrayList<RuleAndReplacement>();
private List<String> uncountables = new ArrayList<String>();

private static Inflector instance; // (Pseudo-)Singleton instance.
private static Inflector instance = new Inflector();

private Inflector() {
// Woo, you can't touch me.
Expand Down Expand Up @@ -109,13 +109,10 @@ private void initialize() {
}

public static Inflector getInstance() {
if (instance == null) {
instance = new Inflector();
}
return instance;
}

public String underscore(String camelCasedWord) {
private String underscore(String camelCasedWord) {

// Regexes in Java are fucking stupid...
String underscoredWord = UNDERSCORE_PATTERN_1.matcher(camelCasedWord).replaceAll("$1_$2");
Expand All @@ -125,14 +122,14 @@ public String underscore(String camelCasedWord) {
return underscoredWord;
}

public String pluralize(String word) {
public synchronized String pluralize(String word) {
if (uncountables.contains(word.toLowerCase())) {
return word;
}
return replaceWithFirstRule(word, plurals);
}

public String singularize(String word) {
public synchronized String singularize(String word) {
if (uncountables.contains(word.toLowerCase())) {
return word;
}
Expand All @@ -154,30 +151,30 @@ private String replaceWithFirstRule(String word, List<RuleAndReplacement> ruleAn
return word;
}

public String tableize(String className) {
private String tableize(String className) {
return pluralize(underscore(className));
}

public String tableize(Class<?> klass) {
private String tableize(Class<?> klass) {
// Strip away package name - we only want the 'base' class name.
String className = klass.getName().replace(klass.getPackage().getName() + ".", "");
return tableize(className);
}

public static void plural(String rule, String replacement) {
private void plural(String rule, String replacement) {
plurals.add(0, new RuleAndReplacement(rule, replacement));
}

public static void singular(String rule, String replacement) {
private void singular(String rule, String replacement) {
singulars.add(0, new RuleAndReplacement(rule, replacement));
}

public static void irregular(String singular, String plural) {
private void irregular(String singular, String plural) {
plural(singular, plural);
singular(plural, singular);
}

public static void uncountable(String... words) {
private void uncountable(String... words) {
for (String word : words) {
uncountables.add(word);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@

import org.junit.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class InflectorTest {

@Test
Expand Down Expand Up @@ -59,4 +67,35 @@ public void testSingularize() {

}

@Test
public void testThreadSafety() throws InterruptedException, ExecutionException {
final int numberOfThreads = 10;
final int numberOfTasks = 1000;

class SingulariseSomething implements Callable<String> {
private final String something;

public SingulariseSomething(String something) {
this.something = something;
}

@Override
public String call() throws Exception {
return Inflector.getInstance().singularize(something);
}
}

List<SingulariseSomething> tasks = new ArrayList<SingulariseSomething>();
for (int i = 0; i < numberOfTasks; i++) {
tasks.add(new SingulariseSomething(i + "zebras"));
}

ExecutorService executorService = Executors.newFixedThreadPool(numberOfThreads);
List<Future<String>> futures = executorService.invokeAll(tasks);

for (Future<String> future : futures) {
future.get();
}
}

}

0 comments on commit f399f9c

Please # to comment.