/* * Copyright 2003-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jetbrains.mps.workbench.actions.model; import jetbrains.mps.ide.findusages.model.SearchQuery; import jetbrains.mps.ide.findusages.model.SearchResults; import jetbrains.mps.ide.findusages.view.FindUtils; import jetbrains.mps.ide.messages.MessagesViewTool; import jetbrains.mps.ide.ui.finders.ModelImportsUsagesFinder; import jetbrains.mps.messages.Message; import jetbrains.mps.messages.MessageKind; import jetbrains.mps.model.ModelDeleteHelper; import jetbrains.mps.progress.EmptyProgressMonitor; import jetbrains.mps.project.AbstractModule; import jetbrains.mps.project.GlobalScope; import jetbrains.mps.project.Project; import jetbrains.mps.project.Solution; import jetbrains.mps.refactoring.framework.BaseRefactoring; import jetbrains.mps.refactoring.framework.IRefactoring; import jetbrains.mps.refactoring.framework.IRefactoringTarget; import jetbrains.mps.refactoring.framework.RefactoringContext; import jetbrains.mps.refactoring.runtime.access.RefactoringAccess; import jetbrains.mps.smodel.Generator; import jetbrains.mps.smodel.Language; import jetbrains.mps.smodel.LanguageAspect; import jetbrains.mps.smodel.SModelInternal; import jetbrains.mps.smodel.SModelStereotype; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.jetbrains.annotations.Nullable; import org.jetbrains.mps.openapi.model.SModel; import org.jetbrains.mps.openapi.module.FindUsagesFacade; import org.jetbrains.mps.openapi.module.SModule; import java.util.Collections; import java.util.Set; public class DeleteModelHelper { private static final Logger LOG = LogManager.getLogger(DeleteModelHelper.class); public static void deleteModel(Project project, SModule contextModule, SModel modelDescriptor, boolean safeDelete, boolean deleteFiles) { if (LanguageAspect.STRUCTURE.is(modelDescriptor)) { Message msg = new Message(MessageKind.WARNING, DeleteModelHelper.class, "Can't delete structure model " + modelDescriptor.getModelName()); project.getComponent(MessagesViewTool.class).add(msg); return; } if (safeDelete) { safeDelete(project, modelDescriptor, deleteFiles); } else { delete(contextModule, modelDescriptor, deleteFiles); } } public static void delete(SModule contextModule, SModel modelDescriptor, boolean deleteFiles) { boolean deleteIfAsked = true; if (contextModule instanceof Language) { deleteIfAsked = deleteModelFromLanguage((Language) contextModule, modelDescriptor); } else if (contextModule instanceof Solution) { deleteModelFromSolution((Solution) contextModule, modelDescriptor); } else if (contextModule instanceof Generator) { deleteModelFromGenerator((Generator) contextModule, modelDescriptor); } else { LOG.warn("Module type " + contextModule.getClass().getSimpleName() + " is not supported by delete refactoring." + "Changes will not be saved automatically for modules of this type."); } if (!modelDescriptor.isReadOnly()) { if (deleteFiles && deleteIfAsked) { new ModelDeleteHelper(modelDescriptor).delete(); } } } public static void safeDelete(final Project project, final SModel modelDescriptor, boolean deleteFiles) { IRefactoring ref = new SafeDeleteModelRefactoring(deleteFiles); final RefactoringContext context = new RefactoringContext(project, ref); context.setSelectedModel(modelDescriptor); context.setSelectedModule(modelDescriptor.getModule()); project.getRepository().getModelAccess().runWriteInEDT(() -> { if (modelDescriptor.getReference().resolve(project.getRepository()) == modelDescriptor) { RefactoringAccess.getInstance().getRefactoringFacade().execute(context); } }); } private static boolean deleteModelFromLanguage(Language language, SModel modelDescriptor) { if (language.isAccessoryModel(modelDescriptor.getReference())) { language.removeAccessoryModel(modelDescriptor); return false; } else { return true; } } private static void deleteModelFromSolution(Solution solution, SModel modelDescriptor) { } private static void deleteModelFromGenerator(Generator generator, SModel modelDescriptor) { generator.deleteReferenceFromPriorities(modelDescriptor.getReference()); } private static class SafeDeleteModel_Target implements IRefactoringTarget { @Override public IRefactoringTarget.TargetType getTarget() { return TargetType.MODEL; } @Override public boolean allowMultipleTargets() { return false; } @Override public boolean isApplicable(final Object entity) { return true; } } private static class SafeDeleteModelRefactoring extends BaseRefactoring { private boolean myDeleteFiles; public SafeDeleteModelRefactoring(boolean deleteFiles) { myDeleteFiles = deleteFiles; } @Override public String getUserFriendlyName() { return "Delete model"; } @Override public IRefactoringTarget getRefactoringTarget() { return new SafeDeleteModel_Target(); } @Override public void refactor(RefactoringContext refactoringContext) { SModel modelDescriptor = refactoringContext.getSelectedModel(); SModule modelOwner = modelDescriptor.getModule(); // delete imports from available models, helps if there are no references to deleted model Set<SModel> usages = FindUsagesFacade.getInstance().findModelUsages( GlobalScope.getInstance(), Collections.singleton(modelDescriptor.getReference()), new EmptyProgressMonitor()); for (SModel md : usages) { if (SModelStereotype.isUserModel(md)) { ((SModelInternal) md).deleteModelImport(modelDescriptor.getReference()); } } delete(modelOwner, modelDescriptor, myDeleteFiles); //todo: check correctness - they are not ALL model owners if (modelOwner instanceof AbstractModule) { ((AbstractModule) modelOwner).save(); } } @Nullable @Override public SearchResults getAffectedNodes(RefactoringContext refactoringContext) { if (refactoringContext.getSelectedModel() == null) return null; SearchQuery searchQuery = new SearchQuery(refactoringContext.getSelectedModel().getReference(), GlobalScope.getInstance()); return FindUtils.getSearchResults(new EmptyProgressMonitor(), searchQuery, new ModelImportsUsagesFinder()); } } }