/******************************************************************************* * Copyright (c) 2013 The PDT Extension Group (https://github.com/pdt-eg) * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html ******************************************************************************/ package org.pdtextensions.internal.semanticanalysis.validation; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import javax.annotation.PostConstruct; import javax.inject.Inject; import javax.inject.Singleton; import org.eclipse.core.resources.ProjectScope; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtensionRegistry; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.dltk.compiler.problem.ProblemSeverity; import org.eclipse.dltk.core.IScriptProject; import org.eclipse.e4.core.di.extensions.Preference; import org.eclipse.php.internal.core.project.PHPNature; import org.osgi.service.prefs.Preferences; import org.pdtextensions.semanticanalysis.PEXAnalysisPlugin; import org.pdtextensions.semanticanalysis.PreferenceConstants; import org.pdtextensions.semanticanalysis.model.validators.Category; import org.pdtextensions.semanticanalysis.model.validators.Type; import org.pdtextensions.semanticanalysis.model.validators.Validator; import org.pdtextensions.semanticanalysis.model.validators.ValidatorsFactory; import org.pdtextensions.semanticanalysis.model.validators.impl.ValidatorsPackageImpl; import org.pdtextensions.semanticanalysis.validation.IValidatorFactory; import org.pdtextensions.semanticanalysis.validation.IValidatorIdentifier; import org.pdtextensions.semanticanalysis.validation.IValidatorManager; @Singleton @SuppressWarnings("restriction") final public class Manager implements IValidatorManager { private static final String SLASH = "/"; //$NON-NLS-1$ final private Map<String, Category> categories = new HashMap<String, Category>(); final private Map<String, Validator> validators = new HashMap<String, Validator>(); final private Validator[] emptyList = new Validator[0]; @Inject @Preference(nodePath=PEXAnalysisPlugin.VALIDATORS_PREFERENCES_NODE_ID) private IEclipsePreferences preferences; @Inject @Preference(nodePath=SLASH + ProjectScope.SCOPE) private IEclipsePreferences projectPreferences; @PostConstruct public void initialize(IExtensionRegistry registry) { ValidatorsPackageImpl.init(); final IConfigurationElement[] config = registry.getConfigurationElementsFor(EXTENSION_ID); // build categories for(final IConfigurationElement el : config) { registerCategory(el); } // build validators for (final IConfigurationElement el : config) { registerValidator(el); } } private void registerCategory(IConfigurationElement el) { if (!el.getName().equals(ELEMENT_CATEGORY)) { return; } final Category category = ValidatorsFactory.eINSTANCE.createCategory(); category.setId(el.getAttribute(ATTR_ID)); category.setLabel(el.getAttribute(ATTR_LABEL)); category.setDescription(el.getAttribute(ATTR_DESCRIPTION)); categories.put(category.getId(), category); } private void registerValidator(IConfigurationElement el) { if (!el.getName().equals(ELEMENT_VALIDATOR)) { return; } final Validator validator = ValidatorsFactory.eINSTANCE.createValidator(); String categoryId = el.getAttribute(ATTR_CATEGORY); validator.setId(el.getAttribute(ATTR_ID)); if (!categories.containsKey(categoryId)) { if (categoryId != null) PEXAnalysisPlugin.error(String.format("Validator %s has reference to a non-existent category %s", validator.getId(), categoryId)); //$NON-NLS-1$ categoryId = DEFAULT_CATEGORY_ID; } validator.setCategory(categories.get(categoryId)); validator.getCategory().getValidators().add(validator); for (IConfigurationElement typeCfg : el.getChildren(ELEMENT_TYPE)) { Type type = ValidatorsFactory.eINSTANCE.createType(); type.setId(typeCfg.getAttribute(ATTR_ID)); type.setDefaultSeverity(ProblemSeverity.valueOf(preferences.node(validator.getId()).get(type.getId(), typeCfg.getAttribute(ATTR_DEFAULT_SEVERITY) == null ? DEFAULT_SEVERITY: typeCfg.getAttribute(ATTR_DEFAULT_SEVERITY)).toUpperCase())); type.setLabel(typeCfg.getAttribute(ATTR_LABEL)); type.setDescription(typeCfg.getAttribute(ATTR_DESCRIPTION)); type.setValidator(validator); validator.getTypes().add(type); } validators.put(validator.getId(), validator); } @Override public boolean isEnabled(IScriptProject scriptProject) { try { if (!scriptProject.getProject().hasNature(PHPNature.ID)) { return false; } return getProjectPreferences(scriptProject).getBoolean(PreferenceConstants.ENABLED, true); } catch (CoreException e) { PEXAnalysisPlugin.error(e); return false; } } @Override public Type getType(IValidatorIdentifier identifier) { assert getValidator(identifier.validator()) != null; return getValidator(identifier.validator()).getType(identifier.type()); } @Override public ProblemSeverity getSeverity(IScriptProject scriptProject, IValidatorIdentifier identifier) { return getSeverity(scriptProject, getType(identifier)); } @Override public ProblemSeverity getSeverity(IScriptProject scriptProject, Type type) { assert type != null; if (!isEnabled(scriptProject)) { return ProblemSeverity.IGNORE; } Preferences prefs = getProjectPreferences(scriptProject).node(type.getValidator().getId()); try { return ProblemSeverity.valueOf(prefs.get(type.getId(), preferences.node(type.getValidator().getId()).get(type.getId(), type.getDefaultSeverity().toString()))); } catch (Exception e) { PEXAnalysisPlugin.error(e); return type.getDefaultSeverity(); } } private Preferences getProjectPreferences(IScriptProject project) { Preferences node = projectPreferences.node(project.getProject().getName()).node(PEXAnalysisPlugin.VALIDATORS_PREFERENCES_NODE_ID); if (node.get(PreferenceConstants.ENABLED, null) != null) { return node; } return preferences; } @Override public Validator[] getValidators() { return validators.values().toArray(new Validator[validators.size()]); } @Override public Validator[] getValidators(IScriptProject scriptProject) { if (!isEnabled(scriptProject)) { return emptyList; } Set<Validator> ret = new HashSet<Validator>(); for (Validator v : validators.values()) { boolean found = false; for (Type t : v.getTypes()) { if (!getSeverity(scriptProject, t).equals(ProblemSeverity.IGNORE)) { found = true; break; } } if (found) { ret.add(v); } } return ret.toArray(new Validator[ret.size()]); } @Override public Category[] getCategories() { return categories.values().toArray(new Category[categories.size()]); } @Override public Category getCategory(String id) { return categories.get(id); } @Override public Validator getValidator(String id) { return validators.get(id); } @Override public IValidatorFactory getValidatorFactory(Validator validator) throws CoreException { for (IConfigurationElement cfg : Platform.getExtensionRegistry().getConfigurationElementsFor(EXTENSION_ID)) { if (cfg.getName().equals(ELEMENT_VALIDATOR) && cfg.getAttribute(ATTR_ID).equals(validator.getId())) { return (IValidatorFactory) cfg.createExecutableExtension(ATTR_CLASS); } } return null; } }