Merge branch 'LANG-1031'
LANG-1031: Add annotations to exclude fields from ReflectionEqualsBuilder, ReflectionToStringBuilder and ReflectionHashCodeBuilder. Thanks to Felipe Adorno. This closes #29, #77.
This commit is contained in:
commit
8548b12d8f
3
pom.xml
3
pom.xml
|
@ -478,6 +478,9 @@
|
|||
<contributor>
|
||||
<name>Michał Kordas</name>
|
||||
</contributor>
|
||||
<contributor>
|
||||
<name>Felipe Adorno</name>
|
||||
</contributor>
|
||||
</contributors>
|
||||
|
||||
<!-- Lang should depend on very little -->
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
<body>
|
||||
|
||||
<release version="3.5" date="tba" description="tba">
|
||||
<action issue="LANG-1031" type="add" dev="britter" due-to="Felipe Adorno">Add annotations to exclude fields from ReflectionEqualsBuilder, ReflectionToStringBuilder and ReflectionHashCodeBuilder</action>
|
||||
<action issue="LANG-1127" type="add" dev="chas">Unit test helpers which set and reset default Locale and TimeZone</action>
|
||||
<action issue="LANG-1128" type="fix" dev="britter" due-to="jacktan1991">JsonToStringStyle doesn't handle chars and objects correctly</action>
|
||||
<action issue="LANG-456" type="fix" dev="britter" due-to="Bob Fields, Woosan Ko, Bruno P. Kinoshita">HashCodeBuilder throws StackOverflowError in bidirectional navigable association</action>
|
||||
|
|
|
@ -411,7 +411,8 @@ public class EqualsBuilder implements Builder<Boolean> {
|
|||
if (!ArrayUtils.contains(excludeFields, f.getName())
|
||||
&& !f.getName().contains("$")
|
||||
&& (useTransients || !Modifier.isTransient(f.getModifiers()))
|
||||
&& !Modifier.isStatic(f.getModifiers())) {
|
||||
&& (!Modifier.isStatic(f.getModifiers()))
|
||||
&& (!f.isAnnotationPresent(EqualsExclude.class))) {
|
||||
try {
|
||||
builder.append(f.get(lhs), f.get(rhs));
|
||||
} catch (final IllegalAccessException e) {
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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.commons.lang3.builder;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
/**
|
||||
* Use this annotation to builds a equals excluding the annotated field.
|
||||
*/
|
||||
@Retention(RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface EqualsExclude {
|
||||
|
||||
}
|
|
@ -192,7 +192,8 @@ public class HashCodeBuilder implements Builder<Integer> {
|
|||
if (!ArrayUtils.contains(excludeFields, field.getName())
|
||||
&& !field.getName().contains("$")
|
||||
&& (useTransients || !Modifier.isTransient(field.getModifiers()))
|
||||
&& !Modifier.isStatic(field.getModifiers())) {
|
||||
&& (!Modifier.isStatic(field.getModifiers()))
|
||||
&& (!field.isAnnotationPresent(HashCodeExclude.class))) {
|
||||
try {
|
||||
final Object fieldValue = field.get(object);
|
||||
builder.append(fieldValue);
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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.commons.lang3.builder;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
/**
|
||||
* Use this annotation to builds a hash code excluding the annotated field.
|
||||
*/
|
||||
@Retention(RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface HashCodeExclude {
|
||||
|
||||
}
|
|
@ -494,6 +494,9 @@ public class ReflectionToStringBuilder extends ToStringBuilder {
|
|||
// Reject fields from the getExcludeFieldNames list.
|
||||
return false;
|
||||
}
|
||||
if(field.isAnnotationPresent(ToStringExclude.class)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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.commons.lang3.builder;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
/**
|
||||
* Use this annotation to builds a String excluding the annotated field.
|
||||
*/
|
||||
@Retention(RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface ToStringExclude {
|
||||
|
||||
}
|
|
@ -1150,5 +1150,37 @@ public class EqualsBuilderTest {
|
|||
assertTrue(EqualsBuilder.reflectionEquals(d1, d3));
|
||||
}
|
||||
|
||||
static class TestObjectEqualsExclude {
|
||||
@EqualsExclude
|
||||
private int a;
|
||||
private int b;
|
||||
|
||||
public TestObjectEqualsExclude(int a, int b) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public int getA() {
|
||||
return a;
|
||||
}
|
||||
|
||||
public int getB() {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToEqualsExclude() {
|
||||
TestObjectEqualsExclude one = new TestObjectEqualsExclude(1, 2);
|
||||
TestObjectEqualsExclude two = new TestObjectEqualsExclude(1, 3);
|
||||
|
||||
assertFalse(EqualsBuilder.reflectionEquals(one, two));
|
||||
|
||||
one = new TestObjectEqualsExclude(1, 2);
|
||||
two = new TestObjectEqualsExclude(2, 2);
|
||||
|
||||
assertTrue(EqualsBuilder.reflectionEquals(one, two));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -622,4 +622,51 @@ public class HashCodeBuilderTest {
|
|||
hcb.toHashCode(), hcb.hashCode());
|
||||
}
|
||||
|
||||
static class TestObjectHashCodeExclude {
|
||||
@HashCodeExclude
|
||||
private int a;
|
||||
private int b;
|
||||
|
||||
public TestObjectHashCodeExclude(int a, int b) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public int getA() {
|
||||
return a;
|
||||
}
|
||||
|
||||
public int getB() {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
static class TestObjectHashCodeExclude2 {
|
||||
@HashCodeExclude
|
||||
private int a;
|
||||
@HashCodeExclude
|
||||
private int b;
|
||||
|
||||
public TestObjectHashCodeExclude2(int a, int b) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public int getA() {
|
||||
return a;
|
||||
}
|
||||
|
||||
public int getB() {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToHashCodeExclude() {
|
||||
TestObjectHashCodeExclude one = new TestObjectHashCodeExclude(1, 2);
|
||||
TestObjectHashCodeExclude2 two = new TestObjectHashCodeExclude2(1, 2);
|
||||
assertEquals(17 * 37 + 2, HashCodeBuilder.reflectionHashCode(one));
|
||||
assertEquals(17, HashCodeBuilder.reflectionHashCode(two));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* 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.commons.lang3.builder;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Test class for ToStringExclude annotation
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ReflectionToStringBuilderExcludeWithAnnotationTest {
|
||||
|
||||
class TestFixture {
|
||||
@ToStringExclude
|
||||
private final String secretField = SECRET_VALUE;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final String showField = NOT_SECRET_VALUE;
|
||||
}
|
||||
|
||||
private static final String NOT_SECRET_FIELD = "showField";
|
||||
|
||||
private static final String NOT_SECRET_VALUE = "Hello World!";
|
||||
|
||||
private static final String SECRET_FIELD = "secretField";
|
||||
|
||||
private static final String SECRET_VALUE = "secret value";
|
||||
|
||||
@Test
|
||||
public void test_toStringExclude() {
|
||||
final String toString = ReflectionToStringBuilder.toString(new TestFixture());
|
||||
this.validateSecretFieldAbsent(toString);
|
||||
}
|
||||
|
||||
private void validateNonSecretField(final String toString) {
|
||||
Assert.assertTrue(toString.indexOf(NOT_SECRET_FIELD) > ArrayUtils.INDEX_NOT_FOUND);
|
||||
Assert.assertTrue(toString.indexOf(NOT_SECRET_VALUE) > ArrayUtils.INDEX_NOT_FOUND);
|
||||
}
|
||||
|
||||
private void validateSecretFieldAbsent(final String toString) {
|
||||
Assert.assertEquals(ArrayUtils.INDEX_NOT_FOUND, toString.indexOf(SECRET_FIELD));
|
||||
Assert.assertEquals(ArrayUtils.INDEX_NOT_FOUND, toString.indexOf(SECRET_VALUE));
|
||||
this.validateNonSecretField(toString);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue