/**
   * Handles the remote dispatch of a local event so that runners on other nodes can eventually
   * receive the data.
   */
  @Override
  public void newStateAdded(ITransition sourceTransition, IState newStateId) {
    if (sourceTransition == null) {
      return;
    }

    NewStateChange change =
        new NewStateChange(
            sourceTransition.getFiredFrom().getId(),
            sourceTransition.getId(),
            newStateId.getId(),
            convert(newStateId.getOutgoingTransitions()),
            "me");

    if (appliedRemoteChanges.contains(change)) {
      appliedRemoteChanges.remove(change);
      return;
    }

    List<IDesignSpaceChange> push = null;
    synchronized (hashSet) {
      hashSet.add(change);
      if (hashSet.size() > 0) {
        push = new ArrayList<IDesignSpaceChange>();
        push.addAll(hashSet);
        hashSet.clear();
      }
    }

    if (push != null) {
      remote.doUpdates(push, identifier);
      //			process(updates);
    }
  }
  @Override
  public void newRootAdded(IState state) {
    NewRootChange newRootChange =
        new NewRootChange(state.getId(), convert(state.getOutgoingTransitions()), "me");

    if (appliedRemoteChanges.contains(newRootChange)) {
      appliedRemoteChanges.remove(newRootChange);
      return;
    }

    List<IDesignSpaceChange> changeList = null;
    synchronized (hashSet) {
      hashSet.add(newRootChange);
      changeList = new ArrayList<IDesignSpaceChange>();
      changeList.addAll(hashSet);
      hashSet.clear();
    }

    if (changeList != null) {
      remote.doUpdates(changeList, identifier);
      //			if (updates != null) {
      //				process(updates);
      //			}
    }

    System.out.println("Root added " + state.getId());
  }
  private boolean merge(IDesignSpaceChange change) {
    if (change instanceof NewRootChange) {
      NewRootChange newRootChange = (NewRootChange) change;

      local.addState(
          null,
          newRootChange.getRootId(),
          convertLocal(newRootChange.getOutgoingTransitions()),
          false);
      System.out.println("DS root is now: " + local.getRoot());
      return true;
    }
    if (change instanceof NewStateChange) {
      NewStateChange newStateChange = (NewStateChange) change;
      IState sourceState = local.getStateById(newStateChange.getSourceStateId());
      if (sourceState != null) {
        //				System.out.println("source state is id: " + newStateChange.getSourceStateId() + "
        // locally found id: "
        //						+ sourceState);
        ITransition sourceTransition = null;
        for (ITransition t : sourceState.getOutgoingTransitions()) {
          if (t.getId().equals(newStateChange.getTransitionId())) {
            sourceTransition = t;
          }
        }
        if (sourceTransition == null) {
          throw new Error();
        }

        appliedRemoteChanges.add(change);
        local.addState(
            sourceTransition,
            newStateChange.getNewStateId(),
            convertLocal(newStateChange.getOutgoingTransitions()),
            false);
        return true;
      } else {
        return false;
      }
    }
    throw new Error();
  }