/*******************************************************************************
* Copyright (c) 2013, 2014 École Polytechnique de Montréal
*
* 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:
* Geneviève Bastien - Initial API and implementation
*******************************************************************************/
package fr.inria.linuxtools.tmf.core.analysis;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import fr.inria.linuxtools.internal.tmf.core.Activator;
import fr.inria.linuxtools.internal.tmf.core.analysis.TmfAnalysisModuleSources;
import fr.inria.linuxtools.tmf.core.trace.ITmfTrace;
/**
* Manages the available analysis helpers from different sources and their
* parameter providers.
*
* @author Geneviève Bastien
* @since 3.0
*/
public class TmfAnalysisManager {
private static final Map<String, IAnalysisModuleHelper> fAnalysisModules = new HashMap<>();
private static final Map<String, List<Class<? extends IAnalysisParameterProvider>>> fParameterProviders = new HashMap<>();
private static final Map<Class<? extends IAnalysisParameterProvider>, IAnalysisParameterProvider> fParamProviderInstances = new HashMap<>();
private static final List<IAnalysisModuleSource> fSources = new ArrayList<>();
private static final List<ITmfNewAnalysisModuleListener> fListeners = new ArrayList<>();
/**
* Registers a new source of modules
*
* @param source
* A {@link IAnalysisModuleSource} instance
*/
public static synchronized void registerModuleSource(IAnalysisModuleSource source) {
fSources.add(source);
refreshModules();
}
/**
* Initializes sources and new module listeners from the extension point
*/
public static synchronized void initialize() {
fSources.clear();
fListeners.clear();
initializeModuleSources();
initializeNewModuleListeners();
}
/**
* Cleans the module sources list and initialize it from the extension point
*/
private static synchronized void initializeModuleSources() {
for (IAnalysisModuleSource source : TmfAnalysisModuleSources.getSources()) {
fSources.add(source);
}
}
/**
* Cleans the new module listeners list and initialize it from the extension
* point
*/
private static synchronized void initializeNewModuleListeners() {
for (ITmfNewAnalysisModuleListener output : TmfAnalysisModuleOutputs.getOutputListeners()) {
fListeners.add(output);
}
}
/**
* Add a new module listener to the list of listeners
*
* @param listener
* The new module listener
*/
public static synchronized void addNewModuleListener(ITmfNewAnalysisModuleListener listener) {
fListeners.add(listener);
}
/**
* Gets all available analysis module helpers
*
* This map is read-only
*
* @return The map of available {@link IAnalysisModuleHelper}
*/
public static synchronized Map<String, IAnalysisModuleHelper> getAnalysisModules() {
if (fAnalysisModules.isEmpty()) {
for (IAnalysisModuleSource source : fSources) {
for (IAnalysisModuleHelper helper : source.getAnalysisModules()) {
fAnalysisModules.put(helper.getId(), helper);
}
}
}
return Collections.unmodifiableMap(fAnalysisModules);
}
/**
* Gets all analysis module helpers that apply to a given trace type
*
* This map is read-only
*
* @param traceclass
* The trace class to get modules for
* @return The map of available {@link IAnalysisModuleHelper}
*/
public static Map<String, IAnalysisModuleHelper> getAnalysisModules(Class<? extends ITmfTrace> traceclass) {
Map<String, IAnalysisModuleHelper> allModules = getAnalysisModules();
Map<String, IAnalysisModuleHelper> map = new HashMap<>();
for (IAnalysisModuleHelper module : allModules.values()) {
if (module.appliesToTraceType(traceclass)) {
map.put(module.getId(), module);
}
}
return Collections.unmodifiableMap(map);
}
/**
* Gets an analysis module helper identified by an id
*
* @param id
* Id of the analysis module to get
* @return The {@link IAnalysisModuleHelper}
*/
public static IAnalysisModuleHelper getAnalysisModule(String id) {
Map<String, IAnalysisModuleHelper> map = getAnalysisModules();
return map.get(id);
}
/**
* Register a new parameter provider for an analysis
*
* @param analysisId
* The id of the analysis
* @param paramProvider
* The class of the parameter provider
*/
public static void registerParameterProvider(String analysisId, Class<? extends IAnalysisParameterProvider> paramProvider) {
synchronized (fParameterProviders) {
if (!fParameterProviders.containsKey(analysisId)) {
fParameterProviders.put(analysisId, new ArrayList<Class<? extends IAnalysisParameterProvider>>());
}
fParameterProviders.get(analysisId).add(paramProvider);
}
}
/**
* Get a parameter provider that applies to the requested trace
*
* @param module
* Analysis module
* @param trace
* The trace
* @return A parameter provider if one applies to the trace, null otherwise
*/
public static List<IAnalysisParameterProvider> getParameterProviders(IAnalysisModule module, ITmfTrace trace) {
List<IAnalysisParameterProvider> providerList = new ArrayList<>();
synchronized (fParameterProviders) {
if (!fParameterProviders.containsKey(module.getId())) {
return providerList;
}
for (Class<? extends IAnalysisParameterProvider> providerClass : fParameterProviders.get(module.getId())) {
try {
IAnalysisParameterProvider provider = fParamProviderInstances.get(providerClass);
if (provider == null) {
provider = providerClass.newInstance();
fParamProviderInstances.put(providerClass, provider);
}
if (provider != null) {
if (provider.appliesToTrace(trace)) {
providerList.add(provider);
}
}
} catch (IllegalArgumentException e) {
Activator.logError(Messages.TmfAnalysisManager_ErrorParameterProvider, e);
} catch (SecurityException e) {
Activator.logError(Messages.TmfAnalysisManager_ErrorParameterProvider, e);
} catch (InstantiationException e) {
Activator.logError(Messages.TmfAnalysisManager_ErrorParameterProvider, e);
} catch (IllegalAccessException e) {
Activator.logError(Messages.TmfAnalysisManager_ErrorParameterProvider, e);
}
}
}
return providerList;
}
/**
* Clear the list of modules so that next time, it is computed again from
* sources
*/
public static synchronized void refreshModules() {
fAnalysisModules.clear();
}
/**
* This method should be called when new analysis modules have been created
* by module helpers to that the {@link ITmfNewAnalysisModuleListener} can
* be executed on the module instance.
*
* @param module
* The newly created analysis module
*/
public static synchronized void analysisModuleCreated(IAnalysisModule module) {
for (ITmfNewAnalysisModuleListener listener : fListeners) {
listener.moduleCreated(module);
}
}
}