package jetbrains.mps.refactoring.framework;
/*Generated by MPS */
import org.apache.log4j.Logger;
import org.apache.log4j.LogManager;
import java.util.List;
import java.util.ArrayList;
import jetbrains.mps.smodel.Language;
import jetbrains.mps.smodel.ModuleRepositoryFacade;
import java.util.Set;
import java.util.HashSet;
import org.jetbrains.mps.openapi.model.SModel;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SModuleOperations;
import jetbrains.mps.util.SNodeOperations;
import org.jetbrains.mps.openapi.model.SNode;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SModelOperations;
import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations;
import org.apache.log4j.Level;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.Arrays;
public class RefactoringUtil {
private static final Logger LOG_1635700302 = LogManager.getLogger(RefactoringUtil.class);
private static final Logger LOG = LogManager.getLogger(RefactoringUtil.class);
public RefactoringUtil() {
}
public static IRefactoring getRefactoringByClassName(String className) {
for (IRefactoring r : RefactoringUtil.getAllRefactorings()) {
Class refClass = r.getClass();
if (refClass.getName().equals(className)) {
return r;
}
}
return null;
}
public static List<IRefactoring> getAllRefactorings() {
List<IRefactoring> allRefactorings = new ArrayList<IRefactoring>();
for (Language language : ModuleRepositoryFacade.getInstance().getAllModules(Language.class)) {
allRefactorings.addAll(RefactoringUtil.getRefactorings(language));
}
return allRefactorings;
}
public static Set<IRefactoring> getRefactorings(Language language) {
Set<IRefactoring> result = new HashSet<IRefactoring>();
SModel refModelDescriptor = SModuleOperations.getAspect(language, "refactorings");
if (refModelDescriptor != null) {
SModel refactoringsModel = refModelDescriptor;
String packageName = SNodeOperations.getModelLongName(refactoringsModel);
for (SNode refactoring : SModelOperations.roots(refactoringsModel, MetaAdapterFactory.getConcept(0x3ecd7c84cde345deL, 0x886c135ecc69b742L, 0x5fb04b74a778e245L, "jetbrains.mps.lang.refactoring.structure.Refactoring"))) {
try {
String fqName = packageName + "." + SPropertyOperations.getString(refactoring, MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"));
Class<IRefactoring> cls = null;
try {
cls = ((Class<IRefactoring>) language.getOwnClass(fqName));
} catch (ClassNotFoundException e) {
// Class not found - refactoring is not available now
}
if (cls == null) {
if (LOG_1635700302.isEnabledFor(Level.WARN)) {
LOG_1635700302.warn("Can't find class " + fqName + " for refactoring. Refactoring disabled.");
}
continue;
}
Constructor<IRefactoring> constructor = cls.getConstructor();
constructor.setAccessible(false);
result.add(constructor.newInstance());
} catch (InstantiationException e) {
if (LOG_1635700302.isEnabledFor(Level.ERROR)) {
LOG_1635700302.error("", e);
}
} catch (InvocationTargetException e) {
if (LOG_1635700302.isEnabledFor(Level.ERROR)) {
LOG_1635700302.error("", e);
}
} catch (IllegalAccessException e) {
if (LOG_1635700302.isEnabledFor(Level.ERROR)) {
LOG_1635700302.error("", e);
}
} catch (NoSuchMethodException e) {
if (LOG_1635700302.isEnabledFor(Level.ERROR)) {
LOG_1635700302.error("", e);
}
}
}
}
return result;
}
public static RefactoringUtil.Applicability getApplicability(IRefactoring refactoring, Collection entities) {
assert !(entities.isEmpty());
assert (entities.size() == 1 || refactoring.getRefactoringTarget().allowMultipleTargets());
IRefactoringTarget target = refactoring.getRefactoringTarget();
if (!(RefactoringUtil.isApplicableToEntities(refactoring.getUserFriendlyName(), target, entities))) {
return RefactoringUtil.Applicability.NOT_APPLICABLE;
}
for (IRefactoring r : RefactoringUtil.getAllRefactorings()) {
if (r.getOverridenRefactoringClass() == null) {
continue;
}
if (r.getRefactoringTarget().getTarget() != target.getTarget()) {
continue;
}
if (!(RefactoringUtil.isApplicableToEntities(r.getUserFriendlyName(), r.getRefactoringTarget(), entities))) {
continue;
}
Class refClass = refactoring.getClass();
if (r.getOverridenRefactoringClass() == null) {
continue;
}
if (r.getOverridenRefactoringClass() == refClass) {
return RefactoringUtil.Applicability.OVERRIDDEN;
}
String overriddenName = r.getOverridenRefactoringClass().getName();
String refClassName = refClass.getName();
String overriddenClassLoader = r.getOverridenRefactoringClass().getClassLoader().toString();
String refClassLoader = refClass.getClassLoader().toString();
assert !(overriddenName.equals(refClassName)) : "Refactoring classes are loaded using different classloaders. overridden: " + overriddenClassLoader + "; " + "ref: " + refClassLoader + "; class: " + refClassName;
}
return RefactoringUtil.Applicability.APPLICABLE;
}
private static boolean isApplicableToEntities(String refactoringName, IRefactoringTarget target, Collection entities) {
if (!(target.allowMultipleTargets()) && entities.size() > 1) {
return false;
}
for (Object entity : entities) {
boolean applicable;
try {
applicable = target.isApplicable(entity);
} catch (Throwable t) {
if (LOG_1635700302.isEnabledFor(Level.ERROR)) {
LOG_1635700302.error("An error occured while executing " + refactoringName + ".isApplicable(). This refactoring will not be available.", t);
}
applicable = false;
}
if (!(applicable)) {
return false;
}
}
return true;
}
public static boolean isApplicable(IRefactoring refactoring, Object target) {
IRefactoringTarget refTarget = refactoring.getRefactoringTarget();
boolean oneEntity = !(refTarget.allowMultipleTargets());
List targetList;
if (!(oneEntity)) {
targetList = ((List) target);
} else {
targetList = Arrays.asList(target);
}
boolean disabled = (targetList.isEmpty() || RefactoringUtil.getApplicability(refactoring, targetList).lessThan(RefactoringUtil.Applicability.APPLICABLE));
return !(disabled);
}
public enum Applicability {
APPLICABLE() {
public boolean lessThan(RefactoringUtil.Applicability level) {
return false;
}
},
NOT_APPLICABLE() {
public boolean lessThan(RefactoringUtil.Applicability level) {
return true;
}
},
OVERRIDDEN() {
public boolean lessThan(RefactoringUtil.Applicability level) {
return level == RefactoringUtil.Applicability.APPLICABLE;
}
};
private Applicability() {
}
public abstract boolean lessThan(RefactoringUtil.Applicability level);
}
}