Author: bryanduxbury
Date: Thu Oct  1 20:53:45 2009
New Revision: 820786

URL: http://svn.apache.org/viewvc?rev=820786&view=rev
Log:
THRIFT-446. java: PartialDeserialization in Java

This patch adds a partialDeserialize method to TDeserializer that allows you to 
request a specific subfield of the serialized data.


Added:
    
incubator/thrift/trunk/lib/java/test/org/apache/thrift/test/PartialDeserializeTest.java
Modified:
    incubator/thrift/trunk/lib/java/build.xml
    incubator/thrift/trunk/lib/java/src/org/apache/thrift/TDeserializer.java
    incubator/thrift/trunk/test/DebugProtoTest.thrift

Modified: incubator/thrift/trunk/lib/java/build.xml
URL: 
http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/java/build.xml?rev=820786&r1=820785&r2=820786&view=diff
==============================================================================
--- incubator/thrift/trunk/lib/java/build.xml (original)
+++ incubator/thrift/trunk/lib/java/build.xml Thu Oct  1 20:53:45 2009
@@ -182,6 +182,8 @@
       classpathref="test.classpath" failonerror="true" />
     <java classname="org.apache.thrift.test.UnionTest"
       classpathref="test.classpath" failonerror="true" />
+    <java classname="org.apache.thrift.test.PartialDeserializeTest"
+      classpathref="test.classpath" failonerror="true" />
   </target>
 
   <target name="generate">

Modified: 
incubator/thrift/trunk/lib/java/src/org/apache/thrift/TDeserializer.java
URL: 
http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/java/src/org/apache/thrift/TDeserializer.java?rev=820786&r1=820785&r2=820786&view=diff
==============================================================================
--- incubator/thrift/trunk/lib/java/src/org/apache/thrift/TDeserializer.java 
(original)
+++ incubator/thrift/trunk/lib/java/src/org/apache/thrift/TDeserializer.java 
Thu Oct  1 20:53:45 2009
@@ -23,7 +23,11 @@
 import java.io.UnsupportedEncodingException;
 
 import org.apache.thrift.protocol.TBinaryProtocol;
+import org.apache.thrift.protocol.TField;
+import org.apache.thrift.protocol.TProtocol;
 import org.apache.thrift.protocol.TProtocolFactory;
+import org.apache.thrift.protocol.TProtocolUtil;
+import org.apache.thrift.protocol.TType;
 import org.apache.thrift.transport.TIOStreamTransport;
 
 /**
@@ -81,6 +85,59 @@
   }
 
   /**
+   * Deserialize only a single Thrift object (addressed by recursively using 
field id)
+   * from a byte record.
+   * @param record The object to read from
+   * @param tb The object to read into
+   * @param fieldIdPath The FieldId's that define a path tb
+   * @throws TException 
+   */
+  public void partialDeserialize(TBase tb, byte[] bytes, int ... fieldIdPath) 
throws TException {
+    // if there are no elements in the path, then the user is looking for the 
+    // regular deserialize method
+    // TODO: it might be nice not to have to do this check every time to save
+    // some performance.
+    if (fieldIdPath.length == 0) {
+      deserialize(tb, bytes);
+      return;
+    }
+
+    TProtocol iprot = protocolFactory_.getProtocol(
+        new TIOStreamTransport(
+          new ByteArrayInputStream(bytes))); 
+
+    // index into field ID path being currently searched for
+    int curPathIndex = 0;
+
+    iprot.readStructBegin();
+
+    while (curPathIndex < fieldIdPath.length) {
+      TField field = iprot.readFieldBegin();
+      // we can stop searching if we either see a stop or we go past the field 
+      // id we're looking for (since fields should now be serialized in asc
+      // order).
+      if (field.type == TType.STOP || field.id > fieldIdPath[curPathIndex]) { 
+        return;
+      }
+
+      if (field.id != fieldIdPath[curPathIndex]) {
+        // Not the field we're looking for. Skip field.
+        TProtocolUtil.skip(iprot, field.type);
+        iprot.readFieldEnd();
+      } else {
+        // This field is the next step in the path. Step into field.
+        curPathIndex++;
+        if (curPathIndex < fieldIdPath.length) {
+          iprot.readStructBegin();
+        }
+      }
+    }
+
+    // when this line is reached, iprot will be positioned at the start of tb.
+    tb.read(iprot);
+  }
+
+  /**
    * Deserialize the Thrift object from a Java string, using the default JVM
    * charset encoding.
    *

Added: 
incubator/thrift/trunk/lib/java/test/org/apache/thrift/test/PartialDeserializeTest.java
URL: 
http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/java/test/org/apache/thrift/test/PartialDeserializeTest.java?rev=820786&view=auto
==============================================================================
--- 
incubator/thrift/trunk/lib/java/test/org/apache/thrift/test/PartialDeserializeTest.java
 (added)
+++ 
incubator/thrift/trunk/lib/java/test/org/apache/thrift/test/PartialDeserializeTest.java
 Thu Oct  1 20:53:45 2009
@@ -0,0 +1,82 @@
+/*
+ * 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.thrift.test;
+
+import org.apache.thrift.TBase;
+import org.apache.thrift.TDeserializer;
+import org.apache.thrift.TException;
+import org.apache.thrift.TSerializer;
+import org.apache.thrift.protocol.TBinaryProtocol;
+import org.apache.thrift.protocol.TCompactProtocol;
+import org.apache.thrift.protocol.TJSONProtocol;
+import org.apache.thrift.protocol.TProtocolFactory;
+
+import thrift.test.Backwards;
+import thrift.test.OneOfEach;
+import thrift.test.PrimitiveThenStruct;
+import thrift.test.StructWithAUnion;
+import thrift.test.TestUnion;
+
+public class PartialDeserializeTest {
+
+  private static final TProtocolFactory[] PROTOCOLS = new TProtocolFactory[] {
+    new TBinaryProtocol.Factory(), 
+    new TCompactProtocol.Factory(), 
+    new TJSONProtocol.Factory()
+  };
+
+  public static void main(String[] args) throws TException {
+    //Root:StructWithAUnion
+    //  1:Union
+    //    1.3:OneOfEach
+    OneOfEach Level3OneOfEach = Fixtures.oneOfEach;
+    TestUnion Level2TestUnion = new TestUnion(TestUnion.STRUCT_FIELD, 
Level3OneOfEach);
+    StructWithAUnion Level1SWU = new StructWithAUnion(Level2TestUnion);
+
+    Backwards bw = new Backwards(2, 1);
+    PrimitiveThenStruct pts = new PrimitiveThenStruct(12345, 67890, bw);
+
+    for (TProtocolFactory factory : PROTOCOLS) {
+      //Full deserialization test
+      testPartialDeserialize(factory, Level1SWU, new StructWithAUnion(), 
Level1SWU);
+
+      //Level 2 test
+      testPartialDeserialize(factory, Level1SWU, new TestUnion(), 
Level2TestUnion, StructWithAUnion.TEST_UNION);
+
+      //Level 3 on 3rd field test
+      testPartialDeserialize(factory, Level1SWU, new OneOfEach(), 
Level3OneOfEach, StructWithAUnion.TEST_UNION, TestUnion.STRUCT_FIELD);
+
+      //Test early termination when traversed path Field.id exceeds the one 
being searched for
+      testPartialDeserialize(factory, Level1SWU, new OneOfEach(), new 
OneOfEach(), StructWithAUnion.TEST_UNION, TestUnion.I32_FIELD);
+      
+      //Test that readStructBegin isn't called on primitive
+      testPartialDeserialize(factory, pts, new Backwards(), bw, 
PrimitiveThenStruct.BW);      
+    }
+  }
+
+  public static void testPartialDeserialize(TProtocolFactory protocolFactory, 
TBase input, TBase output, TBase expected, int ... fieldIdPath) throws 
TException {
+    byte[] record = new TSerializer(protocolFactory).serialize(input);
+    new TDeserializer(protocolFactory).partialDeserialize(output, record, 
fieldIdPath);
+    if(!output.equals(expected))
+      throw new RuntimeException("with " + protocolFactory.toString() + ", 
expected " + expected + " but got " + output);
+  }
+}
+

Modified: incubator/thrift/trunk/test/DebugProtoTest.thrift
URL: 
http://svn.apache.org/viewvc/incubator/thrift/trunk/test/DebugProtoTest.thrift?rev=820786&r1=820785&r2=820786&view=diff
==============================================================================
--- incubator/thrift/trunk/test/DebugProtoTest.thrift (original)
+++ incubator/thrift/trunk/test/DebugProtoTest.thrift Thu Oct  1 20:53:45 2009
@@ -265,4 +265,10 @@
 
 struct StructWithAUnion {
   1: TestUnion test_union;
+}
+
+struct PrimitiveThenStruct {
+  1: i32 blah;
+  2: i32 blah2;
+  3: Backwards bw;
 }
\ No newline at end of file


Reply via email to