From aeb6f86bcdec061ee9c6be96066fa19c56523490 Mon Sep 17 00:00:00 2001 From: Felipe Adorno Date: Sun, 3 May 2015 15:59:00 -0300 Subject: [PATCH] EqualsExlcude notation, HashCodeExclude notation and ToStringExludeNotation --- .../commons/lang3/builder/EqualsBuilder.java | 3 +- .../commons/lang3/builder/EqualsExclude.java | 33 ++++++++++ .../lang3/builder/HashCodeBuilder.java | 3 +- .../lang3/builder/HashCodeExclude.java | 33 ++++++++++ .../builder/ReflectionToStringBuilder.java | 3 + .../lang3/builder/ToStringExclude.java | 33 ++++++++++ .../lang3/builder/EqualsBuilderTest.java | 32 ++++++++++ .../lang3/builder/HashCodeBuilderTest.java | 47 ++++++++++++++ ...tringBuilderExcludeWithAnnotationTest.java | 63 +++++++++++++++++++ 9 files changed, 248 insertions(+), 2 deletions(-) create mode 100755 src/main/java/org/apache/commons/lang3/builder/EqualsExclude.java create mode 100755 src/main/java/org/apache/commons/lang3/builder/HashCodeExclude.java create mode 100755 src/main/java/org/apache/commons/lang3/builder/ToStringExclude.java create mode 100755 src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeWithAnnotationTest.java diff --git a/src/main/java/org/apache/commons/lang3/builder/EqualsBuilder.java b/src/main/java/org/apache/commons/lang3/builder/EqualsBuilder.java index b44976632..be8f4f1ce 100644 --- a/src/main/java/org/apache/commons/lang3/builder/EqualsBuilder.java +++ b/src/main/java/org/apache/commons/lang3/builder/EqualsBuilder.java @@ -411,7 +411,8 @@ public class EqualsBuilder implements Builder { 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) { diff --git a/src/main/java/org/apache/commons/lang3/builder/EqualsExclude.java b/src/main/java/org/apache/commons/lang3/builder/EqualsExclude.java new file mode 100755 index 000000000..bbe2bb01b --- /dev/null +++ b/src/main/java/org/apache/commons/lang3/builder/EqualsExclude.java @@ -0,0 +1,33 @@ +/* + * 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. + * @author Felipe Adorno (felipeadsc@gmail.com) + */ +@Retention(RUNTIME) +@Target(ElementType.FIELD) +public @interface EqualsExclude { + +} diff --git a/src/main/java/org/apache/commons/lang3/builder/HashCodeBuilder.java b/src/main/java/org/apache/commons/lang3/builder/HashCodeBuilder.java index 537b9f579..fbbd110a6 100644 --- a/src/main/java/org/apache/commons/lang3/builder/HashCodeBuilder.java +++ b/src/main/java/org/apache/commons/lang3/builder/HashCodeBuilder.java @@ -192,7 +192,8 @@ public class HashCodeBuilder implements Builder { 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); diff --git a/src/main/java/org/apache/commons/lang3/builder/HashCodeExclude.java b/src/main/java/org/apache/commons/lang3/builder/HashCodeExclude.java new file mode 100755 index 000000000..2984808bb --- /dev/null +++ b/src/main/java/org/apache/commons/lang3/builder/HashCodeExclude.java @@ -0,0 +1,33 @@ +/* + * 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. + * @author Felipe Adorno (felipeadsc@gmail.com) + */ +@Retention(RUNTIME) +@Target(ElementType.FIELD) +public @interface HashCodeExclude { + +} diff --git a/src/main/java/org/apache/commons/lang3/builder/ReflectionToStringBuilder.java b/src/main/java/org/apache/commons/lang3/builder/ReflectionToStringBuilder.java index 5b992bd53..59044699e 100644 --- a/src/main/java/org/apache/commons/lang3/builder/ReflectionToStringBuilder.java +++ b/src/main/java/org/apache/commons/lang3/builder/ReflectionToStringBuilder.java @@ -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; } diff --git a/src/main/java/org/apache/commons/lang3/builder/ToStringExclude.java b/src/main/java/org/apache/commons/lang3/builder/ToStringExclude.java new file mode 100755 index 000000000..b0bf98a56 --- /dev/null +++ b/src/main/java/org/apache/commons/lang3/builder/ToStringExclude.java @@ -0,0 +1,33 @@ +/* + * 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. + * @author Felipe Adorno (felipeadsc@gmail.com) + */ +@Retention(RUNTIME) +@Target(ElementType.FIELD) +public @interface ToStringExclude { + +} diff --git a/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderTest.java b/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderTest.java index 30e2e22f3..702c5a2c8 100644 --- a/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderTest.java +++ b/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderTest.java @@ -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)); + } + } diff --git a/src/test/java/org/apache/commons/lang3/builder/HashCodeBuilderTest.java b/src/test/java/org/apache/commons/lang3/builder/HashCodeBuilderTest.java index 12aba9ee3..9009fbde4 100644 --- a/src/test/java/org/apache/commons/lang3/builder/HashCodeBuilderTest.java +++ b/src/test/java/org/apache/commons/lang3/builder/HashCodeBuilderTest.java @@ -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)); + } + } diff --git a/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeWithAnnotationTest.java b/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeWithAnnotationTest.java new file mode 100755 index 000000000..c01d3b814 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeWithAnnotationTest.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.commons.lang3.builder; + +import org.apache.commons.lang3.ArrayUtils; +import org.junit.Assert; +import org.junit.Test; + +/** + * Test class for ToStringExclude annotation + * @author Felipe Adorno (felipeadsc@gmail.com) + * @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); + } +}