From af457dad44c07e3c03d83745a59fb8dde158db0f Mon Sep 17 00:00:00 2001 From: Mark Ingram Date: Mon, 26 Oct 2015 09:40:58 +0000 Subject: [PATCH] Make Inflector more amenable to thread safety. - reduced public API to 2 synchronized methods: singularize/pluralize - eagerly construct singleton to avoid construction race - remove unnecessary static lists/methods --- .../org/jsonschema2pojo/util/Inflector.java | 29 +++++++------- .../jsonschema2pojo/util/InflectorTest.java | 39 +++++++++++++++++++ 2 files changed, 52 insertions(+), 16 deletions(-) diff --git a/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/util/Inflector.java b/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/util/Inflector.java index 01fe19910..8d8786f58 100644 --- a/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/util/Inflector.java +++ b/jsonschema2pojo-core/src/main/java/org/jsonschema2pojo/util/Inflector.java @@ -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 plurals = new ArrayList(); - private static List singulars = new ArrayList(); - private static List uncountables = new ArrayList(); + private List plurals = new ArrayList(); + private List singulars = new ArrayList(); + private List uncountables = new ArrayList(); - private static Inflector instance; // (Pseudo-)Singleton instance. + private static Inflector instance = new Inflector(); private Inflector() { // Woo, you can't touch me. @@ -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"); @@ -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; } @@ -154,30 +151,30 @@ private String replaceWithFirstRule(String word, List 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); } diff --git a/jsonschema2pojo-core/src/test/java/org/jsonschema2pojo/util/InflectorTest.java b/jsonschema2pojo-core/src/test/java/org/jsonschema2pojo/util/InflectorTest.java index f147cf62d..d9dc0b234 100644 --- a/jsonschema2pojo-core/src/test/java/org/jsonschema2pojo/util/InflectorTest.java +++ b/jsonschema2pojo-core/src/test/java/org/jsonschema2pojo/util/InflectorTest.java @@ -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 @@ -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 { + private final String something; + + public SingulariseSomething(String something) { + this.something = something; + } + + @Override + public String call() throws Exception { + return Inflector.getInstance().singularize(something); + } + } + + List tasks = new ArrayList(); + for (int i = 0; i < numberOfTasks; i++) { + tasks.add(new SingulariseSomething(i + "zebras")); + } + + ExecutorService executorService = Executors.newFixedThreadPool(numberOfThreads); + List> futures = executorService.invokeAll(tasks); + + for (Future future : futures) { + future.get(); + } + } + }