From c068a7522bd817c7e0e3ca953ae2b8e81067d11b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Genevi=C3=A8ve=20Bastien?= Date: Mon, 15 Jul 2013 14:55:41 -0400 Subject: [PATCH] TMF: Introduce a framework to hook trace analysis modules/plugins MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit * Add a new extension point to define trace analysis modules. * Add new interface IAnalysisModule and abstract class TmfAbstractAnalysisModule to implement the analysis itself. * TmfAnalysisManager is the main class to obtain which analysis are available to a trace. * IAnalysisOutput interface describe the different outputs the analysis can provide. Objects of classes implementing this interface can register to an analysis module. * The IAnalysisParameterProvider allows other parts of the system to set an analysis' parameters. * Analysis are executed as Eclipse jobs. * On the UI side, analysis and their provided outputs (if any) are now children of the trace and can be directly opened. * Unit tests in tmf.core and tmf.ui provide stub analysis. Change-Id: Ie0d0fa9b726555b6416829c1c49e44301297d11b Signed-off-by: Geneviève Bastien Reviewed-on: https://git.eclipse.org/r/14935 Tested-by: Hudson CI Reviewed-by: Patrick Tasse IP-Clean: Patrick Tasse --- .../build.properties | 3 +- .../plugin.xml | 42 ++ .../tmf/core/tests/AllTmfCoreTests.java | 1 + .../tmf/core/tests/analysis/AllTests.java | 29 ++ .../tests/analysis/AnalysisManagerTest.java | 92 +++++ .../analysis/AnalysisModuleHelperTest.java | 216 ++++++++++ .../tests/analysis/AnalysisModuleTest.java | 233 +++++++++++ .../AnalysisParameterProviderTest.java | 81 ++++ .../tests/stubs/analysis/TestAnalysis.java | 91 ++++ .../TestAnalysisParameterProvider.java | 59 +++ .../tests/stubs/analysis/TestCtfAnalysis.java | 41 ++ .../META-INF/MANIFEST.MF | 2 + .../build.properties | 3 +- org.eclipse.linuxtools.tmf.core/plugin.xml | 2 +- ....eclipse.linuxtools.tmf.core.analysis.exsd | 217 ++++++++++ .../tmf/core/analysis/TmfAnalysisType.java | 135 ++++++ .../tmf/core/analysis/IAnalysisModule.java | 240 +++++++++++ .../core/analysis/IAnalysisModuleHelper.java | 109 +++++ .../tmf/core/analysis/IAnalysisOutput.java | 37 ++ .../analysis/IAnalysisParameterProvider.java | 67 +++ .../tmf/core/analysis/Messages.java | 58 +++ .../analysis/TmfAbstractAnalysisModule.java | 388 ++++++++++++++++++ .../TmfAbstractAnalysisParamProvider.java | 58 +++ .../tmf/core/analysis/TmfAnalysisManager.java | 148 +++++++ .../analysis/TmfAnalysisModuleHelperCE.java | 145 +++++++ .../tmf/core/analysis/messages.properties | 9 + .../core/exceptions/TmfAnalysisException.java | 47 +++ .../core/signal/TmfStartAnalysisSignal.java | 54 +++ .../linuxtools/tmf/core/trace/ITmfTrace.java | 31 ++ .../linuxtools/tmf/core/trace/TmfTrace.java | 57 +++ .../plugin.xml | 23 +- .../tmf/ui/tests/project/model/AllTests.java | 6 +- .../model/ProjectModelAnalysisTest.java | 165 ++++++++ .../project/model/ProjectModelOutputTest.java | 161 ++++++++ .../project/model/ProjectModelTestData.java | 31 +- .../project/model/ProjectModelTraceTest.java | 12 +- .../tests/stubs/analysis/TestAnalysisUi.java | 62 +++ .../META-INF/MANIFEST.MF | 1 + .../plugin.properties | 7 +- org.eclipse.linuxtools.tmf.ui/plugin.xml | 67 +++ .../tmf/ui/project/handlers/Messages.java | 2 + .../tmf/ui/project/handlers/OpenAction.java | 9 +- .../handlers/OpenAnalysisHelpHandler.java | 114 +++++ .../handlers/OpenAnalysisOutputHandler.java | 89 ++++ .../ui/project/handlers/messages.properties | 3 + .../ui/analysis/TmfAnalysisViewOutput.java | 83 ++++ .../tmf/ui/project/model/Messages.java | 9 + .../ui/project/model/TmfAnalysisElement.java | 178 ++++++++ .../model/TmfAnalysisOutputElement.java | 81 ++++ .../project/model/TmfExperimentElement.java | 17 + .../model/TmfNavigatorContentProvider.java | 51 ++- .../model/TmfNavigatorLabelProvider.java | 28 ++ .../tmf/ui/project/model/TmfTraceElement.java | 91 ++++ .../tmf/ui/project/model/TraceTypeHelper.java | 10 + .../tmf/ui/project/model/messages.properties | 5 +- 55 files changed, 3962 insertions(+), 38 deletions(-) create mode 100644 org.eclipse.linuxtools.tmf.core.tests/plugin.xml create mode 100644 org.eclipse.linuxtools.tmf.core.tests/src/org/eclipse/linuxtools/tmf/core/tests/analysis/AllTests.java create mode 100644 org.eclipse.linuxtools.tmf.core.tests/src/org/eclipse/linuxtools/tmf/core/tests/analysis/AnalysisManagerTest.java create mode 100644 org.eclipse.linuxtools.tmf.core.tests/src/org/eclipse/linuxtools/tmf/core/tests/analysis/AnalysisModuleHelperTest.java create mode 100644 org.eclipse.linuxtools.tmf.core.tests/src/org/eclipse/linuxtools/tmf/core/tests/analysis/AnalysisModuleTest.java create mode 100644 org.eclipse.linuxtools.tmf.core.tests/src/org/eclipse/linuxtools/tmf/core/tests/analysis/AnalysisParameterProviderTest.java create mode 100644 org.eclipse.linuxtools.tmf.core.tests/stubs/org/eclipse/linuxtools/tmf/tests/stubs/analysis/TestAnalysis.java create mode 100644 org.eclipse.linuxtools.tmf.core.tests/stubs/org/eclipse/linuxtools/tmf/tests/stubs/analysis/TestAnalysisParameterProvider.java create mode 100644 org.eclipse.linuxtools.tmf.core.tests/stubs/org/eclipse/linuxtools/tmf/tests/stubs/analysis/TestCtfAnalysis.java create mode 100644 org.eclipse.linuxtools.tmf.core/schema/org.eclipse.linuxtools.tmf.core.analysis.exsd create mode 100644 org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/analysis/TmfAnalysisType.java create mode 100644 org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/IAnalysisModule.java create mode 100644 org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/IAnalysisModuleHelper.java create mode 100644 org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/IAnalysisOutput.java create mode 100644 org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/IAnalysisParameterProvider.java create mode 100644 org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/Messages.java create mode 100644 org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/TmfAbstractAnalysisModule.java create mode 100644 org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/TmfAbstractAnalysisParamProvider.java create mode 100644 org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/TmfAnalysisManager.java create mode 100644 org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/TmfAnalysisModuleHelperCE.java create mode 100644 org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/messages.properties create mode 100644 org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/exceptions/TmfAnalysisException.java create mode 100644 org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/signal/TmfStartAnalysisSignal.java create mode 100644 org.eclipse.linuxtools.tmf.ui.tests/src/org/eclipse/linuxtools/tmf/ui/tests/project/model/ProjectModelAnalysisTest.java create mode 100644 org.eclipse.linuxtools.tmf.ui.tests/src/org/eclipse/linuxtools/tmf/ui/tests/project/model/ProjectModelOutputTest.java create mode 100644 org.eclipse.linuxtools.tmf.ui.tests/widgetStubs/org/eclipse/linuxtools/tmf/ui/tests/stubs/analysis/TestAnalysisUi.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/handlers/OpenAnalysisHelpHandler.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/handlers/OpenAnalysisOutputHandler.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/analysis/TmfAnalysisViewOutput.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TmfAnalysisElement.java create mode 100644 org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TmfAnalysisOutputElement.java diff --git a/org.eclipse.linuxtools.tmf.core.tests/build.properties b/org.eclipse.linuxtools.tmf.core.tests/build.properties index 30e33a7a35..5abbb1ff8f 100644 --- a/org.eclipse.linuxtools.tmf.core.tests/build.properties +++ b/org.eclipse.linuxtools.tmf.core.tests/build.properties @@ -17,5 +17,6 @@ output.. = bin/ bin.includes = META-INF/,\ .,\ plugin.properties,\ - testfiles/ + testfiles/,\ + plugin.xml src.includes = about.html diff --git a/org.eclipse.linuxtools.tmf.core.tests/plugin.xml b/org.eclipse.linuxtools.tmf.core.tests/plugin.xml new file mode 100644 index 0000000000..d280c639b9 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.core.tests/plugin.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.eclipse.linuxtools.tmf.core.tests/src/org/eclipse/linuxtools/tmf/core/tests/AllTmfCoreTests.java b/org.eclipse.linuxtools.tmf.core.tests/src/org/eclipse/linuxtools/tmf/core/tests/AllTmfCoreTests.java index 35b2945950..2e6b9f5c5f 100644 --- a/org.eclipse.linuxtools.tmf.core.tests/src/org/eclipse/linuxtools/tmf/core/tests/AllTmfCoreTests.java +++ b/org.eclipse.linuxtools.tmf.core.tests/src/org/eclipse/linuxtools/tmf/core/tests/AllTmfCoreTests.java @@ -22,6 +22,7 @@ import org.junit.runners.Suite; @RunWith(Suite.class) @Suite.SuiteClasses({ TmfCorePluginTest.class, + org.eclipse.linuxtools.tmf.core.tests.analysis.AllTests.class, org.eclipse.linuxtools.tmf.core.tests.component.AllTests.class, org.eclipse.linuxtools.tmf.core.tests.ctfadaptor.AllTests.class, org.eclipse.linuxtools.tmf.core.tests.event.AllTests.class, diff --git a/org.eclipse.linuxtools.tmf.core.tests/src/org/eclipse/linuxtools/tmf/core/tests/analysis/AllTests.java b/org.eclipse.linuxtools.tmf.core.tests/src/org/eclipse/linuxtools/tmf/core/tests/analysis/AllTests.java new file mode 100644 index 0000000000..27d2ff8b72 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.core.tests/src/org/eclipse/linuxtools/tmf/core/tests/analysis/AllTests.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2013 É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 org.eclipse.linuxtools.tmf.core.tests.analysis; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +/** + * Unit tests for the analysis package. + */ +@RunWith(Suite.class) +@Suite.SuiteClasses({ + AnalysisModuleTest.class, + AnalysisManagerTest.class, + AnalysisParameterProviderTest.class +}) +public class AllTests { + +} diff --git a/org.eclipse.linuxtools.tmf.core.tests/src/org/eclipse/linuxtools/tmf/core/tests/analysis/AnalysisManagerTest.java b/org.eclipse.linuxtools.tmf.core.tests/src/org/eclipse/linuxtools/tmf/core/tests/analysis/AnalysisManagerTest.java new file mode 100644 index 0000000000..4731ed060c --- /dev/null +++ b/org.eclipse.linuxtools.tmf.core.tests/src/org/eclipse/linuxtools/tmf/core/tests/analysis/AnalysisManagerTest.java @@ -0,0 +1,92 @@ +/******************************************************************************* + * Copyright (c) 2013 É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 org.eclipse.linuxtools.tmf.core.tests.analysis; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeTrue; + +import java.util.Map; + +import org.eclipse.linuxtools.tmf.core.analysis.IAnalysisModuleHelper; +import org.eclipse.linuxtools.tmf.core.analysis.TmfAnalysisManager; +import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfTrace; +import org.eclipse.linuxtools.tmf.core.tests.shared.CtfTmfTestTrace; +import org.eclipse.linuxtools.tmf.core.tests.shared.TmfTestTrace; +import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; +import org.junit.After; +import org.junit.Test; + +/** + * Test suite for the TmfAnalysisModule class + */ +public class AnalysisManagerTest { + + /** Id of analysis module with parameter */ + public static final String MODULE_PARAM = "org.eclipse.linuxtools.tmf.core.tests.analysis.test"; + /** ID of analysis module with parameter and default value */ + public static final String MODULE_PARAM_DEFAULT = "org.eclipse.linuxtools.tmf.core.tests.analysis.test2"; + /** ID of analysis module for CTF traces only */ + public static final String MODULE_CTF = "org.eclipse.linuxtools.tmf.core.tests.analysis.testctf"; + + /** + * Some tests use traces, let's clean them here + */ + @After + public void cleanupTraces() { + TmfTestTrace.A_TEST_10K.dispose(); + CtfTmfTestTrace.KERNEL.dispose(); + } + + /** + * Test suite for the {@link TmfAnalysisManager#getAnalysisModules()} method + */ + @Test + public void testGetAnalysisModules() { + Map modules = TmfAnalysisManager.getAnalysisModules(); + /* At least 3 modules should be found */ + assertTrue(modules.size() >= 3); + + IAnalysisModuleHelper module = modules.get(MODULE_PARAM_DEFAULT); + assertTrue(module.isAutomatic()); + + module = modules.get(MODULE_PARAM); + assertFalse(module.isAutomatic()); + } + + /** + * Test suite for {@link TmfAnalysisManager#getAnalysisModules(Class)} Use + * the test TMF trace and test Ctf trace as sample traces + */ + @Test + public void testListForTraces() { + /* Generic TmfTrace */ + ITmfTrace trace = TmfTestTrace.A_TEST_10K.getTrace(); + Map map = TmfAnalysisManager.getAnalysisModules(trace.getClass()); + + assertTrue(map.containsKey(MODULE_PARAM)); + assertTrue(map.containsKey(MODULE_PARAM_DEFAULT)); + assertFalse(map.containsKey(MODULE_CTF)); + + /* Ctf trace */ + assumeTrue(CtfTmfTestTrace.KERNEL.exists()); + CtfTmfTrace ctftrace = CtfTmfTestTrace.KERNEL.getTrace(); + + map = TmfAnalysisManager.getAnalysisModules(ctftrace.getClass()); + + assertFalse(map.containsKey(MODULE_PARAM)); + assertFalse(map.containsKey(MODULE_PARAM_DEFAULT)); + assertTrue(map.containsKey(MODULE_CTF)); + } + +} diff --git a/org.eclipse.linuxtools.tmf.core.tests/src/org/eclipse/linuxtools/tmf/core/tests/analysis/AnalysisModuleHelperTest.java b/org.eclipse.linuxtools.tmf.core.tests/src/org/eclipse/linuxtools/tmf/core/tests/analysis/AnalysisModuleHelperTest.java new file mode 100644 index 0000000000..625b83c50a --- /dev/null +++ b/org.eclipse.linuxtools.tmf.core.tests/src/org/eclipse/linuxtools/tmf/core/tests/analysis/AnalysisModuleHelperTest.java @@ -0,0 +1,216 @@ +/******************************************************************************* + * Copyright (c) 2013 É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 org.eclipse.linuxtools.tmf.core.tests.analysis; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.junit.Assume.assumeTrue; + +import org.eclipse.core.runtime.Platform; +import org.eclipse.linuxtools.tmf.core.analysis.IAnalysisModule; +import org.eclipse.linuxtools.tmf.core.analysis.IAnalysisModuleHelper; +import org.eclipse.linuxtools.tmf.core.analysis.Messages; +import org.eclipse.linuxtools.tmf.core.analysis.TmfAnalysisManager; +import org.eclipse.linuxtools.tmf.core.analysis.TmfAnalysisModuleHelperCE; +import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfTrace; +import org.eclipse.linuxtools.tmf.core.exceptions.TmfAnalysisException; +import org.eclipse.linuxtools.tmf.core.tests.shared.CtfTmfTestTrace; +import org.eclipse.linuxtools.tmf.core.tests.shared.TmfTestTrace; +import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; +import org.eclipse.linuxtools.tmf.core.trace.TmfTrace; +import org.eclipse.linuxtools.tmf.tests.stubs.analysis.TestAnalysis; +import org.eclipse.linuxtools.tmf.tests.stubs.analysis.TestCtfAnalysis; +import org.eclipse.linuxtools.tmf.tests.stubs.ctf.CtfTmfTraceStub; +import org.eclipse.linuxtools.tmf.tests.stubs.trace.TmfTraceStub; +import org.eclipse.osgi.util.NLS; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.osgi.framework.Bundle; + +/** + * Test suite for the {@link TmfAnalysisModuleHelperCE} class + * + * @author Geneviève Bastien + */ +public class AnalysisModuleHelperTest { + + private IAnalysisModuleHelper fModule; + private IAnalysisModuleHelper fCtfModule; + + /** + * Gets the module helpers for 2 test modules + */ + @Before + public void getModules() { + fModule = TmfAnalysisManager.getAnalysisModule(AnalysisManagerTest.MODULE_PARAM); + assertNotNull(fModule); + assertTrue(fModule instanceof TmfAnalysisModuleHelperCE); + fCtfModule = TmfAnalysisManager.getAnalysisModule(AnalysisManagerTest.MODULE_CTF); + assertNotNull(fCtfModule); + assertTrue(fCtfModule instanceof TmfAnalysisModuleHelperCE); + } + + /** + * Some tests use traces, let's clean them here + */ + @After + public void cleanupTraces() { + TmfTestTrace.A_TEST_10K.dispose(); + CtfTmfTestTrace.KERNEL.dispose(); + } + + /** + * Test the helper's getters and setters + */ + @Test + public void testHelperGetters() { + /* With first module */ + assertEquals(AnalysisManagerTest.MODULE_PARAM, fModule.getId()); + assertEquals("Test analysis", fModule.getName()); + assertFalse(fModule.isAutomatic()); + + Bundle helperbundle = fModule.getBundle(); + Bundle thisbundle = Platform.getBundle("org.eclipse.linuxtools.tmf.core.tests"); + assertNotNull(helperbundle); + assertEquals(thisbundle, helperbundle); + + /* With ctf module */ + assertEquals(AnalysisManagerTest.MODULE_CTF, fCtfModule.getId()); + assertEquals("Test analysis ctf", fCtfModule.getName()); + assertTrue(fCtfModule.isAutomatic()); + } + + /** + * Test the {@link TmfAnalysisModuleHelperCE#appliesToTraceType(Class)} + * method for the 2 modules + */ + @Test + public void testAppliesToTrace() { + /* non-ctf module */ + assertFalse(fModule.appliesToTraceType(TmfTrace.class)); + assertTrue(fModule.appliesToTraceType(TmfTraceStub.class)); + assertFalse(fModule.appliesToTraceType(CtfTmfTraceStub.class)); + + /* ctf module */ + assertFalse(fCtfModule.appliesToTraceType(TmfTrace.class)); + assertFalse(fCtfModule.appliesToTraceType(TmfTraceStub.class)); + assertTrue(fCtfModule.appliesToTraceType(CtfTmfTraceStub.class)); + } + + /** + * Test the {@link TmfAnalysisModuleHelperCE#newModule(ITmfTrace)} method + * for the 2 modules + */ + @Test + public void testNewModule() { + /* Test analysis module with traceStub */ + Exception exception = null; + IAnalysisModule module = null; + try { + module = fModule.newModule(TmfTestTrace.A_TEST_10K.getTrace()); + } catch (TmfAnalysisException e) { + exception = e; + } + assertNull(exception); + assertNotNull(module); + assertTrue(module instanceof TestAnalysis); + + /* Test Analysis module with ctf trace, should return an exception */ + assumeTrue(CtfTmfTestTrace.KERNEL.exists()); + CtfTmfTraceStub ctfTrace = (CtfTmfTraceStub) CtfTmfTestTrace.KERNEL.getTrace(); + module = null; + try { + module = fModule.newModule(ctfTrace); + } catch (TmfAnalysisException e) { + exception = e; + } + assertNotNull(exception); + assertEquals(NLS.bind(Messages.TmfAnalysisModuleHelper_AnalysisDoesNotApply, fModule.getName()), exception.getMessage()); + + /* Test analysis CTF module with ctf trace stub */ + exception = null; + module = null; + try { + module = fCtfModule.newModule(ctfTrace); + } catch (TmfAnalysisException e) { + exception = e; + } + assertNull(exception); + assertNotNull(module); + assertTrue(module instanceof TestCtfAnalysis); + } + + /** + * Test for the initialization of parameters from the extension points + */ + @Test + public void testParameters() { + assumeTrue(CtfTmfTestTrace.KERNEL.exists()); + CtfTmfTrace ctftrace = CtfTmfTestTrace.KERNEL.getTrace(); + ITmfTrace trace = TmfTestTrace.A_TEST_10K.getTrace(); + + /* + * This analysis has a parameter, but no default value. we should be + * able to set the parameter + */ + IAnalysisModuleHelper helper = TmfAnalysisManager.getAnalysisModule(AnalysisManagerTest.MODULE_PARAM); + IAnalysisModule module; + try { + module = helper.newModule(trace); + } catch (TmfAnalysisException e1) { + fail(e1.getMessage()); + return; + } + + assertNull(module.getParameter(TestAnalysis.PARAM_TEST)); + module.setParameter(TestAnalysis.PARAM_TEST, 1); + assertEquals(1, module.getParameter(TestAnalysis.PARAM_TEST)); + + /* This module has a parameter with default value */ + helper = TmfAnalysisManager.getAnalysisModule(AnalysisManagerTest.MODULE_PARAM_DEFAULT); + try { + module = helper.newModule(trace); + } catch (TmfAnalysisException e1) { + fail(e1.getMessage()); + return; + } + assertEquals(3, module.getParameter(TestAnalysis.PARAM_TEST)); + module.setParameter(TestAnalysis.PARAM_TEST, 1); + assertEquals(1, module.getParameter(TestAnalysis.PARAM_TEST)); + + /* + * This module does not have a parameter so setting it should throw an + * error + */ + helper = TmfAnalysisManager.getAnalysisModule(AnalysisManagerTest.MODULE_CTF); + try { + module = helper.newModule(ctftrace); + } catch (TmfAnalysisException e1) { + fail(e1.getMessage()); + return; + } + assertNull(module.getParameter(TestAnalysis.PARAM_TEST)); + Exception exception = null; + try { + module.setParameter(TestAnalysis.PARAM_TEST, 1); + } catch (RuntimeException e) { + exception = e; + } + assertNotNull(exception); + } +} diff --git a/org.eclipse.linuxtools.tmf.core.tests/src/org/eclipse/linuxtools/tmf/core/tests/analysis/AnalysisModuleTest.java b/org.eclipse.linuxtools.tmf.core.tests/src/org/eclipse/linuxtools/tmf/core/tests/analysis/AnalysisModuleTest.java new file mode 100644 index 0000000000..3332d8fcf8 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.core.tests/src/org/eclipse/linuxtools/tmf/core/tests/analysis/AnalysisModuleTest.java @@ -0,0 +1,233 @@ +/******************************************************************************* + * Copyright (c) 2013 É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 org.eclipse.linuxtools.tmf.core.tests.analysis; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Status; +import org.eclipse.linuxtools.tmf.core.analysis.IAnalysisModule; +import org.eclipse.linuxtools.tmf.core.analysis.Messages; +import org.eclipse.linuxtools.tmf.core.analysis.TmfAbstractAnalysisModule; +import org.eclipse.linuxtools.tmf.core.exceptions.TmfAnalysisException; +import org.eclipse.linuxtools.tmf.core.tests.shared.CtfTmfTestTrace; +import org.eclipse.linuxtools.tmf.core.tests.shared.TmfTestTrace; +import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; +import org.eclipse.linuxtools.tmf.tests.stubs.analysis.TestAnalysis; +import org.eclipse.linuxtools.tmf.tests.stubs.analysis.TestCtfAnalysis; +import org.eclipse.osgi.util.NLS; +import org.junit.After; +import org.junit.Test; + +/** + * Test suite for the {@link TmfAbstractAnalysisModule} class + */ +public class AnalysisModuleTest { + + private static String MODULE_GENERIC_ID = "test.id"; + private static String MODULE_GENERIC_NAME = "Test analysis"; + + /** + * Some tests use traces, let's clean them here + */ + @After + public void cleanupTraces() { + TmfTestTrace.A_TEST_10K.dispose(); + CtfTmfTestTrace.KERNEL.dispose(); + } + + /** + * Test suite for analysis module getters and setters + */ + @Test + public void testGettersSetters() { + IAnalysisModule module = new TestAnalysis(); + + module.setName(MODULE_GENERIC_NAME); + module.setId(MODULE_GENERIC_ID); + assertEquals(MODULE_GENERIC_ID, module.getId()); + assertEquals(MODULE_GENERIC_NAME, module.getName()); + + module.setAutomatic(false); + assertFalse(module.isAutomatic()); + module.setAutomatic(true); + assertTrue(module.isAutomatic()); + module.addParameter(TestAnalysis.PARAM_TEST); + assertNull(module.getParameter(TestAnalysis.PARAM_TEST)); + module.setParameter(TestAnalysis.PARAM_TEST, 1); + assertEquals(1, module.getParameter(TestAnalysis.PARAM_TEST)); + + /* Try to set and get wrong parameter */ + String wrongParam = "abc"; + Exception exception = null; + try { + module.setParameter(wrongParam, 1); + } catch (RuntimeException e) { + exception = e; + assertEquals(NLS.bind(Messages.TmfAbstractAnalysisModule_InvalidParameter, wrongParam, module.getName()), e.getMessage()); + } + assertNotNull(exception); + assertNull(module.getParameter(wrongParam)); + } + + private static TestAnalysis setUpAnalysis() { + TestAnalysis module = new TestAnalysis(); + + module.setName(MODULE_GENERIC_NAME); + module.setId(MODULE_GENERIC_ID); + module.addParameter(TestAnalysis.PARAM_TEST); + + return module; + + } + + /** + * Test suite for analysis module + * {@link TmfAbstractAnalysisModule#waitForCompletion(IProgressMonitor)} with + * successful execution + */ + @Test + public void testWaitForCompletionSuccess() { + TestAnalysis module = setUpAnalysis(); + + IStatus status = module.schedule(); + assertEquals(IStatus.ERROR, status.getSeverity()); + + /* Set a stub trace for analysis */ + try { + module.setTrace(TmfTestTrace.A_TEST_10K.getTrace()); + } catch (TmfAnalysisException e) { + fail(e.getMessage()); + } + + /* Default execution, with output 1 */ + module.setParameter(TestAnalysis.PARAM_TEST, 1); + status = module.schedule(); + assertEquals(Status.OK_STATUS, status); + boolean completed = module.waitForCompletion(new NullProgressMonitor()); + + assertTrue(completed); + assertEquals(1, module.getAnalysisOutput()); + } + + /** + * Test suite for {@link TmfAbstractAnalysisModule#waitForCompletion(IProgressMonitor)} with cancellation + */ + @Test + public void testWaitForCompletionCancelled() { + TestAnalysis module = setUpAnalysis(); + + /* Set a stub trace for analysis */ + ITmfTrace trace = TmfTestTrace.A_TEST_10K.getTrace(); + try { + module.setTrace(trace); + } catch (TmfAnalysisException e) { + fail(e.getMessage()); + } + + module.setParameter(TestAnalysis.PARAM_TEST, 0); + IStatus status = module.schedule(); + assertEquals(Status.OK_STATUS, status); + boolean completed = module.waitForCompletion(new NullProgressMonitor()); + + assertFalse(completed); + assertEquals(0, module.getAnalysisOutput()); + } + + /** + * Test the {@link TmfAbstractAnalysisModule#setTrace(ITmfTrace)} method with wrong trace + */ + @Test + public void testSetWrongTrace() { + IAnalysisModule module = new TestCtfAnalysis(); + + module.setName(MODULE_GENERIC_NAME); + module.setId(MODULE_GENERIC_ID); + assertEquals(MODULE_GENERIC_ID, module.getId()); + assertEquals(MODULE_GENERIC_NAME, module.getName()); + + Exception exception = null; + try { + module.setTrace(TmfTestTrace.A_TEST_10K.getTrace()); + } catch (TmfAnalysisException e) { + exception = e; + } + assertNotNull(exception); + assertEquals(NLS.bind(Messages.TmfAbstractAnalysisModule_AnalysisCannotExecute, module.getName()), exception.getMessage()); + + } + + /** + * Test suite for the {@link TmfAbstractAnalysisModule#cancel()} method + */ + @Test + public void testCancel() { + TestAnalysis module = setUpAnalysis(); + + module.setParameter(TestAnalysis.PARAM_TEST, 999); + try { + module.setTrace(TmfTestTrace.A_TEST_10K.getTrace()); + } catch (TmfAnalysisException e) { + fail(e.getMessage()); + } + + assertEquals(Status.OK_STATUS, module.schedule()); + + /* Give the job a chance to start */ + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + fail(e.getMessage()); + } + + module.cancel(); + assertFalse(module.waitForCompletion(new NullProgressMonitor())); + assertEquals(-1, module.getAnalysisOutput()); + } + + /** + * Test suite for the {@link IAnalysisModule#notifyParameterChanged(String)} + * method + */ + @Test + public void testParameterChanged() { + TestAnalysis module = setUpAnalysis(); + + try { + module.setTrace(TmfTestTrace.A_TEST_10K.getTrace()); + } catch (TmfAnalysisException e) { + fail(e.getMessage()); + } + + /* Check exception if no wrong parameter name */ + Exception exception = null; + try { + module.notifyParameterChanged("aaa"); + } catch (RuntimeException e) { + exception = e; + } + assertNotNull(exception); + + /* + * Cannot test anymore of this method, need a parameter provider to do + * this + */ + } +} diff --git a/org.eclipse.linuxtools.tmf.core.tests/src/org/eclipse/linuxtools/tmf/core/tests/analysis/AnalysisParameterProviderTest.java b/org.eclipse.linuxtools.tmf.core.tests/src/org/eclipse/linuxtools/tmf/core/tests/analysis/AnalysisParameterProviderTest.java new file mode 100644 index 0000000000..bd3e0c8a9d --- /dev/null +++ b/org.eclipse.linuxtools.tmf.core.tests/src/org/eclipse/linuxtools/tmf/core/tests/analysis/AnalysisParameterProviderTest.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2013 É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 org.eclipse.linuxtools.tmf.core.tests.analysis; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import java.util.List; + +import org.eclipse.linuxtools.tmf.core.analysis.IAnalysisModule; +import org.eclipse.linuxtools.tmf.core.analysis.IAnalysisModuleHelper; +import org.eclipse.linuxtools.tmf.core.analysis.IAnalysisParameterProvider; +import org.eclipse.linuxtools.tmf.core.analysis.TmfAnalysisManager; +import org.eclipse.linuxtools.tmf.core.exceptions.TmfAnalysisException; +import org.eclipse.linuxtools.tmf.core.tests.shared.TmfTestTrace; +import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; +import org.eclipse.linuxtools.tmf.tests.stubs.analysis.TestAnalysis; +import org.eclipse.linuxtools.tmf.tests.stubs.analysis.TestAnalysisParameterProvider; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * Test the TmfAbstractParameterProvider class + * + * @author Geneviève Bastien + */ +public class AnalysisParameterProviderTest { + + /** + * Registers the parameter provider + */ + @Before + public void setup() { + TmfAnalysisManager.registerParameterProvider(AnalysisManagerTest.MODULE_PARAM, TestAnalysisParameterProvider.class); + } + + /** + * Cleanup the trace after testing + */ + @After + public void cleanupTrace() { + TmfTestTrace.A_TEST_10K.dispose(); + } + + /** + * Test that the provider's value is used + */ + @Test + public void testProviderTmfTrace() { + ITmfTrace trace = TmfTestTrace.A_TEST_10K.getTrace(); + /* Make sure the value is set to null */ + IAnalysisModuleHelper helper = TmfAnalysisManager.getAnalysisModule(AnalysisManagerTest.MODULE_PARAM); + IAnalysisModule module; + try { + module = helper.newModule(trace); + } catch (TmfAnalysisException e) { + fail(e.getMessage()); + return; + } + assertEquals(10, module.getParameter(TestAnalysis.PARAM_TEST)); + + /* Change the value of the parameter in the provider */ + List providers = TmfAnalysisManager.getParameterProviders(module, trace); + assertEquals(1, providers.size()); + TestAnalysisParameterProvider provider = (TestAnalysisParameterProvider) providers.get(0); + provider.setValue(5); + assertEquals(5, module.getParameter(TestAnalysis.PARAM_TEST)); + } + +} diff --git a/org.eclipse.linuxtools.tmf.core.tests/stubs/org/eclipse/linuxtools/tmf/tests/stubs/analysis/TestAnalysis.java b/org.eclipse.linuxtools.tmf.core.tests/stubs/org/eclipse/linuxtools/tmf/tests/stubs/analysis/TestAnalysis.java new file mode 100644 index 0000000000..9879ac3b21 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.core.tests/stubs/org/eclipse/linuxtools/tmf/tests/stubs/analysis/TestAnalysis.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * Copyright (c) 2013 É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 org.eclipse.linuxtools.tmf.tests.stubs.analysis; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.linuxtools.tmf.core.analysis.TmfAbstractAnalysisModule; +import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; + +/** + * Simple analysis type for test + */ +public class TestAnalysis extends TmfAbstractAnalysisModule { + + private int output = 0; + + /** + * Test parameter. If set, simulate cancellation + */ + public static final String PARAM_TEST = "test"; + + /** + * Constructor + */ + public TestAnalysis() { + super(); + } + + @Override + public boolean canExecute(ITmfTrace trace) { + return true; + } + + @Override + protected boolean executeAnalysis(final IProgressMonitor monitor) { + if (getParameter(PARAM_TEST) == null) { + throw new RuntimeException("The parameter should be set"); + } + /* If PARAM_TEST is set to 0, simulate cancellation */ + if ((Integer) getParameter(PARAM_TEST) == 0) { + output = 0; + return false; + } else if ((Integer) getParameter(PARAM_TEST) == 999) { + /* just stay in an infinite loop until cancellation */ + while (!monitor.isCanceled()) { + + } + return !monitor.isCanceled(); + } + output = (Integer) getParameter(PARAM_TEST); + return true; + } + + @Override + protected void canceling() { + output = -1; + } + + @Override + public Object getParameter(String name) { + Object value = super.getParameter(name); + if ((value != null) && name.equals(PARAM_TEST) && (value instanceof String)) { + return Integer.parseInt((String) value); + } + return value; + } + + @Override + protected void parameterChanged(String name) { + schedule(); + } + + /** + * Get the analysis output value + * + * @return The analysis output + */ + public int getAnalysisOutput() { + return output; + } + +} diff --git a/org.eclipse.linuxtools.tmf.core.tests/stubs/org/eclipse/linuxtools/tmf/tests/stubs/analysis/TestAnalysisParameterProvider.java b/org.eclipse.linuxtools.tmf.core.tests/stubs/org/eclipse/linuxtools/tmf/tests/stubs/analysis/TestAnalysisParameterProvider.java new file mode 100644 index 0000000000..b5614e8487 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.core.tests/stubs/org/eclipse/linuxtools/tmf/tests/stubs/analysis/TestAnalysisParameterProvider.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright (c) 2013 É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 org.eclipse.linuxtools.tmf.tests.stubs.analysis; + +import org.eclipse.linuxtools.tmf.core.analysis.TmfAbstractAnalysisParamProvider; +import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; +import org.eclipse.linuxtools.tmf.tests.stubs.trace.TmfTraceStub; + +/** + * Test parameter provider for the PARAM_TEST that would apply only to + * CtfTmfTrace (though it is associated with an analysis that supports all trace + * types) + * + * @author Geneviève Bastien + */ +public class TestAnalysisParameterProvider extends TmfAbstractAnalysisParamProvider { + + private int fValue = 10; + + @Override + public String getName() { + return "test parameter provider"; + } + + @Override + public Object getParameter(String name) { + if (name.equals(TestAnalysis.PARAM_TEST)) { + return fValue; + } + return null; + } + + @Override + public boolean appliesToTrace(ITmfTrace trace) { + return (trace instanceof TmfTraceStub); + } + + /** + * Sets a new value for the parameter + * + * @param value + * new parameter value + */ + public void setValue(int value) { + fValue = value; + notifyParameterChanged(TestAnalysis.PARAM_TEST); + } + +} diff --git a/org.eclipse.linuxtools.tmf.core.tests/stubs/org/eclipse/linuxtools/tmf/tests/stubs/analysis/TestCtfAnalysis.java b/org.eclipse.linuxtools.tmf.core.tests/stubs/org/eclipse/linuxtools/tmf/tests/stubs/analysis/TestCtfAnalysis.java new file mode 100644 index 0000000000..517dcf9e9a --- /dev/null +++ b/org.eclipse.linuxtools.tmf.core.tests/stubs/org/eclipse/linuxtools/tmf/tests/stubs/analysis/TestCtfAnalysis.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2013 É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 org.eclipse.linuxtools.tmf.tests.stubs.analysis; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.linuxtools.tmf.core.analysis.TmfAbstractAnalysisModule; +import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; +import org.eclipse.linuxtools.tmf.tests.stubs.ctf.CtfTmfTraceStub; + +/** + * Simple analysis type for test + */ +public class TestCtfAnalysis extends TmfAbstractAnalysisModule{ + + @Override + public boolean canExecute(ITmfTrace trace) { + /* This just makes sure the trace is a ctf stub trace */ + return (CtfTmfTraceStub.class.isAssignableFrom(trace.getClass())); + } + + @Override + protected void canceling() { + + } + + @Override + protected boolean executeAnalysis(final IProgressMonitor monitor) { + return false; + } + +} diff --git a/org.eclipse.linuxtools.tmf.core/META-INF/MANIFEST.MF b/org.eclipse.linuxtools.tmf.core/META-INF/MANIFEST.MF index 3d4f71073e..151937282e 100644 --- a/org.eclipse.linuxtools.tmf.core/META-INF/MANIFEST.MF +++ b/org.eclipse.linuxtools.tmf.core/META-INF/MANIFEST.MF @@ -12,6 +12,7 @@ Require-Bundle: org.eclipse.core.runtime, org.eclipse.core.resources, org.eclipse.linuxtools.ctf.core;bundle-version="3.0.0" Export-Package: org.eclipse.linuxtools.internal.tmf.core;x-friends:="org.eclipse.linuxtools.tmf.core.tests", + org.eclipse.linuxtools.internal.tmf.core.analysis;x-friends:="org.eclipse.linuxtools.tmf.core.tests", org.eclipse.linuxtools.internal.tmf.core.component;x-friends:="org.eclipse.linuxtools.tmf.core.tests", org.eclipse.linuxtools.internal.tmf.core.request;x-friends:="org.eclipse.linuxtools.tmf.core.tests", org.eclipse.linuxtools.internal.tmf.core.statesystem;x-friends:="org.eclipse.linuxtools.tmf.core.tests", @@ -22,6 +23,7 @@ Export-Package: org.eclipse.linuxtools.internal.tmf.core;x-friends:="org.eclipse org.eclipse.linuxtools.internal.tmf.core.trace;x-friends:="org.eclipse.linuxtools.tmf.core.tests", org.eclipse.linuxtools.internal.tmf.core.trace.indexer;x-friends:="org.eclipse.linuxtools.tmf.core.tests", org.eclipse.linuxtools.tmf.core, + org.eclipse.linuxtools.tmf.core.analysis, org.eclipse.linuxtools.tmf.core.callstack, org.eclipse.linuxtools.tmf.core.component, org.eclipse.linuxtools.tmf.core.ctfadaptor, diff --git a/org.eclipse.linuxtools.tmf.core/build.properties b/org.eclipse.linuxtools.tmf.core/build.properties index c0c91cb215..0a6f1d768b 100644 --- a/org.eclipse.linuxtools.tmf.core/build.properties +++ b/org.eclipse.linuxtools.tmf.core/build.properties @@ -16,7 +16,8 @@ bin.includes = META-INF/,\ plugin.properties,\ plugin.xml,\ about.html,\ - . + .,\ + plugin.xml src.includes = about.html additional.bundles = org.eclipse.jdt.annotation jars.extra.classpath = platform:/plugin/org.eclipse.jdt.annotation diff --git a/org.eclipse.linuxtools.tmf.core/plugin.xml b/org.eclipse.linuxtools.tmf.core/plugin.xml index deebba59a7..d22388b812 100644 --- a/org.eclipse.linuxtools.tmf.core/plugin.xml +++ b/org.eclipse.linuxtools.tmf.core/plugin.xml @@ -7,5 +7,5 @@ class="org.eclipse.linuxtools.internal.tmf.core.TmfCorePreferenceInitializer"> - + diff --git a/org.eclipse.linuxtools.tmf.core/schema/org.eclipse.linuxtools.tmf.core.analysis.exsd b/org.eclipse.linuxtools.tmf.core/schema/org.eclipse.linuxtools.tmf.core.analysis.exsd new file mode 100644 index 0000000000..3d54457992 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.core/schema/org.eclipse.linuxtools.tmf.core.analysis.exsd @@ -0,0 +1,217 @@ + + + + + + + + + This extension point is used to contribute new analysis modules to the TMF framework. Analysis modules provide new independent functionalities that can be run on traces. + + + + + + + + + + + + + + + + + a fully qualified identifier of the target extension point + + + + + + + an optional identifier of the extension instance + + + + + + + an optional name of the extension instance + + + + + + + + + + + + + + + + + + + The unique ID that identifies this analysis module. + + + + + + + The trace analysis module's name as it is displayed to the end user + + + + + + + The fully qualified name of a class that implements the <samp>IAnalysisModule</samp> interface. + + + + + + + + + + The icon associated to this analysis module. + + + + + + + + + + Whether to execute this analysis automatically when trace is opened, or wait for the user to ask for it + + + + + + + + + + Parameter for this module + + + + + + + The parameter name + + + + + + + A default value for this parameter + + + + + + + + + + Allow to define the tracetypes this analysis applies to. + + + + + + + The base trace class this analysis applies to or not (it also applies to traces extending this class). + + + + + + + + + + Does this tracetype element mean the class applies or not (default true) + + + + + + + + + + + + 3.0 + + + + + + + + + <p> +For an example implementation of an analysis module see: +<pre> +plug-in: org.eclipse.linuxtools.tmf.core.tests +package: org.eclipse.linuxtools.tmf.core.tests.stubs.analysis +class: TestCtfAnalysis +</pre> +</p> + +<p> +The following is an example of the extension point: +<pre> +<extension + point="org.eclipse.linuxtools.tmf.core.analysis"> + <module + id="org.eclipse.linuxtools.tmf.core.tests.analysis.testctf" + name="Test analysis ctf" + analysis_module="org.eclipse.linuxtools.tmf.tests.stubs.analysis.TestCtfAnalysis" + automatic="true"> + </module> + </extension> +</pre> +</p> + + + + + + + + + <p> +For this extension point, a class implementing IAnalysisModule must be defined (org.eclipse.linuxtools.tmf.core.analysis.IAnalysisModule). Most analysis can just extend the org.eclipse.linuxtools.tmf.core.analysis.TmfAbstractAnalysisModule class, since it already contains everything to manage the trace's, the analysis' execution, cancellation, completion, the help texts, etc. +</p> +<p> +The key method to implement if extending TmfAbstractAnalysisModule is executeAnalysis(final IProgressMonitor monitor). It contains the code of the analysis itself and is executed inside an Eclipse job. +</p> + + + + + + + + + + Copyright (c) 2013 É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 <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a> + + + + diff --git a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/analysis/TmfAnalysisType.java b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/analysis/TmfAnalysisType.java new file mode 100644 index 0000000000..3a5a78aace --- /dev/null +++ b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/internal/tmf/core/analysis/TmfAnalysisType.java @@ -0,0 +1,135 @@ +/******************************************************************************* + * Copyright (c) 2013 É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 org.eclipse.linuxtools.internal.tmf.core.analysis; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.Platform; +import org.eclipse.linuxtools.tmf.core.analysis.IAnalysisModuleHelper; +import org.eclipse.linuxtools.tmf.core.analysis.TmfAnalysisModuleHelperCE; + +/** + * Utility class for accessing TMF analysis type extensions from the platform's + * extensions registry. + * + * @author Geneviève Bastien + * @since 3.0 + */ +public final class TmfAnalysisType { + + /** Extension point ID */ + public static final String TMF_ANALYSIS_TYPE_ID = "org.eclipse.linuxtools.tmf.core.analysis"; //$NON-NLS-1$ + + /** Extension point element 'module' */ + public static final String MODULE_ELEM = "module"; //$NON-NLS-1$ + + /** Extension point element 'parameter' */ + public static final String PARAMETER_ELEM = "parameter"; //$NON-NLS-1$ + + /** Extension point attribute 'ID' */ + public static final String ID_ATTR = "id"; //$NON-NLS-1$ + + /** Extension point attribute 'name' */ + public static final String NAME_ATTR = "name"; //$NON-NLS-1$ + + /** Extension point attribute 'analysis_module' */ + public static final String ANALYSIS_MODULE_ATTR = "analysis_module"; //$NON-NLS-1$ + + /** Extension point attribute 'automatic' */ + public static final String AUTOMATIC_ATTR = "automatic"; //$NON-NLS-1$ + + /** Extension point attribute 'icon' */ + public static final String ICON_ATTR = "icon"; //$NON-NLS-1$ + + /** Extension point attribute 'default_value' */ + public static final String DEFAULT_VALUE_ATTR = "default_value"; //$NON-NLS-1$ + + /** Extension point element 'tracetype' */ + public static final String TRACETYPE_ELEM = "tracetype"; //$NON-NLS-1$ + + /** Extension point attribute 'class' */ + public static final String CLASS_ATTR = "class"; //$NON-NLS-1$ + + /** Extension point attribute 'applies' */ + public static final String APPLIES_ATTR = "applies"; //$NON-NLS-1$ + + /** + * The mapping of available trace type IDs to their corresponding + * configuration element + */ + private final Map fAnalysisTypeAttributes = new HashMap(); + + private static TmfAnalysisType fInstance = null; + + /** + * Retrieves all configuration elements from the platform extension registry + * for the trace type extension. + * + * @return an array of trace type configuration elements + */ + public static IConfigurationElement[] getTypeElements() { + IConfigurationElement[] elements = + Platform.getExtensionRegistry().getConfigurationElementsFor(TMF_ANALYSIS_TYPE_ID); + List typeElements = new LinkedList(); + for (IConfigurationElement element : elements) { + if (element.getName().equals(MODULE_ELEM)) { + typeElements.add(element); + } + } + return typeElements.toArray(new IConfigurationElement[typeElements.size()]); + } + + private TmfAnalysisType() { + populateAnalysisTypes(); + } + + /** + * The analysis type instance + * + * @return the analysis type instance + */ + public static synchronized TmfAnalysisType getInstance() { + if (fInstance == null) { + fInstance = new TmfAnalysisType(); + } + return fInstance; + } + + /** + * Get the list of analysis modules + * + * @return list of analysis modules + */ + public Map getAnalysisModules() { + return fAnalysisTypeAttributes; + } + + private void populateAnalysisTypes() { + if (fAnalysisTypeAttributes.isEmpty()) { + // Populate the Categories and Trace Types + IConfigurationElement[] config = Platform.getExtensionRegistry().getConfigurationElementsFor(TMF_ANALYSIS_TYPE_ID); + for (IConfigurationElement ce : config) { + String elementName = ce.getName(); + if (elementName.equals(TmfAnalysisType.MODULE_ELEM)) { + String analysisTypeId = ce.getAttribute(TmfAnalysisType.ID_ATTR); + fAnalysisTypeAttributes.put(analysisTypeId, new TmfAnalysisModuleHelperCE(ce)); + } + } + } + } + +} diff --git a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/IAnalysisModule.java b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/IAnalysisModule.java new file mode 100644 index 0000000000..95bb5ec746 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/IAnalysisModule.java @@ -0,0 +1,240 @@ +/******************************************************************************* + * Copyright (c) 2013 É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 org.eclipse.linuxtools.tmf.core.analysis; + +import java.util.List; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.linuxtools.tmf.core.exceptions.TmfAnalysisException; +import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; + +/** + * Interface that hooks analysis modules to the rest of TMF. Analysis modules + * are a set of operations to be run on a trace (or experiment). They will + * typically either provide outputs to the end user, or feed other analysis. + * + * An analysis module must tell what trace type it applies to and if it can be + * executed on a given trace of the right type. + * + * Implementations of this interface must define how an analysis will be + * executed once scheduled and provide help texts to describe how to use the + * analysis. + * + * Analysis can also take parameters, manually set, through default values or + * using an {@link IAnalysisParameterProvider}. {@link IAnalysisOutput} can also + * be registered to an analysis modules to display the results of the analysis. + * + * This interface just allows to hook the analysis to the TMF framework, but the + * developer is free to implement the internals of its operations the way he + * wishes. + * + * @author Geneviève Bastien + * @since 3.0 + */ +public interface IAnalysisModule { + + // -------------------------------------------------------- + // Getters and setters + // -------------------------------------------------------- + + /** + * Sets the name of the analysis module + * + * @param name + * name of the module + */ + void setName(String name); + + /** + * Gets the name of the analysis module + * + * @return Name of the module + */ + String getName(); + + /** + * Sets the id of the module + * + * @param id + * id of the module + */ + void setId(String id); + + /** + * Gets the id of the analysis module + * + * @return The id of the module + */ + String getId(); + + /** + * Sets whether this analysis should be run automatically at trace opening + * + * @param auto + * True if analysis should be run automatically for a trace + */ + void setAutomatic(boolean auto); + + /** + * Gets whether the analysis should be run automatically at trace opening + * + * @return true if analysis is to be run automatically + */ + boolean isAutomatic(); + + /** + * Sets the trace on which to run the analysis + * + * Note: The trace cannot be final since most modules are instantiated in a + * way that does not know about the trace, but it shouldn't be set more than + * once since an instance of a module belongs to a trace. It is up to each + * implementation to make sure the trace is set only once. + * + * @param trace + * The trace to run the analysis on + * @throws TmfAnalysisException + */ + void setTrace(ITmfTrace trace) throws TmfAnalysisException; + + /** + * Add a parameter to this module + * + * @param name + * Name of the parameter + */ + void addParameter(String name); + + /** + * Sets the value of a parameter + * + * @param name + * The name of the parameter + * @param value + * The value (subclasses may type-check it) + * @throws RuntimeException + */ + void setParameter(String name, Object value); + + /** + * Gets the value of a parameter + * + * @param name + * Name of the parameter + * @return The value of a parameter + */ + Object getParameter(String name); + + // ----------------------------------------------------- + // Functionalities + // ----------------------------------------------------- + + /** + * Can an analysis be executed on a given trace (otherwise, it is shown + * grayed out and a help message is available to see why it is not + * applicable) + * + * @param trace + * The trace to analyze + * @return Whether the analysis can be executed + */ + boolean canExecute(ITmfTrace trace); + + /** + * Schedule the execution of the analysis. If the trace has been set and is + * opened, the analysis will be executed right away, otherwise it should + * scheduled for execution once all pre-conditions are satisfied. + * + * @return An IStatus indicating if the execution of the analysis could be + * scheduled successfully or not. + */ + IStatus schedule(); + + /** + * Gets a list of outputs + * + * @return The list of {@link IAnalysisOutput} + */ + List getOutputs(); + + /** + * Registers an output for this analysis + * + * @param output + * The {@link IAnalysisOutput} object + */ + void registerOutput(IAnalysisOutput output); + + /** + * Typically the output of an analysis will be available only after it is + * completed. This method allows to wait until an analysis has been + * completed or the analysis has been cancelled + * + * To avoid UI freezes, it should not be called from the main thread of the + * application + * + * @param monitor + * The progress monitor to check for cancellation + * @return If the analysis was successfully completed. If false is returned, + * this either means there was a problem during the analysis, or it + * got cancelled before it could finished or it has not been + * scheduled to run at all. In all cases, the quality or + * availability of the output(s) and results is not guaranteed. + */ + boolean waitForCompletion(IProgressMonitor monitor); + + /** + * Cancels the current analysis + */ + public void cancel(); + + // ----------------------------------------------------- + // Utilities + // ----------------------------------------------------- + + /** + * Gets a generic help message/documentation for this analysis module + * + * This help text will be displayed to the user and may contain information + * on what the module does, how to use it and how to correctly generate the + * trace to make it available + * + * TODO: Help texts could be quite long. They should reside in their own + * file and be accessed either with text, for a command line man page, or + * through the eclipse help context. + * + * @return The generic help text + */ + String getHelpText(); + + /** + * Gets a help text specific for a given trace + * + * For instance, it may explain why the analysis module cannot be executed + * on a trace and how to correct this + * + * @param trace + * The trace to analyze + * @return A help text with information on a specific trace + */ + String getHelpText(ITmfTrace trace); + + /** + * Notify the module that the value of a parameter has changed + * + * @param name + * The of the parameter that changed + */ + void notifyParameterChanged(String name); + +} diff --git a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/IAnalysisModuleHelper.java b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/IAnalysisModuleHelper.java new file mode 100644 index 0000000000..2d24065daa --- /dev/null +++ b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/IAnalysisModuleHelper.java @@ -0,0 +1,109 @@ +/******************************************************************************* + * Copyright (c) 2013 É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 org.eclipse.linuxtools.tmf.core.analysis; + +import org.eclipse.linuxtools.tmf.core.exceptions.TmfAnalysisException; +import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; +import org.osgi.framework.Bundle; + +/** + * Interface for modules helpers that provide basic module information and + * creates module from a source when requested. + * + * @author Geneviève Bastien + */ +public interface IAnalysisModuleHelper { + + // ------------------------------------ + // Getters + // ------------------------------------ + + /** + * Gets the id of the analysis module + * + * @return The id of the module + */ + String getId(); + + /** + * Gets the name of the analysis module + * + * @return The id of the module + */ + String getName(); + + /** + * Gets whether the analysis should be run automatically at trace opening + * + * @return true if analysis is to be run automatically + */ + boolean isAutomatic(); + + /** + * Gets a generic help message/documentation for this analysis module + * + * This help text will be displayed to the user and may contain information + * on what the module does, how to use it and how to correctly generate the + * trace to make it available + * + * TODO: Help texts could be quite long. They should reside in their own + * file and be accessed either with text, for a command line man page, or + * through the eclipse help context. There should be a custom way to make it + * available through the helper, without instantiating the analysis, though + * help text after analysis instantiation may be richer. + * + * @return The generic help text + */ + String getHelpText(); + + /** + * Gets the icon for this module + * + * @return The icon path + */ + String getIcon(); + + /** + * Gets the bundle this analysis module is part of + * + * @return The bundle + */ + Bundle getBundle(); + + /** + * Does an analysis apply to a given trace type (otherwise, it is not shown) + * + * @param traceclass + * The trace to analyze + * @return whether the analysis applies + */ + boolean appliesToTraceType(Class traceclass); + + // --------------------------------------- + // Functionalities + // --------------------------------------- + + /** + * Creates a new instance of the {@link IAnalysisModule} represented by this + * helper and initializes it with the trace. + * + * @param trace + * The trace to be linked to the module + * @return A new {@link IAnalysisModule} instance initialized with the + * trace. + * @throws TmfAnalysisException + * Exceptions that occurred when setting trace + */ + IAnalysisModule newModule(ITmfTrace trace) throws TmfAnalysisException; + +} diff --git a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/IAnalysisOutput.java b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/IAnalysisOutput.java new file mode 100644 index 0000000000..2b574b7997 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/IAnalysisOutput.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2013 É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 org.eclipse.linuxtools.tmf.core.analysis; + +/** + * Interface for all output types of analysis + * + * @author Geneviève Bastien + * @since 3.0 + */ +public interface IAnalysisOutput { + + /** + * Gets the name of the output + * + * @return Name of the output + */ + String getName(); + + /** + * Requests the output for an analysis module. This function does not + * necessarily output the analysis, it just specifies that the user wants + * this output. + */ + void requestOutput(); + +} diff --git a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/IAnalysisParameterProvider.java b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/IAnalysisParameterProvider.java new file mode 100644 index 0000000000..5b6e5d8da1 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/IAnalysisParameterProvider.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2013 É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 org.eclipse.linuxtools.tmf.core.analysis; + +import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; + +/** + * Interface for classes that can provide parameters to analysis when they are + * not set manually + * + * @author Geneviève Bastien + */ +public interface IAnalysisParameterProvider { + + // -------------------------------------------------------- + // Getters and setters + // -------------------------------------------------------- + + /** + * Gets the name of the parameter provider + * + * @return Name of the parameter provider + */ + String getName(); + + /** + * Gets the value of a parameter + * + * @param name + * Name of the parameter + * @return The value of a parameter + */ + Object getParameter(String name); + + // -------------------------------------------------------- + // Functionalities + // -------------------------------------------------------- + + /** + * Does this parameter provider apply to a given trace + * + * @param trace + * The trace to analyse + * @return whether the parameter provider applies + */ + boolean appliesToTrace(ITmfTrace trace); + + /** + * Register an analysis module to be notified when a parameter value is + * changed + * + * @param module + * The listening analysis module + */ + void registerModule(IAnalysisModule module); + +} diff --git a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/Messages.java b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/Messages.java new file mode 100644 index 0000000000..5b57833aec --- /dev/null +++ b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/Messages.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2013 É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 org.eclipse.linuxtools.tmf.core.analysis; + +import org.eclipse.osgi.util.NLS; + +/** + * Message bundle for org.eclipse.linuxtools.tmf.core.analysis + * + * @author Geneviève Bastien + * @since 3.0 + */ +public class Messages extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.linuxtools.tmf.core.analysis.messages"; //$NON-NLS-1$ + + /** Trace was set more than once for this module */ + public static String TmfAbstractAnalysisModule_TraceSetMoreThanOnce; + + /** Analysis Module cannot execute on trace */ + public static String TmfAbstractAnalysisModule_AnalysisCannotExecute; + + /** Analysis Module does not apply to trace */ + public static String TmfAnalysisModuleHelper_AnalysisDoesNotApply; + + /** Analysis Module for trace */ + public static String TmfAbstractAnalysisModule_AnalysisForTrace; + + /** Analysis Module presentation */ + public static String TmfAbstractAnalysisModule_AnalysisModule; + + /** Parameter is invalid */ + public static String TmfAbstractAnalysisModule_InvalidParameter; + + /** Running analysis */ + public static String TmfAbstractAnalysisModule_RunningAnalysis; + + /** Error instantiating parameter provider */ + public static String TmfAnalysisManager_ErrorParameterProvider; + + /** Impossible to instantiate module from helper */ + public static String TmfAnalysisModuleHelper_ImpossibleToCreateModule; + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() { + } +} diff --git a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/TmfAbstractAnalysisModule.java b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/TmfAbstractAnalysisModule.java new file mode 100644 index 0000000000..ecad82db04 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/TmfAbstractAnalysisModule.java @@ -0,0 +1,388 @@ +/******************************************************************************* + * Copyright (c) 2013 É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 org.eclipse.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 java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.linuxtools.internal.tmf.core.Activator; +import org.eclipse.linuxtools.tmf.core.component.TmfComponent; +import org.eclipse.linuxtools.tmf.core.exceptions.TmfAnalysisException; +import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler; +import org.eclipse.linuxtools.tmf.core.signal.TmfStartAnalysisSignal; +import org.eclipse.linuxtools.tmf.core.signal.TmfTraceClosedSignal; +import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; +import org.eclipse.osgi.util.NLS; + +/** + * Base class that analysis modules main class may extend. It provides default + * behavior to some methods of the analysis module + * + * @author Geneviève Bastien + * @since 3.0 + */ +public abstract class TmfAbstractAnalysisModule extends TmfComponent implements IAnalysisModule { + + private String fName, fId; + private boolean fAutomatic = false, fStarted = false; + private ITmfTrace fTrace; + private final Map fParameters = new HashMap(); + private final List fParameterNames = new ArrayList(); + private final List fOutputs = new ArrayList(); + private List fParameterProviders = new ArrayList(); + private Job fJob = null; + + private final Object syncObj = new Object(); + + /* Latch tracking if the analysis is completed or not */ + private CountDownLatch fFinishedLatch = new CountDownLatch(0); + + private boolean fAnalysisCancelled = false; + + @Override + public boolean isAutomatic() { + return fAutomatic; + } + + @Override + public String getName() { + return fName; + } + + @Override + public void setName(String name) { + fName = name; + } + + @Override + public void setId(String id) { + fId = id; + } + + @Override + public String getId() { + return fId; + } + + @Override + public void setAutomatic(boolean auto) { + fAutomatic = auto; + } + + @Override + public void setTrace(ITmfTrace trace) throws TmfAnalysisException { + if (fTrace != null) { + throw new TmfAnalysisException(NLS.bind(Messages.TmfAbstractAnalysisModule_TraceSetMoreThanOnce, getName())); + } + + /* Check that analysis can be executed */ + if (!canExecute(trace)) { + throw new TmfAnalysisException(NLS.bind(Messages.TmfAbstractAnalysisModule_AnalysisCannotExecute, getName())); + } + fTrace = trace; + /* Get the parameter providers for this trace */ + fParameterProviders = TmfAnalysisManager.getParameterProviders(this, fTrace); + for (IAnalysisParameterProvider provider : fParameterProviders) { + provider.registerModule(this); + } + resetAnalysis(); + fStarted = false; + } + + /** + * Gets the trace + * + * @return The trace + */ + protected ITmfTrace getTrace() { + return fTrace; + } + + @Override + public void addParameter(String name) { + fParameterNames.add(name); + } + + @Override + public synchronized void setParameter(String name, Object value) { + if (!fParameterNames.contains(name)) { + throw new RuntimeException(NLS.bind(Messages.TmfAbstractAnalysisModule_InvalidParameter, name, getName())); + } + Object oldValue = fParameters.get(name); + fParameters.put(name, value); + if ((value != null) && !(value.equals(oldValue))) { + parameterChanged(name); + } + } + + @Override + public synchronized void notifyParameterChanged(String name) { + if (!fParameterNames.contains(name)) { + throw new RuntimeException(NLS.bind(Messages.TmfAbstractAnalysisModule_InvalidParameter, name, getName())); + } + Object oldValue = fParameters.get(name); + Object value = getParameter(name); + if ((value != null) && !(value.equals(oldValue))) { + parameterChanged(name); + } + } + + /** + * Used to indicate that a parameter value has been changed + * + * @param name + * The name of the modified parameter + */ + protected void parameterChanged(String name) { + + } + + @Override + public Object getParameter(String name) { + Object paramValue = fParameters.get(name); + /* The parameter is not set, maybe it can be provided by someone else */ + if ((paramValue == null) && (fTrace != null)) { + for (IAnalysisParameterProvider provider : fParameterProviders) { + paramValue = provider.getParameter(name); + if (paramValue != null) { + break; + } + } + } + return paramValue; + } + + @Override + public boolean canExecute(ITmfTrace trace) { + return true; + } + + /** + * Set the countdown latch back to 1 so the analysis can be executed again + */ + protected void resetAnalysis() { + fFinishedLatch = new CountDownLatch(1); + } + + /** + * Actually executes the analysis itself + * + * @param monitor + * Progress monitor + * @return Whether the analysis was completed successfully or not + * @throws TmfAnalysisException + * Method may throw an analysis exception + */ + protected abstract boolean executeAnalysis(final IProgressMonitor monitor) throws TmfAnalysisException; + + /** + * Indicate the analysis has been canceled. It is abstract to force + * implementing class to cleanup what they are running. This is called by + * the job's canceling. It does not need to be called directly. + */ + protected abstract void canceling(); + + /** + * To be called when the analysis is completed, whether normally or because + * it was cancelled or for any other reason. + * + * It has to be called inside a synchronized block + */ + private void setAnalysisCompleted() { + fStarted = false; + fJob = null; + fFinishedLatch.countDown(); + } + + /** + * Cancels the analysis if it is executing + */ + @Override + public final void cancel() { + synchronized (syncObj) { + if (fJob != null) { + if (fJob.cancel()) { + fAnalysisCancelled = true; + setAnalysisCompleted(); + } + } + fStarted = false; + } + } + + private void execute() { + + /* + * TODO: The analysis in a job should be done at the analysis manager + * level instead of depending on this abstract class implementation, + * otherwise another analysis implementation may block the main thread + */ + + /* Do not execute if analysis has already run */ + if (fFinishedLatch.getCount() == 0) { + return; + } + + /* Do not execute if analysis already running */ + synchronized (syncObj) { + if (fStarted) { + return; + } + fStarted = true; + } + + /* + * Actual analysis will be run on a separate thread + */ + fJob = new Job(NLS.bind(Messages.TmfAbstractAnalysisModule_RunningAnalysis, getName())) { + @Override + protected IStatus run(final IProgressMonitor monitor) { + try { + monitor.beginTask("", IProgressMonitor.UNKNOWN); //$NON-NLS-1$ + broadcast(new TmfStartAnalysisSignal(TmfAbstractAnalysisModule.this, TmfAbstractAnalysisModule.this)); + fAnalysisCancelled = !executeAnalysis(monitor); + } catch (TmfAnalysisException e) { + Activator.logError("Error executing analysis with trace " + getTrace().getName(), e); //$NON-NLS-1$ + } finally { + synchronized (syncObj) { + monitor.done(); + setAnalysisCompleted(); + } + } + if (!fAnalysisCancelled) { + return Status.OK_STATUS; + } + return Status.CANCEL_STATUS; + } + + @Override + protected void canceling() { + TmfAbstractAnalysisModule.this.canceling(); + } + + }; + fJob.schedule(); + } + + @Override + public IStatus schedule() { + if (fTrace == null) { + return new Status(IStatus.ERROR, Activator.PLUGIN_ID, String.format("No trace specified for analysis %s", getName())); //$NON-NLS-1$ + } + execute(); + + return Status.OK_STATUS; + } + + @Override + public List getOutputs() { + return Collections.unmodifiableList(fOutputs); + } + + @Override + public void registerOutput(IAnalysisOutput output) { + if (!fOutputs.contains(output)) { + fOutputs.add(output); + } + } + + @Override + public boolean waitForCompletion(IProgressMonitor monitor) { + try { + while (!fFinishedLatch.await(1, TimeUnit.MILLISECONDS)) { + if (monitor.isCanceled()) { + fAnalysisCancelled = true; + return false; + } + } + } catch (InterruptedException e) { + Activator.logError("Error while waiting for module completion", e); //$NON-NLS-1$ + } + return !fAnalysisCancelled; + } + + /** + * Signal handler for trace closing + * + * @param signal + * Trace closed signal + */ + @TmfSignalHandler + public void traceClosed(TmfTraceClosedSignal signal) { + /* Is the closing trace the one that was requested? */ + if (signal.getTrace() == fTrace) { + cancel(); + fTrace = null; + } + } + + /** + * Returns a full help text to display + * + * @return Full help text for the module + */ + protected String getFullHelpText() { + return NLS.bind(Messages.TmfAbstractAnalysisModule_AnalysisModule, getName()); + } + + /** + * Gets a short help text, to display as header to other help text + * + * @param trace + * The trace to show help for + * + * @return Short help text describing the module + */ + protected String getShortHelpText(ITmfTrace trace) { + return NLS.bind(Messages.TmfAbstractAnalysisModule_AnalysisForTrace, getName(), trace.getName()); + } + + /** + * Gets the help text specific for a trace who does not have required + * characteristics for module to execute + * + * @param trace + * The trace to apply the analysis to + * @return Help text + */ + protected String getTraceCannotExecuteHelpText(ITmfTrace trace) { + return Messages.TmfAbstractAnalysisModule_AnalysisCannotExecute; + } + + @Override + public String getHelpText() { + return getFullHelpText(); + } + + @Override + public String getHelpText(ITmfTrace trace) { + if (trace == null) { + return getHelpText(); + } + String text = getShortHelpText(trace); + if (!canExecute(trace)) { + text = text + getTraceCannotExecuteHelpText(trace); + } + return text; + } + +} diff --git a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/TmfAbstractAnalysisParamProvider.java b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/TmfAbstractAnalysisParamProvider.java new file mode 100644 index 0000000000..cec9f213e3 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/TmfAbstractAnalysisParamProvider.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2013 É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 org.eclipse.linuxtools.tmf.core.analysis; + +/** + * Abstract class for parameter providers, implements methods and + * functionalities to warn the analysis module of parameter changed + * + * @author Geneviève Bastien + * @since 3.0 + */ +public abstract class TmfAbstractAnalysisParamProvider implements IAnalysisParameterProvider { + + /** + * The module registered with this provider + */ + private IAnalysisModule fModule; + + @Override + public void registerModule(IAnalysisModule module) { + if (module == null) { + throw new IllegalArgumentException(); + } + fModule = module; + } + + /** + * Gets the analysis module + * + * @return the {@link IAnalysisModule} associated with this provider + */ + protected IAnalysisModule getModule() { + return fModule; + } + + /** + * Notify the registered module that the said parameter has a new value. The + * analysis module will decide what to do with this information + * + * @param name + * Name of the modified parameter + */ + protected void notifyParameterChanged(String name) { + if (fModule != null) { + fModule.notifyParameterChanged(name); + } + } +} diff --git a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/TmfAnalysisManager.java b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/TmfAnalysisManager.java new file mode 100644 index 0000000000..9569bdae40 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/TmfAnalysisManager.java @@ -0,0 +1,148 @@ +/******************************************************************************* + * Copyright (c) 2013 É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 org.eclipse.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 org.eclipse.linuxtools.internal.tmf.core.Activator; +import org.eclipse.linuxtools.internal.tmf.core.analysis.TmfAnalysisType; +import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; + +/** + * Manages the available analysis helpers from different sources and their + * parameter providers. + * + * TODO: Add the concept of analysis source. Now only a plugin's extension point + * is implemented + * + * @author Geneviève Bastien + * @since 3.0 + */ +public class TmfAnalysisManager { + + private static final Map fAnalysisModules = new HashMap(); + private static final Map>> fParameterProviders = new HashMap>>(); + private static final Map, IAnalysisParameterProvider> fParamProviderInstances = new HashMap, IAnalysisParameterProvider>(); + + /** + * Gets all available analysis module helpers + * + * This map is read-only + * + * @return The map of available {@link IAnalysisModuleHelper} + */ + public static Map getAnalysisModules() { + synchronized (fAnalysisModules) { + if (fAnalysisModules.isEmpty()) { + TmfAnalysisType analysis = TmfAnalysisType.getInstance(); + fAnalysisModules.putAll(analysis.getAnalysisModules()); + } + } + 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 getAnalysisModules(Class traceclass) { + Map allModules = getAnalysisModules(); + Map 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 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 paramProvider) { + synchronized (fParameterProviders) { + if (!fParameterProviders.containsKey(analysisId)) { + fParameterProviders.put(analysisId, new ArrayList>()); + } + 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 getParameterProviders(IAnalysisModule module, ITmfTrace trace) { + List providerList = new ArrayList(); + synchronized (fParameterProviders) { + if (!fParameterProviders.containsKey(module.getId())) { + return providerList; + } + for (Class 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; + } + +} diff --git a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/TmfAnalysisModuleHelperCE.java b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/TmfAnalysisModuleHelperCE.java new file mode 100644 index 0000000000..74e0ae7de7 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/TmfAnalysisModuleHelperCE.java @@ -0,0 +1,145 @@ +/******************************************************************************* + * Copyright (c) 2013 É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 org.eclipse.linuxtools.tmf.core.analysis; + +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.linuxtools.internal.tmf.core.Activator; +import org.eclipse.linuxtools.internal.tmf.core.analysis.TmfAnalysisType; +import org.eclipse.linuxtools.tmf.core.exceptions.TmfAnalysisException; +import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; +import org.eclipse.osgi.util.NLS; +import org.osgi.framework.Bundle; + +/** + * Analysis module helper for modules provided by a plugin's configuration + * elements. + * + * @author Geneviève Bastien + */ +public class TmfAnalysisModuleHelperCE implements IAnalysisModuleHelper { + + private final IConfigurationElement fCe; + + /** + * Constructor + * + * @param ce + * The source {@link IConfigurationElement} of this module helper + */ + public TmfAnalysisModuleHelperCE(IConfigurationElement ce) { + fCe = ce; + } + + // ---------------------------------------- + // Wrappers to {@link IAnalysisModule} methods + // ---------------------------------------- + + @Override + public String getId() { + return fCe.getAttribute(TmfAnalysisType.ID_ATTR); + } + + @Override + public String getName() { + return fCe.getAttribute(TmfAnalysisType.NAME_ATTR); + } + + @Override + public boolean isAutomatic() { + return Boolean.valueOf(fCe.getAttribute(TmfAnalysisType.AUTOMATIC_ATTR)); + } + + @Override + public String getHelpText() { + return new String(); + } + + @Override + public String getIcon() { + return fCe.getAttribute(TmfAnalysisType.ICON_ATTR); + } + + @Override + public Bundle getBundle() { + return ContributorFactoryOSGi.resolve(fCe.getContributor()); + } + + @Override + public boolean appliesToTraceType(Class traceclass) { + boolean applies = false; + + /* Get the module's applying tracetypes */ + final IConfigurationElement[] tracetypeCE = fCe.getChildren(TmfAnalysisType.TRACETYPE_ELEM); + for (IConfigurationElement element : tracetypeCE) { + Class applyclass; + try { + applyclass = getBundle().loadClass(element.getAttribute(TmfAnalysisType.CLASS_ATTR)); + String classAppliesVal = element.getAttribute(TmfAnalysisType.APPLIES_ATTR); + boolean classApplies = true; + if (classAppliesVal != null) { + classApplies = Boolean.valueOf(classAppliesVal); + } + if (classApplies) { + applies = applyclass.isAssignableFrom(traceclass); + } else { + applies = !applyclass.isAssignableFrom(traceclass); + } + } catch (ClassNotFoundException e) { + Activator.logError("Error in applies to trace", e); //$NON-NLS-1$ + } catch (InvalidRegistryObjectException e) { + Activator.logError("Error in applies to trace", e); //$NON-NLS-1$ + } + } + return applies; + } + + // --------------------------------------- + // Functionalities + // --------------------------------------- + + @Override + public IAnalysisModule newModule(ITmfTrace trace) throws TmfAnalysisException { + + /* Check that analysis can be executed */ + if (!appliesToTraceType(trace.getClass())) { + throw new TmfAnalysisException(NLS.bind(Messages.TmfAnalysisModuleHelper_AnalysisDoesNotApply, getName())); + } + + IAnalysisModule module = null; + try { + module = (IAnalysisModule) fCe.createExecutableExtension(TmfAnalysisType.ANALYSIS_MODULE_ATTR); + module.setName(getName()); + module.setId(getId()); + module.setAutomatic(isAutomatic()); + + /* Get the module's parameters */ + final IConfigurationElement[] parametersCE = fCe.getChildren(TmfAnalysisType.PARAMETER_ELEM); + for (IConfigurationElement element : parametersCE) { + module.addParameter(element.getAttribute(TmfAnalysisType.NAME_ATTR)); + String defaultValue = element.getAttribute(TmfAnalysisType.DEFAULT_VALUE_ATTR); + if (defaultValue != null) { + module.setParameter(element.getAttribute(TmfAnalysisType.NAME_ATTR), defaultValue); + } + } + module.setTrace(trace); + } catch (CoreException e) { + Activator.logError("Error getting analysis modules from configuration files", e); //$NON-NLS-1$ + } + return module; + + } + +} diff --git a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/messages.properties b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/messages.properties new file mode 100644 index 0000000000..db370165ce --- /dev/null +++ b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/analysis/messages.properties @@ -0,0 +1,9 @@ +TmfAbstractAnalysisModule_TraceSetMoreThanOnce=Trace was set more than once for analysis "{0}" +TmfAbstractAnalysisModule_AnalysisCannotExecute=Cannot perform analysis "{0}" on this trace because the trace does not have the required characteristics +TmfAnalysisModuleHelper_AnalysisDoesNotApply=Cannot perform analysis "{0}" on this trace because the trace is of the wrong type. +TmfAbstractAnalysisModule_AnalysisForTrace=Analysis module: {0} for trace {1} +TmfAbstractAnalysisModule_AnalysisModule=Analysis module: {0} +TmfAbstractAnalysisModule_InvalidParameter=Parameter {0} is not valid for analysis module {1} +TmfAbstractAnalysisModule_RunningAnalysis=Running analysis {0} +TmfAnalysisManager_ErrorParameterProvider=Error instantiating parameter provider +TmfAnalysisModuleHelper_ImpossibleToCreateModule=Could not instantiate module "{0}" diff --git a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/exceptions/TmfAnalysisException.java b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/exceptions/TmfAnalysisException.java new file mode 100644 index 0000000000..8957d02380 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/exceptions/TmfAnalysisException.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2013 É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 org.eclipse.linuxtools.tmf.core.exceptions; + +/** + * Generic exception for an error or issue occurs in analysis setup and + * execution. + * + * For instance, to perform an analysis, a trace must be of the right type and + * have some characteristics. If trying to do an analysis on a trace that does + * not match, this exception is thrown. + * + * @author Geneviève Bastien + * @since 3.0 + */ +public class TmfAnalysisException extends Exception { + + private static final long serialVersionUID = -4567750551324478401L; + + /** + * Default constructor + */ + public TmfAnalysisException() { + super(); + } + + /** + * Constructor with a message + * + * @param message + * Message to attach to this exception + */ + public TmfAnalysisException(String message) { + super(message); + } + +} diff --git a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/signal/TmfStartAnalysisSignal.java b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/signal/TmfStartAnalysisSignal.java new file mode 100644 index 0000000000..5542a2cbf6 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/signal/TmfStartAnalysisSignal.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2013 É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 implementation and API + *******************************************************************************/ + +package org.eclipse.linuxtools.tmf.core.signal; + +import org.eclipse.linuxtools.tmf.core.analysis.IAnalysisModule; + +/** + * Signal indicating an analysis has started. Views and outputs may use it to + * update themselves with the results. + * + * @author Geneviève Bastien + * @since 3.0 + */ +public class TmfStartAnalysisSignal extends TmfSignal { + + private final IAnalysisModule fModule; + + /** + * Constructor for a new signal. + * + * @param source + * The object sending this signal + * @param module + * The analysis module + */ + public TmfStartAnalysisSignal(Object source, IAnalysisModule module) { + super(source); + fModule = module; + } + + /** + * Get the trace object concerning this signal + * + * @return The trace + */ + public IAnalysisModule getAnalysisModule() { + return fModule; + } + + @Override + public String toString() { + return "[" + this.getClass().getSimpleName() + " (" + fModule.getName() + ")]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } +} diff --git a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/trace/ITmfTrace.java b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/trace/ITmfTrace.java index b0f0a38cae..8d858d193f 100644 --- a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/trace/ITmfTrace.java +++ b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/trace/ITmfTrace.java @@ -16,11 +16,13 @@ package org.eclipse.linuxtools.tmf.core.trace; import java.util.Collections; +import java.util.List; import java.util.Map; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IStatus; +import org.eclipse.linuxtools.tmf.core.analysis.IAnalysisModule; import org.eclipse.linuxtools.tmf.core.component.ITmfDataProvider; import org.eclipse.linuxtools.tmf.core.event.ITmfEvent; import org.eclipse.linuxtools.tmf.core.exceptions.TmfTraceException; @@ -235,6 +237,35 @@ public interface ITmfTrace extends ITmfDataProvider { */ void indexTrace(boolean waitForCompletion); + /** + * Returns an analysis module with the given id + * + * @param analysisId + * The analysis module id + * @return The {@link IAnalysisModule} object + */ + IAnalysisModule getAnalysisModule(String analysisId); + + /** + * Return a list of analysis modules that are of a given class + * + * @param moduleclass + * Class returned module must extend + * @return List of {@link IAnalysisModule} of class moduleclass + */ + List getAnalysisModules(Class moduleclass); + + /** + * Returns a map of analysis modules applicable to this trace. The key is + * the analysis id. + * + * This view should be read-only (implementations should use + * {@link Collections#unmodifiableMap}). + * + * @return The map of analysis modules + */ + Map getAnalysisModules(); + // ------------------------------------------------------------------------ // Trace characteristics getters // ------------------------------------------------------------------------ diff --git a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/trace/TmfTrace.java b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/trace/TmfTrace.java index c5f0d16a61..cf6e97e5e3 100644 --- a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/trace/TmfTrace.java +++ b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/trace/TmfTrace.java @@ -23,9 +23,12 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; +import java.util.Map.Entry; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IResource; @@ -36,8 +39,12 @@ import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.linuxtools.internal.tmf.core.Activator; import org.eclipse.linuxtools.tmf.core.TmfCommonConstants; +import org.eclipse.linuxtools.tmf.core.analysis.IAnalysisModule; +import org.eclipse.linuxtools.tmf.core.analysis.IAnalysisModuleHelper; +import org.eclipse.linuxtools.tmf.core.analysis.TmfAnalysisManager; import org.eclipse.linuxtools.tmf.core.component.TmfEventProvider; import org.eclipse.linuxtools.tmf.core.event.ITmfEvent; +import org.eclipse.linuxtools.tmf.core.exceptions.TmfAnalysisException; import org.eclipse.linuxtools.tmf.core.exceptions.TmfTraceException; import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest; import org.eclipse.linuxtools.tmf.core.request.ITmfEventRequest; @@ -131,6 +138,9 @@ public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace { private ITmfTimestampTransform fTsTransform; + private final Map fAnalysisModules = + new LinkedHashMap(); + private static final String SYNCHRONIZATION_FORMULA_FILE = "sync_formula"; //$NON-NLS-1$ // ------------------------------------------------------------------------ @@ -310,6 +320,52 @@ public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace { return Status.OK_STATUS; } + /** + * Instantiate the applicable analysis modules and executes the analysis + * modules that are meant to be automatically executed + * + * @return An IStatus indicating whether the analysis could be run + * successfully or not + * @since 3.0 + */ + protected IStatus executeAnalysis() { + MultiStatus status = new MultiStatus(Activator.PLUGIN_ID, IStatus.OK, null, null); + Map modules = TmfAnalysisManager.getAnalysisModules(this.getClass()); + for (IAnalysisModuleHelper helper : modules.values()) { + try { + IAnalysisModule module = helper.newModule(this); + fAnalysisModules.put(module.getId(), module); + if (module.isAutomatic()) { + status.add(module.schedule()); + } + } catch (TmfAnalysisException e) { + status.add(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e)); + } + } + return status; + } + + @Override + public final IAnalysisModule getAnalysisModule(String analysisId) { + return fAnalysisModules.get(analysisId); + } + + @Override + public List getAnalysisModules(Class moduleclass) { + List modules = new ArrayList(); + for (Entry entry : fAnalysisModules.entrySet()) { + if (moduleclass.isAssignableFrom(entry.getValue().getClass())) { + modules.add(entry.getValue()); + } + } + return modules; + } + + @Override + public Map getAnalysisModules() { + return Collections.unmodifiableMap(fAnalysisModules); + } + /** * Clears the trace */ @@ -695,6 +751,7 @@ public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace { MultiStatus status = new MultiStatus(Activator.PLUGIN_ID, IStatus.OK, null, null); status.add(buildStatistics()); status.add(buildStateSystem()); + status.add(executeAnalysis()); if (!status.isOK()) { Activator.log(status); } diff --git a/org.eclipse.linuxtools.tmf.ui.tests/plugin.xml b/org.eclipse.linuxtools.tmf.ui.tests/plugin.xml index bca93b451c..99128a39f9 100644 --- a/org.eclipse.linuxtools.tmf.ui.tests/plugin.xml +++ b/org.eclipse.linuxtools.tmf.ui.tests/plugin.xml @@ -24,7 +24,14 @@ name="TestSDView2Loaders" restorable="true"> - + + + + + + + + + + + diff --git a/org.eclipse.linuxtools.tmf.ui.tests/src/org/eclipse/linuxtools/tmf/ui/tests/project/model/AllTests.java b/org.eclipse.linuxtools.tmf.ui.tests/src/org/eclipse/linuxtools/tmf/ui/tests/project/model/AllTests.java index 57af25c4d4..d74726b7f4 100644 --- a/org.eclipse.linuxtools.tmf.ui.tests/src/org/eclipse/linuxtools/tmf/ui/tests/project/model/AllTests.java +++ b/org.eclipse.linuxtools.tmf.ui.tests/src/org/eclipse/linuxtools/tmf/ui/tests/project/model/AllTests.java @@ -16,11 +16,13 @@ import org.junit.runner.RunWith; import org.junit.runners.Suite; /** - * Test suite for org.eclipse.linuxtools.tmf.ui.project.model + * Test suite for org.eclipse.linuxtools.tmf.ui.project.model */ @RunWith(Suite.class) @Suite.SuiteClasses({ - ProjectModelTraceTest.class + ProjectModelAnalysisTest.class, + ProjectModelOutputTest.class, + ProjectModelTraceTest.class }) public class AllTests { diff --git a/org.eclipse.linuxtools.tmf.ui.tests/src/org/eclipse/linuxtools/tmf/ui/tests/project/model/ProjectModelAnalysisTest.java b/org.eclipse.linuxtools.tmf.ui.tests/src/org/eclipse/linuxtools/tmf/ui/tests/project/model/ProjectModelAnalysisTest.java new file mode 100644 index 0000000000..b999f8817b --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui.tests/src/org/eclipse/linuxtools/tmf/ui/tests/project/model/ProjectModelAnalysisTest.java @@ -0,0 +1,165 @@ +/******************************************************************************* + * Copyright (c) 2013 É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 org.eclipse.linuxtools.tmf.ui.tests.project.model; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; +import static org.junit.Assume.assumeTrue; + +import java.util.List; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.linuxtools.tmf.core.tests.shared.CtfTmfTestTrace; +import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; +import org.eclipse.linuxtools.tmf.ui.project.model.ITmfProjectModelElement; +import org.eclipse.linuxtools.tmf.ui.project.model.TmfAnalysisElement; +import org.eclipse.linuxtools.tmf.ui.project.model.TmfNavigatorContentProvider; +import org.eclipse.linuxtools.tmf.ui.project.model.TmfProjectElement; +import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceElement; +import org.eclipse.linuxtools.tmf.ui.tests.stubs.analysis.TestAnalysisUi; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * Test suite for the {@link TmfAnalysisElement} class. + * + * @author Geneviève Bastien + */ +public class ProjectModelAnalysisTest { + + /** ID of analysis module in UI */ + public static final String MODULE_UI = "org.eclipse.linuxtools.tmf.ui.tests.test"; + private TmfProjectElement fixture; + + /** + * Perform pre-test initialization. + */ + @Before + public void setUp() { + assumeTrue(CtfTmfTestTrace.KERNEL.exists()); + try { + fixture = ProjectModelTestData.getFilledProject(); + } catch (CoreException e) { + fail(e.getMessage()); + } + } + + /** + * Cleans up the project after tests have been executed + */ + @After + public void cleanUp() { + ProjectModelTestData.deleteProject(fixture); + } + + private TmfTraceElement getTraceElement() { + TmfTraceElement trace = null; + for (ITmfProjectModelElement element : fixture.getTracesFolder().getChildren()) { + if (element instanceof TmfTraceElement) { + TmfTraceElement traceElement = (TmfTraceElement) element; + if (traceElement.getName().equals(ProjectModelTestData.getTraceName())) { + trace = traceElement; + } + } + } + assertNotNull(trace); + return trace; + } + + /** + * Test the getAvailableAnalysis() method + */ + @Test + public void testListAnalysis() { + TmfTraceElement trace = getTraceElement(); + + /* Make sure the analysis list is not empty */ + List analysisList = trace.getAvailableAnalysis(); + assertFalse(analysisList.isEmpty()); + + /* Make sure TestAnalysisUi is there */ + TmfAnalysisElement analysis = null; + for (TmfAnalysisElement analysisElement : analysisList) { + if (analysisElement.getAnalysisId().equals(MODULE_UI)) { + analysis = analysisElement; + } + } + assertNotNull(analysis); + + assertEquals("Test analysis in UI", analysis.getName()); + } + + /** + * Test if the list of available analysis is correctly populated by the + * content provider + */ + @Test + public void testPopulate() { + TmfTraceElement trace = getTraceElement(); + + final TmfNavigatorContentProvider ncp = new TmfNavigatorContentProvider(); + // force the model to be populated + ncp.getChildren(fixture); + + /* Make sure the analysis list is not empty */ + List analysisList = trace.getChildren(); + assertFalse(analysisList.isEmpty()); + + /* Make sure TestAnalysisUi is there */ + TmfAnalysisElement analysis = null; + for (ITmfProjectModelElement element : analysisList) { + if (element instanceof TmfAnalysisElement) { + TmfAnalysisElement analysisElement = (TmfAnalysisElement) element; + if (analysisElement.getAnalysisId().equals(MODULE_UI)) { + analysis = analysisElement; + } + } + } + assertNotNull(analysis); + + assertEquals("Test analysis in UI", analysis.getName()); + } + + /** + * Test the instantiateAnalysis method + */ + @Test + public void testInstantiate() { + TmfTraceElement traceElement = getTraceElement(); + + TmfAnalysisElement analysis = null; + for (TmfAnalysisElement analysisElement : traceElement.getAvailableAnalysis()) { + if (analysisElement.getAnalysisId().equals(MODULE_UI)) { + analysis = analysisElement; + } + } + assertNotNull(analysis); + + /* Instantiate an analysis on a trace that is closed */ + traceElement.closeEditors(); + analysis.activateParent(); + + /* Give some time to the trace to open */ + ProjectModelTestData.delayThread(1000); + + /* Get the analysis module associated with the element */ + ITmfTrace trace = traceElement.getTrace(); + assertNotNull(trace); + TestAnalysisUi module = (TestAnalysisUi) trace.getAnalysisModule(analysis.getAnalysisId()); + assertNotNull(module); + + } +} diff --git a/org.eclipse.linuxtools.tmf.ui.tests/src/org/eclipse/linuxtools/tmf/ui/tests/project/model/ProjectModelOutputTest.java b/org.eclipse.linuxtools.tmf.ui.tests/src/org/eclipse/linuxtools/tmf/ui/tests/project/model/ProjectModelOutputTest.java new file mode 100644 index 0000000000..52a5cf6cf6 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui.tests/src/org/eclipse/linuxtools/tmf/ui/tests/project/model/ProjectModelOutputTest.java @@ -0,0 +1,161 @@ +/******************************************************************************* + * Copyright (c) 2013 É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 org.eclipse.linuxtools.tmf.ui.tests.project.model; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.List; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.linuxtools.tmf.ui.project.model.ITmfProjectModelElement; +import org.eclipse.linuxtools.tmf.ui.project.model.TmfAnalysisElement; +import org.eclipse.linuxtools.tmf.ui.project.model.TmfAnalysisOutputElement; +import org.eclipse.linuxtools.tmf.ui.project.model.TmfProjectElement; +import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceElement; +import org.eclipse.linuxtools.tmf.ui.tests.stubs.analysis.TestAnalysisUi; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PlatformUI; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * Test suite for the {@link TmfAnalysisOutputElement} class. + * + * @author Geneviève Bastien + */ +public class ProjectModelOutputTest { + + private TmfProjectElement fixture; + + /** + * Perform pre-test initialization. + */ + @Before + public void setUp() { + try { + fixture = ProjectModelTestData.getFilledProject(); + } catch (CoreException e) { + fail(e.getMessage()); + } + } + + /** + * Cleans up the project after tests have been executed + */ + @After + public void cleanUp() { + ProjectModelTestData.deleteProject(fixture); + } + + private TmfTraceElement getTraceElement() { + TmfTraceElement trace = null; + for (ITmfProjectModelElement element : fixture.getTracesFolder().getChildren()) { + if (element instanceof TmfTraceElement) { + TmfTraceElement traceElement = (TmfTraceElement) element; + if (traceElement.getName().equals(ProjectModelTestData.getTraceName())) { + trace = traceElement; + } + } + } + assertNotNull(trace); + return trace; + } + + private TmfAnalysisElement getTestAnalysisUi() { + TmfTraceElement trace = getTraceElement(); + + /* Make sure the analysis list is not empty */ + List analysisList = trace.getAvailableAnalysis(); + assertFalse(analysisList.isEmpty()); + + /* Make sure TestAnalysisUi is there */ + TmfAnalysisElement analysis = null; + for (TmfAnalysisElement analysisElement : analysisList) { + if (analysisElement.getAnalysisId().equals(ProjectModelAnalysisTest.MODULE_UI)) { + analysis = analysisElement; + } + } + assertNotNull(analysis); + return analysis; + } + + /** + * Test the getAvailableOutputs() method + */ + @Test + public void testListOutputs() { + TmfAnalysisElement analysis = getTestAnalysisUi(); + + /* To get the list of outputs the trace needs to be opened */ + analysis.activateParent(); + ProjectModelTestData.delayThread(500); + + /* Make sure the output list is not empty */ + List outputList = analysis.getAvailableOutputs(); + assertFalse(outputList.isEmpty()); + boolean found = false; + for (ITmfProjectModelElement element : outputList) { + if (element instanceof TmfAnalysisOutputElement) { + TmfAnalysisOutputElement outputElement = (TmfAnalysisOutputElement) element; + if (outputElement.getName().equals("Test Analysis View")) { + found = true; + } + } + } + assertTrue(found); + } + + /** + * Test the outputAnalysis method for a view + */ + @Test + public void testOpenView() { + TmfAnalysisElement analysis = getTestAnalysisUi(); + + analysis.activateParent(); + ProjectModelTestData.delayThread(1000); + + List outputList = analysis.getAvailableOutputs(); + assertFalse(outputList.isEmpty()); + + final IWorkbench wb = PlatformUI.getWorkbench(); + final IWorkbenchPage activePage = wb.getActiveWorkbenchWindow().getActivePage(); + + IViewPart view = activePage.findView(TestAnalysisUi.VIEW_ID); + if (view != null) { + activePage.hideView(view); + } + + TmfAnalysisOutputElement outputElement = null; + for (ITmfProjectModelElement element : outputList) { + if (element instanceof TmfAnalysisOutputElement) { + TmfAnalysisOutputElement el = (TmfAnalysisOutputElement) element; + if (el.getName().equals("Test Analysis View")) { + outputElement = el; + } + } + } + assertNotNull(outputElement); + + outputElement.outputAnalysis(); + ProjectModelTestData.delayThread(1000); + view = activePage.findView(TestAnalysisUi.VIEW_ID); + assertNotNull(view); + } +} diff --git a/org.eclipse.linuxtools.tmf.ui.tests/src/org/eclipse/linuxtools/tmf/ui/tests/project/model/ProjectModelTestData.java b/org.eclipse.linuxtools.tmf.ui.tests/src/org/eclipse/linuxtools/tmf/ui/tests/project/model/ProjectModelTestData.java index 8eec93b643..05619b91b1 100644 --- a/org.eclipse.linuxtools.tmf.ui.tests/src/org/eclipse/linuxtools/tmf/ui/tests/project/model/ProjectModelTestData.java +++ b/org.eclipse.linuxtools.tmf.ui.tests/src/org/eclipse/linuxtools/tmf/ui/tests/project/model/ProjectModelTestData.java @@ -12,6 +12,8 @@ package org.eclipse.linuxtools.tmf.ui.tests.project.model; +import static org.junit.Assume.assumeTrue; + import java.io.File; import org.eclipse.core.resources.IFolder; @@ -21,6 +23,7 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; +import org.eclipse.linuxtools.internal.tmf.ui.Activator; import org.eclipse.linuxtools.internal.tmf.ui.project.model.TmfImportHelper; import org.eclipse.linuxtools.tmf.core.TmfCommonConstants; import org.eclipse.linuxtools.tmf.core.tests.shared.CtfTmfTestTrace; @@ -34,6 +37,8 @@ import org.eclipse.swt.widgets.Display; /** * Creates objects used for this package's testing purposes + * + * @author Geneviève Bastien */ public class ProjectModelTestData { @@ -51,6 +56,8 @@ public class ProjectModelTestData { */ public static TmfProjectElement getFilledProject() throws CoreException { + assumeTrue(CtfTmfTestTrace.KERNEL.exists()); + IProject project = TmfProjectRegistry.createProject(PROJECT_NAME, null, null); IFolder traceFolder = project.getFolder(TmfTraceFolder.TRACE_FOLDER_NAME); @@ -63,7 +70,7 @@ public class ProjectModelTestData { return null; } linkedTrace.setPersistentProperty(TmfCommonConstants.TRACETYPE, - "org.eclipse.linuxtools.tmf.ui.type.ctf"); + "org.eclipse.linuxtools.tmf.tests.ctf.tracetype"); final TmfProjectElement projectElement = TmfProjectRegistry.getProject(project, true); TmfTraceElement traceElement = projectElement.getTracesFolder().getTraces().get(0); @@ -89,10 +96,8 @@ public class ProjectModelTestData { * * @param project * Project to delete - * @throws CoreException - * Thrown by the resource deletion */ - public static void deleteProject(TmfProjectElement project) throws CoreException { + public static void deleteProject(TmfProjectElement project) { /* Delete experiments */ for (ITmfProjectModelElement element : project.getExperimentsFolder().getChildren()) { if (element instanceof TmfExperimentElement) { @@ -109,7 +114,11 @@ public class ProjectModelTestData { } /* Finally, delete the experiment */ - resource.delete(true, null); + try { + resource.delete(true, null); + } catch (CoreException e) { + Activator.getDefault().logError("Error deleting experiment element", e); + } } } @@ -129,12 +138,20 @@ public class ProjectModelTestData { } /* Finally, delete the trace */ - resource.delete(true, new NullProgressMonitor()); + try { + resource.delete(true, new NullProgressMonitor()); + } catch (CoreException e) { + Activator.getDefault().logError("Error deleting trace element", e); + } } } /* Delete the project itself */ - project.getResource().delete(true, null); + try { + project.getResource().delete(true, null); + } catch (CoreException e) { + Activator.getDefault().logError("Error deleting project", e); + } } /** diff --git a/org.eclipse.linuxtools.tmf.ui.tests/src/org/eclipse/linuxtools/tmf/ui/tests/project/model/ProjectModelTraceTest.java b/org.eclipse.linuxtools.tmf.ui.tests/src/org/eclipse/linuxtools/tmf/ui/tests/project/model/ProjectModelTraceTest.java index ba3260d7d6..ff3ed43b54 100644 --- a/org.eclipse.linuxtools.tmf.ui.tests/src/org/eclipse/linuxtools/tmf/ui/tests/project/model/ProjectModelTraceTest.java +++ b/org.eclipse.linuxtools.tmf.ui.tests/src/org/eclipse/linuxtools/tmf/ui/tests/project/model/ProjectModelTraceTest.java @@ -31,6 +31,8 @@ import org.junit.Test; /** * Test suite for the TmfTraceElement class. + * + * @author Geneviève Bastien */ public class ProjectModelTraceTest { @@ -54,11 +56,7 @@ public class ProjectModelTraceTest { */ @After public void cleanUp() { - try { - ProjectModelTestData.deleteProject(fixture); - } catch (CoreException e) { - fail(e.getMessage()); - } + ProjectModelTestData.deleteProject(fixture); } /** @@ -79,7 +77,7 @@ public class ProjectModelTraceTest { TmfOpenTraceHelper.openTraceFromElement(traceElement); /* Give the trace a chance to open */ - ProjectModelTestData.delayThread(5000); + ProjectModelTestData.delayThread(500); trace = traceElement.getTrace(); assertNotNull(trace); @@ -89,7 +87,7 @@ public class ProjectModelTraceTest { * the exact same element as the active trace */ TmfOpenTraceHelper.openTraceFromElement(traceElement); - ProjectModelTestData.delayThread(5000); + ProjectModelTestData.delayThread(500); ITmfTrace trace2 = TmfTraceManager.getInstance().getActiveTrace(); diff --git a/org.eclipse.linuxtools.tmf.ui.tests/widgetStubs/org/eclipse/linuxtools/tmf/ui/tests/stubs/analysis/TestAnalysisUi.java b/org.eclipse.linuxtools.tmf.ui.tests/widgetStubs/org/eclipse/linuxtools/tmf/ui/tests/stubs/analysis/TestAnalysisUi.java new file mode 100644 index 0000000000..b56a9eca95 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui.tests/widgetStubs/org/eclipse/linuxtools/tmf/ui/tests/stubs/analysis/TestAnalysisUi.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) 2013 É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 org.eclipse.linuxtools.tmf.ui.tests.stubs.analysis; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.linuxtools.tmf.core.analysis.TmfAbstractAnalysisModule; +import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; +import org.eclipse.linuxtools.tmf.ui.analysis.TmfAnalysisViewOutput; + +/** + * Stub for an analysis module with outputs + */ +public class TestAnalysisUi extends TmfAbstractAnalysisModule { + + /** ID of the view opened by this analysis module */ + public static final String VIEW_ID = "org.eclipse.linuxtools.tmf.ui.tests.testAnalysisView"; + + private String fTraceName; + + /** + * Constructor + */ + public TestAnalysisUi() { + super(); + registerOutput(new TmfAnalysisViewOutput(VIEW_ID)); + } + + @Override + protected boolean executeAnalysis(final IProgressMonitor monitor) { + return false; + } + + @Override + protected void canceling() { + + } + + @Override + public ITmfTrace getTrace() { + return super.getTrace(); + } + + /** + * Returns the name of the trace that should be set + * + * @return Name of the trace + */ + public String getTraceName() { + return fTraceName; + } + +} diff --git a/org.eclipse.linuxtools.tmf.ui/META-INF/MANIFEST.MF b/org.eclipse.linuxtools.tmf.ui/META-INF/MANIFEST.MF index 5c14b58751..d8878da334 100644 --- a/org.eclipse.linuxtools.tmf.ui/META-INF/MANIFEST.MF +++ b/org.eclipse.linuxtools.tmf.ui/META-INF/MANIFEST.MF @@ -26,6 +26,7 @@ Export-Package: org.eclipse.linuxtools.internal.tmf.ui;x-friends:="org.eclipse.l org.eclipse.linuxtools.internal.tmf.ui.project.dialogs;x-internal:=true, org.eclipse.linuxtools.internal.tmf.ui.project.handlers;x-internal:=true, org.eclipse.linuxtools.internal.tmf.ui.project.model;x-friends:="org.eclipse.linuxtools.lttng2.ui,org.eclipse.linuxtools.tmf.ui.tests", + org.eclipse.linuxtools.tmf.ui.analysis, org.eclipse.linuxtools.tmf.ui.editors, org.eclipse.linuxtools.tmf.ui.project.model, org.eclipse.linuxtools.tmf.ui.project.wizards, diff --git a/org.eclipse.linuxtools.tmf.ui/plugin.properties b/org.eclipse.linuxtools.tmf.ui/plugin.properties index 363e56b37f..dc1feac866 100644 --- a/org.eclipse.linuxtools.tmf.ui/plugin.properties +++ b/org.eclipse.linuxtools.tmf.ui/plugin.properties @@ -132,7 +132,12 @@ commands.parser.category.name = Parser Commands commands.parser.category.description = Parser Commands commands.parser.manage = Manage Custom Parsers... commands.parser.manage.description = Manage Custom Parsers - + +## Analysis and views +command.analysis_help = Help +command.analysis_help.mnemonic = H +command.analysis_help.description = Help + contenttype.trace = TMF Trace parser.provider.extension-point.name = Parser Providers diff --git a/org.eclipse.linuxtools.tmf.ui/plugin.xml b/org.eclipse.linuxtools.tmf.ui/plugin.xml index bfce198952..e57b56be64 100644 --- a/org.eclipse.linuxtools.tmf.ui/plugin.xml +++ b/org.eclipse.linuxtools.tmf.ui/plugin.xml @@ -405,6 +405,9 @@ + + @@ -736,6 +739,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/handlers/Messages.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/handlers/Messages.java index e429401771..50dd428bf5 100644 --- a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/handlers/Messages.java +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/handlers/Messages.java @@ -50,6 +50,8 @@ public class Messages extends NLS { public static String SynchronizeTracesHandler_ErrorSynchingExperiment; public static String SynchronizeTracesHandler_ErrorSynchingForTrace; + public static String AnalysisModule_Help; + static { // initialize resource bundle NLS.initializeMessages(BUNDLE_NAME, Messages.class); diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/handlers/OpenAction.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/handlers/OpenAction.java index 5ce88c7fdb..70b418bb6b 100644 --- a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/handlers/OpenAction.java +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/handlers/OpenAction.java @@ -21,6 +21,7 @@ import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.linuxtools.internal.tmf.ui.Activator; +import org.eclipse.linuxtools.tmf.ui.project.model.TmfAnalysisOutputElement; import org.eclipse.linuxtools.tmf.ui.project.model.TmfExperimentElement; import org.eclipse.linuxtools.tmf.ui.project.model.TmfProjectModelElement; import org.eclipse.linuxtools.tmf.ui.project.model.TmfTraceElement; @@ -29,9 +30,6 @@ import org.eclipse.ui.handlers.IHandlerService; /** * OpenAction - *

- * Implement me. Please. - *

*/ public class OpenAction extends Action { @@ -58,7 +56,8 @@ public class OpenAction extends Action { IStructuredSelection sSelection = (IStructuredSelection) selection; if (sSelection.size() == 1) { if (sSelection.getFirstElement() instanceof TmfTraceElement || - sSelection.getFirstElement() instanceof TmfExperimentElement) { + sSelection.getFirstElement() instanceof TmfExperimentElement || + sSelection.getFirstElement() instanceof TmfAnalysisOutputElement) { element = (TmfProjectModelElement) sSelection.getFirstElement(); return true; } @@ -71,7 +70,7 @@ public class OpenAction extends Action { public void run() { try { IHandlerService handlerService = (IHandlerService) page.getActivePart().getSite().getService(IHandlerService.class); - boolean executeCommand = (element instanceof TmfTraceElement); + boolean executeCommand = ((element instanceof TmfTraceElement) || (element instanceof TmfAnalysisOutputElement)); if (!executeCommand && element instanceof TmfExperimentElement) { TmfExperimentElement experiment = (TmfExperimentElement) element; diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/handlers/OpenAnalysisHelpHandler.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/handlers/OpenAnalysisHelpHandler.java new file mode 100644 index 0000000000..6ad18fce45 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/handlers/OpenAnalysisHelpHandler.java @@ -0,0 +1,114 @@ +/******************************************************************************* + * Copyright (c) 2013 É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 org.eclipse.linuxtools.internal.tmf.ui.project.handlers; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.linuxtools.tmf.ui.project.model.TmfAnalysisElement; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.MessageBox; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; + +/** + * Handler for when user wants to open the analysis help text + * + * @author Geneviève Bastien + */ +public class OpenAnalysisHelpHandler extends AbstractHandler { + + private TmfAnalysisElement fAnalysis; + + @Override + public boolean isEnabled() { + // Check if we are closing down + final IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + if (window == null) { + return false; + } + + // Get the selection + final IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + final IWorkbenchPart part = page.getActivePart(); + if (part == null) { + return false; + } + final ISelectionProvider selectionProvider = part.getSite().getSelectionProvider(); + if (selectionProvider == null) { + return false; + } + final ISelection selection = selectionProvider.getSelection(); + + // Make sure there is only one selection and that it is a trace + fAnalysis = null; + if (selection instanceof TreeSelection) { + final TreeSelection sel = (TreeSelection) selection; + // There should be only one item selected as per the plugin.xml + final Object element = sel.getFirstElement(); + if (element instanceof TmfAnalysisElement) { + fAnalysis = (TmfAnalysisElement) element; + } + } + + return (fAnalysis != null); + } + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + + // Check if we are closing down + final IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + if (window == null) { + return null; + } + + // Check that the trace is valid + if (fAnalysis == null) { + return null; + } + + Thread thread = new Thread() { + @Override + public void run() { + displayHelpMsg(fAnalysis.getHelpMessage()); + } + }; + + thread.start(); + + return null; + } + + private static void displayHelpMsg(final String errorMsg) { + Display.getDefault().asyncExec(new Runnable() { + @Override + public void run() { + /* + * TODO: A message box is not the best place to show help. + * Something should be done with the Eclipse help + */ + final MessageBox mb = new MessageBox(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell()); + mb.setText(Messages.AnalysisModule_Help); + mb.setMessage(errorMsg); + mb.open(); + } + }); + } + +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/handlers/OpenAnalysisOutputHandler.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/handlers/OpenAnalysisOutputHandler.java new file mode 100644 index 0000000000..772450d16b --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/handlers/OpenAnalysisOutputHandler.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * Copyright (c) 2013 É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 org.eclipse.linuxtools.internal.tmf.ui.project.handlers; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.linuxtools.tmf.ui.project.model.TmfAnalysisOutputElement; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; + +/** + * Handler to programatically open a view + * + * @author Geneviève Bastien + */ +public class OpenAnalysisOutputHandler extends AbstractHandler { + + private TmfAnalysisOutputElement fOutputElement; + + @Override + public boolean isEnabled() { + /* Check if we are closing down */ + final IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + if (window == null) { + return false; + } + + /* Get the selection */ + final IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + final IWorkbenchPart part = page.getActivePart(); + if (part == null) { + return false; + } + final ISelectionProvider selectionProvider = part.getSite().getSelectionProvider(); + if (selectionProvider == null) { + return false; + } + final ISelection selection = selectionProvider.getSelection(); + + /* Make sure there is only one selection and that it is an analysis output */ + fOutputElement = null; + if (selection instanceof TreeSelection) { + final TreeSelection sel = (TreeSelection) selection; + // There should be only one item selected as per the plugin.xml + final Object element = sel.getFirstElement(); + if (element instanceof TmfAnalysisOutputElement) { + fOutputElement = (TmfAnalysisOutputElement) element; + } + } + + return (fOutputElement != null); + } + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + + /* Check if we are closing down */ + final IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + if (window == null) { + return null; + } + + /* Check that the view is valid */ + if (fOutputElement == null) { + return null; + } + + fOutputElement.outputAnalysis(); + + return null; + } + +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/handlers/messages.properties b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/handlers/messages.properties index ba2d8e31ce..a284e5fbfa 100644 --- a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/handlers/messages.properties +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/internal/tmf/ui/project/handlers/messages.properties @@ -38,3 +38,6 @@ SynchronizeTracesHandler_Error=Error synchronizing experiment SynchronizeTracesHandler_ErrorSynchingExperiment=Error synchronizing experiment %s SynchronizeTracesHandler_ErrorSynchingForTrace=Error synchronizing experiment %s for trace %s + +# Analysis modules +AnalysisModule_Help=Help diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/analysis/TmfAnalysisViewOutput.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/analysis/TmfAnalysisViewOutput.java new file mode 100644 index 0000000000..d5de7d09a7 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/analysis/TmfAnalysisViewOutput.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) 2013 É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 org.eclipse.linuxtools.tmf.ui.analysis; + +import org.eclipse.linuxtools.internal.tmf.ui.Activator; +import org.eclipse.linuxtools.tmf.core.analysis.IAnalysisOutput; +import org.eclipse.linuxtools.tmf.ui.project.model.Messages; +import org.eclipse.linuxtools.tmf.ui.project.model.TraceUtils; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.views.IViewDescriptor; + +/** + * Class that implements analysis output as a view. This just opens the view. + * The view itself needs to manage how and when it will execute the analysis and + * display which output. + * + * @author Geneviève Bastien + * @since 3.0 + */ +public class TmfAnalysisViewOutput implements IAnalysisOutput { + + private final String fViewId; + + /** + * Constructor + * + * @param viewid + * id of the view to display as output + */ + public TmfAnalysisViewOutput(String viewid) { + fViewId = viewid; + } + + /** + * Returns the view id of the corresponding view + * + * @return The view id + */ + public String getViewId() { + return fViewId; + } + + @Override + public String getName() { + IViewDescriptor descr = PlatformUI.getWorkbench().getViewRegistry().find(fViewId); + String viewName = (descr != null) ? descr.getLabel() : fViewId + Messages.TmfAnalysisViewOutput_ViewUnavailable; + return viewName; + } + + @Override + public void requestOutput() { + Display.getDefault().asyncExec(new Runnable() { + @Override + public void run() { + + try { + final IWorkbench wb = PlatformUI.getWorkbench(); + final IWorkbenchPage activePage = wb.getActiveWorkbenchWindow().getActivePage(); + + activePage.showView(fViewId); + + } catch (final PartInitException e) { + TraceUtils.displayErrorMsg(Messages.TmfAnalysisViewOutput_Title, "Error opening view " + getName() + e.getMessage()); //$NON-NLS-1$ + Activator.getDefault().logError("Error opening view " + getName(), e); //$NON-NLS-1$ + } + } + }); + } +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/Messages.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/Messages.java index cce6f8e33f..ea715be924 100644 --- a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/Messages.java +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/Messages.java @@ -24,6 +24,12 @@ public class Messages extends NLS { private static final String BUNDLE_NAME = "org.eclipse.linuxtools.tmf.ui.project.model.messages"; //$NON-NLS-1$ + /** Instantiate analysis message box title */ + public static String TmfAnalysisElement_InstantiateAnalysis; + + /** The message when analysis view is not available */ + public static String TmfAnalysisViewOutput_ViewUnavailable; + /** The category of the resource properties */ public static String TmfTraceElement_ResourceProperties; @@ -68,6 +74,9 @@ public class Messages extends NLS { /** Init error */ public static String TmfOpenTraceHelper_InitError; + /** Analysis view title */ + public static String TmfAnalysisViewOutput_Title; + static { // initialize resource bundle NLS.initializeMessages(BUNDLE_NAME, Messages.class); diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TmfAnalysisElement.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TmfAnalysisElement.java new file mode 100644 index 0000000000..559a655f46 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TmfAnalysisElement.java @@ -0,0 +1,178 @@ +/******************************************************************************* + * Copyright (c) 2013 É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 org.eclipse.linuxtools.tmf.ui.project.model; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.IPath; +import org.eclipse.linuxtools.tmf.core.analysis.IAnalysisModule; +import org.eclipse.linuxtools.tmf.core.analysis.IAnalysisModuleHelper; +import org.eclipse.linuxtools.tmf.core.analysis.IAnalysisOutput; +import org.eclipse.linuxtools.tmf.core.analysis.TmfAnalysisManager; +import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; +import org.osgi.framework.Bundle; + +/** + * Class for project elements of type analysis modules + * + * @author Geneviève Bastien + * @since 3.0 + */ +public class TmfAnalysisElement extends TmfProjectModelElement { + + private final String fAnalysisId; + + /** + * Constructor + * + * @param name + * Name of the analysis + * @param resource + * The resource + * @param parent + * Parent of the analysis + * @param id + * The analysis module id + */ + protected TmfAnalysisElement(String name, IResource resource, ITmfProjectModelElement parent, String id) { + super(name, resource, parent); + fAnalysisId = id; + refreshOutputs(); + } + + private void refreshOutputs() { + List outputs = getAvailableOutputs(); + + /* Remove children */ + getChildren().clear(); + + /* Add the children again */ + for (TmfAnalysisOutputElement module : outputs) { + addChild(module); + } + + } + + /** + * Get the list of analysis elements + * + * @return Array of analysis elements + */ + public List getAvailableOutputs() { + List list = new ArrayList(); + + IAnalysisModuleHelper helper = TmfAnalysisManager.getAnalysisModule(fAnalysisId); + if (helper == null) { + return list; + } + + /** Get base path for resource */ + IPath path = getProject().getTracesFolder().getPath(); + if (fResource instanceof IFolder) { + path = ((IFolder) fResource).getFullPath(); + } + + /* We can get a list of available outputs once the analysis is instantiated when the trace is opened */ + ITmfProjectModelElement parent = getParent(); + if (parent instanceof TmfTraceElement) { + ITmfTrace trace = ((TmfTraceElement) parent).getTrace(); + if (trace == null) { + return list; + } + + IAnalysisModule module = trace.getAnalysisModule(fAnalysisId); + if (module == null) { + return list; + } + + for (IAnalysisOutput output : module.getOutputs()) { + if (fResource instanceof IFolder) { + IFolder newresource = ResourcesPlugin.getWorkspace().getRoot().getFolder(path.append(output.getName())); + TmfAnalysisOutputElement out = new TmfAnalysisOutputElement(output.getName(), newresource, this, output); + list.add(out); + } + } + } + return list; + } + + @Override + public TmfProjectElement getProject() { + return getParent().getProject(); + } + + /** + * Gets the analysis id of this module + * + * @return The analysis id + */ + public String getAnalysisId() { + return fAnalysisId; + } + + /** + * Gets the help message for this analysis + * + * @return The help message + */ + public String getHelpMessage() { + IAnalysisModuleHelper helper = TmfAnalysisManager.getAnalysisModule(fAnalysisId); + if (helper == null) { + return new String(); + } + + return helper.getHelpText(); + } + + /** + * Gets the icon file name for the analysis + * + * @return The analysis icon file name + */ + public String getIconFile() { + IAnalysisModuleHelper helper = TmfAnalysisManager.getAnalysisModule(fAnalysisId); + if (helper == null) { + return null; + } + return helper.getIcon(); + } + + /** + * Gets the bundle this analysis is from + * + * @return The analysis bundle + */ + public Bundle getBundle() { + IAnalysisModuleHelper helper = TmfAnalysisManager.getAnalysisModule(fAnalysisId); + if (helper == null) { + return null; + } + return helper.getBundle(); + } + + /** + * Make sure the trace this analysis is associated to is the currently selected one + */ + public void activateParent() { + ITmfProjectModelElement parent = getParent(); + + if (parent instanceof TmfTraceElement) { + TmfTraceElement traceElement = (TmfTraceElement) parent; + TmfOpenTraceHelper.openTraceFromElement(traceElement); + } + } +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TmfAnalysisOutputElement.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TmfAnalysisOutputElement.java new file mode 100644 index 0000000000..ad2154f12e --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TmfAnalysisOutputElement.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2013 É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 org.eclipse.linuxtools.tmf.ui.project.model; + +import org.eclipse.core.resources.IResource; +import org.eclipse.linuxtools.tmf.core.analysis.IAnalysisOutput; +import org.eclipse.linuxtools.tmf.ui.analysis.TmfAnalysisViewOutput; +import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.views.IViewDescriptor; + +/** + * Class for project elements of type analysis output + * + * @author Geneviève Bastien + * @since 3.0 + */ +public class TmfAnalysisOutputElement extends TmfProjectModelElement { + + private final IAnalysisOutput fOutput; + + /** + * Constructor + * + * @param name + * Name of the view + * @param resource + * Resource for the view + * @param parent + * Parent analysis of the view + * @param output + * The output object + */ + protected TmfAnalysisOutputElement(String name, IResource resource, ITmfProjectModelElement parent, IAnalysisOutput output) { + super(name, resource, parent); + fOutput = output; + } + + @Override + public TmfProjectElement getProject() { + return getParent().getProject(); + } + + /** + * Gets the icon of the view, if applicable + * + * @return The view icon or null if output is not a view + */ + public Image getIcon() { + if (fOutput instanceof TmfAnalysisViewOutput) { + IViewDescriptor descr = PlatformUI.getWorkbench().getViewRegistry().find( + ((TmfAnalysisViewOutput) fOutput).getViewId()); + if (descr != null) { + return descr.getImageDescriptor().createImage(); + } + } + return null; + } + + /** + * Outputs the analysis + */ + public void outputAnalysis() { + ITmfProjectModelElement parent = getParent(); + if (parent instanceof TmfAnalysisElement) { + ((TmfAnalysisElement) parent).activateParent(); + fOutput.requestOutput(); + } + } + +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TmfExperimentElement.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TmfExperimentElement.java index 5e8074a9ba..add5be9aab 100644 --- a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TmfExperimentElement.java +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TmfExperimentElement.java @@ -312,4 +312,21 @@ public class TmfExperimentElement extends TmfWithFolderElement implements IPrope } } } + + /** + * Get the list of analysis elements + * + * @return Array of analysis elements + * @since 3.0 + */ + public List getAvailableAnalysis() { + List list = new ArrayList(); + + /** + * TODO : implement this cleanly and test it when experiment types are + * available + */ + + return list; + } } diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TmfNavigatorContentProvider.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TmfNavigatorContentProvider.java index 296037a67f..afdf7af31d 100644 --- a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TmfNavigatorContentProvider.java +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TmfNavigatorContentProvider.java @@ -86,17 +86,9 @@ public class TmfNavigatorContentProvider implements IPipelinedTreeContentProvide IProject project = (IProject) element; return project.isAccessible(); } - if (element instanceof TmfTraceFolder) { - TmfTraceFolder folder = (TmfTraceFolder) element; - return folder.hasChildren(); - } - if (element instanceof TmfExperimentFolder) { - TmfExperimentFolder folder = (TmfExperimentFolder) element; - return folder.hasChildren(); - } - if (element instanceof TmfExperimentElement) { - TmfExperimentElement folder = (TmfExperimentElement) element; - return folder.hasChildren(); + if (element instanceof TmfProjectModelElement) { + TmfProjectModelElement modelElement = (TmfProjectModelElement) element; + return modelElement.hasChildren(); } return false; } @@ -148,6 +140,16 @@ public class TmfNavigatorContentProvider implements IPipelinedTreeContentProvide return getExperimentChildren((TmfExperimentElement) parentElement); } + // Traces + if (parentElement instanceof TmfTraceElement) { + return getTraceChildren((TmfTraceElement) parentElement); + } + + // Analysis + if (parentElement instanceof TmfAnalysisElement) { + return getAnalysisChildren((TmfAnalysisElement) parentElement); + } + return new Object[0]; } @@ -232,6 +234,7 @@ public class TmfNavigatorContentProvider implements IPipelinedTreeContentProvide } children.add(trace); childrenMap.remove(name); + getTraceChildren((TmfTraceElement) trace); } } catch (CoreException e) { } @@ -315,6 +318,32 @@ public class TmfNavigatorContentProvider implements IPipelinedTreeContentProvide // project) cleanupModel(tmfExperiment, childrenMap); + for (TmfAnalysisElement analysis : tmfExperiment.getAvailableAnalysis()) { + children.add(analysis); + } + + return children.toArray(); + } + + private static Object[] getTraceChildren(TmfTraceElement parentElement) { + // The children structure + List children = new ArrayList(); + + for (TmfAnalysisElement analysis : parentElement.getAvailableAnalysis()) { + children.add(analysis); + } + + return children.toArray(); + } + + private static Object[] getAnalysisChildren(TmfAnalysisElement parentElement) { + // The children structure + List children = new ArrayList(); + + for (TmfAnalysisOutputElement output : parentElement.getAvailableOutputs()) { + children.add(output); + } + return children.toArray(); } diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TmfNavigatorLabelProvider.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TmfNavigatorLabelProvider.java index a420a41e76..960661e856 100644 --- a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TmfNavigatorLabelProvider.java +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TmfNavigatorLabelProvider.java @@ -45,6 +45,8 @@ public class TmfNavigatorLabelProvider implements ICommonLabelProvider { private static final String fTraceIconFile = "icons/elcl16/trace.gif"; //$NON-NLS-1$ private static final String fUnknownIconFile = "icons/elcl16/unknown_parser.gif"; //$NON-NLS-1$ private static final String fExperimentIconFile = "icons/elcl16/experiment.gif"; //$NON-NLS-1$ + private static final String fAnalysisIconFile = "icons/ovr16/experiment_folder_ovr.png"; //$NON-NLS-1$ + private static final String fViewIconFile = "icons/obj16/node_obj.gif"; //$NON-NLS-1$ // ------------------------------------------------------------------------ // Attributes @@ -56,6 +58,8 @@ public class TmfNavigatorLabelProvider implements ICommonLabelProvider { private final Image fDefaultTraceIcon; private final Image fUnknownTraceIcon; private final Image fExperimentIcon; + private final Image fDefaultAnalysisIcon; + private final Image fDefaultViewIcon; // ------------------------------------------------------------------------ // Constructors @@ -71,6 +75,8 @@ public class TmfNavigatorLabelProvider implements ICommonLabelProvider { fDefaultTraceIcon = loadIcon(bundle, fTraceIconFile); fUnknownTraceIcon = loadIcon(bundle, fUnknownIconFile); fExperimentIcon = loadIcon(bundle, fExperimentIconFile); + fDefaultAnalysisIcon = loadIcon(bundle, fAnalysisIconFile); + fDefaultViewIcon = loadIcon(bundle, fViewIconFile); } private static Image loadIcon(Bundle bundle, String url) { @@ -130,6 +136,28 @@ public class TmfNavigatorLabelProvider implements ICommonLabelProvider { return fTraceFolderIcon; } + if (element instanceof TmfAnalysisOutputElement) { + TmfAnalysisOutputElement output = (TmfAnalysisOutputElement) element; + Image icon = output.getIcon(); + if (icon == null) { + return fDefaultViewIcon; + } + return icon; + } + + if (element instanceof TmfAnalysisElement) { + TmfAnalysisElement analysis = (TmfAnalysisElement) element; + String iconFile = analysis.getIconFile(); + if (iconFile != null) { + Bundle bundle = analysis.getBundle(); + if (bundle != null) { + Image icon = loadIcon(bundle, iconFile); + return icon; + } + } + return fDefaultAnalysisIcon; + } + return null; } diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TmfTraceElement.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TmfTraceElement.java index 6fea774ca1..1f17f243dc 100644 --- a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TmfTraceElement.java +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TmfTraceElement.java @@ -20,15 +20,19 @@ package org.eclipse.linuxtools.tmf.ui.project.model; import java.io.ByteArrayInputStream; import java.io.InputStream; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Platform; import org.eclipse.linuxtools.internal.tmf.ui.Activator; import org.eclipse.linuxtools.internal.tmf.ui.parsers.custom.CustomTxtEvent; @@ -38,7 +42,12 @@ import org.eclipse.linuxtools.internal.tmf.ui.parsers.custom.CustomXmlEvent; import org.eclipse.linuxtools.internal.tmf.ui.parsers.custom.CustomXmlTrace; import org.eclipse.linuxtools.internal.tmf.ui.parsers.custom.CustomXmlTraceDefinition; import org.eclipse.linuxtools.tmf.core.TmfCommonConstants; +import org.eclipse.linuxtools.tmf.core.analysis.IAnalysisModuleHelper; +import org.eclipse.linuxtools.tmf.core.analysis.TmfAnalysisManager; import org.eclipse.linuxtools.tmf.core.event.ITmfEvent; +import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler; +import org.eclipse.linuxtools.tmf.core.signal.TmfSignalManager; +import org.eclipse.linuxtools.tmf.core.signal.TmfTraceOpenedSignal; import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; import org.eclipse.linuxtools.tmf.core.trace.ITmfTraceProperties; import org.eclipse.linuxtools.tmf.core.trace.TmfTrace; @@ -177,6 +186,7 @@ public class TmfTraceElement extends TmfWithFolderElement implements IActionFilt super(name, trace, parent); parent.addChild(this); refreshTraceType(); + TmfSignalManager.register(this); } // ------------------------------------------------------------------------ @@ -198,6 +208,7 @@ public class TmfTraceElement extends TmfWithFolderElement implements IActionFilt public void refreshTraceType() { try { fTraceTypeId = getResource().getPersistentProperty(TmfCommonConstants.TRACETYPE); + refreshAnalysis(); } catch (CoreException e) { Activator.getDefault().logError("Error refreshing trace type pesistent property for trace " + getName(), e); //$NON-NLS-1$ } @@ -591,4 +602,84 @@ public class TmfTraceElement extends TmfWithFolderElement implements IActionFilt } return null; } + + private void refreshAnalysis() { + List list = getAvailableAnalysis(); + + /* Remove children */ + getChildren().clear(); + + /* Add the children again */ + for (TmfAnalysisElement module : list) { + addChild(module); + } + + } + + /** + * Get the list of analysis elements + * + * @return Array of analysis elements + * @since 3.0 + */ + public List getAvailableAnalysis() { + List list = new ArrayList(); + + TraceTypeHelper helper = TmfTraceType.getInstance().getTraceType(getTraceType()); + + Class traceClass = null; + + if (helper == null && fTraceTypeId != null) { + if (fTraceTypeId.startsWith(CustomTxtTrace.class.getCanonicalName())) { + for (CustomTxtTraceDefinition def : CustomTxtTraceDefinition.loadAll()) { + if (fTraceTypeId.equals(CustomTxtTrace.class.getCanonicalName() + ":" + def.definitionName)) { //$NON-NLS-1$ + traceClass = CustomTxtTrace.class; + } + } + } + if (fTraceTypeId.startsWith(CustomXmlTrace.class.getCanonicalName())) { + for (CustomXmlTraceDefinition def : CustomXmlTraceDefinition.loadAll()) { + if (fTraceTypeId.equals(CustomXmlTrace.class.getCanonicalName() + ":" + def.definitionName)) { //$NON-NLS-1$ + traceClass = CustomTxtTrace.class; + } + } + } + } else if (helper != null) { + traceClass = helper.getTraceClass(); + } + + if (traceClass == null) { + return list; + } + + /** Get the base path to put the resource to */ + IPath path = fResource.getFullPath(); + + for (IAnalysisModuleHelper module : TmfAnalysisManager.getAnalysisModules(traceClass).values()) { + + /** No need for the resource to exist, nothing will be done with it */ + IFolder newresource = ResourcesPlugin.getWorkspace().getRoot().getFolder(path.append(module.getId())); + + TmfAnalysisElement analysis = new TmfAnalysisElement(module.getName(), newresource, this, module.getId()); + list.add(analysis); + } + + return list; + } + + /** + * Handler for the Trace Opened signal + * + * @param signal + * The incoming signal + */ + @TmfSignalHandler + public void traceOpened(TmfTraceOpenedSignal signal) { + if (!signal.getTrace().getResource().equals(getResource())) { + return; + } + + refreshAnalysis(); + getParent().refresh(); + } } diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TraceTypeHelper.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TraceTypeHelper.java index ea48fcf901..b121962376 100644 --- a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TraceTypeHelper.java +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/TraceTypeHelper.java @@ -106,6 +106,16 @@ public class TraceTypeHelper { return valid; } + /** + * Get the class associated with this trace type + * + * @return The trace class + * @since 3.0 + */ + public Class getTraceClass() { + return fTrace.getClass(); + } + @Override public String toString() { return fName; diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/messages.properties b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/messages.properties index 51325d69f4..ecf75e9852 100644 --- a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/messages.properties +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/project/model/messages.properties @@ -11,6 +11,9 @@ ############################################################################### # Environment properties dialog +TmfAnalysisElement_InstantiateAnalysis=Instantiate analysis +TmfAnalysisViewOutput_ViewUnavailable=\ (view unavailable) +TmfAnalysisViewOutput_Title=Open analysis output TmfTraceElement_ResourceProperties = Resource properties TmfTraceElement_TraceProperties = Trace properties TmfTraceElement_Name = name @@ -30,4 +33,4 @@ TmfOpenTraceHelper_ReduceError=Something went wrong TmfOpenTraceHelper_NoTraceType=No trace type associated to that trace\nPlease select a valid type TmfOpenTraceHelper_ErrorTrace=Error opening trace. TmfOpenTraceHelper_ErrorExperiment=Error opening experiment. -TmfOpenTraceHelper_InitError = Error initializing trace. \ No newline at end of file +TmfOpenTraceHelper_InitError = Error initializing trace. -- 2.34.1