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;");
}