package org.infernus.idea.checkstyle; import java.io.IOException; import java.util.List; import javax.swing.JComponent; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.project.Project; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.infernus.idea.checkstyle.checker.CheckerFactoryCache; import org.infernus.idea.checkstyle.model.ConfigurationLocation; import org.infernus.idea.checkstyle.ui.CheckStyleConfigPanel; import org.infernus.idea.checkstyle.util.Notifications; import org.infernus.idea.checkstyle.util.Objects; import org.jetbrains.annotations.NotNull; /** * The "configurable component" required by IntelliJ IDEA to provide a Swing form for inclusion into the 'Settings' * dialog. Registered in {@code plugin.xml} as a {@code projectConfigurable} extension. */ public class CheckStyleConfigurable implements Configurable { private static final Log LOG = LogFactory.getLog(CheckStyleConfigurable.class); private final Project project; private final CheckStyleConfigPanel configPanel; public CheckStyleConfigurable(@NotNull final Project project) { this(project, new CheckStyleConfigPanel(project)); } CheckStyleConfigurable(@NotNull final Project project, @NotNull final CheckStyleConfigPanel configPanel) { this.project = project; this.configPanel = configPanel; } public String getDisplayName() { return CheckStyleBundle.message("plugin.configuration-name"); } public String getHelpTopic() { return null; } public JComponent createComponent() { reset(); return configPanel; } @Override public boolean isModified() { LOG.trace("isModified() - enter"); final CheckStyleConfiguration configuration = getConfiguration(); try { boolean result = haveLocationsChanged(configuration) || hasActiveLocationChanged(configuration) || !configuration.getThirdPartyClassPath().equals(configPanel.getThirdPartyClasspath()) || configuration.getScanScope() != configPanel.getScanScope() || configuration.isSuppressingErrors() != configPanel.isSuppressingErrors() || !configuration.getCheckstyleVersion(null).equals(configPanel.getCheckstyleVersion()); if (LOG.isTraceEnabled()) { LOG.trace("isModified() - exit - result=" + result); } return result; } catch (IOException e) { LOG.error("Failed to read properties from one of " + configPanel.getConfigurationLocations(), e); Notifications.showError(project, CheckStyleBundle.message("checkstyle.file-not-found")); LOG.trace("isModified() - exit - result=true"); return true; } } private boolean hasActiveLocationChanged(final CheckStyleConfiguration pConfiguration) throws IOException { final ConfigurationLocation configActiveLocation = pConfiguration.getActiveConfiguration(); final ConfigurationLocation panelActiveLocation = configPanel.getActiveLocation(); boolean result = false; if (configActiveLocation == null) { result = panelActiveLocation != null; } else { result = configActiveLocation.hasChangedFrom(panelActiveLocation); } return result; } private boolean haveLocationsChanged(final CheckStyleConfiguration pCurrentConfiguration) { LOG.trace("haveLocationsChanged() - enter"); final List<ConfigurationLocation> configLocations = pCurrentConfiguration.configurationLocations(); final List<ConfigurationLocation> panelLocations = configPanel.getConfigurationLocations(); boolean result = !Objects.equals(configLocations, panelLocations); if (LOG.isTraceEnabled()) { LOG.trace("haveLocationsChanged() - exit - result=" + result); } return result; } public void apply() throws ConfigurationException { LOG.trace("apply() - enter"); final CheckStyleConfiguration configuration = getConfiguration(); configuration.setCheckstyleVersion(configPanel.getCheckstyleVersion()); configuration.setConfigurationLocations(configPanel.getConfigurationLocations()); configuration.setActiveConfiguration(configPanel.getActiveLocation()); configuration.setScanScope(configPanel.getScanScope()); configuration.setSuppressingErrors(configPanel.isSuppressingErrors()); final List<String> thirdPartyClasspath = configPanel.getThirdPartyClasspath(); configuration.setThirdPartyClassPath(thirdPartyClasspath); activateCurrentCheckstyleVersion(configPanel.getCheckstyleVersion(), thirdPartyClasspath); LOG.trace("apply() - exit"); } private void activateCurrentCheckstyleVersion(final String checkstyleVersion, final List<String> thirdPartyClasspath) { // Invalidate cache *before* activating the new Checkstyle version getCheckerFactoryCache().invalidate(); CheckstyleProjectService csService = CheckstyleProjectService.getInstance(project); csService.activateCheckstyleVersion(checkstyleVersion, thirdPartyClasspath); } CheckStyleConfiguration getConfiguration() { return CheckStyleConfiguration.getInstance(project); } private CheckerFactoryCache getCheckerFactoryCache() { return ServiceManager.getService(CheckerFactoryCache.class); } public void reset() { LOG.trace("reset() - enter"); final CheckStyleConfiguration configuration = getConfiguration(); configPanel.setCheckstyleVersion(configuration.getCheckstyleVersion(null)); configPanel.setConfigurationLocations(configuration.getAndResolveConfigurationLocations()); configPanel.setActiveLocation(configuration.getActiveConfiguration()); configPanel.setScanScope(configuration.getScanScope()); configPanel.setSuppressingErrors(configuration.isSuppressingErrors()); configPanel.setThirdPartyClasspath(configuration.getThirdPartyClassPath()); activateCurrentCheckstyleVersion( configuration.getCheckstyleVersion(null), configuration.getThirdPartyClassPath()); LOG.trace("reset() - exit"); } public void disposeUIResources() { // do nothing } }