package org.ovirt.engine.core.config.entity;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.configuration.SubnodeConfiguration;
import org.apache.commons.lang.StringUtils;
import org.ovirt.engine.core.config.EngineConfig;
import org.ovirt.engine.core.config.EngineConfigCLIParser;
import org.ovirt.engine.core.config.entity.helper.StringValueHelper;
import org.ovirt.engine.core.config.entity.helper.ValueHelper;
import org.slf4j.LoggerFactory;
public class ConfigKeyFactory {
private HierarchicalConfiguration keysConfig;
private Map<String, String> alternateKeysMap;
private static ConfigKeyFactory instance;
private EngineConfigCLIParser parser;
static {
instance = new ConfigKeyFactory();
}
private ConfigKeyFactory() {
}
public static void init(HierarchicalConfiguration keysConfig,
Map<String, String> alternateKeysMap,
EngineConfigCLIParser parser) {
instance.keysConfig = keysConfig;
instance.alternateKeysMap = alternateKeysMap;
instance.parser = parser;
}
public static ConfigKeyFactory getInstance() {
return instance;
}
public ConfigKey generateByPropertiesKey(String key) {
SubnodeConfiguration configurationAt = null;
try {
if (Character.isLetter(key.charAt(0))) {
configurationAt = keysConfig.configurationAt(key);
}
} catch (IllegalArgumentException e) {
// Can't find a key. maybe its an alternate key.
}
if (configurationAt == null || configurationAt.isEmpty()) {
key = alternateKeysMap.get(key);
configurationAt = keysConfig.configurationAt(key);
}
String type = configurationAt.getString("type");
if (StringUtils.isBlank(type)) {
type = "String";
}
String[] validValues = configurationAt.getStringArray("validValues");
// Description containing the list delimiter *will* be broken into an array, so rejoin it using that delimiter.
// We pad the separator because the strings in the array are trimmed automatically.
String description = StringUtils.join(configurationAt.getStringArray("description"),
configurationAt.getListDelimiter() + " ");
String alternateKey = keysConfig.getString("/" + key + "/" + "alternateKey");
// If the isReloadable attribute isn't specified - assume it is false
boolean reloadable = configurationAt.getBoolean("isReloadable", false);
ConfigKey configKey = new ConfigKey(type, description, alternateKey, key, "", validValues,
"", getHelperByType(type), reloadable, isDeprecated(key));
configKey.setParser(parser);
return configKey;
}
private boolean isDeprecated(String key) {
final String pathToDeprecatedAttribute = key + "/deprecated";
if (!keysConfig.containsKey(pathToDeprecatedAttribute)) {
return false;
}
final List list = keysConfig.getList(pathToDeprecatedAttribute);
if (list.size() != 1) {
throw new IllegalArgumentException("Configuration error; Key \""+key+"\" has ambiguous definition.");
}
final Object value = list.iterator().next();
try {
return Boolean.parseBoolean((String) value);
} catch (ClassCastException e) {
throw new IllegalArgumentException("Configuration error;" +
" Key \""+key+"\" should be either 'true' or 'false'. Value '"+value+"' is not valid.");
}
}
public ConfigKey generateBlankConfigKey(String keyName, String keyType) {
return new ConfigKey(keyType, "", "", keyName, "", null, "", getHelperByType(keyType), false, false);
}
private ValueHelper getHelperByType(String type) {
ValueHelper valueHelper;
try {
if (type == null) {
type = "String";
}
Class<?> cls = Class.forName("org.ovirt.engine.core.config.entity.helper." + type + "ValueHelper");
valueHelper = (ValueHelper) cls.newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
// failed finding a helper for this type. Setting default string type
LoggerFactory.getLogger(EngineConfig.class)
.debug("Unable to find {} type. Using default string type.", type);
valueHelper = new StringValueHelper();
}
return valueHelper;
}
public ConfigKey copyOf(ConfigKey key, String value, String version) {
return new ConfigKey(
key.getType(),
key.getDescription(),
key.getAlternateKeys(),
key.getKey(),
value,
key.getValidValues().toArray(new String[0]),
version,
key.getValueHelper(),
key.isReloadable(),
key.isDeprecated());
}
/**
* Create a ConfigKey from a ResultSet object. <b>Note</b>: Some fields are not represented by the DB, such as
* decription and type.<br>
*
* TODO Consider refactoring the entity to be composed out of a real value-object which will represent the db
* entity and a view-object which will represent the user interaction (view) layer.
* TODO move "option_name" and other column indexes to Enum values.
*/
public ConfigKey fromResultSet(ResultSet resultSet) throws SQLException {
ConfigKey configKey = generateByPropertiesKey(resultSet.getString("option_name"));
configKey.unsafeSetValue(resultSet.getString("option_value"));
configKey.setVersion(resultSet.getString("version"));
return configKey;
}
}