blob: a3e7df06038da19b85ed8f58de4a04325cd15e23 [file] [log] [blame]
/*
* 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.openapi.vcs.checkin;
import com.intellij.openapi.util.Getter;
import com.intellij.openapi.util.TextRange;
import com.intellij.util.PairConsumer;
import com.intellij.util.containers.Convertor;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
/**
* @author irengrig
* Date: 2/18/11
* Time: 12:04 AM
*
* keeps state (position in areas) between invocations
*/
public class StepIntersection<Data, Area> {
private final Convertor<Data,TextRange> myDataConvertor;
private final Convertor<Area,TextRange> myAreasConvertor;
private TextRange myDataRange;
private TextRange myAreaRange;
private Data myCurData;
private Iterator<Data> myDataIterator;
private int myAreaIndex;
private Area myCurArea;
private final List<Area> myAreas;
private final HackSearch<Data,Area,TextRange> myHackSearch;
// EA-28497, EA-26379
private final Getter<String> myDebugDocumentTextGetter;
public StepIntersection(Convertor<Data, TextRange> dataConvertor,
Convertor<Area, TextRange> areasConvertor,
final List<Area> areas,
Getter<String> debugDocumentTextGetter) {
myAreas = areas;
myDebugDocumentTextGetter = debugDocumentTextGetter;
myAreaIndex = 0;
myDataConvertor = dataConvertor;
myAreasConvertor = areasConvertor;
myHackSearch = new HackSearch<Data, Area, TextRange>(myDataConvertor, myAreasConvertor, new Comparator<TextRange>() {
@Override
public int compare(TextRange o1, TextRange o2) {
return o1.intersects(o2) ? 0 : o1.getStartOffset() < o2.getStartOffset() ? -1 : 1;
}
});
}
public void resetIndex() {
myAreaIndex = 0;
}
public List<Data> process(final Iterable<Data> data) {
final List<Data> result = new ArrayList<Data>();
process(data, new PairConsumer<Data, Area>() {
@Override
public void consume(Data data, Area area) {
result.add(data);
}
});
return result;
}
public void process(final Iterable<Data> data, final PairConsumer<Data, Area> consumer) {
myDataIterator = data.iterator();
if (! myDataIterator.hasNext() || noMoreAreas()) return;
dataStep();
initArea();
while (! noMoreAreas()) {
final boolean intersects = myAreaRange.intersects(myDataRange);
if (intersects) {
consumer.consume(myCurData, myCurArea);
}
// take next
if (! myDataIterator.hasNext() && noMoreAreas()) break;
if (! myDataIterator.hasNext()) {
areaStep();
continue;
}
if (noMoreAreas()) {
dataStep();
continue;
}
if (myDataRange.getEndOffset() < myAreaRange.getEndOffset()) {
dataStep();
} else {
areaStep();
}
}
}
private boolean noMoreAreas() {
return (myAreaIndex >= myAreas.size());
}
private void initArea() {
myAreaIndex = 0;
myCurArea = myAreas.get(myAreaIndex);
myAreaRange = myAreasConvertor.convert(myCurArea);
}
private void areaStep() {
// a hack here
final int idx = myHackSearch.search(myAreas.subList(myAreaIndex + 1, myAreas.size()), myCurData);
myAreaIndex = myAreaIndex + 1 + idx;
if (myAreaIndex >= myAreas.size()) {
return;
}
/*assert myAreaRange == null || myAreaRange.getEndOffset() < myAreasConvertor.convert(myAreas.get(myAreaIndex)).getStartOffset() :
"Area ranges intersect: first: " + myAreaRange + ", second: " + myAreasConvertor.convert(myAreas.get(myAreaIndex)) + ", text: '" +
myDebugDocumentTextGetter.get() + "'";*/
myCurArea = myAreas.get(myAreaIndex);
myAreaRange = myAreasConvertor.convert(myCurArea);
}
private void dataStep() {
myCurData = myDataIterator.next();
/*assert myDataRange == null || myDataRange.getEndOffset() < myDataConvertor.convert(myCurData).getStartOffset() :
"Data ranges intersect: first: " + myDataRange + ", second: " + myDataConvertor.convert(myCurData) + ", text: '" +
myDebugDocumentTextGetter.get() + "'";*/
myDataRange = myDataConvertor.convert(myCurData);
}
}