Skip to content

Commit

Permalink
tmf: Support for configuration sources to create data providers
Browse files Browse the repository at this point in the history
Updated org.eclipse.tracecompass.tmf.core.config extension point:
- add data provider configuration source ITmfDataProviderConfigSource
- make global ITmfConfigurationSource
- Update TmfConfigurationSourceManager to handle update extension point

Introduce API ITmfDataProviderSource to implement for getting a list
of data provider descriptors for a given trace, data provider ID and
config ID. Implementers need to make sure that data provider factories
are registered to the DataProviderManager, that the new list are
also returned by DataProviderProvider#getDescriptors() and data
providers can be instantiated with it.

[Added] Support for configuration sources to create data providers
[Updated] org.eclipse.tracecompass.tmf.core.config extension point

Signed-off-by: Bernd Hufmann <[email protected]>
  • Loading branch information
bhufmann committed Sep 18, 2024
1 parent 653bbaf commit bba9e83
Show file tree
Hide file tree
Showing 8 changed files with 266 additions and 20 deletions.
23 changes: 23 additions & 0 deletions tmf/org.eclipse.tracecompass.tmf.core/.settings/.api_filters
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<component id="org.eclipse.tracecompass.tmf.core" version="2">
<resource path="src/org/eclipse/tracecompass/tmf/core/config/TmfConfigurationSourceManager.java" type="org.eclipse.tracecompass.tmf.core.config.TmfConfigurationSourceManager">
<filter comment="Static variable was not supposed to be public. It's pretty new and save to make it private." id="388018290">
<message_arguments>
<message_argument value="org.eclipse.tracecompass.tmf.core.config.TmfConfigurationSourceManager"/>
<message_argument value="CONFIG_EXTENSION_POINT_ID"/>
</message_arguments>
</filter>
<filter comment="Static variable was not supposed to be public. It's pretty new and save to make it private." id="388018290">
<message_arguments>
<message_argument value="org.eclipse.tracecompass.tmf.core.config.TmfConfigurationSourceManager"/>
<message_argument value="SOURCE_ATTR"/>
</message_arguments>
</filter>
<filter comment="Static variable was not supposed to be public. It's pretty new and save to make it private." id="388018290">
<message_arguments>
<message_argument value="org.eclipse.tracecompass.tmf.core.config.TmfConfigurationSourceManager"/>
<message_argument value="SOURCE_TYPE_ELEM"/>
</message_arguments>
</filter>
</resource>
</component>
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
</annotation>
<complexType>
<choice minOccurs="0" maxOccurs="unbounded">
<element ref="source"/>
<element ref="source" minOccurs="0" maxOccurs="1"/>
<element ref="dpSource" minOccurs="0" maxOccurs="1"/>
</choice>
<attribute name="point" type="string" use="required">
<annotation>
Expand Down Expand Up @@ -69,6 +70,28 @@
</complexType>
</element>

<element name="dpSource">
<complexType>
<attribute name="id" type="string" use="required">
<annotation>
<documentation>
The unique ID that identifies this configuration source type handler for data providers
</documentation>
</annotation>
</attribute>
<attribute name="class" type="string">
<annotation>
<documentation>
The fully qualified name of a class that implements the &lt;samp&gt;ITmfDataProviderConfigSource&lt;/samp&gt; interface.
</documentation>
<appinfo>
<meta.attribute kind="java" basedOn=":org.eclipse.tracecompass.tmf.core.config.ITmfDataProviderConfigSource"/>
</appinfo>
</annotation>
</attribute>
</complexType>
</element>

<annotation>
<appinfo>
<meta.section type="since"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,13 @@ public interface ITmfConfigurationSourceType {
* @return A list of query parameter descriptors to be passed
*/
List<ITmfConfigParamDescriptor> getConfigParamDescriptors();

/**
* A string containing a json-schema describing the query parameters
* to be passed when creating a configuration instance of this type.
* A string containing a json-schema describing the query parameters to be
* passed when creating a configuration instance of this type.
*
* Note: Use either {@link #getConfigParamDescriptors()} or {@link #getSchemaFile()}
* Note: Use either {@link #getConfigParamDescriptors()} or
* {@link #getSchemaFile()}
*
* @return A file containing a valid json-schema or null if not used
* @since 9.5
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*******************************************************************************
* Copyright (c) 2024 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.util.Map;

import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.tmf.core.exceptions.TmfConfigurationException;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;

/**
* Interface for configuring data providers for given experiment.
*
* @since 9.5
*/
public interface ITmfDataProviderConfigSource {

/**
* @return {@link ITmfConfigurationSourceType} of this configuration source
*/
ITmfConfigurationSourceType getConfigurationSourceType();

/**
* Check if a this configuration source is applies to a give data provider.
*
* @param dataProviderId
* the data provider ID
* @return true if it applies else false
*/
boolean appliesToDataProvider(String dataProviderId);

/**
* Create a list of data provider descriptors base on input parameters.
*
* @param parameters
* The input parameter
* @param trace
* The trace (or experiment) instance
* @param srcDataProviderId
* The sourceDataProviderId
* @return a new {@link ITmfConfiguration} if successful
* @throws TmfConfigurationException
* If the creation of the configuration fails
*/
ITmfConfiguration create(Map<String, Object> parameters, ITmfTrace trace, String srcDataProviderId) throws TmfConfigurationException;

/**
* Removes a configuration instance.
*
* @param id
* The configuration ID of the configuration to remove
* @param trace
* The trace (or experiment) instance
* @param srcDataProviderId
* The sourceDataProviderId
* @return removed {@link ITmfConfiguration} instance if remove or null if
* not found
*/
@Nullable ITmfConfiguration remove(String id, ITmfTrace trace, String srcDataProviderId);

/**
* Dispose the configuration source.
*/
void dispose();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*******************************************************************************
* Copyright (c) 2024 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.util.List;

import org.eclipse.tracecompass.tmf.core.dataprovider.DataProviderManager;
import org.eclipse.tracecompass.tmf.core.dataprovider.IDataProviderDescriptor;
import org.eclipse.tracecompass.tmf.core.exceptions.TmfConfigurationException;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;

/**
* Interface for creating data providers. Implementers only return the data provider descriptors.
* Instantiating the actual data provider(s) should be done using {@link DataProviderManager}.
* @since 9.5
*/
public interface ITmfDataProviderSource {
/**
* Create a list of data provider descriptors base on input parameters.
*
* @param srcDataProviderId
* The sourceDataProviderId
* @param trace
* The trace (or experiment) instance
* @param configId
* The configuration ID
* @return List of data provider descriptor
* @throws TmfConfigurationException
* if an error occurs
*/
List<IDataProviderDescriptor> getDataProviderDescriptors(String srcDataProviderId, ITmfTrace trace, String configId) throws TmfConfigurationException;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2023 Ericsson
* Copyright (c) 2023, 2024 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License 2.0 which
Expand All @@ -12,8 +12,10 @@

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
Expand All @@ -32,17 +34,22 @@
public class TmfConfigurationSourceManager {

/** Extension point ID */
public static final String CONFIG_EXTENSION_POINT_ID = "org.eclipse.tracecompass.tmf.core.config"; //$NON-NLS-1$
private static final String CONFIG_EXTENSION_POINT_ID = "org.eclipse.tracecompass.tmf.core.config"; //$NON-NLS-1$

/** Extension point element 'source' */
public static final String SOURCE_TYPE_ELEM = "source"; //$NON-NLS-1$
private static final String SOURCE_TYPE_ELEM = "source"; //$NON-NLS-1$

/** Extension point element 'class' */
public static final String SOURCE_ATTR = "class"; //$NON-NLS-1$
private static final String SOURCE_ATTR = "class"; //$NON-NLS-1$

private Map<ITmfConfigurationSourceType, ITmfConfigurationSource> fDescriptors = new ConcurrentHashMap<>();
/** Extension point element 'dpSource'*/
private static final String DP_SOURCE_TYPE_ELEM = "dpSource"; //$NON-NLS-1$

private @Nullable static TmfConfigurationSourceManager fInstance;
private Map<ITmfConfigurationSourceType, ITmfConfigurationSource> fGlobalDescriptors = new ConcurrentHashMap<>();

private Map<ITmfConfigurationSourceType, ITmfDataProviderConfigSource> fDpDescriptors = new ConcurrentHashMap<>();

private static @Nullable TmfConfigurationSourceManager fInstance;

private TmfConfigurationSourceManager() {
}
Expand All @@ -66,8 +73,11 @@ public synchronized static TmfConfigurationSourceManager getInstance() {
* Disposes the instance.
*/
public synchronized void dispose() {
fDescriptors.values().forEach(t -> t.dispose());
fDescriptors.clear();
fGlobalDescriptors.values().forEach(t -> t.dispose());
fGlobalDescriptors.clear();

fDpDescriptors.values().forEach(t -> t.dispose());
fDpDescriptors.clear();
}

/**
Expand All @@ -77,29 +87,66 @@ public synchronized void dispose() {
*/
public List<ITmfConfigurationSourceType> getConfigurationSourceTypes() {
ImmutableList.Builder<ITmfConfigurationSourceType> builder = new ImmutableList.Builder<>();
builder.addAll(fDescriptors.keySet());
builder.addAll(fGlobalDescriptors.keySet());
return builder.build();
}

/**
* Gets a list of available configuration source types for a given data
* provider
*
* @param dataProviderId
* a data provider ID
* @return a list of available {@Link ITmfConfigurationSourceType}s for a
* given data provider
* @since 9.4
*/
public List<ITmfConfigurationSourceType> getConfigurationSourceTypes(String dataProviderId) {
ImmutableList.Builder<ITmfConfigurationSourceType> builder = new ImmutableList.Builder<>();
@SuppressWarnings("null")
Map<ITmfConfigurationSourceType, ITmfDataProviderConfigSource> filteredMap =
fDpDescriptors.entrySet()
.stream()
.filter(entry -> entry.getValue().appliesToDataProvider(dataProviderId))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
builder.addAll(filteredMap.keySet());
return builder.build();
}

/**
* Gets the {@link ITmfConfigurationSource} for a given
* {@Link ITmfConfigurationSourceType}
* {@Link ITmfConfigurationSourceType@getId()}
*
* @param typeId
* The configuration source type ID
* @return Gets the {@link ITmfConfigurationSource} or null if it doesn't
* exist
*/
public @Nullable ITmfConfigurationSource getConfigurationSource(@Nullable String typeId) {
ITmfConfigurationSourceType desc = getDescriptor(typeId);
return desc == null ? null : fDescriptors.get(desc);
ITmfConfigurationSourceType desc = getDescriptor(fGlobalDescriptors, typeId);
return desc == null ? null : fGlobalDescriptors.get(desc);
}

/**
* Gets the {@link ITmfDataProviderConfigSource} for a given
* {@Link ITmfConfigurationSourceType#getId()}
*
* @param typeId
* The configuration source type ID
* @return Gets the {@link ITmfDataProviderConfigSource} or null if it doesn't
* exist
* @since 9.4
*/
public @Nullable ITmfDataProviderConfigSource getDataProviderConfigurationSource(@Nullable String typeId) {
ITmfConfigurationSourceType desc = getDescriptor(fDpDescriptors, typeId);
return desc == null ? null : fDpDescriptors.get(desc);
}

private @Nullable ITmfConfigurationSourceType getDescriptor(@Nullable String typeId) {
private static @Nullable ITmfConfigurationSourceType getDescriptor(Map<ITmfConfigurationSourceType, ?> map, @Nullable String typeId) {
if (typeId == null) {
return null;
}
Optional<ITmfConfigurationSourceType> optional = fDescriptors.keySet().stream().filter(desc -> desc.getId().equals(typeId)).findAny();
Optional<ITmfConfigurationSourceType> optional = map.keySet().stream().filter(desc -> desc.getId().equals(typeId)).findAny();
return optional.isEmpty() ? null : optional.get();
}

Expand All @@ -118,7 +165,20 @@ private void init() {
Activator.logError("ITmfConfigurationSource cannot be instantiated.", e); //$NON-NLS-1$
}
if (sourceInstance != null) {
fDescriptors.put(sourceInstance.getConfigurationSourceType(), sourceInstance);
fGlobalDescriptors.put(sourceInstance.getConfigurationSourceType(), sourceInstance);
}
}
} else if (elementName.equals(DP_SOURCE_TYPE_ELEM)) {
String source = ce.getAttribute(SOURCE_ATTR);
if (source != null) {
ITmfDataProviderConfigSource sourceInstance = null;
try {
sourceInstance = (ITmfDataProviderConfigSource) ce.createExecutableExtension(SOURCE_ATTR);
} catch (CoreException e) {
Activator.logError("ITmfDataProviderConfigSource cannot be instantiated.", e); //$NON-NLS-1$
}
if (sourceInstance != null) {
fDpDescriptors.put(sourceInstance.getConfigurationSourceType(), sourceInstance);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ public Builder setConfigParamDescriptors(List<ITmfConfigParamDescriptor> descrip
* @param schema
* the json schema file
* @return the builder instance.
* @since 9.4
* @since 9.5
*/
public Builder setSchemaFile(@Nullable File schema) {
fSchemaFile = schema;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
package org.eclipse.tracecompass.tmf.core.dataprovider;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.tmf.core.config.ITmfConfiguration;

/**
* Data Provider description, used to list the available providers for a trace
Expand Down Expand Up @@ -87,4 +89,25 @@ public enum ProviderType {
* @return a short description of this data provider.
*/
String getDescription();

/**
* Gets the parent data provider ID for grouping purposes.
*
* @return parent ID or null if not grouped or derived data provider
* @since 9.5
*/
default @Nullable String getParentId() {
return null;
}

/**
* Gets the input configuration used to create this data provider.
*
* @return the {@link ITmfConfiguration} configuration use to create this
* data provider, or null if not applicable
* @since 9.5
*/
default @Nullable ITmfConfiguration getCreationConfiguration() {
return null;
}
}

0 comments on commit bba9e83

Please sign in to comment.