/**
* Copyright (c) 2011 Stefan Henss.
* 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
*
* Contributors:
* Stefan Henss - initial API and implementation.
* Olav Lenz - externalize Strings.
*/
package org.eclipse.recommenders.internal.apidocs.rcp;
import static java.text.MessageFormat.format;
import static org.eclipse.recommenders.internal.apidocs.rcp.ApidocsViewUtils.*;
import static org.eclipse.recommenders.utils.Bags.newHashMultiset;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import javax.inject.Inject;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.ILocalVariable;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeRoot;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.recommenders.apidocs.ClassSelfCallsModelProvider;
import org.eclipse.recommenders.apidocs.ClassSelfcallDirectives;
import org.eclipse.recommenders.apidocs.MethodSelfCallsDirectivesModelProvider;
import org.eclipse.recommenders.apidocs.MethodSelfcallDirectives;
import org.eclipse.recommenders.apidocs.rcp.ApidocProvider;
import org.eclipse.recommenders.apidocs.rcp.JavaSelectionSubscriber;
import org.eclipse.recommenders.internal.apidocs.rcp.l10n.Messages;
import org.eclipse.recommenders.models.IInputStreamTransformer;
import org.eclipse.recommenders.models.IModelIndex;
import org.eclipse.recommenders.models.IModelRepository;
import org.eclipse.recommenders.models.UniqueMethodName;
import org.eclipse.recommenders.models.UniqueTypeName;
import org.eclipse.recommenders.models.rcp.IProjectCoordinateProvider;
import org.eclipse.recommenders.rcp.JavaElementResolver;
import org.eclipse.recommenders.rcp.JavaElementSelectionEvent;
import org.eclipse.recommenders.rcp.utils.JdtUtils;
import org.eclipse.recommenders.utils.Bags;
import org.eclipse.recommenders.utils.names.IMethodName;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import com.google.common.collect.Multiset;
import com.google.common.eventbus.EventBus;
public final class SelfCallsProvider extends ApidocProvider {
private final JavaElementResolver resolver;
private final IProjectCoordinateProvider pcProvider;
private final EventBus workspaceBus;
private final ClassSelfCallsModelProvider cStore;
private final MethodSelfCallsDirectivesModelProvider mStore;
@Inject
public SelfCallsProvider(JavaElementResolver resolver, IProjectCoordinateProvider pcProvider,
EventBus workspaceBus, IModelRepository modelRepo, IModelIndex modelIndex,
Map<String, IInputStreamTransformer> transformers) {
this.resolver = resolver;
this.pcProvider = pcProvider;
this.workspaceBus = workspaceBus;
mStore = new MethodSelfCallsDirectivesModelProvider(modelRepo, modelIndex, transformers);
cStore = new ClassSelfCallsModelProvider(modelRepo, modelIndex, transformers);
}
@JavaSelectionSubscriber
public void onTypeRootSelection(final ITypeRoot root, final JavaElementSelectionEvent event, final Composite parent)
throws ExecutionException {
final IType type = root.findPrimaryType();
if (type != null) {
onTypeSelection(type, event, parent);
}
}
@JavaSelectionSubscriber
public void onVariableSelection(ILocalVariable var, JavaElementSelectionEvent event, Composite parent)
throws ExecutionException {
IType type = ApidocsViewUtils.findType(var).orNull();
if (type != null) {
onTypeSelection(type, event, parent);
}
}
@JavaSelectionSubscriber
public void onVariableSelection(IField var, JavaElementSelectionEvent event, Composite parent)
throws ExecutionException, JavaModelException {
IType type = ApidocsViewUtils.findType(var).orNull();
if (type != null) {
onTypeSelection(type, event, parent);
}
}
@JavaSelectionSubscriber
public void onTypeSelection(final IType type, final JavaElementSelectionEvent event, final Composite parent)
throws ExecutionException {
UniqueTypeName name = pcProvider.toUniqueName(type).orNull();
ClassSelfcallDirectives model = cStore.acquireModel(name).orNull();
try {
if (model != null) {
runSyncInUiThread(new TypeSelfcallDirectivesRenderer(type, model, parent));
}
} finally {
cStore.releaseModel(model);
}
}
@JavaSelectionSubscriber
public void onMethodSelection(final IMethod method, final JavaElementSelectionEvent event, final Composite parent) {
for (IMethod current = method; current != null; current = JdtUtils.findOverriddenMethod(current).orNull()) {
UniqueMethodName name = pcProvider.toUniqueName(current).orNull();
MethodSelfcallDirectives selfcalls = mStore.acquireModel(name).orNull();
try {
if (selfcalls != null) {
runSyncInUiThread(new MethodSelfcallDirectivesRenderer(method, selfcalls, parent));
}
} finally {
mStore.releaseModel(selfcalls);
}
}
}
private class TypeSelfcallDirectivesRenderer implements Runnable {
private final IType type;
private final ClassSelfcallDirectives directive;
private final Composite parent;
private Composite container;
public TypeSelfcallDirectivesRenderer(final IType type, final ClassSelfcallDirectives selfcalls,
final Composite parent) {
this.type = type;
directive = selfcalls;
this.parent = parent;
}
@Override
public void run() {
createContainer();
addHeader();
addDirectives();
}
private void createContainer() {
container = new Composite(parent, SWT.NONE);
setInfoBackgroundColor(container);
container.setLayout(new GridLayout());
}
private void addHeader() {
final String message = format(Messages.PROVIDER_INTRO_SUBCLASS_SELFCALL_STATISTICS,
directive.getNumberOfSubclasses(), type.getElementName());
createLabel(container, message, true);
}
private void addDirectives() {
final int numberOfSubclasses = directive.getNumberOfSubclasses();
final Multiset<IMethodName> b = Bags.newHashMultiset(directive.getCalls());
renderMethodDirectivesBlock(container, b, numberOfSubclasses, workspaceBus, resolver,
Messages.TABLE_CELL_RELATION_CALL);
}
}
private class MethodSelfcallDirectivesRenderer implements Runnable {
private final IMethod method;
private final MethodSelfcallDirectives directive;
private final Composite parent;
private Composite container;
public MethodSelfcallDirectivesRenderer(final IMethod method, final MethodSelfcallDirectives selfcalls,
final Composite parent) {
this.method = method;
directive = selfcalls;
this.parent = parent;
}
@Override
public void run() {
createContainer();
addHeader();
addDirectives();
}
private void createContainer() {
container = new Composite(parent, SWT.NONE);
setInfoBackgroundColor(container);
container.setLayout(new GridLayout());
}
private void addHeader() {
final String message = format(Messages.PROVIDER_INTRO_IMPLEMENTOR_SELFCALL_STATISTIC,
directive.getNumberOfDefinitions(), method.getElementName());
createLabel(container, message, true);
}
private void addDirectives() {
final int numberOfSubclasses = directive.getNumberOfDefinitions();
final Multiset<IMethodName> b = newHashMultiset(directive.getCalls());
renderMethodDirectivesBlock(container, b, numberOfSubclasses, workspaceBus, resolver,
Messages.TABLE_CELL_RELATION_CALL);
}
}
}