/*
* Copyright 2005-2016 Bas Leijdekkers, Sixth and Red River Software
*
* 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.sixrr.stockmetrics.execution;
import com.intellij.analysis.AnalysisScope;
import com.intellij.ide.highlighter.JavaFileType;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.progress.EmptyProgressIndicator;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiJavaFile;
import com.intellij.psi.PsiManager;
import com.intellij.util.Processor;
import com.sixrr.metrics.Metric;
import com.sixrr.metrics.MetricCalculator;
import com.sixrr.metrics.MetricsExecutionContext;
import com.sixrr.metrics.MetricsResultsHolder;
import com.sixrr.stockmetrics.dependency.DependencyMap;
import com.sixrr.stockmetrics.dependency.DependencyMapImpl;
import com.sixrr.stockmetrics.dependency.DependentsMap;
import com.sixrr.stockmetrics.i18n.StockMetricsBundle;
import com.sixrr.stockmetrics.metricModel.BaseMetric;
public abstract class BaseMetricsCalculator implements MetricCalculator {
private static final Key<DependencyMapImpl> dependencyMapKey = new Key<DependencyMapImpl>("dependencyMap");
protected Metric metric = null;
protected MetricsResultsHolder resultsHolder = null;
protected MetricsExecutionContext executionContext = null;
private PsiElementVisitor visitor;
@Override
public void beginMetricsRun(Metric metric, MetricsResultsHolder resultsHolder,
MetricsExecutionContext executionContext) {
this.metric = metric;
this.resultsHolder = resultsHolder;
this.executionContext = executionContext;
if (((BaseMetric)metric).requiresDependents() && getDependencyMap() == null) {
calculateDependencies();
}
visitor = createVisitor();
}
@Override
public void processFile(final PsiFile file) {
ProgressManager.getInstance().runProcess(new Runnable() {
@Override
public void run() {
file.accept(visitor);
}
}, new EmptyProgressIndicator());
}
protected abstract PsiElementVisitor createVisitor();
@Override
public void endMetricsRun() {}
public DependencyMap getDependencyMap() {
return executionContext.getUserData(dependencyMapKey);
}
public DependentsMap getDependentsMap() {
return executionContext.getUserData(dependencyMapKey);
}
private void calculateDependencies() {
final DependencyMapImpl dependencyMap = new DependencyMapImpl();
final ProgressManager progressManager = ProgressManager.getInstance();
final ProgressIndicator progressIndicator = progressManager.getProgressIndicator();
final Project project = executionContext.getProject();
final AnalysisScope analysisScope = new AnalysisScope(project);
final int allFilesCount = analysisScope.getFileCount();
final PsiManager psiManager = PsiManager.getInstance(project);
final Application application = ApplicationManager.getApplication();
analysisScope.accept(new Processor<VirtualFile>() {
private int dependencyProgress = 0;
@Override
public boolean process(VirtualFile virtualFile) {
final String fileName = virtualFile.getName();
progressIndicator.setText(
StockMetricsBundle.message("building.dependency.structure.progress.string", fileName));
progressIndicator.setFraction((double) dependencyProgress / (double) allFilesCount);
dependencyProgress++;
if (virtualFile.getFileType() != JavaFileType.INSTANCE) {
return true;
}
final AccessToken token = application.acquireReadActionLock();
try {
final PsiFile file = psiManager.findFile(virtualFile);
if (!(file instanceof PsiJavaFile)) {
return true;
}
dependencyMap.build(file);
} finally {
token.finish();
}
return true;
}
});
executionContext.putUserData(dependencyMapKey, dependencyMap);
}
}