blob: 69d829fc3f509c79fde78bbf152de337f2d7429a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015 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
*
* Contributors:
* Patrick Tasse - Initial API and implementation
*******************************************************************************/
package org.eclipse.tracecompass.tmf.core.trace;
import java.util.Collection;
import java.util.Map;
import org.eclipse.core.runtime.IAdapterFactory;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
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 com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
/**
* Base class for a trace adapter factory. The factory creates a single instance
* of each adapter type per trace, and disposes the adapter when the trace is
* closed, if it is an instance of {@link IDisposableAdapter}.
*
* @since 2.0
*/
public abstract class AbstractTmfTraceAdapterFactory implements IAdapterFactory {
/**
* Interface for trace adapters that manage resources which must be freed
* when the trace is closed.
*/
public interface IDisposableAdapter {
/**
* Disposes of this trace adapter. All resources must be freed.
*/
void dispose();
}
private final Table<ITmfTrace, Class<?>, Object> fAdapters = HashBasedTable.create();
/**
* Constructor.
*/
public AbstractTmfTraceAdapterFactory() {
TmfSignalManager.register(this);
}
/**
* Disposes the trace adapter factory's resources and all of its adapters.
*/
public synchronized void dispose() {
TmfSignalManager.deregister(this);
disposeAdapters(fAdapters.values());
fAdapters.clear();
}
private static void disposeAdapters(Collection<Object> adapters) {
for (Object adapter : adapters) {
if (adapter instanceof IDisposableAdapter) {
((IDisposableAdapter) adapter).dispose();
}
}
}
@Override
public synchronized <T> T getAdapter(Object adaptableObject, Class<T> adapterType) {
if (adaptableObject instanceof ITmfTrace) {
ITmfTrace trace = (ITmfTrace) adaptableObject;
Object adapter = fAdapters.get(trace, adapterType);
if (adapter == null) {
adapter = getTraceAdapter(trace, adapterType);
}
if (adapter != null) {
fAdapters.put(trace, adapterType, adapter);
return adapterType.cast(adapter);
}
}
return null;
}
/**
* Returns an object which is an instance of the given class associated with
* the given trace. Returns null if no such object can be found.
*
* @param trace
* the trace being adapted
* @param adapterType
* the type of adapter to look up
* @return a object of the given adapter type, or null if this factory does
* not have an adapter of the given type for the given trace
*/
protected abstract <T> @Nullable T getTraceAdapter(@NonNull ITmfTrace trace, Class<T> adapterType);
/**
* Signal handler for the trace closed signal.
*
* @param signal
* the trace closed signal
*/
@TmfSignalHandler
public synchronized void traceClosed(TmfTraceClosedSignal signal) {
Map<Class<?>, Object> row = fAdapters.row(signal.getTrace());
disposeAdapters(row.values());
row.clear();
}
}