diff --git a/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/META-INF/MANIFEST.MF b/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..2789db18ee
--- /dev/null
+++ b/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/META-INF/MANIFEST.MF
@@ -0,0 +1,21 @@
+Manifest-Version: 1.0
+SCA-Version: 1.1
+Bundle-Name: Apache Tuscany SCA Data Binding for Google ProtocolBuffers
+Bundle-Vendor: The Apache Software Foundation
+Bundle-Version: 2.0.0
+Bundle-ManifestVersion: 2
+Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
+Bundle-Description: Apache Tuscany SCA Data Binding for JSON
+Import-Package: javax.xml.namespace,
+ javax.xml.stream,
+ org.apache.tuscany.sca.common.xml.stax;version="2.0.0",
+ org.apache.tuscany.sca.core;version="2.0.0",
+ org.apache.tuscany.sca.databinding;version="2.0.0",
+ org.apache.tuscany.sca.databinding.impl;version="2.0.0",
+ org.apache.tuscany.sca.interfacedef;version="2.0.0",
+ org.apache.tuscany.sca.interfacedef.impl;version="2.0.0";resolution:=optional,
+ org.apache.tuscany.sca.interfacedef.util;version="2.0.0",
+ org.oasisopen.sca.annotation;version="2.0.0"
+Bundle-SymbolicName: org.apache.tuscany.sca.databinding.protobuf
+Bundle-DocURL: http://www.apache.org/
+
diff --git a/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/pom.xml b/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/pom.xml
new file mode 100644
index 0000000000..90b5ba1c68
--- /dev/null
+++ b/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/pom.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    * 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.    
+-->
+<project>
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.tuscany.sca</groupId>
+        <artifactId>tuscany-modules</artifactId>
+        <version>2.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <artifactId>tuscany-databinding-protobuf</artifactId>
+    <name>Apache Tuscany SCA Data Binding for Google ProtocolBuffers</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.tuscany.sca</groupId>
+            <artifactId>tuscany-core-spi</artifactId>
+            <version>2.0-SNAPSHOT</version>
+        </dependency>
+        
+        <dependency>
+            <groupId>org.apache.tuscany.sca</groupId>
+            <artifactId>tuscany-common-xml</artifactId>
+            <version>2.0-SNAPSHOT</version>
+        </dependency>
+        
+        <dependency>
+            <groupId>org.apache.tuscany.sca</groupId>
+            <artifactId>tuscany-databinding</artifactId>
+            <version>2.0-SNAPSHOT</version>
+        </dependency>
+        
+        <dependency>
+            <groupId>com.google.protobuf</groupId>
+            <artifactId>protobuf-java</artifactId>
+            <version>2.3.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.8.1</version>
+            <scope>test</scope>
+        </dependency>
+        
+    </dependencies>
+</project>
diff --git a/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/src/main/java/org/apache/tuscany/sca/databinding/protobuf/InputStream2Protobuf.java b/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/src/main/java/org/apache/tuscany/sca/databinding/protobuf/InputStream2Protobuf.java
new file mode 100644
index 0000000000..7953e4e5b3
--- /dev/null
+++ b/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/src/main/java/org/apache/tuscany/sca/databinding/protobuf/InputStream2Protobuf.java
@@ -0,0 +1,65 @@
+/*
+ * 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.tuscany.sca.databinding.protobuf;
+
+import java.io.InputStream;
+import java.lang.reflect.Method;
+
+import org.apache.tuscany.sca.databinding.PullTransformer;
+import org.apache.tuscany.sca.databinding.TransformationContext;
+import org.apache.tuscany.sca.databinding.TransformationException;
+
+import com.google.protobuf.Message;
+
+/**
+ * 
+ */
+public class InputStream2Protobuf implements PullTransformer<InputStream, Message> {
+
+    @Override
+    public String getSourceDataBinding() {
+        return "application/x-protobuf" + "#" + InputStream.class.getName();
+    }
+
+    @Override
+    public String getTargetDataBinding() {
+        // TODO Auto-generated method stub
+        return ProtobufDatabinding.NAME;
+    }
+
+    @Override
+    public int getWeight() {
+        // TODO Auto-generated method stub
+        return 10;
+    }
+
+    @Override
+    public Message transform(InputStream source, TransformationContext context) {
+        try {
+            Class<?> type = context.getTargetDataType().getPhysical();
+            Method method = type.getMethod("parseFrom", InputStream.class);
+            Object result = method.invoke(null, source);
+            return (Message)result;
+        } catch (Throwable e) {
+            throw new TransformationException(e);
+        }
+    }
+
+}
diff --git a/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/src/main/java/org/apache/tuscany/sca/databinding/protobuf/Protobuf2OutputStream.java b/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/src/main/java/org/apache/tuscany/sca/databinding/protobuf/Protobuf2OutputStream.java
new file mode 100644
index 0000000000..6892287f67
--- /dev/null
+++ b/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/src/main/java/org/apache/tuscany/sca/databinding/protobuf/Protobuf2OutputStream.java
@@ -0,0 +1,60 @@
+/*
+ * 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.tuscany.sca.databinding.protobuf;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.tuscany.sca.databinding.PushTransformer;
+import org.apache.tuscany.sca.databinding.TransformationContext;
+import org.apache.tuscany.sca.databinding.TransformationException;
+
+import com.google.protobuf.Message;
+
+/**
+ * 
+ */
+public class Protobuf2OutputStream implements PushTransformer<Message, OutputStream> {
+    @Override
+    public String getSourceDataBinding() {
+        return ProtobufDatabinding.NAME;
+    }
+
+    @Override
+    public String getTargetDataBinding() {
+        return "application/x-protobuf" + "#" + OutputStream.class.getName();
+    }
+
+    @Override
+    public int getWeight() {
+        return 10;
+    }
+
+    @Override
+    public void transform(Message source, OutputStream sink, TransformationContext context) {
+        try {
+            if (source != null) {
+                source.writeTo(sink);
+            }
+        } catch (IOException e) {
+            throw new TransformationException(e);
+        }
+    }
+}
diff --git a/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/src/main/java/org/apache/tuscany/sca/databinding/protobuf/ProtobufDatabinding.java b/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/src/main/java/org/apache/tuscany/sca/databinding/protobuf/ProtobufDatabinding.java
new file mode 100644
index 0000000000..ad148c7499
--- /dev/null
+++ b/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/src/main/java/org/apache/tuscany/sca/databinding/protobuf/ProtobufDatabinding.java
@@ -0,0 +1,107 @@
+/*
+ * 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.tuscany.sca.databinding.protobuf;
+
+import org.apache.tuscany.sca.databinding.DataBinding;
+import org.apache.tuscany.sca.databinding.WrapperHandler;
+import org.apache.tuscany.sca.databinding.XMLTypeHelper;
+import org.apache.tuscany.sca.interfacedef.DataType;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl;
+
+import com.google.protobuf.Message;
+
+/**
+ * Google ProtocolBuffers databinding
+ */
+public class ProtobufDatabinding implements DataBinding {
+
+    public static final String NAME = "ProtocolBuffers";
+
+    /**
+     * 
+     */
+    public ProtobufDatabinding() {
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.tuscany.sca.databinding.DataBinding#getName()
+     */
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.tuscany.sca.databinding.DataBinding#introspect(org.apache.tuscany.sca.interfacedef.DataType, org.apache.tuscany.sca.interfacedef.Operation)
+     */
+    @Override
+    public boolean introspect(DataType dataType, Operation operation) {
+        if (Message.class.isAssignableFrom(dataType.getPhysical())) {
+            dataType.setDataBinding(NAME);
+            return true;
+        }
+        return false;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.tuscany.sca.databinding.DataBinding#introspect(java.lang.Object, org.apache.tuscany.sca.interfacedef.Operation)
+     */
+    @Override
+    public DataType introspect(Object value, Operation operation) {
+        if (value instanceof Message) {
+            DataType dt = new DataTypeImpl(value.getClass(), null);
+            dt.setDataBinding(NAME);
+            return dt;
+        } else {
+            return null;
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.tuscany.sca.databinding.DataBinding#getWrapperHandler()
+     */
+    @Override
+    public WrapperHandler getWrapperHandler() {
+        return null;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.tuscany.sca.databinding.DataBinding#copy(java.lang.Object, org.apache.tuscany.sca.interfacedef.DataType, org.apache.tuscany.sca.interfacedef.DataType, org.apache.tuscany.sca.interfacedef.Operation, org.apache.tuscany.sca.interfacedef.Operation)
+     */
+    @Override
+    public Object copy(Object object,
+                       DataType sourceDataType,
+                       DataType targetDataType,
+                       Operation sourceOperation,
+                       Operation targetOperation) {
+        Message msg = (Message)object;
+        return ((Message.Builder)msg.toBuilder().clone()).build();
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.tuscany.sca.databinding.DataBinding#getXMLTypeHelper()
+     */
+    @Override
+    public XMLTypeHelper getXMLTypeHelper() {
+        return null;
+    }
+
+}
diff --git a/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding b/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding
new file mode 100644
index 0000000000..35f7932ff9
--- /dev/null
+++ b/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding
@@ -0,0 +1,20 @@
+# 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.
+
+# implementation classes for the databindings
+org.apache.tuscany.sca.databinding.protobuf.ProtobufDatabinding;name=ProtocolBuffers
+
diff --git a/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer b/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer
new file mode 100644
index 0000000000..0f60373c30
--- /dev/null
+++ b/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer
@@ -0,0 +1,20 @@
+# 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.
+
+# Implementation classes for the transformers
+org.apache.tuscany.sca.databinding.protobuf.InputStream2Protobuf;source=application/x-protobuf#java.io.InputStream;target=ProtocolBuffers,weight=10,public=true
+
diff --git a/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PushTransformer b/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PushTransformer
new file mode 100644
index 0000000000..cc1989eb7b
--- /dev/null
+++ b/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PushTransformer
@@ -0,0 +1,17 @@
+# 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.
+org.apache.tuscany.sca.databinding.protobuf.Protobuf2OutputStream;source=ProtocolBuffers;target=application/x-protobuf#java.io.OutputStream,weight=10,public=true
diff --git a/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/src/test/java/com/example/tutorial/AddressBookProtos.java b/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/src/test/java/com/example/tutorial/AddressBookProtos.java
new file mode 100644
index 0000000000..8219fe1099
--- /dev/null
+++ b/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/src/test/java/com/example/tutorial/AddressBookProtos.java
@@ -0,0 +1,1375 @@
+/*
+ * 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.    
+ */
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: addressbook.proto
+
+package com.example.tutorial;
+
+public final class AddressBookProtos {
+    private AddressBookProtos() {
+    }
+
+    public static void registerAllExtensions(com.google.protobuf.ExtensionRegistry registry) {
+    }
+
+    public static final class Person extends com.google.protobuf.GeneratedMessage {
+        // Use Person.newBuilder() to construct.
+        private Person() {
+            initFields();
+        }
+
+        private Person(boolean noInit) {
+        }
+
+        private static final Person defaultInstance;
+
+        public static Person getDefaultInstance() {
+            return defaultInstance;
+        }
+
+        public Person getDefaultInstanceForType() {
+            return defaultInstance;
+        }
+
+        public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() {
+            return com.example.tutorial.AddressBookProtos.internal_static_tutorial_Person_descriptor;
+        }
+
+        protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() {
+            return com.example.tutorial.AddressBookProtos.internal_static_tutorial_Person_fieldAccessorTable;
+        }
+
+        public enum PhoneType implements com.google.protobuf.ProtocolMessageEnum {
+            MOBILE(0, 0), HOME(1, 1), WORK(2, 2), ;
+
+            public final int getNumber() {
+                return value;
+            }
+
+            public static PhoneType valueOf(int value) {
+                switch (value) {
+                    case 0:
+                        return MOBILE;
+                    case 1:
+                        return HOME;
+                    case 2:
+                        return WORK;
+                    default:
+                        return null;
+                }
+            }
+
+            public static com.google.protobuf.Internal.EnumLiteMap<PhoneType> internalGetValueMap() {
+                return internalValueMap;
+            }
+
+            private static com.google.protobuf.Internal.EnumLiteMap<PhoneType> internalValueMap =
+                new com.google.protobuf.Internal.EnumLiteMap<PhoneType>() {
+                    public PhoneType findValueByNumber(int number) {
+                        return PhoneType.valueOf(number);
+                    }
+                };
+
+            public final com.google.protobuf.Descriptors.EnumValueDescriptor getValueDescriptor() {
+                return getDescriptor().getValues().get(index);
+            }
+
+            public final com.google.protobuf.Descriptors.EnumDescriptor getDescriptorForType() {
+                return getDescriptor();
+            }
+
+            public static final com.google.protobuf.Descriptors.EnumDescriptor getDescriptor() {
+                return com.example.tutorial.AddressBookProtos.Person.getDescriptor().getEnumTypes().get(0);
+            }
+
+            private static final PhoneType[] VALUES = {MOBILE, HOME, WORK,};
+
+            public static PhoneType valueOf(com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
+                if (desc.getType() != getDescriptor()) {
+                    throw new java.lang.IllegalArgumentException("EnumValueDescriptor is not for this type.");
+                }
+                return VALUES[desc.getIndex()];
+            }
+
+            private final int index;
+            private final int value;
+
+            private PhoneType(int index, int value) {
+                this.index = index;
+                this.value = value;
+            }
+
+            static {
+                com.example.tutorial.AddressBookProtos.getDescriptor();
+            }
+
+            // @@protoc_insertion_point(enum_scope:tutorial.Person.PhoneType)
+        }
+
+        public static final class PhoneNumber extends com.google.protobuf.GeneratedMessage {
+            // Use PhoneNumber.newBuilder() to construct.
+            private PhoneNumber() {
+                initFields();
+            }
+
+            private PhoneNumber(boolean noInit) {
+            }
+
+            private static final PhoneNumber defaultInstance;
+
+            public static PhoneNumber getDefaultInstance() {
+                return defaultInstance;
+            }
+
+            public PhoneNumber getDefaultInstanceForType() {
+                return defaultInstance;
+            }
+
+            public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() {
+                return com.example.tutorial.AddressBookProtos.internal_static_tutorial_Person_PhoneNumber_descriptor;
+            }
+
+            protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() {
+                return com.example.tutorial.AddressBookProtos.internal_static_tutorial_Person_PhoneNumber_fieldAccessorTable;
+            }
+
+            // required string number = 1;
+            public static final int NUMBER_FIELD_NUMBER = 1;
+            private boolean hasNumber;
+            private java.lang.String number_ = "";
+
+            public boolean hasNumber() {
+                return hasNumber;
+            }
+
+            public java.lang.String getNumber() {
+                return number_;
+            }
+
+            // optional .tutorial.Person.PhoneType type = 2 [default = HOME];
+            public static final int TYPE_FIELD_NUMBER = 2;
+            private boolean hasType;
+            private com.example.tutorial.AddressBookProtos.Person.PhoneType type_;
+
+            public boolean hasType() {
+                return hasType;
+            }
+
+            public com.example.tutorial.AddressBookProtos.Person.PhoneType getType() {
+                return type_;
+            }
+
+            private void initFields() {
+                type_ = com.example.tutorial.AddressBookProtos.Person.PhoneType.HOME;
+            }
+
+            public final boolean isInitialized() {
+                if (!hasNumber)
+                    return false;
+                return true;
+            }
+
+            public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException {
+                getSerializedSize();
+                if (hasNumber()) {
+                    output.writeString(1, getNumber());
+                }
+                if (hasType()) {
+                    output.writeEnum(2, getType().getNumber());
+                }
+                getUnknownFields().writeTo(output);
+            }
+
+            private int memoizedSerializedSize = -1;
+
+            public int getSerializedSize() {
+                int size = memoizedSerializedSize;
+                if (size != -1)
+                    return size;
+
+                size = 0;
+                if (hasNumber()) {
+                    size += com.google.protobuf.CodedOutputStream.computeStringSize(1, getNumber());
+                }
+                if (hasType()) {
+                    size += com.google.protobuf.CodedOutputStream.computeEnumSize(2, getType().getNumber());
+                }
+                size += getUnknownFields().getSerializedSize();
+                memoizedSerializedSize = size;
+                return size;
+            }
+
+            public static com.example.tutorial.AddressBookProtos.Person.PhoneNumber parseFrom(com.google.protobuf.ByteString data)
+                throws com.google.protobuf.InvalidProtocolBufferException {
+                return newBuilder().mergeFrom(data).buildParsed();
+            }
+
+            public static com.example.tutorial.AddressBookProtos.Person.PhoneNumber parseFrom(com.google.protobuf.ByteString data,
+                                                                                              com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+                throws com.google.protobuf.InvalidProtocolBufferException {
+                return newBuilder().mergeFrom(data, extensionRegistry).buildParsed();
+            }
+
+            public static com.example.tutorial.AddressBookProtos.Person.PhoneNumber parseFrom(byte[] data)
+                throws com.google.protobuf.InvalidProtocolBufferException {
+                return newBuilder().mergeFrom(data).buildParsed();
+            }
+
+            public static com.example.tutorial.AddressBookProtos.Person.PhoneNumber parseFrom(byte[] data,
+                                                                                              com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+                throws com.google.protobuf.InvalidProtocolBufferException {
+                return newBuilder().mergeFrom(data, extensionRegistry).buildParsed();
+            }
+
+            public static com.example.tutorial.AddressBookProtos.Person.PhoneNumber parseFrom(java.io.InputStream input)
+                throws java.io.IOException {
+                return newBuilder().mergeFrom(input).buildParsed();
+            }
+
+            public static com.example.tutorial.AddressBookProtos.Person.PhoneNumber parseFrom(java.io.InputStream input,
+                                                                                              com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+                throws java.io.IOException {
+                return newBuilder().mergeFrom(input, extensionRegistry).buildParsed();
+            }
+
+            public static com.example.tutorial.AddressBookProtos.Person.PhoneNumber parseDelimitedFrom(java.io.InputStream input)
+                throws java.io.IOException {
+                Builder builder = newBuilder();
+                if (builder.mergeDelimitedFrom(input)) {
+                    return builder.buildParsed();
+                } else {
+                    return null;
+                }
+            }
+
+            public static com.example.tutorial.AddressBookProtos.Person.PhoneNumber parseDelimitedFrom(java.io.InputStream input,
+                                                                                                       com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+                throws java.io.IOException {
+                Builder builder = newBuilder();
+                if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+                    return builder.buildParsed();
+                } else {
+                    return null;
+                }
+            }
+
+            public static com.example.tutorial.AddressBookProtos.Person.PhoneNumber parseFrom(com.google.protobuf.CodedInputStream input)
+                throws java.io.IOException {
+                return newBuilder().mergeFrom(input).buildParsed();
+            }
+
+            public static com.example.tutorial.AddressBookProtos.Person.PhoneNumber parseFrom(com.google.protobuf.CodedInputStream input,
+                                                                                              com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+                throws java.io.IOException {
+                return newBuilder().mergeFrom(input, extensionRegistry).buildParsed();
+            }
+
+            public static Builder newBuilder() {
+                return Builder.create();
+            }
+
+            public Builder newBuilderForType() {
+                return newBuilder();
+            }
+
+            public static Builder newBuilder(com.example.tutorial.AddressBookProtos.Person.PhoneNumber prototype) {
+                return newBuilder().mergeFrom(prototype);
+            }
+
+            public Builder toBuilder() {
+                return newBuilder(this);
+            }
+
+            public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder<Builder> {
+                private com.example.tutorial.AddressBookProtos.Person.PhoneNumber result;
+
+                // Construct using com.example.tutorial.AddressBookProtos.Person.PhoneNumber.newBuilder()
+                private Builder() {
+                }
+
+                private static Builder create() {
+                    Builder builder = new Builder();
+                    builder.result = new com.example.tutorial.AddressBookProtos.Person.PhoneNumber();
+                    return builder;
+                }
+
+                protected com.example.tutorial.AddressBookProtos.Person.PhoneNumber internalGetResult() {
+                    return result;
+                }
+
+                public Builder clear() {
+                    if (result == null) {
+                        throw new IllegalStateException("Cannot call clear() after build().");
+                    }
+                    result = new com.example.tutorial.AddressBookProtos.Person.PhoneNumber();
+                    return this;
+                }
+
+                public Builder clone() {
+                    return create().mergeFrom(result);
+                }
+
+                public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() {
+                    return com.example.tutorial.AddressBookProtos.Person.PhoneNumber.getDescriptor();
+                }
+
+                public com.example.tutorial.AddressBookProtos.Person.PhoneNumber getDefaultInstanceForType() {
+                    return com.example.tutorial.AddressBookProtos.Person.PhoneNumber.getDefaultInstance();
+                }
+
+                public boolean isInitialized() {
+                    return result.isInitialized();
+                }
+
+                public com.example.tutorial.AddressBookProtos.Person.PhoneNumber build() {
+                    if (result != null && !isInitialized()) {
+                        throw newUninitializedMessageException(result);
+                    }
+                    return buildPartial();
+                }
+
+                private com.example.tutorial.AddressBookProtos.Person.PhoneNumber buildParsed()
+                    throws com.google.protobuf.InvalidProtocolBufferException {
+                    if (!isInitialized()) {
+                        throw newUninitializedMessageException(result).asInvalidProtocolBufferException();
+                    }
+                    return buildPartial();
+                }
+
+                public com.example.tutorial.AddressBookProtos.Person.PhoneNumber buildPartial() {
+                    if (result == null) {
+                        throw new IllegalStateException("build() has already been called on this Builder.");
+                    }
+                    com.example.tutorial.AddressBookProtos.Person.PhoneNumber returnMe = result;
+                    result = null;
+                    return returnMe;
+                }
+
+                public Builder mergeFrom(com.google.protobuf.Message other) {
+                    if (other instanceof com.example.tutorial.AddressBookProtos.Person.PhoneNumber) {
+                        return mergeFrom((com.example.tutorial.AddressBookProtos.Person.PhoneNumber)other);
+                    } else {
+                        super.mergeFrom(other);
+                        return this;
+                    }
+                }
+
+                public Builder mergeFrom(com.example.tutorial.AddressBookProtos.Person.PhoneNumber other) {
+                    if (other == com.example.tutorial.AddressBookProtos.Person.PhoneNumber.getDefaultInstance())
+                        return this;
+                    if (other.hasNumber()) {
+                        setNumber(other.getNumber());
+                    }
+                    if (other.hasType()) {
+                        setType(other.getType());
+                    }
+                    this.mergeUnknownFields(other.getUnknownFields());
+                    return this;
+                }
+
+                public Builder mergeFrom(com.google.protobuf.CodedInputStream input,
+                                         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+                    throws java.io.IOException {
+                    com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+                        com.google.protobuf.UnknownFieldSet.newBuilder(this.getUnknownFields());
+                    while (true) {
+                        int tag = input.readTag();
+                        switch (tag) {
+                            case 0:
+                                this.setUnknownFields(unknownFields.build());
+                                return this;
+                            default: {
+                                if (!parseUnknownField(input, unknownFields, extensionRegistry, tag)) {
+                                    this.setUnknownFields(unknownFields.build());
+                                    return this;
+                                }
+                                break;
+                            }
+                            case 10: {
+                                setNumber(input.readString());
+                                break;
+                            }
+                            case 16: {
+                                int rawValue = input.readEnum();
+                                com.example.tutorial.AddressBookProtos.Person.PhoneType value =
+                                    com.example.tutorial.AddressBookProtos.Person.PhoneType.valueOf(rawValue);
+                                if (value == null) {
+                                    unknownFields.mergeVarintField(2, rawValue);
+                                } else {
+                                    setType(value);
+                                }
+                                break;
+                            }
+                        }
+                    }
+                }
+
+                // required string number = 1;
+                public boolean hasNumber() {
+                    return result.hasNumber();
+                }
+
+                public java.lang.String getNumber() {
+                    return result.getNumber();
+                }
+
+                public Builder setNumber(java.lang.String value) {
+                    if (value == null) {
+                        throw new NullPointerException();
+                    }
+                    result.hasNumber = true;
+                    result.number_ = value;
+                    return this;
+                }
+
+                public Builder clearNumber() {
+                    result.hasNumber = false;
+                    result.number_ = getDefaultInstance().getNumber();
+                    return this;
+                }
+
+                // optional .tutorial.Person.PhoneType type = 2 [default = HOME];
+                public boolean hasType() {
+                    return result.hasType();
+                }
+
+                public com.example.tutorial.AddressBookProtos.Person.PhoneType getType() {
+                    return result.getType();
+                }
+
+                public Builder setType(com.example.tutorial.AddressBookProtos.Person.PhoneType value) {
+                    if (value == null) {
+                        throw new NullPointerException();
+                    }
+                    result.hasType = true;
+                    result.type_ = value;
+                    return this;
+                }
+
+                public Builder clearType() {
+                    result.hasType = false;
+                    result.type_ = com.example.tutorial.AddressBookProtos.Person.PhoneType.HOME;
+                    return this;
+                }
+
+                // @@protoc_insertion_point(builder_scope:tutorial.Person.PhoneNumber)
+            }
+
+            static {
+                defaultInstance = new PhoneNumber(true);
+                com.example.tutorial.AddressBookProtos.internalForceInit();
+                defaultInstance.initFields();
+            }
+
+            // @@protoc_insertion_point(class_scope:tutorial.Person.PhoneNumber)
+        }
+
+        // required string name = 1;
+        public static final int NAME_FIELD_NUMBER = 1;
+        private boolean hasName;
+        private java.lang.String name_ = "";
+
+        public boolean hasName() {
+            return hasName;
+        }
+
+        public java.lang.String getName() {
+            return name_;
+        }
+
+        // required int32 id = 2;
+        public static final int ID_FIELD_NUMBER = 2;
+        private boolean hasId;
+        private int id_ = 0;
+
+        public boolean hasId() {
+            return hasId;
+        }
+
+        public int getId() {
+            return id_;
+        }
+
+        // optional string email = 3;
+        public static final int EMAIL_FIELD_NUMBER = 3;
+        private boolean hasEmail;
+        private java.lang.String email_ = "";
+
+        public boolean hasEmail() {
+            return hasEmail;
+        }
+
+        public java.lang.String getEmail() {
+            return email_;
+        }
+
+        // repeated .tutorial.Person.PhoneNumber phone = 4;
+        public static final int PHONE_FIELD_NUMBER = 4;
+        private java.util.List<com.example.tutorial.AddressBookProtos.Person.PhoneNumber> phone_ =
+            java.util.Collections.emptyList();
+
+        public java.util.List<com.example.tutorial.AddressBookProtos.Person.PhoneNumber> getPhoneList() {
+            return phone_;
+        }
+
+        public int getPhoneCount() {
+            return phone_.size();
+        }
+
+        public com.example.tutorial.AddressBookProtos.Person.PhoneNumber getPhone(int index) {
+            return phone_.get(index);
+        }
+
+        private void initFields() {
+        }
+
+        public final boolean isInitialized() {
+            if (!hasName)
+                return false;
+            if (!hasId)
+                return false;
+            for (com.example.tutorial.AddressBookProtos.Person.PhoneNumber element : getPhoneList()) {
+                if (!element.isInitialized())
+                    return false;
+            }
+            return true;
+        }
+
+        public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException {
+            getSerializedSize();
+            if (hasName()) {
+                output.writeString(1, getName());
+            }
+            if (hasId()) {
+                output.writeInt32(2, getId());
+            }
+            if (hasEmail()) {
+                output.writeString(3, getEmail());
+            }
+            for (com.example.tutorial.AddressBookProtos.Person.PhoneNumber element : getPhoneList()) {
+                output.writeMessage(4, element);
+            }
+            getUnknownFields().writeTo(output);
+        }
+
+        private int memoizedSerializedSize = -1;
+
+        public int getSerializedSize() {
+            int size = memoizedSerializedSize;
+            if (size != -1)
+                return size;
+
+            size = 0;
+            if (hasName()) {
+                size += com.google.protobuf.CodedOutputStream.computeStringSize(1, getName());
+            }
+            if (hasId()) {
+                size += com.google.protobuf.CodedOutputStream.computeInt32Size(2, getId());
+            }
+            if (hasEmail()) {
+                size += com.google.protobuf.CodedOutputStream.computeStringSize(3, getEmail());
+            }
+            for (com.example.tutorial.AddressBookProtos.Person.PhoneNumber element : getPhoneList()) {
+                size += com.google.protobuf.CodedOutputStream.computeMessageSize(4, element);
+            }
+            size += getUnknownFields().getSerializedSize();
+            memoizedSerializedSize = size;
+            return size;
+        }
+
+        public static com.example.tutorial.AddressBookProtos.Person parseFrom(com.google.protobuf.ByteString data)
+            throws com.google.protobuf.InvalidProtocolBufferException {
+            return newBuilder().mergeFrom(data).buildParsed();
+        }
+
+        public static com.example.tutorial.AddressBookProtos.Person parseFrom(com.google.protobuf.ByteString data,
+                                                                              com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+            throws com.google.protobuf.InvalidProtocolBufferException {
+            return newBuilder().mergeFrom(data, extensionRegistry).buildParsed();
+        }
+
+        public static com.example.tutorial.AddressBookProtos.Person parseFrom(byte[] data)
+            throws com.google.protobuf.InvalidProtocolBufferException {
+            return newBuilder().mergeFrom(data).buildParsed();
+        }
+
+        public static com.example.tutorial.AddressBookProtos.Person parseFrom(byte[] data,
+                                                                              com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+            throws com.google.protobuf.InvalidProtocolBufferException {
+            return newBuilder().mergeFrom(data, extensionRegistry).buildParsed();
+        }
+
+        public static com.example.tutorial.AddressBookProtos.Person parseFrom(java.io.InputStream input)
+            throws java.io.IOException {
+            return newBuilder().mergeFrom(input).buildParsed();
+        }
+
+        public static com.example.tutorial.AddressBookProtos.Person parseFrom(java.io.InputStream input,
+                                                                              com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+            throws java.io.IOException {
+            return newBuilder().mergeFrom(input, extensionRegistry).buildParsed();
+        }
+
+        public static com.example.tutorial.AddressBookProtos.Person parseDelimitedFrom(java.io.InputStream input)
+            throws java.io.IOException {
+            Builder builder = newBuilder();
+            if (builder.mergeDelimitedFrom(input)) {
+                return builder.buildParsed();
+            } else {
+                return null;
+            }
+        }
+
+        public static com.example.tutorial.AddressBookProtos.Person parseDelimitedFrom(java.io.InputStream input,
+                                                                                       com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+            throws java.io.IOException {
+            Builder builder = newBuilder();
+            if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+                return builder.buildParsed();
+            } else {
+                return null;
+            }
+        }
+
+        public static com.example.tutorial.AddressBookProtos.Person parseFrom(com.google.protobuf.CodedInputStream input)
+            throws java.io.IOException {
+            return newBuilder().mergeFrom(input).buildParsed();
+        }
+
+        public static com.example.tutorial.AddressBookProtos.Person parseFrom(com.google.protobuf.CodedInputStream input,
+                                                                              com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+            throws java.io.IOException {
+            return newBuilder().mergeFrom(input, extensionRegistry).buildParsed();
+        }
+
+        public static Builder newBuilder() {
+            return Builder.create();
+        }
+
+        public Builder newBuilderForType() {
+            return newBuilder();
+        }
+
+        public static Builder newBuilder(com.example.tutorial.AddressBookProtos.Person prototype) {
+            return newBuilder().mergeFrom(prototype);
+        }
+
+        public Builder toBuilder() {
+            return newBuilder(this);
+        }
+
+        public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder<Builder> {
+            private com.example.tutorial.AddressBookProtos.Person result;
+
+            // Construct using com.example.tutorial.AddressBookProtos.Person.newBuilder()
+            private Builder() {
+            }
+
+            private static Builder create() {
+                Builder builder = new Builder();
+                builder.result = new com.example.tutorial.AddressBookProtos.Person();
+                return builder;
+            }
+
+            protected com.example.tutorial.AddressBookProtos.Person internalGetResult() {
+                return result;
+            }
+
+            public Builder clear() {
+                if (result == null) {
+                    throw new IllegalStateException("Cannot call clear() after build().");
+                }
+                result = new com.example.tutorial.AddressBookProtos.Person();
+                return this;
+            }
+
+            public Builder clone() {
+                return create().mergeFrom(result);
+            }
+
+            public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() {
+                return com.example.tutorial.AddressBookProtos.Person.getDescriptor();
+            }
+
+            public com.example.tutorial.AddressBookProtos.Person getDefaultInstanceForType() {
+                return com.example.tutorial.AddressBookProtos.Person.getDefaultInstance();
+            }
+
+            public boolean isInitialized() {
+                return result.isInitialized();
+            }
+
+            public com.example.tutorial.AddressBookProtos.Person build() {
+                if (result != null && !isInitialized()) {
+                    throw newUninitializedMessageException(result);
+                }
+                return buildPartial();
+            }
+
+            private com.example.tutorial.AddressBookProtos.Person buildParsed()
+                throws com.google.protobuf.InvalidProtocolBufferException {
+                if (!isInitialized()) {
+                    throw newUninitializedMessageException(result).asInvalidProtocolBufferException();
+                }
+                return buildPartial();
+            }
+
+            public com.example.tutorial.AddressBookProtos.Person buildPartial() {
+                if (result == null) {
+                    throw new IllegalStateException("build() has already been called on this Builder.");
+                }
+                if (result.phone_ != java.util.Collections.EMPTY_LIST) {
+                    result.phone_ = java.util.Collections.unmodifiableList(result.phone_);
+                }
+                com.example.tutorial.AddressBookProtos.Person returnMe = result;
+                result = null;
+                return returnMe;
+            }
+
+            public Builder mergeFrom(com.google.protobuf.Message other) {
+                if (other instanceof com.example.tutorial.AddressBookProtos.Person) {
+                    return mergeFrom((com.example.tutorial.AddressBookProtos.Person)other);
+                } else {
+                    super.mergeFrom(other);
+                    return this;
+                }
+            }
+
+            public Builder mergeFrom(com.example.tutorial.AddressBookProtos.Person other) {
+                if (other == com.example.tutorial.AddressBookProtos.Person.getDefaultInstance())
+                    return this;
+                if (other.hasName()) {
+                    setName(other.getName());
+                }
+                if (other.hasId()) {
+                    setId(other.getId());
+                }
+                if (other.hasEmail()) {
+                    setEmail(other.getEmail());
+                }
+                if (!other.phone_.isEmpty()) {
+                    if (result.phone_.isEmpty()) {
+                        result.phone_ =
+                            new java.util.ArrayList<com.example.tutorial.AddressBookProtos.Person.PhoneNumber>();
+                    }
+                    result.phone_.addAll(other.phone_);
+                }
+                this.mergeUnknownFields(other.getUnknownFields());
+                return this;
+            }
+
+            public Builder mergeFrom(com.google.protobuf.CodedInputStream input,
+                                     com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+                throws java.io.IOException {
+                com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+                    com.google.protobuf.UnknownFieldSet.newBuilder(this.getUnknownFields());
+                while (true) {
+                    int tag = input.readTag();
+                    switch (tag) {
+                        case 0:
+                            this.setUnknownFields(unknownFields.build());
+                            return this;
+                        default: {
+                            if (!parseUnknownField(input, unknownFields, extensionRegistry, tag)) {
+                                this.setUnknownFields(unknownFields.build());
+                                return this;
+                            }
+                            break;
+                        }
+                        case 10: {
+                            setName(input.readString());
+                            break;
+                        }
+                        case 16: {
+                            setId(input.readInt32());
+                            break;
+                        }
+                        case 26: {
+                            setEmail(input.readString());
+                            break;
+                        }
+                        case 34: {
+                            com.example.tutorial.AddressBookProtos.Person.PhoneNumber.Builder subBuilder =
+                                com.example.tutorial.AddressBookProtos.Person.PhoneNumber.newBuilder();
+                            input.readMessage(subBuilder, extensionRegistry);
+                            addPhone(subBuilder.buildPartial());
+                            break;
+                        }
+                    }
+                }
+            }
+
+            // required string name = 1;
+            public boolean hasName() {
+                return result.hasName();
+            }
+
+            public java.lang.String getName() {
+                return result.getName();
+            }
+
+            public Builder setName(java.lang.String value) {
+                if (value == null) {
+                    throw new NullPointerException();
+                }
+                result.hasName = true;
+                result.name_ = value;
+                return this;
+            }
+
+            public Builder clearName() {
+                result.hasName = false;
+                result.name_ = getDefaultInstance().getName();
+                return this;
+            }
+
+            // required int32 id = 2;
+            public boolean hasId() {
+                return result.hasId();
+            }
+
+            public int getId() {
+                return result.getId();
+            }
+
+            public Builder setId(int value) {
+                result.hasId = true;
+                result.id_ = value;
+                return this;
+            }
+
+            public Builder clearId() {
+                result.hasId = false;
+                result.id_ = 0;
+                return this;
+            }
+
+            // optional string email = 3;
+            public boolean hasEmail() {
+                return result.hasEmail();
+            }
+
+            public java.lang.String getEmail() {
+                return result.getEmail();
+            }
+
+            public Builder setEmail(java.lang.String value) {
+                if (value == null) {
+                    throw new NullPointerException();
+                }
+                result.hasEmail = true;
+                result.email_ = value;
+                return this;
+            }
+
+            public Builder clearEmail() {
+                result.hasEmail = false;
+                result.email_ = getDefaultInstance().getEmail();
+                return this;
+            }
+
+            // repeated .tutorial.Person.PhoneNumber phone = 4;
+            public java.util.List<com.example.tutorial.AddressBookProtos.Person.PhoneNumber> getPhoneList() {
+                return java.util.Collections.unmodifiableList(result.phone_);
+            }
+
+            public int getPhoneCount() {
+                return result.getPhoneCount();
+            }
+
+            public com.example.tutorial.AddressBookProtos.Person.PhoneNumber getPhone(int index) {
+                return result.getPhone(index);
+            }
+
+            public Builder setPhone(int index, com.example.tutorial.AddressBookProtos.Person.PhoneNumber value) {
+                if (value == null) {
+                    throw new NullPointerException();
+                }
+                result.phone_.set(index, value);
+                return this;
+            }
+
+            public Builder setPhone(int index,
+                                    com.example.tutorial.AddressBookProtos.Person.PhoneNumber.Builder builderForValue) {
+                result.phone_.set(index, builderForValue.build());
+                return this;
+            }
+
+            public Builder addPhone(com.example.tutorial.AddressBookProtos.Person.PhoneNumber value) {
+                if (value == null) {
+                    throw new NullPointerException();
+                }
+                if (result.phone_.isEmpty()) {
+                    result.phone_ =
+                        new java.util.ArrayList<com.example.tutorial.AddressBookProtos.Person.PhoneNumber>();
+                }
+                result.phone_.add(value);
+                return this;
+            }
+
+            public Builder addPhone(com.example.tutorial.AddressBookProtos.Person.PhoneNumber.Builder builderForValue) {
+                if (result.phone_.isEmpty()) {
+                    result.phone_ =
+                        new java.util.ArrayList<com.example.tutorial.AddressBookProtos.Person.PhoneNumber>();
+                }
+                result.phone_.add(builderForValue.build());
+                return this;
+            }
+
+            public Builder addAllPhone(java.lang.Iterable<? extends com.example.tutorial.AddressBookProtos.Person.PhoneNumber> values) {
+                if (result.phone_.isEmpty()) {
+                    result.phone_ =
+                        new java.util.ArrayList<com.example.tutorial.AddressBookProtos.Person.PhoneNumber>();
+                }
+                super.addAll(values, result.phone_);
+                return this;
+            }
+
+            public Builder clearPhone() {
+                result.phone_ = java.util.Collections.emptyList();
+                return this;
+            }
+
+            // @@protoc_insertion_point(builder_scope:tutorial.Person)
+        }
+
+        static {
+            defaultInstance = new Person(true);
+            com.example.tutorial.AddressBookProtos.internalForceInit();
+            defaultInstance.initFields();
+        }
+
+        // @@protoc_insertion_point(class_scope:tutorial.Person)
+    }
+
+    public static final class AddressBook extends com.google.protobuf.GeneratedMessage {
+        // Use AddressBook.newBuilder() to construct.
+        private AddressBook() {
+            initFields();
+        }
+
+        private AddressBook(boolean noInit) {
+        }
+
+        private static final AddressBook defaultInstance;
+
+        public static AddressBook getDefaultInstance() {
+            return defaultInstance;
+        }
+
+        public AddressBook getDefaultInstanceForType() {
+            return defaultInstance;
+        }
+
+        public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() {
+            return com.example.tutorial.AddressBookProtos.internal_static_tutorial_AddressBook_descriptor;
+        }
+
+        protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() {
+            return com.example.tutorial.AddressBookProtos.internal_static_tutorial_AddressBook_fieldAccessorTable;
+        }
+
+        // repeated .tutorial.Person person = 1;
+        public static final int PERSON_FIELD_NUMBER = 1;
+        private java.util.List<com.example.tutorial.AddressBookProtos.Person> person_ = java.util.Collections
+            .emptyList();
+
+        public java.util.List<com.example.tutorial.AddressBookProtos.Person> getPersonList() {
+            return person_;
+        }
+
+        public int getPersonCount() {
+            return person_.size();
+        }
+
+        public com.example.tutorial.AddressBookProtos.Person getPerson(int index) {
+            return person_.get(index);
+        }
+
+        private void initFields() {
+        }
+
+        public final boolean isInitialized() {
+            for (com.example.tutorial.AddressBookProtos.Person element : getPersonList()) {
+                if (!element.isInitialized())
+                    return false;
+            }
+            return true;
+        }
+
+        public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException {
+            getSerializedSize();
+            for (com.example.tutorial.AddressBookProtos.Person element : getPersonList()) {
+                output.writeMessage(1, element);
+            }
+            getUnknownFields().writeTo(output);
+        }
+
+        private int memoizedSerializedSize = -1;
+
+        public int getSerializedSize() {
+            int size = memoizedSerializedSize;
+            if (size != -1)
+                return size;
+
+            size = 0;
+            for (com.example.tutorial.AddressBookProtos.Person element : getPersonList()) {
+                size += com.google.protobuf.CodedOutputStream.computeMessageSize(1, element);
+            }
+            size += getUnknownFields().getSerializedSize();
+            memoizedSerializedSize = size;
+            return size;
+        }
+
+        public static com.example.tutorial.AddressBookProtos.AddressBook parseFrom(com.google.protobuf.ByteString data)
+            throws com.google.protobuf.InvalidProtocolBufferException {
+            return newBuilder().mergeFrom(data).buildParsed();
+        }
+
+        public static com.example.tutorial.AddressBookProtos.AddressBook parseFrom(com.google.protobuf.ByteString data,
+                                                                                   com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+            throws com.google.protobuf.InvalidProtocolBufferException {
+            return newBuilder().mergeFrom(data, extensionRegistry).buildParsed();
+        }
+
+        public static com.example.tutorial.AddressBookProtos.AddressBook parseFrom(byte[] data)
+            throws com.google.protobuf.InvalidProtocolBufferException {
+            return newBuilder().mergeFrom(data).buildParsed();
+        }
+
+        public static com.example.tutorial.AddressBookProtos.AddressBook parseFrom(byte[] data,
+                                                                                   com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+            throws com.google.protobuf.InvalidProtocolBufferException {
+            return newBuilder().mergeFrom(data, extensionRegistry).buildParsed();
+        }
+
+        public static com.example.tutorial.AddressBookProtos.AddressBook parseFrom(java.io.InputStream input)
+            throws java.io.IOException {
+            return newBuilder().mergeFrom(input).buildParsed();
+        }
+
+        public static com.example.tutorial.AddressBookProtos.AddressBook parseFrom(java.io.InputStream input,
+                                                                                   com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+            throws java.io.IOException {
+            return newBuilder().mergeFrom(input, extensionRegistry).buildParsed();
+        }
+
+        public static com.example.tutorial.AddressBookProtos.AddressBook parseDelimitedFrom(java.io.InputStream input)
+            throws java.io.IOException {
+            Builder builder = newBuilder();
+            if (builder.mergeDelimitedFrom(input)) {
+                return builder.buildParsed();
+            } else {
+                return null;
+            }
+        }
+
+        public static com.example.tutorial.AddressBookProtos.AddressBook parseDelimitedFrom(java.io.InputStream input,
+                                                                                            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+            throws java.io.IOException {
+            Builder builder = newBuilder();
+            if (builder.mergeDelimitedFrom(input, extensionRegistry)) {
+                return builder.buildParsed();
+            } else {
+                return null;
+            }
+        }
+
+        public static com.example.tutorial.AddressBookProtos.AddressBook parseFrom(com.google.protobuf.CodedInputStream input)
+            throws java.io.IOException {
+            return newBuilder().mergeFrom(input).buildParsed();
+        }
+
+        public static com.example.tutorial.AddressBookProtos.AddressBook parseFrom(com.google.protobuf.CodedInputStream input,
+                                                                                   com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+            throws java.io.IOException {
+            return newBuilder().mergeFrom(input, extensionRegistry).buildParsed();
+        }
+
+        public static Builder newBuilder() {
+            return Builder.create();
+        }
+
+        public Builder newBuilderForType() {
+            return newBuilder();
+        }
+
+        public static Builder newBuilder(com.example.tutorial.AddressBookProtos.AddressBook prototype) {
+            return newBuilder().mergeFrom(prototype);
+        }
+
+        public Builder toBuilder() {
+            return newBuilder(this);
+        }
+
+        public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder<Builder> {
+            private com.example.tutorial.AddressBookProtos.AddressBook result;
+
+            // Construct using com.example.tutorial.AddressBookProtos.AddressBook.newBuilder()
+            private Builder() {
+            }
+
+            private static Builder create() {
+                Builder builder = new Builder();
+                builder.result = new com.example.tutorial.AddressBookProtos.AddressBook();
+                return builder;
+            }
+
+            protected com.example.tutorial.AddressBookProtos.AddressBook internalGetResult() {
+                return result;
+            }
+
+            public Builder clear() {
+                if (result == null) {
+                    throw new IllegalStateException("Cannot call clear() after build().");
+                }
+                result = new com.example.tutorial.AddressBookProtos.AddressBook();
+                return this;
+            }
+
+            public Builder clone() {
+                return create().mergeFrom(result);
+            }
+
+            public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() {
+                return com.example.tutorial.AddressBookProtos.AddressBook.getDescriptor();
+            }
+
+            public com.example.tutorial.AddressBookProtos.AddressBook getDefaultInstanceForType() {
+                return com.example.tutorial.AddressBookProtos.AddressBook.getDefaultInstance();
+            }
+
+            public boolean isInitialized() {
+                return result.isInitialized();
+            }
+
+            public com.example.tutorial.AddressBookProtos.AddressBook build() {
+                if (result != null && !isInitialized()) {
+                    throw newUninitializedMessageException(result);
+                }
+                return buildPartial();
+            }
+
+            private com.example.tutorial.AddressBookProtos.AddressBook buildParsed()
+                throws com.google.protobuf.InvalidProtocolBufferException {
+                if (!isInitialized()) {
+                    throw newUninitializedMessageException(result).asInvalidProtocolBufferException();
+                }
+                return buildPartial();
+            }
+
+            public com.example.tutorial.AddressBookProtos.AddressBook buildPartial() {
+                if (result == null) {
+                    throw new IllegalStateException("build() has already been called on this Builder.");
+                }
+                if (result.person_ != java.util.Collections.EMPTY_LIST) {
+                    result.person_ = java.util.Collections.unmodifiableList(result.person_);
+                }
+                com.example.tutorial.AddressBookProtos.AddressBook returnMe = result;
+                result = null;
+                return returnMe;
+            }
+
+            public Builder mergeFrom(com.google.protobuf.Message other) {
+                if (other instanceof com.example.tutorial.AddressBookProtos.AddressBook) {
+                    return mergeFrom((com.example.tutorial.AddressBookProtos.AddressBook)other);
+                } else {
+                    super.mergeFrom(other);
+                    return this;
+                }
+            }
+
+            public Builder mergeFrom(com.example.tutorial.AddressBookProtos.AddressBook other) {
+                if (other == com.example.tutorial.AddressBookProtos.AddressBook.getDefaultInstance())
+                    return this;
+                if (!other.person_.isEmpty()) {
+                    if (result.person_.isEmpty()) {
+                        result.person_ = new java.util.ArrayList<com.example.tutorial.AddressBookProtos.Person>();
+                    }
+                    result.person_.addAll(other.person_);
+                }
+                this.mergeUnknownFields(other.getUnknownFields());
+                return this;
+            }
+
+            public Builder mergeFrom(com.google.protobuf.CodedInputStream input,
+                                     com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+                throws java.io.IOException {
+                com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+                    com.google.protobuf.UnknownFieldSet.newBuilder(this.getUnknownFields());
+                while (true) {
+                    int tag = input.readTag();
+                    switch (tag) {
+                        case 0:
+                            this.setUnknownFields(unknownFields.build());
+                            return this;
+                        default: {
+                            if (!parseUnknownField(input, unknownFields, extensionRegistry, tag)) {
+                                this.setUnknownFields(unknownFields.build());
+                                return this;
+                            }
+                            break;
+                        }
+                        case 10: {
+                            com.example.tutorial.AddressBookProtos.Person.Builder subBuilder =
+                                com.example.tutorial.AddressBookProtos.Person.newBuilder();
+                            input.readMessage(subBuilder, extensionRegistry);
+                            addPerson(subBuilder.buildPartial());
+                            break;
+                        }
+                    }
+                }
+            }
+
+            // repeated .tutorial.Person person = 1;
+            public java.util.List<com.example.tutorial.AddressBookProtos.Person> getPersonList() {
+                return java.util.Collections.unmodifiableList(result.person_);
+            }
+
+            public int getPersonCount() {
+                return result.getPersonCount();
+            }
+
+            public com.example.tutorial.AddressBookProtos.Person getPerson(int index) {
+                return result.getPerson(index);
+            }
+
+            public Builder setPerson(int index, com.example.tutorial.AddressBookProtos.Person value) {
+                if (value == null) {
+                    throw new NullPointerException();
+                }
+                result.person_.set(index, value);
+                return this;
+            }
+
+            public Builder setPerson(int index, com.example.tutorial.AddressBookProtos.Person.Builder builderForValue) {
+                result.person_.set(index, builderForValue.build());
+                return this;
+            }
+
+            public Builder addPerson(com.example.tutorial.AddressBookProtos.Person value) {
+                if (value == null) {
+                    throw new NullPointerException();
+                }
+                if (result.person_.isEmpty()) {
+                    result.person_ = new java.util.ArrayList<com.example.tutorial.AddressBookProtos.Person>();
+                }
+                result.person_.add(value);
+                return this;
+            }
+
+            public Builder addPerson(com.example.tutorial.AddressBookProtos.Person.Builder builderForValue) {
+                if (result.person_.isEmpty()) {
+                    result.person_ = new java.util.ArrayList<com.example.tutorial.AddressBookProtos.Person>();
+                }
+                result.person_.add(builderForValue.build());
+                return this;
+            }
+
+            public Builder addAllPerson(java.lang.Iterable<? extends com.example.tutorial.AddressBookProtos.Person> values) {
+                if (result.person_.isEmpty()) {
+                    result.person_ = new java.util.ArrayList<com.example.tutorial.AddressBookProtos.Person>();
+                }
+                super.addAll(values, result.person_);
+                return this;
+            }
+
+            public Builder clearPerson() {
+                result.person_ = java.util.Collections.emptyList();
+                return this;
+            }
+
+            // @@protoc_insertion_point(builder_scope:tutorial.AddressBook)
+        }
+
+        static {
+            defaultInstance = new AddressBook(true);
+            com.example.tutorial.AddressBookProtos.internalForceInit();
+            defaultInstance.initFields();
+        }
+
+        // @@protoc_insertion_point(class_scope:tutorial.AddressBook)
+    }
+
+    private static com.google.protobuf.Descriptors.Descriptor internal_static_tutorial_Person_descriptor;
+    private static com.google.protobuf.GeneratedMessage.FieldAccessorTable internal_static_tutorial_Person_fieldAccessorTable;
+    private static com.google.protobuf.Descriptors.Descriptor internal_static_tutorial_Person_PhoneNumber_descriptor;
+    private static com.google.protobuf.GeneratedMessage.FieldAccessorTable internal_static_tutorial_Person_PhoneNumber_fieldAccessorTable;
+    private static com.google.protobuf.Descriptors.Descriptor internal_static_tutorial_AddressBook_descriptor;
+    private static com.google.protobuf.GeneratedMessage.FieldAccessorTable internal_static_tutorial_AddressBook_fieldAccessorTable;
+
+    public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() {
+        return descriptor;
+    }
+
+    private static com.google.protobuf.Descriptors.FileDescriptor descriptor;
+    static {
+        java.lang.String[] descriptorData =
+            {"\n\021addressbook.proto\022\010tutorial\"\332\001\n\006Person" + "\022\014\n\004name\030\001 \002(\t\022\n\n\002id\030\002 \002(\005\022\r\n\005email\030\003 \001("
+                + "\t\022+\n\005phone\030\004 \003(\0132\034.tutorial.Person.Phone"
+                + "Number\032M\n\013PhoneNumber\022\016\n\006number\030\001 \002(\t\022.\n"
+                + "\004type\030\002 \001(\0162\032.tutorial.Person.PhoneType:"
+                + "\004HOME\"+\n\tPhoneType\022\n\n\006MOBILE\020\000\022\010\n\004HOME\020\001"
+                + "\022\010\n\004WORK\020\002\"/\n\013AddressBook\022 \n\006person\030\001 \003("
+                + "\0132\020.tutorial.PersonB)\n\024com.example.tutor"
+                + "ialB\021AddressBookProtos"};
+        com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
+            new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
+                public com.google.protobuf.ExtensionRegistry assignDescriptors(com.google.protobuf.Descriptors.FileDescriptor root) {
+                    descriptor = root;
+                    internal_static_tutorial_Person_descriptor = getDescriptor().getMessageTypes().get(0);
+                    internal_static_tutorial_Person_fieldAccessorTable =
+                        new com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+                                                                                    internal_static_tutorial_Person_descriptor,
+                                                                                    new java.lang.String[] {"Name",
+                                                                                                            "Id",
+                                                                                                            "Email",
+                                                                                                            "Phone",},
+                                                                                    com.example.tutorial.AddressBookProtos.Person.class,
+                                                                                    com.example.tutorial.AddressBookProtos.Person.Builder.class);
+                    internal_static_tutorial_Person_PhoneNumber_descriptor =
+                        internal_static_tutorial_Person_descriptor.getNestedTypes().get(0);
+                    internal_static_tutorial_Person_PhoneNumber_fieldAccessorTable =
+                        new com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+                                                                                    internal_static_tutorial_Person_PhoneNumber_descriptor,
+                                                                                    new java.lang.String[] {"Number",
+                                                                                                            "Type",},
+                                                                                    com.example.tutorial.AddressBookProtos.Person.PhoneNumber.class,
+                                                                                    com.example.tutorial.AddressBookProtos.Person.PhoneNumber.Builder.class);
+                    internal_static_tutorial_AddressBook_descriptor = getDescriptor().getMessageTypes().get(1);
+                    internal_static_tutorial_AddressBook_fieldAccessorTable =
+                        new com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+                                                                                    internal_static_tutorial_AddressBook_descriptor,
+                                                                                    new java.lang.String[] {"Person",},
+                                                                                    com.example.tutorial.AddressBookProtos.AddressBook.class,
+                                                                                    com.example.tutorial.AddressBookProtos.AddressBook.Builder.class);
+                    return null;
+                }
+            };
+        com.google.protobuf.Descriptors.FileDescriptor
+            .internalBuildGeneratedFileFrom(descriptorData,
+                                            new com.google.protobuf.Descriptors.FileDescriptor[] {},
+                                            assigner);
+    }
+
+    public static void internalForceInit() {
+    }
+
+    // @@protoc_insertion_point(outer_class_scope)
+}
diff --git a/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/src/test/java/org/apache/tuscany/sca/databinding/protobuf/ProtobufTransformationTestCase.java b/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/src/test/java/org/apache/tuscany/sca/databinding/protobuf/ProtobufTransformationTestCase.java
new file mode 100644
index 0000000000..9fc6f30794
--- /dev/null
+++ b/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/src/test/java/org/apache/tuscany/sca/databinding/protobuf/ProtobufTransformationTestCase.java
@@ -0,0 +1,63 @@
+/*
+ * 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.tuscany.sca.databinding.protobuf;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+
+import junit.framework.Assert;
+
+import org.apache.tuscany.sca.databinding.TransformationContext;
+import org.apache.tuscany.sca.databinding.impl.TransformationContextImpl;
+import org.apache.tuscany.sca.interfacedef.DataType;
+import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl;
+import org.junit.Test;
+
+import com.example.tutorial.AddressBookProtos.AddressBook;
+import com.example.tutorial.AddressBookProtos.Person;
+
+/**
+ * 
+ */
+public class ProtobufTransformationTestCase {
+    @Test
+    public void testTransform() throws Exception {
+        Protobuf2OutputStream t1 = new Protobuf2OutputStream();
+        TransformationContext context = new TransformationContextImpl();
+        DataType dt1 = new DataTypeImpl(AddressBook.class, null);
+        context.setSourceDataType(dt1);
+
+        AddressBook addressBook =
+            AddressBook.newBuilder()
+                .addPerson(Person.newBuilder().setId(1).setEmail("abc@example.com").setName("John Smith").build())
+                .build();
+
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        t1.transform(addressBook, bos, context);
+
+        InputStream2Protobuf t2 = new InputStream2Protobuf();
+        context.setSourceDataType(null);
+        context.setTargetDataType(dt1);
+
+        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
+        AddressBook addressBook2 = (AddressBook)t2.transform(bis, context);
+        Assert.assertEquals(addressBook, addressBook2);
+    }
+}
diff --git a/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/src/test/resources/addressbook.proto b/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/src/test/resources/addressbook.proto
new file mode 100644
index 0000000000..395320fb22
--- /dev/null
+++ b/sca-java-2.x/trunk/contrib/modules/databinding-protobuf/src/test/resources/addressbook.proto
@@ -0,0 +1,48 @@
+//
+// 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.    
+//
+// See README.txt for information and build instructions.
+
+package tutorial;
+
+option java_package = "com.example.tutorial";
+option java_outer_classname = "AddressBookProtos";
+
+message Person {
+  required string name = 1;
+  required int32 id = 2;        // Unique ID number for this person.
+  optional string email = 3;
+
+  enum PhoneType {
+    MOBILE = 0;
+    HOME = 1;
+    WORK = 2;
+  }
+
+  message PhoneNumber {
+    required string number = 1;
+    optional PhoneType type = 2 [default = HOME];
+  }
+
+  repeated PhoneNumber phone = 4;
+}
+
+// Our address book file is just one of these.
+message AddressBook {
+  repeated Person person = 1;
+}