blob: edae16b0a0043a699fc74737d488262a2efd02e9 [file] [log] [blame]
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.featureStatistics;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.Pair;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.TestOnly;
import java.io.IOException;
import java.net.URL;
import java.util.*;
public class ProductivityFeaturesRegistryImpl extends ProductivityFeaturesRegistry {
private static final Logger LOG = Logger.getInstance("#com.intellij.featureStatistics.ProductivityFeaturesRegistry");
private final Map<String, FeatureDescriptor> myFeatures = new HashMap<String, FeatureDescriptor>();
private final Map<String, GroupDescriptor> myGroups = new HashMap<String, GroupDescriptor>();
private final List<Pair<String, ApplicabilityFilter>> myApplicabilityFilters = new ArrayList<Pair<String,ApplicabilityFilter>>();
private boolean myAdditionalFeaturesLoaded = false;
@NonNls public static final String WELCOME = "features.welcome";
@NonNls private static final String TAG_FILTER = "filter";
@NonNls private static final String TAG_GROUP = "group";
@NonNls private static final String TAG_FEATURE = "feature";
@NonNls private static final String TODO_HTML_MARKER = "todo.html";
@NonNls private static final String CLASS_ATTR = "class";
@NonNls private static final String PREFIX_ATTR = "prefix";
public ProductivityFeaturesRegistryImpl() {
reloadFromXml();
}
private void reloadFromXml() {
try {
readFromXml("file:///ProductivityFeaturesRegistry.xml");
}
catch (Exception e) {
if (!ApplicationManager.getApplication().isUnitTestMode()) {
LOG.error(e);
}
}
try {
readFromXml("file:///IdeSpecificFeatures.xml");
}
catch (Exception e) {// ignore
}
}
private void readFromXml(String path) throws JDOMException, IOException {
final Document document = JDOMUtil.loadResourceDocument(new URL(path));
final Element root = document.getRootElement();
readGroups(root);
readFilters(root);
}
private void lazyLoadFromPluginsFeaturesProviders() {
if (myAdditionalFeaturesLoaded) return;
loadFeaturesFromProviders(ApplicationManager.getApplication().getComponents(ProductivityFeaturesProvider.class));
loadFeaturesFromProviders(Extensions.getExtensions(ProductivityFeaturesProvider.EP_NAME));
myAdditionalFeaturesLoaded = true;
}
private void loadFeaturesFromProviders(ProductivityFeaturesProvider[] providers) {
for (ProductivityFeaturesProvider provider : providers) {
final GroupDescriptor[] groupDescriptors = provider.getGroupDescriptors();
if (groupDescriptors != null) {
for (GroupDescriptor groupDescriptor : groupDescriptors) {
myGroups.put(groupDescriptor.getId(), groupDescriptor);
}
}
final FeatureDescriptor[] featureDescriptors = provider.getFeatureDescriptors();
if (featureDescriptors != null) {
for (FeatureDescriptor featureDescriptor : featureDescriptors) {
final FeatureDescriptor featureLoadedStatistics = myFeatures.get(featureDescriptor.getId());
if (featureLoadedStatistics != null) {
featureDescriptor.copyStatistics(featureLoadedStatistics);
}
myFeatures.put(featureDescriptor.getId(), featureDescriptor);
}
}
final ApplicabilityFilter[] applicabilityFilters = provider.getApplicabilityFilters();
if (applicabilityFilters != null) {
for (ApplicabilityFilter applicabilityFilter : applicabilityFilters) {
myApplicabilityFilters.add(Pair.create(applicabilityFilter.getPrefix(), applicabilityFilter));
}
}
}
}
private void readFilters(Element element) {
List filters = element.getChildren(TAG_FILTER);
for (Object filter1 : filters) {
Element filterElement = (Element)filter1;
String className = filterElement.getAttributeValue(CLASS_ATTR);
try {
Class klass = Class.forName(className);
if (!ApplicabilityFilter.class.isAssignableFrom(klass)) {
LOG.error("filter class must implement com.intellij.featureSatistics.ApplicabilityFilter");
continue;
}
ApplicabilityFilter filter = (ApplicabilityFilter)klass.newInstance();
myApplicabilityFilters.add(Pair.create(filterElement.getAttributeValue(PREFIX_ATTR), filter));
}
catch (Exception e) {
LOG.error("Cannot instantiate filter " + className, e);
}
}
}
private void readGroups(Element element) {
List groups = element.getChildren(TAG_GROUP);
for (Object group : groups) {
Element groupElement = (Element)group;
readGroup(groupElement);
}
}
private void readGroup(Element groupElement) {
GroupDescriptor groupDescriptor = new GroupDescriptor();
groupDescriptor.readExternal(groupElement);
String groupId = groupDescriptor.getId();
myGroups.put(groupId, groupDescriptor);
readFeatures(groupElement, groupDescriptor);
}
private void readFeatures(Element groupElement, GroupDescriptor groupDescriptor) {
List features = groupElement.getChildren(TAG_FEATURE);
for (Object feature : features) {
Element featureElement = (Element)feature;
FeatureDescriptor featureDescriptor = new FeatureDescriptor(groupDescriptor);
featureDescriptor.readExternal(featureElement);
if (!TODO_HTML_MARKER.equals(featureDescriptor.getTipFileName())) {
myFeatures.put(featureDescriptor.getId(), featureDescriptor);
}
}
}
@NotNull
public Set<String> getFeatureIds() {
lazyLoadFromPluginsFeaturesProviders();
return myFeatures.keySet();
}
public FeatureDescriptor getFeatureDescriptor(@NotNull String id) {
lazyLoadFromPluginsFeaturesProviders();
return getFeatureDescriptorEx(id);
}
public FeatureDescriptor getFeatureDescriptorEx(@NotNull String id) {
if (WELCOME.equals(id)) {
return new FeatureDescriptor(WELCOME, "AdaptiveWelcome.html", FeatureStatisticsBundle.message("feature.statistics.welcome.tip.name"));
}
return myFeatures.get(id);
}
public GroupDescriptor getGroupDescriptor(@NotNull String id) {
lazyLoadFromPluginsFeaturesProviders();
return myGroups.get(id);
}
@NotNull
public ApplicabilityFilter[] getMatchingFilters(@NotNull String featureId) {
lazyLoadFromPluginsFeaturesProviders();
List<ApplicabilityFilter> filters = new ArrayList<ApplicabilityFilter>();
for (Pair<String, ApplicabilityFilter> pair : myApplicabilityFilters) {
if (featureId.startsWith(pair.getFirst())) {
filters.add(pair.getSecond());
}
}
return filters.toArray(new ApplicabilityFilter[filters.size()]);
}
@Override
public String toString() {
return super.toString() + "; myAdditionalFeaturesLoaded="+myAdditionalFeaturesLoaded;
}
@TestOnly
public void prepareForTest() {
myAdditionalFeaturesLoaded = false;
myFeatures.clear();
myApplicabilityFilters.clear();
myGroups.clear();
reloadFromXml();
}
}