package jetbrains.mps.vcs.changesmanager;
/*Generated by MPS */
import org.apache.log4j.Logger;
import org.apache.log4j.LogManager;
import org.jetbrains.annotations.NotNull;
import com.intellij.openapi.vcs.FileStatus;
import org.jetbrains.annotations.Nullable;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.project.Project;
import jetbrains.mps.smodel.ModelAccess;
import org.apache.log4j.Level;
import com.intellij.openapi.vcs.AbstractVcs;
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.diff.DiffProvider;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import com.intellij.openapi.vcs.changes.ContentRevision;
import com.intellij.openapi.vcs.changes.BinaryContentRevision;
import com.intellij.openapi.vcs.VcsException;
import org.jetbrains.mps.openapi.model.SModel;
import org.jetbrains.mps.openapi.persistence.DataSource;
import jetbrains.mps.extapi.persistence.FileDataSource;
import jetbrains.mps.vfs.IFile;
import jetbrains.mps.ide.vfs.VirtualFileUtils;
import com.intellij.openapi.vcs.FileStatusManager;
import jetbrains.mps.util.FileUtil;
import jetbrains.mps.vcspersistence.VCSPersistenceUtil;
import jetbrains.mps.persistence.FilePerRootDataSource;
import java.util.Map;
import jetbrains.mps.internal.collections.runtime.MapSequence;
import java.util.HashMap;
import jetbrains.mps.project.MPSExtentions;
import org.jetbrains.mps.openapi.persistence.ModelFactory;
import jetbrains.mps.extapi.persistence.ModelFactoryService;
import jetbrains.mps.persistence.PreinstalledModelFactoryTypes;
import jetbrains.mps.persistence.PersistenceUtil;
import org.jetbrains.mps.openapi.persistence.datasource.DataSourceType;
import java.io.InputStream;
import java.io.IOException;
import java.io.ByteArrayInputStream;
import java.util.Collections;
public class BaseVersionUtil {
private static final Logger LOG = LogManager.getLogger(BaseVersionUtil.class);
private BaseVersionUtil() {
}
public static boolean isAddedFileStatus(@NotNull FileStatus status) {
return status == FileStatus.ADDED || status == FileStatus.UNKNOWN || status == FileStatus.IGNORED;
}
@Nullable
public static Object getBaseVersionContent(@NotNull VirtualFile file, @NotNull Project project) {
if (ModelAccess.instance().canRead()) {
if (LOG.isEnabledFor(Level.ERROR)) {
LOG.error("BaseVersionUtil.getBaseVersionContent() is invoked from read action: possible deadlock", new IllegalStateException());
}
}
try {
AbstractVcs vcs = ProjectLevelVcsManager.getInstance(project).getVcsFor(file);
if (vcs == null) {
return null;
}
DiffProvider diffProvider = vcs.getDiffProvider();
if (diffProvider == null) {
return null;
}
VcsRevisionNumber revisionNumber = diffProvider.getCurrentRevision(file);
if (revisionNumber == null) {
return null;
}
ContentRevision revision = diffProvider.createFileContent(revisionNumber, file);
if (revision == null) {
return null;
}
if (revision instanceof BinaryContentRevision) {
return ((BinaryContentRevision) revision).getBinaryContent();
}
return revision.getContent();
} catch (VcsException ex) {
if (LOG.isEnabledFor(Level.WARN)) {
LOG.warn("VcsException during getting base version content: ", ex);
}
return null;
}
}
@Nullable
public static SModel getBaseVersionModel(SModel model, Project project) {
DataSource ds = model.getSource();
if (ds instanceof FileDataSource) {
IFile file = ((FileDataSource) ds).getFile();
if (!(file.exists())) {
return null;
}
VirtualFile vFile = VirtualFileUtils.getProjectVirtualFile(file);
if (vFile == null || ProjectLevelVcsManager.getInstance(project).getVcsFor(vFile) == null) {
return null;
}
Object content = BaseVersionUtil.getBaseVersionContent(vFile, project);
if (content == null) {
FileStatus status = FileStatusManager.getInstance(project).getStatus(vFile);
if (status != FileStatus.NOT_CHANGED) {
if (LOG.isEnabledFor(Level.ERROR)) {
LOG.error("Base version content is null while file status is " + status);
}
}
return null;
}
String ext = vFile.getExtension();
byte[] modelData = (content instanceof String ? ((String) content).getBytes(FileUtil.DEFAULT_CHARSET) : (byte[]) content);
return VCSPersistenceUtil.loadModel(modelData, ext);
} else if (ds instanceof FilePerRootDataSource) {
FilePerRootDataSource rds = (FilePerRootDataSource) ds;
Map<String, Object> content = MapSequence.fromMap(new HashMap<String, Object>());
for (String stream : rds.getAvailableStreams()) {
IFile file = rds.getFile(stream);
VirtualFile vFile = VirtualFileUtils.getProjectVirtualFile(file);
if (vFile == null) {
continue;
}
Object o = BaseVersionUtil.getBaseVersionContent(vFile, project);
if (o == null) {
continue;
}
MapSequence.fromMap(content).put(stream, o);
}
if (MapSequence.fromMap(content).containsKey(MPSExtentions.DOT_MODEL_HEADER)) {
// no base version for ".model" file means there was no model
return loadPerRootModel(content);
}
}
return null;
}
private static SModel loadPerRootModel(final Map<String, Object> content) {
ModelFactory factory = ModelFactoryService.getInstance().getFactoryByType(PreinstalledModelFactoryTypes.PER_ROOT_XML);
if (factory == null || factory.isBinary()) {
return null;
}
try {
SModel model = factory.load(new PersistenceUtil.MultiStreamDataSourceBase() {
@Override
public DataSourceType getType() {
return null;
}
@NotNull
@Override
public Iterable<String> getAvailableStreams() {
return content.keySet();
}
@NotNull
@Override
public InputStream openInputStream(String name) throws IOException {
Object data = content.get(name);
if (data instanceof String) {
return new ByteArrayInputStream(((String) data).getBytes(FileUtil.DEFAULT_CHARSET));
} else
if (data instanceof byte[]) {
return new ByteArrayInputStream((byte[]) data);
}
throw new UnsupportedOperationException("Unknown content type : " + content + "; name of the stream: " + name);
}
}, Collections.<String,String>emptyMap());
model.load();
return model;
} catch (IOException ex) {
return null;
}
}
}