// Returns a brand new context based on the location provided
  // and initializes the event queues
  @Override
  public synchronized TmfExperimentContext seekLocation(ITmfLocation<?> location) {
    // Validate the location
    if (location != null && !(location instanceof TmfExperimentLocation)) {
      return null; // Throw an exception?
    }

    if (fTraces == null) { // experiment has been disposed
      return null;
    }

    // Instantiate the location
    TmfExperimentLocation expLocation =
        (location == null)
            ? new TmfExperimentLocation(
                new TmfLocationArray(new ITmfLocation<?>[fTraces.length]), new long[fTraces.length])
            : (TmfExperimentLocation) location.clone();

    // Create and populate the context's traces contexts
    TmfExperimentContext context =
        new TmfExperimentContext(fTraces, new TmfContext[fTraces.length]);
    //		Tracer.trace("Ctx: SeekLocation - start");

    long rank = 0;
    for (int i = 0; i < fTraces.length; i++) {
      // Get the relevant trace attributes
      ITmfLocation<?> traceLocation = expLocation.getLocation().locations[i];
      long traceRank = expLocation.getRanks()[i];

      // Set the corresponding sub-context
      context.getContexts()[i] = fTraces[i].seekLocation(traceLocation);
      context.getContexts()[i].setRank(traceRank);
      rank += traceRank;

      // Set the trace location and read the corresponding event
      expLocation.getLocation().locations[i] = context.getContexts()[i].getLocation();
      context.getEvents()[i] = fTraces[i].getNextEvent(context.getContexts()[i]);
    }

    //		Tracer.trace("Ctx: SeekLocation - done");

    // Finalize context
    context.setLocation(expLocation);
    context.setLastTrace(TmfExperimentContext.NO_TRACE);
    context.setRank(rank);

    fExperimentContext = context;

    return context;
  }
  @Override
  public synchronized TmfEvent getNextEvent(TmfContext context) {

    // Validate the context
    if (!(context instanceof TmfExperimentContext)) {
      return null; // Throw an exception?
    }

    if (!context.equals(fExperimentContext)) {
      //    		Tracer.trace("Ctx: Restoring context");
      fExperimentContext = seekLocation(context.getLocation());
    }

    TmfExperimentContext expContext = (TmfExperimentContext) context;

    //		dumpContext(expContext, true);

    // If an event was consumed previously, get the next one from that trace
    int lastTrace = expContext.getLastTrace();
    if (lastTrace != TmfExperimentContext.NO_TRACE) {
      TmfContext traceContext = expContext.getContexts()[lastTrace];
      expContext.getEvents()[lastTrace] =
          expContext.getTraces()[lastTrace].getNextEvent(traceContext);
      expContext.setLastTrace(TmfExperimentContext.NO_TRACE);
    }

    // Scan the candidate events and identify the "next" trace to read from
    TmfEvent eventArray[] = expContext.getEvents();
    if (eventArray == null) {
      return null;
    }
    int trace = TmfExperimentContext.NO_TRACE;
    TmfTimestamp timestamp = TmfTimestamp.BigCrunch;
    if (eventArray.length == 1) {
      if (eventArray[0] != null) {
        timestamp = eventArray[0].getTimestamp();
        trace = 0;
      }
    } else {
      for (int i = 0; i < eventArray.length; i++) {
        TmfEvent event = eventArray[i];
        if (event != null && event.getTimestamp() != null) {
          TmfTimestamp otherTS = event.getTimestamp();
          if (otherTS.compareTo(timestamp, true) < 0) {
            trace = i;
            timestamp = otherTS;
          }
        }
      }
    }
    // Update the experiment context and set the "next" event
    TmfEvent event = null;
    if (trace != TmfExperimentContext.NO_TRACE) {
      updateIndex(expContext, timestamp);

      TmfContext traceContext = expContext.getContexts()[trace];
      TmfExperimentLocation expLocation = (TmfExperimentLocation) expContext.getLocation();
      //	        expLocation.getLocation()[trace] = traceContext.getLocation().clone();
      expLocation.getLocation().locations[trace] = traceContext.getLocation();

      //	        updateIndex(expContext, timestamp);

      expLocation.getRanks()[trace] = traceContext.getRank();
      expContext.setLastTrace(trace);
      expContext.updateRank(1);
      event = expContext.getEvents()[trace];
      fExperimentContext = expContext;
    }

    //		if (event != null) {
    //    		Tracer.trace("Exp: " + (expContext.getRank() - 1) + ": " +
    // event.getTimestamp().toString());
    //    		dumpContext(expContext, false);
    //    		Tracer.trace("Ctx: Event returned= " + event.getTimestamp().toString());
    //		}

    return event;
  }