package jetbrains.mps.project.persistence;
/*Generated by MPS */
import org.apache.log4j.Logger;
import org.apache.log4j.LogManager;
import jetbrains.mps.project.structure.modules.ModuleDescriptor;
import org.jdom.Element;
import jetbrains.mps.util.xml.XmlUtil;
import jetbrains.mps.internal.collections.runtime.Sequence;
import jetbrains.mps.internal.collections.runtime.IVisitor;
import org.jetbrains.mps.openapi.language.SLanguage;
import jetbrains.mps.smodel.adapter.structure.language.SLanguageAdapter;
import jetbrains.mps.smodel.adapter.ids.SLanguageId;
import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory;
import org.jetbrains.mps.openapi.module.SModuleReference;
import org.jetbrains.mps.openapi.persistence.PersistenceFacade;
import jetbrains.mps.project.structure.modules.LanguageDescriptor;
import jetbrains.mps.project.structure.modules.Dependency;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import java.util.Map;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Set;
import jetbrains.mps.internal.collections.runtime.SetSequence;
import jetbrains.mps.internal.collections.runtime.ISelector;
import java.util.List;
import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes;
import org.jetbrains.mps.openapi.module.SDependencyScope;
import java.util.Collection;
import jetbrains.mps.internal.collections.runtime.CollectionSequence;
import jetbrains.mps.project.structure.model.ModelRootDescriptor;
import jetbrains.mps.util.MacroHelper;
import org.jetbrains.mps.openapi.persistence.Memento;
import jetbrains.mps.persistence.MementoImpl;
import org.apache.log4j.Level;
import jetbrains.mps.project.structure.modules.ModuleFacetDescriptor;
import org.jdom.Attribute;
import jetbrains.mps.internal.collections.runtime.IWhereFilter;
import jetbrains.mps.vfs.IFile;
import jetbrains.mps.util.FileUtil;
import jetbrains.mps.project.ModuleId;
import java.io.InputStreamReader;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.io.IOException;
public class ModuleDescriptorPersistence {
private static final Logger LOG = LogManager.getLogger(ModuleDescriptorPersistence.class);
private static final String HEADER_PATTERN = ".*<(language|dev-kit|solution)[^>]+(namespace|name)=\\\"([^\"]+)\\\"[^>]+uuid=\\\"([^\"]+)\\\".*";
private ModuleDescriptorPersistence() {
}
public static void loadDependencies(final ModuleDescriptor descriptor, Element root) {
descriptor.getDependencies().addAll(loadDependenciesList(XmlUtil.first(root, "dependencies")));
descriptor.setHasLanguageVersions(!(root.getChildren("languageVersions").isEmpty()));
Sequence.fromIterable(XmlUtil.children(XmlUtil.first(root, "languageVersions"), "language")).visitAll(new IVisitor<Element>() {
public void visit(Element it) {
String slang = it.getAttributeValue("slang");
SLanguage lang;
if (slang != null) {
lang = SLanguageAdapter.deserialize(slang);
} else {
// support old format using id+name pair, used before 3.4
SLanguageId id = SLanguageId.deserialize(it.getAttributeValue("id"));
String name = it.getAttributeValue("fqName");
lang = MetaAdapterFactory.getLanguage(id, name);
}
descriptor.getLanguageVersions().put(lang, Integer.parseInt(it.getAttributeValue("version")));
}
});
descriptor.setHasDependencyVersions(!(root.getChildren("dependencyVersions").isEmpty()));
Sequence.fromIterable(XmlUtil.children(XmlUtil.first(root, "dependencyVersions"), "module")).visitAll(new IVisitor<Element>() {
public void visit(Element it) {
SModuleReference id = PersistenceFacade.getInstance().createModuleReference(it.getAttributeValue("reference"));
descriptor.getDependencyVersions().put(id, Integer.parseInt(it.getAttributeValue("version")));
}
});
if (descriptor instanceof LanguageDescriptor) {
LanguageDescriptor ld = (LanguageDescriptor) descriptor;
Element runtimeXML = XmlUtil.first(root, "runtime");
if (runtimeXML != null) {
for (Dependency dep : ListSequence.fromList(loadDependenciesList(runtimeXML))) {
ld.getRuntimeModules().add(dep.getModuleRef());
}
}
}
}
public static void saveDependencies(Element result, ModuleDescriptor descriptor) {
if (!(descriptor.getDependencies().isEmpty())) {
Element dependencies = new Element("dependencies");
saveDependencyList(dependencies, descriptor.getDependencies());
result.addContent(dependencies);
}
Map<SLanguage, Integer> lver = descriptor.getLanguageVersions();
ArrayList<SLanguage> langs = new ArrayList<SLanguage>(lver.keySet());
Collections.sort(langs, new Comparator<SLanguage>() {
public int compare(SLanguage p0, SLanguage p1) {
return p0.getQualifiedName().compareTo(p1.getQualifiedName());
}
});
Element languageVersions = new Element("languageVersions");
for (SLanguage l : langs) {
Element languageVersion = new Element("language");
languageVersion.setAttribute("slang", ((SLanguageAdapter) l).serialize());
languageVersion.setAttribute("version", String.valueOf(lver.get(l)));
languageVersions.addContent(languageVersion);
}
result.addContent(languageVersions);
Map<SModuleReference, Integer> depVer = descriptor.getDependencyVersions();
ArrayList<SModuleReference> deps = new ArrayList<SModuleReference>(depVer.keySet());
Collections.sort(deps, new Comparator<SModuleReference>() {
public int compare(SModuleReference p0, SModuleReference p1) {
return p0.getModuleName().compareTo(p1.getModuleName());
}
});
Element dependencyVersions = new Element("dependencyVersions");
for (SModuleReference ref : deps) {
Element moduleVersion = new Element("module");
moduleVersion.setAttribute("reference", ref.toString());
moduleVersion.setAttribute("version", String.valueOf(depVer.get(ref)));
dependencyVersions.addContent(moduleVersion);
}
result.addContent(dependencyVersions);
if (descriptor instanceof LanguageDescriptor) {
LanguageDescriptor ld = ((LanguageDescriptor) descriptor);
if (!(ld.getRuntimeModules().isEmpty())) {
Element runtime = new Element("runtime");
Set<SModuleReference> runtimeModules = ld.getRuntimeModules();
saveDependencyList(runtime, SetSequence.fromSet(runtimeModules).select(new ISelector<SModuleReference, Dependency>() {
public Dependency select(SModuleReference it) {
return new Dependency(it, false);
}
}).toListSequence());
result.addContent(runtime);
}
}
}
public static List<Dependency> loadDependenciesList(Element depElement) {
return Sequence.fromIterable(XmlUtil.children(depElement, "dependency")).select(new ISelector<Element, Dependency>() {
public Dependency select(final Element d) {
return new _FunctionTypes._return_P0_E0<Dependency>() {
public Dependency invoke() {
final Dependency result_dxyzb6_a0a0a0a0a0a8 = new Dependency();
final SModuleReference result_dxyzb6_a0a0a0a0a0a0a8 = PersistenceFacade.getInstance().createModuleReference(d.getText());
result_dxyzb6_a0a0a0a0a0a8.setModuleRef(result_dxyzb6_a0a0a0a0a0a0a8);
final boolean result_dxyzb6_a1a0a0a0a0a0a8 = XmlUtil.booleanWithDefault(d, "reexport", true);
result_dxyzb6_a0a0a0a0a0a8.setReexport(result_dxyzb6_a1a0a0a0a0a0a8);
SDependencyScope s = SDependencyScope.fromIdentity(d.getAttributeValue("scope"));
final SDependencyScope result_dxyzb6_a3a0a0a0a0a0a8 = (s == null ? SDependencyScope.DEFAULT : s);
result_dxyzb6_a0a0a0a0a0a8.setScope(result_dxyzb6_a3a0a0a0a0a0a8);
return result_dxyzb6_a0a0a0a0a0a8;
}
}.invoke();
}
}).toListSequence();
}
private static void saveDependencyList(Element result, Collection<Dependency> dependencies) {
for (Dependency md : CollectionSequence.fromCollection(dependencies)) {
Element child = new Element("dependency");
child.setAttribute("reexport", Boolean.toString(md.isReexport()));
child.setText(md.getModuleRef().toString());
if (md.getScope() != SDependencyScope.DEFAULT) {
// the only reason not to serialize DEFIAULT for now is to avoid extra diff with existing descriptors meanwhile
// Once there's migration action, it might be reasonable to serialize each scope
child.setAttribute("scope", md.getScope().identify());
}
result.addContent(child);
}
}
public static List<ModelRootDescriptor> loadModelRoots(Iterable<Element> modelRootElements, MacroHelper macroHelper) {
List<ModelRootDescriptor> result = ListSequence.fromList(new ArrayList<ModelRootDescriptor>());
for (Element element : modelRootElements) {
Memento m = new MementoImpl();
readMemento(m, element, macroHelper);
String type = element.getAttributeValue("type");
if (type == null) {
// This is debug code to find out cause of https://youtrack.jetbrains.com/issue/MPS-22589.
String msg = String.format("Unsupported model root detected in module at %s. Likely outdated module is being loaded, please check your environment", macroHelper.expandPath("${module}"));
if (LOG.isEnabledFor(Level.ERROR)) {
LOG.error(msg);
}
throw new IllegalStateException(msg);
}
ListSequence.fromList(result).addElement(new ModelRootDescriptor(type, m));
}
return result;
}
public static List<ModuleFacetDescriptor> loadFacets(Iterable<Element> facetElements, MacroHelper macroHelper) {
List<ModuleFacetDescriptor> result = ListSequence.fromList(new ArrayList<ModuleFacetDescriptor>());
for (Element element : facetElements) {
Memento m = new MementoImpl();
readMemento(m, element, macroHelper);
String type = element.getAttributeValue("type");
if (type != null) {
ListSequence.fromList(result).addElement(new ModuleFacetDescriptor(type, m));
}
}
return result;
}
public static void readMemento(Memento memento, Element element, final MacroHelper macroHelper) {
for (Attribute attr : (List<Attribute>) element.getAttributes()) {
String name = attr.getName();
memento.put(name, (isPathAttribute(name) ? macroHelper.expandPath(attr.getValue()) : attr.getValue()));
}
for (Element elem : (List<Element>) element.getChildren()) {
Memento child = memento.createChild(elem.getName());
readMemento(child, elem, macroHelper);
}
}
public static void writeMemento(Memento memento, Element element, final MacroHelper macroHelper) {
for (String key : memento.getKeys()) {
element.setAttribute(key, (isPathAttribute(key) ? macroHelper.shrinkPath(memento.get(key)) : memento.get(key)));
}
for (Memento childMemento : memento.getChildren()) {
Element child = new Element(childMemento.getType());
writeMemento(childMemento, child, macroHelper);
element.addContent(child);
}
}
private static boolean isPathAttribute(String name) {
return name.equals("path") || name.endsWith("Path");
}
public static List<String> loadStubModelEntries(Element stubModelEntriesElement, final MacroHelper macroHelper) {
return Sequence.fromIterable(XmlUtil.children(stubModelEntriesElement, "stubModelEntry")).select(new ISelector<Element, String>() {
public String select(Element mre) {
return loadStubModelEntry(mre, macroHelper);
}
}).where(new IWhereFilter<String>() {
public boolean accept(String it) {
return it != null;
}
}).toListSequence();
}
private static String loadStubModelEntry(Element modelRootElement, MacroHelper macroHelper) {
Element manager = XmlUtil.first(modelRootElement, "manager");
if (manager != null) {
String className = XmlUtil.stringWithDefault(manager, "className", "");
if (!("jetbrains.mps.baseLanguage.stubs.JavaStubs".equals(className))) {
return null;
}
}
return macroHelper.expandPath(modelRootElement.getAttributeValue("path"));
}
public static void saveFacets(Element result, Collection<ModuleFacetDescriptor> facets, MacroHelper macroHelper) {
for (ModuleFacetDescriptor facet : CollectionSequence.fromCollection(facets)) {
Memento memento = facet.getMemento();
Element facetElement = new Element("facet");
writeMemento(memento, facetElement, macroHelper);
String type = facet.getType();
facetElement.setAttribute("type", type);
result.addContent(facetElement);
}
}
public static void saveModelRoots(Element result, Collection<ModelRootDescriptor> modelRoots, MacroHelper macroHelper) {
for (ModelRootDescriptor root : CollectionSequence.fromCollection(modelRoots)) {
Memento memento = root.getMemento();
Element modelRoot = new Element("modelRoot");
writeMemento(memento, modelRoot, macroHelper);
String type = root.getType();
if ((type != null && type.length() > 0) && !("obsolete".equals(type))) {
modelRoot.setAttribute("type", type);
} else {
modelRoot.removeAttribute("type");
}
result.addContent(modelRoot);
}
}
public static void saveStubModelEntries(Element result, Collection<String> entries, MacroHelper macroHelper) {
for (String root : entries) {
Element stubModelEntry = new Element("stubModelEntry");
stubModelEntry.setAttribute("path", macroHelper.shrinkPath((root == null ? "" : root)));
result.addContent(stubModelEntry);
}
}
public static void setTimestamp(ModuleDescriptor descriptor, IFile file) {
descriptor.setTimestamp(Long.toString(file.lastModified()));
}
public static void loadBrokenModule(ModuleDescriptor md, IFile file, ModuleReadException exception) {
if (LOG.isEnabledFor(Level.WARN)) {
LOG.warn("Module descriptor " + md + " from the file " + file + " has been loaded with error " + exception);
}
md.setNamespace(FileUtil.getNameWithoutExtension(file.getName()));
md.setId(ModuleId.regular());
InputStreamReader r = null;
try {
r = new InputStreamReader(file.openInputStream(), FileUtil.DEFAULT_CHARSET);
char[] buf = new char[1024];
int readChars = r.read(buf);
if (readChars >= 0) {
String s = new String(buf, 0, readChars);
Pattern pattern = Pattern.compile(HEADER_PATTERN);
for (String line : s.split("\n")) {
Matcher m = pattern.matcher(line);
if (m.matches()) {
md.setNamespace(m.group(3));
md.setId(ModuleId.fromString(m.group(4)));
}
}
}
} catch (IOException e) {
if (LOG.isEnabledFor(Level.ERROR)) {
LOG.error("", e);
}
} finally {
FileUtil.closeFileSafe(r);
}
setTimestamp(md, file);
md.setLoadException((exception.getCause() == null ? exception : exception.getCause()));
}
}