package models; import org.apache.commons.io.FileUtils; import org.apache.jena.atlas.RuntimeIOException; import play.Logger; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** * Created by fo on 24.03.16. */ public class GraphHistory { private final File mCommitDir; private final File mHistoryFile; private final Map<String, List<Commit>> mIndex; private final List<Commit> mLog; public GraphHistory(File aCommitDir, File aHistoryFile) { if (!aCommitDir.isDirectory() || !aCommitDir.canWrite()) { throw new IllegalArgumentException("Not a writable directory: " + aCommitDir); } if (!aHistoryFile.isFile() || !aHistoryFile.canWrite()) { throw new IllegalArgumentException("Not a writable file: " + aHistoryFile); } mCommitDir = aCommitDir; mHistoryFile = aHistoryFile; mIndex = new HashMap<>(); mLog = new ArrayList<>(); for (Commit commit : this.fetch()) { indexCommit(commit); } } public void add(Commit aCommit) throws IOException { String commitId = aCommit.getId(); File commitFile = new File(mCommitDir, commitId); FileUtils.writeStringToFile(commitFile, aCommit.toString(), StandardCharsets.UTF_8); FileUtils.writeStringToFile(mHistoryFile, commitId.concat("\n"), StandardCharsets.UTF_8, true); indexCommit(aCommit); } public int size() { return mLog.size(); } public List<Commit> log() { return mLog; } public List<Commit> log(String aURI) { if (!mIndex.containsKey(aURI)) { return new ArrayList<>(); } return mIndex.get(aURI); } public List<Commit> until(String aCommitId) { List<Commit> commits = new ArrayList<>(); for (Commit commit : log()) { if (commit.getId().equals(aCommitId)) { break; } commits.add(commit); } return commits; } private List<Commit> fetch() { List<String> commitIds; try { commitIds = FileUtils.readLines(mHistoryFile, StandardCharsets.UTF_8); } catch (IOException e) { throw new RuntimeIOException(e); } List<Commit> commits = new ArrayList<>(); for (String commitId : commitIds) { File commitFile = new File(mCommitDir, commitId); try { TripleCommit commit = TripleCommit.fromString(FileUtils.readFileToString(commitFile, StandardCharsets.UTF_8)); commits.add(commit); } catch (IllegalArgumentException | IOException e) { Logger.trace("Could not read commit, skipping", e); } } return commits; } private Set<String> getModified(Commit aCommit) { Set<String> modified = new HashSet<>(); for (Commit.Diff.Line line : aCommit.getDiff().getLines()) { org.apache.jena.rdf.model.Resource subject = ((TripleCommit.Diff.Line) line).stmt.getSubject(); org.apache.jena.rdf.model.RDFNode object = ((TripleCommit.Diff.Line) line).stmt.getObject(); if (subject.isURIResource()) { modified.add(subject.toString()); } if (object.isURIResource()) { modified.add(object.toString()); } } return modified; } private void indexCommit(Commit aCommit) { mLog.add(0, aCommit); for (String id : getModified(aCommit)) { if (!mIndex.containsKey(id)) { mIndex.put(id, new ArrayList<>()); } mIndex.get(id).add(0, aCommit); } } }