package jetbrains.mps.smodel.persistence.def.v6;
/*Generated by MPS */
import org.apache.log4j.Logger;
import org.apache.log4j.LogManager;
import org.jetbrains.mps.openapi.model.SModelReference;
import java.util.Map;
import jetbrains.mps.smodel.SModel;
import java.util.HashMap;
import org.jetbrains.annotations.NotNull;
import jetbrains.mps.vcspersistence.VCSPersistenceUtil;
import org.jetbrains.mps.openapi.model.SReference;
import org.jetbrains.mps.openapi.model.SNode;
import jetbrains.mps.smodel.DynamicReference;
import jetbrains.mps.smodel.StaticReference;
import jetbrains.mps.smodel.SNodeId;
public class VersionUtil {
private static final Logger LOG = LogManager.getLogger(VersionUtil.class);
private static final char VERSION_SEPARATOR_CHAR = ':';
private static final char MODEL_SEPARATOR_CHAR = '.';
private SModelReference myModelRef;
private Map<SModelReference, SModel.ImportElement> myImports;
public VersionUtil(SModel model) {
myModelRef = model.getReference();
myImports = new HashMap<SModelReference, SModel.ImportElement>();
fillReferenceIDs(model);
// replace "-1" indice to valid values and advance maxImportIndex
for (SModel.ImportElement elem : model.importedModels()) {
myImports.put(elem.getModelReference(), elem);
}
for (SModel.ImportElement elem : model.getImplicitImportsSupport().getAdditionalModelVersions()) {
myImports.put(elem.getModelReference(), elem);
}
}
/*package*/ static void fillReferenceIDs(SModel model) {
int maxImport = 0;
for (SModel.ImportElement elem : model.importedModels()) {
maxImport = Math.max(elem.getReferenceID(), maxImport);
}
for (SModel.ImportElement elem : model.getImplicitImportsSupport().getAdditionalModelVersions()) {
maxImport = Math.max(elem.getReferenceID(), maxImport);
}
for (SModel.ImportElement elem : model.importedModels()) {
if (elem.getReferenceID() < 0) {
elem.setReferenceID(++maxImport);
}
}
for (SModel.ImportElement elem : model.getImplicitImportsSupport().getAdditionalModelVersions()) {
if (elem.getReferenceID() < 0) {
elem.setReferenceID(++maxImport);
}
}
}
public String genImportIndex(SModel.ImportElement elem) {
return Integer.toString(elem.getReferenceID());
}
@NotNull
public String genReferenceString(@NotNull SModelReference ref, @NotNull String text, boolean usemodel) {
SModel.ImportElement impElem = myImports.get(ref);
if (impElem == null) {
LOG.error("model " + ref + " not found in imports");
return text;
}
StringBuilder result = new StringBuilder();
if (usemodel && !(myModelRef.equals(ref))) {
result.append(impElem.getReferenceID()).append(MODEL_SEPARATOR_CHAR);
}
result.append(text);
if (impElem.getUsedVersion() >= 0) {
result.append(VERSION_SEPARATOR_CHAR).append(impElem.getUsedVersion());
}
return result.toString();
}
private Map<Integer, SModel.ImportElement> myImportByIx;
public VersionUtil(SModelReference modelRef) {
myModelRef = modelRef;
myImports = new HashMap<SModelReference, SModel.ImportElement>();
myImportByIx = new HashMap<Integer, SModel.ImportElement>();
}
public void addImport(SModel model, String index, String modelUID, int version, boolean implicit) {
if (modelUID == null) {
LOG.error("Error loading import element for index " + index + " in " + myModelRef);
return;
}
int ix = Integer.parseInt(index);
SModelReference modelRef = VCSPersistenceUtil.createModelReference(modelUID);
SModel.ImportElement elem = new SModel.ImportElement(modelRef, ix, version);
myImports.put(modelRef, elem);
myImportByIx.put(ix, elem);
if (implicit) {
model.getImplicitImportsSupport().addAdditionalModelVersion(elem);
} else
model.addModelImport(elem);
}
public SModelReference getSModelReference(int ix) {
return (ix == -1 ? myModelRef : myImportByIx.get(ix).getModelReference());
}
private static class ParseResult {
public int modelID;
public String text;
public int version;
}
private VersionUtil.ParseResult parse(String src, boolean hasmodel) {
VersionUtil.ParseResult res = parseWithoutCheck(src, hasmodel);
// check integrity except concepts and attribute roles
if (hasmodel) {
// && !AttributeOperations.isOldAttributeRole(res.text)) { // todo: ? remove this persistence?
SModel.ImportElement elem = myImports.get(getSModelReference(res.modelID));
if (elem == null || res.version != myImports.get(getSModelReference(res.modelID)).getUsedVersion()) {
LOG.error("wrong version of " + src + ", model=" + getSModelReference(res.modelID) + ". Possible reason: merge conflict was not resolved.");
}
}
return res;
}
private static VersionUtil.ParseResult parseWithoutCheck(String src, boolean hasmodel) {
VersionUtil.ParseResult res = new VersionUtil.ParseResult();
char[] chars = src.toCharArray();
int i0 = -1;
int i1 = chars.length;
if (hasmodel) {
// false means we shouldn't try to parse model id
while (++i0 < i1) {
if (!(Character.isDigit(chars[i0]))) {
break;
}
}
if (i0 == i1 || chars[i0] != MODEL_SEPARATOR_CHAR) {
i0 = -1;
}
}
while (i0 < --i1) {
if (!(Character.isDigit(chars[i1]))) {
break;
}
}
if (i0 == i1 || chars[i1] != VERSION_SEPARATOR_CHAR) {
i1 = chars.length;
}
res.text = src.substring(i0 + 1, i1);
res.modelID = (i0 > 0 ? Integer.parseInt(src.substring(0, i0)) : -1);
res.version = (i1 < chars.length - 1 ? Integer.parseInt(src.substring(i1 + 1)) : -1);
return res;
}
public String readType(String s) {
return parse(s, false).text;
}
public String readRole(String s) {
return parse(s, true).text;
}
public String readName(String s) {
return parse(s, true).text;
}
public SReference readLink(SNode node, String rawRole, String rawTarget, String resolveInfo) {
String role = readRole(rawRole);
VersionUtil.ParseResult target = parse(rawTarget, true);
SModelReference modelRef = getSModelReference(target.modelID);
if (modelRef == null) {
LOG.error("couldn't create reference '" + role + "' : import for index [" + target.modelID + "] not found");
return null;
} else
if (target.text.equals("^")) {
return new DynamicReference(role, node, modelRef, resolveInfo);
} else {
return new StaticReference(role, node, modelRef, SNodeId.fromString(target.text), resolveInfo);
}
}
public static String readRoleSimple(String s) {
return parseWithoutCheck(s, true).text;
}
}