ctf: Introduce ICTFStream
authorMatthew Khouzam <matthew.khouzam@ericsson.com>
Tue, 15 Dec 2015 20:12:00 +0000 (15:12 -0500)
committerMatthew Khouzam <matthew.khouzam@ericsson.com>
Wed, 16 Dec 2015 21:45:26 +0000 (16:45 -0500)
This allows a CTFStream to be shared while not being modifyiable.

Change-Id: I4bf4985abd5221ebfa543d0a7ff0cfeda0874fce
Signed-off-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Reviewed-on: https://git.eclipse.org/r/62767
Reviewed-by: Francis Giraldeau <francis.giraldeau@gmail.com>
Reviewed-by: Hudson CI
17 files changed:
ctf/org.eclipse.tracecompass.ctf.core.tests/src/org/eclipse/tracecompass/ctf/core/tests/trace/CTFStreamInputReaderTest.java
ctf/org.eclipse.tracecompass.ctf.core.tests/src/org/eclipse/tracecompass/ctf/core/tests/trace/CTFStreamInputTest.java
ctf/org.eclipse.tracecompass.ctf.core.tests/src/org/eclipse/tracecompass/ctf/core/tests/trace/CTFStreamTest.java
ctf/org.eclipse.tracecompass.ctf.core.tests/src/org/eclipse/tracecompass/ctf/core/tests/trace/CTFTraceTest.java
ctf/org.eclipse.tracecompass.ctf.core.tests/src/org/eclipse/tracecompass/ctf/core/tests/trace/MetadataTest.java
ctf/org.eclipse.tracecompass.ctf.core.tests/src/org/eclipse/tracecompass/ctf/core/tests/types/EventDeclarationTest.java
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/event/IEventDeclaration.java
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/event/LostEventDeclaration.java
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/CTFStream.java [deleted file]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/CTFStreamInput.java
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/CTFTrace.java
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/CTFTraceReader.java
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/CTFTraceWriter.java
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/ICTFStream.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/EventDeclaration.java
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/IOStructGen.java
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/trace/CTFStream.java [new file with mode: 0644]

index aad70eb98c4c939244fa7b7a4f59b224bf9250d8..ccfab8e98543b9d8031cc8bbdcf8e60c86697bcf 100644 (file)
@@ -29,11 +29,12 @@ import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
 import org.eclipse.tracecompass.ctf.core.event.types.StructDefinition;
 import org.eclipse.tracecompass.ctf.core.tests.shared.CtfTestTraceUtils;
 import org.eclipse.tracecompass.ctf.core.trace.CTFResponse;
-import org.eclipse.tracecompass.ctf.core.trace.CTFStream;
 import org.eclipse.tracecompass.ctf.core.trace.CTFStreamInput;
 import org.eclipse.tracecompass.ctf.core.trace.CTFStreamInputReader;
 import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.ctf.core.trace.ICTFStream;
 import org.eclipse.tracecompass.internal.ctf.core.event.EventDeclaration;
+import org.eclipse.tracecompass.internal.ctf.core.trace.CTFStream;
 import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace;
 import org.junit.Before;
 import org.junit.Test;
@@ -68,13 +69,12 @@ public class CTFStreamInputReaderTest {
                         null,
                         "packet",
                         new Definition[] { new StringDefinition(StringDeclaration.getStringDeclaration(Encoding.UTF8), null, "field", "test") }),
-                null)
-                );
+                null));
     }
 
     private static CTFStreamInputReader getStreamInputReader() throws CTFException {
         CTFTrace trace = CtfTestTraceUtils.getTrace(testTrace);
-        CTFStream s = trace.getStream((long) 0);
+        ICTFStream s = trace.getStream((long) 0);
         Set<CTFStreamInput> streamInput = s.getStreamInputs();
         CTFStreamInputReader retVal = null;
         for (CTFStreamInput si : streamInput) {
index 9146c77c7f2e2ae7562fdf7476d7f7de0a1f8046..884f13abaf95eb79595df1b8e80c4e7fc07d902e 100644 (file)
@@ -24,8 +24,9 @@ import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.tracecompass.ctf.core.CTFException;
 import org.eclipse.tracecompass.ctf.core.event.types.IDefinition;
 import org.eclipse.tracecompass.ctf.core.tests.shared.CtfTestTraceUtils;
-import org.eclipse.tracecompass.ctf.core.trace.CTFStream;
 import org.eclipse.tracecompass.ctf.core.trace.CTFStreamInput;
+import org.eclipse.tracecompass.ctf.core.trace.ICTFStream;
+import org.eclipse.tracecompass.internal.ctf.core.trace.CTFStream;
 import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace;
 import org.junit.Before;
 import org.junit.Test;
@@ -103,7 +104,7 @@ public class CTFStreamInputTest {
      */
     @Test
     public void testGetStream() {
-        CTFStream result = fixture.getStream();
+        ICTFStream result = fixture.getStream();
         assertNotNull(result);
     }
 
index 737a06dada1d8ec3d6b31e035f87f5858b0f391c..6c29917134c2665cea0bae30cb2ea76000f1b6e0 100644 (file)
@@ -23,11 +23,11 @@ import org.eclipse.tracecompass.ctf.core.CTFException;
 import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
 import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
 import org.eclipse.tracecompass.ctf.core.tests.shared.CtfTestTraceUtils;
-import org.eclipse.tracecompass.ctf.core.trace.CTFStream;
 import org.eclipse.tracecompass.ctf.core.trace.CTFStreamInput;
 import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
 import org.eclipse.tracecompass.internal.ctf.core.event.EventDeclaration;
 import org.eclipse.tracecompass.internal.ctf.core.event.metadata.exceptions.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.trace.CTFStream;
 import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace;
 import org.junit.Before;
 import org.junit.Test;
index ffd3989c1cf98c47e7c06ed7329d3bc78198babb..fa9b59fe1ba4a2fed546dd1e35008bd101fd3778 100644 (file)
@@ -29,9 +29,10 @@ import org.eclipse.tracecompass.ctf.core.event.CTFClock;
 import org.eclipse.tracecompass.ctf.core.event.types.IDefinition;
 import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
 import org.eclipse.tracecompass.ctf.core.tests.shared.CtfTestTraceUtils;
-import org.eclipse.tracecompass.ctf.core.trace.CTFStream;
 import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.ctf.core.trace.ICTFStream;
 import org.eclipse.tracecompass.internal.ctf.core.event.metadata.exceptions.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.trace.CTFStream;
 import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace;
 import org.junit.Before;
 import org.junit.Test;
@@ -186,7 +187,7 @@ public class CTFTraceTest {
     @Test
     public void testGetStream() {
         Long id = new Long(0L);
-        CTFStream result = fixture.getStream(id);
+        ICTFStream result = fixture.getStream(id);
         assertNotNull(result);
     }
 
index b6005352bebb74c47701d2701e7e724d7c923af2..fc3699aeed671f4292caa9350cc6a385a691821f 100644 (file)
@@ -27,8 +27,8 @@ import org.eclipse.tracecompass.ctf.core.event.IEventDeclaration;
 import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
 import org.eclipse.tracecompass.ctf.core.event.types.ISimpleDatatypeDeclaration;
 import org.eclipse.tracecompass.ctf.core.tests.shared.CtfTestTraceUtils;
-import org.eclipse.tracecompass.ctf.core.trace.CTFStream;
 import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.ctf.core.trace.ICTFStream;
 import org.eclipse.tracecompass.ctf.core.trace.Metadata;
 import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace;
 import org.junit.Before;
@@ -251,12 +251,12 @@ public class MetadataTest {
     protected CTFTrace testSingleFragment() throws CTFException {
         fixture = new Metadata();
         CTFTrace trace = fixture.getTrace();
-        for (CTFStream s : trace.getStreams()) {
+        for (ICTFStream s : trace.getStreams()) {
             fail("This should be empty, has" + s.toString());
         }
         fixture.parseText(mdStart);
         int count = 0;
-        for (CTFStream s : trace.getStreams()) {
+        for (ICTFStream s : trace.getStreams()) {
             count++;
             assertNotNull(s);
         }
index 9b3c96c915fc533903b713fc0db6e02a258319cd..101d05e11951f4922426237f2a44d2416933cd8d 100644 (file)
@@ -23,10 +23,10 @@ import org.eclipse.tracecompass.ctf.core.event.IEventDeclaration;
 import org.eclipse.tracecompass.ctf.core.event.LostEventDeclaration;
 import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
 import org.eclipse.tracecompass.ctf.core.tests.shared.CtfTestTraceUtils;
-import org.eclipse.tracecompass.ctf.core.trace.CTFStream;
 import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
 import org.eclipse.tracecompass.ctf.core.trace.CTFTraceReader;
 import org.eclipse.tracecompass.internal.ctf.core.event.EventDeclaration;
+import org.eclipse.tracecompass.internal.ctf.core.trace.CTFStream;
 import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace;
 import org.junit.Before;
 import org.junit.Test;
index 166b8e1da5208afbceb61ae165048e79a9bac7eb..6419c95592f0ae8bc0e842da835b9d96d1f73fae 100644 (file)
@@ -17,8 +17,9 @@ import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.tracecompass.ctf.core.CTFException;
 import org.eclipse.tracecompass.ctf.core.event.io.BitBuffer;
 import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
-import org.eclipse.tracecompass.ctf.core.trace.CTFStream;
 import org.eclipse.tracecompass.ctf.core.trace.CTFStreamInputReader;
+import org.eclipse.tracecompass.ctf.core.trace.ICTFStream;
+import org.eclipse.tracecompass.internal.ctf.core.trace.CTFStream;
 
 /**
  * Representation of one type of event. A bit like "int" or "long" but for trace
@@ -83,8 +84,9 @@ public interface IEventDeclaration {
      * Gets the {@link CTFStream} of an event declaration
      *
      * @return the stream
+     * @since 2.0
      */
-    CTFStream getStream();
+    ICTFStream getStream();
 
     /**
      * What is the log level of this event?
index 1ffddc43ce5ffce8ba5b6e6745cdbc1f0d94ee59..a995feebbd853d4fbde1ad79e7f792c859f7598d 100644 (file)
@@ -19,8 +19,8 @@ import org.eclipse.tracecompass.ctf.core.CTFStrings;
 import org.eclipse.tracecompass.ctf.core.event.io.BitBuffer;
 import org.eclipse.tracecompass.ctf.core.event.types.IntegerDeclaration;
 import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
-import org.eclipse.tracecompass.ctf.core.trace.CTFStream;
 import org.eclipse.tracecompass.ctf.core.trace.CTFStreamInputReader;
+import org.eclipse.tracecompass.ctf.core.trace.ICTFStream;
 
 /**
  * A lost event definition
@@ -75,8 +75,11 @@ public class LostEventDeclaration implements IEventDeclaration {
         return LOST_EVENT_ID;
     }
 
+    /**
+     * @since 2.0
+     */
     @Override
-    public CTFStream getStream() {
+    public ICTFStream getStream() {
         return null;
     }
 
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/CTFStream.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/CTFStream.java
deleted file mode 100644 (file)
index 00b2537..0000000
+++ /dev/null
@@ -1,359 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2011, 2014 Ericsson, Ecole Polytechnique de Montreal and others
- *
- * 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: Matthew Khouzam - Initial API and implementation
- * Contributors: Simon Marchi - Initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.tracecompass.ctf.core.trace;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.jdt.annotation.Nullable;
-import org.eclipse.tracecompass.common.core.NonNullUtils;
-import org.eclipse.tracecompass.ctf.core.CTFException;
-import org.eclipse.tracecompass.ctf.core.event.IEventDeclaration;
-import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
-import org.eclipse.tracecompass.ctf.core.event.types.IEventHeaderDeclaration;
-import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
-import org.eclipse.tracecompass.internal.ctf.core.event.EventDeclaration;
-import org.eclipse.tracecompass.internal.ctf.core.event.metadata.exceptions.ParseException;
-
-/**
- * <b><u>Stream</u></b>
- * <p>
- * Represents a stream in a trace.
- */
-public class CTFStream {
-
-    // ------------------------------------------------------------------------
-    // Attributes
-    // ------------------------------------------------------------------------
-
-    /**
-     * The numerical ID of the stream
-     */
-    private long fId = 0;
-
-    /**
-     * Declarations of the stream-specific structures
-     */
-    private StructDeclaration fPacketContextDecl = null;
-    private IDeclaration fEventHeaderDecl = null;
-    private StructDeclaration fEventContextDecl = null;
-
-    /**
-     * The trace to which the stream belongs
-     */
-    private CTFTrace fTrace = null;
-
-    /**
-     * Maps event ids to events
-     */
-    private final ArrayList<@Nullable IEventDeclaration> fEvents = new ArrayList<>();
-
-    private boolean fEventUnsetId = false;
-    private boolean fStreamIdSet = false;
-
-    /**
-     * The inputs associated to this stream
-     */
-    private final Set<CTFStreamInput> fInputs = new HashSet<>();
-
-    // ------------------------------------------------------------------------
-    // Constructors
-    // ------------------------------------------------------------------------
-
-    /**
-     * Constructs a Stream that belongs to a Trace
-     *
-     * @param trace
-     *            The trace to which belongs this stream.
-     */
-    public CTFStream(CTFTrace trace) {
-        fTrace = trace;
-    }
-
-    // ------------------------------------------------------------------------
-    // Getters/Setters/Predicates
-    // ------------------------------------------------------------------------
-
-    /**
-     * Sets the id of a stream
-     *
-     * @param id
-     *            the id of a stream
-     */
-    public void setId(long id) {
-        fId = id;
-        fStreamIdSet = true;
-    }
-
-    /**
-     * Gets the id of a stream
-     *
-     * @return id the id of a stream
-     * @since 1.0
-     */
-    public long getId() {
-        return fId;
-    }
-
-    /**
-     * Is the id of a stream set
-     *
-     * @return If the ID is set or not
-     */
-    public boolean isIdSet() {
-        return fStreamIdSet;
-    }
-
-    /**
-     *
-     * @return is the event header set (timestamp and stuff) (see Ctf Spec)
-     */
-    public boolean isEventHeaderSet() {
-        return fEventHeaderDecl != null;
-    }
-
-    /**
-     *
-     * @return is the event context set (pid and stuff) (see Ctf Spec)
-     */
-    public boolean isEventContextSet() {
-        return fEventContextDecl != null;
-    }
-
-    /**
-     *
-     * @return Is the packet context set (see Ctf Spec)
-     */
-    public boolean isPacketContextSet() {
-        return fPacketContextDecl != null;
-    }
-
-    /**
-     * Sets the event header
-     *
-     * @param eventHeader
-     *            the current event header for all events in this stream
-     */
-    public void setEventHeader(StructDeclaration eventHeader) {
-        fEventHeaderDecl = eventHeader;
-    }
-
-    /**
-     * Sets the event header, this typically has the id and the timestamp
-     *
-     * @param eventHeader
-     *            the current event header for all events in this stream
-     */
-    public void setEventHeader(IEventHeaderDeclaration eventHeader) {
-        fEventHeaderDecl = eventHeader;
-    }
-
-    /**
-     *
-     * @param eventContext
-     *            the context for all events in this stream
-     */
-    public void setEventContext(StructDeclaration eventContext) {
-        fEventContextDecl = eventContext;
-    }
-
-    /**
-     *
-     * @param packetContext
-     *            the packet context for all packets in this stream
-     */
-    public void setPacketContext(StructDeclaration packetContext) {
-        fPacketContextDecl = packetContext;
-    }
-
-    /**
-     * Gets the event header declaration
-     *
-     * @return the event header declaration in declaration form
-     */
-    public IDeclaration getEventHeaderDeclaration() {
-        return fEventHeaderDecl;
-    }
-
-    /**
-     *
-     * @return the event context declaration in structdeclaration form
-     */
-    public StructDeclaration getEventContextDecl() {
-        return fEventContextDecl;
-    }
-
-    /**
-     *
-     * @return the packet context declaration in structdeclaration form
-     */
-    public StructDeclaration getPacketContextDecl() {
-        return fPacketContextDecl;
-    }
-
-    /**
-     *
-     * @return the set of all stream inputs for this stream
-     */
-    public Set<CTFStreamInput> getStreamInputs() {
-        return fInputs;
-    }
-
-    /**
-     *
-     * @return the parent trace
-     */
-    public CTFTrace getTrace() {
-        return fTrace;
-    }
-
-    /**
-     * Get all the event declarations in this stream.
-     *
-     * @return The event declarations for this stream
-     * @since 2.0
-     */
-    public @NonNull List<@Nullable IEventDeclaration> getEventDeclarations() {
-        return NonNullUtils.checkNotNull(Collections.unmodifiableList(fEvents));
-    }
-
-    /**
-     * Get the event declaration for a given ID.
-     *
-     * @param eventId
-     *            The ID, can be {@link EventDeclaration#UNSET_EVENT_ID}, or any
-     *            positive value
-     * @return The event declaration with the given ID for this stream, or
-     *         'null' if there are no declaration with this ID
-     * @throws IllegalArgumentException
-     *             If the passed ID is invalid
-     */
-    public @Nullable IEventDeclaration getEventDeclaration(int eventId) {
-        int eventIndex = (eventId == IEventDeclaration.UNSET_EVENT_ID) ? 0 : eventId;
-        if (eventIndex < 0) {
-            /* Any negative value other than UNSET_EVENT_ID is invalid */
-            throw new IllegalArgumentException("Event ID cannot be negative."); //$NON-NLS-1$
-        }
-        if (eventIndex >= fEvents.size()) {
-            /* This ID could be valid, but there are no declarations with it */
-            return null;
-        }
-        return fEvents.get(eventIndex);
-    }
-
-    // ------------------------------------------------------------------------
-    // Operations
-    // ------------------------------------------------------------------------
-
-    /**
-     * Adds an event to the event list.
-     *
-     * An event in a stream can omit its id if it is the only event in this
-     * stream. An event for which no id has been specified has a null id. It is
-     * thus not possible to add an event with the null key if the map is not
-     * empty. It is also not possible to add an event to the map if the null key
-     * is present in the map.
-     *
-     * @param event
-     *            The event to add
-     * @throws ParseException
-     *             If there was a problem reading the event or adding it to the
-     *             stream
-     */
-    public void addEvent(IEventDeclaration event) throws ParseException {
-        if (fEventUnsetId) {
-            throw new ParseException("Event without id with multiple events in a stream"); //$NON-NLS-1$
-        }
-        int id = ((EventDeclaration) event).id();
-
-        /*
-         * If there is an event without id (the null key), it must be the only
-         * one
-         */
-        if (id == IEventDeclaration.UNSET_EVENT_ID) {
-            if (!fEvents.isEmpty()) {
-                throw new ParseException("Event without id with multiple events in a stream"); //$NON-NLS-1$
-            }
-            fEventUnsetId = true;
-            fEvents.add(event);
-        } else {
-            /* Check if an event with the same ID already exists */
-            if (fEvents.size() > id && fEvents.get(id) != null) {
-                throw new ParseException("Event id already exists"); //$NON-NLS-1$
-            }
-            ensureSize(fEvents, id);
-            /* Put the event in the list */
-            fEvents.set(id, event);
-        }
-    }
-
-    /**
-     * Add a list of event declarations to this stream. There must be no overlap
-     * between the two lists of event declarations. This will merge the two
-     * lists and preserve the indexes of both lists.
-     *
-     * @param events
-     *            list of the events to add
-     * @throws CTFException
-     *             if the list already contains data
-     */
-    public void addEvents(Collection<IEventDeclaration> events) throws CTFException {
-        if (fEventUnsetId) {
-            throw new CTFException("Cannot add to a stream with an unidentified event"); //$NON-NLS-1$
-        }
-        if (fEvents.isEmpty()) {
-            fEvents.addAll(events);
-            return;
-        }
-        for (IEventDeclaration event : events) {
-            if (event != null) {
-                int index = event.getId().intValue();
-                ensureSize(fEvents, index);
-                if (fEvents.get(index) != null) {
-                    throw new CTFException("Both lists have an event defined at position " + index); //$NON-NLS-1$
-                }
-                fEvents.set(index, event);
-            }
-        }
-    }
-
-    private static void ensureSize(ArrayList<@Nullable ? extends Object> list, int index) {
-        list.ensureCapacity(index);
-        while (list.size() <= index) {
-            list.add(null);
-        }
-    }
-
-    /**
-     * Add an input to this Stream
-     *
-     * @param input
-     *            The StreamInput to add.
-     */
-    public void addInput(CTFStreamInput input) {
-        fInputs.add(input);
-    }
-
-    @Override
-    public String toString() {
-        return "Stream [id=" + fId + ", packetContextDecl=" + fPacketContextDecl //$NON-NLS-1$ //$NON-NLS-2$
-                + ", eventHeaderDecl=" + fEventHeaderDecl //$NON-NLS-1$
-                + ", eventContextDecl=" + fEventContextDecl + ", trace=" + fTrace //$NON-NLS-1$ //$NON-NLS-2$
-                + ", events=" + fEvents + ", inputs=" + fInputs + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-    }
-}
index 7c62cfb1b2179daa529b03c34f0a7b6af9d8bc9c..babc8ad04d942ce383ea32a0eb04f91ea5250ff3 100644 (file)
@@ -54,7 +54,7 @@ public class CTFStreamInput implements IDefinitionScope {
     /**
      * The associated Stream
      */
-    private final CTFStream fStream;
+    private final ICTFStream fStream;
 
     /**
      * Information on the file (used for debugging)
@@ -99,8 +99,9 @@ public class CTFStreamInput implements IDefinitionScope {
      *            The stream to which this StreamInput belongs to.
      * @param file
      *            Information about the trace file (for debugging purposes).
+     * @since 2.0
      */
-    public CTFStreamInput(CTFStream stream, File file) {
+    public CTFStreamInput(ICTFStream stream, File file) {
         fStream = stream;
         fFile = file;
         String name = fFile.getName();
@@ -135,8 +136,9 @@ public class CTFStreamInput implements IDefinitionScope {
      * Gets the stream the streamInput wrapper is wrapping
      *
      * @return the stream the streamInput wrapper is wrapping
+     * @since 2.0
      */
-    public CTFStream getStream() {
+    public ICTFStream getStream() {
         return fStream;
     }
 
index dab024292bb38e1a1085bee1c6a83ee1b2c945eb..e44ad4a9f02ebc0714dacf6ba9e1a56c5ca9d0a8 100644 (file)
@@ -49,6 +49,7 @@ import org.eclipse.tracecompass.ctf.core.event.types.StructDefinition;
 import org.eclipse.tracecompass.internal.ctf.core.SafeMappedByteBuffer;
 import org.eclipse.tracecompass.internal.ctf.core.event.metadata.MetadataStrings;
 import org.eclipse.tracecompass.internal.ctf.core.event.metadata.exceptions.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.trace.CTFStream;
 import org.eclipse.tracecompass.internal.ctf.core.trace.Utils;
 
 /**
@@ -119,7 +120,7 @@ public class CTFTrace implements IDefinitionScope {
     /**
      * Collection of streams contained in the trace.
      */
-    private final Map<Long, CTFStream> fStreams = new HashMap<>();
+    private final Map<Long, ICTFStream> fStreams = new HashMap<>();
 
     /**
      * Collection of environment variables set by the tracer
@@ -201,7 +202,7 @@ public class CTFTrace implements IDefinitionScope {
         }
 
         /* Create their index */
-        for (CTFStream stream : getStreams()) {
+        for (ICTFStream stream : getStreams()) {
             Set<CTFStreamInput> inputs = stream.getStreamInputs();
             for (CTFStreamInput s : inputs) {
                 addStream(s);
@@ -221,7 +222,7 @@ public class CTFTrace implements IDefinitionScope {
      * @return The list of event declarations
      */
     public Collection<IEventDeclaration> getEventDeclarations(Long streamId) {
-        CTFStream stream = fStreams.get(streamId);
+        ICTFStream stream = fStreams.get(streamId);
         if (stream == null) {
             return null;
         }
@@ -234,8 +235,9 @@ public class CTFTrace implements IDefinitionScope {
      * @param id
      *            Long the id of the stream
      * @return Stream the stream that we need
+     * @since 2.0
      */
-    public CTFStream getStream(Long id) {
+    public ICTFStream getStream(Long id) {
         if (id == null) {
             return fStreams.get(0L);
         }
@@ -405,7 +407,7 @@ public class CTFTrace implements IDefinitionScope {
      *
      * @return Iterable&lt;Stream&gt; an iterable over streams.
      */
-    public Iterable<CTFStream> getStreams() {
+    public Iterable<ICTFStream> getStreams() {
         return fStreams.values();
     }
 
@@ -428,7 +430,7 @@ public class CTFTrace implements IDefinitionScope {
         /*
          * add the stream
          */
-        CTFStream stream = s.getStream();
+        ICTFStream stream = s.getStream();
         fStreams.put(stream.getId(), stream);
 
         /*
@@ -449,10 +451,10 @@ public class CTFTrace implements IDefinitionScope {
      * @throws CTFException
      *             if there is a file error
      */
-    private CTFStream openStreamInput(File streamFile) throws CTFException {
+    private ICTFStream openStreamInput(File streamFile) throws CTFException {
         ByteBuffer byteBuffer;
         BitBuffer streamBitBuffer;
-        CTFStream stream;
+        ICTFStream stream;
 
         if (!streamFile.canRead()) {
             throw new CTFException("Unreadable file : " //$NON-NLS-1$
@@ -504,13 +506,16 @@ public class CTFTrace implements IDefinitionScope {
             throw new CTFException("Unexpected end of stream"); //$NON-NLS-1$
         }
 
+        if (!(stream instanceof CTFStream)) {
+            throw new CTFException("Stream is not a CTFStream, but rather a " + stream.getClass().getCanonicalName()); //$NON-NLS-1$
+        }
+        CTFStream ctfStream = (CTFStream) stream;
         /*
          * Create the stream input and add a reference to the streamInput in the
          * stream.
          */
-        stream.addInput(new CTFStreamInput(stream, streamFile));
-
-        return stream;
+        ctfStream.addInput(new CTFStreamInput(ctfStream, streamFile));
+        return ctfStream;
     }
 
     private void validateUUID(StructDefinition packetHeaderDef) throws CTFException {
@@ -586,8 +591,9 @@ public class CTFTrace implements IDefinitionScope {
      *            A stream object.
      * @throws ParseException
      *             If there was some problem reading the metadata
+     * @since 2.0
      */
-    public void addStream(CTFStream stream) throws ParseException {
+    public void addStream(ICTFStream stream) throws ParseException {
         /*
          * If there is already a stream without id (the null key), it must be
          * the only one
@@ -607,7 +613,7 @@ public class CTFTrace implements IDefinitionScope {
         /*
          * If a stream with the same ID already exists, it is not valid.
          */
-        CTFStream existingStream = fStreams.get(stream.getId());
+        ICTFStream existingStream = fStreams.get(stream.getId());
         if (existingStream != null) {
             throw new ParseException("Stream id already exists"); //$NON-NLS-1$
         }
@@ -709,7 +715,7 @@ public class CTFTrace implements IDefinitionScope {
      */
     public long getCurrentStartTime() {
         long currentStart = Long.MAX_VALUE;
-        for (CTFStream stream : fStreams.values()) {
+        for (ICTFStream stream : fStreams.values()) {
             for (CTFStreamInput si : stream.getStreamInputs()) {
                 currentStart = Math.min(currentStart, si.getIndex().getElement(0).getTimestampBegin());
             }
@@ -724,7 +730,7 @@ public class CTFTrace implements IDefinitionScope {
      */
     public long getCurrentEndTime() {
         long currentEnd = Long.MIN_VALUE;
-        for (CTFStream stream : fStreams.values()) {
+        for (ICTFStream stream : fStreams.values()) {
             for (CTFStreamInput si : stream.getStreamInputs()) {
                 currentEnd = Math.max(currentEnd, si.getTimestampEnd());
             }
@@ -807,12 +813,17 @@ public class CTFTrace implements IDefinitionScope {
         if (file == null) {
             throw new CTFException("cannot create a stream with no file"); //$NON-NLS-1$
         }
-        CTFStream stream = fStreams.get(id);
+        ICTFStream stream = fStreams.get(id);
         if (stream == null) {
             stream = new CTFStream(this);
             fStreams.put(id, stream);
         }
-        stream.addInput(new CTFStreamInput(stream, file));
+        if (stream instanceof CTFStream) {
+            CTFStream ctfStream = (CTFStream) stream;
+            ctfStream.addInput(new CTFStreamInput(stream, file));
+        } else {
+            throw new CTFException("Stream does not support adding input"); //$NON-NLS-1$
+        }
     }
 
     /**
index 905856dbb20859dd36bf5ee71ed80a5c2e5a4078..9c9bae563b5784fccbc5a630aa1cd13ed5e24458 100644 (file)
@@ -201,7 +201,7 @@ public class CTFTraceReader implements AutoCloseable {
         /*
          * For each stream.
          */
-        for (CTFStream stream : fTrace.getStreams()) {
+        for (ICTFStream stream : fTrace.getStreams()) {
             Set<CTFStreamInput> streamInputs = stream.getStreamInputs();
 
             /*
@@ -240,7 +240,7 @@ public class CTFTraceReader implements AutoCloseable {
      */
     public void update() throws CTFException {
         Set<CTFStreamInputReader> readers = new HashSet<>();
-        for (CTFStream stream : fTrace.getStreams()) {
+        for (ICTFStream stream : fTrace.getStreams()) {
             Set<CTFStreamInput> streamInputs = stream.getStreamInputs();
             for (CTFStreamInput streamInput : streamInputs) {
                 /*
index 46eaa665b1cdd34677869e0db00c5026f0feb183..c51977740ddc7e6af39b0d33832a31b5d8c6d5d7 100644 (file)
@@ -99,7 +99,7 @@ public class CTFTraceWriter {
             }
 
             // Copy packets
-            for (CTFStream stream : trace.getStreams()) {
+            for (ICTFStream stream : trace.getStreams()) {
                 Set<CTFStreamInput> inputs = stream.getStreamInputs();
                 for (CTFStreamInput s : inputs) {
                     CTFStreamOutputWriter streamOutputwriter = new CTFStreamOutputWriter(checkNotNull(s), out);
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/ICTFStream.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/ICTFStream.java
new file mode 100644 (file)
index 0000000..d98f131
--- /dev/null
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2014 Ericsson, Ecole Polytechnique de Montreal and others
+ *
+ * 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: Matthew Khouzam - Initial API and implementation
+ * Contributors: Simon Marchi - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.ctf.core.trace;
+
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.ctf.core.event.IEventDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
+import org.eclipse.tracecompass.internal.ctf.core.event.EventDeclaration;
+
+/**
+ * An _event stream_ can be divided into contiguous event packets of variable
+ * size. An event packet can contain a certain amount of padding at the end. The
+ * stream header is repeated at the beginning of each event packet. The
+ * rationale for the event stream design choices is explained in
+ * <a href="http://diamon.org/ctf/#specB" >Stream header rationale<a/>.
+ * <p>
+ *
+ * The event stream header will therefore be referred to as the _event packet
+ * header_ throughout the rest of this document.
+ *
+ * @author Matthew Khouzam
+ * @author Efficios - Javadoc
+ * @since 2.0
+ */
+public interface ICTFStream {
+
+    /**
+     * Gets the id of a stream
+     *
+     * @return id the id of a stream
+     * @since 1.0
+     */
+    long getId();
+
+    /**
+     * Is the id of a stream set
+     *
+     * @return If the ID is set or not
+     */
+    boolean isIdSet();
+
+    /**
+     *
+     * @return is the event header set (timestamp and stuff) (see Ctf Spec)
+     */
+    boolean isEventHeaderSet();
+
+    /**
+     *
+     * @return is the event context set (pid and stuff) (see Ctf Spec)
+     */
+    boolean isEventContextSet();
+
+    /**
+     *
+     * @return Is the packet context set (see Ctf Spec)
+     */
+    boolean isPacketContextSet();
+
+    /**
+     * Gets the event header declaration
+     *
+     * @return the event header declaration in declaration form
+     */
+    IDeclaration getEventHeaderDeclaration();
+
+    /**
+     *
+     * @return the event context declaration in structdeclaration form
+     */
+    StructDeclaration getEventContextDecl();
+
+    /**
+     *
+     * @return the packet context declaration in structdeclaration form
+     */
+    StructDeclaration getPacketContextDecl();
+
+    /**
+     *
+     * @return the set of all stream inputs for this stream
+     */
+    Set<CTFStreamInput> getStreamInputs();
+
+    /**
+     *
+     * @return the parent trace
+     */
+    CTFTrace getTrace();
+
+    /**
+     * Get all the event declarations in this stream.
+     *
+     * @return The event declarations for this stream
+     * @since 2.0
+     */
+    @NonNull
+    List<@Nullable IEventDeclaration> getEventDeclarations();
+
+    /**
+     * Get the event declaration for a given ID.
+     *
+     * @param eventId
+     *            The ID, can be {@link EventDeclaration#UNSET_EVENT_ID}, or any
+     *            positive value
+     * @return The event declaration with the given ID for this stream, or
+     *         'null' if there are no declaration with this ID
+     * @throws IllegalArgumentException
+     *             If the passed ID is invalid
+     */
+    @Nullable
+    IEventDeclaration getEventDeclaration(int eventId);
+
+}
\ No newline at end of file
index 6eb404b3a2046cc246f2a492d6d0aad1a6f6c619..3172b9daa219862dc9553c5abe5af7d0f952d887 100644 (file)
@@ -31,11 +31,11 @@ import org.eclipse.tracecompass.ctf.core.event.types.IntegerDefinition;
 import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
 import org.eclipse.tracecompass.ctf.core.event.types.StructDefinition;
 import org.eclipse.tracecompass.ctf.core.trace.CTFIOException;
-import org.eclipse.tracecompass.ctf.core.trace.CTFStream;
 import org.eclipse.tracecompass.ctf.core.trace.CTFStreamInputReader;
 import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
 import org.eclipse.tracecompass.ctf.core.trace.ICTFPacketDescriptor;
 import org.eclipse.tracecompass.internal.ctf.core.event.types.composite.EventHeaderDefinition;
+import org.eclipse.tracecompass.internal.ctf.core.trace.CTFStream;
 
 /**
  * Representation of one type of event. A bit like "int" or "long" but for trace
index e94d57ffcbd9ccf38d878d875c3ad462a79f49d0..bd7c26dc3b0f051733d949212baefadbfae1a313 100644 (file)
@@ -45,8 +45,8 @@ import org.eclipse.tracecompass.ctf.core.event.types.IntegerDeclaration;
 import org.eclipse.tracecompass.ctf.core.event.types.StringDeclaration;
 import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
 import org.eclipse.tracecompass.ctf.core.event.types.VariantDeclaration;
-import org.eclipse.tracecompass.ctf.core.trace.CTFStream;
 import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.ctf.core.trace.ICTFStream;
 import org.eclipse.tracecompass.ctf.parser.CTFParser;
 import org.eclipse.tracecompass.internal.ctf.core.Activator;
 import org.eclipse.tracecompass.internal.ctf.core.event.EventDeclaration;
@@ -56,6 +56,7 @@ import org.eclipse.tracecompass.internal.ctf.core.event.types.SequenceDeclaratio
 import org.eclipse.tracecompass.internal.ctf.core.event.types.StructDeclarationFlattener;
 import org.eclipse.tracecompass.internal.ctf.core.event.types.composite.EventHeaderCompactDeclaration;
 import org.eclipse.tracecompass.internal.ctf.core.event.types.composite.EventHeaderLargeDeclaration;
+import org.eclipse.tracecompass.internal.ctf.core.trace.CTFStream;
 
 import com.google.common.collect.Iterables;
 
@@ -458,8 +459,8 @@ public class IOStructGen {
             EnumDeclaration newEnum = new EnumDeclaration(IntegerDeclaration.createDeclaration(containerType.getLength(), containerType.isSigned(),
                     containerType.getBase(), byteOrder, containerType.getEncoding(),
                     containerType.getClock(), containerType.getAlignment()));
-            for( Entry<String, Pair> entry : decl.getEnumTable().entrySet()){
-               newEnum.add(entry.getValue().getFirst(), entry.getValue().getSecond(), entry.getKey());
+            for (Entry<String, Pair> entry : decl.getEnumTable().entrySet()) {
+                newEnum.add(entry.getValue().getFirst(), entry.getValue().getSecond(), entry.getKey());
             }
 
             parentScope.replaceType(name, newEnum);
@@ -724,10 +725,11 @@ public class IOStructGen {
              * could be possible to just get the only existing stream, whatever
              * is its id.
              */
-            CTFStream stream = fTrace.getStream(null);
+            ICTFStream iStream = fTrace.getStream(null);
+            if (iStream instanceof CTFStream) {
 
-            if (stream != null) {
-                event.setStream(stream);
+                CTFStream ctfStream = (CTFStream) iStream;
+                event.setStream(ctfStream);
             } else {
                 throw new ParseException("Event without stream_id, but there is no stream without id"); //$NON-NLS-1$
             }
@@ -739,6 +741,7 @@ public class IOStructGen {
         event.getStream().addEvent(event);
 
         popScope();
+
     }
 
     private void parseEventDeclaration(CommonTree eventDecl,
@@ -785,13 +788,15 @@ public class IOStructGen {
 
             long streamId = getStreamID(rightNode);
 
-            CTFStream stream = fTrace.getStream(streamId);
+            ICTFStream iStream = fTrace.getStream(streamId);
 
-            if (stream == null) {
+            if (iStream instanceof CTFStream) {
+                CTFStream stream = (CTFStream) iStream;
+                event.setStream(stream);
+            } else {
                 throw new ParseException("Stream " + streamId + " not found"); //$NON-NLS-1$ //$NON-NLS-2$
             }
 
-            event.setStream(stream);
         } else if (left.equals(MetadataStrings.CONTEXT)) {
             if (event.contextIsSet()) {
                 throw new ParseException("context already defined"); //$NON-NLS-1$
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/trace/CTFStream.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/trace/CTFStream.java
new file mode 100644 (file)
index 0000000..b434e4c
--- /dev/null
@@ -0,0 +1,316 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2014 Ericsson, Ecole Polytechnique de Montreal and others
+ *
+ * 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: Matthew Khouzam - Initial API and implementation
+ * Contributors: Simon Marchi - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.trace;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.ctf.core.CTFException;
+import org.eclipse.tracecompass.ctf.core.event.IEventDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.IEventHeaderDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
+import org.eclipse.tracecompass.ctf.core.trace.CTFStreamInput;
+import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.ctf.core.trace.ICTFStream;
+import org.eclipse.tracecompass.internal.ctf.core.event.EventDeclaration;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.exceptions.ParseException;
+
+/**
+ * <b><u>Stream</u></b>
+ * <p>
+ * Represents a stream in a trace.
+ */
+public class CTFStream implements ICTFStream {
+
+    // ------------------------------------------------------------------------
+    // Attributes
+    // ------------------------------------------------------------------------
+
+    /**
+     * The numerical ID of the stream
+     */
+    private long fId = 0;
+
+    /**
+     * Declarations of the stream-specific structures
+     */
+    private StructDeclaration fPacketContextDecl = null;
+    private IDeclaration fEventHeaderDecl = null;
+    private StructDeclaration fEventContextDecl = null;
+
+    /**
+     * The trace to which the stream belongs
+     */
+    private CTFTrace fTrace = null;
+
+    /**
+     * Maps event ids to events
+     */
+    private final ArrayList<@Nullable IEventDeclaration> fEvents = new ArrayList<>();
+
+    private boolean fEventUnsetId = false;
+    private boolean fStreamIdSet = false;
+
+    /**
+     * The inputs associated to this stream
+     */
+    private final Set<CTFStreamInput> fInputs = new HashSet<>();
+
+    // ------------------------------------------------------------------------
+    // Constructors
+    // ------------------------------------------------------------------------
+
+    /**
+     * Constructs a Stream that belongs to a Trace
+     *
+     * @param trace
+     *            The trace to which belongs this stream.
+     */
+    public CTFStream(CTFTrace trace) {
+        fTrace = trace;
+    }
+
+    // ------------------------------------------------------------------------
+    // Getters/Setters/Predicates
+    // ------------------------------------------------------------------------
+
+    /**
+     * Sets the id of a stream
+     *
+     * @param id
+     *            the id of a stream
+     */
+    public void setId(long id) {
+        fId = id;
+        fStreamIdSet = true;
+    }
+
+    @Override
+    public long getId() {
+        return fId;
+    }
+
+    @Override
+    public boolean isIdSet() {
+        return fStreamIdSet;
+    }
+
+    @Override
+    public boolean isEventHeaderSet() {
+        return fEventHeaderDecl != null;
+    }
+
+    @Override
+    public boolean isEventContextSet() {
+        return fEventContextDecl != null;
+    }
+
+    @Override
+    public boolean isPacketContextSet() {
+        return fPacketContextDecl != null;
+    }
+
+    /**
+     * Sets the event header
+     *
+     * @param eventHeader
+     *            the current event header for all events in this stream
+     */
+    public void setEventHeader(StructDeclaration eventHeader) {
+        fEventHeaderDecl = eventHeader;
+    }
+
+    /**
+     * Sets the event header, this typically has the id and the timestamp
+     *
+     * @param eventHeader
+     *            the current event header for all events in this stream
+     */
+    public void setEventHeader(IEventHeaderDeclaration eventHeader) {
+        fEventHeaderDecl = eventHeader;
+    }
+
+    /**
+     *
+     * @param eventContext
+     *            the context for all events in this stream
+     */
+    public void setEventContext(StructDeclaration eventContext) {
+        fEventContextDecl = eventContext;
+    }
+
+    /**
+     *
+     * @param packetContext
+     *            the packet context for all packets in this stream
+     */
+    public void setPacketContext(StructDeclaration packetContext) {
+        fPacketContextDecl = packetContext;
+    }
+
+    @Override
+    public IDeclaration getEventHeaderDeclaration() {
+        return fEventHeaderDecl;
+    }
+
+    @Override
+    public StructDeclaration getEventContextDecl() {
+        return fEventContextDecl;
+    }
+
+    @Override
+    public StructDeclaration getPacketContextDecl() {
+        return fPacketContextDecl;
+    }
+
+    @Override
+    public Set<CTFStreamInput> getStreamInputs() {
+        return fInputs;
+    }
+
+    @Override
+    public CTFTrace getTrace() {
+        return fTrace;
+    }
+
+    /**
+     * @since 2.0
+     */
+    @Override
+    public List<@Nullable IEventDeclaration> getEventDeclarations() {
+        return NonNullUtils.checkNotNull(Collections.unmodifiableList(fEvents));
+    }
+
+    @Override
+    public IEventDeclaration getEventDeclaration(int eventId) {
+        int eventIndex = (eventId == IEventDeclaration.UNSET_EVENT_ID) ? 0 : eventId;
+        if (eventIndex < 0) {
+            /* Any negative value other than UNSET_EVENT_ID is invalid */
+            throw new IllegalArgumentException("Event ID cannot be negative."); //$NON-NLS-1$
+        }
+        if (eventIndex >= fEvents.size()) {
+            /* This ID could be valid, but there are no declarations with it */
+            return null;
+        }
+        return fEvents.get(eventIndex);
+    }
+
+    // ------------------------------------------------------------------------
+    // Operations
+    // ------------------------------------------------------------------------
+
+    /**
+     * Adds an event to the event list.
+     *
+     * An event in a stream can omit its id if it is the only event in this
+     * stream. An event for which no id has been specified has a null id. It is
+     * thus not possible to add an event with the null key if the map is not
+     * empty. It is also not possible to add an event to the map if the null key
+     * is present in the map.
+     *
+     * @param event
+     *            The event to add
+     * @throws ParseException
+     *             If there was a problem reading the event or adding it to the
+     *             stream
+     * @since 2.0
+     */
+    public void addEvent(IEventDeclaration event) throws ParseException {
+        if (fEventUnsetId) {
+            throw new ParseException("Event without id with multiple events in a stream"); //$NON-NLS-1$
+        }
+        int id = ((EventDeclaration) event).id();
+
+        /*
+         * If there is an event without id (the null key), it must be the only
+         * one
+         */
+        if (id == IEventDeclaration.UNSET_EVENT_ID) {
+            if (!fEvents.isEmpty()) {
+                throw new ParseException("Event without id with multiple events in a stream"); //$NON-NLS-1$
+            }
+            fEventUnsetId = true;
+            fEvents.add(event);
+        } else {
+            /* Check if an event with the same ID already exists */
+            if (fEvents.size() > id && fEvents.get(id) != null) {
+                throw new ParseException("Event id already exists"); //$NON-NLS-1$
+            }
+            ensureSize(fEvents, id);
+            /* Put the event in the list */
+            fEvents.set(id, event);
+        }
+    }
+
+    /**
+     * Add a list of event declarations to this stream. There must be no overlap
+     * between the two lists of event declarations. This will merge the two
+     * lists and preserve the indexes of both lists.
+     *
+     * @param events
+     *            list of the events to add
+     * @throws CTFException
+     *             if the list already contains data
+     */
+    public void addEvents(Collection<IEventDeclaration> events) throws CTFException {
+        if (fEventUnsetId) {
+            throw new CTFException("Cannot add to a stream with an unidentified event"); //$NON-NLS-1$
+        }
+        if (fEvents.isEmpty()) {
+            fEvents.addAll(events);
+            return;
+        }
+        for (IEventDeclaration event : events) {
+            if (event != null) {
+                int index = event.getId().intValue();
+                ensureSize(fEvents, index);
+                if (fEvents.get(index) != null) {
+                    throw new CTFException("Both lists have an event defined at position " + index); //$NON-NLS-1$
+                }
+                fEvents.set(index, event);
+            }
+        }
+    }
+
+    private static void ensureSize(ArrayList<@Nullable ? extends Object> list, int index) {
+        list.ensureCapacity(index);
+        while (list.size() <= index) {
+            list.add(null);
+        }
+    }
+
+    /**
+     * Add an input to this Stream
+     *
+     * @param input
+     *            The StreamInput to add.
+     */
+    public void addInput(CTFStreamInput input) {
+        fInputs.add(input);
+    }
+
+    @Override
+    public String toString() {
+        return "Stream [id=" + fId + ", packetContextDecl=" + fPacketContextDecl //$NON-NLS-1$ //$NON-NLS-2$
+                + ", eventHeaderDecl=" + fEventHeaderDecl //$NON-NLS-1$
+                + ", eventContextDecl=" + fEventContextDecl + ", trace=" + fTrace //$NON-NLS-1$ //$NON-NLS-2$
+                + ", events=" + fEvents + ", inputs=" + fInputs + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+    }
+}
This page took 0.044565 seconds and 5 git commands to generate.