package jetbrains.mps.internal.make.runtime.util;
/*Generated by MPS */
import jetbrains.mps.make.delta.IDelta;
import org.apache.log4j.Logger;
import org.apache.log4j.LogManager;
import java.util.Map;
import jetbrains.mps.vfs.IFile;
import jetbrains.mps.internal.collections.runtime.MapSequence;
import java.util.HashMap;
import jetbrains.mps.make.delta.IDeltaVisitor;
import jetbrains.mps.vfs.FileSystem;
import jetbrains.mps.internal.collections.runtime.IVisitor;
import jetbrains.mps.internal.collections.runtime.IMapping;
import java.util.Set;
import jetbrains.mps.internal.collections.runtime.SetSequence;
import java.util.HashSet;
public class FilesDelta implements IDelta {
private static Logger LOG = LogManager.getLogger(FilesDelta.class);
private Map<IFile, FilesDelta.Status> files = MapSequence.fromMap(new HashMap<IFile, FilesDelta.Status>());
private final String key;
public FilesDelta(IFile dir) {
this.key = DirUtil.asDir(DirUtil.straighten(DirUtil.urlToPath(dir.getPath())));
}
private FilesDelta(FilesDelta copyFrom) {
this.key = copyFrom.key;
MapSequence.fromMap(this.files).putAll(copyFrom.files);
}
public void written(IFile file) {
MapSequence.fromMap(files).put(file, FilesDelta.Status.WRITTEN);
}
public void kept(IFile file) {
MapSequence.fromMap(files).put(file, FilesDelta.Status.KEPT);
}
public void deleted(IFile file) {
MapSequence.fromMap(files).put(file, FilesDelta.Status.DELETED);
}
public void stale(IFile file) {
if (!(MapSequence.fromMap(files).containsKey(file))) {
MapSequence.fromMap(files).put(file, FilesDelta.Status.STALE);
}
}
@Override
public boolean reconcile() {
return acceptVisitor(new FilesDelta.Visitor() {
@Override
public boolean acceptDeleted(IFile file) {
FilesDelta.LOG.debug("Reconciled: deleting " + file);
try {
file.delete();
} catch (RuntimeException ignore) {
FilesDelta.LOG.error("Exception deleting file " + file, ignore);
}
return true;
}
});
}
@Override
public boolean acceptVisitor(IDeltaVisitor visitor) {
if (!(visitor instanceof FilesDelta.Visitor)) {
return true;
}
return acceptFilesVisitor(((FilesDelta.Visitor) visitor));
}
@Override
public IDelta merge(IDelta toMerge) {
if (!(toMerge instanceof FilesDelta)) {
throw new IllegalArgumentException();
}
FilesDelta that = (FilesDelta) toMerge;
if (this.contains(that)) {
return new FilesDelta(this).copy(that);
} else if (toMerge.contains(this)) {
return new FilesDelta(that).copy(this);
}
String commonPrefix = DirUtil.commonDirPrefix(this.key, that.key);
if (!(commonPrefix.isEmpty())) {
return new FilesDelta(FileSystem.getInstance().getFileByPath(commonPrefix)).copy(this).copy(that);
}
throw new IllegalArgumentException();
}
private boolean acceptFilesVisitor(final FilesDelta.Visitor visitor) {
MapSequence.fromMap(files).visitAll(new IVisitor<IMapping<IFile, FilesDelta.Status>>() {
public void visit(IMapping<IFile, FilesDelta.Status> m) {
if (m.value() == FilesDelta.Status.KEPT && !(m.key().isDirectory())) {
visitor.acceptKept(m.key());
} else if (m.value() == FilesDelta.Status.WRITTEN) {
visitor.acceptWritten(m.key());
} else if (m.value() == FilesDelta.Status.DELETED || m.value() == FilesDelta.Status.STALE) {
visitor.acceptDeleted(m.key());
}
}
});
return true;
}
private FilesDelta copy(FilesDelta that) {
// provided there's this.contains(that) call before copy()
// DirUtil.startsWith(that, this) == true
if (!(DirUtil.startsWith(that.key, this.key))) {
throw new IllegalArgumentException();
}
Set<IFile> newlyTouchedDirs = SetSequence.fromSet(new HashSet<IFile>());
// copy all but stale values, stale entries shall not override explicitly set
for (IFile file : MapSequence.fromMap(that.files).keySet()) {
FilesDelta.Status newStatus = MapSequence.fromMap(that.files).get(file);
if (newStatus == FilesDelta.Status.STALE && MapSequence.fromMap(files).containsKey(file)) {
continue;
} else {
MapSequence.fromMap(files).put(file, newStatus);
}
SetSequence.fromSet(newlyTouchedDirs).addElement((file.isDirectory() ? file : file.getParent()));
}
// in case we've got stale directory, check if any updates from that didn't touch it
for (IFile file : MapSequence.fromMap(files).keySet()) {
if (MapSequence.fromMap(files).get(file) == FilesDelta.Status.STALE && file.isDirectory()) {
String staleDir = DirUtil.normalizeAsDir(file.getPath());
for (IFile touchDir : newlyTouchedDirs) {
// if staleDir is parent of any newly touched directories, it's not stale any more
if (DirUtil.startsWith(DirUtil.normalizeAsDir(touchDir.getPath()), staleDir)) {
MapSequence.fromMap(files).put(file, FilesDelta.Status.KEPT);
break;
}
}
}
}
return this;
}
@Override
public boolean contains(IDelta other) {
if (!(other instanceof FilesDelta)) {
return false;
}
FilesDelta that = (FilesDelta) other;
if (that.key.equals(this.key)) {
return true;
}
return DirUtil.startsWith(that.key, this.key);
}
public static class Visitor implements IDeltaVisitor {
public Visitor() {
}
public boolean acceptWritten(IFile file) {
return true;
}
public boolean acceptKept(IFile file) {
return true;
}
public boolean acceptDeleted(IFile file) {
return true;
}
}
/**
* DELETED are files explicitly requested to be removed
* STALE are files that are likely to need removal, unless there's another subsequent
* delta that bring them back to life.
*/
public enum Status {
WRITTEN(),
KEPT(),
DELETED(),
STALE();
private Status() {
}
}
}