-
Notifications
You must be signed in to change notification settings - Fork 27
Propose new api for configurable data provider factories #235
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
bcf083a
384fa92
7b47e78
e218b9e
3455a21
6f08bea
70d5719
eeb672c
c11317c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,288 @@ | ||
| /********************************************************************** | ||
| * 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.config; | ||
|
|
||
| import java.io.File; | ||
| import java.io.FileWriter; | ||
| import java.io.IOException; | ||
| import java.io.Writer; | ||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
|
|
||
| import org.eclipse.core.runtime.IPath; | ||
| import org.eclipse.core.runtime.Path; | ||
| import org.eclipse.jdt.annotation.NonNull; | ||
| import org.eclipse.tracecompass.internal.tmf.core.Activator; | ||
| import org.eclipse.tracecompass.tmf.core.dataprovider.IDataProviderDescriptor; | ||
| import org.eclipse.tracecompass.tmf.core.exceptions.TmfConfigurationException; | ||
| import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler; | ||
| import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager; | ||
| import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal; | ||
| import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal; | ||
| import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; | ||
| import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager; | ||
| import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperiment; | ||
|
|
||
| import com.google.common.collect.HashBasedTable; | ||
| import com.google.common.collect.Table; | ||
| import com.google.gson.Gson; | ||
| import com.google.gson.JsonParseException; | ||
|
|
||
| /** | ||
| * This class meant to be extended by data provider factories that want to be | ||
| * able to handle configurations. | ||
| * | ||
| * @since 9.6 | ||
| */ | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you need a
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
| public abstract class AbstractTmfDataProviderConfigurator implements ITmfDataProviderConfigurator{ | ||
|
|
||
| /** | ||
| * Constructor | ||
| */ | ||
| protected AbstractTmfDataProviderConfigurator() { | ||
| TmfSignalManager.register(this); | ||
| } | ||
|
|
||
| /** | ||
| * The json file extension | ||
| * @since 9.5 | ||
| */ | ||
| public static final String JSON_EXTENSION = "json"; //$NON-NLS-1$ | ||
|
|
||
| private Table<String, ITmfTrace, ITmfConfiguration> fTmfConfigurationTable = HashBasedTable.create(); | ||
|
|
||
| /** | ||
| * Return the configuration table | ||
| * | ||
| * @return a table mapping configuration id and trace (exp) to its configuration | ||
| */ | ||
| public Table<String, ITmfTrace, ITmfConfiguration> getConfigurationTable(){ | ||
| return fTmfConfigurationTable; | ||
| } | ||
|
|
||
| /** | ||
| * Create instances implementing {@link ITmfConfiguration}. Override this | ||
| * method if the data provider configurator needs another configuration | ||
| * instead of the default {@link TmfConfiguration} | ||
| * | ||
| * @param configuration | ||
| * a object implementing implementing {@link ITmfConfiguration}. | ||
| * @return the instance of the class implementing {@link ITmfConfiguration}. | ||
| * Default is {@link TmfConfiguration}. | ||
| */ | ||
| protected ITmfConfiguration createConfiguration(ITmfConfiguration configuration) { | ||
| String description = configuration.getDescription(); | ||
| if (configuration.getDescription().equals(TmfConfiguration.UNKNOWN)) { | ||
| description = "Data provider defined by configuration " + configuration.getName(); //$NON-NLS-1$ | ||
| } | ||
|
|
||
| TmfConfiguration.Builder builder = new TmfConfiguration.Builder(); | ||
frallax marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| builder.setId(configuration.getId()) | ||
| .setSourceTypeId(configuration.getSourceTypeId()) | ||
| .setName(configuration.getName()) | ||
| .setDescription(description) | ||
| .setParameters(configuration.getParameters()) | ||
| .build(); | ||
| return builder.build(); | ||
| } | ||
|
|
||
| @Override | ||
| public @NonNull IDataProviderDescriptor createDataProviderDescriptors(ITmfTrace trace, ITmfConfiguration configuration) throws TmfConfigurationException { | ||
|
|
||
| if (configuration.getName().equals(TmfConfiguration.UNKNOWN)) { | ||
| throw new TmfConfigurationException("Missing configuration name"); //$NON-NLS-1$ | ||
| } | ||
|
|
||
| if (configuration.getSourceTypeId().equals(TmfConfiguration.UNKNOWN)) { | ||
| throw new TmfConfigurationException("Missing configuration type"); //$NON-NLS-1$ | ||
| } | ||
|
|
||
| ITmfConfiguration config = createConfiguration(configuration); | ||
|
|
||
| applyConfiguration(trace, config, true); | ||
| if (fTmfConfigurationTable.contains(config.getId(), trace)) { | ||
| throw new TmfConfigurationException("Configuration already existis with label: " + config.getName()); //$NON-NLS-1$ | ||
| } | ||
| fTmfConfigurationTable.put(config.getId(), trace, config); | ||
| return getDescriptorFromConfig(config); | ||
| } | ||
|
|
||
| /** | ||
| * Return a data provider descriptor based on the configuration parameter | ||
| * | ||
| * @param config | ||
| * a configuration | ||
| * @return A data provider descriptor based on the configuration parameter | ||
| */ | ||
| protected abstract IDataProviderDescriptor getDescriptorFromConfig(ITmfConfiguration config); | ||
|
|
||
| /** | ||
| * This is the method that handles what happens when a configuration is | ||
| * applied | ||
| * | ||
| * @param trace | ||
| * trace to which the configuration should be applied | ||
| * @param config | ||
| * the configuration to be applied | ||
| * @param writeConfig | ||
| * true if the configuration should be written to disk, false | ||
| * otherwise | ||
| */ | ||
| protected abstract void applyConfiguration(ITmfTrace trace, ITmfConfiguration config, boolean writeConfig); | ||
|
|
||
| @Override | ||
| public void removeDataProviderDescriptor(ITmfTrace trace, IDataProviderDescriptor descriptor) throws TmfConfigurationException { | ||
| ITmfConfiguration creationConfiguration = descriptor.getConfiguration(); | ||
| if (creationConfiguration == null) { | ||
| throw new TmfConfigurationException("Data provider was not created by a configuration"); //$NON-NLS-1$ | ||
| } | ||
|
|
||
| String configId = creationConfiguration.getId(); | ||
| ITmfConfiguration config = fTmfConfigurationTable.get(configId, trace); | ||
| if (config == null) { | ||
| return; | ||
| } | ||
| config = fTmfConfigurationTable.remove(configId, trace); | ||
| removeConfiguration(trace, config); | ||
| } | ||
|
|
||
| /** | ||
| * This is the method that handles what happens when a configuration is | ||
| * removed (e.g. remove analysis, dp etc) | ||
| * | ||
| * @param trace | ||
| * trace to which the configuration should be applied | ||
| * @param config | ||
| * the configuration to be applied | ||
| */ | ||
| protected abstract void removeConfiguration(@NonNull ITmfTrace trace, @NonNull ITmfConfiguration config); | ||
|
|
||
| /** | ||
| * Signal handler for opened trace signal. Will populate trace | ||
| * configurations | ||
| * | ||
| * @param signal | ||
| * the signal to handle | ||
| */ | ||
| @TmfSignalHandler | ||
| public void traceOpened(TmfTraceOpenedSignal signal) { | ||
| ITmfTrace trace = signal.getTrace(); | ||
| if (trace == null) { | ||
| return; | ||
| } | ||
| try { | ||
| if (trace instanceof TmfExperiment) { | ||
| for (ITmfTrace tr : TmfTraceManager.getTraceSet(trace)) { | ||
| // Read configurations from sub-trace | ||
| List<ITmfConfiguration> configs = readConfigurations(tr); | ||
| readAndApplyConfiguration(trace, configs); | ||
| } | ||
| } | ||
| // Read configurations from trace or top level experiment | ||
| List<ITmfConfiguration> configs = readConfigurations(trace); | ||
| readAndApplyConfiguration(trace, configs); | ||
| } catch (TmfConfigurationException e) { | ||
| Activator.logError("Error applying configurations for trace " + trace.getName(), e); //$NON-NLS-1$ | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Handles trace closed signal | ||
| * | ||
| * @param signal | ||
| * the close signal to handle | ||
| */ | ||
| @TmfSignalHandler | ||
| public void traceClosed(TmfTraceClosedSignal signal) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This this class handles tmf signals, we need to register to the signal manager and also derigster when it's disposed. You can register in the constructor. TmfSignalManager.register(this);Probably this class should have a dispose method to deregister from the signal manager. The factory dispose() method would call then this method.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
| ITmfTrace trace = signal.getTrace(); | ||
| fTmfConfigurationTable.column(trace).clear(); | ||
| } | ||
|
|
||
| private void readAndApplyConfiguration(ITmfTrace trace, List<ITmfConfiguration> configs) throws TmfConfigurationException { | ||
| for (ITmfConfiguration config : configs) { | ||
| if (!fTmfConfigurationTable.contains(config.getId(), trace)) { | ||
| fTmfConfigurationTable.put(config.getId(), trace, config); | ||
| applyConfiguration(trace, config, false); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Reads the configurations for a given trace | ||
| * | ||
| * @param trace | ||
| * the trace to read configurations from | ||
| * @return list of configurations if any | ||
| * @throws TmfConfigurationException | ||
| * if an error occurs | ||
| */ | ||
| private @NonNull List<ITmfConfiguration> readConfigurations(@NonNull ITmfTrace trace) throws TmfConfigurationException { | ||
| IPath rootPath = getConfigurationRootFolder(trace); | ||
| File folder = rootPath.toFile(); | ||
| List<ITmfConfiguration> list = new ArrayList<>(); | ||
| if (folder.exists()) { | ||
| File[] listOfFiles = folder.listFiles(); | ||
| for (File file : listOfFiles) { | ||
| IPath path = new Path(file.getName()); | ||
| if (path.getFileExtension().equals(JSON_EXTENSION)) { | ||
| ITmfConfiguration config = TmfConfiguration.fromJsonFile(file); | ||
| list.add(config); | ||
| } | ||
| } | ||
| } | ||
| return list; | ||
| } | ||
|
|
||
| /** | ||
| * Serialize {@link ITmfConfiguration} to JSON file with name configId.json | ||
| * | ||
| * @param configuration | ||
| * the configuration to serialize | ||
| * @param rootPath | ||
| * the root path to store the configuration | ||
| * @throws TmfConfigurationException | ||
| * if an error occurs | ||
| * @since 9.5 | ||
| */ | ||
| protected static void writeConfiguration(ITmfConfiguration configuration, IPath rootPath) throws TmfConfigurationException { | ||
| IPath supplPath = rootPath; | ||
| File folder = supplPath.toFile(); | ||
| if (!folder.exists()) { | ||
| folder.mkdir(); | ||
| } | ||
| supplPath = supplPath.addTrailingSeparator().append(configuration.getId()).addFileExtension(JSON_EXTENSION); | ||
| File file = supplPath.toFile(); | ||
| try (Writer writer = new FileWriter(file)) { | ||
| writer.append(new Gson().toJson(configuration)); | ||
| } catch (IOException | JsonParseException e) { | ||
| Activator.logError(e.getMessage(), e); | ||
| throw new TmfConfigurationException("Error writing configuration.", e); //$NON-NLS-1$ | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Return the path where the configuration for a trace is stored | ||
| * | ||
| * @param trace | ||
| * the trace to which the configuration should be applied to | ||
| * @return the path where the configuration should be stored | ||
| */ | ||
| @SuppressWarnings("null") | ||
| protected @NonNull abstract IPath getConfigurationRootFolder(@NonNull ITmfTrace trace); | ||
|
|
||
| /** | ||
| * Disposes the signal manager | ||
| */ | ||
| protected void dispose() { | ||
| TmfSignalManager.dispose(); | ||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,7 +26,6 @@ | |
| import org.eclipse.jdt.annotation.Nullable; | ||
| import org.eclipse.tracecompass.internal.tmf.core.Activator; | ||
| import org.eclipse.tracecompass.tmf.core.exceptions.TmfConfigurationException; | ||
|
|
||
| import com.google.gson.Gson; | ||
| import com.google.gson.JsonParseException; | ||
| import com.google.gson.annotations.Expose; | ||
|
|
@@ -49,8 +48,11 @@ public class TmfConfiguration implements ITmfConfiguration { | |
|
|
||
| /** | ||
| * The json file extension | ||
| * | ||
| * @since 9.5 | ||
| * @deprecated use {@link AbstractTmfDataProviderConfigurator#JSON_EXTENSION} instead | ||
| */ | ||
| @Deprecated | ||
| public static final String JSON_EXTENSION = "json"; //$NON-NLS-1$ | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can't remove it just yet. It's api and needs to be deprecated first. In incubator master branch there is already a new class that uses it.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
|
|
||
| @Expose | ||
|
|
@@ -327,7 +329,11 @@ public static ITmfConfiguration fromJsonFile(File jsonFile) throws TmfConfigurat | |
| * @throws TmfConfigurationException | ||
| * if an error occurs | ||
| * @since 9.5 | ||
| * @deprecated use | ||
| * {@link AbstractTmfDataProviderConfigurator#writeConfiguration(ITmfConfiguration, IPath)} | ||
| * instead | ||
| */ | ||
| @Deprecated | ||
| public static void writeConfiguration(ITmfConfiguration configuration, IPath rootPath) throws TmfConfigurationException { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can't remove it just yet. It's api and needs to be deprecated first. In incubator master branch there is already a new class that uses it.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
| IPath supplPath = rootPath; | ||
| File folder = supplPath.toFile(); | ||
|
|
@@ -343,4 +349,5 @@ public static void writeConfiguration(ITmfConfiguration configuration, IPath roo | |
| throw new TmfConfigurationException("Error writing configuration.", e); //$NON-NLS-1$ | ||
| } | ||
| } | ||
|
|
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copyright header
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done