--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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:
+ * 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();
+ }
+}