activemq-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From chir...@apache.org
Subject svn commit: r703019 - in /activemq/sandbox/activemq-protobuf: activemq-protobuf-test/src/main/proto/ activemq-protobuf-test/src/test/java/org/ activemq-protobuf-test/src/test/java/org/apache/ activemq-protobuf-test/src/test/java/org/apache/activemq/ ac...
Date Wed, 08 Oct 2008 23:32:16 GMT
Author: chirino
Date: Wed Oct  8 16:32:15 2008
New Revision: 703019

URL: http://svn.apache.org/viewvc?rev=703019&view=rev
Log:
Added an option to support deferred decoding of messages. 
messages now implement equals() and hashCode()


Added:
    activemq/sandbox/activemq-protobuf/activemq-protobuf-test/src/main/proto/deferred_decode.proto
    activemq/sandbox/activemq-protobuf/activemq-protobuf-test/src/test/java/org/
    activemq/sandbox/activemq-protobuf/activemq-protobuf-test/src/test/java/org/apache/
    activemq/sandbox/activemq-protobuf/activemq-protobuf-test/src/test/java/org/apache/activemq/
    activemq/sandbox/activemq-protobuf/activemq-protobuf-test/src/test/java/org/apache/activemq/protobuf/
    activemq/sandbox/activemq-protobuf/activemq-protobuf-test/src/test/java/org/apache/activemq/protobuf/DeferredUnmarshalTest.java
    activemq/sandbox/activemq-protobuf/activemq-protobuf-test/src/test/java/org/apache/activemq/protobuf/EqualsTest.java
    activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/DeferredDecodeMessage.java
Modified:
    activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/BaseMessage.java
    activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/JavaGenerator.java

Added: activemq/sandbox/activemq-protobuf/activemq-protobuf-test/src/main/proto/deferred_decode.proto
URL: http://svn.apache.org/viewvc/activemq/sandbox/activemq-protobuf/activemq-protobuf-test/src/main/proto/deferred_decode.proto?rev=703019&view=auto
==============================================================================
--- activemq/sandbox/activemq-protobuf/activemq-protobuf-test/src/main/proto/deferred_decode.proto
(added)
+++ activemq/sandbox/activemq-protobuf/activemq-protobuf-test/src/main/proto/deferred_decode.proto
Wed Oct  8 16:32:15 2008
@@ -0,0 +1,38 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You 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 org.apache.activemq.protobuf;
+option java_outer_classname = "DeferredUnmarshal";
+option deferred_decode = true;
+
+message Foo {
+ 
+  optional int32 field1 =  1;
+  optional int64 field2 =  2;
+ 
+}
+
+
+message Bar {
+ 
+  optional int32 field1 =  1;
+  optional int64 field2 =  2;
+ 
+  optional Foo field3 =  3;
+
+}
+

Added: activemq/sandbox/activemq-protobuf/activemq-protobuf-test/src/test/java/org/apache/activemq/protobuf/DeferredUnmarshalTest.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/activemq-protobuf/activemq-protobuf-test/src/test/java/org/apache/activemq/protobuf/DeferredUnmarshalTest.java?rev=703019&view=auto
==============================================================================
--- activemq/sandbox/activemq-protobuf/activemq-protobuf-test/src/test/java/org/apache/activemq/protobuf/DeferredUnmarshalTest.java
(added)
+++ activemq/sandbox/activemq-protobuf/activemq-protobuf-test/src/test/java/org/apache/activemq/protobuf/DeferredUnmarshalTest.java
Wed Oct  8 16:32:15 2008
@@ -0,0 +1,75 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.activemq.protobuf;
+
+import org.apache.activemq.protobuf.DeferredUnmarshal.Foo;
+import org.apache.activemq.protobuf.DeferredUnmarshal.Bar;
+
+import com.google.protobuf.InvalidProtocolBufferException;
+
+import junit.framework.TestCase;
+
+public class DeferredUnmarshalTest extends TestCase {
+	
+	public void testDeferredDecoding() throws InvalidProtocolBufferException {
+		
+		Foo foo = new Foo();
+		foo.setField1(5);
+		foo.setField2(20);
+		
+		Bar bar = new Bar();
+		
+		// There is no decoding pending so its' considered decoded.
+		assertTrue(bar.isDecoded());
+		
+		bar.setField1(25);
+		bar.setField2(220);
+		bar.setField3(foo);
+		
+		// The message should not be encoded yet.
+		assertFalse(bar.isEncoded());
+
+		// The message should be encoded now..
+		byte[] encodedForm = bar.toUnframedByteArray();
+		assertTrue(bar.isEncoded());
+
+		// Repeated encoding operations should just give back the same byte[]
+		assertTrue(encodedForm == bar.toUnframedByteArray());
+
+		// Decoding does not occur until a field is accessed.  The new message should still be
considered encoded.
+		Bar bar2 = Bar.parseUnframed(encodedForm);
+		assertTrue(bar2.isEncoded());
+		assertFalse(bar2.isDecoded());
+		
+		// This should now decode the message.
+		assertEquals(25, bar2.getField1());
+		assertTrue(bar2.isDecoded());
+		
+		// Since bar2 still has not been modified it should still spit out the same byte[]
+		assertTrue(encodedForm == bar2.toUnframedByteArray());
+				
+		// Nested messages should remain un-decoded.
+		assertFalse( bar2.getField3().isDecoded() );
+		
+		// Changing a field should remove the encoding.
+		bar2.setField1(35);
+		assertFalse(bar2.isEncoded());
+		assertTrue(bar2.isDecoded());
+		
+	}
+
+}

Added: activemq/sandbox/activemq-protobuf/activemq-protobuf-test/src/test/java/org/apache/activemq/protobuf/EqualsTest.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/activemq-protobuf/activemq-protobuf-test/src/test/java/org/apache/activemq/protobuf/EqualsTest.java?rev=703019&view=auto
==============================================================================
--- activemq/sandbox/activemq-protobuf/activemq-protobuf-test/src/test/java/org/apache/activemq/protobuf/EqualsTest.java
(added)
+++ activemq/sandbox/activemq-protobuf/activemq-protobuf-test/src/test/java/org/apache/activemq/protobuf/EqualsTest.java
Wed Oct  8 16:32:15 2008
@@ -0,0 +1,58 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.activemq.protobuf;
+
+import org.apache.activemq.protobuf.DeferredUnmarshal.Bar;
+import org.apache.activemq.protobuf.DeferredUnmarshal.Foo;
+
+import junit.framework.TestCase;
+
+public class EqualsTest extends TestCase {
+	
+	public void testDeferredUnmarshal() {
+		
+		Bar bar1 = createBar();
+		Bar bar2 = createBar();
+
+		// They should have the same hash and equal the same value.
+		assertTrue(bar1.hashCode()==bar2.hashCode());
+		assertTrue(bar1.equals(bar2));
+		
+		// Change bar2 a little.
+		
+		bar2.setField2(35);
+		
+		assertFalse(bar1.hashCode()==bar2.hashCode());
+		assertFalse(bar1.equals(bar2));
+		
+		
+	}
+
+	private Bar createBar() {
+		Bar bar;
+		Foo foo = new Foo();
+		foo.setField1(5);
+		foo.setField2(20);
+		
+		bar = new Bar();
+		bar.setField1(25);
+		bar.setField2(220);
+		bar.setField3(foo);
+		return bar;
+	}
+
+}

Modified: activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/BaseMessage.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/BaseMessage.java?rev=703019&r1=703018&r2=703019&view=diff
==============================================================================
--- activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/BaseMessage.java
(original)
+++ activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/BaseMessage.java
Wed Oct  8 16:32:15 2008
@@ -39,6 +39,10 @@
     
     abstract public T clone() throws CloneNotSupportedException;
 
+	public void clear() {
+		memoizedSerializedSize = -1;
+	}
+
     ///////////////////////////////////////////////////////////////////
     // Write related helpers.
     ///////////////////////////////////////////////////////////////////
@@ -225,6 +229,7 @@
         return rc;
     }
 
+    abstract protected T checktInitialized() throws InvalidProtocolBufferException;
 
     /**
      * Read a raw Varint from the stream.  If larger than 32 bits, discard the
@@ -274,4 +279,8 @@
     	}
     	return (byte) rc;
     }
+
+	protected void loadAndClear() {
+		memoizedSerializedSize=-1;
+	}
 }

Added: activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/DeferredDecodeMessage.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/DeferredDecodeMessage.java?rev=703019&view=auto
==============================================================================
--- activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/DeferredDecodeMessage.java
(added)
+++ activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/DeferredDecodeMessage.java
Wed Oct  8 16:32:15 2008
@@ -0,0 +1,91 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.activemq.protobuf;
+
+import java.io.IOException;
+
+import com.google.protobuf.CodedInputStream;
+import com.google.protobuf.InvalidProtocolBufferException;
+
+abstract public class DeferredDecodeMessage<T> extends BaseMessage<T>{
+
+	protected byte[] encodedForm;
+	protected boolean decoded=true;
+
+	@Override
+    public T mergeFramed(CodedInputStream input) throws IOException {
+        int length = input.readRawVarint32();
+        int oldLimit = input.pushLimit(length);
+        T rc=  mergeUnframed(input.readRawBytes(length));
+        input.popLimit(oldLimit);
+        return rc;
+    }
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public T mergeUnframed(byte[] data) throws InvalidProtocolBufferException {
+		encodedForm = data;
+		decoded=false;
+		return (T)this;
+	}
+
+	@Override
+	public byte[] toUnframedByteArray() {
+		if( encodedForm==null ) {
+			encodedForm = super.toUnframedByteArray();
+		}
+		return encodedForm;
+	}
+
+	protected void load() {
+		if (!decoded) {
+			decoded = true;
+			try {
+				byte[] originalForm = encodedForm;
+				CodedInputStream input = CodedInputStream.newInstance(originalForm);
+				mergeUnframed(input);
+				input.checkLastTagWas(0);
+				// We need to reset the encoded form because the mergeUnframed from a stream clears it
out.
+				encodedForm = originalForm;
+				checktInitialized();
+			} catch (Throwable e) {
+				throw new RuntimeException("Deferred message decoding failed: "+e.getMessage(), e);
+			}
+		}
+	}
+	
+	protected void loadAndClear() {
+		super.loadAndClear();
+		load();
+		encodedForm = null;
+	}
+
+	public void clear() {
+		super.clear();
+		encodedForm = null;
+		decoded = true;
+	}
+
+	public boolean isDecoded() {
+		return decoded;
+	}
+	
+	public boolean isEncoded() {
+		return encodedForm!=null;
+	}
+
+}

Modified: activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/JavaGenerator.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/JavaGenerator.java?rev=703019&r1=703018&r2=703019&view=diff
==============================================================================
--- activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/JavaGenerator.java
(original)
+++ activemq/sandbox/activemq-protobuf/activemq-protobuf/src/main/java/org/apache/activemq/protobuf/compiler/JavaGenerator.java
Wed Oct  8 16:32:15 2008
@@ -29,6 +29,7 @@
 import java.io.FileOutputStream;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
@@ -48,10 +49,9 @@
     private String outerClassName;
     private PrintWriter w;
     private int indent;
-    private String optimizeFor;
     private ArrayList<String> errors = new ArrayList<String>();
     private boolean multipleFiles;
-	private boolean defferedUnmarshall;
+	private boolean deferredDecode;
 
     public static void main(String[] args) {
         
@@ -121,9 +121,9 @@
         // Load the options..
         javaPackage = javaPackage(proto);
         outerClassName = javaClassName(proto);
-        optimizeFor = getOption(proto.getOptions(), "optimize_for", "SPEED");
+//        optimizeFor = getOption(proto.getOptions(), "optimize_for", "SPEED");
         multipleFiles = isMultipleFilesEnabled(proto);
-        defferedUnmarshall = Boolean.getBoolean(getOption(proto.getOptions(), "deferred_unmarshall",
"false"));
+		deferredDecode = Boolean.parseBoolean(getOption(proto.getOptions(), "deferred_decode",
"false"));
         
         if( multipleFiles ) {
             generateProtoFile();
@@ -267,7 +267,13 @@
             implementsExpression = "implements "+javaImplements+" ";
         }
         
-        p("public "+staticOption+"final class " + className + " extends org.apache.activemq.protobuf.BaseMessage<"
+ className + "> "+implementsExpression+"{");
+        String baseClass = "org.apache.activemq.protobuf.BaseMessage";
+        if( deferredDecode ) {
+            baseClass = "org.apache.activemq.protobuf.DeferredDecodeMessage";
+        }
+        
+        
+        p("public "+staticOption+"final class " + className + " extends "+baseClass+"<"
+ className + "> "+implementsExpression+"{");
         p();
 
         indent();
@@ -320,13 +326,15 @@
         generateMethodVisitor(m);
                 
         generateMethodType(m, className);
+        
+        generateMethodEquals(m, className);
                 
         unindent();
         p("}");
         p();
     }
 
-    /**
+	/**
      * If the java_visitor message option is set, then this method generates a visitor method.
 The option 
      * speifiies the class name of the visitor and optionally the return value and exceptions
thrown by the visitor.
      * 
@@ -411,69 +419,184 @@
     }
     
     private void generateMethodParseFrom(MessageDescriptor m, String className) {
+    	
+    	String postMergeProcessing = ".checktInitialized()";
+        if( deferredDecode ) {
+        	postMergeProcessing="";
+        }
+        
         p("public static "+className+" parseUnframed(com.google.protobuf.CodedInputStream
data) throws com.google.protobuf.InvalidProtocolBufferException, java.io.IOException {");
         indent();
-        p("return new "+className+"().mergeUnframed(data).checktInitialized();");
+        p("return new "+className+"().mergeUnframed(data)"+postMergeProcessing+";");
         unindent();
         p("}");
         p();
 
         p("public static "+className+" parseUnframed(com.google.protobuf.ByteString data)
throws com.google.protobuf.InvalidProtocolBufferException {");
         indent();
-        p("return new "+className+"().mergeUnframed(data).checktInitialized();");
+        p("return new "+className+"().mergeUnframed(data)"+postMergeProcessing+";");
         unindent();
         p("}");
         p();
 
         p("public static "+className+" parseUnframed(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException
{");
         indent();
-        p("return new "+className+"().mergeUnframed(data).checktInitialized();");
+        p("return new "+className+"().mergeUnframed(data)"+postMergeProcessing+";");
         unindent();
         p("}");
         p();
         
         p("public static "+className+" parseUnframed(java.io.InputStream data) throws com.google.protobuf.InvalidProtocolBufferException,
java.io.IOException {");
         indent();
-        p("return new "+className+"().mergeUnframed(data).checktInitialized();");
+        p("return new "+className+"().mergeUnframed(data)"+postMergeProcessing+";");
         unindent();
         p("}");
         p();
         
         p("public static "+className+" parseFramed(com.google.protobuf.CodedInputStream data)
throws com.google.protobuf.InvalidProtocolBufferException, java.io.IOException {");
         indent();
-        p("return new "+className+"().mergeFramed(data).checktInitialized();");
+        p("return new "+className+"().mergeFramed(data)"+postMergeProcessing+";");
         unindent();
         p("}");
         p();
         
         p("public static "+className+" parseFramed(com.google.protobuf.ByteString data) throws
com.google.protobuf.InvalidProtocolBufferException {");
         indent();
-        p("return new "+className+"().mergeFramed(data).checktInitialized();");
+        p("return new "+className+"().mergeFramed(data)"+postMergeProcessing+";");
         unindent();
         p("}");
         p();
 
         p("public static "+className+" parseFramed(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException
{");
         indent();
-        p("return new "+className+"().mergeFramed(data).checktInitialized();");
+        p("return new "+className+"().mergeFramed(data)"+postMergeProcessing+";");
         unindent();
         p("}");
         p();
         
         p("public static "+className+" parseFramed(java.io.InputStream data) throws com.google.protobuf.InvalidProtocolBufferException,
java.io.IOException {");
         indent();
-        p("return new "+className+"().mergeFramed(data).checktInitialized();");
+        p("return new "+className+"().mergeFramed(data)"+postMergeProcessing+";");
         unindent();
         p("}");
         p();
     }
 
+    private void generateMethodEquals(MessageDescriptor m, String className) {
+        p("public boolean equals(Object obj) {");
+        indent();
+        p("if( obj==this )");
+        p("   return true;");
+        p("");
+        p("if( obj==null || obj.getClass()!="+className+".class )");
+        p("   return false;");
+        p("");
+        p("return equals(("+className+")obj);");
+        unindent();
+        p("}");
+        p("");
+        
+        p("public boolean equals("+className+" obj) {");
+        indent();
+        if( deferredDecode ) {
+        	p("return java.util.Arrays.equals(toUnframedByteArray(), obj.toUnframedByteArray());");
+        } else {        
+	        for (FieldDescriptor field : m.getFields().values()) {
+	            String uname = uCamel(field.getName());
+	            String getterMethod="get"+uname+"()";     
+	            String hasMethod = "has"+uname+"()";
+	
+	            if( field.getRule() == FieldDescriptor.REPEATED_RULE ) {
+	                getterMethod = "get"+uname+"List()";
+	            }
+	            
+	            p("if ("+hasMethod+" ^ obj."+hasMethod+" ) ");
+	            p("   return false;");
+	            
+	            
+	            
+	            if( field.getRule() != FieldDescriptor.REPEATED_RULE && (field.isNumberType()
|| field.getType()==FieldDescriptor.BOOL_TYPE) ) {
+	                p("if ("+hasMethod+" && ( "+getterMethod+"!=obj."+getterMethod+"
))");
+	            } else {
+	                p("if ("+hasMethod+" && ( !"+getterMethod+".equals(obj."+getterMethod+")
))");
+	            }
+	            p("   return false;");
+	        }
+	        p("return true;");
+        }
+        unindent();
+        p("}");
+        p("");
+        p("public int hashCode() {");
+        indent();
+        if( deferredDecode ) {
+        	int hc = className.hashCode();
+        	p("byte []target = new byte[]{ (byte)"+((hc>>24)&0xFF)+", (byte)"+((hc>>16)&0xFF)+",
(byte)"+((hc>>8)&0xFF)+", (byte)"+(hc&0xFF)+" };");
+        	p("byte []data = toUnframedByteArray();");
+        	p("for(int i=0; i < data.length; i++) {");
+            indent();
+        	p("target[i%4] ^= data[i];");
+            unindent();
+        	p("}");
+        	p("");
+            p("return target[0]<<24 | target[1]<<16 | target[2]<<8 | target[3];");
+        } else {
+            p("int rc="+className.hashCode()+";");
+	        int counter=0;
+	        for (FieldDescriptor field : m.getFields().values()) {
+	        	counter++;
+	        	
+	            String uname = uCamel(field.getName());
+	            String getterMethod="get"+uname+"()";     
+	            String hasMethod = "has"+uname+"()";
+	
+	            if( field.getRule() == FieldDescriptor.REPEATED_RULE ) {
+	                getterMethod = "get"+uname+"List()";
+	            }
+	            
+	            p("if ("+hasMethod+") {");
+	            indent();
+	            
+	            if( field.getRule() == FieldDescriptor.REPEATED_RULE ) {
+	                p("rc ^= ( "+uname.hashCode()+"^"+getterMethod+".hashCode() );");
+	            } else if( field.isInteger32Type() ) {
+	                p("rc ^= ( "+uname.hashCode()+"^"+getterMethod+" );");
+	            } else if( field.isInteger64Type() ) {
+	                p("rc ^= ( "+uname.hashCode()+"^(new Long("+getterMethod+")).hashCode()
);");
+	            } else if( field.getType()==FieldDescriptor.DOUBLE_TYPE ) {
+	                p("rc ^= ( "+uname.hashCode()+"^(new Double("+getterMethod+")).hashCode()
);");
+	            } else if( field.getType()==FieldDescriptor.FLOAT_TYPE ) {
+	                p("rc ^= ( "+uname.hashCode()+"^(new Double("+getterMethod+")).hashCode()
);");
+	            } else if( field.getType()==FieldDescriptor.BOOL_TYPE ) {
+	                p("rc ^= ( "+uname.hashCode()+"^ ("+getterMethod+"? "+counter+":-"+counter+")
);");
+	            } else {
+	                p("rc ^= ( "+uname.hashCode()+"^"+getterMethod+".hashCode() );");
+	            }
+	            
+	            unindent();
+	            p("}");
+	            
+	        }
+	        p("return rc;");
+        }
+        unindent();
+        p("}");
+        p("");
+	}
+    
     /**
      * @param m
      */
     private void generateMethodSerializedSize(MessageDescriptor m) {
         p("public int serializedSizeUnframed() {");
         indent();
+        if( deferredDecode ) {
+			p("if (encodedForm != null) {");
+			indent();
+            p("return encodedForm.length;");
+			unindent();
+			p("}");
+        }
         p("if (memoizedSerializedSize != -1)");
         p("   return memoizedSerializedSize;");
         p();
@@ -553,6 +676,16 @@
     private void generateMethodWriteTo(MessageDescriptor m) {
         p("public void writeUnframed(com.google.protobuf.CodedOutputStream output) throws
java.io.IOException {");
         indent();
+        
+        if( deferredDecode ) {
+			p("if (encodedForm == null) {");
+			indent();
+			p("encodedForm = new byte[serializedSizeUnframed()];");
+			p("com.google.protobuf.CodedOutputStream original = output;");
+			p("output = com.google.protobuf.CodedOutputStream.newInstance(encodedForm);");
+        }
+        
+
         for (FieldDescriptor field : m.getFields().values()) {
             String uname = uCamel(field.getName());
             String getter="get"+uname+"()";            
@@ -613,8 +746,15 @@
             unindent();
             p("}");
         }
-        // TODO: handle unknown fields
-        // getUnknownFields().writeTo(output);
+        
+        if( deferredDecode ) {
+        	p("output.checkNoSpaceLeft();");
+			p("output = original;");
+			unindent();
+			p("}");
+	        p("output.writeRawBytes(encodedForm);");
+        }        
+
         unindent();
         p("}");
         p();        
@@ -626,158 +766,188 @@
      */
     private void generateMethodMergeFromStream(MessageDescriptor m, String className) {
         p("public "+className+" mergeUnframed(com.google.protobuf.CodedInputStream input)
throws java.io.IOException {");
-        indent(); {
-          p("while (true) {");
-          indent(); {
-              p("int tag = input.readTag();");
-              p("if ((tag & 0x07) == 4) {");
-              p("   return this;");
-              p("}");
-              
-              p("switch (tag) {");
-              p("case 0:");
-              p("   return this;");
-              p("default: {");
-
-              p("   break;");
-              p("}");
-              
-              
-              for (FieldDescriptor field : m.getFields().values()) {
-                  String uname = uCamel(field.getName());
-                  String setter = "set"+uname;
-                  boolean repeated = field.getRule() == FieldDescriptor.REPEATED_RULE;
-                  if( repeated ) {
-                      setter = "get"+uname+"List().add";
-                  }
-                  if( field.getType()==FieldDescriptor.STRING_TYPE ) {
-                      p("case "+makeTag(field.getTag(), WIRETYPE_LENGTH_DELIMITED)+":");
-                      indent();
-                      p(setter+"(input.readString());");
-                  } else if( field.getType()==FieldDescriptor.BYTES_TYPE ) {
-                      p("case "+makeTag(field.getTag(), WIRETYPE_LENGTH_DELIMITED)+":");
-                      indent();
-                      p(setter+"(input.readBytes());");
-                  } else if( field.getType()==FieldDescriptor.BOOL_TYPE ) {
-                      p("case "+makeTag(field.getTag(), WIRETYPE_VARINT)+":");
-                      indent();
-                      p(setter+"(input.readBool());");
-                  } else if( field.getType()==FieldDescriptor.DOUBLE_TYPE ) {
-                      p("case "+makeTag(field.getTag(), WIRETYPE_FIXED64)+":");
-                      indent();
-                      p(setter+"(input.readDouble());");
-                  } else if( field.getType()==FieldDescriptor.FLOAT_TYPE ) {
-                      p("case "+makeTag(field.getTag(), WIRETYPE_FIXED32)+":");
-                      indent();
-                      p(setter+"(input.readFloat());");
-                  } else if( field.getType()==FieldDescriptor.INT32_TYPE ) {
-                      p("case "+makeTag(field.getTag(), WIRETYPE_VARINT)+":");
-                      indent();
-                      p(setter+"(input.readInt32());");
-                  } else if( field.getType()==FieldDescriptor.INT64_TYPE ) {
-                      p("case "+makeTag(field.getTag(), WIRETYPE_VARINT)+":");
-                      indent();
-                      p(setter+"(input.readInt64());");
-                  } else if( field.getType()==FieldDescriptor.SINT32_TYPE ) {
-                      p("case "+makeTag(field.getTag(), WIRETYPE_VARINT)+":");
-                      indent();
-                      p(setter+"(input.readSInt32());");
-                  } else if( field.getType()==FieldDescriptor.SINT64_TYPE ) {
-                      p("case "+makeTag(field.getTag(), WIRETYPE_VARINT)+":");
-                      indent();
-                      p(setter+"(input.readSInt64());");
-                  } else if( field.getType()==FieldDescriptor.UINT32_TYPE ) {
-                      p("case "+makeTag(field.getTag(), WIRETYPE_VARINT)+":");
-                      indent();
-                      p(setter+"(input.readUInt32());");
-                  } else if( field.getType()==FieldDescriptor.UINT64_TYPE ) {
-                      p("case "+makeTag(field.getTag(), WIRETYPE_VARINT)+":");
-                      indent();
-                      p(setter+"(input.readUInt64());");
-                  } else if( field.getType()==FieldDescriptor.FIXED32_TYPE ) {
-                      p("case "+makeTag(field.getTag(), WIRETYPE_FIXED32)+":");
-                      indent();
-                      p(setter+"(input.readFixed32());");
-                  } else if( field.getType()==FieldDescriptor.FIXED64_TYPE ) {
-                      p("case "+makeTag(field.getTag(), WIRETYPE_FIXED64)+":");
-                      indent();
-                      p(setter+"(input.readFixed64());");
-                  } else if( field.getType()==FieldDescriptor.SFIXED32_TYPE ) {
-                      p("case "+makeTag(field.getTag(), WIRETYPE_FIXED32)+":");
-                      indent();
-                      p(setter+"(input.readSFixed32());");
-                  } else if( field.getType()==FieldDescriptor.SFIXED64_TYPE ) {
-                      p("case "+makeTag(field.getTag(), WIRETYPE_FIXED64)+":");
-                      indent();
-                      p(setter+"(input.readSFixed64());");
-                  } else if( field.getTypeDescriptor().isEnum() ) {
-                      p("case "+makeTag(field.getTag(), WIRETYPE_VARINT)+":");
-                      indent();
-                      String type = javaType(field);
-                      p("{");
-                      indent();
-                      p("int t = input.readEnum();");
-                      p(""+type+" value = "+type+".valueOf(t);");
-                      p("if( value !=null ) {");
-                      indent();
-                      p(setter+"(value);");
-                      unindent();
-                      p("}");
-                      // TODO: else store it as an known
-                      
-                      unindent();
-                      p("}");
-                      
-                  } else if ( field.getGroup()!=null ) {
-                      p("case "+makeTag(field.getTag(), WIRETYPE_START_GROUP)+":");
-                      indent();
-                      String type = javaType(field);
-                      if( repeated ) {
-                          p(setter+"(readGroup(input, "+field.getTag()+", new "+type+"()));");
-                      } else {
-                          p("if (has"+uname+"()) {");
-                          indent();
-                          p("readGroup(input, "+field.getTag()+", get"+uname+"());");
-                          unindent();
-                          p("} else {");
-                          indent();
-                          p(setter+"(readGroup(input, "+field.getTag()+",new "+type+"()));");
-                          unindent();
-                          p("}");
-                      }
-                      p("");
-                  } else {
-                      p("case "+makeTag(field.getTag(), WIRETYPE_LENGTH_DELIMITED)+":");
-                      indent();
-                      String type = javaType(field);
-                      if( repeated ) {
-                          p(setter+"(new "+type+"().mergeFramed(input));");
-                      } else {
-                          p("if (has"+uname+"()) {");
-                          indent();
-                          p("get"+uname+"().mergeFramed(input);");
-                          unindent();
-                          p("} else {");
-                          indent();
-                          p(setter+"(new "+type+"().mergeFramed(input));");
-                          unindent();
-                          p("}");
-                      }
-                  }
-                  p("break;");
-                  unindent();
-              }              
-              p("}");
-          } unindent();
-          p("}"); 
-        } unindent();
-        p("}");
+        indent();
+		{        
+			p("while (true) {");
+			indent();
+			{
+				p("int tag = input.readTag();");
+				p("if ((tag & 0x07) == 4) {");
+				p("   return this;");
+				p("}");
+
+				p("switch (tag) {");
+				p("case 0:");
+				p("   return this;");
+				p("default: {");
+
+				p("   break;");
+				p("}");
+
+				for (FieldDescriptor field : m.getFields().values()) {
+					String uname = uCamel(field.getName());
+					String setter = "set" + uname;
+					boolean repeated = field.getRule() == FieldDescriptor.REPEATED_RULE;
+					if (repeated) {
+						setter = "get" + uname + "List().add";
+					}
+					if (field.getType() == FieldDescriptor.STRING_TYPE) {
+						p("case "
+								+ makeTag(field.getTag(),
+										WIRETYPE_LENGTH_DELIMITED) + ":");
+						indent();
+						p(setter + "(input.readString());");
+					} else if (field.getType() == FieldDescriptor.BYTES_TYPE) {
+						p("case "
+								+ makeTag(field.getTag(),
+										WIRETYPE_LENGTH_DELIMITED) + ":");
+						indent();
+						p(setter + "(input.readBytes());");
+					} else if (field.getType() == FieldDescriptor.BOOL_TYPE) {
+						p("case " + makeTag(field.getTag(), WIRETYPE_VARINT)
+								+ ":");
+						indent();
+						p(setter + "(input.readBool());");
+					} else if (field.getType() == FieldDescriptor.DOUBLE_TYPE) {
+						p("case " + makeTag(field.getTag(), WIRETYPE_FIXED64)
+								+ ":");
+						indent();
+						p(setter + "(input.readDouble());");
+					} else if (field.getType() == FieldDescriptor.FLOAT_TYPE) {
+						p("case " + makeTag(field.getTag(), WIRETYPE_FIXED32)
+								+ ":");
+						indent();
+						p(setter + "(input.readFloat());");
+					} else if (field.getType() == FieldDescriptor.INT32_TYPE) {
+						p("case " + makeTag(field.getTag(), WIRETYPE_VARINT)
+								+ ":");
+						indent();
+						p(setter + "(input.readInt32());");
+					} else if (field.getType() == FieldDescriptor.INT64_TYPE) {
+						p("case " + makeTag(field.getTag(), WIRETYPE_VARINT)
+								+ ":");
+						indent();
+						p(setter + "(input.readInt64());");
+					} else if (field.getType() == FieldDescriptor.SINT32_TYPE) {
+						p("case " + makeTag(field.getTag(), WIRETYPE_VARINT)
+								+ ":");
+						indent();
+						p(setter + "(input.readSInt32());");
+					} else if (field.getType() == FieldDescriptor.SINT64_TYPE) {
+						p("case " + makeTag(field.getTag(), WIRETYPE_VARINT)
+								+ ":");
+						indent();
+						p(setter + "(input.readSInt64());");
+					} else if (field.getType() == FieldDescriptor.UINT32_TYPE) {
+						p("case " + makeTag(field.getTag(), WIRETYPE_VARINT)
+								+ ":");
+						indent();
+						p(setter + "(input.readUInt32());");
+					} else if (field.getType() == FieldDescriptor.UINT64_TYPE) {
+						p("case " + makeTag(field.getTag(), WIRETYPE_VARINT)
+								+ ":");
+						indent();
+						p(setter + "(input.readUInt64());");
+					} else if (field.getType() == FieldDescriptor.FIXED32_TYPE) {
+						p("case " + makeTag(field.getTag(), WIRETYPE_FIXED32)
+								+ ":");
+						indent();
+						p(setter + "(input.readFixed32());");
+					} else if (field.getType() == FieldDescriptor.FIXED64_TYPE) {
+						p("case " + makeTag(field.getTag(), WIRETYPE_FIXED64)
+								+ ":");
+						indent();
+						p(setter + "(input.readFixed64());");
+					} else if (field.getType() == FieldDescriptor.SFIXED32_TYPE) {
+						p("case " + makeTag(field.getTag(), WIRETYPE_FIXED32)
+								+ ":");
+						indent();
+						p(setter + "(input.readSFixed32());");
+					} else if (field.getType() == FieldDescriptor.SFIXED64_TYPE) {
+						p("case " + makeTag(field.getTag(), WIRETYPE_FIXED64)
+								+ ":");
+						indent();
+						p(setter + "(input.readSFixed64());");
+					} else if (field.getTypeDescriptor().isEnum()) {
+						p("case " + makeTag(field.getTag(), WIRETYPE_VARINT)
+								+ ":");
+						indent();
+						String type = javaType(field);
+						p("{");
+						indent();
+						p("int t = input.readEnum();");
+						p("" + type + " value = " + type + ".valueOf(t);");
+						p("if( value !=null ) {");
+						indent();
+						p(setter + "(value);");
+						unindent();
+						p("}");
+						// TODO: else store it as an known
+
+						unindent();
+						p("}");
+
+					} else if (field.getGroup() != null) {
+						p("case "
+								+ makeTag(field.getTag(), WIRETYPE_START_GROUP)
+								+ ":");
+						indent();
+						String type = javaType(field);
+						if (repeated) {
+							p(setter + "(readGroup(input, " + field.getTag()
+									+ ", new " + type + "()));");
+						} else {
+							p("if (has" + uname + "()) {");
+							indent();
+							p("readGroup(input, " + field.getTag() + ", get"
+									+ uname + "());");
+							unindent();
+							p("} else {");
+							indent();
+							p(setter + "(readGroup(input, " + field.getTag()
+									+ ",new " + type + "()));");
+							unindent();
+							p("}");
+						}
+						p("");
+					} else {
+						p("case "
+								+ makeTag(field.getTag(),
+										WIRETYPE_LENGTH_DELIMITED) + ":");
+						indent();
+						String type = javaType(field);
+						if (repeated) {
+							p(setter + "(new " + type
+									+ "().mergeFramed(input));");
+						} else {
+							p("if (has" + uname + "()) {");
+							indent();
+							p("get" + uname + "().mergeFramed(input);");
+							unindent();
+							p("} else {");
+							indent();
+							p(setter + "(new " + type
+									+ "().mergeFramed(input));");
+							unindent();
+							p("}");
+						}
+					}
+					p("break;");
+					unindent();
+				}
+				p("}");
+			}
+			unindent();
+			p("}");
+		}
+		unindent();
+		p("}");
     }
 
     /**
-     * @param m
-     * @param className
-     */
+	 * @param m
+	 * @param className
+	 */
     private void generateMethodMergeFromBean(MessageDescriptor m, String className) {
         p("public "+className+" mergeFrom("+className+" other) {");
         indent();
@@ -824,12 +994,12 @@
     }
 
     /**
-     * @param m
-     */
+	 * @param m
+	 */
     private void generateMethodClear(MessageDescriptor m) {
         p("public final void clear() {");
         indent();
-        p("memoizedSerializedSize=-1;");
+        p("super.clear();");
         for (FieldDescriptor field : m.getFields().values()) {
             String uname = uCamel(field.getName());
             p("clear" + uname + "();");
@@ -863,7 +1033,7 @@
         p("}");
         p();
         
-        p("private final "+className+" checktInitialized() throws com.google.protobuf.InvalidProtocolBufferException
{");
+        p("protected final "+className+" checktInitialized() throws com.google.protobuf.InvalidProtocolBufferException
{");
         indent();
         p("java.util.ArrayList<String> missingFields = missingFields();");
         p("if( !missingFields.isEmpty()) {");
@@ -878,6 +1048,9 @@
 
         p("public final java.util.ArrayList<String> missingFields() {");
         indent();
+        if( deferredDecode ) {
+        	p("load();");
+        }        
         p("java.util.ArrayList<String> missingFields = new java.util.ArrayList<String>();");
         
         for (FieldDescriptor field : m.getFields().values()) {
@@ -891,41 +1064,43 @@
             }
         }
         
-        for (FieldDescriptor field : m.getFields().values()) {
-            if( field.getTypeDescriptor()!=null && !field.getTypeDescriptor().isEnum())
{
-                String uname = uCamel(field.getName());
-                p("if( has" + uname + "() ) {");
-                indent();
-                if( !field.isRepeated() ) {
-                    p("try {");
-                    indent();
-                    p("get" + uname + "().assertInitialized();");
-                    unindent();
-                    p("} catch (org.apache.activemq.protobuf.UninitializedMessageException
e){");
-                    indent();
-                    p("missingFields.addAll(prefix(e.getMissingFields(),\""+field.getName()+".\"));");
-                    unindent();
-                    p("}");
-                } else {
-                    String type = javaCollectionType(field);
-                    p("java.util.List<"+type+"> l = get" + uname + "List();");
-                    p("for( int i=0; i < l.size(); i++ ) {");
-                    indent();
-                    p("try {");
-                    indent();
-                    p("l.get(i).assertInitialized();");
-                    unindent();
-                    p("} catch (org.apache.activemq.protobuf.UninitializedMessageException
e){");
-                    indent();
-                    p("missingFields.addAll(prefix(e.getMissingFields(),\""+field.getName()+"[\"+i+\"]\"));");
-                    unindent();
-                    p("}");
-                    unindent();
-                    p("}");
-                }
-                unindent();
-                p("}");
-            }
+        if( !deferredDecode ) {
+	        for (FieldDescriptor field : m.getFields().values()) {
+	            if( field.getTypeDescriptor()!=null && !field.getTypeDescriptor().isEnum())
{
+	                String uname = uCamel(field.getName());
+	                p("if( has" + uname + "() ) {");
+	                indent();
+	                if( !field.isRepeated() ) {
+	                    p("try {");
+	                    indent();
+	                    p("get" + uname + "().assertInitialized();");
+	                    unindent();
+	                    p("} catch (org.apache.activemq.protobuf.UninitializedMessageException
e){");
+	                    indent();
+	                    p("missingFields.addAll(prefix(e.getMissingFields(),\""+field.getName()+".\"));");
+	                    unindent();
+	                    p("}");
+	                } else {
+	                    String type = javaCollectionType(field);
+	                    p("java.util.List<"+type+"> l = get" + uname + "List();");
+	                    p("for( int i=0; i < l.size(); i++ ) {");
+	                    indent();
+	                    p("try {");
+	                    indent();
+	                    p("l.get(i).assertInitialized();");
+	                    unindent();
+	                    p("} catch (org.apache.activemq.protobuf.UninitializedMessageException
e){");
+	                    indent();
+	                    p("missingFields.addAll(prefix(e.getMissingFields(),\""+field.getName()+"[\"+i+\"]\"));");
+	                    unindent();
+	                    p("}");
+	                    unindent();
+	                    p("}");
+	                }
+	                unindent();
+	                p("}");
+	            }
+	        }
         }
         p("return missingFields;");
         unindent();
@@ -945,6 +1120,9 @@
         p("public java.lang.StringBuilder toString(java.lang.StringBuilder sb, String prefix)
{");
         indent();
         
+        if( deferredDecode ) {
+        	p("load();");
+        }        
         for (FieldDescriptor field : m.getFields().values()) {
             String uname = uCamel(field.getName());
             p("if(  has" + uname + "() ) {");
@@ -1011,6 +1189,9 @@
             // Create the field accessors
             p("public boolean has" + uname + "() {");
             indent();
+            if( deferredDecode ) {
+            	p("load();");
+            }        
             p("return this.f_" + lname + "!=null && !this.f_" + lname + ".isEmpty();");
             unindent();
             p("}");
@@ -1018,6 +1199,9 @@
 
             p("public java.util.List<" + type + "> get" + uname + "List() {");
             indent();
+            if( deferredDecode ) {
+            	p("load();");
+            }        
             p("if( this.f_" + lname + " == null ) {");
             indent();
             p("this.f_" + lname + " = new java.util.ArrayList<" + type + ">();");
@@ -1030,6 +1214,7 @@
 
             p("public "+className+" set" + uname + "List(java.util.List<" + type + ">
" + lname + ") {");
             indent();
+          	p("loadAndClear();");
             p("this.f_" + lname + " = " + lname + ";");
             p("return this;");
             unindent();
@@ -1038,6 +1223,9 @@
             
             p("public int get" + uname + "Count() {");
             indent();
+            if( deferredDecode ) {
+            	p("load();");
+            }        
             p("if( this.f_" + lname + " == null ) {");
             indent();
             p("return 0;");
@@ -1050,6 +1238,9 @@
             
             p("public " + type + " get" + uname + "(int index) {");
             indent();
+            if( deferredDecode ) {
+            	p("load();");
+            }        
             p("if( this.f_" + lname + " == null ) {");
             indent();
             p("return null;");
@@ -1062,6 +1253,7 @@
                             
             p("public "+className+" set" + uname + "(int index, " + type + " value) {");
             indent();
+          	p("loadAndClear();");
             p("get" + uname + "List().set(index, value);");
             p("return this;");
             unindent();
@@ -1070,6 +1262,7 @@
             
             p("public "+className+" add" + uname + "(" + type + " value) {");
             indent();
+          	p("loadAndClear();");
             p("get" + uname + "List().add(value);");
             p("return this;");
             unindent();
@@ -1078,6 +1271,7 @@
             
             p("public "+className+" addAll" + uname + "(java.lang.Iterable<? extends "
+ type + "> collection) {");
             indent();
+          	p("loadAndClear();");
             p("super.addAll(collection, get" + uname + "List());");
             p("return this;");
             unindent();
@@ -1086,6 +1280,7 @@
 
             p("public void clear" + uname + "() {");
             indent();
+          	p("loadAndClear();");
             p("this.f_" + lname + " = null;");
             unindent();
             p("}");
@@ -1102,6 +1297,9 @@
             // Create the field accessors
             p("public boolean has" + uname + "() {");
             indent();
+            if( deferredDecode ) {
+            	p("load();");
+            }        
             if (primitive) {
                 p("return this.b_" + lname + ";");
             } else {
@@ -1113,6 +1311,9 @@
 
             p("public " + type + " get" + uname + "() {");
             indent();
+            if( deferredDecode ) {
+            	p("load();");
+            }        
             if( field.getTypeDescriptor()!=null && !field.getTypeDescriptor().isEnum())
{
                 p("if( this.f_" + lname + " == null ) {");
                 indent();
@@ -1127,6 +1328,7 @@
 
             p("public "+className+" set" + uname + "(" + type + " " + lname + ") {");
             indent();
+          	p("loadAndClear();");
             if (primitive) {
                 p("this.b_" + lname + " = true;");
             }
@@ -1138,6 +1340,7 @@
 
             p("public void clear" + uname + "() {");
             indent();
+          	p("loadAndClear();");
             if (primitive) {
                 p("this.b_" + lname + " = false;");
             }



Mime
View raw message