/* LanguageTool, a natural language style checker
* Copyright (C) 2005 Daniel Naber (http://www.danielnaber.de)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
* USA
*/
package org.languagetool.gui;
import org.languagetool.Language;
import org.languagetool.tools.StringTools;
import java.io.*;
import java.util.*;
/**
* Configuration like list of disabled rule IDs, server mode etc.
* Configuration is loaded from and stored to a properties file.
*
* @author Daniel Naber
*/
public class Configuration {
static final int DEFAULT_SERVER_PORT = 8081; // TODO: should be HTTPServerConfig.DEFAULT_PORT but we don't have that dependency
private static final String CONFIG_FILE = "languagetool.properties";
private static final String DISABLED_RULES_CONFIG_KEY = "disabledRules";
private static final String ENABLED_RULES_CONFIG_KEY = "enabledRules";
private static final String DISABLED_CATEGORIES_CONFIG_KEY = "disabledCategories";
private static final String MOTHER_TONGUE_CONFIG_KEY = "motherTongue";
private static final String AUTO_DETECT_CONFIG_KEY = "autoDetect";
private static final String SERVER_RUN_CONFIG_KEY = "serverMode";
private static final String SERVER_PORT_CONFIG_KEY = "serverPort";
private static final String USE_GUI_CONFIG_KEY = "useGUIConfig";
private static final String DELIMITER = ",";
private final File configFile;
private final HashMap<String, String> configForOtherLangs;
private Set<String> disabledRuleIds = new HashSet<String>();
private Set<String> enabledRuleIds = new HashSet<String>();
private Set<String> disabledCategoryNames = new HashSet<String>();
private Language motherTongue;
private boolean runServer;
private boolean autoDetect;
private boolean guiConfig;
private int serverPort = DEFAULT_SERVER_PORT;
/**
* Uses the configuration file from the default location.
* @param lang The language for the configuration, used to distinguish
* rules that are enabled or disabled per language.
*
* @throws IOException
*/
public Configuration(final Language lang) throws IOException {
this(new File(System.getProperty("user.home")), CONFIG_FILE, lang);
}
public Configuration(final File baseDir, final String filename, final Language lang)
throws IOException {
if (!baseDir.isDirectory()) {
throw new IllegalArgumentException("Not a directory: " + baseDir);
}
configFile = new File(baseDir, filename);
configForOtherLangs = new HashMap<String, String>();
loadConfiguration(lang);
}
public Configuration(final File baseDir, final Language lang) throws IOException {
this(baseDir, CONFIG_FILE, lang);
}
public Set<String> getDisabledRuleIds() {
return disabledRuleIds;
}
public Set<String> getEnabledRuleIds() {
return enabledRuleIds;
}
public Set<String> getDisabledCategoryNames() {
return disabledCategoryNames;
}
public void setDisabledRuleIds(final Set<String> ruleIDs) {
disabledRuleIds = ruleIDs;
}
public void setEnabledRuleIds(final Set<String> ruleIDs) {
enabledRuleIds = ruleIDs;
}
public void setDisabledCategoryNames(final Set<String> categoryNames) {
disabledCategoryNames = categoryNames;
}
public Language getMotherTongue() {
return motherTongue;
}
public void setMotherTongue(final Language motherTongue) {
this.motherTongue = motherTongue;
}
public boolean getAutoDetect() {
return autoDetect;
}
public void setAutoDetect(final boolean autoDetect) {
this.autoDetect = autoDetect;
}
public boolean getRunServer() {
return runServer;
}
public void setRunServer(final boolean runServer) {
this.runServer = runServer;
}
public int getServerPort() {
return serverPort;
}
public void setUseGUIConfig(final boolean useGUIConfig) {
this.guiConfig = useGUIConfig;
}
public boolean getUseGUIConfig() {
return guiConfig;
}
public void setServerPort(final int serverPort) {
this.serverPort = serverPort;
}
private void loadConfiguration(final Language lang) throws IOException {
final String qualifier = getQualifier(lang);
FileInputStream fis = null;
try {
fis = new FileInputStream(configFile);
final Properties props = new Properties();
props.load(fis);
disabledRuleIds.addAll(getListFromProperties(props, DISABLED_RULES_CONFIG_KEY + qualifier));
enabledRuleIds.addAll(getListFromProperties(props, ENABLED_RULES_CONFIG_KEY + qualifier));
disabledCategoryNames.addAll(getListFromProperties(props, DISABLED_CATEGORIES_CONFIG_KEY + qualifier));
final String motherTongueStr = (String) props.get(MOTHER_TONGUE_CONFIG_KEY);
if (motherTongueStr != null) {
motherTongue = Language.getLanguageForShortName(motherTongueStr);
}
autoDetect = "true".equals(props.get(AUTO_DETECT_CONFIG_KEY));
guiConfig = "true".equals(props.get(USE_GUI_CONFIG_KEY));
runServer = "true".equals(props.get(SERVER_RUN_CONFIG_KEY));
final String serverPortString = (String) props.get(SERVER_PORT_CONFIG_KEY);
if (serverPortString != null) {
serverPort = Integer.parseInt(serverPortString);
}
//store config for other languages
loadConfigForOtherLanguages(lang, props);
} catch (final FileNotFoundException e) {
// file not found: okay, leave disabledRuleIds empty
} finally {
if (fis != null) {
fis.close();
}
}
}
private String getQualifier(final Language lang) {
String qualifier = "";
if (lang != null) {
qualifier = "." + lang.getShortNameWithVariant();
}
return qualifier;
}
private void loadConfigForOtherLanguages(final Language lang, final Properties prop) {
for (Language otherLang : Language.getAllLanguages()) {
if (!otherLang.equals(lang)) {
final String languageSuffix = "." + otherLang.getShortNameWithVariant();
storeConfigKeyFromProp(prop, DISABLED_RULES_CONFIG_KEY + languageSuffix);
storeConfigKeyFromProp(prop, ENABLED_RULES_CONFIG_KEY + languageSuffix);
storeConfigKeyFromProp(prop, DISABLED_CATEGORIES_CONFIG_KEY + languageSuffix);
}
}
}
private void storeConfigKeyFromProp(final Properties prop, final String key) {
if (prop.containsKey(key)) {
configForOtherLangs.put(key, prop.getProperty(key));
}
}
private Collection<? extends String> getListFromProperties(final Properties props, final String key) {
final String value = (String) props.get(key);
final List<String> list = new ArrayList<String>();
if (value != null) {
final String[] names = value.split(DELIMITER);
list.addAll(Arrays.asList(names));
}
return list;
}
public void saveConfiguration(final Language lang) throws IOException {
final Properties props = new Properties();
final String qualifier = getQualifier(lang);
addListToProperties(props, DISABLED_RULES_CONFIG_KEY + qualifier, disabledRuleIds);
addListToProperties(props, ENABLED_RULES_CONFIG_KEY + qualifier, enabledRuleIds);
addListToProperties(props, DISABLED_CATEGORIES_CONFIG_KEY + qualifier, disabledCategoryNames);
if (motherTongue != null) {
props.setProperty(MOTHER_TONGUE_CONFIG_KEY, motherTongue.getShortName());
}
props.setProperty(AUTO_DETECT_CONFIG_KEY, Boolean.valueOf(autoDetect).toString());
props.setProperty(USE_GUI_CONFIG_KEY, Boolean.valueOf(guiConfig).toString());
props.setProperty(SERVER_RUN_CONFIG_KEY, Boolean.valueOf(runServer).toString());
props.setProperty(SERVER_PORT_CONFIG_KEY, Integer.valueOf(serverPort).toString());
for (final String key : configForOtherLangs.keySet()) {
props.setProperty(key, configForOtherLangs.get(key));
}
final FileOutputStream fos = new FileOutputStream(configFile);
try {
props.store(fos, "LanguageTool configuration");
} finally {
fos.close();
}
}
private void addListToProperties(final Properties props, final String key, final Set<String> list) {
if (list == null) {
props.setProperty(key, "");
} else {
props.setProperty(key, StringTools.listToString(list, DELIMITER));
}
}
}