public void processMessage() throws CruiseRuntimeException {
    TupleExpression tuple = messages.remove();
    for (MessageHandler mh : behavior.getHandlers()) {
      Map<String,ValueExpression> match = new HashMap<String,ValueExpression>(state);
      if (mh.matches(tuple, match)) {
        match.put("$self", new ActorIdentifier(this.getName()));
        // First, instantiate actors.
        for (CreateActorStatement create : mh.getCreations()) {
          create.execute(engine, match);
        }
        for (SendMessageStatement outmsg : mh.getSends()) {
          SendMessageStatement msg = (SendMessageStatement) outmsg.instantiateVariables(match);
          engine.sendMessage(this, msg.getConcreteTarget().getName(), msg.getConcreteMessage());
        }
        String replacementBehavior = mh.getReplacementBehavior();
        if (replacementBehavior != null) {
          behavior = actorSpec.getBehavior(replacementBehavior);
          if (behavior == null) {
            throw new CruiseRuntimeException("No behavior " + behavior + " in actor type " + actorSpec.getName());
          }
          adoptBehavior(behavior, mh.getReplacementParameters(), match);
        }
        return;
      }
    }
    throw new CruiseRuntimeException("Actor type " + actorSpec.getName() + " has no action to match message " + tuple);
  }