blob: b50ad2dbd3f4b1464be2acae2cfbff7745c3d7eb [file] [log] [blame]
/*
* Copyright 2000-2009 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.history.integration.ui.models;
import com.intellij.diff.Block;
import com.intellij.diff.FindBlock;
import com.intellij.history.core.Content;
import com.intellij.history.core.revisions.Revision;
import com.intellij.history.core.tree.Entry;
import com.intellij.history.integration.IdeaGateway;
import com.intellij.util.diff.FilesTooBigForDiffException;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class SelectionCalculator {
private static final Block EMPTY_BLOCK = new Block("", 0, 0);
private final IdeaGateway myGateway;
private final List<Revision> myRevisions;
private final int myFromLine;
private final int myToLine;
private final Map<Integer, Block> myCache = new HashMap<Integer, Block>();
public SelectionCalculator(IdeaGateway gw, List<Revision> rr, int fromLine, int toLine) {
myGateway = gw;
myRevisions = rr;
myFromLine = fromLine;
myToLine = toLine;
}
public boolean canCalculateFor(Revision r, Progress p) throws FilesTooBigForDiffException {
try {
doGetSelectionFor(r, p);
}
catch (ContentIsUnavailableException e) {
return false;
}
return true;
}
public Block getSelectionFor(Revision r, Progress p) throws FilesTooBigForDiffException {
return doGetSelectionFor(r, p);
}
private Block doGetSelectionFor(Revision r, Progress p) throws FilesTooBigForDiffException {
int target = myRevisions.indexOf(r);
return getSelectionFor(target, target + 1, p);
}
private Block getSelectionFor(int revisionIndex, int totalRevisions, Progress p) throws FilesTooBigForDiffException {
Block cached = myCache.get(revisionIndex);
if (cached != null) return cached;
String content = getRevisionContent(myRevisions.get(revisionIndex));
p.processed(((totalRevisions - revisionIndex) * 100) / totalRevisions);
Block result;
if (content == null) {
result = EMPTY_BLOCK;
} else if (revisionIndex == 0) {
result = new Block(content, myFromLine, myToLine);
}
else {
Block prev = EMPTY_BLOCK;
int i = revisionIndex;
while(prev == EMPTY_BLOCK && i > 0) {
i--;
prev = getSelectionFor(i, totalRevisions, p);
}
result = new FindBlock(content, prev).getBlockInThePrevVersion();
}
myCache.put(revisionIndex, result);
return result;
}
@Nullable
private String getRevisionContent(Revision r) {
Entry e = r.findEntry();
if (e == null) return null;
Content c = e.getContent();
if (!c.isAvailable()) throw new ContentIsUnavailableException();
return c.getString(e, myGateway);
}
private static class ContentIsUnavailableException extends RuntimeException {
}
}