Mercurial > jhg
view src/org/tmatesoft/hg/internal/RevisionSet.java @ 649:e79cf9a8130b
Push: phase4 - update local and remote phase information
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Wed, 26 Jun 2013 20:52:38 +0200 |
parents | 690e71d29bf6 |
children | 3b275cc2d2aa |
line wrap: on
line source
/* * Copyright (c) 2013 TMate Software Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * This program 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 General Public License for more details. * * For information on how to redistribute this software under * the terms of a license other than GNU General Public License * contact TMate Software at support@hg4j.com */ package org.tmatesoft.hg.internal; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.tmatesoft.hg.core.Nodeid; import org.tmatesoft.hg.repo.HgChangelog; import org.tmatesoft.hg.repo.HgParentChildMap; /** * Unmodifiable collection of revisions with handy set operations * * @author Artem Tikhomirov * @author TMate Software Ltd. */ public final class RevisionSet implements Iterable<Nodeid> { private final Set<Nodeid> elements; public RevisionSet(Collection<Nodeid> revisions) { this(revisions == null ? new HashSet<Nodeid>() : new HashSet<Nodeid>(revisions)); } private RevisionSet(HashSet<Nodeid> revisions) { if (revisions.isEmpty()) { elements = Collections.<Nodeid>emptySet(); } else { elements = revisions; } } /** * elements of the set with no parents or parents not from the same set */ public RevisionSet roots(HgParentChildMap<HgChangelog> ph) { HashSet<Nodeid> copy = new HashSet<Nodeid>(elements); for (Nodeid n : elements) { assert ph.knownNode(n); Nodeid p1 = ph.firstParent(n); if (p1 != null && elements.contains(p1)) { copy.remove(n); continue; } Nodeid p2 = ph.secondParent(n); if (p2 != null && elements.contains(p2)) { copy.remove(n); continue; } } return copy.size() == elements.size() ? this : new RevisionSet(copy); } /** * elements of the set that has no children in this set */ public RevisionSet heads(HgParentChildMap<HgChangelog> ph) { HashSet<Nodeid> copy = new HashSet<Nodeid>(elements); // can't do copy.removeAll(ph.childrenOf(asList())); as actual heads are indeed children of some other node for (Nodeid n : elements) { assert ph.knownNode(n); Nodeid p1 = ph.firstParent(n); Nodeid p2 = ph.secondParent(n); if (p1 != null && elements.contains(p1)) { copy.remove(p1); } if (p2 != null && elements.contains(p2)) { copy.remove(p2); } } return copy.size() == elements.size() ? this : new RevisionSet(copy); } /** * Immediate parents of the supplied children set found in this one. */ public RevisionSet parentsOf(RevisionSet children, HgParentChildMap<HgChangelog> parentHelper) { if (isEmpty()) { return this; } if (children.isEmpty()) { return children; } RevisionSet chRoots = children.roots(parentHelper); HashSet<Nodeid> parents = new HashSet<Nodeid>(); for (Nodeid n : chRoots.elements) { Nodeid p1 = parentHelper.firstParent(n); Nodeid p2 = parentHelper.secondParent(n); if (p1 != null && elements.contains(p1)) { parents.add(p1); } if (p2 != null && elements.contains(p2)) { parents.add(p2); } } return new RevisionSet(parents); } public RevisionSet intersect(RevisionSet other) { if (isEmpty()) { return this; } if (other.isEmpty()) { return other; } HashSet<Nodeid> copy = new HashSet<Nodeid>(elements); copy.retainAll(other.elements); return copy.size() == elements.size() ? this : new RevisionSet(copy); } public RevisionSet subtract(RevisionSet other) { if (isEmpty() || other.isEmpty()) { return this; } HashSet<Nodeid> copy = new HashSet<Nodeid>(elements); copy.removeAll(other.elements); return copy.size() == elements.size() ? this : new RevisionSet(copy); } public RevisionSet union(RevisionSet other) { if (isEmpty()) { return other; } if (other.isEmpty()) { return this; } HashSet<Nodeid> copy = new HashSet<Nodeid>(elements); copy.addAll(other.elements); return new RevisionSet(copy); } /** * A ^ B := (A\B).union(B\A) * A ^ B := A.union(B) \ A.intersect(B) */ public RevisionSet symmetricDifference(RevisionSet other) { if (isEmpty()) { return this; } if (other.isEmpty()) { return other; } HashSet<Nodeid> copyA = new HashSet<Nodeid>(elements); HashSet<Nodeid> copyB = new HashSet<Nodeid>(other.elements); copyA.removeAll(other.elements); copyB.removeAll(elements); copyA.addAll(copyB); return new RevisionSet(copyA); } public boolean isEmpty() { return elements.isEmpty(); } public List<Nodeid> asList() { return new ArrayList<Nodeid>(elements); } public Iterator<Nodeid> iterator() { return elements.iterator(); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append('<'); if (!isEmpty()) { sb.append(elements.size()); sb.append(':'); } for (Nodeid n : elements) { sb.append(n.shortNotation()); sb.append(','); } if (sb.length() > 1) { sb.setCharAt(sb.length() - 1, '>'); } else { sb.append('>'); } return sb.toString(); } @Override public boolean equals(Object obj) { if (false == obj instanceof RevisionSet) { return false; } return elements.equals(((RevisionSet) obj).elements); } @Override public int hashCode() { return elements.hashCode(); } }