package jetbrains.mps.ide.java.util;
/*Generated by MPS */
import org.apache.log4j.Logger;
import org.apache.log4j.LogManager;
import jetbrains.mps.smodel.SModelStereotype;
import jetbrains.mps.smodel.LanguageID;
import java.util.Set;
import org.jetbrains.mps.openapi.model.SModelReference;
import org.jetbrains.mps.openapi.module.SRepository;
import org.jetbrains.mps.openapi.model.SModel;
import jetbrains.mps.internal.collections.runtime.SetSequence;
import java.util.HashSet;
import jetbrains.mps.internal.collections.runtime.Sequence;
import jetbrains.mps.internal.collections.runtime.ISelector;
import java.util.List;
import org.jetbrains.mps.openapi.model.SReference;
import java.util.Map;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import java.util.ArrayList;
import jetbrains.mps.smodel.ModuleRepositoryFacade;
import org.jetbrains.mps.openapi.model.SNode;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SModelOperations;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations;
import jetbrains.mps.internal.collections.runtime.MapSequence;
import java.util.HashMap;
import jetbrains.mps.internal.collections.runtime.IWhereFilter;
import jetbrains.mps.internal.collections.runtime.IVisitor;
import jetbrains.mps.smodel.SModelInternal;
import jetbrains.mps.kernel.model.MissingDependenciesFixer;
import jetbrains.mps.project.OptimizeImportsHelper;
import jetbrains.mps.project.MPSProject;
import org.jetbrains.mps.openapi.module.SModule;
import org.jetbrains.mps.openapi.model.EditableSModel;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations;
import jetbrains.mps.scope.Scope;
import jetbrains.mps.smodel.constraints.ModelConstraints;
import jetbrains.mps.scope.ErrorScope;
import jetbrains.mps.typesystem.inference.TypeContextManager;
import jetbrains.mps.util.Computable;
import jetbrains.mps.internal.collections.runtime.IListSequence;
import org.apache.log4j.Level;
import org.jetbrains.mps.openapi.model.SNodeAccessUtil;
public class StubResolver {
private static final Logger LOG = LogManager.getLogger(StubResolver.class);
private static final String JAVA_STUB = SModelStereotype.getStubStereotypeForId(LanguageID.JAVA);
private Set<SModelReference> myUsedModels;
private final SRepository myContextRepository;
public StubResolver(SRepository contextRepo) {
// resolve to any nonstub model
myUsedModels = null;
myContextRepository = contextRepo;
}
public StubResolver(SRepository contextRepo, Iterable<SModel> models) {
// resolve only to models from sequence
myUsedModels = SetSequence.fromSetWithValues(new HashSet<SModelReference>(), Sequence.fromIterable(models).select(new ISelector<SModel, SModelReference>() {
public SModelReference select(SModel it) {
return it.getReference();
}
}));
myContextRepository = contextRepo;
}
private List<SReference> getReferencesToResolve(SModel sourceModel, Map<SModelReference, SModelReference> models) {
// fills models map with stub -> model correspondance
List<SReference> result = ListSequence.fromList(new ArrayList<SReference>());
ModuleRepositoryFacade repoFacade = new ModuleRepositoryFacade(myContextRepository);
for (SNode node : ListSequence.fromList(SModelOperations.nodes(sourceModel, null))) {
for (SReference ref : ListSequence.fromList(SNodeOperations.getReferences(node))) {
SModelReference targetModelRef = ref.getTargetSModelReference();
if (targetModelRef == null || !(JAVA_STUB.equals(targetModelRef.getName().getStereotype()))) {
continue;
}
// trying to find correspondent nonstub model
SModelReference modelRef = check_ar1im2_a0d0a0d0h(repoFacade.getModelByName(targetModelRef.getName().getLongName()));
if (modelRef == null) {
continue;
}
if (myUsedModels == null || SetSequence.fromSet(myUsedModels).contains(modelRef)) {
MapSequence.fromMap(models).put(targetModelRef, modelRef);
ListSequence.fromList(result).addElement(ref);
}
}
}
return result;
}
public void resolveInModel(final SModel model) {
Map<SModelReference, SModelReference> models = MapSequence.fromMap(new HashMap<SModelReference, SModelReference>());
List<SReference> toResolve = getReferencesToResolve(model, models);
if (ListSequence.fromList(toResolve).isEmpty()) {
return;
}
Iterable<SModelReference> modelsToAdd = Sequence.fromIterable(MapSequence.fromMap(models).values()).where(new IWhereFilter<SModelReference>() {
public boolean accept(SModelReference it) {
return !(jetbrains.mps.smodel.SModelOperations.getImportedModelUIDs(model).contains(it));
}
});
Sequence.fromIterable(modelsToAdd).visitAll(new IVisitor<SModelReference>() {
public void visit(SModelReference it) {
((SModelInternal) model).addModelImport(it, false);
}
});
if (Sequence.fromIterable(modelsToAdd).isNotEmpty()) {
new MissingDependenciesFixer(model).fixModuleDependencies();
}
int cnt = StubResolver.resolveReferences(toResolve, models);
new OptimizeImportsHelper(myContextRepository).optimizeModelImports(model);
if (LOG.isInfoEnabled()) {
LOG.info(cnt + " stub references were re-resolved in model " + SModelOperations.getModelName(model) + ". (" + ListSequence.fromList(toResolve).count() + ")");
}
}
public void resolveInModels(List<SModel> models) {
for (SModel model : ListSequence.fromList(models)) {
resolveInModel(model);
}
}
public void resolveInProject(MPSProject project) {
for (SModule module : Sequence.fromIterable(project.getModulesWithGenerators())) {
if (module.isReadOnly()) {
continue;
}
for (SModel model : Sequence.fromIterable(module.getModels())) {
if (SModelStereotype.isUserModel(model) && model instanceof EditableSModel) {
resolveInModel(model);
}
}
}
}
public static int resolveReferences(List<SReference> toResolve, Map<SModelReference, SModelReference> models) {
int cnt = 0;
boolean found;
do {
found = false;
for (SReference ref : ListSequence.fromList(toResolve).toGenericArray(SReference.class)) {
SNode node = ref.getSourceNode();
final SModelReference modelRef = MapSequence.fromMap(models).get(ref.getTargetSModelReference());
final String resolveInfo = SLinkOperations.getResolveInfo(ref);
if (modelRef == null || resolveInfo == null) {
continue;
}
final Scope refScope = ModelConstraints.getScope(ref);
if (refScope instanceof ErrorScope) {
continue;
}
List<SNode> resolved = TypeContextManager.getInstance().runResolveAction(new Computable<IListSequence<SNode>>() {
public IListSequence<SNode> compute() {
return Sequence.fromIterable(refScope.getAvailableElements(null)).where(new IWhereFilter<SNode>() {
public boolean accept(SNode n) {
return modelRef.equals(SNodeOperations.getModel(n).getReference()) && resolveInfo.equals(jetbrains.mps.util.SNodeOperations.getResolveInfo(n));
}
}).toListSequence();
}
});
if (ListSequence.fromList(resolved).count() > 1) {
if (LOG.isEnabledFor(Level.ERROR)) {
LOG.error("more than 1 possible resolution for " + SLinkOperations.getResolveInfo(ref) + " in model " + modelRef.getName());
}
}
if (ListSequence.fromList(resolved).isNotEmpty()) {
SNodeAccessUtil.setReferenceTarget(node, ref.getLink(), ListSequence.fromList(resolved).first());
ListSequence.fromList(toResolve).removeElement(ref);
++cnt;
found = true;
}
}
} while (found);
return cnt;
}
private static SModelReference check_ar1im2_a0d0a0d0h(SModel checkedDotOperand) {
if (null != checkedDotOperand) {
return checkedDotOperand.getReference();
}
return null;
}
}