package jetbrains.mps.baseLanguage.textGen;
/*Generated by MPS */
import org.apache.log4j.Logger;
import org.apache.log4j.LogManager;
import jetbrains.mps.baseLanguage.tuples.runtime.Tuples;
import org.jetbrains.mps.openapi.model.SNode;
import org.jetbrains.mps.openapi.language.SContainmentLink;
import java.util.Map;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations;
import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory;
import org.apache.log4j.Level;
import java.util.Collections;
import jetbrains.mps.baseLanguage.tuples.runtime.MultiTuple;
import java.util.HashMap;
import jetbrains.mps.baseLanguage.behavior.Classifier__BehaviorDescriptor;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations;
import jetbrains.mps.lang.core.behavior.INamedConcept__BehaviorDescriptor;
public class ContextClassifiersInRoot {
private static final Logger LOG = LogManager.getLogger(ContextClassifiersInRoot.class);
private SimpleCache<Tuples._2<SNode, SContainmentLink>, Map<String, String>> contextClassifiersCache;
private SimpleCache<SNode, Map<String, String>> nestedClassifiersCache;
public ContextClassifiersInRoot(SNode rootNode) {
contextClassifiersCache = new SimpleCache<Tuples._2<SNode, SContainmentLink>, Map<String, String>>() {
@Override
protected Map<String, String> innerGet(Tuples._2<SNode, SContainmentLink> key) {
return getContextClassifiers(key._0(), key._1());
}
};
nestedClassifiersCache = new SimpleCache<SNode, Map<String, String>>() {
@Override
protected Map<String, String> innerGet(SNode key) {
return getNestedClassifiers(key);
}
};
}
public Map<String, String> getContextClassifiers(SNode contextNode) {
// only AnonymousClass has Classifier as reference
// todo: make it clearer
if (SNodeOperations.isInstanceOf(contextNode, MetaAdapterFactory.getInterfaceConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x2f89e470eed6258eL, "jetbrains.mps.baseLanguage.structure.IAnonymousClass"))) {
contextNode = SNodeOperations.getParent(contextNode);
}
if (SNodeOperations.isInstanceOf(contextNode, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier"))) {
if (LOG.isEnabledFor(Level.WARN)) {
LOG.warn("contextNode is classifier in getContextClassifiers: " + contextNode);
}
return Collections.emptyMap();
}
// find first classifier in path
SContainmentLink sourceChildRole = null;
while ((contextNode != null) && !(SNodeOperations.isInstanceOf(contextNode, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier")))) {
sourceChildRole = contextNode.getContainmentLink();
contextNode = SNodeOperations.getParent(contextNode);
}
if ((contextNode == null)) {
// todo: impossible?
return Collections.emptyMap();
}
return contextClassifiersCache.get(MultiTuple.<SNode,SContainmentLink>from(SNodeOperations.cast(contextNode, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier")), sourceChildRole));
}
private Map<String, String> getContextClassifiers(SNode contextNode, SContainmentLink sourceChildRole) {
Map<String, String> bindings = new HashMap<String, String>();
SNode current = contextNode;
while ((current != null)) {
if (SNodeOperations.isInstanceOf(current, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier"))) {
boolean processNestedClassifiers = false;
if (SNodeOperations.isInstanceOf(current, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x1107e0cb103L, "jetbrains.mps.baseLanguage.structure.AnonymousClass")) || SNodeOperations.isInstanceOf(current, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfc367070a5L, "jetbrains.mps.baseLanguage.structure.EnumClass"))) {
processNestedClassifiers = true;
} else if (SNodeOperations.isInstanceOf(current, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101edd46144L, "jetbrains.mps.baseLanguage.structure.Interface"))) {
processNestedClassifiers = !(MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101edd46144L, 0x101eddadad7L, "extendedInterface").equals(sourceChildRole));
} else if (SNodeOperations.isInstanceOf(current, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c108ca66L, "jetbrains.mps.baseLanguage.structure.ClassConcept"))) {
processNestedClassifiers = !((MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c108ca66L, 0x10f6353296dL, "superclass").equals(sourceChildRole) || MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c108ca66L, 0xff2ac0b419L, "implementedInterface").equals(sourceChildRole)));
} else {
if (LOG.isEnabledFor(Level.WARN)) {
LOG.warn("Illegal classifier node in bl textgen: " + current);
}
}
// todo: is it true? had a bug with it. Look like nested classifier has more priority then class with same name
addClassifierToBindingMap(bindings, SNodeOperations.cast(current, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier")));
if (processNestedClassifiers) {
for (Map.Entry<String, String> simpleToFqName : nestedClassifiersCache.get(SNodeOperations.cast(current, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier"))).entrySet()) {
if (!(bindings.containsKey(simpleToFqName.getKey()))) {
bindings.put(simpleToFqName.getKey(), simpleToFqName.getValue());
}
}
}
}
// todo: specialized links?
// should not be a problem: superclass/extendedInterface/implementedInterface not specialized
sourceChildRole = current.getContainmentLink();
current = SNodeOperations.getParent(current);
}
return bindings;
}
private static Map<String, String> getNestedClassifiers(SNode classifier) {
// returns map from simpleName to fqName
Map<String, String> nestedClassifiers = new HashMap<String, String>();
// todo: classifiers with same names in different supertypes?
for (SNode superClassifier : Classifier__BehaviorDescriptor.getAllExtendedClassifiers_id2xreLMO8jma.invoke(SNodeOperations.cast(classifier, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier")))) {
for (SNode nestedClassifier : Classifier__BehaviorDescriptor.nestedClassifiers_id4_LVZ3pBjGQ.invoke(superClassifier)) {
addClassifierToBindingMap(nestedClassifiers, nestedClassifier);
}
}
return nestedClassifiers;
}
private static void addClassifierToBindingMap(Map<String, String> bindings, SNode classifier) {
String simpleName = SPropertyOperations.getString(classifier, MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"));
String fqName = INamedConcept__BehaviorDescriptor.getFqName_idhEwIO9y.invoke(classifier);
if (!(bindings.containsKey(simpleName))) {
bindings.put(simpleName, fqName);
}
}
}