diff --git a/releng/org.eclipse.tracecompass.integration.core.tests/src/org/eclipse/tracecompass/integration/core/tests/dataproviders/DataProviderManagerTest.java b/releng/org.eclipse.tracecompass.integration.core.tests/src/org/eclipse/tracecompass/integration/core/tests/dataproviders/DataProviderManagerTest.java index 85aad4fe23..626137cb01 100644 --- a/releng/org.eclipse.tracecompass.integration.core.tests/src/org/eclipse/tracecompass/integration/core/tests/dataproviders/DataProviderManagerTest.java +++ b/releng/org.eclipse.tracecompass.integration.core.tests/src/org/eclipse/tracecompass/integration/core/tests/dataproviders/DataProviderManagerTest.java @@ -415,17 +415,45 @@ public void test() { public void testGetter() { ITmfTrace trace = fKernelTrace; assertNotNull(trace); - ITmfTreeXYDataProvider<@NonNull ITmfTreeDataModel> dp = DataProviderManager.getInstance().getExistingDataProvider(trace, CPU_USAGE_DP_ID, ITmfTreeXYDataProvider.class); - assertNull(dp); - dp = DataProviderManager.getInstance().getOrCreateDataProvider(trace, CPU_USAGE_DP_ID, ITmfTreeXYDataProvider.class); - assertNotNull(dp); - ITmfTreeXYDataProvider<@NonNull ITmfTreeDataModel> dp2 = DataProviderManager.getInstance().getExistingDataProvider(trace, CPU_USAGE_DP_ID, ITmfTreeXYDataProvider.class); - assertNotNull(dp2); - assertTrue(dp == dp2); - ITmfTreeXYDataProvider<@NonNull ITmfTreeDataModel> dp3 = DataProviderManager.getInstance().getOrCreateDataProvider(trace, CPU_USAGE_DP_ID, ITmfTreeXYDataProvider.class); - assertNotNull(dp3); - assertTrue(dp == dp3); - assertTrue(dp == dp2); + try { + ITmfTreeXYDataProvider<@NonNull ITmfTreeDataModel> dp = DataProviderManager.getInstance().getExistingDataProvider(trace, CPU_USAGE_DP_ID, ITmfTreeXYDataProvider.class); + assertNull(dp); + dp = DataProviderManager.getInstance().getOrCreateDataProvider(trace, CPU_USAGE_DP_ID, ITmfTreeXYDataProvider.class); + assertNotNull(dp); + ITmfTreeXYDataProvider<@NonNull ITmfTreeDataModel> dp2 = DataProviderManager.getInstance().getExistingDataProvider(trace, CPU_USAGE_DP_ID, ITmfTreeXYDataProvider.class); + assertNotNull(dp2); + assertTrue(dp == dp2); + ITmfTreeXYDataProvider<@NonNull ITmfTreeDataModel> dp3 = DataProviderManager.getInstance().getOrCreateDataProvider(trace, CPU_USAGE_DP_ID, ITmfTreeXYDataProvider.class); + assertNotNull(dp3); + assertTrue(dp == dp3); + assertTrue(dp == dp2); + } finally { + DataProviderManager.getInstance().removeDataProvider(trace, CPU_USAGE_DP_ID); + } + } + + /** + * Test different get methods + */ + @Test + public void testGetterNew() { + ITmfTrace trace = fKernelTrace; + assertNotNull(trace); + try { + ITmfTreeXYDataProvider<@NonNull ITmfTreeDataModel> dp = DataProviderManager.getInstance().fetchExistingDataProvider(trace, CPU_USAGE_DP_ID, ITmfTreeXYDataProvider.class); + assertNull(dp); + dp = DataProviderManager.getInstance().fetchOrCreateDataProvider(trace, CPU_USAGE_DP_ID, ITmfTreeXYDataProvider.class); + assertNotNull(dp); + ITmfTreeXYDataProvider<@NonNull ITmfTreeDataModel> dp2 = DataProviderManager.getInstance().fetchExistingDataProvider(trace, CPU_USAGE_DP_ID, ITmfTreeXYDataProvider.class); + assertNotNull(dp2); + assertTrue(dp == dp2); + ITmfTreeXYDataProvider<@NonNull ITmfTreeDataModel> dp3 = DataProviderManager.getInstance().fetchOrCreateDataProvider(trace, CPU_USAGE_DP_ID, ITmfTreeXYDataProvider.class); + assertNotNull(dp3); + assertTrue(dp == dp3); + assertTrue(dp == dp2); + } finally { + DataProviderManager.getInstance().removeDataProvider(trace, CPU_USAGE_DP_ID); + } } /** diff --git a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/dataprovider/DataProviderManager.java b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/dataprovider/DataProviderManager.java index 0380ad8576..250aff4549 100644 --- a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/dataprovider/DataProviderManager.java +++ b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/dataprovider/DataProviderManager.java @@ -45,6 +45,7 @@ import org.eclipse.tracecompass.internal.tmf.core.Activator; import org.eclipse.tracecompass.tmf.core.component.DataProviderConstants; import org.eclipse.tracecompass.tmf.core.config.ITmfConfiguration; +import org.eclipse.tracecompass.tmf.core.model.ITmfDataProvider; import org.eclipse.tracecompass.tmf.core.model.tree.ITmfTreeDataModel; import org.eclipse.tracecompass.tmf.core.model.tree.ITmfTreeDataProvider; import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler; @@ -88,7 +89,7 @@ public class DataProviderManager { private Multimap fHideDataProviders = HashMultimap.create(); private Multimap fShowDataProviders = HashMultimap.create(); - private final Multimap> fInstances = LinkedHashMultimap.create(); + private final Multimap fInstances = LinkedHashMultimap.create(); /** * Get the instance of the manager @@ -219,15 +220,38 @@ private void loadHiddenDataProviders() { * @return the data provider or null if no data provider is found for the * input parameter. * @since 8.0 + * + * @deprecated As of version 9.7, use {@link #fetchOrCreateDataProvider(ITmfTrace, String, Class)} instead */ + @Deprecated(since = "9.7", forRemoval = true) public synchronized @Nullable > T getOrCreateDataProvider(@NonNull ITmfTrace trace, String id, Class dataProviderClass) { - ITmfTreeDataProvider dataProvider = getExistingDataProvider(trace, id, dataProviderClass); + return fetchOrCreateDataProvider(trace, id, dataProviderClass); + } + + /** + * Gets or creates the data provider for the given trace. + *

+ * This method should never be called from within a + * {@link TmfSignalHandler}. + * + * @param trace + * An instance of {@link ITmfTrace}. Note, that trace can be an + * instance of TmfExperiment, too. + * @param id + * Id of the data provider. This ID can be the concatenation of a + * provider ID + ':' + a secondary ID used to differentiate + * multiple instances of a same provider. + * @param dataProviderClass + * Returned data provider must extend this class + * @return the data provider or null if no data provider is found for the + * input parameter. + * @since 9.7 + */ + public synchronized @Nullable T fetchOrCreateDataProvider(@NonNull ITmfTrace trace, String id, Class dataProviderClass) { + ITmfDataProvider dataProvider = fetchExistingDataProvider(trace, id, dataProviderClass); if (dataProvider != null) { return dataProviderClass.cast(dataProvider); } - if (isHidden(id, trace)) { - return null; - } String[] ids = id.split(DataProviderConstants.ID_SEPARATOR, 2); for (ITmfTrace opened : TmfTraceManager.getInstance().getOpenedTraces()) { if (TmfTraceManager.getTraceSetWithExperiment(opened).contains(trace)) { @@ -236,7 +260,7 @@ private void loadHiddenDataProviders() { */ IDataProviderFactory providerFactory = fDataProviderFactories.get(ids[0]); if (providerFactory != null) { - dataProvider = ids.length > 1 ? providerFactory.createProvider(trace, String.valueOf(ids[1])) : providerFactory.createProvider(trace); + dataProvider = ids.length > 1 ? providerFactory.createDataProvider(trace, String.valueOf(ids[1])) : providerFactory.createDataProvider(trace); if (dataProvider != null && id.equals(dataProvider.getId()) && dataProviderClass.isAssignableFrom(dataProvider.getClass())) { fInstances.put(trace, dataProvider); return dataProviderClass.cast(dataProvider); @@ -268,9 +292,36 @@ private void loadHiddenDataProviders() { * Returned data provider must extend this class * @return the data provider or null * @since 8.0 + * @deprecated As of version 9.7, use {@link #fetchExistingDataProvider(ITmfTrace, String, Class)} instead */ + @Deprecated(since = "9.7", forRemoval = true) public synchronized @Nullable > T getExistingDataProvider(@NonNull ITmfTrace trace, String id, Class dataProviderClass) { - for (ITmfTreeDataProvider dataProvider : fInstances.get(trace)) { + return fetchExistingDataProvider(trace, id, dataProviderClass); + } + + /** + * Get a data provider for the given trace if it already exists due to + * calling {@link #fetchOrCreateDataProvider(ITmfTrace, String, Class)} + * before. + * + *

+ * This method should never be called from within a + * {@link TmfSignalHandler}. + * + * @param trace + * An instance of {@link ITmfTrace}. Note, that trace can be an + * instance of TmfExperiment, too. + * @param id + * Id of the data provider. This ID can be the concatenation of a + * provider ID + ':' + a secondary ID used to differentiate + * multiple instances of a same provider. + * @param dataProviderClass + * Returned data provider must extend this class + * @return the data provider or null + * @since 9.7 + */ + public synchronized @Nullable T fetchExistingDataProvider(@NonNull ITmfTrace trace, String id, Class dataProviderClass) { + for (ITmfDataProvider dataProvider : fInstances.get(trace)) { if (id.equals(dataProvider.getId()) && dataProviderClass.isAssignableFrom(dataProvider.getClass()) && !isHidden(id, trace)) { return dataProviderClass.cast(dataProvider); } @@ -290,7 +341,7 @@ public void traceClosed(final TmfTraceClosedSignal signal) { new Thread(() -> { synchronized (DataProviderManager.this) { for (ITmfTrace trace : TmfTraceManager.getTraceSetWithExperiment(signal.getTrace())) { - fInstances.removeAll(trace).forEach(ITmfTreeDataProvider::dispose); + fInstances.removeAll(trace).forEach(ITmfDataProvider::dispose); } } }).start(); @@ -402,9 +453,9 @@ public > boolean rem * @since 9.7 */ public void removeDataProvider(ITmfTrace trace, String id) { - Iterator> iter = fInstances.get(trace).iterator(); + Iterator iter = fInstances.get(trace).iterator(); while (iter.hasNext()) { - ITmfTreeDataProvider dp = iter.next(); + ITmfDataProvider dp = iter.next(); if (dp.getId().equals(id)) { dp.dispose(); iter.remove(); @@ -487,9 +538,9 @@ public synchronized void removeDataProviderFactory(String id) { private void removeExistingDataProviders(IDataProviderFactory factory, String passedFactoryId) { if (factory != null) { for (ITmfTrace trace : fInstances.keySet()) { - Iterator> iter = fInstances.get(trace).iterator(); + Iterator iter = fInstances.get(trace).iterator(); while (iter.hasNext()) { - ITmfTreeDataProvider dp = iter.next(); + ITmfDataProvider dp = iter.next(); String factoryId = extractFactoryId(dp.getId()); if (passedFactoryId.equals(factoryId)) { dp.dispose(); diff --git a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/dataprovider/IDataProviderFactory.java b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/dataprovider/IDataProviderFactory.java index 9ae19e82cd..c14aef960c 100644 --- a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/dataprovider/IDataProviderFactory.java +++ b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/dataprovider/IDataProviderFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017 Ericsson + * Copyright (c) 2017, 2025 Ericsson * * All rights reserved. This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 which @@ -18,6 +18,7 @@ import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.tracecompass.tmf.core.config.ITmfDataProviderConfigurator; +import org.eclipse.tracecompass.tmf.core.model.ITmfDataProvider; import org.eclipse.tracecompass.tmf.core.model.tree.ITmfTreeDataModel; import org.eclipse.tracecompass.tmf.core.model.tree.ITmfTreeDataProvider; import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; @@ -40,11 +41,28 @@ public interface IDataProviderFactory extends IAdaptable { * A trace * @return {@link ITmfTreeDataProvider} that can be use for the given trace * @since 4.0 + * @deprecated As of version 9.7, use {@link #createDataProvider(ITmfTrace)} instead */ - @Nullable ITmfTreeDataProvider createProvider(@NonNull ITmfTrace trace); + @Deprecated(since = "9.7", forRemoval = true) + @Nullable default ITmfTreeDataProvider createProvider(@NonNull ITmfTrace trace) { + return null; + } /** - * Create a {@link ITmfTreeDataProvider} for the given trace. If this factory + * Create a {@link ITmfDataProvider} for the given trace. If this factory + * does not know how to handle the given trace it will return null + * + * @param trace + * A trace + * @return {@link ITmfDataProvider} that can be use for the given trace + * @since 9.7 + */ + @Nullable default ITmfDataProvider createDataProvider(@NonNull ITmfTrace trace) { + return createProvider(trace); + } + + /** +D * Create a {@link ITmfTreeDataProvider} for the given trace. If this factory * does not know how to handle the given trace it will return null. The * resulting provider should have an ID that is an aggregate of the provider's * own ID and the secondaryId as such: : @@ -59,11 +77,34 @@ public interface IDataProviderFactory extends IAdaptable { * ID :, or null if no provider * is available for this trace and ID * @since 4.0 + * @deprecated As of version 9.7, use {@link #createDataProvider(ITmfTrace)} instead */ + @Deprecated(since = "9.7", forRemoval = true) default @Nullable ITmfTreeDataProvider createProvider(@NonNull ITmfTrace trace, @NonNull String secondaryId) { return createProvider(trace); } + /** + * Create a {@link ITmfDataProvider} for the given trace. If this factory + * does not know how to handle the given trace it will return null. The + * resulting provider should have an ID that is an aggregate of the provider's + * own ID and the secondaryId as such: : + * + * @param trace + * A trace + * @param secondaryId + * Additional ID to identify different instances of the same + * provider, for instance, when the same provider can be used for + * different analysis modules + * @return {@link ITmfDataProvider} that can be use for the given trace with + * ID :, or null if no provider + * is available for this trace and ID + * @since 9.7 + */ + default @Nullable ITmfDataProvider createDataProvider(@NonNull ITmfTrace trace, @NonNull String secondaryId) { + return createProvider(trace, secondaryId); + } + /** * Gets the collection of data provider descriptors for this trace that this * data provider factory can create, if the trace supports it, else diff --git a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/model/ITmfDataProvider.java b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/model/ITmfDataProvider.java new file mode 100644 index 0000000000..a77f3ae189 --- /dev/null +++ b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/model/ITmfDataProvider.java @@ -0,0 +1,76 @@ +/********************************************************************** + * Copyright (c) 2025 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License 2.0 which + * accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + **********************************************************************/ + +package org.eclipse.tracecompass.tmf.core.model; + +/** + * Base interface that each data provider has to implement. + * + * Each data provider needs to provide at least one fetch method, that is + * typical for this data provider type and which returns @link TmfModelResponse} + * with a defined serializable model. + * + *

+ * Example interface: + *

{@code
+ * public ICustomDataProvider implements ITmfDataProvider {
+ *   TmfModelResponse fetchCustomData(Map fetchParameters, @Nullable IProgressMonitor monitor);
+ * }
+ * }
+ *

+ * Example implementation: + *
{@code
+ *  public class CustomModel {
+ *    private final String fValue = value;
+ *    public CustomModel(String value) {
+ *      fValue = value;
+ *    }
+ *    String getValue() {
+ *      return fValue;
+ *    }
+ *  }
+ *
+ *  public class CustomDataProvider implements ICustomDataProvider {
+ *    // ITmfDataProvider
+ *    public String getId() {
+ *      return "customId";
+ *    }
+ *    public void dispose() {}
+ *
+ *    // ICustomDataProvider
+ *    TmfModelResponse fetchCustomData(Map fetchParameters, @Nullable IProgressMonitor monitor) {
+ *        CustomModel model = new CustomModel("my data");
+ *        return new TmfModelResponse<>(model, ITmfResponse.Status.COMPLETED, CommonStatusMessage.COMPLETED);
+ *    }
+ *  }
+ * }
+ * + * + * @since 9.7 + * @author Matthew Khouzam + * @auther Bernd Hufmann + * + */ +public interface ITmfDataProvider { + /** + * This method return the extension point ID of this provider + * + * @return The ID + */ + String getId(); + + /** + * Dispose of the provider to avoid resource leakage. + */ + public default void dispose() { + // Do nothing for now + } +} diff --git a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/model/tree/ITmfTreeDataProvider.java b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/model/tree/ITmfTreeDataProvider.java index f7056af531..809c01799a 100644 --- a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/model/tree/ITmfTreeDataProvider.java +++ b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/model/tree/ITmfTreeDataProvider.java @@ -15,6 +15,7 @@ import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.tmf.core.model.ITmfDataProvider; import org.eclipse.tracecompass.tmf.core.response.TmfModelResponse; /** @@ -26,7 +27,7 @@ * Tree model extending {@link ITmfTreeDataModel} * @since 4.0 */ -public interface ITmfTreeDataProvider { +public interface ITmfTreeDataProvider extends ITmfDataProvider{ /** * This methods computes a tree model. Then, it returns a @@ -42,19 +43,6 @@ public interface ITmfTreeDataProvider { * @since 5.0 */ TmfModelResponse> fetchTree(Map fetchParameters, @Nullable IProgressMonitor monitor); +} - /** - * This method return the extension point ID of this provider - * - * @return The ID - */ - String getId(); - /** - * Dispose of the provider to avoid resource leakage. - * - * @since 4.0 - */ - public default void dispose() { - } -}