/*
 * Copyright 2009 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.rpc.server;

import static com.google.gwt.rpc.client.impl.CommandClientSerializationStreamReader.BACKREF_IDENT;

import com.google.gwt.rpc.client.ast.ArrayValueCommand;
import com.google.gwt.rpc.client.ast.BooleanValueCommand;
import com.google.gwt.rpc.client.ast.ByteValueCommand;
import com.google.gwt.rpc.client.ast.CharValueCommand;
import com.google.gwt.rpc.client.ast.CommandSink;
import com.google.gwt.rpc.client.ast.DoubleValueCommand;
import com.google.gwt.rpc.client.ast.EnumValueCommand;
import com.google.gwt.rpc.client.ast.FloatValueCommand;
import com.google.gwt.rpc.client.ast.InstantiateCommand;
import com.google.gwt.rpc.client.ast.IntValueCommand;
import com.google.gwt.rpc.client.ast.InvokeCustomFieldSerializerCommand;
import com.google.gwt.rpc.client.ast.LongValueCommand;
import com.google.gwt.rpc.client.ast.NullValueCommand;
import com.google.gwt.rpc.client.ast.ReturnCommand;
import com.google.gwt.rpc.client.ast.RpcCommand;
import com.google.gwt.rpc.client.ast.RpcCommandVisitor;
import com.google.gwt.rpc.client.ast.SetCommand;
import com.google.gwt.rpc.client.ast.ShortValueCommand;
import com.google.gwt.rpc.client.ast.StringValueCommand;
import com.google.gwt.rpc.client.ast.ThrowCommand;
import com.google.gwt.rpc.client.ast.ValueCommand;
import com.google.gwt.rpc.client.impl.CommandClientSerializationStreamReader;
import com.google.gwt.rpc.client.impl.EscapeUtil;
import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException;
import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.client.rpc.SerializationStreamReader;
import com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamWriter;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Stack;

/**
 * A CommandSink that will generate a web-mode payload.
 * 
 * ONE-SHOT EVAL (no incremental evaluation, must call finish())
 */
public class WebModePayloadSink extends CommandSink {

  private class BackRefAssigner extends RpcCommandVisitor {
    private final Set<ValueCommand> seenOnce = new HashSet<ValueCommand>();

    @Override
    public void endVisit(InvokeCustomFieldSerializerCommand x, Context ctx) {
      // We always need a backref for custom serializers
      makeBackRef(x);
    }

    @Override
    public void endVisit(LongValueCommand x, Context ctx) {
      process(x);
    }

    @Override
    public void endVisit(StringValueCommand x, Context ctx) {
      process(x);
    }

    @Override
    public boolean visit(ArrayValueCommand x, Context ctx) {
      return process(x);
    }

    @Override
    public boolean visit(InstantiateCommand x, Context ctx) {
      return process(x);
    }

    private boolean process(ValueCommand x) {
      if (!seenOnce.add(x)) {
        makeBackRef(x);
        return false;
      }
      return true;
    }
  }
  private class PayloadVisitor extends RpcCommandVisitor {
    private final Map<Class<?>, byte[]> constructorFunctions = new IdentityHashMap<Class<?>, byte[]>();
    private final Map<RpcCommand, ByteBuffer> commandBuffers = new IdentityHashMap<RpcCommand, ByteBuffer>();
    private ByteBuffer currentBuffer;
    private final Stack<RpcCommand> stack = new Stack<RpcCommand>();
    private final Set<RpcCommand> started = new HashSet<RpcCommand>();

    @Override
    public void endVisit(BooleanValueCommand x, Context ctx) {
      if (x.getValue()) {
        one();
      } else {
        zero();
      }
    }

    @Override
    public void endVisit(ByteValueCommand x, Context ctx) {
      push(String.valueOf(x.getValue()));
    }

    @Override
    public void endVisit(CharValueCommand x, Context ctx) {
      push(String.valueOf((int) x.getValue()));
    }

    @Override
    public void endVisit(DoubleValueCommand x, Context ctx) {
      push(String.valueOf(x.getValue()));
    }

    @Override
    public void endVisit(EnumValueCommand x, Context ctx) {
      String fieldName = clientOracle.getFieldId(x.getValue());
      if (fieldName == null) {
        throw new IncompatibleRemoteServiceException(
            "The client cannot accept " + x.getValue().name());
      }
      String clinitName = clientOracle.getMethodId(
          x.getValue().getDeclaringClass(), "$clinit");
      assert clinitName != null;

      // (clinit(), A)
      lparen();
      push(clinitName);
      lparen();
      rparen();
      comma();
      push(fieldName);
      rparen();
    }

    @Override
    public void endVisit(FloatValueCommand x, Context ctx) {
      push(String.valueOf((double) x.getValue()));
    }

    @Override
    public void endVisit(IntValueCommand x, Context ctx) {
      push(String.valueOf(x.getValue()));
    }

    @Override
    public void endVisit(LongValueCommand x, Context ctx) {
      long fieldValue = x.getValue();

      /*
       * Client code represents longs internally as an array of two Numbers. In
       * order to make serialization of longs faster, we'll send the component
       * parts so that the value can be directly reconstituted on the client.
       */
      double[] parts = AbstractSerializationStreamWriter.makeLongComponents(
          (int) (fieldValue >> 32), (int) fieldValue);
      assert parts.length == 2;
      lbracket();
      push(String.valueOf(parts[0]));
      comma();
      push(String.valueOf(parts[1]));
      rbracket();
    }

    @Override
    public void endVisit(NullValueCommand x, Context ctx) {
      _null();
    }

    @Override
    public void endVisit(ShortValueCommand x, Context ctx) {
      push(String.valueOf(x.getValue()));
    }

    @Override
    public void endVisit(StringValueCommand x, Context ctx) {
      if (hasBackRef(x)) {
        if (!isStarted(x)) {
          String escaped = EscapeUtil.escape(x.getValue());
          push(begin(x));
          eq();
          quote();
          push(escaped);
          quote();
          commit(x, false);
        } else {
          push(makeBackRef(x));
        }
      } else {
        String escaped = EscapeUtil.escape(x.getValue());
        quote();
        push(escaped);
        quote();
      }
    }

    @Override
    public boolean visit(ArrayValueCommand x, Context ctx) {
      boolean hasBackRef = hasBackRef(x);
      if (hasBackRef && isStarted(x)) {
        push(makeBackRef(x));
        return false;
      }

      // constructorFunction(x = [value,value,value])
      byte[] currentBackRef = begin(x);
      push(constructorFunction(x));
      lparen();
      if (hasBackRef) {
        push(currentBackRef);
        eq();
      }
      lbracket();
      for (Iterator<ValueCommand> it = x.getComponentValues().iterator(); it.hasNext();) {
        accept(it.next());
        if (it.hasNext()) {
          comma();
        }
      }
      rbracket();
      rparen();
      commit(x, false);
      if (!hasBackRef) {
        forget(x);
      }
      return false;
    }

    @Override
    public boolean visit(InstantiateCommand x, Context ctx) {
      boolean hasBackRef = hasBackRef(x);
      if (hasBackRef && isStarted(x)) {
        push(makeBackRef(x));
        return false;
      }

      byte[] currentBackRef = begin(x);
      byte[] constructorFunction = constructorFunction(x);
      String seedName = clientOracle.getSeedName(x.getTargetClass());

      if (seedName == null) {
        throw new IncompatibleRemoteServiceException(
            "The client cannot create type " + x.getTargetClass());
      }

      /*
       * If we need to maintain a backreference to the object, it's established
       * in the first argument instead of using the return value of the
       * constructorFunction. This is done in case one of the fields should
       * require a reference to the object that is currently being constructed.
       */
      // constructorFunctionFoo(x = new Foo, field1, field2)
      push(constructorFunction);
      lparen();
      if (hasBackRef) {
        push(currentBackRef);
        eq();
      }
      _new();
      push(seedName);
      for (SetCommand setter : x.getSetters()) {
        comma();
        accept(setter.getValue());
      }
      rparen();

      commit(x, false);
      if (!hasBackRef) {
        forget(x);
      }
      return false;
    }

    @Override
    public boolean visit(InvokeCustomFieldSerializerCommand x, Context ctx) {
      byte[] currentBackRef = null;
      // TODO Extract the commands as an inline function
      if (!isStarted(x)) {
        InstantiateCommand makeReader = new InstantiateCommand(
            CommandClientSerializationStreamReader.class);
        /*
         * Ensure that the reader will stick around for both instantiate and
         * deserialize calls.
         */
        makeBackRef(makeReader);

        ArrayValueCommand payload = new ArrayValueCommand(Object.class);
        for (ValueCommand value : x.getValues()) {
          payload.add(value);
        }
        makeReader.set(CommandClientSerializationStreamReader.class, "payload",
            payload);

        currentBackRef = begin(x);

        String instantiateIdent = clientOracle.getMethodId(
            x.getSerializerClass(), "instantiate",
            SerializationStreamReader.class);

        // x = $Foo(new Foo);
        // x = instantiate(reader);
        push(currentBackRef);
        eq();
        if (instantiateIdent == null) {
          // No instantiate method, we'll have to invoke the constructor

          instantiateIdent = clientOracle.getSeedName(x.getTargetClass());
          assert instantiateIdent != null : "instantiateIdent";

          // $Foo()
          String constructorMethodName;
          if (x.getTargetClass().getEnclosingClass() == null) {
            constructorMethodName = "$" + x.getTargetClass().getSimpleName();
          } else {
            String name = x.getTargetClass().getName();
            constructorMethodName = "$"
                + name.substring(name.lastIndexOf('.') + 1);
          }

          String constructorIdent = clientOracle.getMethodId(
              x.getTargetClass(), constructorMethodName, x.getTargetClass());
          assert constructorIdent != null : "constructorIdent "
              + constructorMethodName;

          // constructor(new Seed);
          push(constructorIdent);
          lparen();
          _new();
          push(instantiateIdent);
          rparen();
          semi();
        } else {
          // instantiate(reader);
          push(instantiateIdent);
          lparen();
          accept(makeReader);
          rparen();
          semi();
        }

        // Call the deserialize method if it exists
        String deserializeIdent = clientOracle.getMethodId(
            x.getSerializerClass(), "deserialize",
            SerializationStreamReader.class, x.getManuallySerializedType());
        if (deserializeIdent != null) {
          // deserialize(reader, obj);
          push(deserializeIdent);
          lparen();
          accept(makeReader);
          comma();
          push(currentBackRef);
          rparen();
          semi();
        }

        // If there are extra fields, set them
        for (SetCommand setter : x.getSetters()) {
          accept(setter);
          semi();
        }

        commit(x);
        forget(makeReader);
      }

      if (currentBackRef == null) {
        push(makeBackRef(x));
      } else {
        push(currentBackRef);
      }

      return false;
    }

    @Override
    public boolean visit(ReturnCommand x, Context ctx) {
      int size = x.getValues().size();

      begin(x);
      _return();

      // return [a,b,c];
      lbracket();
      for (int i = 0; i < size; i++) {
        accept(x.getValues().get(i));
        if (i < size - 1) {
          comma();
        }
      }
      rbracket();

      semi();
      commit(x);

      return false;
    }

    @Override
    public boolean visit(SetCommand x, Context ctx) {
      String fieldName = clientOracle.getFieldId(x.getFieldDeclClass(),
          x.getField());

      if (fieldName == null) {
        // TODO: What does it mean if the client doesn't have a field?
        throw new IncompatibleRemoteServiceException(
            "The client does not have field " + x.getField() + " in type "
                + x.getFieldDeclClass().getName());
      }

      // i[3].foo = bar
      push(makeBackRef((ValueCommand) stack.peek()));
      dot();
      push(fieldName);
      eq();
      accept(x.getValue());

      return false;
    }

    /**
     * In order to improve robustness of the payload, we perform the throw from
     * within a function.
     */
    @Override
    public boolean visit(ThrowCommand x, Context ctx) {
      // throw foo;
      begin(x);
      _throw();

      assert x.getValues().size() == 1;
      accept(x.getValues());

      semi();
      commit(x);

      return false;
    }

    // CHECKSTYLE_OFF

    private void _new() {
      push(NEW_BYTES);
    }

    private void _null() {
      push(NULL_BYTES);
    }

    private void _return() {
      push(RETURN_BYTES);
    }

    private void _throw() {
      push(THROW_BYTES);
    }

    // CHECKSTYLE_ON

    private void begin(RpcCommand x) {
      assert !commandBuffers.containsKey(x) : "ValueCommand already active";

      started.add(x);
      stack.push(x);
      currentBuffer = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE);
      commandBuffers.put(x, currentBuffer);
    }

    private byte[] begin(ValueCommand x) {
      begin((RpcCommand) x);
      return makeBackRef(x);
    }

    private void comma() {
      push(COMMA_BYTES);
      spaceOpt();
    }

    private void commit(RpcCommand x) {
      commit(x, true);
    }

    private void commit(RpcCommand x, boolean send) {
      if (stack.pop() != x) {
        throw new IllegalStateException("Did not pop expected command");
      }

      // Don't need to retain any internal data
      x.clear();

      ByteBuffer sb = commandBuffers.remove(x);
      assert sb != null : "No ByteBuffer for " + x;

      if (!stack.isEmpty()) {
        currentBuffer = commandBuffers.get(stack.peek());
        assert currentBuffer != null : "Could not restore currentBuilder";
      } else {
        currentBuffer = null;
      }

      sb.limit(sb.position()).rewind();

      if (send) {
        try {
          send(sb);
        } catch (SerializationException e) {
          halt(e);
        }
      } else {
        push(sb);
      }
    }

    private byte[] constructorFunction(ArrayValueCommand x) {
      Class<?> targetClass = Array.newInstance(x.getComponentType(), 0).getClass();
      byte[] functionName = constructorFunctions.get(targetClass);
      if (functionName != null) {
        return functionName;
      }

      String initValuesId = clientOracle.getMethodId(
          "com.google.gwt.lang.Array", "initValues", "Ljava/lang/Class;", "I",
          "I", "Lcom/google/gwt/lang/Array;");
      assert initValuesId != null : "Could not find initValues";

      String classLitId = clientOracle.getFieldId(
          "com.google.gwt.lang.ClassLiteralHolder",
          getJavahSignatureName(x.getComponentType()) + "_classLit");
      assert classLitId != null : "No class literal for "
          + x.getComponentType().getName();

      functionName = getBytes(clientOracle.createUnusedIdent(classLitId));
      constructorFunctions.put(targetClass, functionName);

      /*
       * Set the typeIds and queryIds to exact values, or fall back to acting
       * like a plain Object[] array.
       */
      int typeId = clientOracle.getTypeId(targetClass);
      if (typeId == 0) {
        typeId = clientOracle.getTypeId(Object[].class);
      }

      int queryId = clientOracle.getTypeId(x.getComponentType());
      if (queryId == 0) {
        queryId = clientOracle.getTypeId(Object.class);
      }

      byte[] ident = getBytes("_0");

      // function foo(_0) {return initValues(classLid, typeId, queryId, _0)}
      function();
      push(functionName);
      lparen();
      push(ident);
      rparen();
      lbrace();
      _return();
      push(initValuesId);
      lparen();
      push(classLitId);
      comma();
      push(String.valueOf(typeId));
      comma();
      push(String.valueOf(queryId));
      comma();
      push(ident);
      rparen();
      rbrace();

      flush(x);

      return functionName;
    }

    private byte[] constructorFunction(InstantiateCommand x) {
      Class<?> targetClass = x.getTargetClass();
      byte[] functionName = constructorFunctions.get(targetClass);
      if (functionName != null) {
        return functionName;
      }

      String seedName = clientOracle.getSeedName(targetClass);
      assert seedName != null : "TypeOverride failed to rescue "
          + targetClass.getName();
      functionName = getBytes(clientOracle.createUnusedIdent(seedName));
      constructorFunctions.put(targetClass, functionName);
      byte[][] idents = new byte[x.getSetters().size() + 1][];
      for (int i = 0, j = idents.length; i < j; i++) {
        idents[i] = getBytes("_" + i);
      }

      // function foo(_0, _1, _2) {_0.a = _1; _0.b=_2; return _0}
      function();
      push(functionName);
      lparen();
      for (int i = 0, j = idents.length; i < j; i++) {
        push(idents[i]);
        if (i < j - 1) {
          comma();
        }
      }
      rparen();
      lbrace();
      newlineOpt();
      for (int i = 1, j = idents.length; i < j; i++) {
        SetCommand setter = x.getSetters().get(i - 1);
        String fieldIdent = clientOracle.getFieldId(setter.getFieldDeclClass(),
            setter.getField());

        // _0.foo = bar;
        spaceOpt();
        push(idents[0]);
        dot();
        push(fieldIdent);
        eq();
        push(idents[i]);
        semi();
      }
      spaceOpt();
      _return();
      push(idents[0]);
      rbrace();
      newlineOpt();

      flush(x);

      return functionName;
    }

    private void dot() {
      push(DOT_BYTES);
    }

    private void eq() {
      spaceOpt();
      push(EQ_BYTES);
      spaceOpt();
    }

    /**
     * Cause an immediate write of accumulated output for a command. This is
     * used primarily for writing object allocations
     */
    private void flush(RpcCommand x) {
      ByteBuffer sb = commandBuffers.get(x);
      if (sb == null || sb.position() == 0) {
        return;
      }

      sb.limit(sb.position()).rewind();
      try {
        send(sb);
      } catch (SerializationException e) {
        halt(e);
      }
      sb.clear();
    }

    private void function() {
      newlineOpt();
      push(FUNCTION_BYTES);
    }

    /**
     * Keep in sync with JReferenceType implementations.
     */
    private String getJavahSignatureName(Class<?> clazz) {
      if (clazz.isArray()) {
        Class<?> leafType = clazz;
        int dims = 0;
        do {
          dims++;
          leafType = leafType.getComponentType();
        } while (leafType.getComponentType() != null);
        assert dims > 0;
        assert leafType != null;

        String s = getJavahSignatureName(leafType);
        for (int i = 0; i < dims; ++i) {
          s = "_3" + s;
        }
        return s;
      } else if (clazz.isPrimitive()) {
        return WebModeClientOracle.jsniName(clazz);
      } else {
        String name = clazz.getName();
        return "L" + name.replaceAll("_", "_1").replace('.', '_') + "_2";
      }
    }

    private boolean isStarted(RpcCommand x) {
      return started.contains(x);
    }

    private void lbrace() {
      push(LBRACE_BYTES);
    }

    private void lbracket() {
      push(LBRACKET_BYTES);
    }

    private void lparen() {
      push(LPAREN_BYTES);
    }

    private void newlineOpt() {
      pushOpt(NEWLINE_BYTES);
    }

    private void one() {
      push(ONE_BYTES);
    }

    /**
     * Add data to the current command's serialization output.
     */
    private void push(byte[] bytes) {
      assert currentBuffer != null : "Must call begin(RpcCommand) first";
      try {
        currentBuffer.put(bytes);
      } catch (BufferOverflowException e) {
        reallocateCurrentBuffer(bytes.length);
        currentBuffer.put(bytes);
      }
    }

    /**
     * Add data to the current command's serialization output.
     */
    private void push(ByteBuffer buffer) {
      assert currentBuffer != null : "Must call begin(RpcCommand) first";
      try {
        currentBuffer.put(buffer);
      } catch (BufferOverflowException e) {
        reallocateCurrentBuffer(buffer.remaining());
        currentBuffer.put(buffer);
      }
    }

    /**
     * Add data to the current command's serialization output.
     */
    private void push(String s) {
      push(getBytes(s));
    }

    /**
     * Optionally add data to the current command's serialization output.
     */
    private void pushOpt(byte[] x) {
      if (PRETTY) {
        push(x);
      }
    }

    private void quote() {
      push(QUOTE_BYTES);
    }

    private void rbrace() {
      push(RBRACE_BYTES);
    }

    private void rbracket() {
      push(RBRACKET_BYTES);
    }

    private void reallocateCurrentBuffer(int bytesNeeded) {
      // Allocate a new buffer of sufficient size
      int newSize = currentBuffer.capacity()
          + Math.max(2 * bytesNeeded, currentBuffer.capacity());
      ByteBuffer newBuffer = ByteBuffer.allocate(newSize);

      // Copy the old buffer over
      currentBuffer.limit(currentBuffer.position()).rewind();
      newBuffer.put(currentBuffer);

      // Reassign the current buffer
      assert commandBuffers.get(stack.peek()) == currentBuffer;
      commandBuffers.put(stack.peek(), newBuffer);
      currentBuffer = newBuffer;
    }

    private void rparen() {
      push(RPAREN_BYTES);
    }

    private void semi() {
      push(SEMI_BYTES);
      newlineOpt();
    }

    private void spaceOpt() {
      pushOpt(SPACE_BYTES);
    }

    private void zero() {
      push(ZERO_BYTES);
    }
  }

  /*
   * Instead of converting these commonly-used strings to bytes every time we
   * want to write them to the output, we'll simply create a fixed pool.
   */
  static final byte[] COMMA_BYTES = getBytes(",");
  static final byte[] DOT_BYTES = getBytes(".");
  static final byte[] EQ_BYTES = getBytes("=");
  static final byte[] FUNCTION_BYTES = getBytes("function ");
  static final byte[] LBRACE_BYTES = getBytes("{");
  static final byte[] LBRACKET_BYTES = getBytes("[");
  static final byte[] LPAREN_BYTES = getBytes("(");
  static final byte[] NEW_BYTES = getBytes("new ");
  static final byte[] NEWLINE_BYTES = getBytes("\n");
  static final byte[] NULL_BYTES = getBytes("null");
  static final byte[] ONE_BYTES = getBytes("1");
  static final byte[] QUOTE_BYTES = getBytes("\"");
  static final byte[] RBRACE_BYTES = getBytes("}");
  static final byte[] RBRACKET_BYTES = getBytes("]");
  static final byte[] RETURN_BYTES = getBytes("return ");
  static final byte[] RPAREN_BYTES = getBytes(")");
  static final byte[] SPACE_BYTES = getBytes(" ");
  static final byte[] SEMI_BYTES = getBytes(";");
  static final byte[] THROW_BYTES = getBytes("throw ");
  static final byte[] ZERO_BYTES = getBytes("0");

  /**
   * A runtime flag to indicate that the generated output should be made to be
   * human-readable.
   */
  static final boolean PRETTY = Boolean.getBoolean("gwt.rpc.pretty");

  private static final int DEFAULT_BUFFER_SIZE = 256;

  static byte[] getBytes(String x) {
    try {
      return x.getBytes("UTF-8");
    } catch (UnsupportedEncodingException e) {
      throw new RuntimeException("UTF-8 is unsupported", e);
    }
  }

  private final ClientOracle clientOracle;
  private boolean finished = false;
  private final OutputStream out;
  private final Map<ValueCommand, byte[]> valueBackRefs = new HashMap<ValueCommand, byte[]>();
  private final PayloadVisitor visitor = new PayloadVisitor();

  private Stack<byte[]> freeBackRefs = new Stack<byte[]>();

  public WebModePayloadSink(ClientOracle clientOracle, OutputStream out) {
    this.clientOracle = clientOracle;
    this.out = out;
  }

  @Override
  public void accept(RpcCommand command) throws SerializationException {
    if (finished) {
      throw new IllegalStateException("finish() has already been called");
    }

    new BackRefAssigner().accept(command);

    if (command instanceof ValueCommand) {
      makeBackRef((ValueCommand) command);
    }
    visitor.accept(command);
  }

  /**
   * The caller must close the stream.
   */
  @Override
  public void finish() throws SerializationException {
    if (finished) {
      return;
    }
    try {
      out.flush();
    } catch (IOException e) {
      throw new SerializationException("Could not flush stream", e);
    }
    finished = true;
  }

  void forget(ValueCommand x) {
    assert valueBackRefs.containsKey(x);
    freeBackRefs.push(valueBackRefs.remove(x));
  }

  boolean hasBackRef(ValueCommand x) {
    return valueBackRefs.containsKey(x);
  }

  byte[] makeBackRef(ValueCommand x) {
    byte[] toReturn = valueBackRefs.get(x);
    if (toReturn == null) {
      if (freeBackRefs.isEmpty()) {
        int idx = valueBackRefs.size();
        toReturn = getBytes(BACKREF_IDENT + "._"
            + Integer.toString(idx, Character.MAX_RADIX));
      } else {
        toReturn = freeBackRefs.pop();
      }
      valueBackRefs.put(x, toReturn);
    }
    return toReturn;
  }

  void send(ByteBuffer x) throws SerializationException {
    try {
      assert x.hasArray();
      out.write(x.array(), x.position(), x.limit());
    } catch (IOException e) {
      throw new SerializationException("Could not send data", e);
    }
  }

  void send(String x) throws SerializationException {
    try {
      out.write(getBytes(x));
    } catch (IOException e) {
      throw new SerializationException("Could not send data", e);
    }
  }
}
