Fix ConstraintViolationImpl.equals

Returned true for two constraints with different paths.
Could have thrown NullPointerException in some cases.

Bug-Link: https://github.com/gwtproject/gwt/issues/6531
Change-Id: I928ada3b8decac5a45ff309a1d13787d21a47784
diff --git a/user/src/com/google/gwt/validation/client/impl/ConstraintViolationImpl.java b/user/src/com/google/gwt/validation/client/impl/ConstraintViolationImpl.java
index ad2ad1b..097ffeb 100644
--- a/user/src/com/google/gwt/validation/client/impl/ConstraintViolationImpl.java
+++ b/user/src/com/google/gwt/validation/client/impl/ConstraintViolationImpl.java
@@ -17,6 +17,7 @@
 
 import java.io.Serializable;
 import java.lang.annotation.ElementType;
+import java.util.Objects;
 
 import javax.validation.ConstraintViolation;
 import javax.validation.Path;
@@ -150,14 +151,12 @@
       return false;
     }
     ConstraintViolationImpl<?> other = (ConstraintViolationImpl<?>) o;
-    return (message == null ? other.message == null : message.equals(other.message)
-        && propertyPath == null ? other.propertyPath == null :
-          propertyPath.equals(other.propertyPath)
-        && rootBean == null ? other.rootBean == null : rootBean.equals(other.rootBean)
-        && leafBean == null ? other.leafBean == null : leafBean.equals(other.leafBean)
-        && elementType == null ? other.elementType == null : elementType.equals(other.elementType)
-        && invalidValue == null ? other.invalidValue == null :
-          invalidValue.equals(other.invalidValue));
+    return Objects.equals(message, other.message)
+        && Objects.equals(propertyPath, other.propertyPath)
+        && Objects.equals(rootBean, other.rootBean)
+        && Objects.equals(leafBean, other.leafBean)
+        && Objects.equals(elementType, other.elementType)
+        && Objects.equals(invalidValue, other.invalidValue);
   }
 
   @Override
diff --git a/user/test/com/google/gwt/validation/ValidationClientJreSuite.java b/user/test/com/google/gwt/validation/ValidationClientJreSuite.java
index 72f166d..4b6fb16 100644
--- a/user/test/com/google/gwt/validation/ValidationClientJreSuite.java
+++ b/user/test/com/google/gwt/validation/ValidationClientJreSuite.java
@@ -15,6 +15,7 @@
  */
 package com.google.gwt.validation;
 
+import com.google.gwt.validation.client.impl.ConstraintViolationImplTest;
 import com.google.gwt.validation.client.impl.NodeImplTest;
 import com.google.gwt.validation.client.impl.PathImplTest;
 import com.google.gwt.validation.client.impl.metadata.ValidationGroupsMetadataTest;
@@ -33,6 +34,7 @@
     suite.addTestSuite(PathImplTest.class);
     suite.addTestSuite(NodeImplTest.class);
     suite.addTestSuite(ValidationGroupsMetadataTest.class);
+    suite.addTestSuite(ConstraintViolationImplTest.class);
     return suite;
   }
 }
diff --git a/user/test/com/google/gwt/validation/client/impl/ConstraintViolationImplTest.java b/user/test/com/google/gwt/validation/client/impl/ConstraintViolationImplTest.java
new file mode 100644
index 0000000..55ba3f1
--- /dev/null
+++ b/user/test/com/google/gwt/validation/client/impl/ConstraintViolationImplTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Licensed 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 com.google.gwt.validation.client.impl;
+
+import junit.framework.TestCase;
+
+import javax.validation.ConstraintViolation;
+
+/**
+ * Tests for {@link ConstraintViolationImpl}.
+ */
+public class ConstraintViolationImplTest extends TestCase {
+
+  public <T> void testEquals() throws Exception {
+    String constraintMessage = "May not be null";
+    String path = "path";
+    ConstraintViolation<T> a = createViolation(constraintMessage, path);
+    ConstraintViolation<T> b = createViolation(constraintMessage, path);
+    assertTrue(a.equals(b));
+  }
+
+  public <T> void testNotEquals() throws Exception {
+    String constraintMessage = "May not be null";
+    ConstraintViolation<T> a = createViolation(constraintMessage, "path 1");
+    ConstraintViolation<T> b = createViolation(constraintMessage, "path 2");
+    assertFalse(a.equals(b));
+  }
+
+  private <T> ConstraintViolation<T> createViolation(String msg, final String path) {
+    return new ConstraintViolationImpl.Builder<T>()
+        .setMessage(msg)
+        .setRootBean(null)
+        .setPropertyPath(new PathImpl().append(path))
+        .build();
+  }
+
+}