Loading src/main/java/me/brianlong/git/CompositeIterator.java 0 → 100644 +42 −0 Original line number Diff line number Diff line package me.brianlong.git; import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.NoSuchElementException; public class CompositeIterator<E> implements Iterator<E> { private final List<Iterator<E>> iterators = new LinkedList<Iterator<E>>(); private final Iterator<Iterator<E>> iteratorIterators; private Iterator<E> iterator; public CompositeIterator(@SuppressWarnings("unchecked") Collection<E>... cs) { for (Collection<E> c : cs) if (c != null && !c.isEmpty()) this.iterators.add(c.iterator()); this.iteratorIterators = this.iterators.iterator(); } @Override public boolean hasNext() { if (this.iterator == null) { if (!this.iteratorIterators.hasNext()) return false; this.iterator = this.iteratorIterators.next(); } while (!this.iterator.hasNext() && this.iteratorIterators.hasNext()) this.iterator = this.iteratorIterators.next(); return this.iterator.hasNext(); } @Override public E next() { if (!this.hasNext()) throw new NoSuchElementException(); return this.iterator.next(); } } src/main/java/me/brianlong/git/CredentialedGit.java +1 −1 Original line number Diff line number Diff line Loading @@ -12,7 +12,7 @@ import org.eclipse.jgit.api.errors.TransportException; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.transport.CredentialsProvider; public class CredentialedGit extends CachedGit { public class CredentialedGit extends ExtendedGit { private CredentialsProvider credProvider; Loading src/main/java/me/brianlong/git/ExtendedGit.java 0 → 100644 +127 −0 Original line number Diff line number Diff line package me.brianlong.git; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.jgit.api.CloneCommand; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.ListBranchCommand; import org.eclipse.jgit.api.ListBranchCommand.ListMode; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.InvalidRemoteException; import org.eclipse.jgit.api.errors.TransportException; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ExtendedGit extends CachedGit { private final Logger logger = LoggerFactory.getLogger(ExtendedGit.class); private final Pattern gitUrlPattern = Pattern.compile("(((ssh|http(s)?)://([^@]+@)?([^:/]+)(:[0-9]+)?/)|git@([^:]+):)([\\w\\.@\\:/\\-~]+)(\\.git)"); public ExtendedGit(Git git) { super(git.getRepository()); } public ExtendedGit(CloneCommand clone) throws TransportException, InvalidRemoteException, GitAPIException { super(clone.call().getRepository()); } public ExtendedGit(Repository repo) { super(repo); } public String getFirstRemoteUrl() throws GitAPIException { return this.remoteList().call().iterator().next().getURIs().iterator().next().toString(); } public String getRepositoryFullyQualifiedName() throws GitAPIException, URISyntaxException { String gitUrl = this.getFirstRemoteUrl(); if (this.logger.isDebugEnabled()) this.logger.debug("Remote URL: " + gitUrl); Matcher matcher = this.gitUrlPattern.matcher(gitUrl); if (!matcher.find()) throw new URISyntaxException(gitUrl, "The Git URL does not match the expected regular expression: " + this.gitUrlPattern.toString()); return matcher.group(9); } /** * This method retrieves all branches, but excludes remote branches that are tracked with a local branch. * @return */ public List<Ref> getAllUniqueBranches() throws GitAPIException { return this.getAllUniqueBranches(null); } /** * This method retrieves all branches, but excludes remote branches that are tracked with a local branch. * @return */ public List<Ref> getAllUniqueBranches(String containsCommitish) throws GitAPIException { ListBranchCommand command = this.branchList().setListMode(ListMode.ALL); if (containsCommitish != null) command.setContains(containsCommitish); List<Ref> branches = command.call(); Set<String> abbrevBranchNames = new HashSet<String>(branches.size()); List<Ref> trimmedBranches = new ArrayList<Ref>(branches.size()); // sort them by local, then remote; keep order the same otherwise Collections.sort(branches, new Comparator<Ref>() { @Override public int compare(Ref o1, Ref o2) { if (o1 == null) return -1; else if (o2 == null) return 1; else { boolean o1local = o1.getName().startsWith(Constants.R_HEADS); boolean o2local = o2.getName().startsWith(Constants.R_HEADS); if (o1local && o2local) return 0; else if (o1local) return -1; else if (o2local) return 1; else return 0; } } }); for (Ref branch : branches) { String fqBranchName = branch.getName(); String abbrevBranchName = null; if (fqBranchName.startsWith(Constants.R_REMOTES)) { if (this.logger.isDebugEnabled()) this.logger.debug("Ref is a remote branch: " + fqBranchName); abbrevBranchName = this.getRepository().shortenRemoteBranchName(fqBranchName); } else if (fqBranchName.startsWith(Constants.R_HEADS)) { if (this.logger.isDebugEnabled()) this.logger.debug("Ref is a local branch: " + fqBranchName); abbrevBranchName = Repository.shortenRefName(fqBranchName); } else { if (this.logger.isDebugEnabled()) this.logger.debug("Ref is not a local or remote branch: " + fqBranchName); } if (abbrevBranchName != null) { if (abbrevBranchNames.contains(abbrevBranchName)) { if (this.logger.isDebugEnabled()) this.logger.debug("Branch already found; ignoring ..."); } else { abbrevBranchNames.add(abbrevBranchName); trimmedBranches.add(branch); } } } return trimmedBranches; } } src/main/java/me/brianlong/git/LocalRepositoryCache.java +5 −5 Original line number Diff line number Diff line Loading @@ -48,19 +48,19 @@ public class LocalRepositoryCache { this.clear(); } public synchronized Git acquire(String url) throws GitAPIException, InvalidRemoteException, RefNotFoundException { public synchronized ExtendedGit acquire(String url) throws GitAPIException, InvalidRemoteException, RefNotFoundException { return this.acquire(url, null, null); } public synchronized Git acquire(String url, GitCredentials creds) throws GitAPIException, InvalidRemoteException, RefNotFoundException { public synchronized ExtendedGit acquire(String url, GitCredentials creds) throws GitAPIException, InvalidRemoteException, RefNotFoundException { return this.acquire(url, creds, null); } public synchronized Git acquire(String url, String branch) throws GitAPIException, InvalidRemoteException, RefNotFoundException { public synchronized ExtendedGit acquire(String url, String branch) throws GitAPIException, InvalidRemoteException, RefNotFoundException { return this.acquire(url, null, branch); } public synchronized Git acquire(String url, GitCredentials creds, String branch) throws GitAPIException, InvalidRemoteException, RefNotFoundException { public synchronized ExtendedGit acquire(String url, GitCredentials creds, String branch) throws GitAPIException, InvalidRemoteException, RefNotFoundException { if (this.logger.isTraceEnabled()) this.logger.trace("acquire('" + url + "', " + creds + ", '" + branch + "')"); Loading @@ -78,7 +78,7 @@ public class LocalRepositoryCache { if (this.logger.isDebugEnabled()) this.logger.debug("cloning Git repository: " + url); Git git = creds != null ? new CredentialedGit(clone, creds) : new CachedGit(clone); ExtendedGit git = creds != null ? new CredentialedGit(clone, creds) : new ExtendedGit(clone); if (this.logger.isInfoEnabled()) this.logger.info("Cloned Git Repository"); return git; Loading src/main/java/me/brianlong/git/UniquePriorityFifoQueue.java 0 → 100644 +236 −0 Original line number Diff line number Diff line package me.brianlong.git; import java.util.Arrays; import java.util.Collection; import java.util.Comparator; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Queue; import java.util.TreeSet; public class UniquePriorityFifoQueue<T> implements Queue<T> { private final Counter counter = new SimpleCounter(); private final Counter fakeCounter = new FakeCounter(); private final TreeSet<PriorityFifoElement<T>> elements; public UniquePriorityFifoQueue() { this.elements = new TreeSet<PriorityFifoElement<T>>(); } public UniquePriorityFifoQueue(Collection<? extends T> c) { this.elements = new TreeSet<PriorityFifoElement<T>>(); for (T element : c) this.elements.add(new PriorityFifoElement<T>(element, this.counter)); } public UniquePriorityFifoQueue(final Comparator<? super T> comparator) { this.elements = new TreeSet<PriorityFifoElement<T>>(new Comparator<PriorityFifoElement<T>>() { @Override public int compare(PriorityFifoElement<T> o1, PriorityFifoElement<T> o2) { int compare = comparator.compare(o1.element, o2.element); if (compare != 0) return compare; return o1.compareTo(o2); } }); } @Override public boolean add(T e) { return this.elements.add(new PriorityFifoElement<T>(e, this.counter)); } @Override public boolean addAll(Collection<? extends T> c) { if (c != null) for (T e : c) this.elements.add(new PriorityFifoElement<T>(e, this.counter)); return true; } @Override public void clear() { this.elements.clear(); } @SuppressWarnings("unchecked") @Override public boolean contains(Object o) { return this.elements.contains(new PriorityFifoElement<T>((T)o, this.fakeCounter)); } @Override public boolean containsAll(Collection<?> c) { if (c != null) for (Object o : c) if (!this.contains(o)) return false; return true; } @Override public T element() { return this.elements.iterator().next().element; } @Override public boolean isEmpty() { return this.elements.isEmpty(); } @Override public Iterator<T> iterator() { final Iterator<PriorityFifoElement<T>> i = this.elements.iterator(); return new Iterator<T>() { @Override public boolean hasNext() { return i.hasNext(); } @Override public T next() { return i.next().element; } @Override public void remove() { i.remove(); } }; } @Override public boolean offer(T e) { return this.elements.add(new PriorityFifoElement<T>(e, this.counter)); } @Override public T peek() { Iterator<T> i = this.iterator(); return i.hasNext() ? i.next() : null; } @Override public T poll() { PriorityFifoElement<T> element = this.elements.pollFirst(); return element == null ? null : element.element; } @Override public T remove() { PriorityFifoElement<T> element = this.elements.pollFirst(); if (element == null) throw new NoSuchElementException(); return element.element; } @SuppressWarnings("unchecked") @Override public boolean remove(Object o) { return this.elements.remove(new PriorityFifoElement<T>((T)o, this.fakeCounter)); } @Override public boolean removeAll(Collection<?> c) { if (c != null) for (Object o : c) this.remove(o); return true; } @Override public boolean retainAll(Collection<?> c) { Iterator<PriorityFifoElement<T>> i = this.elements.iterator(); while (i.hasNext()) { T e = i.next().element; if (!c.contains(e)) i.remove(); } return true; } @Override public int size() { return this.elements.size(); } @SuppressWarnings("unchecked") @Override public Object[] toArray() { Object[] objs = this.elements.toArray(); Object[] ts = new Object[objs.length]; for (int i = 0; i < objs.length; i++) ts[i] = ((PriorityFifoElement<T>)objs[i]).element; return ts; } @SuppressWarnings("unchecked") public <U extends Object> U[] toArray(U[] a) { if (a.length < this.elements.size()) a = Arrays.copyOf(a, this.elements.size()); int i = 0; for (PriorityFifoElement<T> element : this.elements) a[i] = (U)element.element; return a; } private class PriorityFifoElement<E> implements Comparable<PriorityFifoElement<E>> { private final E element; private final int fifoId; public PriorityFifoElement(E element, Counter counter) { this.element = element; this.fifoId = counter.next(); } @Override public int compareTo(PriorityFifoElement<E> o) { if (o == null) return 1; else return this.fifoId - o.fifoId; } @Override public int hashCode() { return this.element.hashCode(); } @SuppressWarnings("rawtypes") @Override public boolean equals(Object obj) { if (obj instanceof PriorityFifoElement) { return this.element.equals(((PriorityFifoElement)obj).element); } else { return false; } } } private interface Counter { int next(); } public class FakeCounter implements Counter { public int next() { return 0; } } public class SimpleCounter implements Counter { private int count = 0; public synchronized int next() { this.count++; return this.count; } } } Loading
src/main/java/me/brianlong/git/CompositeIterator.java 0 → 100644 +42 −0 Original line number Diff line number Diff line package me.brianlong.git; import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.NoSuchElementException; public class CompositeIterator<E> implements Iterator<E> { private final List<Iterator<E>> iterators = new LinkedList<Iterator<E>>(); private final Iterator<Iterator<E>> iteratorIterators; private Iterator<E> iterator; public CompositeIterator(@SuppressWarnings("unchecked") Collection<E>... cs) { for (Collection<E> c : cs) if (c != null && !c.isEmpty()) this.iterators.add(c.iterator()); this.iteratorIterators = this.iterators.iterator(); } @Override public boolean hasNext() { if (this.iterator == null) { if (!this.iteratorIterators.hasNext()) return false; this.iterator = this.iteratorIterators.next(); } while (!this.iterator.hasNext() && this.iteratorIterators.hasNext()) this.iterator = this.iteratorIterators.next(); return this.iterator.hasNext(); } @Override public E next() { if (!this.hasNext()) throw new NoSuchElementException(); return this.iterator.next(); } }
src/main/java/me/brianlong/git/CredentialedGit.java +1 −1 Original line number Diff line number Diff line Loading @@ -12,7 +12,7 @@ import org.eclipse.jgit.api.errors.TransportException; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.transport.CredentialsProvider; public class CredentialedGit extends CachedGit { public class CredentialedGit extends ExtendedGit { private CredentialsProvider credProvider; Loading
src/main/java/me/brianlong/git/ExtendedGit.java 0 → 100644 +127 −0 Original line number Diff line number Diff line package me.brianlong.git; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.jgit.api.CloneCommand; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.ListBranchCommand; import org.eclipse.jgit.api.ListBranchCommand.ListMode; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.InvalidRemoteException; import org.eclipse.jgit.api.errors.TransportException; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ExtendedGit extends CachedGit { private final Logger logger = LoggerFactory.getLogger(ExtendedGit.class); private final Pattern gitUrlPattern = Pattern.compile("(((ssh|http(s)?)://([^@]+@)?([^:/]+)(:[0-9]+)?/)|git@([^:]+):)([\\w\\.@\\:/\\-~]+)(\\.git)"); public ExtendedGit(Git git) { super(git.getRepository()); } public ExtendedGit(CloneCommand clone) throws TransportException, InvalidRemoteException, GitAPIException { super(clone.call().getRepository()); } public ExtendedGit(Repository repo) { super(repo); } public String getFirstRemoteUrl() throws GitAPIException { return this.remoteList().call().iterator().next().getURIs().iterator().next().toString(); } public String getRepositoryFullyQualifiedName() throws GitAPIException, URISyntaxException { String gitUrl = this.getFirstRemoteUrl(); if (this.logger.isDebugEnabled()) this.logger.debug("Remote URL: " + gitUrl); Matcher matcher = this.gitUrlPattern.matcher(gitUrl); if (!matcher.find()) throw new URISyntaxException(gitUrl, "The Git URL does not match the expected regular expression: " + this.gitUrlPattern.toString()); return matcher.group(9); } /** * This method retrieves all branches, but excludes remote branches that are tracked with a local branch. * @return */ public List<Ref> getAllUniqueBranches() throws GitAPIException { return this.getAllUniqueBranches(null); } /** * This method retrieves all branches, but excludes remote branches that are tracked with a local branch. * @return */ public List<Ref> getAllUniqueBranches(String containsCommitish) throws GitAPIException { ListBranchCommand command = this.branchList().setListMode(ListMode.ALL); if (containsCommitish != null) command.setContains(containsCommitish); List<Ref> branches = command.call(); Set<String> abbrevBranchNames = new HashSet<String>(branches.size()); List<Ref> trimmedBranches = new ArrayList<Ref>(branches.size()); // sort them by local, then remote; keep order the same otherwise Collections.sort(branches, new Comparator<Ref>() { @Override public int compare(Ref o1, Ref o2) { if (o1 == null) return -1; else if (o2 == null) return 1; else { boolean o1local = o1.getName().startsWith(Constants.R_HEADS); boolean o2local = o2.getName().startsWith(Constants.R_HEADS); if (o1local && o2local) return 0; else if (o1local) return -1; else if (o2local) return 1; else return 0; } } }); for (Ref branch : branches) { String fqBranchName = branch.getName(); String abbrevBranchName = null; if (fqBranchName.startsWith(Constants.R_REMOTES)) { if (this.logger.isDebugEnabled()) this.logger.debug("Ref is a remote branch: " + fqBranchName); abbrevBranchName = this.getRepository().shortenRemoteBranchName(fqBranchName); } else if (fqBranchName.startsWith(Constants.R_HEADS)) { if (this.logger.isDebugEnabled()) this.logger.debug("Ref is a local branch: " + fqBranchName); abbrevBranchName = Repository.shortenRefName(fqBranchName); } else { if (this.logger.isDebugEnabled()) this.logger.debug("Ref is not a local or remote branch: " + fqBranchName); } if (abbrevBranchName != null) { if (abbrevBranchNames.contains(abbrevBranchName)) { if (this.logger.isDebugEnabled()) this.logger.debug("Branch already found; ignoring ..."); } else { abbrevBranchNames.add(abbrevBranchName); trimmedBranches.add(branch); } } } return trimmedBranches; } }
src/main/java/me/brianlong/git/LocalRepositoryCache.java +5 −5 Original line number Diff line number Diff line Loading @@ -48,19 +48,19 @@ public class LocalRepositoryCache { this.clear(); } public synchronized Git acquire(String url) throws GitAPIException, InvalidRemoteException, RefNotFoundException { public synchronized ExtendedGit acquire(String url) throws GitAPIException, InvalidRemoteException, RefNotFoundException { return this.acquire(url, null, null); } public synchronized Git acquire(String url, GitCredentials creds) throws GitAPIException, InvalidRemoteException, RefNotFoundException { public synchronized ExtendedGit acquire(String url, GitCredentials creds) throws GitAPIException, InvalidRemoteException, RefNotFoundException { return this.acquire(url, creds, null); } public synchronized Git acquire(String url, String branch) throws GitAPIException, InvalidRemoteException, RefNotFoundException { public synchronized ExtendedGit acquire(String url, String branch) throws GitAPIException, InvalidRemoteException, RefNotFoundException { return this.acquire(url, null, branch); } public synchronized Git acquire(String url, GitCredentials creds, String branch) throws GitAPIException, InvalidRemoteException, RefNotFoundException { public synchronized ExtendedGit acquire(String url, GitCredentials creds, String branch) throws GitAPIException, InvalidRemoteException, RefNotFoundException { if (this.logger.isTraceEnabled()) this.logger.trace("acquire('" + url + "', " + creds + ", '" + branch + "')"); Loading @@ -78,7 +78,7 @@ public class LocalRepositoryCache { if (this.logger.isDebugEnabled()) this.logger.debug("cloning Git repository: " + url); Git git = creds != null ? new CredentialedGit(clone, creds) : new CachedGit(clone); ExtendedGit git = creds != null ? new CredentialedGit(clone, creds) : new ExtendedGit(clone); if (this.logger.isInfoEnabled()) this.logger.info("Cloned Git Repository"); return git; Loading
src/main/java/me/brianlong/git/UniquePriorityFifoQueue.java 0 → 100644 +236 −0 Original line number Diff line number Diff line package me.brianlong.git; import java.util.Arrays; import java.util.Collection; import java.util.Comparator; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Queue; import java.util.TreeSet; public class UniquePriorityFifoQueue<T> implements Queue<T> { private final Counter counter = new SimpleCounter(); private final Counter fakeCounter = new FakeCounter(); private final TreeSet<PriorityFifoElement<T>> elements; public UniquePriorityFifoQueue() { this.elements = new TreeSet<PriorityFifoElement<T>>(); } public UniquePriorityFifoQueue(Collection<? extends T> c) { this.elements = new TreeSet<PriorityFifoElement<T>>(); for (T element : c) this.elements.add(new PriorityFifoElement<T>(element, this.counter)); } public UniquePriorityFifoQueue(final Comparator<? super T> comparator) { this.elements = new TreeSet<PriorityFifoElement<T>>(new Comparator<PriorityFifoElement<T>>() { @Override public int compare(PriorityFifoElement<T> o1, PriorityFifoElement<T> o2) { int compare = comparator.compare(o1.element, o2.element); if (compare != 0) return compare; return o1.compareTo(o2); } }); } @Override public boolean add(T e) { return this.elements.add(new PriorityFifoElement<T>(e, this.counter)); } @Override public boolean addAll(Collection<? extends T> c) { if (c != null) for (T e : c) this.elements.add(new PriorityFifoElement<T>(e, this.counter)); return true; } @Override public void clear() { this.elements.clear(); } @SuppressWarnings("unchecked") @Override public boolean contains(Object o) { return this.elements.contains(new PriorityFifoElement<T>((T)o, this.fakeCounter)); } @Override public boolean containsAll(Collection<?> c) { if (c != null) for (Object o : c) if (!this.contains(o)) return false; return true; } @Override public T element() { return this.elements.iterator().next().element; } @Override public boolean isEmpty() { return this.elements.isEmpty(); } @Override public Iterator<T> iterator() { final Iterator<PriorityFifoElement<T>> i = this.elements.iterator(); return new Iterator<T>() { @Override public boolean hasNext() { return i.hasNext(); } @Override public T next() { return i.next().element; } @Override public void remove() { i.remove(); } }; } @Override public boolean offer(T e) { return this.elements.add(new PriorityFifoElement<T>(e, this.counter)); } @Override public T peek() { Iterator<T> i = this.iterator(); return i.hasNext() ? i.next() : null; } @Override public T poll() { PriorityFifoElement<T> element = this.elements.pollFirst(); return element == null ? null : element.element; } @Override public T remove() { PriorityFifoElement<T> element = this.elements.pollFirst(); if (element == null) throw new NoSuchElementException(); return element.element; } @SuppressWarnings("unchecked") @Override public boolean remove(Object o) { return this.elements.remove(new PriorityFifoElement<T>((T)o, this.fakeCounter)); } @Override public boolean removeAll(Collection<?> c) { if (c != null) for (Object o : c) this.remove(o); return true; } @Override public boolean retainAll(Collection<?> c) { Iterator<PriorityFifoElement<T>> i = this.elements.iterator(); while (i.hasNext()) { T e = i.next().element; if (!c.contains(e)) i.remove(); } return true; } @Override public int size() { return this.elements.size(); } @SuppressWarnings("unchecked") @Override public Object[] toArray() { Object[] objs = this.elements.toArray(); Object[] ts = new Object[objs.length]; for (int i = 0; i < objs.length; i++) ts[i] = ((PriorityFifoElement<T>)objs[i]).element; return ts; } @SuppressWarnings("unchecked") public <U extends Object> U[] toArray(U[] a) { if (a.length < this.elements.size()) a = Arrays.copyOf(a, this.elements.size()); int i = 0; for (PriorityFifoElement<T> element : this.elements) a[i] = (U)element.element; return a; } private class PriorityFifoElement<E> implements Comparable<PriorityFifoElement<E>> { private final E element; private final int fifoId; public PriorityFifoElement(E element, Counter counter) { this.element = element; this.fifoId = counter.next(); } @Override public int compareTo(PriorityFifoElement<E> o) { if (o == null) return 1; else return this.fifoId - o.fifoId; } @Override public int hashCode() { return this.element.hashCode(); } @SuppressWarnings("rawtypes") @Override public boolean equals(Object obj) { if (obj instanceof PriorityFifoElement) { return this.element.equals(((PriorityFifoElement)obj).element); } else { return false; } } } private interface Counter { int next(); } public class FakeCounter implements Counter { public int next() { return 0; } } public class SimpleCounter implements Counter { private int count = 0; public synchronized int next() { this.count++; return this.count; } } }