Skip to content

Commit

Permalink
#1072_visitor_set
Browse files Browse the repository at this point in the history
  • Loading branch information
ryan-beckett committed Oct 2, 2017
1 parent f88872d commit 027a460
Show file tree
Hide file tree
Showing 2 changed files with 308 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
/*
* Copyright (C) 2007-2010 Júlio Vilmar Gesser.
* Copyright (C) 2011, 2013-2016 The JavaParser Team.
*
* This file is part of JavaParser.
*
* JavaParser can be used either under the terms of
* a) the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* b) the terms of the Apache License
*
* You should have received a copy of both licenses in LICENCE.LGPL and
* LICENCE.APACHE. Please refer to those files for details.
*
* JavaParser is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*/

package com.github.javaparser.utils;

import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.stream.Collectors;

import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.visitor.GenericVisitor;
import com.github.javaparser.ast.visitor.Visitable;
import com.github.javaparser.ast.visitor.VoidVisitor;

/**
* A set that overrides the equals and hashcode calculation of the added nodes
* by using another equals and hashcode visitor for those methods.
*/
public class VisitorSet<N extends Node> implements Set<N> {

private final Set<EqualsHashcodeOverridingFacade> innerSet = new HashSet<>();
private final GenericVisitor<Integer, Void> hashcodeVisitor;
private final GenericVisitor<Boolean, Visitable> equalsVisitor;

/**
* Pass the visitors to use for equals and hashcode.
*/
public VisitorSet(GenericVisitor<Integer, Void> hashcodeVisitor, GenericVisitor<Boolean, Visitable> equalsVisitor) {
this.hashcodeVisitor = hashcodeVisitor;
this.equalsVisitor = equalsVisitor;
}

@Override
public boolean add(N elem) {
return innerSet.add(new EqualsHashcodeOverridingFacade(elem));
}

@Override
public boolean addAll(Collection<? extends N> col) {
boolean modified = false;
for (N elem : col)
if (add(elem))
modified = true;
return modified;
}

@Override
public void clear() {
innerSet.clear();
}

@Override
public boolean contains(Object elem) {
return innerSet.contains(new EqualsHashcodeOverridingFacade((N) elem));
}

@Override
public boolean containsAll(Collection<?> col) {
for (Object elem : col)
if (!contains(elem))
return false;
return true;
}

@Override
public boolean isEmpty() {
return innerSet.isEmpty();
}

@Override
public Iterator<N> iterator() {
return new Iterator<N>() {
final Iterator<EqualsHashcodeOverridingFacade> itr = innerSet.iterator();

@Override
public boolean hasNext() {
return itr.hasNext();
}

@Override
public N next() {
return itr.next().overridden;
}

@Override
public void remove() {
itr.remove();
}
};
}

@Override
public boolean remove(Object elem) {
return innerSet.remove(new EqualsHashcodeOverridingFacade((N) elem));
}

@Override
public boolean removeAll(Collection<?> col) {
boolean modified = false;
for (Object elem : col)
if (remove(elem))
modified = true;
return modified;
}

@Override
public boolean retainAll(Collection<?> col) {
int oldSetSize = innerSet.size();
innerSet.clear();
addAll((Collection<? extends N>) col);
return innerSet.size() != oldSetSize;
}

@Override
public int size() {
return innerSet.size();
}

@Override
public Object[] toArray() {
return innerSet.stream().map(facade -> facade.overridden).collect(Collectors.toList()).toArray();
}

@Override
public <T> T[] toArray(T[] arr) {
return innerSet.stream().map(facade -> facade.overridden).collect(Collectors.toList()).toArray(arr);
}

private class EqualsHashcodeOverridingFacade implements Visitable {
private final N overridden;

EqualsHashcodeOverridingFacade(N overridden) {
this.overridden = overridden;
}

@Override
public <R, A> R accept(GenericVisitor<R, A> v, A arg) {
throw new AssertionError();
}

@Override
public <A> void accept(VoidVisitor<A> v, A arg) {
throw new AssertionError();
}

@Override
public final int hashCode() {
return overridden.accept(hashcodeVisitor, null);
}

@Override
public boolean equals(final Object obj) {
if (obj == null || !(obj instanceof VisitorSet.EqualsHashcodeOverridingFacade)) {
return false;
}
return overridden.accept(equalsVisitor, ((EqualsHashcodeOverridingFacade) obj).overridden);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/*
* Copyright (C) 2007-2010 Júlio Vilmar Gesser.
* Copyright (C) 2011, 2013-2016 The JavaParser Team.
*
* This file is part of JavaParser.
*
* JavaParser can be used either under the terms of
* a) the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* b) the terms of the Apache License
*
* You should have received a copy of both licenses in LICENCE.LGPL and
* LICENCE.APACHE. Please refer to those files for details.
*
* JavaParser is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*/

package com.github.javaparser.utils;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.junit.Test;

import com.github.javaparser.JavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.visitor.ObjectIdentityEqualsVisitor;
import com.github.javaparser.ast.visitor.ObjectIdentityHashCodeVisitor;

public class VisitorSetTest {

@Test
public void normalEqualsDoesDeepCompare() {
Set<CompilationUnit> set = new HashSet<>();
set.add(JavaParser.parse("class X{}"));
set.add(JavaParser.parse("class X{}"));
assertEquals(1, set.size());
}

@Test
public void objectIdentityEqualsDoesShallowCompare() {
Set<CompilationUnit> set = new VisitorSet<>(new ObjectIdentityHashCodeVisitor(),
new ObjectIdentityEqualsVisitor());
set.add(JavaParser.parse("class X{}"));
set.add(JavaParser.parse("class X{}"));
assertEquals(2, set.size());
}

@Test
public void visitorSetContains() {
CompilationUnit x1 = JavaParser.parse("class X{}");
Set<CompilationUnit> set = new VisitorSet<>(new ObjectIdentityHashCodeVisitor(),
new ObjectIdentityEqualsVisitor());
set.add(x1);
assertTrue(set.contains(x1));
}

@Test
public void visitorSetContainsAll() {
List<CompilationUnit> lst = new ArrayList<>();
lst.add(JavaParser.parse("class X{}"));
lst.add(JavaParser.parse("class X{}"));
Set<CompilationUnit> set = new VisitorSet<>(new ObjectIdentityHashCodeVisitor(),
new ObjectIdentityEqualsVisitor());
set.addAll(lst);
assertTrue(set.size() == 2 && set.containsAll(lst));
}

@Test
public void visitorSetIterator() {
Set<CompilationUnit> set = new VisitorSet<>(new ObjectIdentityHashCodeVisitor(),
new ObjectIdentityEqualsVisitor());
set.add(JavaParser.parse("class X{}"));
set.add(JavaParser.parse("class X{}"));
Iterator<CompilationUnit> itr = set.iterator();
itr.next();
itr.remove();
assertTrue(set.size() == 1);
itr.next();
itr.remove();
assertTrue(set.size() == 0);
}

@Test
public void visitorSetRemove() {
CompilationUnit x1 = JavaParser.parse("class X{}");
Set<CompilationUnit> set = new VisitorSet<>(new ObjectIdentityHashCodeVisitor(),
new ObjectIdentityEqualsVisitor());
set.add(x1);
assertTrue(set.remove(x1));
}

@Test
public void visitorSetRemoveAll() {
List<CompilationUnit> lst = new ArrayList<>();
lst.add(JavaParser.parse("class X{}"));
lst.add(JavaParser.parse("class X{}"));
Set<CompilationUnit> set = new VisitorSet<>(new ObjectIdentityHashCodeVisitor(),
new ObjectIdentityEqualsVisitor());
set.addAll(lst);
set.removeAll(lst);
assertTrue(set.size() == 0);
}

@Test
public void visitorSetRetainAll() {
List<CompilationUnit> lst = new ArrayList<>();
lst.add(JavaParser.parse("class X{}"));
lst.add(JavaParser.parse("class X{}"));
Set<CompilationUnit> set = new VisitorSet<>(new ObjectIdentityHashCodeVisitor(),
new ObjectIdentityEqualsVisitor());
set.addAll(lst);
set.add(JavaParser.parse("class X{}"));
set.retainAll(lst);
assertTrue(set.size() == 2);
}

}

0 comments on commit 027a460

Please sign in to comment.