Repository: redpen-cc/redpen
Pull request #562 (2016-03-07 10:30:38)

Use all available validators in RedPen Server
RedPen Server now serves all validators with all default properties.
This will allow using all available validators and properties in WordPress plugin.

This pull request contains also previous ones, please review starting from commit https://github.com/redpen-cc/redpen/commit/abf7b9fa9ccc36c5cba3abdd9f84cd426b9bcb04


Patch:
diff --git a/pom.xml b/pom.xml
index ffa1b1dc..bc71f543 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
     <modelVersion>4.0.0</modelVersion>
 
     <groupId>cc.redpen</groupId>
-    <version>1.4.8-SNAPSHOT</version>
+    <version>1.5.0-SNAPSHOT</version>
     <artifactId>redpen</artifactId>
     <url>http://redpen.cc</url>
     <name>redpen</name>
diff --git a/redpen-cli/pom.xml b/redpen-cli/pom.xml
index cb9a2cdf..5beccacb 100644
--- a/redpen-cli/pom.xml
+++ b/redpen-cli/pom.xml
@@ -5,11 +5,11 @@
     <parent>
         <groupId>cc.redpen</groupId>
         <artifactId>redpen</artifactId>
-        <version>1.4.8-SNAPSHOT</version>
+        <version>1.5.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>redpen-cli</artifactId>
-    <version>1.4.8-SNAPSHOT</version>
+    <version>1.5.0-SNAPSHOT</version>
     <name>redpen-cli</name>
     <description>RedPen is an open source proofreading tool a tool to check if your technical documents meet the writing standard . RedPen supports various markup text formats (Markdown, Textile, AsciiDoc, and LaTeX).</description>
     <url>http://redpen.cc</url>
@@ -106,12 +106,12 @@
         <dependency>
             <groupId>cc.redpen</groupId>
             <artifactId>redpen-core</artifactId>
-            <version>1.4.8-SNAPSHOT</version>
+            <version>1.5.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>cc.redpen</groupId>
             <artifactId>redpen-plugin</artifactId>
-            <version>1.4.8-SNAPSHOT</version>
+            <version>1.5.0-SNAPSHOT</version>
             <scope>test</scope>
         </dependency>
         <dependency>
diff --git a/redpen-core/pom.xml b/redpen-core/pom.xml
index 564e534c..71904809 100644
--- a/redpen-core/pom.xml
+++ b/redpen-core/pom.xml
@@ -5,11 +5,11 @@
     <parent>
         <groupId>cc.redpen</groupId>
         <artifactId>redpen</artifactId>
-        <version>1.4.8-SNAPSHOT</version>
+        <version>1.5.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>redpen-core</artifactId>
-    <version>1.4.8-SNAPSHOT</version>
+    <version>1.5.0-SNAPSHOT</version>
     <name>redpen-core</name>
     <description>RedPen is an open source proofreading tool a tool to check if your technical documents meet the writing standard . RedPen supports various markup text formats (Markdown, Textile, AsciiDoc, and LaTeX).</description>
     <url>http://redpen.cc</url>
diff --git a/redpen-core/src/main/java/cc/redpen/RedPen.java b/redpen-core/src/main/java/cc/redpen/RedPen.java
index 0fab8767..8250bc03 100644
--- a/redpen-core/src/main/java/cc/redpen/RedPen.java
+++ b/redpen-core/src/main/java/cc/redpen/RedPen.java
@@ -39,7 +39,7 @@ import java.util.*;
 public class RedPen {
     private static final Logger LOG = LoggerFactory.getLogger(RedPen.class);
 
-    public static final String VERSION = "1.4.7";
+    public static final String VERSION = "1.5.0";
 
     private final Configuration configuration;
     private final SentenceExtractor sentenceExtractor;
diff --git a/redpen-core/src/main/java/cc/redpen/config/Configuration.java b/redpen-core/src/main/java/cc/redpen/config/Configuration.java
index e42d21be..08df6341 100644
--- a/redpen-core/src/main/java/cc/redpen/config/Configuration.java
+++ b/redpen-core/src/main/java/cc/redpen/config/Configuration.java
@@ -106,7 +106,7 @@ public class Configuration implements Serializable, Cloneable {
     }
 
     /**
-     * returns Tokenizer aasociated with this configuration
+     * returns Tokenizer associated with this configuration
      *
      * @return tokenizer
      */
diff --git a/redpen-core/src/main/java/cc/redpen/config/ConfigurationExporter.java b/redpen-core/src/main/java/cc/redpen/config/ConfigurationExporter.java
index 2bcab416..4e7c5ddd 100644
--- a/redpen-core/src/main/java/cc/redpen/config/ConfigurationExporter.java
+++ b/redpen-core/src/main/java/cc/redpen/config/ConfigurationExporter.java
@@ -44,14 +44,14 @@ public class ConfigurationExporter {
     sax.writeStartElement("validators");
 
     for (ValidatorConfiguration v : validators) {
-      if (v.getAttributes().isEmpty()) sax.writeEmptyElement("validator"); else sax.writeStartElement("validator");
+      if (v.getProperties().isEmpty()) sax.writeEmptyElement("validator"); else sax.writeStartElement("validator");
       sax.writeAttribute("name", v.getConfigurationName());
-      for (Map.Entry<String, String> attr : v.getAttributes().entrySet()) {
+      for (Map.Entry<String, String> prop : v.getProperties().entrySet()) {
         sax.writeEmptyElement("property");
-        sax.writeAttribute("name", attr.getKey());
-        sax.writeAttribute("value", attr.getValue());
+        sax.writeAttribute("name", prop.getKey());
+        sax.writeAttribute("value", prop.getValue());
       }
-      if (!v.getAttributes().isEmpty()) sax.writeEndElement();
+      if (!v.getProperties().isEmpty()) sax.writeEndElement();
     }
 
     sax.writeEndElement();
diff --git a/redpen-core/src/main/java/cc/redpen/config/ConfigurationLoader.java b/redpen-core/src/main/java/cc/redpen/config/ConfigurationLoader.java
index 00b4a1d7..d90ba349 100644
--- a/redpen-core/src/main/java/cc/redpen/config/ConfigurationLoader.java
+++ b/redpen-core/src/main/java/cc/redpen/config/ConfigurationLoader.java
@@ -243,7 +243,7 @@ public class ConfigurationLoader {
             Element propertyElement = (Element) pNode;
             if (propertyElement.getNodeName().equals("property")
                     && currentConfiguration != null) {
-                currentConfiguration.addAttribute(
+                currentConfiguration.addProperty(
                         propertyElement.getAttribute("name"),
                         propertyElement.getAttribute("value"));
             }
diff --git a/redpen-core/src/main/java/cc/redpen/config/ValidatorConfiguration.java b/redpen-core/src/main/java/cc/redpen/config/ValidatorConfiguration.java
index 7a24b949..6e8df1a4 100644
--- a/redpen-core/src/main/java/cc/redpen/config/ValidatorConfiguration.java
+++ b/redpen-core/src/main/java/cc/redpen/config/ValidatorConfiguration.java
@@ -27,35 +27,41 @@ import java.util.Objects;
  */
 public class ValidatorConfiguration implements Serializable, Cloneable {
     private final String configurationName;
-    private Map<String, String> attributes;
+    private Map<String, String> properties;
 
     /**
-     * Constructor.
-     *
      * @param name name configuration settings
      */
     public ValidatorConfiguration(String name) {
+        this(name, new HashMap<>());
+    }
+
+    /**
+     * @param name name configuration settings
+     * @param properties validator properties
+     */
+    public ValidatorConfiguration(String name, Map<String, String> properties) {
         this.configurationName = name;
-        this.attributes = new HashMap<>();
+        this.properties = properties;
     }
 
     /**
-     * Return the attributes map
+     * Return the properties map
      *
-     * @return a map of the configuration attributes to their values
+     * @return a map of the configuration properties to their values
      */
-    public Map<String, String> getAttributes() {
-        return attributes;
+    public Map<String, String> getProperties() {
+        return properties;
     }
 
     /**
-     * Get attribute value.
+     * Get property value.
      *
-     * @param name attribute name
-     * @return value of the specified attribute
+     * @param name property name
+     * @return value of the specified property
      */
-    public String getAttribute(String name) {
-        return this.attributes.get(name);
+    public String getProperty(String name) {
+        return this.properties.get(name);
     }
 
     /**
@@ -77,27 +83,20 @@ public class ValidatorConfiguration implements Serializable, Cloneable {
     }
 
     /**
-     * Add an attribute.
+     * Add an property.
      *
-     * @param name  attribute name
-     * @param value attribute value
+     * @param name  property name
+     * @param value property value
      * @return this object
      */
-    public ValidatorConfiguration addAttribute(String name, String value) {
-        attributes.put(name, value);
+    public ValidatorConfiguration addProperty(String name, Object value) {
+        properties.put(name, String.valueOf(value));
         return this;
     }
 
-    /**
-     * Add an attribute.
-     *
-     * @param name  attribute name
-     * @param value attribute value
-     * @return this object
-     */
-    public ValidatorConfiguration addAttribute(String name, boolean value) {
-        attributes.put(name, String.valueOf(value));
-        return this;
+    @Deprecated
+    public ValidatorConfiguration addAttribute(String name, Object value) {
+        return addProperty(name, value);
     }
 
     @Override public boolean equals(Object o) {
@@ -105,7 +104,7 @@ public class ValidatorConfiguration implements Serializable, Cloneable {
         if (!(o instanceof ValidatorConfiguration)) return false;
         ValidatorConfiguration that = (ValidatorConfiguration)o;
         return Objects.equals(configurationName, that.configurationName) &&
-               Objects.equals(attributes, that.attributes);
+               Objects.equals(properties, that.properties);
     }
 
     @Override public int hashCode() {
@@ -122,7 +121,7 @@ public class ValidatorConfiguration implements Serializable, Cloneable {
     @Override public ValidatorConfiguration clone() {
         try {
             ValidatorConfiguration clone = (ValidatorConfiguration)super.clone();
-            clone.attributes = new HashMap<>(attributes);
+            clone.properties = new HashMap<>(properties);
             return clone;
         }
         catch (CloneNotSupportedException e) {
diff --git a/redpen-core/src/main/java/cc/redpen/util/SpellingUtils.java b/redpen-core/src/main/java/cc/redpen/util/SpellingUtils.java
deleted file mode 100644
index 642246b4..00000000
--- a/redpen-core/src/main/java/cc/redpen/util/SpellingUtils.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- * redpen: a text inspection tool
- * Copyright (c) 2014-2015 Recruit Technologies Co., Ltd. and contributors
- * (see CONTRIBUTORS.md)
- * <p>
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package cc.redpen.util;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.*;
-
-/**
- * Spelling utility
- */
-public class SpellingUtils {
-
-    private static final String DEFAULT_LANGUAGE = "en";
-    private static final Logger LOG = LoggerFactory.getLogger(SpellingUtils.class);
-
-    // a map of dictionaries per language
-    private static Map<String, Set<String>> dictionaries = new HashMap<>();
-    private static final String DEFAULT_RESOURCE_PATH = "default-resources/spellchecker";
-
-    protected static void loadDictionary(String lang) {
-        if (dictionaries.get(lang) == null) {
-            String defaultDictionaryFile = DEFAULT_RESOURCE_PATH + "/spellchecker-" + lang + ".dat";
-            Set<String> dictionary = new DictionaryLoader<Set<String>>(HashSet::new, (set, line) -> set.add(line.toLowerCase()))
-              .loadCachedFromResource(defaultDictionaryFile, "spell dictionary");
-            dictionaries.put(lang, Collections.unmodifiableSet(dictionary));
-        }
-    }
-
-    /**
-     * Get the default dictionary entries for the specified language
-     *
-     * @param lang language to retrieve
-     * @return default dictionary for the specified language
-     */
-    public static Set<String> getDictionary(String lang) {
-        loadDictionary(lang == null ? DEFAULT_LANGUAGE : lang);
-        return dictionaries.get(lang);
-    }
-
-}
diff --git a/redpen-core/src/main/java/cc/redpen/validator/DictionaryValidator.java b/redpen-core/src/main/java/cc/redpen/validator/DictionaryValidator.java
new file mode 100644
index 00000000..e41f9516
--- /dev/null
+++ b/redpen-core/src/main/java/cc/redpen/validator/DictionaryValidator.java
@@ -0,0 +1,66 @@
+package cc.redpen.validator;
+
+import cc.redpen.RedPenException;
+import cc.redpen.util.DictionaryLoader;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.Stream;
+
+import static java.util.Collections.emptySet;
+import static java.util.stream.Stream.concat;
+import static org.apache.commons.lang3.StringUtils.isNotEmpty;
+
+/**
+ * Base class for dictionary-based validators.
+ */
+public abstract class DictionaryValidator extends Validator {
+  protected DictionaryLoader<Set<String>> loader = WORD_LIST;
+  private String dictionaryPrefix;
+  private Set<String> dictionary = emptySet();
+
+  public DictionaryValidator() {
+    super("list", new HashSet<>(), "dict", "");
+  }
+
+  public DictionaryValidator(Object...keyValues) {
+    this();
+    addDefaultProperties(keyValues);
+  }
+
+  public DictionaryValidator(String dictionaryPrefix) {
+    this();
+    this.dictionaryPrefix = dictionaryPrefix;
+  }
+
+  public DictionaryValidator(DictionaryLoader<Set<String>> loader, String dictionaryPrefix) {
+    this(dictionaryPrefix);
+    this.loader = loader;
+  }
+
+  @Override protected void init() throws RedPenException {
+    if (dictionaryPrefix != null) {
+      String defaultDictionaryFile = "default-resources/" + dictionaryPrefix + "-" + getSymbolTable().getLang() + ".dat";
+      dictionary = loader.loadCachedFromResource(defaultDictionaryFile, getClass().getSimpleName() + " default dictionary");
+    }
+
+    String confFile = getString("dict");
+    if (isNotEmpty(confFile)) {
+      getSet("list").addAll(loader.loadCachedFromFile(findFile(confFile), getClass().getSimpleName() + " user dictionary"));
+    }
+  }
+
+  protected boolean inDictionary(String word) {
+    Set<String> customDictionary = getSet("list");
+    return dictionary.contains(word) || customDictionary != null && customDictionary.contains(word);
+  }
+
+  protected boolean dictionaryExists() {
+    Set<String> customDictionary = getSet("list");
+    return !dictionary.isEmpty() || customDictionary != null && !customDictionary.isEmpty();
+  }
+
+  protected Stream<String> streamDictionary() {
+    return concat(dictionary.stream(), getSet("list").stream());
+  }
+}
diff --git a/redpen-core/src/main/java/cc/redpen/validator/JavaScriptValidator.java b/redpen-core/src/main/java/cc/redpen/validator/JavaScriptValidator.java
index 512e4c8d..711ecfcd 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/JavaScriptValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/JavaScriptValidator.java
@@ -57,14 +57,17 @@ import java.util.*;
  */
 public class JavaScriptValidator extends Validator {
     private static final Logger LOG = LoggerFactory.getLogger(JavaScriptValidator.class);
-    public final String DEFAULT_JS_VALIDATORS_PATH = "js";
     final List<Script> scripts = new ArrayList<>();
 
+    public JavaScriptValidator() {
+        super("script-path", "js");
+    }
+
     @Override
     protected void init() throws RedPenException {
-        Optional<String> jsValidatorsPath = getConfigAttribute("script-path");
         try {
-            File jsDirectory = findFile(jsValidatorsPath.orElse(DEFAULT_JS_VALIDATORS_PATH));
+            String jsValidatorsPath = getString("script-path");
+            File jsDirectory = findFile(jsValidatorsPath);
             LOG.info("JavaScript validators directory: {}", jsValidatorsPath);
             File[] jsValidatorFiles = jsDirectory.listFiles();
             if (jsValidatorFiles != null) {
diff --git a/redpen-core/src/main/java/cc/redpen/validator/Validator.java b/redpen-core/src/main/java/cc/redpen/validator/Validator.java
index 798dfc6a..1282cef4 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/Validator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/Validator.java
@@ -17,7 +17,6 @@
  */
 package cc.redpen.validator;
 
-
 import cc.redpen.RedPenException;
 import cc.redpen.config.Configuration;
 import cc.redpen.config.SymbolTable;
@@ -36,20 +35,48 @@ import java.io.File;
 import java.text.MessageFormat;
 import java.util.*;
 
+import static java.lang.Boolean.parseBoolean;
+import static java.lang.Double.parseDouble;
+import static java.lang.Integer.parseInt;
+import static java.util.Arrays.asList;
+import static java.util.ResourceBundle.Control.FORMAT_DEFAULT;
+import static java.util.stream.Collectors.toSet;
+import static org.apache.commons.lang3.StringUtils.isEmpty;
+
 /**
  * Validate input document.
  */
 public abstract class Validator {
-
     private static final Logger LOG = LoggerFactory.getLogger(Validator.class);
-    private final static ResourceBundle.Control fallbackControl = ResourceBundle.Control.getNoFallbackControl(ResourceBundle.Control.FORMAT_DEFAULT);
+    private final static ResourceBundle.Control fallbackControl = ResourceBundle.Control.getNoFallbackControl(FORMAT_DEFAULT);
 
+    private Map<String, Object> properties;
     private ResourceBundle errorMessages = null;
     private ValidatorConfiguration config;
     private Configuration globalConfig;
 
     public Validator() {
+        this(new Object[0]);
+    }
+
+    /**
+     * @param keyValues String key and Object value pairs for supported config properties.
+     */
+    public Validator(Object...keyValues) {
         setLocale(Locale.getDefault());
+        setDefaultProperties(keyValues);
+    }
+
+    protected void setDefaultProperties(Object...keyValues) {
+        properties = new LinkedHashMap<>();
+        addDefaultProperties(keyValues);
+    }
+
+    protected void addDefaultProperties(Object[] keyValues) {
+        if (keyValues.length % 2 != 0) throw new IllegalArgumentException("Not enough values specified");
+        for (int i = 0; i < keyValues.length; i+=2) {
+            properties.put(keyValues[i].toString(), keyValues[i+1]);
+        }
     }
 
     private List<ValidationError> errors;
@@ -116,9 +143,27 @@ public abstract class Validator {
     public final void preInit(ValidatorConfiguration config, Configuration globalConfig) throws RedPenException {
         this.config = config;
         this.globalConfig = globalConfig;
+        loadProperties(config);
         init();
     }
 
+    private void loadProperties(ValidatorConfiguration config) {
+        properties.forEach((name, defaultValue) -> {
+            String value = config.getProperty(name);
+            if (value == null) return;
+            if (defaultValue instanceof Integer)
+                properties.put(name, Integer.valueOf(value));
+            else if (defaultValue instanceof Float)
+                properties.put(name, Float.valueOf(value));
+            else if (defaultValue instanceof Boolean)
+                properties.put(name, Boolean.valueOf(value));
+            else if (defaultValue instanceof Set)
+                properties.put(name, isEmpty(value) ? defaultValue : asList((value).split(",")).stream().map(String::toLowerCase).collect(toSet()));
+            else
+                properties.put(name, value);
+        });
+    }
+
     void setLocale(Locale locale) {
         // getPackage() would return null for default package
         String packageName = this.getClass().getPackage() != null ? this.getClass().getPackage().getName() : "";
@@ -133,12 +178,13 @@ public abstract class Validator {
     }
 
     /**
-     * Return the configuration attributes
+     * Return the configuration properties
      *
-     * @return a map of configuration attributes to their values
+     * @return a map of configuration properties to their values
      */
+    @Deprecated
     public Map<String, String> getConfigAttributes() {
-        return config.getAttributes();
+        return config.getProperties();
     }
 
     /**
@@ -149,53 +195,56 @@ public abstract class Validator {
     protected void init() throws RedPenException {
     }
 
-    protected Optional<String> getConfigAttribute(String attributeName) {
-        return Optional.ofNullable(config.getAttribute(attributeName));
+    public Map<String, Object> getProperties() {
+        return properties;
     }
 
-    protected String getConfigAttribute(String attributeName, String defaultValue) {
-        String value = config.getAttribute(attributeName);
-        if (value != null) {
-            LOG.info("{} is set to {}", attributeName, value);
-            return value;
-        } else {
-            LOG.info("{} is not set. Use default value of {}", attributeName, defaultValue);
-            return defaultValue;
-        }
+    protected int getInt(String name) {
+        return (int)properties.get(name);
     }
 
+    protected float getFloat(String name) {
+        return (float)properties.get(name);
+    }
 
-    protected int getConfigAttributeAsInt(String attributeName, int defaultValue) {
-        String value = config.getAttribute(attributeName);
-        if (value != null) {
-            LOG.info("{} is set to {}", attributeName, value);
-            return Integer.valueOf(value);
-        } else {
-            LOG.info("{} is not set. Use default value of {}", attributeName, defaultValue);
-            return defaultValue;
-        }
+    protected String getString(String name) {
+        return (String)properties.get(name);
     }
 
-    protected boolean getConfigAttributeAsBoolean(String attributeName, boolean defaultValue) {
-        String value = config.getAttribute(attributeName);
-        if (value != null) {
-            LOG.info("{} is set to {}", attributeName, value);
-            return Boolean.valueOf(value);
-        } else {
-            LOG.info("{} is not set. Use default value of {}", attributeName, defaultValue);
-            return defaultValue;
-        }
+    protected boolean getBoolean(String name) {
+        return (boolean)properties.get(name);
     }
 
-    protected double getConfigAttributeAsDouble(String attributeName, double defaultValue) {
-        String value = config.getAttribute(attributeName);
-        if (value != null) {
-            LOG.info("{} is set to {}", attributeName, value);
-            return Double.valueOf(value);
-        } else {
-            LOG.info("{} is not set. Use default value of {}", attributeName, defaultValue);
-            return defaultValue;
-        }
+    @SuppressWarnings("unchecked")
+    protected Set<String> getSet(String name) {
+        return (Set) properties.get(name);
+    }
+
+    /** @deprecated Please use constructor with default properties instead, and then getXXX() methods */
+    @Deprecated
+    protected Optional<String> getConfigAttribute(String name) {
+        return Optional.ofNullable(config.getProperty(name));
+    }
+
+    /** @deprecated Please use constructor with default properties instead, and then getXXX() methods */
+    @Deprecated
+    protected String getConfigAttribute(String name, String defaultValue) {
+        return getConfigAttribute(name).orElse(defaultValue);
+    }
+
+    @Deprecated
+    protected int getConfigAttributeAsInt(String name, int defaultValue) {
+        return parseInt(getConfigAttribute(name, Integer.toString(defaultValue)));
+    }
+
+    @Deprecated
+    protected boolean getConfigAttributeAsBoolean(String name, boolean defaultValue) {
+        return parseBoolean(getConfigAttribute(name, Boolean.toString(defaultValue)));
+    }
+
+    @Deprecated
+    protected double getConfigAttributeAsDouble(String name, double defaultValue) {
+        return parseDouble(getConfigAttribute(name, Double.toString(defaultValue)));
     }
 
     protected SymbolTable getSymbolTable() {
@@ -374,6 +423,22 @@ public abstract class Validator {
                                                   Optional<LineOffset> start, Optional<LineOffset> end, Object... args) {
         errors.add(new ValidationError(this.getClass(), getLocalizedErrorMessage(messageKey, args), sentenceWithError, start.get(), end.get()));
     }
+
+    @Override public String toString() {
+        return getClass().getSimpleName() + properties;
+    }
+
+    @Override public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof Validator)) return false;
+        Validator validator = (Validator)o;
+        return Objects.equals(getClass(), validator.getClass()) && Objects.equals(config, validator.config);
+    }
+
+    @Override public int hashCode() {
+        return Objects.hash(getClass(), config);
+    }
+
     /**
      * Resource Extractor loads key-value dictionary
      */
diff --git a/redpen-core/src/main/java/cc/redpen/validator/ValidatorFactory.java b/redpen-core/src/main/java/cc/redpen/validator/ValidatorFactory.java
index 55aa9d06..9fcca5e3 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/ValidatorFactory.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/ValidatorFactory.java
@@ -23,12 +23,14 @@ import cc.redpen.config.ValidatorConfiguration;
 import cc.redpen.validator.section.*;
 import cc.redpen.validator.sentence.*;
 
+import java.util.Collection;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
 import static java.util.Arrays.asList;
 import static java.util.stream.Collectors.*;
+import static org.apache.commons.lang3.StringUtils.join;
 
 /**
  * Factory class of validators.
@@ -90,7 +92,19 @@ public class ValidatorFactory {
         return validators.entrySet().stream().filter(e -> {
             List<String> supportedLanguages = e.getValue().getSupportedLanguages();
             return supportedLanguages.isEmpty() || supportedLanguages.contains(lang);
-        }).map(e -> new ValidatorConfiguration(e.getKey())).collect(toList());
+        }).map(e -> new ValidatorConfiguration(e.getKey(), toStrings(e.getValue().getProperties()))).collect(toList());
+    }
+
+    @SuppressWarnings("unchecked")
+    static Map<String, String> toStrings(Map<String, Object> properties) {
+        Map<String, String> result = new LinkedHashMap<>();
+        for (Map.Entry<String, Object> e : properties.entrySet()) {
+            if (e.getValue() instanceof Iterable)
+                result.put(e.getKey(), join((Iterable)e.getValue(), ','));
+            else
+                result.put(e.getKey(), e.getValue().toString());
+        }
+        return result;
     }
 
     public static Validator getInstance(String validatorName) throws RedPenException {
diff --git a/redpen-core/src/main/java/cc/redpen/validator/section/DuplicatedSectionValidator.java b/redpen-core/src/main/java/cc/redpen/validator/section/DuplicatedSectionValidator.java
index 8cbe79eb..c8a92191 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/section/DuplicatedSectionValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/section/DuplicatedSectionValidator.java
@@ -17,7 +17,6 @@
  */
 package cc.redpen.validator.section;
 
-import cc.redpen.RedPenException;
 import cc.redpen.model.Paragraph;
 import cc.redpen.model.Section;
 import cc.redpen.model.Sentence;
@@ -30,12 +29,6 @@ import java.util.*;
  * DuplicatedSectionValidator check if there are highly similar section pairs.
  */
 final public class DuplicatedSectionValidator extends Validator {
-    /**
-     * Default threshold (Cosine similarity).
-     */
-    static final public double DEFAULT_SIMILARITY_THRESHOLD = 0.9d;
-
-    private double threhold;
     private List<SectionVector> sectionVectors = new ArrayList<>();
 
     class SectionVector {
@@ -48,6 +41,10 @@ final public class DuplicatedSectionValidator extends Validator {
         }
     }
 
+    public DuplicatedSectionValidator() {
+        super("threshold", 0.9f); // Default threshold (Cosine similarity).
+    }
+
     @Override
     public void preValidate(Section section) {
         Map<String, Integer> sectionVector = extractWordFrequency(section);
@@ -75,7 +72,7 @@ final public class DuplicatedSectionValidator extends Validator {
             Map<String, Integer> candidateVector = sectionVector.sectionVector;
             // NOTE: not header.equals() since the we need check if the references are identical
             if (sectionVector.header != section.getHeaderContent(0) &&
-                    calcCosine(targetVector, candidateVector) > threhold) {
+                    calcCosine(targetVector, candidateVector) > getFloat("threshold")) {
                 Optional<Sentence> header = Optional.ofNullable(section.getHeaderContent(0));
                 addLocalizedError(header.orElse(section.getParagraph(0).getSentence(0)),
                         sectionVector.header.getLineNumber());
@@ -114,34 +111,4 @@ final public class DuplicatedSectionValidator extends Validator {
             sectionVector.put(surface, ++currentNum);
         }
     }
-
-    @Override
-    protected void init() throws RedPenException {
-        this.threhold = getConfigAttributeAsDouble("threshold", DEFAULT_SIMILARITY_THRESHOLD);
-    }
-
-    @Override
-    public String toString() {
-        return "DuplicatedSectionValidator{" +
-                "sectionVectors=" + sectionVectors +
-                '}';
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        DuplicatedSectionValidator that = (DuplicatedSectionValidator) o;
-
-        if (sectionVectors != null ? !sectionVectors.equals(that.sectionVectors) : that.sectionVectors != null)
-            return false;
-
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        return sectionVectors != null ? sectionVectors.hashCode() : 0;
-    }
 }
diff --git a/redpen-core/src/main/java/cc/redpen/validator/section/FrequentSentenceStartValidator.java b/redpen-core/src/main/java/cc/redpen/validator/section/FrequentSentenceStartValidator.java
index fe39876b..4f348b3d 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/section/FrequentSentenceStartValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/section/FrequentSentenceStartValidator.java
@@ -17,7 +17,6 @@
  */
 package cc.redpen.validator.section;
 
-import cc.redpen.RedPenException;
 import cc.redpen.model.Document;
 import cc.redpen.model.Paragraph;
 import cc.redpen.model.Sentence;
@@ -30,29 +29,21 @@ import java.util.Map;
  * Check that too many sentences don't start with the same words
  */
 public class FrequentSentenceStartValidator extends Validator {
-
     private Map<String, Integer> sentenceStartHistogram = new HashMap<>(); // histogram of sentence starts
-    private int leadingWordLimit = 3; // number of words starting each sentence to consider
-    private int percentageThreshold = 25; // maximum percentage of sentences that can start with the same words
-    private int minimumSentenceCount = 5; // must have at least this number of sentences
 
-    @Override
-    protected void init() throws RedPenException {
-        super.init();
-        leadingWordLimit = getConfigAttributeAsInt("leading_word_limit", leadingWordLimit);
-        percentageThreshold = getConfigAttributeAsInt("percentage_threshold", percentageThreshold);
-        minimumSentenceCount = getConfigAttributeAsInt("min_sentence_count", minimumSentenceCount);
+    public FrequentSentenceStartValidator() {
+        super("leading_word_limit", 3, // number of words starting each sentence to consider
+              "percentage_threshold", 25, // maximum percentage of sentences that can start with the same words
+              "min_sentence_count", 5); // must have at least this number of sentences
     }
 
     /**
      * Add sequences of tokens, up to leadingWordLimit, in the histogram
-     *
-     * @param sentence
      */
     private void processSentence(Sentence sentence) {
-        if (sentence.getTokens().size() > leadingWordLimit) {
+        if (sentence.getTokens().size() > getInt("leading_word_limit")) {
             String leadingPhrase = "";
-            for (int i = 0; i < leadingWordLimit; i++) {
+            for (int i = 0; i < getInt("leading_word_limit"); i++) {
                 leadingPhrase += (leadingPhrase.isEmpty() ? "" : " ") + sentence.getTokens().get(i).getSurface();
                 Integer count = sentenceStartHistogram.get(leadingPhrase);
                 if (sentenceStartHistogram.get(leadingPhrase) == null) {
@@ -65,7 +56,6 @@ public class FrequentSentenceStartValidator extends Validator {
 
     @Override
     public void validate(Document document) {
-
         // remember the last sentence since we can't add an error without a sentence
         Sentence lastSentence = null;
         int sentenceCount = 0;
@@ -80,11 +70,11 @@ public class FrequentSentenceStartValidator extends Validator {
         }
 
         // make sure we have enough sentences to make this validation worthwhile
-        if (sentenceCount >= minimumSentenceCount) {
+        if (sentenceCount >= getInt("min_sentence_count")) {
             for (String start : sentenceStartHistogram.keySet()) {
                 int count = sentenceStartHistogram.get(start);
                 int percentage = (int) ((100.0 * (float) count / (float) sentenceStartHistogram.size()));
-                if (percentage > percentageThreshold) {
+                if (percentage > getInt("percentage_threshold")) {
                     addLocalizedError("SentenceStartTooFrequent", lastSentence, percentage, start);
                 }
             }
diff --git a/redpen-core/src/main/java/cc/redpen/validator/section/ParagraphNumberValidator.java b/redpen-core/src/main/java/cc/redpen/validator/section/ParagraphNumberValidator.java
index c9183478..3151a86a 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/section/ParagraphNumberValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/section/ParagraphNumberValidator.java
@@ -17,7 +17,6 @@
  */
 package cc.redpen.validator.section;
 
-import cc.redpen.RedPenException;
 import cc.redpen.model.Section;
 import cc.redpen.validator.Validator;
 
@@ -26,49 +25,15 @@ import cc.redpen.validator.Validator;
  * This validator reports it.
  */
 final public class ParagraphNumberValidator extends Validator {
-    /**
-     * Default maximum number of paragraphs in a section.
-     */
-    @SuppressWarnings("WeakerAccess")
-    public static final int DEFAULT_MAX_PARAGRAPHS_IN_A_SECTION = 5;
-    private int maxParagraphs;
+    public ParagraphNumberValidator() {
+        super("max_num", 5); // Default maximum number of paragraphs in a section.
+    }
 
     @Override
     public void validate(Section section) {
         int paragraphNumber = section.getNumberOfParagraphs();
-        if (maxParagraphs < paragraphNumber) {
+        if (getInt("max_num") < paragraphNumber) {
             addLocalizedError(section.getJoinedHeaderContents(), paragraphNumber);
         }
     }
-
-    @Override
-    protected void init() throws RedPenException {
-        this.maxParagraphs = getConfigAttributeAsInt("max_num", DEFAULT_MAX_PARAGRAPHS_IN_A_SECTION);
-    }
-
-    @Override
-    public String toString() {
-        return "ParagraphNumberValidator{" +
-                "maxParagraphs=" + maxParagraphs +
-                '}';
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        ParagraphNumberValidator that = (ParagraphNumberValidator) o;
-
-        return maxParagraphs == that.maxParagraphs;
-    }
-
-    @Override
-    public int hashCode() {
-        return maxParagraphs;
-    }
-
-    protected void setMaxParagraphNumber(int max) {
-        this.maxParagraphs = max;
-    }
 }
diff --git a/redpen-core/src/main/java/cc/redpen/validator/section/ParagraphStartWithValidator.java b/redpen-core/src/main/java/cc/redpen/validator/section/ParagraphStartWithValidator.java
index 6aca69b5..9a7bed2a 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/section/ParagraphStartWithValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/section/ParagraphStartWithValidator.java
@@ -17,7 +17,6 @@
  */
 package cc.redpen.validator.section;
 
-import cc.redpen.RedPenException;
 import cc.redpen.model.Paragraph;
 import cc.redpen.model.Section;
 import cc.redpen.model.Sentence;
@@ -27,12 +26,9 @@ import cc.redpen.validator.Validator;
  * Validate whether paragraph start as specified.
  */
 public final class ParagraphStartWithValidator extends Validator {
-    /**
-     * Default matter paragraph start with.
-     */
-    @SuppressWarnings("WeakerAccess")
-    public static final String DEFAULT_PARAGRAPH_START_WITH = "";
-    private String beginningOfParagraph = DEFAULT_PARAGRAPH_START_WITH;
+    public ParagraphStartWithValidator() {
+        super("start_from", ""); // Default matter paragraph start with.
+    }
 
     @Override
     public void validate(Section section) {
@@ -41,31 +37,10 @@ public final class ParagraphStartWithValidator extends Validator {
                 continue;
             }
             Sentence firstSentence = currentParagraph.getSentence(0);
-            if (firstSentence.getContent().indexOf(this.beginningOfParagraph) != 0) {
+            if (firstSentence.getContent().indexOf(getString("start_from")) != 0) {
                 addLocalizedError(section.getJoinedHeaderContents(),
                         firstSentence.getContent().charAt(0));
             }
         }
     }
-
-    @Override
-    protected void init() throws RedPenException {
-        this.beginningOfParagraph = getConfigAttribute("start_from", DEFAULT_PARAGRAPH_START_WITH);
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        ParagraphStartWithValidator that = (ParagraphStartWithValidator) o;
-
-        return !(beginningOfParagraph != null ? !beginningOfParagraph.equals(that.beginningOfParagraph) : that.beginningOfParagraph != null);
-
-    }
-
-    @Override
-    public int hashCode() {
-        return beginningOfParagraph != null ? beginningOfParagraph.hashCode() : 0;
-    }
 }
diff --git a/redpen-core/src/main/java/cc/redpen/validator/section/SectionLengthValidator.java b/redpen-core/src/main/java/cc/redpen/validator/section/SectionLengthValidator.java
index a75085c1..6221cea3 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/section/SectionLengthValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/section/SectionLengthValidator.java
@@ -17,22 +17,18 @@
  */
 package cc.redpen.validator.section;
 
-import cc.redpen.RedPenException;
 import cc.redpen.model.Paragraph;
 import cc.redpen.model.Section;
 import cc.redpen.model.Sentence;
 import cc.redpen.validator.Validator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * Validate the length of one section.
  */
 final public class SectionLengthValidator extends Validator {
-    private static final int DEFAULT_MAXIMUM_CHAR_NUMBER_IN_A_SECTION = 1000;
-    private static final Logger LOG =
-            LoggerFactory.getLogger(SectionLengthValidator.class);
-    private int maxSectionCharNumber;
+    public SectionLengthValidator() {
+        super("max_num", 1000);
+    }
 
     @Override
     public void validate(Section section) {
@@ -44,41 +40,8 @@ final public class SectionLengthValidator extends Validator {
             }
         }
 
-        if (sectionCharNumber > maxSectionCharNumber) {
+        if (sectionCharNumber > getInt("max_num")) {
             addLocalizedError(section.getJoinedHeaderContents(), sectionCharNumber);
         }
     }
-
-    @Override
-    protected void init() throws RedPenException {
-        this.maxSectionCharNumber = getConfigAttributeAsInt("max_num", DEFAULT_MAXIMUM_CHAR_NUMBER_IN_A_SECTION);
-    }
-
-    protected void setMaxSectionLength(int max) {
-        this.maxSectionCharNumber = max;
-    }
-
-    @Override
-    public String toString() {
-        return "SectionLengthValidator{" +
-                "maxSectionCharNumber=" + maxSectionCharNumber +
-                '}';
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        SectionLengthValidator that = (SectionLengthValidator) o;
-
-        if (maxSectionCharNumber != that.maxSectionCharNumber) return false;
-
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        return maxSectionCharNumber;
-    }
 }
diff --git a/redpen-core/src/main/java/cc/redpen/validator/section/UnexpandedAcronymValidator.java b/redpen-core/src/main/java/cc/redpen/validator/section/UnexpandedAcronymValidator.java
index 0a1de7e9..7e14b1eb 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/section/UnexpandedAcronymValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/section/UnexpandedAcronymValidator.java
@@ -22,24 +22,18 @@ import cc.redpen.model.Document;
 import cc.redpen.model.Paragraph;
 import cc.redpen.model.Sentence;
 import cc.redpen.tokenizer.TokenElement;
-import cc.redpen.util.SpellingUtils;
-import cc.redpen.validator.Validator;
+import cc.redpen.validator.sentence.SpellingDictionaryValidator;
 
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
+
+import static java.util.Collections.singletonList;
 
 /**
  * Ensure that there are candidates for expanded versions of acronyms. That is, if there exists an
  * acronym ABC then there must exist a sequence of capitalized words such as Axxx Bxx Cxxx.
  */
-public class UnexpandedAcronymValidator extends Validator {
-
-    private static final int MIN_ACRONYM_LENGTH_DEFAULT = 3; // TLA
+public class UnexpandedAcronymValidator extends SpellingDictionaryValidator {
 
-    // ignore uppercase words smaller than this length
-    private int minAcronymLength = MIN_ACRONYM_LENGTH_DEFAULT;
     // a set of small words used to join acronyms, such as 'of', 'the' and 'for'
     private Set<String> acronymJoiningWords = new HashSet<>();
     // the set of acronyms we've deduced from sequences of capitalized words
@@ -47,14 +41,17 @@ public class UnexpandedAcronymValidator extends Validator {
     // the set of acronyms we found literally within the document
     private Set<String> contractedAcronyms = new HashSet<>();
 
-    // a dictionary to filter out acronyms that are just uppercase words
-    private Set<String> dictionary;
+    public UnexpandedAcronymValidator() {
+        setDefaultProperties("min_acronym_length", 3); // ignore uppercase words smaller than this length
+    }
+
+    @Override public List<String> getSupportedLanguages() {
+        return singletonList(Locale.ENGLISH.getLanguage());
+    }
 
     @Override
     protected void init() throws RedPenException {
         super.init();
-        dictionary = SpellingUtils.getDictionary(getSymbolTable().getLang());
-        minAcronymLength = getConfigAttributeAsInt("min_acronym_length", MIN_ACRONYM_LENGTH_DEFAULT);
         acronymJoiningWords.add("of");
         acronymJoiningWords.add("the");
         acronymJoiningWords.add("for");
@@ -68,8 +65,9 @@ public class UnexpandedAcronymValidator extends Validator {
         for (TokenElement token : sentence.getTokens()) {
             String word = token.getSurface();
             if (!word.trim().isEmpty()) {
+                int minAcronymLength = getInt("min_acronym_length");
                 if (isAllCapitals(word)) {
-                    if ((word.length() >= minAcronymLength) && !dictionary.contains(word.toLowerCase())) {
+                    if ((word.length() >= minAcronymLength) && !inDictionary(word.toLowerCase())) {
                         contractedAcronyms.add(word);
                     }
                 } else if (isCapitalized(word)) {
@@ -93,9 +91,6 @@ public class UnexpandedAcronymValidator extends Validator {
 
     /**
      * Return true of the supplied word is all in capitals
-     *
-     * @param word
-     * @return
      */
     private boolean isAllCapitals(String word) {
         if (word.length() > 1) {
@@ -111,9 +106,6 @@ public class UnexpandedAcronymValidator extends Validator {
 
     /**
      * Return true if the word only starts with a capital letter
-     *
-     * @param word
-     * @return
      */
     private boolean isCapitalized(String word) {
         if (!word.isEmpty()) {
diff --git a/redpen-core/src/main/java/cc/redpen/validator/section/WordFrequencyValidator.java b/redpen-core/src/main/java/cc/redpen/validator/section/WordFrequencyValidator.java
index c019c2d6..5a568f62 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/section/WordFrequencyValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/section/WordFrequencyValidator.java
@@ -23,8 +23,7 @@ import cc.redpen.model.Paragraph;
 import cc.redpen.model.Sentence;
 import cc.redpen.tokenizer.TokenElement;
 import cc.redpen.util.DictionaryLoader;
-import cc.redpen.util.SpellingUtils;
-import cc.redpen.validator.Validator;
+import cc.redpen.validator.sentence.SpellingDictionaryValidator;
 
 import java.text.DecimalFormat;
 import java.util.HashMap;
@@ -33,34 +32,29 @@ import java.util.Map;
 /**
  * Ensure that known (dictionary) words are not used too frequently within the document
  */
-public class WordFrequencyValidator extends Validator {
+public class WordFrequencyValidator extends SpellingDictionaryValidator {
 
     private static final String DEFAULT_RESOURCE_PATH = "default-resources/word-frequency";
 
     // reference set of word frequencies
-    private Map<String, Double> referenceWordFrequencies = null;
+    private Map<String, Double> referenceWordFrequencies;
     // how the reference words deviate from their average use
-    private Map<String, Double> referenceWordDeviations = null;
+    private Map<String, Double> referenceWordDeviations;
     // the occurance of words in the document
     private Map<String, Integer> documentWordOccurances = new HashMap<>();
     // the number of words in the document
     private int wordCount = 0;
-    // the minimum number of words in the document before this validator activates
-    private int minWordCount = 200;
-    // the standard deviation of the reference words
-    private double referenceStdDeviation = 0;
-    // the maximum deviation from the reference frequency permitted before a validation error is created
-    private double deviationFactor = 3f;
     // one ugly side-effect of using forEach...
     private Sentence lastSentence;
 
+    public WordFrequencyValidator() {
+        setDefaultProperties("deviation_factor", 3f, // the maximum deviation from the reference frequency permitted before a validation error is created
+                             "min_word_count", 200); // the minimum number of words in the document before this validator activates
+    }
+
     @Override
     protected void init() throws RedPenException {
         super.init();
-
-        deviationFactor = getConfigAttributeAsDouble("deviation_factor", deviationFactor);
-        minWordCount = getConfigAttributeAsInt("min_word_count", minWordCount);
-
         String defaultDictionaryFile = DEFAULT_RESOURCE_PATH + "/word-frequency-" + getSymbolTable().getLang() + ".dat";
         referenceWordDeviations = new HashMap<>();
         referenceWordFrequencies =
@@ -68,39 +62,37 @@ public class WordFrequencyValidator extends Validator {
                     String[] fields = line.split(" ");
                     set.put(fields[1], Double.valueOf(fields[0]));
                 }).loadCachedFromResource(defaultDictionaryFile, "word frequencies");
-        referenceStdDeviation = getDeviations(referenceWordFrequencies, referenceWordDeviations);
+        initDeviations(referenceWordFrequencies, referenceWordDeviations);
     }
 
     /**
      * Add the words in the sentence to the word frequency histogram
-     *
-     * @param sentence
      */
     private void processSentence(Sentence sentence) {
         for (TokenElement token : sentence.getTokens()) {
             String word = token.getSurface().toLowerCase();
             if (referenceWordDeviations.get(word) != null) {
-                Integer occurances = documentWordOccurances.get(word);
-                if (occurances == null) {
+                Integer occurrences = documentWordOccurances.get(word);
+                if (occurrences == null) {
                     documentWordOccurances.put(word, 1);
                 } else {
-                    documentWordOccurances.put(word, occurances + 1);
+                    documentWordOccurances.put(word, occurrences + 1);
                 }
                 wordCount++;
-            } else if (SpellingUtils.getDictionary(getSymbolTable().getLang()).contains(word)) {
+            } else if (!dictionaryExists() || inDictionary(word)) {
                 wordCount++;
             }
         }
     }
 
     /**
-     * Return the standard deviation and full the deviations map with root of each word's variance
+     * Initializes the deviations map with root of each word's variance
      *
      * @param histogram  word frequency histogram
      * @param deviations a map that gets filled with each words variance
      * @return the standard deviation of the histogram
      */
-    private double getDeviations(Map<String, Double> histogram, Map<String, Double> deviations) {
+    private double initDeviations(Map<String, Double> histogram, Map<String, Double> deviations) {
         double sum = 0;
         for (String word : histogram.keySet()) {
             sum += histogram.get(word);
@@ -123,7 +115,6 @@ public class WordFrequencyValidator extends Validator {
 
     @Override
     public void validate(Document document) {
-
         // process each sentence in the document
         lastSentence = null;
         for (int i = 0; i < document.size(); i++) {
@@ -136,7 +127,7 @@ public class WordFrequencyValidator extends Validator {
         }
 
         // don't validate if the document is too short
-        if (wordCount >= minWordCount) {
+        if (wordCount >= getInt("min_word_count")) {
             Map<String, Double> documentWordFrequencies = new HashMap<>();
 
             documentWordOccurances.forEach((word, count) -> {
@@ -146,7 +137,7 @@ public class WordFrequencyValidator extends Validator {
             DecimalFormat df = new DecimalFormat("0.00");
 
             Map<String, Double> documentDeviations = new HashMap<>();
-            double stddev = getDeviations(documentWordFrequencies, documentDeviations);
+            double stddev = initDeviations(documentWordFrequencies, documentDeviations);
             documentDeviations.forEach((word, deviation) -> {
                 Double referenceDeviation = referenceWordDeviations.get(word);
                 if (referenceDeviation != null) {
@@ -156,7 +147,7 @@ public class WordFrequencyValidator extends Validator {
 
                     // if the word deviates significantly from the norm and also from the reference percentage,
                     // then raise an error
-                    if ((devRatio > 1) && (docPercentage > referencePercentage * deviationFactor)) {
+                    if ((devRatio > 1) && (docPercentage > referencePercentage * getFloat("deviation_factor"))) {
                         addLocalizedError(
                                 "WordUsedTooFrequently",
                                 lastSentence,
diff --git a/redpen-core/src/main/java/cc/redpen/validator/sentence/CommaNumberValidator.java b/redpen-core/src/main/java/cc/redpen/validator/sentence/CommaNumberValidator.java
index 01714732..40a7c7f5 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/sentence/CommaNumberValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/sentence/CommaNumberValidator.java
@@ -17,28 +17,27 @@
  */
 package cc.redpen.validator.sentence;
 
-
 import cc.redpen.RedPenException;
 import cc.redpen.model.Sentence;
 import cc.redpen.validator.Validator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 
 import static cc.redpen.config.SymbolType.COMMA;
 
 /**
  * Validate the number of commas in one sentence.
  */
-final public class CommaNumberValidator extends Validator {
-    private static final Logger LOG = LoggerFactory.getLogger(CommaNumberValidator.class);
-    /**
-     * Default maximum number of comma.
-     */
-    private static final int DEFAULT_MAX_COMMA_NUMBER = 3;
-    private int maxCommaNum = DEFAULT_MAX_COMMA_NUMBER;
+public final class CommaNumberValidator extends Validator {
+
+    public CommaNumberValidator() {
+        super("max_num", 3);
+    }
+
     private char comma;
 
+    private int getMaxNum() {
+        return getInt("max_num");
+    }
+
     @Override
     public void validate(Sentence sentence) {
         String content = sentence.getContent();
@@ -49,42 +48,13 @@ final public class CommaNumberValidator extends Validator {
             commaCount++;
             content = content.substring(position + 1, content.length());
         }
-        if (maxCommaNum < commaCount) {
-            addLocalizedError(sentence, commaCount, maxCommaNum);
+        if (getMaxNum() < commaCount) {
+            addLocalizedError(sentence, commaCount, getMaxNum());
         }
     }
 
     @Override
     protected void init() throws RedPenException {
-        this.maxCommaNum = getConfigAttributeAsInt("max_num", DEFAULT_MAX_COMMA_NUMBER);
         this.comma = getSymbolTable().getValueOrFallbackToDefault(COMMA);
     }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        CommaNumberValidator that = (CommaNumberValidator) o;
-
-        if (comma != that.comma) return false;
-        if (maxCommaNum != that.maxCommaNum) return false;
-
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        int result = maxCommaNum;
-        result = 31 * result + (int) comma;
-        return result;
-    }
-
-    @Override
-    public String toString() {
-        return "CommaNumberValidator{" +
-                "maxCommaNum=" + maxCommaNum +
-                ", comma=" + comma +
-                '}';
-    }
 }
diff --git a/redpen-core/src/main/java/cc/redpen/validator/sentence/ContractionValidator.java b/redpen-core/src/main/java/cc/redpen/validator/sentence/ContractionValidator.java
index ba44383f..ab90ead8 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/sentence/ContractionValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/sentence/ContractionValidator.java
@@ -21,7 +21,12 @@ import cc.redpen.model.Sentence;
 import cc.redpen.tokenizer.TokenElement;
 import cc.redpen.validator.Validator;
 
-import java.util.*;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+
+import static java.util.Collections.singletonList;
 
 /**
  * Validate English contraction in the input document.
@@ -118,12 +123,12 @@ final public class ContractionValidator extends Validator {
         nonContractions.add("they");
     }
 
-    private int foundContractionNum = 0;
-    private int foundNonContractionNum = 0;
+    private int foundContractionNum;
+    private int foundNonContractionNum;
 
     @Override
     public List<String> getSupportedLanguages() {
-        return Arrays.asList(Locale.ENGLISH.getLanguage());
+        return singletonList(Locale.ENGLISH.getLanguage());
     }
 
     @Override
@@ -148,30 +153,4 @@ final public class ContractionValidator extends Validator {
             }
         }
     }
-
-    @Override
-    public String toString() {
-        return "ContractionValidator{" +
-                "foundContractionNum=" + foundContractionNum +
-                ", foundNonContractionNum=" + foundNonContractionNum +
-                '}';
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        ContractionValidator that = (ContractionValidator) o;
-
-        return foundContractionNum == that.foundContractionNum && foundNonContractionNum == that.foundNonContractionNum;
-
-    }
-
-    @Override
-    public int hashCode() {
-        int result = foundContractionNum;
-        result = 31 * result + foundNonContractionNum;
-        return result;
-    }
 }
diff --git a/redpen-core/src/main/java/cc/redpen/validator/sentence/DoubleNegativeValidator.java b/redpen-core/src/main/java/cc/redpen/validator/sentence/DoubleNegativeValidator.java
index f0cb21ac..559368a5 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/sentence/DoubleNegativeValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/sentence/DoubleNegativeValidator.java
@@ -22,8 +22,6 @@ import cc.redpen.model.Sentence;
 import cc.redpen.tokenizer.TokenElement;
 import cc.redpen.validator.ExpressionRule;
 import cc.redpen.validator.Validator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import java.util.List;
 import java.util.Locale;
@@ -39,8 +37,6 @@ public class DoubleNegativeValidator extends Validator {
             "default-resources/double-negative/double-negative-expression-";
     private static final String DEFAULT_RESOURCE_WORD_PATH =
             "default-resources/double-negative/double-negative-word-";
-    private static final Logger LOG =
-            LoggerFactory.getLogger(DoubleNegativeValidator.class);
     private Set<ExpressionRule> invalidExpressions;
     private Set<String> negativeWords;
 
diff --git a/redpen-core/src/main/java/cc/redpen/validator/sentence/DoubledJoshiValidator.java b/redpen-core/src/main/java/cc/redpen/validator/sentence/DoubledJoshiValidator.java
index bc28261a..22de57c5 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/sentence/DoubledJoshiValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/sentence/DoubledJoshiValidator.java
@@ -17,20 +17,24 @@
  */
 package cc.redpen.validator.sentence;
 
-import cc.redpen.RedPenException;
 import cc.redpen.model.Sentence;
 import cc.redpen.tokenizer.TokenElement;
 import cc.redpen.validator.Validator;
 
 import java.util.*;
 
+import static java.util.Collections.emptySet;
+import static java.util.Collections.singletonList;
+
 /**
  * DoubledJoshiValidator checks if the input texts has duplicated Kakujoshi words in one setnences.
  * <br>
  * Note: this validator works only for Japanese texts.
  */
 public class DoubledJoshiValidator extends Validator {
-    private Set<String> skipList = new HashSet<>();
+    public DoubledJoshiValidator() {
+        super("list", emptySet());
+    }
 
     @Override
     public void validate(Sentence sentence) {
@@ -44,21 +48,14 @@ public class DoubledJoshiValidator extends Validator {
                         counts.get(tokenElement.getSurface())+1);
             }
         }
+        Set<String> skipList = getSet("list");
         counts.entrySet().stream()
                 .filter(e -> e.getValue() >= 2 && !skipList.contains(e.getKey()))
                 .forEach(e -> addLocalizedError(sentence, e.getKey()));
     }
 
-    @Override
-    protected void init() throws RedPenException {
-        //TODO: filter with the kind of Joshi such as Kakujoshi, KakariJoshi etc...
-        getConfigAttribute("list").ifPresent((f -> {
-            skipList.addAll(Arrays.asList(f.split(",")));
-        }));
-    }
-
     @Override
     public List<String> getSupportedLanguages() {
-        return Arrays.asList(Locale.JAPANESE.getLanguage());
+        return singletonList(Locale.JAPANESE.getLanguage());
     }
 }
diff --git a/redpen-core/src/main/java/cc/redpen/validator/sentence/DoubledWordValidator.java b/redpen-core/src/main/java/cc/redpen/validator/sentence/DoubledWordValidator.java
index 5b46e545..1249746a 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/sentence/DoubledWordValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/sentence/DoubledWordValidator.java
@@ -17,86 +17,28 @@
  */
 package cc.redpen.validator.sentence;
 
-import cc.redpen.RedPenException;
 import cc.redpen.model.Sentence;
 import cc.redpen.tokenizer.TokenElement;
-import cc.redpen.validator.Validator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import cc.redpen.validator.DictionaryValidator;
 
 import java.util.HashSet;
-import java.util.Optional;
 import java.util.Set;
 
-import static java.util.Arrays.asList;
-import static java.util.stream.Collectors.toList;
+final public class DoubledWordValidator extends DictionaryValidator {
 
-final public class DoubledWordValidator extends Validator {
-    private static final Logger LOG =
-            LoggerFactory.getLogger(DoubledWordValidator.class);
-    private static final String DEFAULT_RESOURCE_PATH = "default-resources/doubled-word";
-
-    private Set<String> skipList;
-    private Set<String> customSkipList;
+    public DoubledWordValidator() {
+        super("doubled-word/doubled-word-skiplist");
+    }
 
     @Override
     public void validate(Sentence sentence) {
         Set<String> surfaces = new HashSet<>();
         for (TokenElement token : sentence.getTokens()) {
             String currentSurface = token.getSurface().toLowerCase();
-            if (surfaces.contains(currentSurface) && !skipList.contains(currentSurface)
-                    && !customSkipList.contains(currentSurface)) {
+            if (surfaces.contains(currentSurface) && !inDictionary(currentSurface)) {
                 addLocalizedErrorFromToken(sentence, token);
             }
             surfaces.add(currentSurface);
         }
     }
-
-    @Override
-    protected void init() throws RedPenException {
-        String defaultDictionaryFile = DEFAULT_RESOURCE_PATH
-                + "/doubled-word-skiplist-" + getSymbolTable().getLang() + ".dat";
-        skipList = WORD_LIST.loadCachedFromResource(defaultDictionaryFile, "doubled word skip list");
-
-        customSkipList = new HashSet<>();
-        Optional<String> skipListStr = getConfigAttribute("list");
-        skipListStr.ifPresent(f -> {
-            String normalized = f.toLowerCase();
-            LOG.info("Found user defined skip list.");
-            customSkipList.addAll(asList(normalized.split(",")).stream().map(String::toLowerCase).collect(toList()));
-            LOG.info("Succeeded to add elements of user defined skip list.");
-        });
-
-        Optional<String> confFile = getConfigAttribute("dict");
-        if (confFile.isPresent()) {
-            customSkipList.addAll(WORD_LIST.loadCachedFromFile(findFile(confFile.get()), "DoubledWordValidator user dictionary"));
-        }
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        DoubledWordValidator that = (DoubledWordValidator) o;
-
-        if (skipList != null ? !skipList.equals(that.skipList) : that.skipList != null) return false;
-        return !(customSkipList != null ? !customSkipList.equals(that.customSkipList) : that.customSkipList != null);
-
-    }
-
-    @Override
-    public int hashCode() {
-        int result = skipList != null ? skipList.hashCode() : 0;
-        result = 31 * result + (customSkipList != null ? customSkipList.hashCode() : 0);
-        return result;
-    }
-
-    @Override
-    public String toString() {
-        return "DoubledWordValidator{" +
-                "skipList=" + skipList +
-                ", customSkipList=" + customSkipList +
-                '}';
-    }
 }
diff --git a/redpen-core/src/main/java/cc/redpen/validator/sentence/EndOfSentenceValidator.java b/redpen-core/src/main/java/cc/redpen/validator/sentence/EndOfSentenceValidator.java
index f8712861..4eee64da 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/sentence/EndOfSentenceValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/sentence/EndOfSentenceValidator.java
@@ -21,27 +21,26 @@ import cc.redpen.RedPenException;
 import cc.redpen.model.Sentence;
 import cc.redpen.validator.Validator;
 
-import java.util.Arrays;
 import java.util.List;
 import java.util.Locale;
 
 import static cc.redpen.config.SymbolType.*;
+import static java.util.Collections.singletonList;
 
 /**
  * This validator check if the style end of sentence is American style.
  * @see <a href="http://grammar.ccc.commnet.edu/grammar/marks/quotation.htm">Description of quotation marks</a>
  */
-final public class EndOfSentenceValidator extends Validator {
-
-    private char rightSingleQuotation = '\'';
-    private char rightDoubleQuotation = '"';
-    private char period = '.';
-    private char questionMark = '?';
-    private char exclamationMark = '!';
+public final class EndOfSentenceValidator extends Validator {
+    private char rightSingleQuotation;
+    private char rightDoubleQuotation;
+    private char period;
+    private char questionMark;
+    private char exclamationMark;
 
     @Override
     public List<String> getSupportedLanguages() {
-        return Arrays.asList(Locale.ENGLISH.getLanguage());
+        return singletonList(Locale.ENGLISH.getLanguage());
     }
 
     @Override
@@ -57,11 +56,9 @@ final public class EndOfSentenceValidator extends Validator {
                 || lastCharacter == exclamationMark) {
             if (secondCharacter == rightSingleQuotation
                     || secondCharacter == rightDoubleQuotation) {
-                StringBuilder builder = new StringBuilder();
-                builder.append(secondCharacter).append(lastCharacter);
                 addLocalizedErrorWithPosition(sentence,
                         content.length() - 2,
-                        content.length() - 1, builder.toString());
+                        content.length() - 1, String.valueOf(secondCharacter) + lastCharacter);
             }
         }
     }
@@ -74,41 +71,4 @@ final public class EndOfSentenceValidator extends Validator {
         questionMark = getSymbolTable().getSymbol(QUESTION_MARK).getValue();
         exclamationMark = getSymbolTable().getSymbol(EXCLAMATION_MARK).getValue();
     }
-
-    @Override
-    public String toString() {
-        return "EndOfSentenceValidator{" +
-                "rightSingleQuotation=" + rightSingleQuotation +
-                ", rightDoubleQuotation=" + rightDoubleQuotation +
-                ", period=" + period +
-                ", questionMark=" + questionMark +
-                ", exclamationMark=" + exclamationMark +
-                '}';
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        EndOfSentenceValidator that = (EndOfSentenceValidator) o;
-
-        if (exclamationMark != that.exclamationMark) return false;
-        if (period != that.period) return false;
-        if (questionMark != that.questionMark) return false;
-        if (rightDoubleQuotation != that.rightDoubleQuotation) return false;
-        if (rightSingleQuotation != that.rightSingleQuotation) return false;
-
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        int result = (int) rightSingleQuotation;
-        result = 31 * result + (int) rightDoubleQuotation;
-        result = 31 * result + (int) period;
-        result = 31 * result + (int) questionMark;
-        result = 31 * result + (int) exclamationMark;
-        return result;
-    }
 }
diff --git a/redpen-core/src/main/java/cc/redpen/validator/sentence/HankakuKanaValidator.java b/redpen-core/src/main/java/cc/redpen/validator/sentence/HankakuKanaValidator.java
index d1168585..a7bc44d5 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/sentence/HankakuKanaValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/sentence/HankakuKanaValidator.java
@@ -3,12 +3,13 @@ package cc.redpen.validator.sentence;
 import cc.redpen.model.Sentence;
 import cc.redpen.validator.Validator;
 
-import java.util.Arrays;
 import java.util.List;
 import java.util.Locale;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import static java.util.Collections.singletonList;
+
 public class HankakuKanaValidator extends Validator {
     static Pattern pattern = Pattern.compile("[\\uFF65-\\uFF9F\\s-]");
 
@@ -16,7 +17,7 @@ public class HankakuKanaValidator extends Validator {
 
     @Override
     public List<String> getSupportedLanguages() {
-        return Arrays.asList(Locale.JAPANESE.getLanguage());
+        return singletonList(Locale.JAPANESE.getLanguage());
     }
 
     @Override
diff --git a/redpen-core/src/main/java/cc/redpen/validator/sentence/HyphenationValidator.java b/redpen-core/src/main/java/cc/redpen/validator/sentence/HyphenationValidator.java
index 6601cb2e..893362f3 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/sentence/HyphenationValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/sentence/HyphenationValidator.java
@@ -20,18 +20,14 @@ package cc.redpen.validator.sentence;
 
 import cc.redpen.model.Sentence;
 import cc.redpen.tokenizer.TokenElement;
-import cc.redpen.util.SpellingUtils;
-import cc.redpen.validator.Validator;
 
 /**
  * Ensure groups of words that are hyphenated in the dictionary are hyphenated in the sentence
  */
-public class HyphenationValidator extends Validator {
+public class HyphenationValidator extends SpellingDictionaryValidator {
 
     @Override
     public void validate(Sentence sentence) {
-        String lang = getSymbolTable().getLang();
-
         // consider hyphenated words of this array's length
         TokenElement tokens[] = new TokenElement[]{null, null, null, null};
 
@@ -47,7 +43,7 @@ public class HyphenationValidator extends Validator {
                 String hyphenatedForm = tokens[0].getSurface();
                 for (int j = 1; (j < tokens.length) && (tokens[j] != null); j++) {
                     hyphenatedForm += "-" + tokens[j].getSurface();
-                    if (SpellingUtils.getDictionary(lang).contains(hyphenatedForm.toLowerCase())) {
+                    if (inDictionary(hyphenatedForm.toLowerCase())) {
                         addLocalizedErrorWithPosition(
                                 "HyphenatedInDictionary",
                                 sentence,
diff --git a/redpen-core/src/main/java/cc/redpen/validator/sentence/InvalidExpressionValidator.java b/redpen-core/src/main/java/cc/redpen/validator/sentence/InvalidExpressionValidator.java
index 2ace583f..a1eb1f26 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/sentence/InvalidExpressionValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/sentence/InvalidExpressionValidator.java
@@ -17,88 +17,24 @@
  */
 package cc.redpen.validator.sentence;
 
-import cc.redpen.RedPenException;
 import cc.redpen.model.Sentence;
-import cc.redpen.validator.Validator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Optional;
-import java.util.Set;
-import java.util.function.Consumer;
+import cc.redpen.validator.DictionaryValidator;
 
 /**
  * Validate input sentences contain invalid expression.
  */
-final public class InvalidExpressionValidator extends Validator {
-    private static final String DEFAULT_RESOURCE_PATH = "default-resources/invalid-expression";
-    private static final Logger LOG =
-            LoggerFactory.getLogger(InvalidExpressionValidator.class);
-    private Set<String> invalidExpressions;
-    private Set<String> customInvalidExpressions;
+public final class InvalidExpressionValidator extends DictionaryValidator {
+    public InvalidExpressionValidator() {
+        super("invalid-expression/invalid-expression");
+    }
 
     @Override
     public void validate(Sentence sentence) {
-        Consumer<String> tConsumer = value -> {
+        streamDictionary().forEach(value -> {
             int startPosition = sentence.getContent().indexOf(value);
             if (startPosition != -1) {
                 addLocalizedErrorWithPosition(sentence, startPosition, startPosition + value.length(), value);
             }
-        };
-
-        invalidExpressions.stream().forEach(tConsumer);
-        customInvalidExpressions.stream().forEach(tConsumer);
-    }
-
-    @Override
-    protected void init() throws RedPenException {
-
-        String lang = getSymbolTable().getLang();
-        String defaultDictionaryFile = DEFAULT_RESOURCE_PATH
-                + "/invalid-expression-" + lang + ".dat";
-        invalidExpressions = WORD_LIST.loadCachedFromResource(defaultDictionaryFile, "invalid expression");
-
-        customInvalidExpressions = new HashSet<>();
-        Optional<String> listStr = getConfigAttribute("list");
-        listStr.ifPresent(f -> {
-            LOG.info("User defined invalid expression list found.");
-            customInvalidExpressions.addAll(Arrays.asList(f.split(",")));
-            LOG.info("Succeeded to add elements of user defined list.");
         });
-
-        Optional<String> confFile = getConfigAttribute("dict");
-        if (confFile.isPresent()) {
-            customInvalidExpressions.addAll(WORD_LIST.loadCachedFromFile(findFile(confFile.get()), "InvalidExpressionValidator user dictionary"));
-        }
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        InvalidExpressionValidator that = (InvalidExpressionValidator) o;
-
-        if (invalidExpressions != null ? !invalidExpressions.equals(that.invalidExpressions) : that.invalidExpressions != null)
-            return false;
-        return !(customInvalidExpressions != null ? !customInvalidExpressions.equals(that.customInvalidExpressions) : that.customInvalidExpressions != null);
-
-    }
-
-    @Override
-    public int hashCode() {
-        int result = invalidExpressions != null ? invalidExpressions.hashCode() : 0;
-        result = 31 * result + (customInvalidExpressions != null ? customInvalidExpressions.hashCode() : 0);
-        return result;
-    }
-
-    @Override
-    public String toString() {
-        return "InvalidExpressionValidator{" +
-                "invalidExpressions=" + invalidExpressions +
-                ", customInvalidExpressions=" + customInvalidExpressions +
-                '}';
     }
 }
diff --git a/redpen-core/src/main/java/cc/redpen/validator/sentence/InvalidSymbolValidator.java b/redpen-core/src/main/java/cc/redpen/validator/sentence/InvalidSymbolValidator.java
index f4613175..f35518e8 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/sentence/InvalidSymbolValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/sentence/InvalidSymbolValidator.java
@@ -27,7 +27,7 @@ import java.util.Set;
 /**
  * Validate if there is invalid characters in sentences.
  */
-final public class InvalidSymbolValidator extends Validator {
+public final class InvalidSymbolValidator extends Validator {
 
     @Override
     public void validate(Sentence sentence) {
diff --git a/redpen-core/src/main/java/cc/redpen/validator/sentence/InvalidWordValidator.java b/redpen-core/src/main/java/cc/redpen/validator/sentence/InvalidWordValidator.java
index 4673d581..67790863 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/sentence/InvalidWordValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/sentence/InvalidWordValidator.java
@@ -17,85 +17,35 @@
  */
 package cc.redpen.validator.sentence;
 
-import cc.redpen.RedPenException;
 import cc.redpen.model.Sentence;
 import cc.redpen.tokenizer.TokenElement;
-import cc.redpen.validator.Validator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import cc.redpen.validator.DictionaryValidator;
 
-import java.util.*;
+import java.util.List;
+import java.util.Locale;
+
+import static java.util.Collections.singletonList;
 
 /**
  * Detect invalid word occurrences.
  */
-final public class InvalidWordValidator extends Validator {
-    private static final String DEFAULT_RESOURCE_PATH =
-            "default-resources/invalid-word";
-    private static final Logger LOG =
-            LoggerFactory.getLogger(InvalidWordValidator.class);
-    private Set<String> invalidWords;
-    private Set<String> customInvalidWords = new HashSet<>();
+public final class InvalidWordValidator extends DictionaryValidator {
+    public InvalidWordValidator() {
+        super("invalid-word/invalid-word");
+    }
 
     @Override
     public List<String> getSupportedLanguages() {
-        return Arrays.asList(Locale.ENGLISH.getLanguage());
+        return singletonList(Locale.ENGLISH.getLanguage());
     }
 
     @Override
     public void validate(Sentence sentence) {
-        //NOTE: only Ascii white space since this validator works for european languages.
         for (TokenElement token : sentence.getTokens()) {
-            if (invalidWords.contains(token.getSurface().toLowerCase())
-                    || customInvalidWords.contains(token.getSurface().toLowerCase())) {
+            String word = token.getSurface().toLowerCase();
+            if (inDictionary(word)) {
                 addLocalizedErrorFromToken(sentence, token);
             }
         }
     }
-
-    @Override
-    protected void init() throws RedPenException {
-        String lang = getSymbolTable().getLang();
-        String defaultDictionaryResource = DEFAULT_RESOURCE_PATH
-                + "/invalid-word-" + lang + ".dat";
-        invalidWords = WORD_LIST.loadCachedFromResource(defaultDictionaryResource, "invalid word");
-
-        getConfigAttribute("list").ifPresent((f -> {
-            LOG.info("User defined invalid expression list found.");
-            customInvalidWords.addAll(Arrays.asList(f.split(",")));
-            LOG.info("Succeeded to add elements of user defined list.");
-        }));
-
-        Optional<String> confFile = getConfigAttribute("dict");
-        if (confFile.isPresent()) {
-            customInvalidWords.addAll(WORD_LIST.loadCachedFromFile(findFile(confFile.get()), "InvalidWordValidator user dictionary"));
-        }
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        InvalidWordValidator that = (InvalidWordValidator) o;
-
-        if (invalidWords != null ? !invalidWords.equals(that.invalidWords) : that.invalidWords != null) return false;
-        return !(customInvalidWords != null ? !customInvalidWords.equals(that.customInvalidWords) : that.customInvalidWords != null);
-
-    }
-
-    @Override
-    public int hashCode() {
-        int result = invalidWords != null ? invalidWords.hashCode() : 0;
-        result = 31 * result + (customInvalidWords != null ? customInvalidWords.hashCode() : 0);
-        return result;
-    }
-
-    @Override
-    public String toString() {
-        return "InvalidWordValidator{" +
-                "invalidWords=" + invalidWords +
-                ", customInvalidWords=" + customInvalidWords +
-                '}';
-    }
 }
diff --git a/redpen-core/src/main/java/cc/redpen/validator/sentence/JapaneseStyleValidator.java b/redpen-core/src/main/java/cc/redpen/validator/sentence/JapaneseStyleValidator.java
index 5b34a84c..51a41442 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/sentence/JapaneseStyleValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/sentence/JapaneseStyleValidator.java
@@ -20,15 +20,15 @@ package cc.redpen.validator.sentence;
 import cc.redpen.model.Sentence;
 import cc.redpen.validator.Validator;
 
-import java.util.Arrays;
 import java.util.List;
 import java.util.Locale;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import static java.util.Collections.singletonList;
+
 /**
  * Validate Japanese document if it contains both Desumasu and Dearu styles.
- * 
  */
 public class JapaneseStyleValidator extends Validator {
     private static final Pattern DEARU_PATTERN = Pattern.compile("のだが|したが|したので|ないかと|してきた|であるから");
@@ -55,8 +55,8 @@ public class JapaneseStyleValidator extends Validator {
         String content = sentence.getContent();
         Matcher mat = pattern.matcher(content);
         int count = 0;
-        while(mat.find()){
-            count +=1;
+        while(mat.find()) {
+            count += 1;
         }
         return count;
     }
@@ -98,34 +98,6 @@ public class JapaneseStyleValidator extends Validator {
 
     @Override
     public List<String> getSupportedLanguages() {
-        return Arrays.asList(Locale.JAPANESE.getLanguage());
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        JapaneseStyleValidator that = (JapaneseStyleValidator) o;
-
-        if (dearuCount != that.dearuCount) return false;
-        if (desumasuCount != that.desumasuCount) return false;
-
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        int result = dearuCount;
-        result = 31 * result + desumasuCount;
-        return result;
-    }
-
-    @Override
-    public String toString() {
-        return "JapaneseStyleValidator{" +
-                "dearuCount=" + dearuCount +
-                ", desumasuCount=" + desumasuCount +
-                '}';
+        return singletonList(Locale.JAPANESE.getLanguage());
     }
 }
diff --git a/redpen-core/src/main/java/cc/redpen/validator/sentence/KatakanaEndHyphenValidator.java b/redpen-core/src/main/java/cc/redpen/validator/sentence/KatakanaEndHyphenValidator.java
index 448dd495..fd93f8ef 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/sentence/KatakanaEndHyphenValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/sentence/KatakanaEndHyphenValidator.java
@@ -17,14 +17,15 @@
  */
 package cc.redpen.validator.sentence;
 
-import cc.redpen.RedPenException;
 import cc.redpen.model.Sentence;
 import cc.redpen.util.StringUtils;
-import cc.redpen.validator.Validator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import cc.redpen.validator.DictionaryValidator;
 
-import java.util.*;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+
+import static java.util.Collections.singletonList;
 
 /**
  * Validate the end hyphens of Katakana words in Japanese documents.
@@ -45,10 +46,7 @@ import java.util.*;
  * <p>
  * Note that KatakanaEndHyphenValidator only checks the rules a) and b).
  */
-final public class KatakanaEndHyphenValidator extends Validator {
-    private static final Logger LOG =
-            LoggerFactory.getLogger(KatakanaEndHyphenValidator.class);
-
+public final class KatakanaEndHyphenValidator extends DictionaryValidator {
     /**
      * Default Katakana limit length without hypen.
      */
@@ -62,12 +60,6 @@ final public class KatakanaEndHyphenValidator extends Validator {
      */
     private static final char KATAKANA_MIDDLE_DOT = '・';
 
-    private Set<String> customSkipList;
-
-    public KatakanaEndHyphenValidator() {
-        super();
-    }
-
     public static boolean isKatakanaEndHyphen(String katakana) {
         return (DEFAULT_KATAKANA_LIMIT_LENGTH < katakana.length()
                 && katakana.charAt(katakana.length() - 1) == HYPHEN);
@@ -75,12 +67,12 @@ final public class KatakanaEndHyphenValidator extends Validator {
 
     @Override
     public List<String> getSupportedLanguages() {
-        return Arrays.asList(Locale.JAPANESE.getLanguage());
+        return singletonList(Locale.JAPANESE.getLanguage());
     }
 
     @Override
     public void validate(Sentence sentence) {
-        StringBuilder katakana = new StringBuilder("");
+        StringBuilder katakana = new StringBuilder();
         for (int i = 0; i < sentence.getContent().length(); i++) {
             char c = sentence.getContent().charAt(i);
             if (StringUtils.isKatakana(c) && c != KATAKANA_MIDDLE_DOT) {
@@ -93,51 +85,12 @@ final public class KatakanaEndHyphenValidator extends Validator {
         this.checkKatakanaEndHyphen(sentence, katakana.toString(), sentence.getContent().length() - 1);
     }
 
-    private void checkKatakanaEndHyphen(Sentence sentence,
-                                                         String katakana,
-                                                         int position) {
-        if ( !(customSkipList != null && customSkipList.contains(katakana)) ) {
+    private void checkKatakanaEndHyphen(Sentence sentence, String katakana, int position) {
+        Set<String> customSkipList = getSet("list");
+        if (customSkipList.isEmpty() || !customSkipList.contains(katakana)) {
             if (isKatakanaEndHyphen(katakana)) {
                 addLocalizedErrorWithPosition(sentence, position, position + 1, katakana);
             }
         }
     }
-
-    @Override
-    protected void init() throws RedPenException {
-        customSkipList = new HashSet<>();
-        Optional<String> skipListStr = getConfigAttribute("list");
-        skipListStr.ifPresent(f -> {
-            LOG.info("Found user defined skip list.");
-            customSkipList.addAll(Arrays.asList(f.split(",")));
-            LOG.info("Succeeded to add elements of user defined skip list.");
-        });
-
-        Optional<String> confFile = getConfigAttribute("dict");
-        if (confFile.isPresent()) {
-            customSkipList.addAll(WORD_LIST.loadCachedFromFile(findFile(confFile.get()), "KatakanaEndHyphenValidator user dictionary"));
-        }
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        KatakanaEndHyphenValidator that = (KatakanaEndHyphenValidator) o;
-
-        return !(customSkipList != null ? !customSkipList.equals(that.customSkipList) : that.customSkipList != null);
-    }
-
-    @Override
-    public int hashCode() {
-        return customSkipList != null ? customSkipList.hashCode() : 0;
-    }
-
-    @Override
-    public String toString() {
-        return "KatakanaEndHyphenValidator{" +
-                "customSkipList=" + customSkipList +
-                '}';
-    }
 }
diff --git a/redpen-core/src/main/java/cc/redpen/validator/sentence/KatakanaSpellCheckValidator.java b/redpen-core/src/main/java/cc/redpen/validator/sentence/KatakanaSpellCheckValidator.java
index e2368ea9..24e40c68 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/sentence/KatakanaSpellCheckValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/sentence/KatakanaSpellCheckValidator.java
@@ -21,12 +21,12 @@ import cc.redpen.RedPenException;
 import cc.redpen.model.Sentence;
 import cc.redpen.util.LevenshteinDistance;
 import cc.redpen.util.StringUtils;
-import cc.redpen.validator.Validator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import cc.redpen.validator.DictionaryValidator;
 
 import java.util.*;
 
+import static java.util.Collections.singletonList;
+
 /**
  * Validate the correctness of Katakana word spelling.
  * Japanese Katakana words have orthographical variations.
@@ -47,31 +47,11 @@ import java.util.*;
  * word is smaller than the threshold, we do not detect
  * the similarity.
  */
-final public class KatakanaSpellCheckValidator extends Validator {
-    /**
-     * The default threshold of similarity ratio between the length and the distance. <br>
-     * <p>
-     * The similarities are computed by edit distance.
-     */
-    private static final float DEFAULT_SIMILARITY_RATIO = 0.3f;
-    /**
-     * The default threshold of word frequencies of Katakana Words.
-     */
-    private static final int DEFAULT_MINIMUM_FREQUENCIES = 5;
-    /**
-     * The default threshold value for the length of Katakana word
-     * to ignore.
-     */
-    private static final int MAX_IGNORE_KATAKANA_LENGTH = 3;
+ public final class KatakanaSpellCheckValidator extends DictionaryValidator {
     /**
      * Default dictionary for Katakana spell checking.
      */
     private static final String DEFAULT_RESOURCE_PATH = "default-resources/katakana";
-    /**
-     * Logger
-     */
-    private static final Logger LOG =
-            LoggerFactory.getLogger(KatakanaSpellCheckValidator.class);
 
     /**
      * Katakana word dic with line number.
@@ -82,17 +62,18 @@ final public class KatakanaSpellCheckValidator extends Validator {
      */
     private Set<String> exceptions = new HashSet<>();
 
-    private Set<String> customExceptions = new HashSet<>();
-
     private Map<String, Integer> katakanaWordFrequencies = new HashMap<>();
 
-    private float minimumRatio = DEFAULT_SIMILARITY_RATIO;
-
-    private int minimumFrequencies = DEFAULT_MINIMUM_FREQUENCIES;
+    public KatakanaSpellCheckValidator() {
+        super("min_ratio", 0.3f, // The default threshold of similarity ratio between the length and the distance. The similarities are computed by edit distance.
+              "min_freq", 5, // The default threshold of word frequencies of Katakana Words.
+              "max_ignore_len", 3, // The default threshold value for the length of Katakana word to ignore
+              "disable-default", false);
+    }
 
     @Override
     public List<String> getSupportedLanguages() {
-        return Arrays.asList(Locale.JAPANESE.getLanguage());
+        return singletonList(Locale.JAPANESE.getLanguage());
     }
 
     @Override
@@ -138,16 +119,16 @@ final public class KatakanaSpellCheckValidator extends Validator {
     }
 
     private void checkKatakanaSpell(Sentence sentence, String katakana) {
-        if (katakana.length() <= MAX_IGNORE_KATAKANA_LENGTH) {
+        if (katakana.length() <= getInt("max_ignore_len")) {
             return;
         }
         if (dic.containsKey(katakana) || exceptions.contains(katakana)
-                || customExceptions.contains(katakana) ||
+                || getSet("list").contains(katakana) ||
                 (katakanaWordFrequencies.get(katakana) != null
-                        && katakanaWordFrequencies.get(katakana) > minimumFrequencies)) {
+                        && katakanaWordFrequencies.get(katakana) > getInt("min_freq"))) {
             return;
         }
-        final int minLsDistance = Math.round(katakana.length() * minimumRatio);
+        int minLsDistance = Math.round(katakana.length() * getFloat("min_ratio"));
         boolean found = false;
         for (String key : dic.keySet()) {
             if (LevenshteinDistance.getDistance(key, katakana) <= minLsDistance) {
@@ -162,59 +143,10 @@ final public class KatakanaSpellCheckValidator extends Validator {
 
     @Override
     protected void init() throws RedPenException {
-        boolean disableDefault = getConfigAttributeAsBoolean("disable-default", false);
-        if (!disableDefault) {
+        super.init();
+        if (!getBoolean("disable-default")) {
             String defaultDictionaryFile = DEFAULT_RESOURCE_PATH + "/katakana-spellcheck.dat";
             exceptions = WORD_LIST.loadCachedFromResource(defaultDictionaryFile, "katakana word dictionary");
         }
-
-        Optional<String> confFile = getConfigAttribute("dict");
-        if (confFile.isPresent()) {
-            LOG.info("User defined Katakana word dictionary found.");
-            customExceptions.addAll(WORD_LIST.loadCachedFromFile(findFile(confFile.get()),
-                    "KatakanaSpellCheckValidator user dictionary"));
-            LOG.info("Succeeded to add elements of user defined dictionary.");
-        }
-
-        getConfigAttribute("list").ifPresent((f -> {
-            LOG.info("User defined Katakana words list found.");
-            customExceptions.addAll(Arrays.asList(f.split(",")));
-            LOG.info("Succeeded to add elements of user defined list.");
-        }));
-
-        minimumRatio = (float) getConfigAttributeAsDouble("min_ratio", DEFAULT_SIMILARITY_RATIO);
-        minimumFrequencies = getConfigAttributeAsInt("min_freq", DEFAULT_MINIMUM_FREQUENCIES);
-
-        //TODO : configurable MAX_IGNORE_KATAKANA_LENGTH.
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        KatakanaSpellCheckValidator that = (KatakanaSpellCheckValidator) o;
-
-        if (dic != null ? !dic.equals(that.dic) : that.dic != null) return false;
-        if (exceptions != null ? !exceptions.equals(that.exceptions) : that.exceptions != null) return false;
-        return !(customExceptions != null ? !customExceptions.equals(that.customExceptions) : that.customExceptions != null);
-
-    }
-
-    @Override
-    public int hashCode() {
-        int result = dic != null ? dic.hashCode() : 0;
-        result = 31 * result + (exceptions != null ? exceptions.hashCode() : 0);
-        result = 31 * result + (customExceptions != null ? customExceptions.hashCode() : 0);
-        return result;
-    }
-
-    @Override
-    public String toString() {
-        return "KatakanaSpellCheckValidator{" +
-                "dic=" + dic +
-                ", exceptions=" + exceptions +
-                ", customExceptions=" + customExceptions +
-                '}';
     }
 }
diff --git a/redpen-core/src/main/java/cc/redpen/validator/sentence/NumberFormatValidator.java b/redpen-core/src/main/java/cc/redpen/validator/sentence/NumberFormatValidator.java
index 168890d8..89fe3629 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/sentence/NumberFormatValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/sentence/NumberFormatValidator.java
@@ -31,17 +31,16 @@ public class NumberFormatValidator extends Validator {
     // specifies which characters delimite the decimal part of a number
     private String decimalDelimiters = DOT_DELIMITERS;
 
-    // should we ignore years (basically four digit integers)
-    boolean ignoreYears = false;
+    public NumberFormatValidator() {
+        super("decimal_delimiter_is_comma", false, "ignore_years", false);
+    }
 
     @Override
     protected void init() throws RedPenException {
         super.init();
 
         // set the following to true to support EU formats such as 1.000,00
-        boolean decimalDelimiterComma = getConfigAttributeAsBoolean("decimal_delimiter_is_comma", false);
-        ignoreYears = getConfigAttributeAsBoolean("ignore_years", false);
-        if (decimalDelimiterComma) {
+        if (getBoolean("decimal_delimiter_is_comma")) {
             decimalDelimiters = COMMA_DELIMITERS;
         } else {
             decimalDelimiters = DOT_DELIMITERS;
@@ -86,10 +85,6 @@ public class NumberFormatValidator extends Validator {
 
     /**
      * Inspect how a number is formatted and generate an error where appropriate
-     *
-     * @param sentence
-     * @param position
-     * @param number
      */
     private void validateNumber(Sentence sentence, int position, String number) {
         if (!number.isEmpty()) {
@@ -115,7 +110,7 @@ public class NumberFormatValidator extends Validator {
             }
 
             // if it's a four digit integer and we are ignoring years, ignore this
-            if (ignoreYears && isInteger && (integerPortion.length() == 4)) {
+            if (getBoolean("ignore_years") && isInteger && (integerPortion.length() == 4)) {
                 return;
             }
 
diff --git a/redpen-core/src/main/java/cc/redpen/validator/sentence/OkuriganaValidator.java b/redpen-core/src/main/java/cc/redpen/validator/sentence/OkuriganaValidator.java
index b71adbc0..38bf8acf 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/sentence/OkuriganaValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/sentence/OkuriganaValidator.java
@@ -23,7 +23,13 @@ import cc.redpen.tokenizer.TokenElement;
 import cc.redpen.validator.ExpressionRule;
 import cc.redpen.validator.Validator;
 
-import java.util.*;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.singletonList;
 
 // Checks if the Japanese input sentences contain the invalid Okurigana style.
 public class OkuriganaValidator extends Validator {
@@ -32,10 +38,10 @@ public class OkuriganaValidator extends Validator {
 
     static {
         invalidOkuriganaTokens = new HashSet<>();
-        invalidOkuriganaTokens.add(new ExpressionRule().addElement(new TokenElement("合さ", Arrays.asList("動詞", "自立"), 0)));
-        invalidOkuriganaTokens.add(new ExpressionRule().addElement(new TokenElement("合し", Arrays.asList("動詞", "自立"), 0)));
-        invalidOkuriganaTokens.add(new ExpressionRule().addElement(new TokenElement("合す", Arrays.asList("動詞", "自立"), 0)));
-        invalidOkuriganaTokens.add(new ExpressionRule().addElement(new TokenElement("合せ", Arrays.asList("動詞", "自立"), 0)));
+        invalidOkuriganaTokens.add(new ExpressionRule().addElement(new TokenElement("合さ", asList("動詞", "自立"), 0)));
+        invalidOkuriganaTokens.add(new ExpressionRule().addElement(new TokenElement("合し", asList("動詞", "自立"), 0)));
+        invalidOkuriganaTokens.add(new ExpressionRule().addElement(new TokenElement("合す", asList("動詞", "自立"), 0)));
+        invalidOkuriganaTokens.add(new ExpressionRule().addElement(new TokenElement("合せ", asList("動詞", "自立"), 0)));
     }
 
     static {
@@ -149,16 +155,11 @@ public class OkuriganaValidator extends Validator {
 
     @Override
     public List<String> getSupportedLanguages() {
-        return Arrays.asList(Locale.JAPANESE.getLanguage());
+        return singletonList(Locale.JAPANESE.getLanguage());
     }
 
     @Override
     protected void init() throws RedPenException {
         // TODO: user dictionary
     }
-
-    @Override
-    public String toString() {
-        return "OkuriganaValidator{}";
-    }
 }
diff --git a/redpen-core/src/main/java/cc/redpen/validator/sentence/ParenthesizedSentenceValidator.java b/redpen-core/src/main/java/cc/redpen/validator/sentence/ParenthesizedSentenceValidator.java
index fef5e5ce..0ba4dc42 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/sentence/ParenthesizedSentenceValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/sentence/ParenthesizedSentenceValidator.java
@@ -18,7 +18,6 @@
 package cc.redpen.validator.sentence;
 
 
-import cc.redpen.RedPenException;
 import cc.redpen.model.Sentence;
 import cc.redpen.tokenizer.TokenElement;
 import cc.redpen.validator.Validator;
@@ -27,20 +26,13 @@ import cc.redpen.validator.Validator;
  * Warn if too many (or overly long (or nested parenthesized sentences (where you do this))) are used in a sentence
  */
 public class ParenthesizedSentenceValidator extends Validator {
-
     private static final String OPEN_PARENS = "(（";
     private static final String CLOSE_PARENS = ")）";
 
-    private int nestingLevelMax = 2; // the limit on how many parenthesized expressions are permitted
-    private int subsentenceCountMax = 1; // the number of parenthesized expressions allowed
-    private int subsentenceLengthMax = 4; // the maximum number of words in a parenthesized expression
-
-    @Override
-    protected void init() throws RedPenException {
-        super.init();
-        nestingLevelMax = getConfigAttributeAsInt("max_nesting_level", 1);
-        subsentenceCountMax = getConfigAttributeAsInt("max_count", 1);
-        subsentenceLengthMax = getConfigAttributeAsInt("max_length", 3);
+    public ParenthesizedSentenceValidator() {
+        super("max_nesting_level", 1, // the limit on how many parenthesized expressions are permitted
+              "max_count", 1,  // the number of parenthesized expressions allowed
+              "max_length", 3); // the maximum number of words in a parenthesized expression
     }
 
     /**
@@ -57,7 +49,7 @@ public class ParenthesizedSentenceValidator extends Validator {
             if (token.getSurface().length() == 1) {
                 if (OPEN_PARENS.indexOf(token.getSurface().charAt(0)) != -1) {
                     nestingLevel++;
-                    if (nestingLevel > nestingLevelMax) {
+                    if (nestingLevel > getInt("max_nesting_level")) {
                         addLocalizedErrorWithPosition(
                                 "NestingLevelTooDeep",
                                 sentence,
@@ -68,7 +60,7 @@ public class ParenthesizedSentenceValidator extends Validator {
                     nestingLevel = Math.max(0, nestingLevel - 1);
                     if (nestingLevel == 0) {
                         subsentenceCount++;
-                        if (subsentenceLength > subsentenceLengthMax) {
+                        if (subsentenceLength > getInt("max_length")) {
                             addLocalizedErrorWithPosition(
                                     "SubsentenceTooLong",
                                     sentence,
@@ -85,9 +77,8 @@ public class ParenthesizedSentenceValidator extends Validator {
             }
         }
 
-        if (subsentenceCount > subsentenceCountMax) {
+        if (subsentenceCount > getInt("max_count")) {
             addLocalizedError("SubsentenceTooFrequent", sentence);
         }
-
     }
 }
diff --git a/redpen-core/src/main/java/cc/redpen/validator/sentence/QuotationValidator.java b/redpen-core/src/main/java/cc/redpen/validator/sentence/QuotationValidator.java
index df6939b0..dc2c59ea 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/sentence/QuotationValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/sentence/QuotationValidator.java
@@ -23,11 +23,11 @@ import cc.redpen.model.Sentence;
 import cc.redpen.validator.Validator;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 import java.util.Locale;
 
 import static cc.redpen.config.SymbolType.*;
+import static java.util.Collections.singletonList;
 
 /**
  * Validator to validate quotation characters.
@@ -49,25 +49,28 @@ public class QuotationValidator extends Validator {
     private Symbol rightDoubleQuotationMark;
     private char period;
 
+    public QuotationValidator() {
+        super("use_ascii", false);
+    }
+
     @Override
     public List<String> getSupportedLanguages() {
-        return Arrays.asList(Locale.ENGLISH.getLanguage());
+        return singletonList(Locale.ENGLISH.getLanguage());
     }
 
     @Override
     public void validate(Sentence sentence) {
         // validate single quotation
-        this.checkQuotation(sentence, leftSingleQuotationMark, rightSingleQuotationMark);
+        checkQuotation(sentence, leftSingleQuotationMark, rightSingleQuotationMark);
 
         // validate double quotation
-        this.checkQuotation(sentence, leftDoubleQuotationMark, rightDoubleQuotationMark);
+        checkQuotation(sentence, leftDoubleQuotationMark, rightDoubleQuotationMark);
     }
 
     @Override
     protected void init() throws RedPenException {
         this.period = getSymbolTable().getValueOrFallbackToDefault(FULL_STOP);
-
-        setUseAscii(getConfigAttributeAsBoolean("use_ascii", false));
+        setUseAscii(getBoolean("use_ascii"));
     }
 
     private void setUseAscii(boolean useAscii) {
diff --git a/redpen-core/src/main/java/cc/redpen/validator/sentence/SentenceLengthValidator.java b/redpen-core/src/main/java/cc/redpen/validator/sentence/SentenceLengthValidator.java
index 0063554e..dc548684 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/sentence/SentenceLengthValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/sentence/SentenceLengthValidator.java
@@ -17,70 +17,22 @@
  */
 package cc.redpen.validator.sentence;
 
-import cc.redpen.RedPenException;
 import cc.redpen.model.Sentence;
 import cc.redpen.validator.Validator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * Validate input sentences contain more characters more than specified.
  */
-final public class SentenceLengthValidator extends Validator {
-    /**
-     * Default maximum length of sentences.
-     */
-    @SuppressWarnings("WeakerAccess")
-    public static final int DEFAULT_MAX_LENGTH = 120;
-    private static final Logger LOG =
-            LoggerFactory.getLogger(SentenceLengthValidator.class);
-    private int maxLength = DEFAULT_MAX_LENGTH;
+public final class SentenceLengthValidator extends Validator {
+    public SentenceLengthValidator() {
+        super("max_len", 120);
+    }
 
     @Override
     public void validate(Sentence sentence) {
+        int maxLength = getInt("max_len");
         if (sentence.getContent().length() > maxLength) {
             addLocalizedError(sentence, sentence.getContent().length(), maxLength);
         }
     }
-
-    @Override
-    protected void init() throws RedPenException {
-        this.maxLength = getConfigAttributeAsInt("max_len", DEFAULT_MAX_LENGTH);
-    }
-
-    /**
-     * Set maximum length of sentence.
-     *
-     * @param maxLength max limit of sentence length
-     */
-    protected void setLengthLimit(int maxLength) {
-        this.setMaxLength(maxLength);
-    }
-
-    protected void setMaxLength(int max) {
-        this.maxLength = max;
-    }
-
-    @Override
-    public String toString() {
-        return "SentenceLengthValidator{" +
-                "maxLength=" + maxLength +
-                '}';
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        SentenceLengthValidator that = (SentenceLengthValidator) o;
-
-        return maxLength == that.maxLength;
-
-    }
-
-    @Override
-    public int hashCode() {
-        return maxLength;
-    }
 }
diff --git a/redpen-core/src/main/java/cc/redpen/validator/sentence/SpaceBeginningOfSentenceValidator.java b/redpen-core/src/main/java/cc/redpen/validator/sentence/SpaceBeginningOfSentenceValidator.java
index d5af4d2e..6392894e 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/sentence/SpaceBeginningOfSentenceValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/sentence/SpaceBeginningOfSentenceValidator.java
@@ -29,7 +29,7 @@ import java.util.Map;
  * Validate input sentences except for first sentence of a paragraph start with
  * a space.
  */
-final public class SpaceBeginningOfSentenceValidator extends Validator {
+public final class SpaceBeginningOfSentenceValidator extends Validator {
     private Map<Integer, List<Sentence>> sentencePositions = new HashMap<>();
 
     private boolean isFirstInLine(Sentence sentence) {
@@ -52,27 +52,4 @@ final public class SpaceBeginningOfSentenceValidator extends Validator {
         List<Sentence> list = sentencePositions.get(sentence.getLineNumber());
         list.add(sentence);
     }
-
-    @Override
-    public String toString() {
-        return "SpaceBeginningOfSentenceValidator{" +
-                "sentencePositions=" + sentencePositions +
-                '}';
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        SpaceBeginningOfSentenceValidator that = (SpaceBeginningOfSentenceValidator) o;
-
-        return !(sentencePositions != null ? !sentencePositions.equals(that.sentencePositions) : that.sentencePositions != null);
-
-    }
-
-    @Override
-    public int hashCode() {
-        return sentencePositions != null ? sentencePositions.hashCode() : 0;
-    }
 }
diff --git a/redpen-core/src/main/java/cc/redpen/validator/sentence/SpellingDictionaryValidator.java b/redpen-core/src/main/java/cc/redpen/validator/sentence/SpellingDictionaryValidator.java
new file mode 100644
index 00000000..7767cef0
--- /dev/null
+++ b/redpen-core/src/main/java/cc/redpen/validator/sentence/SpellingDictionaryValidator.java
@@ -0,0 +1,12 @@
+package cc.redpen.validator.sentence;
+
+import cc.redpen.validator.DictionaryValidator;
+
+/**
+ * Base class for Validators using the spelling dictionary.
+ */
+public abstract class SpellingDictionaryValidator extends DictionaryValidator {
+  public SpellingDictionaryValidator() {
+    super(WORD_LIST_LOWERCASED, "spellchecker/spellchecker");
+  }
+}
diff --git a/redpen-core/src/main/java/cc/redpen/validator/sentence/SpellingValidator.java b/redpen-core/src/main/java/cc/redpen/validator/sentence/SpellingValidator.java
index 4f893b44..31e37d4c 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/sentence/SpellingValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/sentence/SpellingValidator.java
@@ -17,48 +17,11 @@
  */
 package cc.redpen.validator.sentence;
 
-import cc.redpen.RedPenException;
 import cc.redpen.model.Sentence;
 import cc.redpen.tokenizer.TokenElement;
-import cc.redpen.util.SpellingUtils;
-import cc.redpen.validator.Validator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Optional;
-import java.util.Set;
-
-public class SpellingValidator extends Validator {
-
-    private static final Logger LOG = LoggerFactory.getLogger(SpellingValidator.class);
 
+public final class SpellingValidator extends SpellingDictionaryValidator {
     private static String skipCharacters = "[\\!-/:-@\\[-`{-~]";
-    // TODO: replace more memory efficient data structure
-    private Set<String> defaultDictionary;
-    private Set<String> customDictionary;
-
-
-    @Override
-    protected void init() throws RedPenException {
-        defaultDictionary = SpellingUtils.getDictionary(getSymbolTable().getLang());
-
-        customDictionary = new HashSet<>();
-
-        Optional<String> listStr = getConfigAttribute("list");
-        listStr.ifPresent(f -> {
-            LOG.info("User defined valid word list found.");
-            customDictionary.addAll(Arrays.asList(f.split(",")));
-            LOG.info("Succeeded to add elements of user defined list.");
-        });
-
-        Optional<String> userDictionaryFile = getConfigAttribute("dict");
-        if (userDictionaryFile.isPresent()) {
-            String f = userDictionaryFile.get();
-            customDictionary.addAll(WORD_LIST_LOWERCASED.loadCachedFromFile(findFile(f), "SpellingValidator user dictionary"));
-        }
-    }
 
     @Override
     public void validate(Sentence sentence) {
@@ -68,7 +31,7 @@ public class SpellingValidator extends Validator {
                 continue;
             }
 
-            if (!this.defaultDictionary.contains(surface) && !this.customDictionary.contains(surface)) {
+            if (dictionaryExists() && !inDictionary(surface)) {
                 addLocalizedErrorFromToken(sentence, token);
             }
         }
@@ -77,32 +40,4 @@ public class SpellingValidator extends Validator {
     private String normalize(String token) {
         return token.toLowerCase().replaceAll(skipCharacters, "");
     }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        SpellingValidator that = (SpellingValidator) o;
-
-        if (defaultDictionary != null ? !defaultDictionary.equals(that.defaultDictionary) : that.defaultDictionary != null)
-            return false;
-        return !(customDictionary != null ? !customDictionary.equals(that.customDictionary) : that.customDictionary != null);
-
-    }
-
-    @Override
-    public int hashCode() {
-        int result = defaultDictionary != null ? defaultDictionary.hashCode() : 0;
-        result = 31 * result + (customDictionary != null ? customDictionary.hashCode() : 0);
-        return result;
-    }
-
-    @Override
-    public String toString() {
-        return "SpellingValidator{" +
-                "defaultDictionary=" + defaultDictionary +
-                ", customDictionary=" + customDictionary +
-                '}';
-    }
 }
diff --git a/redpen-core/src/main/java/cc/redpen/validator/sentence/StartWithCapitalLetterValidator.java b/redpen-core/src/main/java/cc/redpen/validator/sentence/StartWithCapitalLetterValidator.java
index 2f9fca04..75450536 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/sentence/StartWithCapitalLetterValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/sentence/StartWithCapitalLetterValidator.java
@@ -17,28 +17,26 @@
  */
 package cc.redpen.validator.sentence;
 
-import cc.redpen.RedPenException;
 import cc.redpen.model.Sentence;
 import cc.redpen.tokenizer.TokenElement;
-import cc.redpen.validator.Validator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import cc.redpen.validator.DictionaryValidator;
 
-import java.util.*;
+import java.util.List;
+import java.util.Locale;
+
+import static java.util.Collections.singletonList;
 
 /**
  * Check if the input sentence start with a capital letter.
  */
-final public class StartWithCapitalLetterValidator extends Validator {
-    private static final String DEFAULT_RESOURCE_PATH = "default-resources/capital-letter-exception-list";
-    private static final Logger LOG =
-            LoggerFactory.getLogger(SpellingValidator.class);
-    private Set<String> whiteList;
-    private Set<String> customWhiteList = new HashSet<>();
+final public class StartWithCapitalLetterValidator extends DictionaryValidator {
+    public StartWithCapitalLetterValidator() {
+        super("capital-letter-exception-list/capital-case-exception-list");
+    }
 
     @Override
     public List<String> getSupportedLanguages() {
-        return Arrays.asList(Locale.ENGLISH.getLanguage());
+        return singletonList(Locale.ENGLISH.getLanguage());
     }
 
     @Override
@@ -53,7 +51,7 @@ final public class StartWithCapitalLetterValidator extends Validator {
             }
         }
 
-        if (tokens.size() == 0 || this.whiteList.contains(headWord) || this.customWhiteList.contains(headWord)) {
+        if (tokens.size() == 0 || inDictionary(headWord)) {
             return;
         }
 
@@ -73,42 +71,4 @@ final public class StartWithCapitalLetterValidator extends Validator {
             addLocalizedError(sentence, headChar);
         }
     }
-
-    @Override
-    protected void init() throws RedPenException {
-        String defaultDictionaryFile = DEFAULT_RESOURCE_PATH + "/default-capital-case-exception-list.dat";
-        whiteList = WORD_LIST.loadCachedFromResource(defaultDictionaryFile, "capital letter exception dictionary");
-
-        Optional<String> confFile = getConfigAttribute("dict");
-        if (confFile.isPresent()) {
-            customWhiteList = WORD_LIST.loadCachedFromFile(findFile(confFile.get()), "StartWithCapitalLetterValidator user dictionary");
-        }
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        StartWithCapitalLetterValidator that = (StartWithCapitalLetterValidator) o;
-
-        if (whiteList != null ? !whiteList.equals(that.whiteList) : that.whiteList != null) return false;
-        return !(customWhiteList != null ? !customWhiteList.equals(that.customWhiteList) : that.customWhiteList != null);
-
-    }
-
-    @Override
-    public int hashCode() {
-        int result = whiteList != null ? whiteList.hashCode() : 0;
-        result = 31 * result + (customWhiteList != null ? customWhiteList.hashCode() : 0);
-        return result;
-    }
-
-    @Override
-    public String toString() {
-        return "StartWithCapitalLetterValidator{" +
-                "whiteList=" + whiteList +
-                ", customWhiteList=" + customWhiteList +
-                '}';
-    }
 }
diff --git a/redpen-core/src/main/java/cc/redpen/validator/sentence/SuggestExpressionValidator.java b/redpen-core/src/main/java/cc/redpen/validator/sentence/SuggestExpressionValidator.java
index 874fd534..0967c5ce 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/sentence/SuggestExpressionValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/sentence/SuggestExpressionValidator.java
@@ -25,16 +25,21 @@ import org.slf4j.LoggerFactory;
 
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Optional;
+
+import static org.apache.commons.lang3.StringUtils.isNotEmpty;
 
 /**
  * If input sentences contain invalid expressions, this validator
  * returns the errors with corrected expressions.
  */
-final public class SuggestExpressionValidator extends Validator {
+public final class SuggestExpressionValidator extends Validator {
     private static final Logger LOG = LoggerFactory.getLogger(SuggestExpressionValidator.class);
     private Map<String, String> synonyms = new HashMap<>();
 
+    public SuggestExpressionValidator() {
+        super("dict", "");
+    }
+
     @Override
     public void validate(Sentence sentence) {
         synonyms.keySet().stream().forEach(value -> {
@@ -49,10 +54,10 @@ final public class SuggestExpressionValidator extends Validator {
     @Override
     protected void init() throws RedPenException {
         //TODO: support default dictionary.
-        Optional<String> confFile = getConfigAttribute("dict");
-        if (confFile.isPresent()) {
+        String confFile = getString("dict");
+        if (isNotEmpty(confFile)) {
             LOG.info("Dictionary file is " + confFile);
-            synonyms = KEY_VALUE.loadCachedFromFile(findFile(confFile.get()), "SuggestExpressionValidator dictionary");
+            synonyms = KEY_VALUE.loadCachedFromFile(findFile(confFile), "SuggestExpressionValidator dictionary");
         }
         else {
             LOG.warn("Dictionary file is not specified");
@@ -62,27 +67,4 @@ final public class SuggestExpressionValidator extends Validator {
     protected void setSynonyms(Map<String, String> synonymMap) {
         this.synonyms = synonymMap;
     }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        SuggestExpressionValidator that = (SuggestExpressionValidator) o;
-
-        return !(synonyms != null ? !synonyms.equals(that.synonyms) : that.synonyms != null);
-
-    }
-
-    @Override
-    public int hashCode() {
-        return synonyms != null ? synonyms.hashCode() : 0;
-    }
-
-    @Override
-    public String toString() {
-        return "SuggestExpressionValidator{" +
-                "synonyms=" + synonyms +
-                '}';
-    }
 }
diff --git a/redpen-core/src/main/java/cc/redpen/validator/sentence/WordNumberValidator.java b/redpen-core/src/main/java/cc/redpen/validator/sentence/WordNumberValidator.java
index f1d02894..f798a99d 100644
--- a/redpen-core/src/main/java/cc/redpen/validator/sentence/WordNumberValidator.java
+++ b/redpen-core/src/main/java/cc/redpen/validator/sentence/WordNumberValidator.java
@@ -17,57 +17,23 @@
  */
 package cc.redpen.validator.sentence;
 
-import cc.redpen.RedPenException;
 import cc.redpen.model.Sentence;
 import cc.redpen.validator.Validator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * Validate input sentences have more words than specified.
  */
 final public class WordNumberValidator extends Validator {
-    /**
-     * Default maximum number of words in one sentence.
-     */
-    @SuppressWarnings("WeakerAccess")
-    public static final int DEFAULT_MAXIMUM_WORDS_IN_A_SENTENCE = 30;
-    private static final Logger LOG =
-            LoggerFactory.getLogger(WordNumberValidator.class);
-    private int maxWordNumber = DEFAULT_MAXIMUM_WORDS_IN_A_SENTENCE;
+    public WordNumberValidator() {
+        super("max_num", 30); // Default maximum number of words in one sentence.
+    }
 
     @Override
     public void validate(Sentence sentence) {
         int wordNum = sentence.getTokens().size();
-        if (wordNum > maxWordNumber) {
-            addLocalizedError(sentence, wordNum, maxWordNumber);
+        int maxNum = getInt("max_num");
+        if (wordNum > maxNum) {
+            addLocalizedError(sentence, wordNum, maxNum);
         }
     }
-
-    @Override
-    protected void init() throws RedPenException {
-        this.maxWordNumber = getConfigAttributeAsInt("max_num", DEFAULT_MAXIMUM_WORDS_IN_A_SENTENCE);
-    }
-
-    @Override
-    public String toString() {
-        return "WordNumberValidator{" +
-                "maxWordNumber=" + maxWordNumber +
-                '}';
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        WordNumberValidator that = (WordNumberValidator) o;
-
-        return maxWordNumber == that.maxWordNumber;
-    }
-
-    @Override
-    public int hashCode() {
-        return maxWordNumber;
-    }
 }
diff --git a/redpen-core/src/main/resources/default-resources/capital-letter-exception-list/default-capital-case-exception-list.dat b/redpen-core/src/main/resources/default-resources/capital-letter-exception-list/capital-case-exception-list-en.dat
similarity index 70%
rename from redpen-core/src/main/resources/default-resources/capital-letter-exception-list/default-capital-case-exception-list.dat
rename to redpen-core/src/main/resources/default-resources/capital-letter-exception-list/capital-case-exception-list-en.dat
index bc0c4107..8e5d1c23 100644
--- a/redpen-core/src/main/resources/default-resources/capital-letter-exception-list/default-capital-case-exception-list.dat
+++ b/redpen-core/src/main/resources/default-resources/capital-letter-exception-list/capital-case-exception-list-en.dat
@@ -1,4 +1,4 @@
 iPhone
 mixi
 mRNA
-iTune
+iTunes
diff --git a/redpen-distribution/pom.xml b/redpen-distribution/pom.xml
index 2c851806..5c5b5236 100644
--- a/redpen-distribution/pom.xml
+++ b/redpen-distribution/pom.xml
@@ -3,7 +3,7 @@
     <parent>
         <artifactId>redpen</artifactId>
         <groupId>cc.redpen</groupId>
-        <version>1.4.8-SNAPSHOT</version>
+        <version>1.5.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/redpen-plugin/pom.xml b/redpen-plugin/pom.xml
index 9eec8fc1..0c5afe55 100644
--- a/redpen-plugin/pom.xml
+++ b/redpen-plugin/pom.xml
@@ -3,7 +3,7 @@
     <parent>
         <artifactId>redpen</artifactId>
         <groupId>cc.redpen</groupId>
-        <version>1.4.8-SNAPSHOT</version>
+        <version>1.5.0-SNAPSHOT</version>
     </parent>
     <packaging>jar</packaging>
     <modelVersion>4.0.0</modelVersion>
@@ -57,7 +57,7 @@
         <dependency>
             <groupId>cc.redpen</groupId>
             <artifactId>redpen-core</artifactId>
-            <version>1.4.8-SNAPSHOT</version>
+            <version>1.5.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>junit</groupId>
diff --git a/redpen-server/pom.xml b/redpen-server/pom.xml
index e55406da..8406a8ed 100644
--- a/redpen-server/pom.xml
+++ b/redpen-server/pom.xml
@@ -3,7 +3,7 @@
     <parent>
         <artifactId>redpen</artifactId>
         <groupId>cc.redpen</groupId>
-        <version>1.4.8-SNAPSHOT</version>
+        <version>1.5.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -165,7 +165,7 @@
         <dependency>
             <groupId>cc.redpen</groupId>
             <artifactId>redpen-core</artifactId>
-            <version>1.4.8-SNAPSHOT</version>
+            <version>1.5.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.wink</groupId>
diff --git a/redpen-server/src/main/java/cc/redpen/server/api/RedPenService.java b/redpen-server/src/main/java/cc/redpen/server/api/RedPenService.java
index 84b1dd49..078f4694 100644
--- a/redpen-server/src/main/java/cc/redpen/server/api/RedPenService.java
+++ b/redpen-server/src/main/java/cc/redpen/server/api/RedPenService.java
@@ -25,30 +25,19 @@ import cc.redpen.config.ConfigurationLoader;
 import cc.redpen.config.ValidatorConfiguration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.core.io.Resource;
-import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
 
 import javax.servlet.ServletContext;
-import java.io.IOException;
-import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.Map;
-import java.util.Set;
-import java.util.stream.Stream;
-
-import static java.util.Collections.emptySet;
-import static java.util.stream.Collectors.toSet;
 
 /**
  * Helper class to access RedPen instances for use within the webapp
  */
 public class RedPenService {
-
     private static final Logger LOG = LoggerFactory.getLogger(RedPenService.class);
 
-    private final static String DEFAULT_INTERNAL_CONFIG_PATH = "/conf/redpen-conf.xml";
     private final static String DEFAULT_LANGUAGE = "default";
-
-    static Map<String, RedPen> langRedPenMap = new HashMap<>();
+    static final Map<String, RedPen> redPens = new LinkedHashMap<>();
 
     /**
      * Create redpens for the given context
@@ -56,25 +45,23 @@ public class RedPenService {
      * @param context the servlet context
      */
     public RedPenService(ServletContext context) {
-        synchronized (this) {
-            if (langRedPenMap.size() == 0) {
+        synchronized (redPens) {
+            if (redPens.isEmpty()) {
                 LOG.info("Creating RedPen instances");
                 try {
-                    for (String fileName : findConfFiles()) {
-                        Configuration config = new ConfigurationLoader().secure().loadFromResource(fileName);
-                        RedPen redPen = new RedPen(config);
-                        langRedPenMap.put(config.getKey(), redPen);
+                    for (String key : Configuration.getDefaultConfigKeys()) {
+                        redPens.put(key, new RedPen(Configuration.builder(key).secure().addAvailableValidatorConfigs().build()));
                     }
 
                     String configPath = context != null ? context.getInitParameter("redpen.conf.path") : null;
                     if (configPath != null) {
                         LOG.info("Config Path is set to \"{}\"", configPath);
                         RedPen defaultRedPen = new RedPen(new ConfigurationLoader().secure().loadFromResource(configPath));
-                        langRedPenMap.put(DEFAULT_LANGUAGE, defaultRedPen);
+                        redPens.put(DEFAULT_LANGUAGE, defaultRedPen);
                     } else {
                         // if config path is not set, fallback to default config path
-                        LOG.info("Config Path is set to \"{}\"", DEFAULT_INTERNAL_CONFIG_PATH);
-                        langRedPenMap.put(DEFAULT_LANGUAGE, langRedPenMap.get("en"));
+                        LOG.info("No Config Path set, using default configurations");
+                        redPens.put(DEFAULT_LANGUAGE, redPens.get("en"));
                     }
                     LOG.info("Document Validator Server is running.");
                 } catch (RedPenException e) {
@@ -85,19 +72,8 @@ public class RedPenService {
         }
     }
 
-    private Set<String> findConfFiles() {
-        try {
-            Resource[] resources = new PathMatchingResourcePatternResolver(getClass().getClassLoader()).getResources("classpath*:conf/*.xml");
-            return Stream.of(resources).map(r -> "/conf/" + r.getFilename()).collect(toSet());
-        }
-        catch (IOException e) {
-            LOG.error("Failed to load default config files", e);
-            return emptySet();
-        }
-    }
-
     public RedPen getRedPen(String lang) {
-        return langRedPenMap.getOrDefault(lang, langRedPenMap.get(DEFAULT_LANGUAGE));
+        return redPens.getOrDefault(lang, redPens.get(DEFAULT_LANGUAGE));
     }
 
     /**
@@ -114,9 +90,7 @@ public class RedPenService {
         // add the validators and their properties
         validatorProperties.forEach((validatorName, props) -> {
             ValidatorConfiguration validatorConfig = new ValidatorConfiguration(validatorName);
-            props.forEach((name, value) -> {
-                validatorConfig.addAttribute(name, value);
-            });
+            props.forEach(validatorConfig::addProperty);
             configBuilder.addValidatorConfig(validatorConfig);
         });
         try {
@@ -133,6 +107,6 @@ public class RedPenService {
      * @return map of available RedPens
      */
     public Map<String, RedPen> getRedPens() {
-        return langRedPenMap;
+        return redPens;
     }
 }
diff --git a/redpen-server/src/main/resources/conf/redpen-conf-ja-hankaku.xml b/redpen-server/src/main/resources/conf/redpen-conf-ja-hankaku.xml
deleted file mode 100644
index 561307eb..00000000
--- a/redpen-server/src/main/resources/conf/redpen-conf-ja-hankaku.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<redpen-conf lang="ja" variant="hankaku">
-    <validators>
-        <validator name="SentenceLength">
-            <property name="max_len" value="100"/>
-        </validator>
-        <validator name="InvalidSymbol"/>
-        <validator name="KatakanaEndHyphen"/>
-        <validator name="KatakanaSpellCheck"/>
-        <validator name="SectionLength">
-            <property name="max_num" value="1500"/>
-        </validator>
-        <validator name="ParagraphNumber"/>
-        <validator name="DoubledWord" />
-        <validator name="SpaceBetweenAlphabeticalWord" />
-        <validator name="CommaNumber" />
-        <validator name="SuccessiveWord" />
-        <validator name="HankakuKana" />
-    </validators>
-</redpen-conf>
diff --git a/redpen-server/src/main/resources/conf/redpen-conf-ja-zenkaku2.xml b/redpen-server/src/main/resources/conf/redpen-conf-ja-zenkaku2.xml
deleted file mode 100644
index eb3f7628..00000000
--- a/redpen-server/src/main/resources/conf/redpen-conf-ja-zenkaku2.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<redpen-conf lang="ja" variant="zenkaku2">
-    <validators>
-        <validator name="SentenceLength">
-            <property name="max_len" value="100"/>
-        </validator>
-        <validator name="InvalidSymbol"/>
-        <validator name="KatakanaEndHyphen"/>
-        <validator name="KatakanaSpellCheck"/>
-        <validator name="SectionLength">
-            <property name="max_num" value="1500"/>
-        </validator>
-        <validator name="ParagraphNumber"/>
-        <validator name="DoubledWord" />
-        <validator name="SpaceBetweenAlphabeticalWord" />
-        <validator name="CommaNumber" />
-        <validator name="SuccessiveWord" />
-        <validator name="HankakuKana" />
-    </validators>
-</redpen-conf>
diff --git a/redpen-server/src/main/resources/conf/redpen-conf-ja.xml b/redpen-server/src/main/resources/conf/redpen-conf-ja.xml
deleted file mode 100644
index 7766f867..00000000
--- a/redpen-server/src/main/resources/conf/redpen-conf-ja.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<redpen-conf lang="ja">
-    <validators>
-        <validator name="SentenceLength">
-            <property name="max_len" value="100"/>
-        </validator>
-        <validator name="InvalidSymbol"/>
-        <validator name="KatakanaEndHyphen"/>
-        <validator name="KatakanaSpellCheck"/>
-        <validator name="SectionLength">
-            <property name="max_num" value="1500"/>
-        </validator>
-        <validator name="ParagraphNumber"/>
-        <validator name="DoubledWord" />
-        <validator name="SpaceBetweenAlphabeticalWord" />
-        <validator name="CommaNumber" />
-        <validator name="SuccessiveWord" />
-        <validator name="HankakuKana" />
-    </validators>
-</redpen-conf>
diff --git a/redpen-server/src/main/resources/conf/redpen-conf.xml b/redpen-server/src/main/resources/conf/redpen-conf.xml
deleted file mode 100644
index 2f248c88..00000000
--- a/redpen-server/src/main/resources/conf/redpen-conf.xml
+++ /dev/null
@@ -1,61 +0,0 @@
-<!--
-  ~ redpen: a text inspection tool
-  ~ Copyright (C) 2014 Recruit Technologies Co., Ltd. and contributors
-  ~ (see CONTRIBUTORS.md)
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~ http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<redpen-conf lang="en">
-    <validators>
-        <validator name="SentenceLength">
-            <property name="max_len" value="200"/>
-        </validator>
-        <validator name="InvalidSymbol"/>
-        <validator name="SymbolWithSpace"/>
-        <validator name="SectionLength">
-            <property name="max_char_num" value="2000"/>
-        </validator>
-        <validator name="ParagraphNumber"/>
-        <validator name="Spelling"/>
-        <validator name="Contraction"/>
-        <validator name="DoubledWord"/>
-        <validator name="SuccessiveWord"/>
-
-        <validator name="CommaNumber"/>
-        <validator name="EndOfSentence"/>
-        <validator name="InvalidExpression"/>
-        <validator name="InvalidWord"/>
-
-        <validator name="Quotation"/>
-        <validator name="SpaceBetweenAlphabeticalWord"/>
-        <validator name="StartWithCapitalLetter"/>
-        <validator name="WordNumber"/>
-
-        <validator name="FrequentSentenceStart"/>
-        <validator name="UnexpandedAcronym"/>
-        <validator name="WordFrequency"/>
-        <validator name="Hyphenation"/>
-        <validator name="NumberFormat"/>
-        <validator name="ParenthesizedSentence"/>
-        <validator name="WeakExpression"/>
-
-        <!--<validator name="SpaceBeginningOfSentence"/>-->
-        <!--<validator name="ParagraphStartWith"/>-->
-        <!--<validator name="DuplicatedSection"/>-->
-        <!--<validator name="SuggestExpression">-->
-            <!--<property name="dict" value="location_of_dictionary"/>-->
-        <!--</validator>-->
-
-    </validators>
-</redpen-conf>
diff --git a/redpen-server/src/main/webapp/WEB-INF/web.xml b/redpen-server/src/main/webapp/WEB-INF/web.xml
index b47d9297..ec16c155 100644
--- a/redpen-server/src/main/webapp/WEB-INF/web.xml
+++ b/redpen-server/src/main/webapp/WEB-INF/web.xml
@@ -5,11 +5,6 @@
     <display-name>RedPen Server</display-name>
     <description>RedPen Server</description>
 
-    <context-param>
-        <param-name>redpen.conf.path</param-name>
-        <param-value>/conf/redpen-conf.xml</param-value>
-    </context-param>
-
     <!-- Wink SDK servlet configuration. This servlet handles HTTP requests of
     SDK web service on application server. -->
     <servlet>


Test patch:
diff --git a/redpen-core/src/test/java/cc/redpen/RedPenTest.java b/redpen-core/src/test/java/cc/redpen/RedPenTest.java
index e33b59ec..223c3603 100644
--- a/redpen-core/src/test/java/cc/redpen/RedPenTest.java
+++ b/redpen-core/src/test/java/cc/redpen/RedPenTest.java
@@ -184,7 +184,7 @@ public class RedPenTest {
             RedPenException {
 
         Configuration configuration = Configuration.builder()
-                .addValidatorConfig(new ValidatorConfiguration("SentenceLength").addAttribute("max_len", "5"))
+                .addValidatorConfig(new ValidatorConfiguration("SentenceLength").addProperty("max_len", "5"))
                 .build();
         return new RedPen(configuration);
     }
@@ -192,7 +192,7 @@ public class RedPenTest {
     private RedPen getRedPenWithSectionValidator() throws
             RedPenException {
         Configuration configuration = Configuration.builder()
-                .addValidatorConfig(new ValidatorConfiguration("SectionLength").addAttribute("max_num", "5"))
+                .addValidatorConfig(new ValidatorConfiguration("SectionLength").addProperty("max_num", "5"))
                 .build();
         return new RedPen(configuration);
     }
diff --git a/redpen-core/src/test/java/cc/redpen/config/ConfigurationExporterTest.java b/redpen-core/src/test/java/cc/redpen/config/ConfigurationExporterTest.java
index 7c561d2e..ac793627 100644
--- a/redpen-core/src/test/java/cc/redpen/config/ConfigurationExporterTest.java
+++ b/redpen-core/src/test/java/cc/redpen/config/ConfigurationExporterTest.java
@@ -36,7 +36,7 @@ public class ConfigurationExporterTest {
   public void validators() throws Exception {
     Configuration config = Configuration.builder()
       .addValidatorConfig(new ValidatorConfiguration("Mega"))
-      .addValidatorConfig(new ValidatorConfiguration("Super").addAttribute("hello", "world")).build();
+      .addValidatorConfig(new ValidatorConfiguration("Super").addProperty("hello", "world")).build();
     exporter.export(config, out);
     assertEquals(
       "<redpen-conf lang=\"en\">\n" +
diff --git a/redpen-core/src/test/java/cc/redpen/config/ConfigurationLoaderTest.java b/redpen-core/src/test/java/cc/redpen/config/ConfigurationLoaderTest.java
index 7b1c4f50..d10697e2 100644
--- a/redpen-core/src/test/java/cc/redpen/config/ConfigurationLoaderTest.java
+++ b/redpen-core/src/test/java/cc/redpen/config/ConfigurationLoaderTest.java
@@ -60,7 +60,7 @@ public class ConfigurationLoaderTest {
         assertEquals("SentenceLength",
                 configuration.getValidatorConfigs().get(0).getConfigurationName());
         assertEquals("200",
-                configuration.getValidatorConfigs().get(0).getAttribute("max_length"));
+                configuration.getValidatorConfigs().get(0).getProperty("max_length"));
         assertEquals("MaxParagraphNumber",
                 configuration.getValidatorConfigs().get(1).getConfigurationName());
         assertNotNull(configuration.getSymbolTable());
@@ -92,7 +92,7 @@ public class ConfigurationLoaderTest {
         assertEquals("SentenceLength",
                 configuration.getValidatorConfigs().get(0).getConfigurationName());
         assertEquals("200",
-                configuration.getValidatorConfigs().get(0).getAttribute("max_length"));
+                configuration.getValidatorConfigs().get(0).getProperty("max_length"));
         assertEquals("MaxParagraphNumber",
                 configuration.getValidatorConfigs().get(1).getConfigurationName());
         assertNotNull(configuration.getSymbolTable());
@@ -133,7 +133,7 @@ public class ConfigurationLoaderTest {
         assertEquals("SentenceLength",
                 configuration.getValidatorConfigs().get(0).getConfigurationName());
         assertEquals("200",
-                configuration.getValidatorConfigs().get(0).getAttribute("max_length"));
+                configuration.getValidatorConfigs().get(0).getProperty("max_length"));
         assertEquals("MaxParagraphNumber",
                 configuration.getValidatorConfigs().get(1).getConfigurationName());
         assertNotNull(configuration.getSymbolTable());
diff --git a/redpen-core/src/test/java/cc/redpen/config/ConfigurationRedPenBuilderTest.java b/redpen-core/src/test/java/cc/redpen/config/ConfigurationRedPenBuilderTest.java
index bf72e5a0..643b4f65 100644
--- a/redpen-core/src/test/java/cc/redpen/config/ConfigurationRedPenBuilderTest.java
+++ b/redpen-core/src/test/java/cc/redpen/config/ConfigurationRedPenBuilderTest.java
@@ -59,20 +59,20 @@ public class ConfigurationRedPenBuilderTest {
     public void testBuildConfigurationAddingProperties() {
         Configuration config = Configuration.builder()
                 .addValidatorConfig(new ValidatorConfiguration("InvalidExpression")
-                        .addAttribute("dict", "./foobar.dict"))
+                        .addProperty("dict", "./foobar.dict"))
                 .addValidatorConfig(new ValidatorConfiguration("SentenceLength")
-                        .addAttribute("max_length", "10")).build();
+                        .addProperty("max_length", "10")).build();
 
         assertEquals(2, config.getValidatorConfigs().size());
         assertNotNull(config.getSymbolTable());
         assertEquals("InvalidExpression", config.getValidatorConfigs()
                 .get(0).getConfigurationName());
         assertEquals("./foobar.dict",
-                config.getValidatorConfigs().get(0).getAttribute("dict"));
+                config.getValidatorConfigs().get(0).getProperty("dict"));
         assertEquals("SentenceLength", config.getValidatorConfigs()
                 .get(1).getConfigurationName());
         assertEquals("10",
-                config.getValidatorConfigs().get(1).getAttribute("max_length"));
+                config.getValidatorConfigs().get(1).getProperty("max_length"));
     }
 
     @Test
diff --git a/redpen-core/src/test/java/cc/redpen/config/ConfigurationTest.java b/redpen-core/src/test/java/cc/redpen/config/ConfigurationTest.java
index bcff86a0..81947c4d 100644
--- a/redpen-core/src/test/java/cc/redpen/config/ConfigurationTest.java
+++ b/redpen-core/src/test/java/cc/redpen/config/ConfigurationTest.java
@@ -226,11 +226,18 @@ public class ConfigurationTest {
     @Test
     public void addAvailableValidatorsForLanguage() throws Exception {
         Configuration ja = Configuration.builder("ja").addAvailableValidatorConfigs().build();
-        assertTrue(ja.getValidatorConfigs().contains(new ValidatorConfiguration("SentenceLength")));
-        assertTrue(ja.getValidatorConfigs().contains(new ValidatorConfiguration("HankakuKana")));
+        assertTrue(ja.getValidatorConfigs().stream().anyMatch(v -> v.getConfigurationName().equals("SentenceLength")));
+        assertTrue(ja.getValidatorConfigs().stream().anyMatch(v -> v.getConfigurationName().equals("HankakuKana")));
 
         Configuration en = Configuration.builder("en").addAvailableValidatorConfigs().build();
-        assertTrue(en.getValidatorConfigs().contains(new ValidatorConfiguration("SentenceLength")));
-        assertFalse(en.getValidatorConfigs().contains(new ValidatorConfiguration("HankakuKana")));
+        assertTrue(en.getValidatorConfigs().stream().anyMatch(v -> v.getConfigurationName().equals("SentenceLength")));
+        assertFalse(en.getValidatorConfigs().stream().anyMatch(v -> v.getConfigurationName().equals("HankakuKana")));
+
+        ValidatorConfiguration sentenceLength = en.getValidatorConfigs().stream().filter(v -> v.getConfigurationName().equals("SentenceLength")).findAny().get();
+        assertEquals("120", sentenceLength.getProperty("max_len"));
+
+        ValidatorConfiguration spelling = en.getValidatorConfigs().stream().filter(v -> v.getConfigurationName().equals("Spelling")).findAny().get();
+        assertEquals("", spelling.getProperty("list"));
+        assertEquals("", spelling.getProperty("dict"));
     }
 }
diff --git a/redpen-core/src/test/java/cc/redpen/config/ValidatorConfigurationTest.java b/redpen-core/src/test/java/cc/redpen/config/ValidatorConfigurationTest.java
index 729e2669..22da95e5 100644
--- a/redpen-core/src/test/java/cc/redpen/config/ValidatorConfigurationTest.java
+++ b/redpen-core/src/test/java/cc/redpen/config/ValidatorConfigurationTest.java
@@ -8,27 +8,27 @@ public class ValidatorConfigurationTest {
 
   @Test
   public void canBeCloned() throws Exception {
-    ValidatorConfiguration conf = new ValidatorConfiguration("test").addAttribute("foo", "bar");
+    ValidatorConfiguration conf = new ValidatorConfiguration("test").addProperty("foo", "bar");
     ValidatorConfiguration clone = conf.clone();
 
     assertNotSame(conf, clone);
     assertEquals(conf, clone);
 
-    assertNotSame(conf.getAttributes(), clone.getAttributes());
-    assertEquals(conf.getAttributes(), clone.getAttributes());
+    assertNotSame(conf.getProperties(), clone.getProperties());
+    assertEquals(conf.getProperties(), clone.getProperties());
   }
 
   @Test
   public void equals() throws Exception {
-    ValidatorConfiguration conf = new ValidatorConfiguration("test").addAttribute("foo", "bar");
-    ValidatorConfiguration conf2 = new ValidatorConfiguration("test").addAttribute("foo", "bar");
+    ValidatorConfiguration conf = new ValidatorConfiguration("test").addProperty("foo", "bar");
+    ValidatorConfiguration conf2 = new ValidatorConfiguration("test").addProperty("foo", "bar");
     assertEquals(conf, conf2);
   }
 
   @Test
-  public void equals_attributes() throws Exception {
-    ValidatorConfiguration conf = new ValidatorConfiguration("test").addAttribute("foo", "bar");
-    ValidatorConfiguration conf2 = new ValidatorConfiguration("test").addAttribute("foo", "bar2");
+  public void equals_properties() throws Exception {
+    ValidatorConfiguration conf = new ValidatorConfiguration("test").addProperty("foo", "bar");
+    ValidatorConfiguration conf2 = new ValidatorConfiguration("test").addProperty("foo", "bar2");
     assertFalse(conf.equals(conf2));
   }
 
diff --git a/redpen-core/src/test/java/cc/redpen/validator/JavaScriptValidatorTest.java b/redpen-core/src/test/java/cc/redpen/validator/JavaScriptValidatorTest.java
index a4e130c7..38d33278 100644
--- a/redpen-core/src/test/java/cc/redpen/validator/JavaScriptValidatorTest.java
+++ b/redpen-core/src/test/java/cc/redpen/validator/JavaScriptValidatorTest.java
@@ -77,7 +77,7 @@ public class JavaScriptValidatorTest extends JavaScriptValidator {
         validatorJS.deleteOnExit();
 
         Configuration config = Configuration.builder()
-                .addValidatorConfig(new ValidatorConfiguration("JavaScript").addAttribute("script-path", javaScriptValidatorsDir.getAbsolutePath()))
+                .addValidatorConfig(new ValidatorConfiguration("JavaScript").addProperty("script-path", javaScriptValidatorsDir.getAbsolutePath()))
                 .build();
 
         Document document = Document.builder()
@@ -198,8 +198,4 @@ public class JavaScriptValidatorTest extends JavaScriptValidator {
     }
 
     ArrayList<ValidationError> errors = new ArrayList<>();
-
-    public void markCalled(String msg) {
-        calledFunctions.add(msg);
-    }
 }
diff --git a/redpen-core/src/test/java/cc/redpen/validator/ValidationErrorMessageTest.java b/redpen-core/src/test/java/cc/redpen/validator/ValidationErrorMessageTest.java
index ebaac5bc..5ae6b361 100644
--- a/redpen-core/src/test/java/cc/redpen/validator/ValidationErrorMessageTest.java
+++ b/redpen-core/src/test/java/cc/redpen/validator/ValidationErrorMessageTest.java
@@ -21,6 +21,13 @@ import cc.redpen.model.Sentence;
 
 class ValidationErrorMessageTest extends Validator {
 
+    public ValidationErrorMessageTest() {
+    }
+
+    public ValidationErrorMessageTest(Object...defaultAttributes) {
+        super(defaultAttributes);
+    }
+
     @Override
     public void validate(Sentence sentence) {
         addLocalizedError(sentence, 1, 2, 3, "sentence");
diff --git a/redpen-core/src/test/java/cc/redpen/validator/ValidatorFactoryTest.java b/redpen-core/src/test/java/cc/redpen/validator/ValidatorFactoryTest.java
index 7d36d8d5..d3c158e6 100644
--- a/redpen-core/src/test/java/cc/redpen/validator/ValidatorFactoryTest.java
+++ b/redpen-core/src/test/java/cc/redpen/validator/ValidatorFactoryTest.java
@@ -25,7 +25,10 @@ import org.junit.Test;
 
 import java.io.File;
 import java.lang.reflect.Modifier;
+import java.util.HashMap;
+import java.util.Map;
 
+import static java.util.Arrays.asList;
 import static org.junit.Assert.*;
 
 class CustomValidator extends Validator {
@@ -70,6 +73,22 @@ public class ValidatorFactoryTest {
         checkValidators(validatorsPackage, validators);
     }
 
+    @Test
+    public void mapToStrings() throws Exception {
+        Map<String, Object> properties = new HashMap<>();
+        properties.put("string", "bar");
+        properties.put("integer", 100);
+        properties.put("boolean", false);
+        properties.put("collection", asList("foo", "bar"));
+
+        Map<String, String> result = ValidatorFactory.toStrings(properties);
+
+        assertEquals("bar", result.get("string"));
+        assertEquals("100", result.get("integer"));
+        assertEquals("false", result.get("boolean"));
+        assertEquals("foo,bar", result.get("collection"));
+    }
+
     @SuppressWarnings("ConstantConditions")
     private void checkValidators(String validatorsPackage, File validators) throws ClassNotFoundException {
         for (File file : validators.listFiles()) {
diff --git a/redpen-core/src/test/java/cc/redpen/validator/ValidatorTest.java b/redpen-core/src/test/java/cc/redpen/validator/ValidatorTest.java
index bf2eb7be..5e351690 100644
--- a/redpen-core/src/test/java/cc/redpen/validator/ValidatorTest.java
+++ b/redpen-core/src/test/java/cc/redpen/validator/ValidatorTest.java
@@ -18,27 +18,32 @@
 package cc.redpen.validator;
 
 import cc.redpen.RedPenException;
+import cc.redpen.config.Configuration;
+import cc.redpen.config.ValidatorConfiguration;
 import cc.redpen.model.Sentence;
 import cc.redpen.tokenizer.TokenElement;
 import org.junit.Test;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 import java.util.Locale;
 
+import static java.util.Collections.singletonList;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 
 public class ValidatorTest {
+    private final Configuration globalConfig = Configuration.builder().build();
+
     @Test
-    public void testValidationErrorCreation() throws RedPenException {
+    public void validationErrorCreation() throws RedPenException {
         ValidationErrorMessageTest validationErrorMessageTest = new ValidationErrorMessageTest();
-        validationErrorMessageTest.preInit(null, null);
+        validationErrorMessageTest.preInit(new ValidatorConfiguration("blah"), Configuration.builder().build());
         validationErrorMessageTest.setLocale(Locale.ENGLISH);
         List<ValidationError> validationErrors = new ArrayList<>();
         validationErrorMessageTest.setErrorList(validationErrors);
         Sentence sentence = new Sentence("sentence", 1);
-        sentence.setTokens(Arrays.asList(new TokenElement("word", Arrays.asList(""), 0)));
+        sentence.setTokens(singletonList(new TokenElement("word", singletonList(""), 0)));
         validationErrorMessageTest.validate(sentence);
         assertEquals("error str:sentence 1:1 2:2 3:3", validationErrors.get(0).getMessage());
         assertEquals("with Key :sentence", validationErrors.get(1).getMessage());
@@ -49,7 +54,37 @@ public class ValidatorTest {
         validationErrorMessageTest.validate(sentence);
         assertEquals("エラー ストリング:sentence 1:1 2:2 3:3", validationErrors.get(0).getMessage());
         assertEquals("キー指定 :sentence", validationErrors.get(1).getMessage());
+    }
+
+    @Test
+    public void configOverridesDefaultAttributes() throws Exception {
+        Validator validator = new Validator("hello", 123) {};
+        assertEquals(123, validator.getInt("hello"));
+
+        validator.preInit(new ValidatorConfiguration("blah").addProperty("hello", "234"), globalConfig);
+        assertEquals(234, validator.getInt("hello"));
+    }
 
+    @Test
+    public void equalsAndHashCode() throws Exception {
+        Validator validator = new ValidationErrorMessageTest();
+        Validator validator2 = new ValidationErrorMessageTest();
+        assertEquals(validator, validator2);
+        assertEquals(validator.hashCode(), validator2.hashCode());
+
+        validator.preInit(new ValidatorConfiguration("blah"), globalConfig);
+        assertFalse(validator.equals(validator2));
+        assertFalse(validator.hashCode() == validator2.hashCode());
+
+        validator2.preInit(new ValidatorConfiguration("blah"), globalConfig);
+        assertEquals(validator, validator2);
+        assertEquals(validator.hashCode(), validator2.hashCode());
+    }
+
+    @Test
+    public void testToString() throws Exception {
+        assertEquals("ValidationErrorMessageTest{}", new ValidationErrorMessageTest().toString());
+        assertEquals("ValidationErrorMessageTest{hello=123}", new ValidationErrorMessageTest("hello", 123).toString());
     }
 }
 
diff --git a/redpen-core/src/test/java/cc/redpen/validator/section/DuplicatedSectionValidatorTest.java b/redpen-core/src/test/java/cc/redpen/validator/section/DuplicatedSectionValidatorTest.java
index 698a8f41..4e2447c7 100644
--- a/redpen-core/src/test/java/cc/redpen/validator/section/DuplicatedSectionValidatorTest.java
+++ b/redpen-core/src/test/java/cc/redpen/validator/section/DuplicatedSectionValidatorTest.java
@@ -108,7 +108,7 @@ public class DuplicatedSectionValidatorTest {
     @Test
     public void testDetectNonDuplicatedSectionWithLowThreshold() throws RedPenException {
         Configuration config = Configuration.builder()
-                .addValidatorConfig(new ValidatorConfiguration("DuplicatedSection").addAttribute("threshold", "0.0"))
+                .addValidatorConfig(new ValidatorConfiguration("DuplicatedSection").addProperty("threshold", "0.0"))
                 .build();
 
         List<Document> documents = new ArrayList<>();
diff --git a/redpen-core/src/test/java/cc/redpen/validator/section/ParagraphNumberValidatorTest.java b/redpen-core/src/test/java/cc/redpen/validator/section/ParagraphNumberValidatorTest.java
index f75e0563..c4f6df93 100644
--- a/redpen-core/src/test/java/cc/redpen/validator/section/ParagraphNumberValidatorTest.java
+++ b/redpen-core/src/test/java/cc/redpen/validator/section/ParagraphNumberValidatorTest.java
@@ -17,11 +17,13 @@
  */
 package cc.redpen.validator.section;
 
-import cc.redpen.model.Document;
+import cc.redpen.RedPenException;
+import cc.redpen.config.Configuration;
+import cc.redpen.config.ValidatorConfiguration;
 import cc.redpen.model.Paragraph;
 import cc.redpen.model.Section;
 import cc.redpen.validator.ValidationError;
-import org.junit.BeforeClass;
+import org.junit.Before;
 import org.junit.Test;
 
 import java.util.ArrayList;
@@ -30,13 +32,11 @@ import java.util.List;
 import static org.junit.Assert.assertEquals;
 
 public class ParagraphNumberValidatorTest {
+    private ParagraphNumberValidator validator = new ParagraphNumberValidator();
 
-    private static ParagraphNumberValidator validator;
-
-    @BeforeClass
-    public static void setUp() {
-        validator = new ParagraphNumberValidator();
-        validator.setMaxParagraphNumber(3);
+    @Before
+    public void setUp() throws RedPenException {
+        validator.preInit(new ValidatorConfiguration("ParagraphNumber").addProperty("max_num", "3"), Configuration.builder().build());
     }
 
     @Test
@@ -56,16 +56,12 @@ public class ParagraphNumberValidatorTest {
 
     @Test
     public void testSectionWithOnlyOneSection() {
-
         Section section = new Section(0);
         section.appendParagraph(new Paragraph());
 
-        Document document = Document.builder().appendSection(section).build();
-
         List<ValidationError> errors = new ArrayList<>();
         validator.setErrorList(errors);
         validator.validate(section);
         assertEquals(0, errors.size());
     }
-
 }
diff --git a/redpen-core/src/test/java/cc/redpen/validator/section/SectionLengthValidatorTest.java b/redpen-core/src/test/java/cc/redpen/validator/section/SectionLengthValidatorTest.java
index 70bd0343..84ac4f97 100644
--- a/redpen-core/src/test/java/cc/redpen/validator/section/SectionLengthValidatorTest.java
+++ b/redpen-core/src/test/java/cc/redpen/validator/section/SectionLengthValidatorTest.java
@@ -17,10 +17,13 @@
  */
 package cc.redpen.validator.section;
 
+import cc.redpen.RedPenException;
+import cc.redpen.config.Configuration;
+import cc.redpen.config.ValidatorConfiguration;
 import cc.redpen.model.Paragraph;
 import cc.redpen.model.Section;
 import cc.redpen.validator.ValidationError;
-import org.junit.BeforeClass;
+import org.junit.Before;
 import org.junit.Test;
 
 import java.util.ArrayList;
@@ -29,13 +32,12 @@ import java.util.List;
 import static org.junit.Assert.assertEquals;
 
 public class SectionLengthValidatorTest {
+    private SectionLengthValidator validator;
 
-    private static SectionLengthValidator validator;
-
-    @BeforeClass
-    public static void setUp() {
+    @Before
+    public void setUp() throws RedPenException {
         validator = new SectionLengthValidator();
-        validator.setMaxSectionLength(10);
+        validator.preInit(new ValidatorConfiguration("SectionLength").addProperty("max_num", "10"), Configuration.builder().build());
     }
 
     @Test
diff --git a/redpen-core/src/test/java/cc/redpen/validator/section/WordFrequencyValidatorTest.java b/redpen-core/src/test/java/cc/redpen/validator/section/WordFrequencyValidatorTest.java
index e8fdcd48..b0f1fded 100644
--- a/redpen-core/src/test/java/cc/redpen/validator/section/WordFrequencyValidatorTest.java
+++ b/redpen-core/src/test/java/cc/redpen/validator/section/WordFrequencyValidatorTest.java
@@ -18,6 +18,8 @@
 package cc.redpen.validator.section;
 
 import cc.redpen.RedPenException;
+import cc.redpen.config.Configuration;
+import cc.redpen.config.ValidatorConfiguration;
 import cc.redpen.model.Document;
 import cc.redpen.model.Sentence;
 import cc.redpen.tokenizer.WhiteSpaceTokenizer;
@@ -32,31 +34,26 @@ import static org.junit.Assert.assertEquals;
 
 public class WordFrequencyValidatorTest {
 
+    String text[] = {
+      "Mesa Verde National Park is a U.S. National Park and UNESCO World Heritage Site located in Montezuma County, Colorado.",
+      "It protects some of the best preserved Ancestral Puebloan archeological sites in the United States.",
+      "The park was created by President Theodore Roosevelt in 1906.",
+      "It occupies 52,485 acres (21,240 ha) near the Four Corners region, and with more than 4,000 sites and 600 cliff dwellings, it is the largest archeological preserve in the US.",
+      "Mesa Verde (Spanish for 'green table') is best known for structures such as Cliff Palace, thought to be the largest cliff dwelling in North America.",
+      "Starting c. 7,500 BCE, Mesa Verde was seasonally inhabited by a group of nomadic Paleo-Indians known as the Foothills Mountain Complex.",
+      "The variety of projectile points found in the region indicates they were influenced by surrounding areas, including the Great Basin, the San Juan Basin, and the Rio Grande Valley.",
+      "Later, Archaic people established semi-permanent rockshelters in and around the mesa.",
+      "By 1,000, the Basketmaker culture emerged from the local Archaic population, and by 750 CE the Ancestral Puebloans had developed from the Basketmaker culture.",
+      "The Mesa Verdeans survived by utilizing a combination of hunting, gathering, and subsistence farming of crops such as corn, beans, and squash.",
+      "They built the mesa's first pueblos sometime after 650, and by the end of the 12th century they began to construct the massive cliff dwellings for which the park is best known.",
+      "By 1285, following a period of social and environmental instability driven by a series of severe and prolonged droughts, they abandoned the area and moved south to locations in Arizona and New Mexico, including Rio Chama, Pajarito Plateau, and Santa Fe."
+    };
+
     @Test
     public void testDocument() throws RedPenException {
         WordFrequencyValidator validator = (WordFrequencyValidator) ValidatorFactory.getInstance("WordFrequency");
 
-        String text[] = {
-                "Mesa Verde National Park is a U.S. National Park and UNESCO World Heritage Site located in Montezuma County, Colorado.",
-                "It protects some of the best preserved Ancestral Puebloan archeological sites in the United States.",
-                "The park was created by President Theodore Roosevelt in 1906.",
-                "It occupies 52,485 acres (21,240 ha) near the Four Corners region, and with more than 4,000 sites and 600 cliff dwellings, it is the largest archeological preserve in the US.",
-                "Mesa Verde (Spanish for 'green table') is best known for structures such as Cliff Palace, thought to be the largest cliff dwelling in North America.",
-                "Starting c. 7,500 BCE, Mesa Verde was seasonally inhabited by a group of nomadic Paleo-Indians known as the Foothills Mountain Complex.",
-                "The variety of projectile points found in the region indicates they were influenced by surrounding areas, including the Great Basin, the San Juan Basin, and the Rio Grande Valley.",
-                "Later, Archaic people established semi-permanent rockshelters in and around the mesa.",
-                "By 1,000, the Basketmaker culture emerged from the local Archaic population, and by 750 CE the Ancestral Puebloans had developed from the Basketmaker culture.",
-                "The Mesa Verdeans survived by utilizing a combination of hunting, gathering, and subsistence farming of crops such as corn, beans, and squash.",
-                "They built the mesa's first pueblos sometime after 650, and by the end of the 12th century they began to construct the massive cliff dwellings for which the park is best known.",
-                "By 1285, following a period of social and environmental instability driven by a series of severe and prolonged droughts, they abandoned the area and moved south to locations in Arizona and New Mexico, including Rio Chama, Pajarito Plateau, and Santa Fe."
-        };
-
-        Document.DocumentBuilder builder = Document.builder(new WhiteSpaceTokenizer()).addSection(1).addParagraph();
-        int sentenceNumber = 1;
-        for (String line : text) {
-            builder.addSentence(new Sentence(line, sentenceNumber++));
-        }
-        Document document = builder.build();
+        Document document = buildDocument();
 
         List<ValidationError> errors = new ArrayList<>();
         validator.setErrorList(errors);
@@ -64,4 +61,27 @@ public class WordFrequencyValidatorTest {
 
         assertEquals(1, errors.size());
     }
+
+    @Test
+    public void testEmptySpellingDictionary() throws Exception {
+        WordFrequencyValidator validator = new WordFrequencyValidator();
+        validator.preInit(new ValidatorConfiguration("WordFrequency"), Configuration.builder("za").build());
+
+        Document document = buildDocument();
+
+        List<ValidationError> errors = new ArrayList<>();
+        validator.setErrorList(errors);
+        validator.validate(document);
+
+        assertEquals(0, errors.size());
+    }
+
+    private Document buildDocument() {
+        Document.DocumentBuilder builder = Document.builder(new WhiteSpaceTokenizer()).addSection(1).addParagraph();
+        int sentenceNumber = 1;
+        for (String line : text) {
+            builder.addSentence(new Sentence(line, sentenceNumber++));
+        }
+        return builder.build();
+    }
 }
diff --git a/redpen-core/src/test/java/cc/redpen/validator/sentence/DoubledJoshiValidatorTest.java b/redpen-core/src/test/java/cc/redpen/validator/sentence/DoubledJoshiValidatorTest.java
index c081b85a..bfa3eb2a 100644
--- a/redpen-core/src/test/java/cc/redpen/validator/sentence/DoubledJoshiValidatorTest.java
+++ b/redpen-core/src/test/java/cc/redpen/validator/sentence/DoubledJoshiValidatorTest.java
@@ -79,7 +79,7 @@ public class DoubledJoshiValidatorTest {
                 .build());
 
         Configuration config = Configuration.builder("ja")
-                .addValidatorConfig(new ValidatorConfiguration("DoubledJoshi").addAttribute("list", "は"))
+                .addValidatorConfig(new ValidatorConfiguration("DoubledJoshi").addProperty("list", "は"))
                 .build();
 
         RedPen redPen = new RedPen(config);
diff --git a/redpen-core/src/test/java/cc/redpen/validator/sentence/DoubledWordValidatorTest.java b/redpen-core/src/test/java/cc/redpen/validator/sentence/DoubledWordValidatorTest.java
index 97ccd029..aca15344 100644
--- a/redpen-core/src/test/java/cc/redpen/validator/sentence/DoubledWordValidatorTest.java
+++ b/redpen-core/src/test/java/cc/redpen/validator/sentence/DoubledWordValidatorTest.java
@@ -71,7 +71,7 @@ public class DoubledWordValidatorTest extends BaseValidatorTest {
     public void testDoubledUserDefinedSkipWord() throws RedPenException {
         config = Configuration.builder()
                 .addValidatorConfig(new ValidatorConfiguration(validatorName)
-                        .addAttribute("list", "redpen,tool"))
+                        .addProperty("list", "redpen,tool"))
                 .build();
 
         Document document = prepareSimpleDocument("RedPen is RedPen right?");
@@ -84,7 +84,7 @@ public class DoubledWordValidatorTest extends BaseValidatorTest {
     @Test
     public void testDoubledUserDefinedSkipWordWithoutNormalization() throws RedPenException {
         config = Configuration.builder()
-                .addValidatorConfig(new ValidatorConfiguration(validatorName).addAttribute("list", "RedPen,Tool"))
+                .addValidatorConfig(new ValidatorConfiguration(validatorName).addProperty("list", "RedPen,Tool"))
                 .build();
 
         Document document = prepareSimpleDocument("redPen is redPen right?");
diff --git a/redpen-core/src/test/java/cc/redpen/validator/sentence/EndOfSentenceValidatorTest.java b/redpen-core/src/test/java/cc/redpen/validator/sentence/EndOfSentenceValidatorTest.java
index a09398bc..b18d610c 100644
--- a/redpen-core/src/test/java/cc/redpen/validator/sentence/EndOfSentenceValidatorTest.java
+++ b/redpen-core/src/test/java/cc/redpen/validator/sentence/EndOfSentenceValidatorTest.java
@@ -29,6 +29,7 @@ import cc.redpen.parser.SentenceExtractor;
 import cc.redpen.tokenizer.JapaneseTokenizer;
 import cc.redpen.validator.ValidationError;
 import junit.framework.Assert;
+import org.junit.Before;
 import org.junit.Test;
 
 import java.util.ArrayList;
@@ -38,9 +39,15 @@ import java.util.Map;
 import static org.junit.Assert.assertEquals;
 
 public class EndOfSentenceValidatorTest {
+    private EndOfSentenceValidator validator = new EndOfSentenceValidator();
+
+    @Before
+    public void setUp() throws Exception {
+        validator.preInit(new ValidatorConfiguration("EndOfSentence"), Configuration.builder().build());
+    }
+
     @Test
     public void testInvalidEndOfSentence() {
-        EndOfSentenceValidator validator = new EndOfSentenceValidator();
         List<ValidationError> errors = new ArrayList<>();
         validator.setErrorList(errors);
         validator.validate(new Sentence("He said \"that is right\".", 0));
@@ -49,7 +56,6 @@ public class EndOfSentenceValidatorTest {
 
     @Test
     public void testValidEndOfSentence() {
-        EndOfSentenceValidator validator = new EndOfSentenceValidator();
         List<ValidationError> errors = new ArrayList<>();
         validator.setErrorList(errors);
         validator.validate(new Sentence("He said \"that is right.\"", 0));
@@ -58,16 +64,14 @@ public class EndOfSentenceValidatorTest {
 
     @Test
     public void testInValidEndOfSentenceWithQuestionMark() {
-        EndOfSentenceValidator validator = new EndOfSentenceValidator();
         List<ValidationError> errors = new ArrayList<>();
         validator.setErrorList(errors);
-        validator.validate( new Sentence("He said \"Is it right\"?", 0));
+        validator.validate(new Sentence("He said \"Is it right\"?", 0));
         assertEquals(1, errors.size());
     }
 
     @Test
     public void testVoid() {
-        EndOfSentenceValidator validator = new EndOfSentenceValidator();
         List<ValidationError> errors = new ArrayList<>();
         validator.setErrorList(errors);
         validator.validate(new Sentence("", 0));
diff --git a/redpen-core/src/test/java/cc/redpen/validator/sentence/InvalidExpressionValidatorTest.java b/redpen-core/src/test/java/cc/redpen/validator/sentence/InvalidExpressionValidatorTest.java
index a261f0af..94b74402 100644
--- a/redpen-core/src/test/java/cc/redpen/validator/sentence/InvalidExpressionValidatorTest.java
+++ b/redpen-core/src/test/java/cc/redpen/validator/sentence/InvalidExpressionValidatorTest.java
@@ -44,7 +44,7 @@ public class InvalidExpressionValidatorTest {
     @Test
     public void testSimpleRun() throws RedPenException {
         Configuration config = Configuration.builder()
-                .addValidatorConfig(new ValidatorConfiguration("InvalidExpression").addAttribute("list", "may"))
+                .addValidatorConfig(new ValidatorConfiguration("InvalidExpression").addProperty("list", "may"))
                 .build();
         Validator validator = ValidatorFactory.getInstance(config.getValidatorConfigs().get(0), config);
         List<ValidationError> errors = new ArrayList<>();
@@ -56,7 +56,7 @@ public class InvalidExpressionValidatorTest {
     @Test
     public void testVoid() throws RedPenException {
         Configuration config = Configuration.builder()
-                .addValidatorConfig(new ValidatorConfiguration("InvalidExpression").addAttribute("list", "may"))
+                .addValidatorConfig(new ValidatorConfiguration("InvalidExpression").addProperty("list", "may"))
                 .build();
         Validator validator = ValidatorFactory.getInstance(config.getValidatorConfigs().get(0), config);
         List<ValidationError> errors = new ArrayList<>();
@@ -105,7 +105,7 @@ public class InvalidExpressionValidatorTest {
     @Test
     public void testLoadJapaneseInvalidList() throws RedPenException {
         Configuration config = Configuration.builder("ja")
-                .addValidatorConfig(new ValidatorConfiguration("InvalidExpression").addAttribute("list", "うふぉ,ガチ"))
+                .addValidatorConfig(new ValidatorConfiguration("InvalidExpression").addProperty("list", "うふぉ,ガチ"))
                 .build();
 
         List<Document> documents = new ArrayList<>();documents.add(
diff --git a/redpen-core/src/test/java/cc/redpen/validator/sentence/InvalidWordValidatorTest.java b/redpen-core/src/test/java/cc/redpen/validator/sentence/InvalidWordValidatorTest.java
index 065a9a1f..25c015e5 100644
--- a/redpen-core/src/test/java/cc/redpen/validator/sentence/InvalidWordValidatorTest.java
+++ b/redpen-core/src/test/java/cc/redpen/validator/sentence/InvalidWordValidatorTest.java
@@ -49,7 +49,7 @@ public class InvalidWordValidatorTest {
                         .build());
 
         Configuration config = Configuration.builder()
-                .addValidatorConfig(new ValidatorConfiguration("InvalidWord").addAttribute("list", "foolish"))
+                .addValidatorConfig(new ValidatorConfiguration("InvalidWord").addProperty("list", "foolish"))
                 .build();
         Validator validator = ValidatorFactory.getInstance(config.getValidatorConfigs().get(0), config);
 
@@ -69,7 +69,7 @@ public class InvalidWordValidatorTest {
                         .build());
 
         Configuration config = Configuration.builder()
-                .addValidatorConfig(new ValidatorConfiguration("InvalidWord").addAttribute("list", "foolish"))
+                .addValidatorConfig(new ValidatorConfiguration("InvalidWord").addProperty("list", "foolish"))
                 .build();
         Validator validator = ValidatorFactory.getInstance(config.getValidatorConfigs().get(0), config);
         List<ValidationError> errors = new ArrayList<>();
@@ -101,7 +101,7 @@ public class InvalidWordValidatorTest {
     @Test
     public void testLoadUserDictionary() throws RedPenException {
         Configuration config = Configuration.builder()
-                .addValidatorConfig(new ValidatorConfiguration("InvalidWord").addAttribute("list", "boom,domo"))
+                .addValidatorConfig(new ValidatorConfiguration("InvalidWord").addProperty("list", "boom,domo"))
                 .build();
 
         List<Document> documents = new ArrayList<>();documents.add(
diff --git a/redpen-core/src/test/java/cc/redpen/validator/sentence/KatakanaEndHyphenValidatorTest.java b/redpen-core/src/test/java/cc/redpen/validator/sentence/KatakanaEndHyphenValidatorTest.java
index aef1cc08..7bd9243e 100644
--- a/redpen-core/src/test/java/cc/redpen/validator/sentence/KatakanaEndHyphenValidatorTest.java
+++ b/redpen-core/src/test/java/cc/redpen/validator/sentence/KatakanaEndHyphenValidatorTest.java
@@ -34,10 +34,10 @@ import java.util.Map;
 import static org.junit.Assert.assertEquals;
 
 public class KatakanaEndHyphenValidatorTest {
+    private KatakanaEndHyphenValidator validator = new KatakanaEndHyphenValidator();
+
     @Test
     public void testEmptyString() {
-        KatakanaEndHyphenValidator validator
-                = new KatakanaEndHyphenValidator();
         Sentence str = new Sentence("", 0);
         List<ValidationError> errors = new ArrayList<>();
         validator.setErrorList(errors);
@@ -47,8 +47,6 @@ public class KatakanaEndHyphenValidatorTest {
 
     @Test
     public void testSingleHiragana() {
-        KatakanaEndHyphenValidator validator
-                = new KatakanaEndHyphenValidator();
         Sentence str = new Sentence("あ", 0);
         List<ValidationError> errors = new ArrayList<>();
         validator.setErrorList(errors);
@@ -58,8 +56,6 @@ public class KatakanaEndHyphenValidatorTest {
 
     @Test
     public void testSingleKatakana() {
-        KatakanaEndHyphenValidator validator
-                = new KatakanaEndHyphenValidator();
         Sentence str = new Sentence("ア", 0);
         List<ValidationError> errors = new ArrayList<>();
         validator.setErrorList(errors);
@@ -69,8 +65,6 @@ public class KatakanaEndHyphenValidatorTest {
 
     @Test
     public void testKatakanaOfLength2() {
-        KatakanaEndHyphenValidator validator
-                = new KatakanaEndHyphenValidator();
         Sentence str = new Sentence("ドア", 0);
         List<ValidationError> errors = new ArrayList<>();
         validator.setErrorList(errors);
@@ -80,8 +74,6 @@ public class KatakanaEndHyphenValidatorTest {
 
     @Test
     public void testKatakanaOfLength3andHyphen() {
-        KatakanaEndHyphenValidator validator
-                = new KatakanaEndHyphenValidator();
         Sentence str = new Sentence("ミラー", 0);
         List<ValidationError> errors = new ArrayList<>();
         validator.setErrorList(errors);
@@ -91,8 +83,6 @@ public class KatakanaEndHyphenValidatorTest {
 
     @Test
     public void testKatakanaOfLength4andHyphen() {
-        KatakanaEndHyphenValidator validator
-                = new KatakanaEndHyphenValidator();
         Sentence str = new Sentence("コーヒー", 0); // This is an error.
         List<ValidationError> errors = new ArrayList<>();
         validator.setErrorList(errors);
@@ -102,8 +92,6 @@ public class KatakanaEndHyphenValidatorTest {
 
     @Test
     public void testSentenceBeginningWithKatakanaWithHypen() {
-        KatakanaEndHyphenValidator validator
-                = new KatakanaEndHyphenValidator();
         Sentence str = new Sentence("コンピューターが壊れた。", 0);
         List<ValidationError> errors = new ArrayList<>();
         validator.setErrorList(errors);
@@ -113,8 +101,6 @@ public class KatakanaEndHyphenValidatorTest {
 
     @Test
     public void testSentenceBeginningWithKatakanaWithoutHypen() {
-        KatakanaEndHyphenValidator validator
-                = new KatakanaEndHyphenValidator();
         Sentence str = new Sentence("コンピュータが壊れた。", 0);
         List<ValidationError> errors = new ArrayList<>();
         validator.setErrorList(errors);
@@ -124,8 +110,6 @@ public class KatakanaEndHyphenValidatorTest {
 
     @Test
     public void testSentenceContainKatakanaWithHypen() {
-        KatakanaEndHyphenValidator validator
-                = new KatakanaEndHyphenValidator();
         Sentence str = new Sentence("僕のコンピューターが壊れた。", 0);
         List<ValidationError> errors = new ArrayList<>();
         validator.setErrorList(errors);
@@ -135,8 +119,6 @@ public class KatakanaEndHyphenValidatorTest {
 
     @Test
     public void testSentenceContainKatakanaWitouthHypen() {
-        KatakanaEndHyphenValidator validator
-                = new KatakanaEndHyphenValidator();
         Sentence str = new Sentence("僕のコンピュータが壊れた。", 0);
         List<ValidationError> errors = new ArrayList<>();
         validator.setErrorList(errors);
@@ -146,8 +128,6 @@ public class KatakanaEndHyphenValidatorTest {
 
     @Test
     public void testSentenceEndingWithKatakanaWithHypen() {
-        KatakanaEndHyphenValidator validator
-                = new KatakanaEndHyphenValidator();
         Sentence str = new Sentence("僕のコンピューター", 0);
         List<ValidationError> errors = new ArrayList<>();
         validator.setErrorList(errors);
@@ -157,8 +137,6 @@ public class KatakanaEndHyphenValidatorTest {
 
     @Test
     public void testSentenceEndingWithKatakanaWithoutHypen() {
-        KatakanaEndHyphenValidator validator
-                = new KatakanaEndHyphenValidator();
         Sentence str = new Sentence("僕のコンピュータ", 0);
         List<ValidationError> errors = new ArrayList<>();
         validator.setErrorList(errors);
@@ -168,8 +146,6 @@ public class KatakanaEndHyphenValidatorTest {
 
     @Test
     public void testSentenceContainWithKatakanaMiddleDot() {
-        KatakanaEndHyphenValidator validator
-                = new KatakanaEndHyphenValidator();
         Sentence str = new Sentence("コーヒー・コンピューター", 0);
         List<ValidationError> errors = new ArrayList<>();
         validator.setErrorList(errors);
@@ -180,7 +156,7 @@ public class KatakanaEndHyphenValidatorTest {
     @Test
     public void testHonorsSkipWordList() throws RedPenException {
         Configuration config = Configuration.builder("ja")
-                .addValidatorConfig(new ValidatorConfiguration("KatakanaEndHyphen").addAttribute("list", "コーヒー"))
+                .addValidatorConfig(new ValidatorConfiguration("KatakanaEndHyphen").addProperty("list", "コーヒー"))
                 .build();
 
         List<Document> documents = new ArrayList<>();documents.add(
@@ -199,7 +175,7 @@ public class KatakanaEndHyphenValidatorTest {
     public void testHonorsSkipWordDict() throws RedPenException {
         Configuration config = Configuration.builder("ja")
                 .addValidatorConfig(new ValidatorConfiguration("KatakanaEndHyphen")
-                        .addAttribute("dict", "src/test/resources/cc/redpen/validator/KatakanaEndHyphenValidatorTest-skipworddict.txt")) // XXX
+                        .addProperty("dict", "src/test/resources/cc/redpen/validator/KatakanaEndHyphenValidatorTest-skipworddict.txt")) // XXX
                 .build();
 
         List<Document> documents = new ArrayList<>();documents.add(
diff --git a/redpen-core/src/test/java/cc/redpen/validator/sentence/KatakanaSpellCheckValidatorTest.java b/redpen-core/src/test/java/cc/redpen/validator/sentence/KatakanaSpellCheckValidatorTest.java
index 3b8a52d8..6939b03e 100644
--- a/redpen-core/src/test/java/cc/redpen/validator/sentence/KatakanaSpellCheckValidatorTest.java
+++ b/redpen-core/src/test/java/cc/redpen/validator/sentence/KatakanaSpellCheckValidatorTest.java
@@ -108,7 +108,7 @@ public class KatakanaSpellCheckValidatorTest {
     @Test
     public void testSetMinimumRatio() throws RedPenException {
         Configuration config = Configuration.builder("ja")
-                .addValidatorConfig(new ValidatorConfiguration("KatakanaSpellCheck").addAttribute("min_ratio", "0.001"))
+                .addValidatorConfig(new ValidatorConfiguration("KatakanaSpellCheck").addProperty("min_ratio", "0.001"))
                 .build();
 
         List<Document> documents = new ArrayList<>();
@@ -127,7 +127,7 @@ public class KatakanaSpellCheckValidatorTest {
     @Test
     public void testSetMinimumFrequency() throws RedPenException {
         Configuration config = Configuration.builder("ja")
-                .addValidatorConfig(new ValidatorConfiguration("KatakanaSpellCheck").addAttribute("min_freq", "0"))
+                .addValidatorConfig(new ValidatorConfiguration("KatakanaSpellCheck").addProperty("min_freq", "0"))
                 .build();
 
         List<Document> documents = new ArrayList<>();
@@ -146,7 +146,7 @@ public class KatakanaSpellCheckValidatorTest {
     @Test
     public void testLoadUserDictionary() throws RedPenException {
         Configuration config = Configuration.builder("ja")
-                .addValidatorConfig(new ValidatorConfiguration("KatakanaSpellCheck").addAttribute("list", "ミニマムサポート,ミニマムサポータ"))
+                .addValidatorConfig(new ValidatorConfiguration("KatakanaSpellCheck").addProperty("list", "ミニマムサポート,ミニマムサポータ"))
                 .build();
 
         List<Document> documents = new ArrayList<>();
@@ -165,7 +165,7 @@ public class KatakanaSpellCheckValidatorTest {
     @Test
     public void testDisableDefaultDictionary() throws RedPenException {
         Configuration config = Configuration.builder("ja")
-                .addValidatorConfig(new ValidatorConfiguration("KatakanaSpellCheck").addAttribute("disable-default", "true"))
+                .addValidatorConfig(new ValidatorConfiguration("KatakanaSpellCheck").addProperty("disable-default", "true"))
                 .build();
 
         List<Document> documents = new ArrayList<>();documents.add(
diff --git a/redpen-core/src/test/java/cc/redpen/validator/sentence/NumberFormatValidatorTest.java b/redpen-core/src/test/java/cc/redpen/validator/sentence/NumberFormatValidatorTest.java
index d9073aff..a0b25474 100644
--- a/redpen-core/src/test/java/cc/redpen/validator/sentence/NumberFormatValidatorTest.java
+++ b/redpen-core/src/test/java/cc/redpen/validator/sentence/NumberFormatValidatorTest.java
@@ -47,5 +47,4 @@ public class NumberFormatValidatorTest {
 
         assertEquals(st1.toString(), 6, errors.size());
     }
-
 }
diff --git a/redpen-core/src/test/java/cc/redpen/validator/sentence/ParenthesizedSentenceValidatorTest.java b/redpen-core/src/test/java/cc/redpen/validator/sentence/ParenthesizedSentenceValidatorTest.java
index 9ed58408..2c847c50 100644
--- a/redpen-core/src/test/java/cc/redpen/validator/sentence/ParenthesizedSentenceValidatorTest.java
+++ b/redpen-core/src/test/java/cc/redpen/validator/sentence/ParenthesizedSentenceValidatorTest.java
@@ -17,6 +17,9 @@
  */
 package cc.redpen.validator.sentence;
 
+import cc.redpen.RedPenException;
+import cc.redpen.config.Configuration;
+import cc.redpen.config.ValidatorConfiguration;
 import cc.redpen.model.Document;
 import cc.redpen.model.Sentence;
 import cc.redpen.tokenizer.WhiteSpaceTokenizer;
@@ -30,8 +33,9 @@ import static org.junit.Assert.assertEquals;
 
 public class ParenthesizedSentenceValidatorTest {
     @Test
-    public void testSingleSentence() {
+    public void testSingleSentence() throws RedPenException {
         ParenthesizedSentenceValidator validator = new ParenthesizedSentenceValidator();
+        validator.preInit(new ValidatorConfiguration("ParenthesizedSentence").addProperty("max_nesting_level", "2"), Configuration.builder().build());
 
         List<Document> documents = new ArrayList<>();
         documents.add(
diff --git a/redpen-core/src/test/java/cc/redpen/validator/sentence/QuotationValidatorTest.java b/redpen-core/src/test/java/cc/redpen/validator/sentence/QuotationValidatorTest.java
index d8a94c69..dc99f06f 100644
--- a/redpen-core/src/test/java/cc/redpen/validator/sentence/QuotationValidatorTest.java
+++ b/redpen-core/src/test/java/cc/redpen/validator/sentence/QuotationValidatorTest.java
@@ -170,7 +170,7 @@ public class QuotationValidatorTest {
     @Test
     public void testAsciiExceptionCase() throws RedPenException {
         Configuration conf = Configuration.builder()
-                .addValidatorConfig(new ValidatorConfiguration("Quotation").addAttribute("use_ascii", false))
+                .addValidatorConfig(new ValidatorConfiguration("Quotation").addProperty("use_ascii", false))
                 .build();
         Validator validator = ValidatorFactory.getInstance(conf.getValidatorConfigs().get(0), conf);
         Sentence str = new Sentence("I'm a jedi knight.", 0);
@@ -184,7 +184,7 @@ public class QuotationValidatorTest {
     @Test
     public void testAsciiDoubleQuotationMakrk() throws RedPenException {
         Configuration conf = Configuration.builder()
-                .addValidatorConfig(new ValidatorConfiguration("Quotation").addAttribute("use_ascii", false))
+                .addValidatorConfig(new ValidatorConfiguration("Quotation").addProperty("use_ascii", false))
                 .build();
         Validator validator = ValidatorFactory.getInstance(conf.getValidatorConfigs().get(0), conf);
         Sentence str = new Sentence("I said \"that is true\".", 0);
@@ -198,7 +198,7 @@ public class QuotationValidatorTest {
     @Test
     public void testNoQuotationMakrk() throws RedPenException {
         Configuration conf = Configuration.builder()
-                .addValidatorConfig(new ValidatorConfiguration("Quotation").addAttribute("use_ascii", true))
+                .addValidatorConfig(new ValidatorConfiguration("Quotation").addProperty("use_ascii", true))
                 .build();
         Validator validator = ValidatorFactory.getInstance(conf.getValidatorConfigs().get(0), conf);
         Sentence str = new Sentence("I said that is true.", 0);
@@ -212,7 +212,7 @@ public class QuotationValidatorTest {
     @Test
     public void testNoInput() throws RedPenException {
         Configuration conf = Configuration.builder()
-                .addValidatorConfig(new ValidatorConfiguration("Quotation").addAttribute("use_ascii", true))
+                .addValidatorConfig(new ValidatorConfiguration("Quotation").addProperty("use_ascii", true))
                 .build();
         Validator validator = ValidatorFactory.getInstance(conf.getValidatorConfigs().get(0), conf);
         Sentence str = new Sentence("", 0);
@@ -259,7 +259,7 @@ public class QuotationValidatorTest {
     @Test
     public void testLeftAsciiDoubleQuotationsWihtoutSpace() throws RedPenException {
         Configuration conf = Configuration.builder()
-                .addValidatorConfig(new ValidatorConfiguration("Quotation").addAttribute("use_ascii", true))
+                .addValidatorConfig(new ValidatorConfiguration("Quotation").addProperty("use_ascii", true))
                 .build();
         Validator validator = ValidatorFactory.getInstance(conf.getValidatorConfigs().get(0), conf);
         Sentence str = new Sentence("I said\"that is true\".", 0);
@@ -284,7 +284,7 @@ public class QuotationValidatorTest {
     @Test
     public void testRightAsciiDoubleQuotationsWihtoutSpace() throws RedPenException {
         Configuration conf = Configuration.builder()
-                .addValidatorConfig(new ValidatorConfiguration("Quotation").addAttribute("use_ascii", true))
+                .addValidatorConfig(new ValidatorConfiguration("Quotation").addProperty("use_ascii", true))
                 .build();
         Validator validator = ValidatorFactory.getInstance(conf.getValidatorConfigs().get(0), conf);
         Sentence str = new Sentence("I said \"that is true\"is true.", 0);
@@ -298,7 +298,7 @@ public class QuotationValidatorTest {
     @Test
     public void testDoubleQuotationsWithNonAsciiPeriod() throws RedPenException {
         Configuration conf = Configuration.builder()
-                .addValidatorConfig(new ValidatorConfiguration("Quotation").addAttribute("use_ascii", true))
+                .addValidatorConfig(new ValidatorConfiguration("Quotation").addProperty("use_ascii", true))
                 .addSymbol(new Symbol(SymbolType.FULL_STOP, '。'))
                 .build();
         Validator validator = ValidatorFactory.getInstance(conf.getValidatorConfigs().get(0), conf);
diff --git a/redpen-core/src/test/java/cc/redpen/validator/sentence/SentenceLengthValidatorTest.java b/redpen-core/src/test/java/cc/redpen/validator/sentence/SentenceLengthValidatorTest.java
index 4b494003..5faf88da 100644
--- a/redpen-core/src/test/java/cc/redpen/validator/sentence/SentenceLengthValidatorTest.java
+++ b/redpen-core/src/test/java/cc/redpen/validator/sentence/SentenceLengthValidatorTest.java
@@ -17,8 +17,11 @@
  */
 package cc.redpen.validator.sentence;
 
+import cc.redpen.config.Configuration;
+import cc.redpen.config.ValidatorConfiguration;
 import cc.redpen.model.Sentence;
 import cc.redpen.validator.ValidationError;
+import org.junit.Before;
 import org.junit.Test;
 
 import java.util.ArrayList;
@@ -27,10 +30,15 @@ import java.util.List;
 import static org.junit.Assert.assertEquals;
 
 public class SentenceLengthValidatorTest {
+    private SentenceLengthValidator validator = new SentenceLengthValidator();
+
+    @Before
+    public void setUp() throws Exception {
+        validator.preInit(new ValidatorConfiguration("SentenceLength").addProperty("max_len", "30"), Configuration.builder().build());
+    }
+
     @Test
     public void testWithLongSentence() {
-        SentenceLengthValidator validator = new SentenceLengthValidator();
-        validator.setLengthLimit(30);
         Sentence str = new Sentence("this is a very long long long long long long"
                 + "long long long long long long sentence.", 0);
         List<ValidationError> errors = new ArrayList<>();
@@ -41,8 +49,6 @@ public class SentenceLengthValidatorTest {
 
     @Test
     public void testWithShortSentence() {
-        SentenceLengthValidator validator = new SentenceLengthValidator();
-        validator.setLengthLimit(30);
         Sentence str = new Sentence("this is a sentence.", 0);
         List<ValidationError> errors = new ArrayList<>();
         validator.setErrorList(errors);
@@ -52,8 +58,6 @@ public class SentenceLengthValidatorTest {
 
     @Test
     public void testWithZeroLengthSentence() {
-        SentenceLengthValidator validator = new SentenceLengthValidator();
-        validator.setLengthLimit(30);
         Sentence str = new Sentence("", 0);
         List<ValidationError> errors = new ArrayList<>();
         validator.setErrorList(errors);
diff --git a/redpen-core/src/test/java/cc/redpen/validator/sentence/SpellingValidatorTest.java b/redpen-core/src/test/java/cc/redpen/validator/sentence/SpellingValidatorTest.java
index 315fd109..3eeb8f0a 100644
--- a/redpen-core/src/test/java/cc/redpen/validator/sentence/SpellingValidatorTest.java
+++ b/redpen-core/src/test/java/cc/redpen/validator/sentence/SpellingValidatorTest.java
@@ -43,7 +43,7 @@ public class SpellingValidatorTest extends BaseValidatorTest {
     @Test
     public void testValidate() throws Exception {
         config = Configuration.builder()
-          .addValidatorConfig(new ValidatorConfiguration(validatorName).addAttribute("list", "this,a,pen"))
+          .addValidatorConfig(new ValidatorConfiguration(validatorName).addProperty("list", "this,a,pen"))
           .build();
 
         Document document = prepareSimpleDocument("this iz a pen");
@@ -87,7 +87,7 @@ public class SpellingValidatorTest extends BaseValidatorTest {
     @Test
     public void testUserSkipList() throws RedPenException {
         config = Configuration.builder()
-                .addValidatorConfig(new ValidatorConfiguration(validatorName).addAttribute("list", "abeshi,baz"))
+                .addValidatorConfig(new ValidatorConfiguration(validatorName).addProperty("list", "abeshi,baz"))
                 .build();
 
         Document document = prepareSimpleDocument("Abeshi is a word used in a comic.");
@@ -140,4 +140,16 @@ public class SpellingValidatorTest extends BaseValidatorTest {
         Map<Document, List<ValidationError>> errors = redPen.validate(singletonList(document));
         assertEquals(0, errors.get(document).size());
     }
+
+    @Test
+    public void doNotShowErrorsInCaseOfMissingDictionary() throws Exception {
+        Document document = prepareSimpleDocument("test");
+        config = Configuration.builder("foo")
+          .addValidatorConfig(new ValidatorConfiguration(validatorName))
+          .build();
+
+        RedPen redPen = new RedPen(config);
+        Map<Document, List<ValidationError>> errors = redPen.validate(singletonList(document));
+        assertEquals(0, errors.get(document).size());
+    }
 }
diff --git a/redpen-core/src/test/java/cc/redpen/validator/sentence/StartWithCapitalLetterValidatorTest.java b/redpen-core/src/test/java/cc/redpen/validator/sentence/StartWithCapitalLetterValidatorTest.java
index 3cb36277..d7b47755 100644
--- a/redpen-core/src/test/java/cc/redpen/validator/sentence/StartWithCapitalLetterValidatorTest.java
+++ b/redpen-core/src/test/java/cc/redpen/validator/sentence/StartWithCapitalLetterValidatorTest.java
@@ -27,7 +27,6 @@ import cc.redpen.tokenizer.JapaneseTokenizer;
 import cc.redpen.validator.ValidationError;
 import cc.redpen.validator.Validator;
 import cc.redpen.validator.ValidatorFactory;
-import junit.framework.Assert;
 import org.junit.Test;
 
 import java.util.ArrayList;
@@ -82,7 +81,7 @@ public class StartWithCapitalLetterValidatorTest {
                 .addSentence(new Sentence("iPhone is a mobile computer.", 1))
                 .build());
         Configuration config = Configuration.builder()
-                .addValidatorConfig(new ValidatorConfiguration("StartWithCapitalLetter").addAttribute("list", "iPhone"))
+                .addValidatorConfig(new ValidatorConfiguration("StartWithCapitalLetter").addProperty("list", "iPhone"))
                 .build();
         Validator validator = ValidatorFactory.getInstance(config.getValidatorConfigs().get(0), config);
         List<ValidationError> errors = new ArrayList<>();
@@ -100,7 +99,7 @@ public class StartWithCapitalLetterValidatorTest {
                 .addSentence(new Sentence("iPhone はカッコイイ．", 1))
                 .build());
         Configuration config = Configuration.builder()
-                .addValidatorConfig(new ValidatorConfiguration("StartWithCapitalLetter").addAttribute("list", "iPhone"))
+                .addValidatorConfig(new ValidatorConfiguration("StartWithCapitalLetter").addProperty("list", "iPhone"))
                 .build();
         Validator validator = ValidatorFactory.getInstance(config.getValidatorConfigs().get(0), config);
         List<ValidationError> errors = new ArrayList<>();
@@ -118,7 +117,7 @@ public class StartWithCapitalLetterValidatorTest {
                 .addSentence(new Sentence(" iPhone is a mobile computer.", 1))
                 .build());
         Configuration config = Configuration.builder()
-                .addValidatorConfig(new ValidatorConfiguration("StartWithCapitalLetter").addAttribute("list", "iPhone"))
+                .addValidatorConfig(new ValidatorConfiguration("StartWithCapitalLetter").addProperty("list", "iPhone"))
                 .build();
         Validator validator = ValidatorFactory.getInstance(config.getValidatorConfigs().get(0), config);
         List<ValidationError> errors = new ArrayList<>();
@@ -136,7 +135,7 @@ public class StartWithCapitalLetterValidatorTest {
                 .addSentence(new Sentence("", 1))
                 .build());
         Configuration config = Configuration.builder()
-                .addValidatorConfig(new ValidatorConfiguration("StartWithCapitalLetter").addAttribute("list", "iPhone"))
+                .addValidatorConfig(new ValidatorConfiguration("StartWithCapitalLetter").addProperty("list", "iPhone"))
                 .build();
         Validator validator = ValidatorFactory.getInstance(config.getValidatorConfigs().get(0), config);
         List<ValidationError> errors = new ArrayList<>();
@@ -160,10 +159,9 @@ public class StartWithCapitalLetterValidatorTest {
 
         RedPen redPen = new RedPen(config);
         Map<Document, List<ValidationError>> errors = redPen.validate(documents);
-        Assert.assertEquals(0, errors.get(documents.get(0)).size());
+        assertEquals(0, errors.get(documents.get(0)).size());
     }
 
-
     @Test
     public void testDetectStartWithSmallCharacterInSecondSentence() throws RedPenException {
         Configuration config = Configuration.builder()
@@ -180,6 +178,6 @@ public class StartWithCapitalLetterValidatorTest {
 
         RedPen redPen = new RedPen(config);
         Map<Document, List<ValidationError>> errors = redPen.validate(documents);
-        Assert.assertEquals(1, errors.get(documents.get(0)).size());
+        assertEquals(1, errors.get(documents.get(0)).size());
     }
 }
diff --git a/redpen-server/src/test/java/cc/redpen/server/api/RedPenResourceTest.java b/redpen-server/src/test/java/cc/redpen/server/api/RedPenResourceTest.java
index a9eb14f8..65662687 100644
--- a/redpen-server/src/test/java/cc/redpen/server/api/RedPenResourceTest.java
+++ b/redpen-server/src/test/java/cc/redpen/server/api/RedPenResourceTest.java
@@ -24,7 +24,6 @@ import org.json.JSONArray;
 import org.json.JSONObject;
 import org.springframework.mock.web.MockHttpServletRequest;
 import org.springframework.mock.web.MockHttpServletResponse;
-import org.springframework.mock.web.MockServletContext;
 
 import javax.ws.rs.core.MediaType;
 import java.io.FileNotFoundException;
@@ -47,13 +46,9 @@ public class RedPenResourceTest extends MockServletInvocationTest {
     }
 
     public void testRun() throws Exception {
-        MockHttpServletRequest request =
-                constructMockRequest("POST", "/document/validate", WILDCARD);
-        request.setContent(("document=Foobar").getBytes());
-        MockServletContext context = new MockServletContext();
-        context.addInitParameter("redpen.conf.path", "conf/redpen-conf.xml");
+        MockHttpServletRequest request = constructMockRequest("POST", "/document/validate", WILDCARD);
+        request.setContent("document=Foobar".getBytes());
         MockHttpServletResponse response = invoke(request);
-
         assertEquals("HTTP status", HttpStatus.OK.getCode(), response.getStatus());
         JSONArray errors = (JSONArray) new JSONObject(response.getContentAsString()).get("errors");
         assertEquals(0, errors.length());
@@ -62,8 +57,6 @@ public class RedPenResourceTest extends MockServletInvocationTest {
     public void testRunWithErrors() throws Exception {
         MockHttpServletRequest request = constructMockRequest("POST", "/document/validate", WILDCARD);
         request.setContent(("document=foobar.foobar").getBytes()); //NOTE: need space between periods.
-        MockServletContext context = new MockServletContext();
-        context.addInitParameter("redpen.conf.path", "conf/redpen-conf.xml");
         MockHttpServletResponse response = invoke(request);
 
         assertEquals("HTTP status", HttpStatus.OK.getCode(), response.getStatus());
@@ -78,8 +71,6 @@ public class RedPenResourceTest extends MockServletInvocationTest {
     public void testRunWithoutContent() throws Exception {
         MockHttpServletRequest request = constructMockRequest("POST", "/document/validate", WILDCARD);
         request.setContent(("").getBytes()); //NOTE: need space between periods.
-        MockServletContext context = new MockServletContext();
-        context.addInitParameter("redpen.conf.path", "conf/redpen-conf.xml");
         MockHttpServletResponse response = invoke(request);
         assertEquals("HTTP status", HttpStatus.OK.getCode(), response.getStatus());
     }
@@ -87,8 +78,6 @@ public class RedPenResourceTest extends MockServletInvocationTest {
     public void testRunWithOnlyFormName() throws Exception {
         MockHttpServletRequest request = constructMockRequest("POST", "/document/validate", WILDCARD);
         request.setContent(("document=").getBytes()); //NOTE: need space between periods.
-        MockServletContext context = new MockServletContext();
-        context.addInitParameter("redpen.conf.path", "conf/redpen-conf.xml");
         MockHttpServletResponse response = invoke(request);
 
         assertEquals("HTTP status", HttpStatus.OK.getCode(), response.getStatus());
@@ -126,16 +115,11 @@ public class RedPenResourceTest extends MockServletInvocationTest {
     }
 
     // test helper
-    private MockHttpServletRequest constructMockRequest(String method,
-                                                        String requestURI,
-                                                        String acceptHeader) {
+    private MockHttpServletRequest constructMockRequest(String method, String requestURI, String acceptHeader) {
         return constructMockRequest(method, requestURI, acceptHeader, MediaType.APPLICATION_FORM_URLENCODED);
     }
 
-    private MockHttpServletRequest constructMockRequest(String method,
-                                                        String requestURI,
-                                                        String acceptHeader,
-                                                        String contentType) {
+    private MockHttpServletRequest constructMockRequest(String method, String requestURI, String acceptHeader, String contentType) {
         MockHttpServletRequest mockRequest = new MockHttpServletRequest() {
             public String getPathTranslated() {
                 return null; // prevent Spring to resolve the file on the filesystem which fails
@@ -150,5 +134,4 @@ public class RedPenResourceTest extends MockServletInvocationTest {
         mockRequest.setContentType(contentType);
         return mockRequest;
     }
-
 }
diff --git a/redpen-server/src/test/java/cc/redpen/server/api/RedPenServiceTest.java b/redpen-server/src/test/java/cc/redpen/server/api/RedPenServiceTest.java
index 618b8dff..df9a2f4c 100644
--- a/redpen-server/src/test/java/cc/redpen/server/api/RedPenServiceTest.java
+++ b/redpen-server/src/test/java/cc/redpen/server/api/RedPenServiceTest.java
@@ -14,11 +14,11 @@ import static org.junit.Assert.assertTrue;
 public class RedPenServiceTest {
   @Before
   public void setUp() {
-    RedPenService.langRedPenMap.clear();
+    RedPenService.redPens.clear();
   }
 
   @Test
-  public void twoConfigurationsByDefault() throws Exception {
+  public void defaultConfigurations() throws Exception {
     RedPenService service = new RedPenService(null);
     Map<String, RedPen> redPens = service.getRedPens();
     assertEquals(5, redPens.size());
@@ -40,9 +40,9 @@ public class RedPenServiceTest {
   @Test
   public void canSpecifyDifferentDefaultConfiguration() throws Exception {
     MockServletContext context = new MockServletContext();
-    context.addInitParameter("redpen.conf.path", "/conf/redpen-conf-ja.xml");
+    context.addInitParameter("redpen.conf.path", "/conf/redpen-conf-ru.xml");
     RedPen defaultRedPen = new RedPenService(context).getRedPen("default");
-    assertEquals("ja", defaultRedPen.getConfiguration().getKey());
+    assertEquals("ru", defaultRedPen.getConfiguration().getKey());
     assertTrue(defaultRedPen.getConfiguration().isSecure());
   }
 
diff --git a/redpen-server/src/test/java/ui/RedPenDemoTest.java b/redpen-server/src/test/java/ui/RedPenDemoTest.java
index 720d79db..175084e2 100644
--- a/redpen-server/src/test/java/ui/RedPenDemoTest.java
+++ b/redpen-server/src/test/java/ui/RedPenDemoTest.java
@@ -81,7 +81,7 @@ public class RedPenDemoTest {
     validatorProperties.click();
 
     $(".popover-title").should(appear).shouldHave(text("SentenceLength properties"));
-    $(".popover-content input[type=text]").shouldHave(value("max_len=200")).val("max_len=10");
+    $(".popover-content input[type=text]").shouldHave(value("max_len=120")).val("max_len=10");
     $(".popover-content button[type=submit]").click();
 
     validatorProperties.shouldHave(text("max_len=10"));
diff --git a/redpen-server/src/test/resources/conf/redpen-conf-ru.xml b/redpen-server/src/test/resources/conf/redpen-conf-ru.xml
new file mode 100644
index 00000000..0b0a268b
--- /dev/null
+++ b/redpen-server/src/test/resources/conf/redpen-conf-ru.xml
@@ -0,0 +1,1 @@
+<redpen-conf lang="ru"/>