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; } }