Browse Source

Fix Java maps reflection to call onChange to populate changes to parent
builders.

Change-Id: Ibf6ae3c0fe6bc31f74b8018c81a5af461b1c24ea

Jisi Liu 10 years ago
parent
commit
20042b72da

+ 27 - 23
java/src/main/java/com/google/protobuf/GeneratedMessage.java

@@ -73,7 +73,7 @@ public abstract class GeneratedMessage extends AbstractMessage
 
   /** For use by generated code only.  */
   protected UnknownFieldSet unknownFields;
-  
+
   protected GeneratedMessage() {
     unknownFields = UnknownFieldSet.getDefaultInstance();
   }
@@ -549,12 +549,12 @@ public abstract class GeneratedMessage extends AbstractMessage
      * Gets the map field with the given field number. This method should be
      * overridden in the generated message class if the message contains map
      * fields.
-     * 
+     *
      * Unlike other field types, reflection support for map fields can't be
      * implemented based on generated public API because we need to access a
      * map field as a list in reflection API but the generated API only allows
      * us to access it as a map. This method returns the underlying map field
-     * directly and thus enables us to access the map field as a list. 
+     * directly and thus enables us to access the map field as a list.
      */
     @SuppressWarnings({"unused", "rawtypes"})
     protected MapField internalGetMapField(int fieldNumber) {
@@ -683,7 +683,7 @@ public abstract class GeneratedMessage extends AbstractMessage
     public final <Type> Type getExtension(
         final ExtensionLite<MessageType, Type> extensionLite) {
       Extension<MessageType, Type> extension = checkNotLite(extensionLite);
-      
+
       verifyExtensionContainingType(extension);
       FieldDescriptor descriptor = extension.getDescriptor();
       final Object value = extensions.getField(descriptor);
@@ -1313,7 +1313,7 @@ public abstract class GeneratedMessage extends AbstractMessage
       implements ExtensionDescriptorRetriever {
     private volatile FieldDescriptor descriptor;
     protected abstract FieldDescriptor loadDescriptor();
-    
+
     public FieldDescriptor getDescriptor() {
       if (descriptor == null) {
         synchronized (this) {
@@ -1651,17 +1651,17 @@ public abstract class GeneratedMessage extends AbstractMessage
       }
     }
   }
-  
+
   /**
    * Gets the map field with the given field number. This method should be
    * overridden in the generated message class if the message contains map
    * fields.
-   * 
+   *
    * Unlike other field types, reflection support for map fields can't be
    * implemented based on generated public API because we need to access a
    * map field as a list in reflection API but the generated API only allows
    * us to access it as a map. This method returns the underlying map field
-   * directly and thus enables us to access the map field as a list. 
+   * directly and thus enables us to access the map field as a list.
    */
   @SuppressWarnings({"rawtypes", "unused"})
   protected MapField internalGetMapField(int fieldNumber) {
@@ -1709,7 +1709,7 @@ public abstract class GeneratedMessage extends AbstractMessage
       oneofs = new OneofAccessor[descriptor.getOneofs().size()];
       initialized = false;
     }
-    
+
     private boolean isMapFieldEnabled(FieldDescriptor field) {
       boolean result = true;
       return result;
@@ -1934,11 +1934,11 @@ public abstract class GeneratedMessage extends AbstractMessage
       protected final FieldDescriptor field;
       protected final boolean isOneofField;
       protected final boolean hasHasMethod;
-      
+
       private int getOneofFieldNumber(final GeneratedMessage message) {
         return ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber();
       }
-      
+
       private int getOneofFieldNumber(final GeneratedMessage.Builder builder) {
         return ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber();
       }
@@ -2130,15 +2130,15 @@ public abstract class GeneratedMessage extends AbstractMessage
 
       private final FieldDescriptor field;
       private final Message mapEntryMessageDefaultInstance;
-      
+
       private MapField<?, ?> getMapField(GeneratedMessage message) {
         return (MapField<?, ?>) message.internalGetMapField(field.getNumber());
       }
-      
+
       private MapField<?, ?> getMapField(GeneratedMessage.Builder builder) {
         return (MapField<?, ?>) builder.internalGetMapField(field.getNumber());
       }
-      
+
       public Object get(GeneratedMessage message) {
         List result = new ArrayList();
         for (int i = 0; i < getRepeatedCount(message); i++) {
@@ -2171,10 +2171,12 @@ public abstract class GeneratedMessage extends AbstractMessage
       }
 
       public void setRepeated(Builder builder, int index, Object value) {
+        builder.onChanged();
         getMapField(builder).getMutableList().set(index, (Message) value);
       }
 
       public void addRepeated(Builder builder, Object value) {
+        builder.onChanged();
         getMapField(builder).getMutableList().add((Message) value);
       }
 
@@ -2197,6 +2199,7 @@ public abstract class GeneratedMessage extends AbstractMessage
       }
 
       public void clear(Builder builder) {
+        builder.onChanged();
         getMapField(builder).getMutableList().clear();
       }
 
@@ -2208,7 +2211,7 @@ public abstract class GeneratedMessage extends AbstractMessage
         throw new UnsupportedOperationException(
             "Nested builder not supported for map fields.");
       }
-      
+
       public com.google.protobuf.Message.Builder getRepeatedBuilder(
           Builder builder, int index) {
         throw new UnsupportedOperationException(
@@ -2226,7 +2229,7 @@ public abstract class GeneratedMessage extends AbstractMessage
           final Class<? extends Builder> builderClass,
           final String containingOneofCamelCaseName) {
         super(descriptor, camelCaseName, messageClass, builderClass, containingOneofCamelCaseName);
-        
+
         enumDescriptor = descriptor.getEnumType();
 
         valueOfMethod = getMethodOrDie(type, "valueOf",
@@ -2244,12 +2247,12 @@ public abstract class GeneratedMessage extends AbstractMessage
               getMethodOrDie(builderClass, "set" + camelCaseName + "Value", int.class);
         }
       }
-      
+
       private EnumDescriptor enumDescriptor;
 
       private Method valueOfMethod;
       private Method getValueDescriptorMethod;
-      
+
       private boolean supportUnknownEnumValue;
       private Method getValueMethod;
       private Method getValueMethodBuilder;
@@ -2291,7 +2294,7 @@ public abstract class GeneratedMessage extends AbstractMessage
           final Class<? extends GeneratedMessage> messageClass,
           final Class<? extends Builder> builderClass) {
         super(descriptor, camelCaseName, messageClass, builderClass);
-        
+
         enumDescriptor = descriptor.getEnumType();
 
         valueOfMethod = getMethodOrDie(type, "valueOf",
@@ -2315,7 +2318,7 @@ public abstract class GeneratedMessage extends AbstractMessage
 
       private final Method valueOfMethod;
       private final Method getValueDescriptorMethod;
-      
+
       private boolean supportUnknownEnumValue;
       private Method getRepeatedValueMethod;
       private Method getRepeatedValueMethodBuilder;
@@ -2395,7 +2398,8 @@ public abstract class GeneratedMessage extends AbstractMessage
           final Class<? extends GeneratedMessage> messageClass,
           final Class<? extends Builder> builderClass,
           final String containingOneofCamelCaseName) {
-        super(descriptor, camelCaseName, messageClass, builderClass, containingOneofCamelCaseName);
+        super(descriptor, camelCaseName, messageClass, builderClass,
+            containingOneofCamelCaseName);
 
         newBuilderMethod = getMethodOrDie(type, "newBuilder");
         getBuilderMethodBuilder =
@@ -2492,7 +2496,7 @@ public abstract class GeneratedMessage extends AbstractMessage
   protected Object writeReplace() throws ObjectStreamException {
     return new GeneratedMessageLite.SerializedForm(this);
   }
-  
+
   /**
    * Checks that the {@link Extension} is non-Lite and returns it as a
    * {@link GeneratedExtension}.
@@ -2503,7 +2507,7 @@ public abstract class GeneratedMessage extends AbstractMessage
     if (extension.isLite()) {
       throw new IllegalArgumentException("Expected non-lite extension.");
     }
-    
+
     return (Extension<MessageType, T>) extension;
   }
 }

+ 105 - 66
java/src/test/java/com/google/protobuf/MapTest.java

@@ -57,22 +57,22 @@ public class MapTest extends TestCase {
     builder.getMutableInt32ToStringField().put(1, "11");
     builder.getMutableInt32ToStringField().put(2, "22");
     builder.getMutableInt32ToStringField().put(3, "33");
-    
+
     builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("11"));
     builder.getMutableInt32ToBytesField().put(2, TestUtil.toBytes("22"));
     builder.getMutableInt32ToBytesField().put(3, TestUtil.toBytes("33"));
-    
+
     builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.FOO);
     builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.BAR);
     builder.getMutableInt32ToEnumField().put(3, TestMap.EnumValue.BAZ);
-    
+
     builder.getMutableInt32ToMessageField().put(
         1, MessageValue.newBuilder().setValue(11).build());
     builder.getMutableInt32ToMessageField().put(
         2, MessageValue.newBuilder().setValue(22).build());
     builder.getMutableInt32ToMessageField().put(
         3, MessageValue.newBuilder().setValue(33).build());
-    
+
     builder.getMutableStringToInt32Field().put("1", 11);
     builder.getMutableStringToInt32Field().put("2", 22);
     builder.getMutableStringToInt32Field().put("3", 33);
@@ -88,22 +88,22 @@ public class MapTest extends TestCase {
     assertEquals("11", message.getInt32ToStringField().get(1));
     assertEquals("22", message.getInt32ToStringField().get(2));
     assertEquals("33", message.getInt32ToStringField().get(3));
-    
+
     assertEquals(3, message.getInt32ToBytesField().size());
     assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesField().get(1));
     assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesField().get(2));
     assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
-    
+
     assertEquals(3, message.getInt32ToEnumField().size());
     assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(1));
     assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(2));
     assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
-    
+
     assertEquals(3, message.getInt32ToMessageField().size());
     assertEquals(11, message.getInt32ToMessageField().get(1).getValue());
     assertEquals(22, message.getInt32ToMessageField().get(2).getValue());
     assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
-    
+
     assertEquals(3, message.getStringToInt32Field().size());
     assertEquals(11, message.getStringToInt32Field().get("1").intValue());
     assertEquals(22, message.getStringToInt32Field().get("2").intValue());
@@ -118,21 +118,21 @@ public class MapTest extends TestCase {
     builder.getMutableInt32ToStringField().put(1, "111");
     builder.getMutableInt32ToStringField().remove(2);
     builder.getMutableInt32ToStringField().put(4, "44");
-    
+
     builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("111"));
     builder.getMutableInt32ToBytesField().remove(2);
     builder.getMutableInt32ToBytesField().put(4, TestUtil.toBytes("44"));
-    
+
     builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.BAR);
     builder.getMutableInt32ToEnumField().remove(2);
     builder.getMutableInt32ToEnumField().put(4, TestMap.EnumValue.QUX);
-    
+
     builder.getMutableInt32ToMessageField().put(
         1, MessageValue.newBuilder().setValue(111).build());
     builder.getMutableInt32ToMessageField().remove(2);
     builder.getMutableInt32ToMessageField().put(
         4, MessageValue.newBuilder().setValue(44).build());
-    
+
     builder.getMutableStringToInt32Field().put("1", 111);
     builder.getMutableStringToInt32Field().remove("2");
     builder.getMutableStringToInt32Field().put("4", 44);
@@ -148,22 +148,22 @@ public class MapTest extends TestCase {
     assertEquals("111", message.getInt32ToStringField().get(1));
     assertEquals("33", message.getInt32ToStringField().get(3));
     assertEquals("44", message.getInt32ToStringField().get(4));
-    
+
     assertEquals(3, message.getInt32ToBytesField().size());
     assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesField().get(1));
     assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
     assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesField().get(4));
-    
+
     assertEquals(3, message.getInt32ToEnumField().size());
     assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
     assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
     assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumField().get(4));
-    
+
     assertEquals(3, message.getInt32ToMessageField().size());
     assertEquals(111, message.getInt32ToMessageField().get(1).getValue());
     assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
     assertEquals(44, message.getInt32ToMessageField().get(4).getValue());
-    
+
     assertEquals(3, message.getStringToInt32Field().size());
     assertEquals(111, message.getStringToInt32Field().get("1").intValue());
     assertEquals(33, message.getStringToInt32Field().get("3").intValue());
@@ -183,17 +183,17 @@ public class MapTest extends TestCase {
     TestMap.Builder builder = TestMap.newBuilder();
     TestMap message = builder.build();
     assertMapValuesCleared(message);
-    
+
     builder = message.toBuilder();
     setMapValues(builder);
     message = builder.build();
     assertMapValuesSet(message);
-    
+
     builder = message.toBuilder();
     updateMapValues(builder);
     message = builder.build();
     assertMapValuesUpdated(message);
-    
+
     builder = message.toBuilder();
     builder.clear();
     message = builder.build();
@@ -207,14 +207,14 @@ public class MapTest extends TestCase {
     assertEquals(message.getSerializedSize(), message.toByteString().size());
     message = TestMap.PARSER.parseFrom(message.toByteString());
     assertMapValuesSet(message);
-    
+
     builder = message.toBuilder();
     updateMapValues(builder);
     message = builder.build();
     assertEquals(message.getSerializedSize(), message.toByteString().size());
     message = TestMap.PARSER.parseFrom(message.toByteString());
     assertMapValuesUpdated(message);
-    
+
     builder = message.toBuilder();
     builder.clear();
     message = builder.build();
@@ -222,12 +222,12 @@ public class MapTest extends TestCase {
     message = TestMap.PARSER.parseFrom(message.toByteString());
     assertMapValuesCleared(message);
   }
-  
+
   public void testMergeFrom() throws Exception {
     TestMap.Builder builder = TestMap.newBuilder();
     setMapValues(builder);
     TestMap message = builder.build();
-    
+
     TestMap.Builder other = TestMap.newBuilder();
     other.mergeFrom(message);
     assertMapValuesSet(other.build());
@@ -236,7 +236,7 @@ public class MapTest extends TestCase {
   public void testEqualsAndHashCode() throws Exception {
     // Test that generated equals() and hashCode() will disregard the order
     // of map entries when comparing/hashing map fields.
-    
+
     // We can't control the order of elements in a HashMap. The best we can do
     // here is to add elements in different order.
     TestMap.Builder b1 = TestMap.newBuilder();
@@ -244,23 +244,23 @@ public class MapTest extends TestCase {
     b1.getMutableInt32ToInt32Field().put(3, 4);
     b1.getMutableInt32ToInt32Field().put(5, 6);
     TestMap m1 = b1.build();
-    
+
     TestMap.Builder b2 = TestMap.newBuilder();
     b2.getMutableInt32ToInt32Field().put(5, 6);
     b2.getMutableInt32ToInt32Field().put(1, 2);
     b2.getMutableInt32ToInt32Field().put(3, 4);
     TestMap m2 = b2.build();
-    
+
     assertEquals(m1, m2);
     assertEquals(m1.hashCode(), m2.hashCode());
-    
+
     // Make sure we did compare map fields.
     b2.getMutableInt32ToInt32Field().put(1, 0);
     m2 = b2.build();
     assertFalse(m1.equals(m2));
     // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
     // to be different.
-    
+
     // Regression test for b/18549190: if a map is a subset of the other map,
     // equals() should return false.
     b2.getMutableInt32ToInt32Field().remove(1);
@@ -268,57 +268,96 @@ public class MapTest extends TestCase {
     assertFalse(m1.equals(m2));
     assertFalse(m2.equals(m1));
   }
-  
-  
+
+
   public void testNestedBuilderOnChangeEventPropagation() {
     TestOnChangeEventPropagation.Builder parent =
         TestOnChangeEventPropagation.newBuilder();
     parent.getOptionalMessageBuilder().getMutableInt32ToInt32Field().put(1, 2);
     TestOnChangeEventPropagation message = parent.build();
     assertEquals(2, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
-    
+
     // Make a change using nested builder.
     parent.getOptionalMessageBuilder().getMutableInt32ToInt32Field().put(1, 3);
-    
+
     // Should be able to observe the change.
     message = parent.build();
     assertEquals(3, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
-    
+
     // Make another change using mergeFrom()
     TestMap.Builder other = TestMap.newBuilder();
     other.getMutableInt32ToInt32Field().put(1, 4);
     parent.getOptionalMessageBuilder().mergeFrom(other.build());
-    
+
     // Should be able to observe the change.
     message = parent.build();
     assertEquals(4, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
-    
+
     // Make yet another change by clearing the nested builder.
     parent.getOptionalMessageBuilder().clear();
-    
+
     // Should be able to observe the change.
     message = parent.build();
     assertEquals(0, message.getOptionalMessage().getInt32ToInt32Field().size());
   }
-  
+
+  public void testNestedBuilderOnChangeEventPropagationReflection() {
+    FieldDescriptor intMapField = f("int32_to_int32_field");
+    // Create an outer message builder with nested builder.
+    TestOnChangeEventPropagation.Builder parentBuilder =
+        TestOnChangeEventPropagation.newBuilder();
+    TestMap.Builder testMapBuilder = parentBuilder.getOptionalMessageBuilder();
+
+    // Create a map entry message.
+    TestMap.Builder entryBuilder = TestMap.newBuilder();
+    entryBuilder.getMutableInt32ToInt32Field().put(1, 1);
+
+    // Put the entry into the nested builder.
+    testMapBuilder.addRepeatedField(
+        intMapField, entryBuilder.getRepeatedField(intMapField, 0));
+
+    // Should be able to observe the change.
+    TestOnChangeEventPropagation message = parentBuilder.build();
+    assertEquals(1, message.getOptionalMessage().getInt32ToInt32Field().size());
+
+    // Change the entry value.
+    entryBuilder.getMutableInt32ToInt32Field().put(1, 4);
+    testMapBuilder = parentBuilder.getOptionalMessageBuilder();
+    testMapBuilder.setRepeatedField(
+        intMapField, 0, entryBuilder.getRepeatedField(intMapField, 0));
+
+    // Should be able to observe the change.
+    message = parentBuilder.build();
+    assertEquals(4,
+        message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
+
+    // Clear the nested builder.
+    testMapBuilder = parentBuilder.getOptionalMessageBuilder();
+    testMapBuilder.clearField(intMapField);
+
+    // Should be able to observe the change.
+    message = parentBuilder.build();
+    assertEquals(0, message.getOptionalMessage().getInt32ToInt32Field().size());
+  }
+
   // The following methods are used to test reflection API.
-  
+
   private static FieldDescriptor f(String name) {
     return TestMap.getDescriptor().findFieldByName(name);
   }
-  
+
   private static Object getFieldValue(Message mapEntry, String name) {
     FieldDescriptor field = mapEntry.getDescriptorForType().findFieldByName(name);
     return mapEntry.getField(field);
   }
-  
+
   private static Message.Builder setFieldValue(
       Message.Builder mapEntry, String name, Object value) {
     FieldDescriptor field = mapEntry.getDescriptorForType().findFieldByName(name);
     mapEntry.setField(field, value);
     return mapEntry;
   }
-  
+
   private static void assertHasMapValues(Message message, String name, Map<?, ?> values) {
     FieldDescriptor field = f(name);
     for (Object entry : (List<?>) message.getField(field)) {
@@ -337,7 +376,7 @@ public class MapTest extends TestCase {
       assertEquals(value, values.get(key));
     }
   }
-  
+
   private static <KeyType, ValueType>
   Message newMapEntry(Message.Builder builder, String name, KeyType key, ValueType value) {
     FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name);
@@ -348,7 +387,7 @@ public class MapTest extends TestCase {
     entryBuilder.setField(valueField, value);
     return entryBuilder.build();
   }
-  
+
   private static void setMapValues(Message.Builder builder, String name, Map<?, ?> values) {
     List<Message> entryList = new ArrayList<Message>();
     for (Map.Entry<?, ?> entry : values.entrySet()) {
@@ -357,7 +396,7 @@ public class MapTest extends TestCase {
     FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name);
     builder.setField(field, entryList);
   }
-  
+
   private static <KeyType, ValueType>
   Map<KeyType, ValueType> mapForValues(
       KeyType key1, ValueType value1, KeyType key2, ValueType value2) {
@@ -385,14 +424,14 @@ public class MapTest extends TestCase {
         mapForValues(
             11, MessageValue.newBuilder().setValue(22).build(),
             33, MessageValue.newBuilder().setValue(44).build()));
-    
+
     // Test clearField()
     builder.clearField(f("int32_to_int32_field"));
     builder.clearField(f("int32_to_message_field"));
     message = builder.build();
     assertEquals(0, message.getInt32ToInt32Field().size());
     assertEquals(0, message.getInt32ToMessageField().size());
-    
+
     // Test setField()
     setMapValues(builder, "int32_to_int32_field",
         mapForValues(11, 22, 33, 44));
@@ -405,7 +444,7 @@ public class MapTest extends TestCase {
     assertEquals(44, message.getInt32ToInt32Field().get(33).intValue());
     assertEquals(222, message.getInt32ToMessageField().get(111).getValue());
     assertEquals(444, message.getInt32ToMessageField().get(333).getValue());
-    
+
     // Test addRepeatedField
     builder.addRepeatedField(f("int32_to_int32_field"),
         newMapEntry(builder, "int32_to_int32_field", 55, 66));
@@ -425,7 +464,7 @@ public class MapTest extends TestCase {
     message = builder.build();
     assertEquals(55, message.getInt32ToInt32Field().get(55).intValue());
     assertEquals(555, message.getInt32ToMessageField().get(555).getValue());
-    
+
     // Test setRepeatedField
     for (int i = 0; i < builder.getRepeatedFieldCount(f("int32_to_int32_field")); i++) {
       Message mapEntry = (Message) builder.getRepeatedField(f("int32_to_int32_field"), i);
@@ -442,35 +481,35 @@ public class MapTest extends TestCase {
     assertEquals(33, message.getInt32ToInt32Field().get(44).intValue());
     assertEquals(55, message.getInt32ToInt32Field().get(55).intValue());
   }
-  
+
   public void testTextFormat() throws Exception {
     TestMap.Builder builder = TestMap.newBuilder();
     setMapValues(builder);
     TestMap message = builder.build();
-    
+
     String textData = TextFormat.printToString(message);
-    
+
     builder = TestMap.newBuilder();
     TextFormat.merge(textData, builder);
     message = builder.build();
-    
+
     assertMapValuesSet(message);
   }
-  
+
   public void testDynamicMessage() throws Exception {
     TestMap.Builder builder = TestMap.newBuilder();
     setMapValues(builder);
     TestMap message = builder.build();
-    
+
     Message dynamicDefaultInstance =
         DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
     Message dynamicMessage = dynamicDefaultInstance
         .newBuilderForType().mergeFrom(message.toByteString()).build();
-    
+
     assertEquals(message, dynamicMessage);
     assertEquals(message.hashCode(), dynamicMessage.hashCode());
   }
-  
+
   public void testReflectionEqualsAndHashCode() throws Exception {
     // Test that generated equals() and hashCode() will disregard the order
     // of map entries when comparing/hashing map fields.
@@ -479,22 +518,22 @@ public class MapTest extends TestCase {
     Message dynamicDefaultInstance =
         DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
     FieldDescriptor field = f("int32_to_int32_field");
-    
+
     Message.Builder b1 = dynamicDefaultInstance.newBuilderForType();
     b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 1, 2));
     b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 3, 4));
     b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 5, 6));
     Message m1 = b1.build();
-    
+
     Message.Builder b2 = dynamicDefaultInstance.newBuilderForType();
     b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 5, 6));
     b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 1, 2));
     b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 3, 4));
     Message m2 = b2.build();
-    
+
     assertEquals(m1, m2);
     assertEquals(m1.hashCode(), m2.hashCode());
-    
+
     // Make sure we did compare map fields.
     b2.setRepeatedField(field, 0, newMapEntry(b1, "int32_to_int32_field", 0, 0));
     m2 = b2.build();
@@ -502,7 +541,7 @@ public class MapTest extends TestCase {
     // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
     // to be different.
   }
-  
+
   public void testUnknownEnumValues() throws Exception {
     TestMap.Builder builder = TestMap.newBuilder();
     builder.getMutableInt32ToEnumFieldValue().put(0, 0);
@@ -517,7 +556,7 @@ public class MapTest extends TestCase {
     assertEquals(TestMap.EnumValue.UNRECOGNIZED,
         message.getInt32ToEnumField().get(2));
     assertEquals(1000, message.getInt32ToEnumFieldValue().get(2).intValue());
-    
+
     // Unknown enum values should be preserved after:
     //   1. Serialization and parsing.
     //   2. toBuild().
@@ -528,7 +567,7 @@ public class MapTest extends TestCase {
     assertEquals(1000, builder.getInt32ToEnumFieldValue().get(2).intValue());
     builder = TestMap.newBuilder().mergeFrom(message);
     assertEquals(1000, builder.getInt32ToEnumFieldValue().get(2).intValue());
-    
+
     // hashCode()/equals() should take unknown enum values into account.
     builder.getMutableInt32ToEnumFieldValue().put(2, 1001);
     TestMap message2 = builder.build();
@@ -538,17 +577,17 @@ public class MapTest extends TestCase {
     // should be the same.
     assertTrue(message.getInt32ToEnumField().equals(message2.getInt32ToEnumField()));
   }
-  
+
   public void testUnknownEnumValuesInReflectionApi() throws Exception {
     Descriptor descriptor = TestMap.getDescriptor();
     EnumDescriptor enumDescriptor = TestMap.EnumValue.getDescriptor();
     FieldDescriptor field = descriptor.findFieldByName("int32_to_enum_field");
-    
+
     Map<Integer, Integer> data = new HashMap<Integer, Integer>();
     data.put(0, 0);
     data.put(1, 1);
     data.put(2, 1000);  // unknown value.
-    
+
     TestMap.Builder builder = TestMap.newBuilder();
     for (Map.Entry<Integer, Integer> entry : data.entrySet()) {
       builder.getMutableInt32ToEnumFieldValue().put(entry.getKey(), entry.getValue());