Skip to content

Commit

Permalink
Added @IgnoreDefaultEqualsAndToString annotation that allows by-pass …
Browse files Browse the repository at this point in the history
…Groovy equals and toString methods for Map and Collection objects
  • Loading branch information
pditommaso committed Jun 25, 2017
1 parent 5492f93 commit 8a9f43b
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 0 deletions.
37 changes: 37 additions & 0 deletions src/main/groovy/lang/IgnoreDefaultEqualsAndToString.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* 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 groovy.lang;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Classes marked with this {@link IgnoreDefaultEqualsAndToString} annotation
* by-pass the default groovy formatting and equality rules and allowing
* a user to provide a custom format and equals method
*
* @author Paolo Di Tommaso <[email protected]>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface IgnoreDefaultEqualsAndToString {
}
Original file line number Diff line number Diff line change
Expand Up @@ -12026,6 +12026,9 @@ public static boolean equals(List left, List right) {
if (left == right) {
return true;
}
if( left.getClass().getAnnotation(IgnoreDefaultEqualsAndToString.class)!=null && right.getClass().getAnnotation(IgnoreDefaultEqualsAndToString.class)!=null ) {
return left.equals(right);
}
if (left.size() != right.size()) {
return false;
}
Expand Down Expand Up @@ -12078,6 +12081,9 @@ public static <T> boolean equals(Set<T> self, Set<T> other) {
if (self == other) {
return true;
}
if( self.getClass().getAnnotation(IgnoreDefaultEqualsAndToString.class)!=null && other.getClass().getAnnotation(IgnoreDefaultEqualsAndToString.class)!=null ) {
return self.equals(other);
}
if (self.size() != other.size()) {
return false;
}
Expand Down Expand Up @@ -12122,6 +12128,9 @@ public static boolean equals(Map self, Map other) {
if (self == other) {
return true;
}
if( self.getClass().getAnnotation(IgnoreDefaultEqualsAndToString.class)!=null && other.getClass().getAnnotation(IgnoreDefaultEqualsAndToString.class)!=null ) {
return self.equals(other);
}
if (self.size() != other.size()) {
return false;
}
Expand Down
7 changes: 7 additions & 0 deletions src/main/org/codehaus/groovy/runtime/InvokerHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import groovy.lang.GroovyObject;
import groovy.lang.GroovyRuntimeException;
import groovy.lang.GroovySystem;
import groovy.lang.IgnoreDefaultEqualsAndToString;
import groovy.lang.MetaClass;
import groovy.lang.MetaClassRegistry;
import groovy.lang.MissingMethodException;
Expand Down Expand Up @@ -688,6 +689,9 @@ private static String formatMap(Map map, boolean verbose, int maxSize, boolean s
if (map.isEmpty()) {
return "[:]";
}
if (map.getClass().getAnnotation(IgnoreDefaultEqualsAndToString.class)!=null) {
return map.toString();
}
StringBuilder buffer = new StringBuilder(ITEM_ALLOCATE_SIZE * map.size() * 2);
buffer.append('[');
boolean first = true;
Expand Down Expand Up @@ -723,6 +727,9 @@ private static int sizeLeft(int maxSize, StringBuilder buffer) {
}

private static String formatCollection(Collection collection, boolean verbose, int maxSize, boolean safe) {
if (collection.getClass().getAnnotation(IgnoreDefaultEqualsAndToString.class)!=null) {
return collection.toString();
}
StringBuilder buffer = new StringBuilder(ITEM_ALLOCATE_SIZE * collection.size());
buffer.append('[');
boolean first = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,4 +266,56 @@ public class DefaultGroovyMethodsTest extends GroovyTestCase {
delegate.iterator()
}
}


@IgnoreDefaultEqualsAndToString
private static class CustomList extends ArrayList {
CustomList( Object... items) {
addAll(items)
}

@Override
boolean equals(Object other) {
return this.sum() == other.sum()
}
}

@IgnoreDefaultEqualsAndToString
private static class CustomSet extends HashSet {
CustomSet( Object... items) {
addAll(items)
}

@Override
boolean equals(Object other) {
return this.collect { it.toString().toUpperCase() } == other.collect { it.toString().toUpperCase() }
}
}

@IgnoreDefaultEqualsAndToString
private static class CustomMap extends HashMap {
CustomMap(Map params) {
this.putAll(params)
}

boolean equals(Object other) {
this.values().sum() == other.values().sum()
}
}

public void testCustomEqualsForList() {

assertTrue(new CustomList(1,2,3).equals(new CustomList(3,3)))
assertTrue(new CustomList(1,2,3) == new CustomList(3,3) )

assertTrue(new CustomSet('a','b','c').equals(new CustomSet('A','B','C')))
assertTrue(new CustomSet('a','b','c') == new CustomSet('A','B','C') )

assertTrue(new CustomMap(a:10) == new CustomMap(b:3,c:7))
assertTrue(new CustomMap(a:10).equals(new CustomMap(b:3,c:7)))
assertFalse(new CustomMap(a:1) == new CustomMap(b:2))

}


}
Original file line number Diff line number Diff line change
Expand Up @@ -214,4 +214,42 @@ class InvokerHelperFormattingTest extends GroovyTestCase {
assert '[(this Map):(this Map)]' == InvokerHelper.toString(m)
}



public void testIgnoreDefaultToStringForCustomList() {

String TEST = "" +
"@IgnoreDefaultEqualsAndToString \n" +
"class Foo extends ArrayList { \n" +
" String toString() { return this.reverse().join('-') } \n" +
"}\n" +
"" +
"def foo = new Foo()\n" +
"foo << 1 << 2 << 3 \n" +
"assert foo.toString() == \"1-2-3\"\n" +
"assert \"$foo\".toString() == \"1-2-3\"\n" +
"return true";

assertTrue((Boolean)Eval.me(TEST));

}

public void testIgnoreDefaultToStringForCustomMap() {

String TEST = "" +
"@IgnoreDefaultEqualsAndToString \n" +
"class Foo extends HashMap { \n" +
" String toString() { return 'MyCustomToString' } \n" +
"}\n" +
"" +
"def foo = new Foo()\n" +
"assert foo.toString() == 'MyCustomToString'\n" +
"assert \"$foo\".toString() == 'MyCustomToString'\n" +
"return true";

assertTrue((Boolean)Eval.me(TEST));

}


}

0 comments on commit 8a9f43b

Please sign in to comment.