package org.infernus.idea.checkstyle;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.infernus.idea.checkstyle.model.ConfigurationLocation;
import org.infernus.idea.checkstyle.model.ConfigurationLocationFactory;
import org.jetbrains.annotations.NotNull;
import java.util.*;
/**
* A manager for CheckStyle module configuration.
*/
@State(
name = CheckStylePlugin.ID_MODULE_PLUGIN,
storages = {@Storage(id = "other", file = "$MODULE_FILE$")}
)
public final class CheckStyleModuleConfiguration extends Properties
implements PersistentStateComponent<CheckStyleModuleConfiguration.ModuleSettings> {
private static final Log LOG = LogFactory.getLog(CheckStyleModuleConfiguration.class);
private static final long serialVersionUID = 2804470793153632480L;
private static final String ACTIVE_CONFIG = "active-configuration";
private static final String EXCLUDE_FROM_SCAN = "exclude-from-scan";
private final Module module;
/**
* Create a new configuration bean.
*
* @param module the module we belong to.
*/
public CheckStyleModuleConfiguration(final Module module) {
if (module == null) {
throw new IllegalArgumentException("Module is required");
}
this.module = module;
}
public void setActiveConfiguration(final ConfigurationLocation configurationLocation) {
if (configurationLocation != null && !configurationLocations().contains(configurationLocation)) {
throw new IllegalArgumentException("Location is not valid: " + configurationLocation);
}
if (configurationLocation != null) {
setProperty(ACTIVE_CONFIG, configurationLocation.getDescriptor());
} else {
remove(ACTIVE_CONFIG);
}
}
public void setExcluded(final boolean excluded) {
if (excluded) {
setProperty(EXCLUDE_FROM_SCAN, "true");
} else {
remove(EXCLUDE_FROM_SCAN);
}
}
public boolean isExcluded() {
return containsKey(EXCLUDE_FROM_SCAN)
&& "true".equalsIgnoreCase(getProperty(EXCLUDE_FROM_SCAN, "false"));
}
public boolean isUsingModuleConfiguration() {
return containsKey(ACTIVE_CONFIG);
}
public ConfigurationLocation getActiveConfiguration() {
if (!containsKey(ACTIVE_CONFIG)) {
return getProjectConfiguration();
}
ConfigurationLocation activeLocation = null;
try {
activeLocation = configurationLocationFactory(module.getProject()).create(module.getProject(), getProperty(ACTIVE_CONFIG));
} catch (IllegalArgumentException e) {
LOG.warn("Could not load active configuration", e);
}
if (activeLocation == null || !configurationLocations().contains(activeLocation)) {
LOG.info("Active module configuration is invalid, returning project configuration");
return getProjectConfiguration();
}
return activeLocation;
}
private ConfigurationLocation getProjectConfiguration() {
return checkstylePlugin().getConfiguration().getActiveConfiguration();
}
public List<ConfigurationLocation> configurationLocations() {
return checkstylePlugin().getConfiguration().configurationLocations();
}
public List<ConfigurationLocation> getAndResolveConfigurationLocations() {
return checkstylePlugin().getConfiguration().getAndResolveConfigurationLocations();
}
@NotNull
private CheckStylePlugin checkstylePlugin() {
final CheckStylePlugin checkStylePlugin = module.getProject().getComponent(CheckStylePlugin.class);
if (checkStylePlugin == null) {
throw new IllegalStateException("Couldn't get checkstyle plugin");
}
return checkStylePlugin;
}
private ConfigurationLocationFactory configurationLocationFactory(final Project project) {
return ServiceManager.getService(project, ConfigurationLocationFactory.class);
}
public ModuleSettings getState() {
final ModuleSettings moduleSettings = new ModuleSettings();
for (String configurationKey : stringPropertyNames()) {
moduleSettings.configuration.put(configurationKey, getProperty(configurationKey));
}
return moduleSettings;
}
public void loadState(final ModuleSettings moduleSettings) {
clear();
if (moduleSettings != null && moduleSettings.configuration != null) {
for (final String key : moduleSettings.configuration.keySet()) {
setProperty(key, moduleSettings.configuration.get(key));
}
}
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
CheckStyleModuleConfiguration that = (CheckStyleModuleConfiguration) o;
return module.equals(that.module);
}
@Override
public int hashCode() {
return 31 * super.hashCode() + module.hashCode();
}
/**
* Wrapper class for IDEA state serialisation.
*/
public static class ModuleSettings {
// this must remain public for serialisation purposes
public Map<String, String> configuration = new HashMap<>();
public ModuleSettings() {
this.configuration = new HashMap<>();
}
public ModuleSettings(final Map<String, String> configuration) {
this.configuration = configuration;
}
public Map<String, String> configurationAsMap() {
if (configuration == null) {
return Collections.emptyMap();
}
return configuration;
}
}
}