From f5a39cc5dd23783183a850dbbe39225aebe0016f Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 18 Jan 2013 14:26:27 +0400 Subject: [PATCH] CompositeIterator removed --- .../diff/impl/incrementalMerge/MergeList.java | 5 +- .../util/containers/CompositeIterator.java | 84 ------- .../util/containers/ContainerUtil.java | 15 +- .../util/containers/SequenceIterator.java | 46 ++-- .../util/containers/SequenceIteratorTest.java | 237 +++++++++++++++++- .../impl/patch/apply/GenericPatchApplier.java | 6 +- .../vcs/changes/VcsDirtyScopeImpl.java | 4 +- .../history/wholeTree/CommitIdsHolder.java | 4 +- 8 files changed, 272 insertions(+), 129 deletions(-) delete mode 100644 platform/util/src/com/intellij/util/containers/CompositeIterator.java diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeList.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeList.java index 13e244e237fc..b17dc4d33397 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeList.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeList.java @@ -33,7 +33,7 @@ import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.*; -import com.intellij.util.containers.SequenceIterator; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.diff.FilesTooBigForDiffException; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -187,8 +187,7 @@ public class MergeList implements UserDataHolder { } public Iterator getAllChanges() { - return SequenceIterator.create(myBaseToLeftChangeList.getChanges().iterator(), - myBaseToRightChangeList.getChanges().iterator()); + return ContainerUtil.concatIterators(myBaseToLeftChangeList.getChanges().iterator(), myBaseToRightChangeList.getChanges().iterator()); } public void addListener(ChangeList.Listener listener) { diff --git a/platform/util/src/com/intellij/util/containers/CompositeIterator.java b/platform/util/src/com/intellij/util/containers/CompositeIterator.java deleted file mode 100644 index 0f5c5f5a08f7..000000000000 --- a/platform/util/src/com/intellij/util/containers/CompositeIterator.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2000-2011 JetBrains s.r.o. - * - * Licensed 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 com.intellij.util.containers; - -import java.util.Iterator; -import java.util.List; - -/** - * Created by IntelliJ IDEA. - * User: Irina.Chernushina - * Date: 9/28/11 - * Time: 12:38 PM - */ -public class CompositeIterator implements Iterator { - private int myPreviousIdx; - private int myIdx; - private final List> myIterators; - private boolean myIsOnLast; - - public CompositeIterator(final List> iterators) { - myIterators = iterators; - myIdx = -1; - myPreviousIdx = -1; - for (int i = 0; i < myIterators.size(); i++) { - final Iterator iterator = myIterators.get(i); - if (iterator.hasNext()) { - myIdx = i; - break; - } - } - } - - @Override - public boolean hasNext() { - return (myIdx >= 0) && myIterators.get(myIdx).hasNext(); - } - - @Override - public Key next() { - final Key result = myIterators.get(myIdx).next(); - myIsOnLast = false; - recalculateCurrent(); - return result; - } - - private void recalculateCurrent() { - if (myIdx == -1) return; - if (! myIterators.get(myIdx).hasNext()) { - myIsOnLast = true; - myPreviousIdx = myIdx; - myIdx = -1; - for (int i = myPreviousIdx; i < myIterators.size(); i++) { - final Iterator iterator = myIterators.get(i); - if (iterator.hasNext()) { - myIdx = i; - break; - } - } - } - } - - @Override - public void remove() { - if (myIsOnLast) { - // last element - myIterators.get(myPreviousIdx).remove(); // already on last position - } else { - myIterators.get(myIdx).remove(); - } - } -} diff --git a/platform/util/src/com/intellij/util/containers/ContainerUtil.java b/platform/util/src/com/intellij/util/containers/ContainerUtil.java index bd1a7d795ccc..c817d2001fb7 100644 --- a/platform/util/src/com/intellij/util/containers/ContainerUtil.java +++ b/platform/util/src/com/intellij/util/containers/ContainerUtil.java @@ -1044,10 +1044,21 @@ public class ContainerUtil extends ContainerUtilRt { Iterable iterable = iterables[i]; iterators[i] = iterable.iterator(); } - return new SequenceIterator(iterators); + return concatIterators(iterators); } }; } + + @NotNull + public static Iterator concatIterators(@NotNull Iterator... iterators) { + return new SequenceIterator(iterators); + } + + @NotNull + public static Iterator concatIterators(@NotNull Collection> iterators) { + return new SequenceIterator(iterators); + } + @NotNull public static Iterable concat(@NotNull final T[]... iterables) { return new Iterable() { @@ -1058,7 +1069,7 @@ public class ContainerUtil extends ContainerUtilRt { T[] iterable = iterables[i]; iterators[i] = Arrays.asList(iterable).iterator(); } - return new SequenceIterator(iterators); + return concatIterators(iterators); } }; } diff --git a/platform/util/src/com/intellij/util/containers/SequenceIterator.java b/platform/util/src/com/intellij/util/containers/SequenceIterator.java index ca5f69ea01e7..b0bbeff13208 100644 --- a/platform/util/src/com/intellij/util/containers/SequenceIterator.java +++ b/platform/util/src/com/intellij/util/containers/SequenceIterator.java @@ -17,44 +17,48 @@ package com.intellij.util.containers; import org.jetbrains.annotations.NotNull; +import java.util.Collection; import java.util.Iterator; import java.util.NoSuchElementException; public class SequenceIterator implements Iterator { - private final Iterator[] myIterators; + private final Iterator[] myIterators; private int myCurrentIndex; - public SequenceIterator(@NotNull Iterator... iterators){ + public SequenceIterator(@NotNull Iterator... iterators){ myIterators = new Iterator[iterators.length]; System.arraycopy(iterators, 0, myIterators, 0, iterators.length); } - - public boolean hasNext(){ - if(myCurrentIndex >= myIterators.length){ - return false; - } - else if(myIterators[myCurrentIndex] == null){ - myCurrentIndex++; - return hasNext(); - } - else if(myIterators[myCurrentIndex].hasNext()){ - return true; - } - else{ - myCurrentIndex++; - return hasNext(); - } + public SequenceIterator(@NotNull Collection> iterators) { + this(iterators.toArray(new Iterator[iterators.size()])); } + @Override + public boolean hasNext(){ + for (int index = myCurrentIndex; index < myIterators.length; index++) { + Iterator iterator = myIterators[index]; + if (iterator != null && iterator.hasNext()) { + myCurrentIndex = index; + return true; + } + } + return false; + } + + @Override public T next(){ - if(hasNext()){ - return (T)myIterators[myCurrentIndex].next(); + if(hasNext()) { + return myIterators[myCurrentIndex].next(); } throw new NoSuchElementException("Iterator has no more elements"); } + @Override public void remove(){ - throw new UnsupportedOperationException("Remove not supported"); + if(myCurrentIndex >= myIterators.length){ + throw new IllegalStateException(); + } + myIterators[myCurrentIndex].remove(); } public static SequenceIterator create(Iterator first, Iterator second) { diff --git a/platform/util/testSrc/com/intellij/util/containers/SequenceIteratorTest.java b/platform/util/testSrc/com/intellij/util/containers/SequenceIteratorTest.java index e75d6dd36da0..dd2790c289e9 100644 --- a/platform/util/testSrc/com/intellij/util/containers/SequenceIteratorTest.java +++ b/platform/util/testSrc/com/intellij/util/containers/SequenceIteratorTest.java @@ -23,41 +23,254 @@ import junit.framework.TestCase; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; +import java.util.List; public class SequenceIteratorTest extends TestCase { private final Assertion CHECK = new Assertion(); public void testOneIterator() { Iterator iterator = iterate("1", "2"); - com.intellij.util.containers.SequenceIterator seq = new com.intellij.util.containers.SequenceIterator(new Iterator[]{iterator}); - CHECK.compareAll(new Object[]{"1", "2"}, com.intellij.util.containers.ContainerUtil.collect(seq)); + Iterator seq = ContainerUtil.concatIterators(iterator); + CHECK.compareAll(new Object[]{"1", "2"}, ContainerUtil.collect(seq)); } public void testTwoNotEmpties() { - Iterator seq = com.intellij.util.containers.SequenceIterator.create(iterate("1", "2"), iterate("3", "4")); - CHECK.compareAll(new Object[]{"1", "2", "3", "4"}, com.intellij.util.containers.ContainerUtil.collect(seq)); + Iterator seq = ContainerUtil.concatIterators(iterate("1", "2"), iterate("3", "4")); + CHECK.compareAll(new Object[]{"1", "2", "3", "4"}, ContainerUtil.collect(seq)); } public void testAllEmpty() { - Assert.assertFalse(new com.intellij.util.containers.SequenceIterator(new Iterator[]{empty()}).hasNext()); - Assert.assertFalse(new com.intellij.util.containers.SequenceIterator(new Iterator[]{empty(), empty()}).hasNext()); + Assert.assertFalse(ContainerUtil.concatIterators(empty()).hasNext()); + Assert.assertFalse(ContainerUtil.concatIterators(empty(), empty()).hasNext()); } public void testIntermediateEmpty() { - com.intellij.util.containers.SequenceIterator seq = com.intellij.util.containers.SequenceIterator.create(iterate("1", "2"), empty(), iterate("3", "4")); - CHECK.compareAll(new Object[]{"1", "2", "3", "4"}, com.intellij.util.containers.ContainerUtil.collect(seq)); + Iterator seq = ContainerUtil.concatIterators(iterate("1", "2"), empty(), iterate("3", "4")); + CHECK.compareAll(new Object[]{"1", "2", "3", "4"}, ContainerUtil.collect(seq)); } public void testFirstEmpty() { - com.intellij.util.containers.SequenceIterator seq = com.intellij.util.containers.SequenceIterator.create(empty(), iterate("1", "2")); - CHECK.compareAll(new Object[]{"1", "2"}, com.intellij.util.containers.ContainerUtil.collect(seq)); + Iterator seq = ContainerUtil.concatIterators(empty(), iterate("1", "2")); + CHECK.compareAll(new Object[]{"1", "2"}, ContainerUtil.collect(seq)); } - private Iterator iterate(String first, String second) { + private static Iterator iterate(String first, String second) { return Arrays.asList(new Object[]{first, second}).iterator(); } - private Iterator empty() { + private static Iterator empty() { return new ArrayList().iterator(); } + + + public void testSimple() throws Exception { + final Iterator iterator = compose(Arrays.>asList(iter(arr1), iter(arr2), iter(arr3))); + int cnt = 0; + while (iterator.hasNext()) { + Integer next = iterator.next(); + System.out.println(next); + ++ cnt; + } + Assert.assertEquals(arr1.length + arr2.length + arr3.length, cnt); + } + + private static Iterator compose(List> iterators) { + return ContainerUtil.concatIterators(iterators); + } + + public void testOne() throws Exception { + final Iterator iterator = compose(Arrays.>asList(iter(arr1))); + int cnt = 0; + while (iterator.hasNext()) { + Integer next = iterator.next(); + System.out.println(next); + ++ cnt; + } + Assert.assertEquals(arr1.length, cnt); + } + + public void testOneOne() throws Exception { + final Iterator iterator = compose(Arrays.>asList(iter(new Integer[]{1}))); + int cnt = 0; + while (iterator.hasNext()) { + Integer next = iterator.next(); + System.out.println(next); + ++ cnt; + } + Assert.assertEquals(1, cnt); + } + + public void testEmpty() throws Exception { + final Iterator iterator = compose(Arrays.>asList(iter(new Integer[]{}))); + int cnt = 0; + while (iterator.hasNext()) { + Integer next = iterator.next(); + System.out.println(next); + ++ cnt; + } + Assert.assertEquals(0, cnt); + } + + public void testManyEmpty() throws Exception { + final Iterator iterator = + compose(Arrays.>asList(iter(new Integer[]{}), iter(new Integer[]{}), iter(new Integer[]{}))); + int cnt = 0; + while (iterator.hasNext()) { + Integer next = iterator.next(); + System.out.println(next); + ++ cnt; + } + Assert.assertEquals(0, cnt); + } + + public void testRemoveSimple() throws Exception { + final ArrayList list1 = new ArrayList(Arrays.asList(arr1)); + final ArrayList list2 = new ArrayList(Arrays.asList(arr2)); + final ArrayList list3 = new ArrayList(Arrays.asList(arr3)); + + final Iterator iterator = + compose(Arrays.>asList(list1.iterator(), list2.iterator(), list3.iterator())); + int cnt = 0; + while (iterator.hasNext()) { + Integer next = iterator.next(); + System.out.println("next: " + next); + if ((cnt - 2) % 5 == 0) { + iterator.remove(); + System.out.println("REMOVED"); + } + ++ cnt; + } + Assert.assertTrue(! list1.contains(3)); + Assert.assertTrue(! list2.contains(13)); + Assert.assertTrue(! list3.contains(103)); + } + + public void testRemoveAfterLast() throws Exception { + final ArrayList list1 = new ArrayList(Arrays.asList(arr1)); + final Iterator it1 = list1.iterator(); + while (it1.hasNext()) { + Integer next = it1.next(); + } + it1.remove(); // ok, removes last + Assert.assertTrue(! list1.contains(5)); + list1.add(5); + + final ArrayList list2 = new ArrayList(Arrays.asList(arr2)); + final ArrayList list3 = new ArrayList(Arrays.asList(arr3)); + + final Iterator iterator = + compose(Arrays.>asList(list1.iterator(), list2.iterator(), list3.iterator())); + while (iterator.hasNext()) { + Integer next = iterator.next(); + } + iterator.remove(); + Assert.assertTrue(! list3.contains(105)); + } + + public void testRemoveOnlyOne() throws Exception { + final ArrayList list1 = new ArrayList(Arrays.asList(new Integer[]{1})); + final Iterator iterator = compose(Arrays.>asList(list1.iterator())); + iterator.next(); + iterator.remove(); + Assert.assertTrue(list1.isEmpty()); + } + + public void testIterateWithEmptyInside() throws Exception { + final Iterator iterator = compose(Arrays.>asList(iter(arr1), iter(new Integer[]{}), iter(arr3))); + int cnt = 0; + int sum = 0; + while (iterator.hasNext()) { + Integer next = iterator.next(); + System.out.println(next); + ++ cnt; + sum += next; + } + Assert.assertEquals(arr1.length + arr3.length, cnt); + Assert.assertEquals(530, sum); + } + + public void testRemoveIfNextNotCalled() throws Exception { + final ArrayList list1 = new ArrayList(Arrays.asList(new Integer[]{1})); + final Iterator iterator = compose(Arrays.>asList(list1.iterator())); + try { + iterator.remove(); + Assert.assertTrue(false); + } catch (IllegalStateException e) { + // ok + } + } + + public void testRemoveTwice() throws Exception { + final ArrayList list1 = new ArrayList(Arrays.asList(new Integer[]{1,2,3,4,5})); + final Iterator iterator = compose(Arrays.>asList(list1.iterator())); + try { + iterator.next(); + iterator.remove(); + iterator.remove(); // wrong, next() should be called inside + Assert.assertTrue(false); + } catch (IllegalStateException e) { + // ok + } + } + + public void testRemoveAll() throws Exception { + final ArrayList list1 = new ArrayList(Arrays.asList(1,2)); + final ArrayList list2 = new ArrayList(Arrays.asList(3,4)); + final ArrayList list3 = new ArrayList(Arrays.asList(5,6)); + + final Iterator iterator = + compose(Arrays.>asList(list1.iterator(), list2.iterator(), list3.iterator())); + while (iterator.hasNext()) { + Integer next = iterator.next(); + System.out.println(next); + iterator.remove(); + } + Assert.assertTrue(list1.isEmpty()); + Assert.assertTrue(list2.isEmpty()); + Assert.assertTrue(list3.isEmpty()); + } + + public void testRemoveAllWithEmptyInside() throws Exception { + final ArrayList list1 = new ArrayList(Arrays.asList(1,2)); + final ArrayList list2 = new ArrayList(); + final ArrayList list3 = new ArrayList(Arrays.asList(5,6)); + + final Iterator iterator = + compose(Arrays.>asList(list1.iterator(), list2.iterator(), list3.iterator())); + while (iterator.hasNext()) { + Integer next = iterator.next(); + System.out.println(next); + iterator.remove(); + } + Assert.assertTrue(list1.isEmpty()); + Assert.assertTrue(list2.isEmpty()); + Assert.assertTrue(list3.isEmpty()); + } + + public void testRemoveLastAndFirstINNext() throws Exception { + final ArrayList list1 = new ArrayList(Arrays.asList(1,2)); + final ArrayList list2 = new ArrayList(Arrays.asList(3,4)); + final ArrayList list3 = new ArrayList(Arrays.asList(5,6)); + + final Iterator iterator = + compose(Arrays.>asList(list1.iterator(), list2.iterator(), list3.iterator())); + iterator.next(); + iterator.next(); + iterator.remove(); + iterator.next(); + iterator.remove(); + + Assert.assertTrue(list1.size() == 1 && ! list1.contains(2)); + Assert.assertTrue(list2.size() == 1 && ! list1.contains(3)); + Assert.assertTrue(list3.size() == 2); + } + + private static final Integer[] arr1 = {1,2,3,4,5}; + private static final Integer[] arr2 = {11,12,13,14,15}; + private static final Integer[] arr3= {101,102,103,104,105}; + + private Iterator iter(final Integer[] arr) { + return Arrays.asList(arr).iterator(); + } + } diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/apply/GenericPatchApplier.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/apply/GenericPatchApplier.java index b17f1c6ff1d4..592f71283cfa 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/apply/GenericPatchApplier.java +++ b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/apply/GenericPatchApplier.java @@ -25,7 +25,7 @@ import com.intellij.openapi.util.text.LineTokenizer; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.BeforeAfter; import com.intellij.util.Consumer; -import com.intellij.util.containers.CompositeIterator; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import java.util.*; @@ -737,8 +737,8 @@ public class GenericPatchApplier { } private Iterator getMatchingIterator(final String line, final int originalStart, final int maxWalkFromBinding) { - return new CompositeIterator(Arrays.>asList(new WalkingIterator(line, originalStart, maxWalkFromBinding, true), - new WalkingIterator(line, originalStart, maxWalkFromBinding, false))); + return ContainerUtil.concatIterators(new WalkingIterator(line, originalStart, maxWalkFromBinding, true), + new WalkingIterator(line, originalStart, maxWalkFromBinding, false)); } private class WalkingIterator implements Iterator { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeImpl.java index de0d9b6fa6a0..316341cfc2cc 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeImpl.java @@ -29,7 +29,7 @@ import com.intellij.util.Consumer; import com.intellij.util.PairProcessor; import com.intellij.util.Processor; import com.intellij.util.SmartList; -import com.intellij.util.containers.CompositeIterator; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.Convertor; import com.intellij.util.containers.MultiMap; import gnu.trove.THashSet; @@ -72,7 +72,7 @@ public class VcsDirtyScopeImpl extends VcsModifiableDirtyScope { for (THashSet paths : myDirtyFiles.values()) { iteratorList.add(paths.iterator()); } - return new CompositeIterator(iteratorList); + return ContainerUtil.concatIterators(iteratorList); } @Nullable diff --git a/plugins/git4idea/src/git4idea/history/wholeTree/CommitIdsHolder.java b/plugins/git4idea/src/git4idea/history/wholeTree/CommitIdsHolder.java index 3d6dab152673..280691ea003c 100644 --- a/plugins/git4idea/src/git4idea/history/wholeTree/CommitIdsHolder.java +++ b/plugins/git4idea/src/git4idea/history/wholeTree/CommitIdsHolder.java @@ -15,7 +15,7 @@ */ package git4idea.history.wholeTree; -import com.intellij.util.containers.CompositeIterator; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.SLRUMap; import java.util.*; @@ -74,7 +74,7 @@ public class CommitIdsHolder { final List> iterators = new ArrayList>(2); iterators.add(myProbationalQueue.keySet().iterator()); iterators.add(myProtectedQueue.keySet().iterator()); - return new CompositeIterator(iterators); + return ContainerUtil.concatIterators(iterators); } } }