/******************************************************************************* * 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 * Mathieu Rail - Added functionality for getting a module's requirements *******************************************************************************/ package org.eclipse.tracecompass.tmf.core.analysis; import java.util.Collections; import java.util.HashSet; import java.util.Set; import org.eclipse.core.runtime.ContributorFactoryOSGi; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.InvalidRegistryObjectException; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.tracecompass.internal.tmf.core.Activator; import org.eclipse.tracecompass.internal.tmf.core.analysis.TmfAnalysisModuleSourceConfigElement; import org.eclipse.tracecompass.tmf.core.analysis.requirements.TmfAbstractAnalysisRequirement; import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException; import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType; import org.eclipse.tracecompass.tmf.core.project.model.TraceTypeHelper; import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager; import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperiment; import org.osgi.framework.Bundle; /** * Analysis module helper for modules provided by a plugin's configuration * elements. * * @author Geneviève Bastien */ public class TmfAnalysisModuleHelperConfigElement implements IAnalysisModuleHelper { private final IConfigurationElement fCe; /** * Constructor * * @param ce * The source {@link IConfigurationElement} of this module helper */ public TmfAnalysisModuleHelperConfigElement(IConfigurationElement ce) { fCe = ce; } // ---------------------------------------- // Wrappers to {@link IAnalysisModule} methods // ---------------------------------------- @Override public String getId() { String id = fCe.getAttribute(TmfAnalysisModuleSourceConfigElement.ID_ATTR); if (id == null) { throw new IllegalStateException(); } return id; } @Override public String getName() { String name = fCe.getAttribute(TmfAnalysisModuleSourceConfigElement.NAME_ATTR); if (name == null) { throw new IllegalStateException(); } return name; } @Override public boolean isAutomatic() { return Boolean.parseBoolean(fCe.getAttribute(TmfAnalysisModuleSourceConfigElement.AUTOMATIC_ATTR)); } /** * @since 1.0 */ @Override public boolean appliesToExperiment() { return Boolean.parseBoolean(fCe.getAttribute(TmfAnalysisModuleSourceConfigElement.APPLIES_EXP_ATTR)); } @Override public String getHelpText() { /* * FIXME: No need to externalize this. A better solution will be found * soon and this string is just temporary */ return "The trace must be opened to get the help message"; //$NON-NLS-1$ } @Override public String getIcon() { return fCe.getAttribute(TmfAnalysisModuleSourceConfigElement.ICON_ATTR); } @Override public Bundle getBundle() { return ContributorFactoryOSGi.resolve(fCe.getContributor()); } private boolean appliesToTraceClass(Class<? extends ITmfTrace> traceclass) { boolean applies = false; /* Get the module's applying tracetypes */ final IConfigurationElement[] tracetypeCE = fCe.getChildren(TmfAnalysisModuleSourceConfigElement.TRACETYPE_ELEM); for (IConfigurationElement element : tracetypeCE) { Class<?> applyclass; try { applyclass = getBundle().loadClass(element.getAttribute(TmfAnalysisModuleSourceConfigElement.CLASS_ATTR)); String classAppliesVal = element.getAttribute(TmfAnalysisModuleSourceConfigElement.APPLIES_ATTR); boolean classApplies = true; if (classAppliesVal != null) { classApplies = Boolean.parseBoolean(classAppliesVal); } if (classApplies) { applies |= applyclass.isAssignableFrom(traceclass); } else { /* * If the trace type does not apply, reset the applies * variable to false */ if (applyclass.isAssignableFrom(traceclass)) { applies = false; } } } catch (ClassNotFoundException | InvalidRegistryObjectException e) { Activator.logError("Error in applies to trace", e); //$NON-NLS-1$ } } return applies; } @Override public boolean appliesToTraceType(Class<? extends ITmfTrace> traceclass) { boolean applies = appliesToTraceClass(traceclass); /* Check if it applies to an experiment */ if (!applies && TmfExperiment.class.isAssignableFrom(traceclass)) { applies = appliesToExperiment(); } return applies; } @Override public Iterable<Class<? extends ITmfTrace>> getValidTraceTypes() { Set<Class<? extends ITmfTrace>> traceTypes = new HashSet<>(); for (TraceTypeHelper tth : TmfTraceType.getTraceTypeHelpers()) { if (appliesToTraceType(tth.getTraceClass())) { traceTypes.add(tth.getTraceClass()); } } return traceTypes; } @Override public Iterable<TmfAbstractAnalysisRequirement> getAnalysisRequirements() { IAnalysisModule module = createModule(); if (module != null) { Iterable<@NonNull TmfAbstractAnalysisRequirement> requirements = module.getAnalysisRequirements(); module.dispose(); return requirements; } return Collections.EMPTY_SET; } // --------------------------------------- // Functionalities // --------------------------------------- private IAnalysisModule createModule() { IAnalysisModule module = null; try { module = (IAnalysisModule) fCe.createExecutableExtension(TmfAnalysisModuleSourceConfigElement.ANALYSIS_MODULE_ATTR); module.setName(getName()); module.setId(getId()); } catch (CoreException e) { Activator.logError("Error getting analysis modules from configuration files", e); //$NON-NLS-1$ } return module; } @Override public IAnalysisModule newModule(ITmfTrace trace) throws TmfAnalysisException { /* Check if it applies to trace itself */ boolean applies = appliesToTraceClass(trace.getClass()); /* * If the trace is an experiment, check if this module would apply to an * experiment should it apply to one of its traces. */ if (!applies && (trace instanceof TmfExperiment) && appliesToExperiment()) { for (ITmfTrace expTrace : TmfTraceManager.getTraceSet(trace)) { if (appliesToTraceClass(expTrace.getClass())) { applies = true; break; } } } if (!applies) { return null; } IAnalysisModule module = createModule(); if (module == null) { return null; } module.setAutomatic(isAutomatic()); /* Get the module's parameters */ final IConfigurationElement[] parametersCE = fCe.getChildren(TmfAnalysisModuleSourceConfigElement.PARAMETER_ELEM); for (IConfigurationElement element : parametersCE) { String paramName = element.getAttribute(TmfAnalysisModuleSourceConfigElement.NAME_ATTR); if (paramName == null) { continue; } module.addParameter(paramName); String defaultValue = element.getAttribute(TmfAnalysisModuleSourceConfigElement.DEFAULT_VALUE_ATTR); if (defaultValue != null) { module.setParameter(paramName, defaultValue); } } if (module.setTrace(trace)) { TmfAnalysisManager.analysisModuleCreated(module); } else { module.dispose(); module = null; } return module; } @Override public String getHelpText(@NonNull ITmfTrace trace) { IAnalysisModule module = createModule(); if (module != null) { String ret = module.getHelpText(trace); module.dispose(); return ret; } return getHelpText(); } }