From c8bcec783ca9640b3ee127f379a7dacf1053b4be Mon Sep 17 00:00:00 2001
From: Anders Blomdell <anders.blomdell@control.lth.se>
Date: Tue, 2 Jun 2015 12:25:43 +0200
Subject: [PATCH] Renaming implemented for Java. Various cleanups.

---
 compiler/2014/Java_CodeGen.jrag               | 72 ++++++++--------
 lib/csharp/Makefile                           |  2 +-
 .../lth/control/labcomm2014/DecoderChannel.cs |  8 +-
 .../control/labcomm2014/DecoderRegistry.cs    |  2 +-
 .../lth/control/labcomm2014/EncoderChannel.cs |  2 +-
 .../control/labcomm2014/EncoderRegistry.cs    |  2 +-
 .../control/labcomm2014/RenamingDecoder.cs    | 13 +--
 .../control/labcomm2014/RenamingEncoder.cs    |  7 +-
 lib/java/Makefile                             |  5 ++
 .../se/lth/control/labcomm2014/Decoder.java   |  2 +-
 .../control/labcomm2014/DecoderChannel.java   | 85 +++++++------------
 .../se/lth/control/labcomm2014/Encoder.java   |  4 +-
 .../control/labcomm2014/EncoderChannel.java   |  7 +-
 .../control/labcomm2014/EncoderRegistry.java  | 24 ++----
 .../control/labcomm2014/RenamingDecoder.java  | 37 ++++++++
 .../control/labcomm2014/RenamingEncoder.java  | 54 ++++++++++++
 .../control/labcomm2014/RenamingRegistry.java | 64 ++++++++++++++
 .../control/labcomm2014/SampleDispatcher.java | 10 ---
 .../control/labcomm2014/WrappingDecoder.java  | 70 +++++++++++++++
 .../control/labcomm2014/WrappingEncoder.java  | 69 +++++++++++++++
 test/Makefile                                 | 18 ++--
 test/relay_gen_cs.py                          |  4 +-
 test/relay_gen_java.py                        | 42 ++++++---
 23 files changed, 443 insertions(+), 160 deletions(-)
 create mode 100644 lib/java/se/lth/control/labcomm2014/RenamingDecoder.java
 create mode 100644 lib/java/se/lth/control/labcomm2014/RenamingEncoder.java
 create mode 100644 lib/java/se/lth/control/labcomm2014/RenamingRegistry.java
 create mode 100644 lib/java/se/lth/control/labcomm2014/WrappingDecoder.java
 create mode 100644 lib/java/se/lth/control/labcomm2014/WrappingEncoder.java

diff --git a/compiler/2014/Java_CodeGen.jrag b/compiler/2014/Java_CodeGen.jrag
index d7f7dc5..3d33a3b 100644
--- a/compiler/2014/Java_CodeGen.jrag
+++ b/compiler/2014/Java_CodeGen.jrag
@@ -510,36 +510,36 @@ aspect Java_Class {
     env.println("private static class Dispatcher implements SampleDispatcher "+genericStr+"{");
     env.indent();
     env.println();
-    env.println("public Class"+genericStr+" getSampleClass() {");
-    env.indent();
-    env.println("return " + getName() + ".class;");
-    env.unindent();
-    env.println("}");
-    env.println();
+//    env.println("public Class"+genericStr+" getSampleClass() {");
+//    env.indent();
+//    env.println("return " + getName() + ".class;");
+//    env.unindent();
+//    env.println("}");
+//    env.println();
     env.println("public String getName() {");
     env.indent();
     env.println("return \"" + getName() + "\";");
     env.unindent();
     env.println("}");
     env.println();
-    env.println("public byte getTypeDeclTag() {");
-    env.indent();
-    if(env.version == 2006) {
-      if(isSample) {
-        env.println("return Constant.SAMPLE;");
-      } else {
-        env.println("return Constant.TYPEDEF;");
-      }
-    } else {
-      if(isSample) {
-        env.println("return Constant.SAMPLE_DEF;");
-      } else {
-        env.println("return Constant.TYPE_DEF;");
-      }
-    }
-    env.unindent();
-    env.println("}");
-    env.println();
+//    env.println("public byte getTypeDeclTag() {");
+//    env.indent();
+//    if(env.version == 2006) {
+//      if(isSample) {
+//        env.println("return Constant.SAMPLE;");
+//      } else {
+//        env.println("return Constant.TYPEDEF;");
+//      }
+//    } else {
+//      if(isSample) {
+//        env.println("return Constant.SAMPLE_DEF;");
+//      } else {
+//        env.println("return Constant.TYPE_DEF;");
+//      }
+//    }
+//    env.unindent();
+//    env.println("}");
+//    env.println();
 //    env.println("public boolean isSample() {");
 //    env.indent();
 //    env.println("return "+isSample+";");
@@ -568,16 +568,16 @@ aspect Java_Class {
 //    env.unindent();
 //    env.println("}");
 //    env.println();
-    env.println("public void encodeTypeDef(Encoder e, int index) throws IOException{");
-    env.indent();
-    if(!isSample || hasDependencies()) {
-      env.println("emitSignature(e);");
-    } else {
-      env.println("// the type has no dependencies, do nothing");
-    }
-    env.unindent();
-    env.println("}");
-    env.println();
+//    env.println("public void encodeTypeDef(Encoder e, int index) throws IOException{");
+//    env.indent();
+//    if(!isSample || hasDependencies()) {
+//      env.println("emitSignature(e);");
+//    } else {
+//      env.println("// the type has no dependencies, do nothing");
+//    }
+//    env.unindent();
+//    env.println("}");
+//    env.println();
     env.println("public boolean canDecodeAndHandle() {");
     env.indent();
     env.println("return "+isSample+";");
@@ -834,7 +834,7 @@ aspect Java_Class {
   public void PrimType.Java_emitTypePrefix(Java_env env) {
     switch (getToken()) {
       case LABCOMM_STRING: { env.print("String"); } break;
-      case LABCOMM_SAMPLE: { env.print("Class"); } break;
+      case LABCOMM_SAMPLE: { env.print("SampleDispatcher"); } break;
       default: { env.print(getName()); } break;
     }
   }
@@ -961,7 +961,7 @@ aspect Java_Class {
   public void PrimType.Java_emitType(Java_env env) {
     switch (getToken()) {
       case LABCOMM_STRING: { env.print("String"); } break;
-      case LABCOMM_SAMPLE: { env.print("Class"); } break;
+      case LABCOMM_SAMPLE: { env.print("SampleDispatcher"); } break;
       default: { env.print(getName()); } break;
     }
   }
diff --git a/lib/csharp/Makefile b/lib/csharp/Makefile
index 71a5c31..3c803ee 100644
--- a/lib/csharp/Makefile
+++ b/lib/csharp/Makefile
@@ -1,4 +1,4 @@
-MODULES=Constant\
+MODULES=Constant \
 	Decoder \
 	DecoderChannel \
 	DecoderRegistry \
diff --git a/lib/csharp/se/lth/control/labcomm2014/DecoderChannel.cs b/lib/csharp/se/lth/control/labcomm2014/DecoderChannel.cs
index cf3426b..154e02e 100644
--- a/lib/csharp/se/lth/control/labcomm2014/DecoderChannel.cs
+++ b/lib/csharp/se/lth/control/labcomm2014/DecoderChannel.cs
@@ -50,9 +50,10 @@ namespace se.lth.control.labcomm2014 {
           if (e == null) {
             throw new IOException("Unhandled tag " + tag);
           }
-          SampleDispatcher d = e.getSampleDispatcher();
+          SampleDispatcher d = e.getDispatcher();
           if (d == null) {
-            throw new IOException("No dispatcher for '" + e.getName() + "'" + e.getSignature());
+            throw new IOException("No dispatcher for '" + e.getName() + "' " +
+                                  e.getSignature());
           }
           SampleHandler h = e.getHandler();
           if (h == null) {
@@ -164,8 +165,9 @@ namespace se.lth.control.labcomm2014 {
       int index = (int)ReadInt(4);
       try {
         DecoderRegistry.Entry e = ref_registry.get(index);
-        return e.getSampleDispatcher();
+        return e.getDispatcher();
       } catch (NullReferenceException) {
+        // Handles both the case where index == 0 and unregistered sample
         return null;
       }
     }
diff --git a/lib/csharp/se/lth/control/labcomm2014/DecoderRegistry.cs b/lib/csharp/se/lth/control/labcomm2014/DecoderRegistry.cs
index d9f9c58..b5b9350 100644
--- a/lib/csharp/se/lth/control/labcomm2014/DecoderRegistry.cs
+++ b/lib/csharp/se/lth/control/labcomm2014/DecoderRegistry.cs
@@ -27,7 +27,7 @@ namespace se.lth.control.labcomm2014 {
 	this.signature = signature;
       }
 
-      public SampleDispatcher getSampleDispatcher() {
+      public SampleDispatcher getDispatcher() {
 	return dispatcher;
       }
 
diff --git a/lib/csharp/se/lth/control/labcomm2014/EncoderChannel.cs b/lib/csharp/se/lth/control/labcomm2014/EncoderChannel.cs
index 7355905..9f2a76a 100644
--- a/lib/csharp/se/lth/control/labcomm2014/EncoderChannel.cs
+++ b/lib/csharp/se/lth/control/labcomm2014/EncoderChannel.cs
@@ -137,7 +137,7 @@ namespace se.lth.control.labcomm2014 {
       try {
         index = ref_registry.getTag(value);
       } catch (NullReferenceException) {
-        //we want to return 0 for unregistered ref types
+        // encode 0 for unregistered ref types
       }
       WriteInt(index, 4);
     }
diff --git a/lib/csharp/se/lth/control/labcomm2014/EncoderRegistry.cs b/lib/csharp/se/lth/control/labcomm2014/EncoderRegistry.cs
index e8b5730..38d6989 100644
--- a/lib/csharp/se/lth/control/labcomm2014/EncoderRegistry.cs
+++ b/lib/csharp/se/lth/control/labcomm2014/EncoderRegistry.cs
@@ -15,7 +15,7 @@ namespace se.lth.control.labcomm2014 {
 	this.index = index;
       }
 
-      public SampleDispatcher getSampleDispatcher() {
+      public SampleDispatcher getDispatcher() {
 	return dispatcher;
       }
 
diff --git a/lib/csharp/se/lth/control/labcomm2014/RenamingDecoder.cs b/lib/csharp/se/lth/control/labcomm2014/RenamingDecoder.cs
index 0ed4ac6..8f46199 100644
--- a/lib/csharp/se/lth/control/labcomm2014/RenamingDecoder.cs
+++ b/lib/csharp/se/lth/control/labcomm2014/RenamingDecoder.cs
@@ -4,7 +4,6 @@ namespace se.lth.control.labcomm2014 {
 
   public class RenamingDecoder : WrappingDecoder {
 
-    private Decoder decoder;
     private RenamingRegistry registry;
     private Func<String,String> rename;
     
@@ -12,20 +11,22 @@ namespace se.lth.control.labcomm2014 {
                            RenamingRegistry registry,
                            Func<String,String> rename)
     : base(decoder) {
-      this.decoder = decoder;
       this.registry = registry;
       this.rename = rename;
     }
 
     public override void register(SampleDispatcher dispatcher, 
 			 SampleHandler handler) {
-      decoder.register(registry.add(
-        dispatcher, rename(dispatcher.getName())), handler);
+      base.register(registry.add(
+                      dispatcher,
+                      rename(dispatcher.getName())),
+                    handler);
     }
 
     public override void registerSampleRef(SampleDispatcher dispatcher) {
-      decoder.registerSampleRef(registry.add(
-        dispatcher, rename(dispatcher.getName())));
+      base.registerSampleRef(registry.add(
+                               dispatcher,
+                               rename(dispatcher.getName())));
     }
 
 
diff --git a/lib/csharp/se/lth/control/labcomm2014/RenamingEncoder.cs b/lib/csharp/se/lth/control/labcomm2014/RenamingEncoder.cs
index cfafe48..6872445 100644
--- a/lib/csharp/se/lth/control/labcomm2014/RenamingEncoder.cs
+++ b/lib/csharp/se/lth/control/labcomm2014/RenamingEncoder.cs
@@ -5,7 +5,6 @@ namespace se.lth.control.labcomm2014 {
 
   public class RenamingEncoder : WrappingEncoder {
 
-    private Encoder encoder;
     private RenamingRegistry registry;
     private Func<String,String> rename;
     private Dictionary<SampleDispatcher, SampleDispatcher> alias;
@@ -14,7 +13,6 @@ namespace se.lth.control.labcomm2014 {
                            RenamingRegistry registry,
                            Func<String,String> rename)
     : base(encoder) {
-      this.encoder = encoder;
       this.registry = registry;
       this.rename = rename;
       alias = new Dictionary<SampleDispatcher, SampleDispatcher>();
@@ -28,7 +26,6 @@ namespace se.lth.control.labcomm2014 {
           alias.Add(identity, renamed);
         }
       }
-      get(identity);
       return renamed;
     }
 
@@ -40,11 +37,11 @@ namespace se.lth.control.labcomm2014 {
       return renamed;
     }
     public override void register(SampleDispatcher identity) {
-      encoder.register(add(identity));
+      base.register(add(identity));
     }
 
     public override void registerSampleRef(SampleDispatcher identity) {
-      encoder.registerSampleRef(add(identity));
+      base.registerSampleRef(add(identity));
     }
 
     public override void begin(SampleDispatcher identity) {
diff --git a/lib/java/Makefile b/lib/java/Makefile
index a593965..220aeb7 100644
--- a/lib/java/Makefile
+++ b/lib/java/Makefile
@@ -6,10 +6,15 @@ MODULES=Constant \
 	EncoderChannel \
 	EncoderRegistry \
 	Reader \
+	RenamingDecoder \
+	RenamingEncoder \
+	RenamingRegistry \
 	Sample \
 	SampleDispatcher \
 	SampleHandler \
 	SampleType \
+	WrappingDecoder \
+	WrappingEncoder \
 	Writer \
 	WriterWrapper
 
diff --git a/lib/java/se/lth/control/labcomm2014/Decoder.java b/lib/java/se/lth/control/labcomm2014/Decoder.java
index cb83979..9866ec8 100644
--- a/lib/java/se/lth/control/labcomm2014/Decoder.java
+++ b/lib/java/se/lth/control/labcomm2014/Decoder.java
@@ -19,6 +19,6 @@ public interface Decoder {
   public double decodeDouble() throws IOException;
   public String decodeString() throws IOException;
   public int decodePacked32() throws IOException;
-  public Class decodeSampleRef() throws IOException;
+  public SampleDispatcher decodeSampleRef() throws IOException;
 
 }
diff --git a/lib/java/se/lth/control/labcomm2014/DecoderChannel.java b/lib/java/se/lth/control/labcomm2014/DecoderChannel.java
index 25d04f2..1a819a2 100644
--- a/lib/java/se/lth/control/labcomm2014/DecoderChannel.java
+++ b/lib/java/se/lth/control/labcomm2014/DecoderChannel.java
@@ -16,42 +16,6 @@ public class DecoderChannel implements Decoder {
     this.in = new DataInputStream(in);
   }
 
-  private void processSampleDef() throws IOException {
-    int index = decodePacked32();
-    String name = decodeString();
-    int signature_length = decodePacked32();
-    byte[] signature = new byte[signature_length];
-    ReadBytes(signature, signature_length);
-    def_registry.add(index, name, signature);
-  }	   
-
-  private void processSampleRef() throws IOException {
-    int index = decodePacked32();
-    String name = decodeString();
-    int signature_length = decodePacked32();
-    byte[] signature = new byte[signature_length];
-    ReadBytes(signature, signature_length);
-    ref_registry.add(index, name, signature);
-  }	   
-
-  private void processSample(int tag) throws Exception {
-    DecoderRegistry.Entry e = def_registry.get(tag);
-    if (e == null) {
-      throw new IOException("Unhandled tag " + tag);
-    }
-    SampleDispatcher d = e.getDispatcher();
-    if (d == null) {
-      throw new IOException("No dispatcher for '" + e.getName() + "'");
-    }
-    SampleHandler h = e.getHandler();
-    if (h == null) {
-      throw new IOException("No handler for '" + e.getName() +"'");
-    }
-    // decodeAndHandle throws Exception and not IOException because
-    // the user provided handler might throw anything
-    d.decodeAndHandle(this, h);
-  }	  
-
   public void runOne() throws Exception {
     boolean done = false;
     while (!done) {
@@ -66,15 +30,38 @@ public class DecoderChannel implements Decoder {
           }
         } break;
         case Constant.SAMPLE_DEF: {
-            processSampleDef();
+          int index = decodePacked32();
+          String name = decodeString();
+          int signature_length = decodePacked32();
+          byte[] signature = new byte[signature_length];
+          ReadBytes(signature, signature_length);
+          def_registry.add(index, name, signature);
         } break;
         case Constant.SAMPLE_REF: {
-            processSampleRef();
+          int index = decodePacked32();
+          String name = decodeString();
+          int signature_length = decodePacked32();
+          byte[] signature = new byte[signature_length];
+          ReadBytes(signature, signature_length);
+          ref_registry.add(index, name, signature);
         } break;
         default: {
-            processSample(tag);
-            done = true;
-
+          DecoderRegistry.Entry e = def_registry.get(tag);
+          if (e == null) {
+            throw new IOException("Unhandled tag " + tag);
+          }
+          SampleDispatcher d = e.getDispatcher();
+          if (d == null) {
+            throw new IOException("No dispatcher for '" + e.getName() + "'");
+          }
+          SampleHandler h = e.getHandler();
+          if (h == null) {
+            throw new IOException("No handler for '" + e.getName() +"'");
+          }
+          // decodeAndHandle throws Exception and not IOException because
+          // the user provided handler might throw anything
+          d.decodeAndHandle(this, h);
+          done = true;
         }
       }
     }
@@ -162,27 +149,17 @@ public class DecoderChannel implements Decoder {
     return (int) (res & 0xffffffff);
   }
 
-  public Class decodeSampleRef() throws IOException {
+  public SampleDispatcher decodeSampleRef() throws IOException {
     int index = in.readInt();
     try {
       DecoderRegistry.Entry e = ref_registry.get(index);
-      return e.getDispatcher().getSampleClass();
+      return e.getDispatcher();
     } catch (NullPointerException e) {
+      // Handles both the case where index == 0 and unregistered sample
       return null;
     }
 
   }
     
-  /* Package visible methods for use from TypeDefParser */
-
-  String getSampleName(int idx) {
-    DecoderRegistry.Entry e = def_registry.get(idx); 
-    return e.getName();  
-  }
-
-  byte[] getSampleSignature(int idx) {
-    DecoderRegistry.Entry e = def_registry.get(idx); 
-    return e.getSignature();  
-  }
 }
 
diff --git a/lib/java/se/lth/control/labcomm2014/Encoder.java b/lib/java/se/lth/control/labcomm2014/Encoder.java
index ff7951e..069dc07 100644
--- a/lib/java/se/lth/control/labcomm2014/Encoder.java
+++ b/lib/java/se/lth/control/labcomm2014/Encoder.java
@@ -17,7 +17,7 @@ public interface Encoder {
   public void encodeFloat(float value) throws IOException;
   public void encodeDouble(double value) throws IOException;
   public void encodeString(String value) throws IOException;
-  public void encodePacked32(long value) throws IOException;
-  public void encodeSampleRef(Class value) throws IOException;
+  public void encodePacked32(int value) throws IOException;
+  public void encodeSampleRef(SampleDispatcher value) throws IOException;
 
 }
diff --git a/lib/java/se/lth/control/labcomm2014/EncoderChannel.java b/lib/java/se/lth/control/labcomm2014/EncoderChannel.java
index b12840c..97d7f48 100644
--- a/lib/java/se/lth/control/labcomm2014/EncoderChannel.java
+++ b/lib/java/se/lth/control/labcomm2014/EncoderChannel.java
@@ -40,7 +40,6 @@ public class EncoderChannel implements Encoder {
   }
 
   public void registerSampleRef(SampleDispatcher dispatcher) throws IOException {
-    System.err.println(dispatcher);
     int index = ref_registry.add(dispatcher);
     begin(Constant.SAMPLE_REF);
     encodePacked32(index);
@@ -129,7 +128,7 @@ public class EncoderChannel implements Encoder {
     }
   }
 
-  public void encodePacked32(long value) throws IOException {
+  public void encodePacked32(int value) throws IOException {
     byte[] tmp = new byte[5];
     long v = value & 0xffffffff;
     int i;
@@ -142,12 +141,12 @@ public class EncoderChannel implements Encoder {
     }
   }
 
-  public void encodeSampleRef(Class value) throws IOException {
+  public void encodeSampleRef(SampleDispatcher value) throws IOException {
     int index = 0;
     try {
       index = ref_registry.getTag(value);
     } catch (NullPointerException e) {
-        //we want to return 0 for unregistered ref types
+        // encode 0 for unregistered ref types
     }
     data.writeInt(index);
   }
diff --git a/lib/java/se/lth/control/labcomm2014/EncoderRegistry.java b/lib/java/se/lth/control/labcomm2014/EncoderRegistry.java
index 804ffac..1cc9559 100644
--- a/lib/java/se/lth/control/labcomm2014/EncoderRegistry.java
+++ b/lib/java/se/lth/control/labcomm2014/EncoderRegistry.java
@@ -26,38 +26,30 @@ public class EncoderRegistry {
   }
 
   private int userIndex = Constant.FIRST_USER_INDEX;
-  private HashMap<Class, Entry> byClass;
+  private HashMap<SampleDispatcher, Entry> byDispatcher;
 
   public EncoderRegistry() {
-    byClass = new HashMap<Class, Entry>();
+    byDispatcher = new HashMap<SampleDispatcher, Entry>();
   }
 
   public synchronized int add(SampleDispatcher dispatcher) {
-    Entry e = byClass.get(dispatcher.getSampleClass());
+    Entry e = byDispatcher.get(dispatcher);
     if (e == null) {
       e = new Entry(dispatcher, userIndex);
-      byClass.put(dispatcher.getSampleClass(), e);
+      byDispatcher.put(dispatcher, e);
       userIndex++;
     }
     return e.getIndex();
   }
   
-  public int getTag(SampleDispatcher d) throws IOException {
-      return getTag(d.getSampleClass());
-  }
-
-  public int getTag(Class<? extends SampleType> sample) throws IOException {
-    Entry e = byClass.get(sample);
+  public synchronized int getTag(SampleDispatcher sample) throws IOException {
+    Entry e = byDispatcher.get(sample);
     if (e == null) {
       throw new IOException("'" + 
-			    sample.getSimpleName() + 
+			    sample.getName() + 
 			    "' is not registered");
     }
-    return e.index;
-  }
-
-  public boolean contains(Class<? extends SampleType> sample) {
-    return byClass.containsKey(sample);
+    return e.getIndex();
   }
 
 }
diff --git a/lib/java/se/lth/control/labcomm2014/RenamingDecoder.java b/lib/java/se/lth/control/labcomm2014/RenamingDecoder.java
new file mode 100644
index 0000000..a586cb1
--- /dev/null
+++ b/lib/java/se/lth/control/labcomm2014/RenamingDecoder.java
@@ -0,0 +1,37 @@
+package se.lth.control.labcomm2014;
+
+import java.io.IOException;
+import java.util.HashMap;
+
+public class RenamingDecoder extends WrappingDecoder {
+
+  public interface Rename {
+    String rename(String name);   
+  }
+
+  private RenamingRegistry registry;
+  private Rename rename;
+    
+  public RenamingDecoder(Decoder decoder,
+                         RenamingRegistry registry,
+                         Rename rename) throws IOException {
+    super(decoder);
+    this.registry = registry;
+    this.rename = rename;
+  }
+
+  public void register(SampleDispatcher dispatcher, 
+                       SampleHandler handler) throws IOException {
+    super.register(registry.add(
+                     dispatcher,
+                     rename.rename(dispatcher.getName())),
+                   handler);
+  }
+
+  public void registerSampleRef(SampleDispatcher dispatcher) throws IOException {
+    super.registerSampleRef(registry.add(
+                              dispatcher,
+                              rename.rename(dispatcher.getName())));
+  }
+
+} 
diff --git a/lib/java/se/lth/control/labcomm2014/RenamingEncoder.java b/lib/java/se/lth/control/labcomm2014/RenamingEncoder.java
new file mode 100644
index 0000000..834d2e0
--- /dev/null
+++ b/lib/java/se/lth/control/labcomm2014/RenamingEncoder.java
@@ -0,0 +1,54 @@
+package se.lth.control.labcomm2014;
+
+import java.io.IOException;
+import java.util.HashMap;
+
+public class RenamingEncoder extends WrappingEncoder {
+
+  public interface Rename {
+    String rename(String name);   
+  }
+
+  private RenamingRegistry registry;
+  private Rename rename;
+  private HashMap<SampleDispatcher, SampleDispatcher> alias;
+
+  public RenamingEncoder(Encoder encoder,
+                         RenamingRegistry registry,
+                         Rename rename) throws IOException {
+    super(encoder);
+    this.registry = registry;
+    this.rename = rename;
+    alias = new HashMap<SampleDispatcher, SampleDispatcher>();
+  }
+
+  private synchronized SampleDispatcher add(SampleDispatcher identity) {
+    SampleDispatcher renamed = alias.get(identity);
+    if (renamed == null) {
+      renamed = registry.add(identity, rename.rename(identity.getName()));
+      alias.put(identity, renamed);
+    }
+    return renamed;
+  }
+
+  private synchronized SampleDispatcher get(SampleDispatcher identity) {
+    return alias.get(identity);
+  }
+
+  public void register(SampleDispatcher identity) throws IOException {
+    super.register(add(identity));
+  }
+  
+  public void registerSampleRef(SampleDispatcher identity) throws IOException {
+    super.registerSampleRef(add(identity));
+  }
+  
+  public void begin(SampleDispatcher identity) throws IOException {
+    super.begin(get(identity));
+  }
+  
+  public void end(SampleDispatcher identity) throws IOException {
+    super.end(get(identity));
+  }
+
+} 
diff --git a/lib/java/se/lth/control/labcomm2014/RenamingRegistry.java b/lib/java/se/lth/control/labcomm2014/RenamingRegistry.java
new file mode 100644
index 0000000..761a110
--- /dev/null
+++ b/lib/java/se/lth/control/labcomm2014/RenamingRegistry.java
@@ -0,0 +1,64 @@
+package se.lth.control.labcomm2014;
+
+import java.util.HashMap;
+
+public class RenamingRegistry {
+
+  public static class Dispatcher implements SampleDispatcher {
+    
+    private final SampleDispatcher dispatcher;
+    private final String name;
+    
+    public Dispatcher(SampleDispatcher dispatcher,
+                      String name) {
+      this.dispatcher = dispatcher;
+      this.name = name;
+    }
+    
+    public String getName() {
+      return name;
+    }
+    
+    public byte[] getSignature() {
+      return dispatcher.getSignature();
+    }
+    
+    public void decodeAndHandle(Decoder decoder,
+                                SampleHandler handler) throws Exception {
+      dispatcher.decodeAndHandle(decoder, handler);
+    }
+    
+    public boolean equals(Object obj) {
+      if (! (obj instanceof Dispatcher)) {
+        return false;
+      } else {
+        Dispatcher other = (Dispatcher)obj;
+        return (dispatcher == other.dispatcher &&
+                name.equals(other.name));
+      }
+    }
+    
+    public int hashCode() {
+      return dispatcher.hashCode() ^ name.hashCode();
+    }
+    
+  }
+
+  private HashMap<Dispatcher, Dispatcher> registry;
+
+  public RenamingRegistry() {
+    registry = new HashMap<Dispatcher, Dispatcher>();
+  }
+  
+  public synchronized SampleDispatcher add(SampleDispatcher dispatcher,
+                                           String newName) {
+    Dispatcher tmp = new Dispatcher(dispatcher, newName);
+    Dispatcher result = registry.get(tmp);
+    if (result == null) {
+      registry.put(tmp, tmp);
+      result = tmp;
+    }
+    return result;
+  }
+
+}
diff --git a/lib/java/se/lth/control/labcomm2014/SampleDispatcher.java b/lib/java/se/lth/control/labcomm2014/SampleDispatcher.java
index 7a07981..5af5a64 100644
--- a/lib/java/se/lth/control/labcomm2014/SampleDispatcher.java
+++ b/lib/java/se/lth/control/labcomm2014/SampleDispatcher.java
@@ -4,8 +4,6 @@ import java.io.IOException;
 
 public interface SampleDispatcher <T extends SampleType>{
     
-  public Class<T> getSampleClass();
-    
   public String getName();
 
   public byte[] getSignature();
@@ -13,13 +11,5 @@ public interface SampleDispatcher <T extends SampleType>{
   public void decodeAndHandle(Decoder decoder,
 			      SampleHandler handler) throws Exception;
 
-  public void encodeTypeDef(Encoder e, int index) throws IOException;
-
-  /** return the tag SAMPLE_DEF or TYPE_DEF, for use
-   *  by encoder.register.
-   *  TODO: refactor types, moving this to a super-interface
-   *  applicable to both type and sample defs.
-   */ 
-  public byte getTypeDeclTag();
 }
 
diff --git a/lib/java/se/lth/control/labcomm2014/WrappingDecoder.java b/lib/java/se/lth/control/labcomm2014/WrappingDecoder.java
new file mode 100644
index 0000000..f82168a
--- /dev/null
+++ b/lib/java/se/lth/control/labcomm2014/WrappingDecoder.java
@@ -0,0 +1,70 @@
+package se.lth.control.labcomm2014;
+
+import java.io.IOException;
+
+public class WrappingDecoder implements Decoder {
+
+  private Decoder decoder;
+
+  public WrappingDecoder(Decoder decoder) {
+    this.decoder = decoder;
+  }
+
+  public void runOne() throws Exception {
+    decoder.runOne();
+  }
+  
+  public void run() throws Exception {
+    decoder.run();
+  }    
+  
+  public void register(SampleDispatcher dispatcher, 
+                       SampleHandler handler) throws IOException{
+    decoder.register(dispatcher, handler);
+  }
+  
+  public void registerSampleRef(SampleDispatcher dispatcher) throws IOException {
+    decoder.registerSampleRef(dispatcher);
+  }
+  
+  public boolean decodeBoolean() throws IOException {
+    return decoder.decodeBoolean();
+  }
+  
+  public byte decodeByte() throws IOException {
+    return decoder.decodeByte();
+  }
+  
+  public short decodeShort() throws IOException {
+    return decoder.decodeShort();
+  }
+  
+  public int decodeInt() throws IOException {
+    return decoder.decodeInt();
+  }
+  
+  public long decodeLong() throws IOException {
+    return decoder.decodeLong();
+  }
+  
+  public float decodeFloat() throws IOException {
+    return decoder.decodeFloat();
+  }
+  
+  public double decodeDouble() throws IOException {
+    return decoder.decodeDouble();
+  }
+  
+  public String decodeString() throws IOException {
+    return decoder.decodeString();
+  }
+  
+  public int decodePacked32() throws IOException {
+    return decoder.decodePacked32();
+  }
+  
+  public SampleDispatcher decodeSampleRef() throws IOException {
+    return decoder.decodeSampleRef();
+  }
+  
+}
diff --git a/lib/java/se/lth/control/labcomm2014/WrappingEncoder.java b/lib/java/se/lth/control/labcomm2014/WrappingEncoder.java
new file mode 100644
index 0000000..ae98c73
--- /dev/null
+++ b/lib/java/se/lth/control/labcomm2014/WrappingEncoder.java
@@ -0,0 +1,69 @@
+package se.lth.control.labcomm2014;
+
+import java.io.IOException;
+
+public class WrappingEncoder implements Encoder {
+
+  private Encoder encoder;
+  
+  public WrappingEncoder(Encoder encoder) throws IOException {
+    this.encoder = encoder;
+  }
+
+  public void register(SampleDispatcher dispatcher) throws IOException {
+    encoder.register(dispatcher);
+  }
+  
+  public void registerSampleRef(SampleDispatcher dispatcher) throws IOException {
+    encoder.registerSampleRef(dispatcher);
+  }
+  
+  public void begin(SampleDispatcher dispatcher) throws IOException {
+    encoder.begin(dispatcher);
+  }
+  
+  public void end(SampleDispatcher dispatcher) throws IOException {
+    encoder.end(dispatcher);
+  }
+  
+  public void encodeBoolean(boolean value) throws IOException {
+    encoder.encodeBoolean(value);
+  }
+  
+  public void encodeByte(byte value) throws IOException {
+    encoder.encodeByte(value);
+  }
+  
+  public void encodeShort(short value) throws IOException {
+    encoder.encodeShort(value);
+  }
+  
+  public void encodeInt(int value) throws IOException {
+    encoder.encodeInt(value);
+  }
+  
+  public void encodeLong(long value) throws IOException {
+    encoder.encodeLong(value);
+  }
+  
+  public void encodeFloat(float value) throws IOException {
+    encoder.encodeFloat(value);
+  }
+  
+  public void encodeDouble(double value) throws IOException {
+    encoder.encodeDouble(value);
+  }
+  
+  public void encodeString(String value) throws IOException {
+    encoder.encodeString(value);
+  }
+  
+  public void encodePacked32(int value) throws IOException {
+    encoder.encodePacked32(value);
+  }
+  
+  public void encodeSampleRef(SampleDispatcher value) throws IOException {
+    encoder.encodeSampleRef(value);
+  }
+  
+}
diff --git a/test/Makefile b/test/Makefile
index 055df04..3694ac5 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -36,7 +36,7 @@ test_%: gen/%/signatures.py \
 test_renaming_%: gen/%/signatures.py \
 		gen/%/c_renaming_relay \
 		gen/%/cs_renaming_relay.exe \
-		gen/%/java_relay.class \
+		gen/%/java_renaming_relay.class \
 		gen/%/java_code
 	PYTHONPATH=$(PYTHONPATH) MONO_PATH=$(MONO_PATH) \
 	    ./test_renaming_encoder_decoder.py \
@@ -45,10 +45,9 @@ test_renaming_%: gen/%/signatures.py \
 		--test $(shell echo $(VALGRIND) | sed -e 's/[-][-]/\\\\--/g') \
 		       gen/$*/c_renaming_relay /dev/stdin /dev/stdout \
 		--test mono gen/$*/cs_renaming_relay.exe \
-		       /dev/stdin /dev/stdout
-	echo \
+		       /dev/stdin /dev/stdout \
 		--test java \\-cp gen/$*:../lib/java/labcomm2014.jar \
-		       java_relay /dev/stdin /dev/stdout
+		       java_renaming_relay /dev/stdin /dev/stdout
 
 # test cases for compiler error checking
 .PHONY: compiler_errors testErrorsOK testErrorsNOK
@@ -133,4 +132,13 @@ gen/%/java_relay.java: gen/%/typeinfo relay_gen_java.py Makefile
 
 .PRECIOUS: gen/%/java_relay.class
 gen/%/java_relay.class: gen/%/java_relay.java gen/%/java_code Makefile
-	javac -d gen/$*  -cp ../lib/java/labcomm2014.jar:gen/$*/java_code $<
+	javac -d gen/$* -cp ../lib/java/labcomm2014.jar:gen/$*/java_code $<
+
+.PRECIOUS: gen/%/java_renaming_relay.java
+gen/%/java_renaming_relay.java: gen/%/typeinfo relay_gen_java.py Makefile
+	./relay_gen_java.py --renaming $< > $@
+
+.PRECIOUS: gen/%/java_renaming_relay.class
+gen/%/java_renaming_relay.class: gen/%/java_renaming_relay.java \
+                                 gen/%/java_code Makefile
+	javac -d gen/$* -cp ../lib/java/labcomm2014.jar:gen/$*/java_code $<
diff --git a/test/relay_gen_cs.py b/test/relay_gen_cs.py
index b2bfffe..bdf782e 100755
--- a/test/relay_gen_cs.py
+++ b/test/relay_gen_cs.py
@@ -19,7 +19,7 @@ def shuffle(l):
     return result
 
 if __name__ == '__main__':
-    parser = argparse.ArgumentParser(description='Generate C test relay.')
+    parser = argparse.ArgumentParser(description='Generate C# test relay.')
     parser.add_argument('--renaming', action='store_true')
     parser.add_argument('typeinfo', help='typeinfo file')
 
@@ -86,8 +86,6 @@ if __name__ == '__main__':
         |    encoder = new RenamingEncoder(
         |        encoder, registry, s => "prefix:" + s + ":suffix");
         """))
-
-
     for func,arg in shuffle(sample):
         result.append('    %s.register(decoder, this);' % func)
         pass
diff --git a/test/relay_gen_java.py b/test/relay_gen_java.py
index c522367..314b667 100755
--- a/test/relay_gen_java.py
+++ b/test/relay_gen_java.py
@@ -1,5 +1,6 @@
 #!/usr/bin/python
 
+import argparse
 import re
 import sys
 import random
@@ -18,7 +19,17 @@ def shuffle(l):
     return result
 
 if __name__ == '__main__':
-    f = open(sys.argv[1])
+    parser = argparse.ArgumentParser(description='Generate Java test relay.')
+    parser.add_argument('--renaming', action='store_true')
+    parser.add_argument('typeinfo', help='typeinfo file')
+
+    options = parser.parse_args(sys.argv[1:])
+    if options.renaming:
+        relay_name = 'java_renaming_relay'
+    else:
+        relay_name = 'java_relay'
+
+    f = open(options.typeinfo)
     sample = []
     for l in map(lambda s: s.strip(), f):
         lang,kind,func,arg,dummy = l[1:].split(l[0])
@@ -31,19 +42,20 @@ if __name__ == '__main__':
       |import java.io.FileInputStream;
       |import java.io.FileOutputStream;
       |import java.io.IOException;
-      |import se.lth.control.labcomm2014.DecoderChannel;
-      |import se.lth.control.labcomm2014.EncoderChannel;
-      |import se.lth.control.labcomm2014.Sample;
+      |import se.lth.control.labcomm2014.*;
       |
-      |public class java_relay implements
     """))
+    result.extend(split_match('^[^|]*\|(.*)$', """
+    |public class %(relay_name)s implements
+    """ % dict(relay_name = relay_name)))
     for func,arg in sample[0:-1]:
         result.append('  %s.Handler,' % func)
         pass
     result.append('  %s.Handler' % sample[-1][0])
     result.extend(split_match('^[^|]*\|(.*)$', """
       |{
-      |  EncoderChannel encoder;
+      |  Encoder encoder;
+      |  Decoder decoder;
     """))
     for func,arg in sample:
         if arg == 'void':
@@ -62,13 +74,21 @@ if __name__ == '__main__':
             pass
         pass
     result.extend(split_match('^[^|]*\|(.*)$', """
-      |  public java_relay(String InName, String OutName) throws Exception {
+      |  public %(relay_name)s(String InName, String OutName) throws Exception {
       |    FileInputStream InFile = new FileInputStream(InName);
-      |    DecoderChannel decoder = new DecoderChannel(InFile);
+      |    decoder = new DecoderChannel(InFile);
       |    FileOutputStream OutFile = new FileOutputStream(OutName);
       |    encoder = new EncoderChannel(OutFile);
       |
-    """))
+    """ % dict(relay_name=relay_name)))
+    if options.renaming:
+        result.extend(split_match('^[^|]*\|(.*)$', """
+        |    RenamingRegistry registry = new RenamingRegistry();
+        |    decoder = new RenamingDecoder(
+        |        decoder, registry, s -> "prefix:" + s + ":suffix");
+        |    encoder = new RenamingEncoder(
+        |        encoder, registry, s -> "prefix:" + s + ":suffix");
+        """))
     for func,arg in shuffle(sample):
         result.append('    %s.register(decoder, this);' % func)
         pass
@@ -88,9 +108,9 @@ if __name__ == '__main__':
       |    }
       |  }
       |  public static void main(String[] arg) throws Exception {
-      |    new java_relay(arg[0], arg[1]);
+      |    new %(relay_name)s(arg[0], arg[1]);
       |  }
       |}
-    """))
+    """ % dict(relay_name=relay_name)))
     print "\n".join(result)
     pass
-- 
GitLab