/*************************************************************************************************** * Copyright (c) 2003, 2004 IBM Corporation and others. All rights reserved. This program and the * accompanying materials are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: IBM Corporation - initial API and implementation **************************************************************************************************/ package org.eclipse.jst.j2ee.internal.rename; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.emf.common.command.AbstractCommand; import org.eclipse.emf.common.command.CompoundCommand; import org.eclipse.emf.common.util.URI; import org.eclipse.jst.j2ee.application.Module; import org.eclipse.jst.j2ee.internal.J2EEEditModel; import org.eclipse.jst.j2ee.internal.earcreation.AddModuleToEARProjectCommand; import org.eclipse.jst.j2ee.internal.earcreation.EAREditModel; import org.eclipse.jst.j2ee.internal.earcreation.EARNatureRuntime; import org.eclipse.jst.j2ee.internal.earcreation.RemoveModuleFromEARProjectCommand; import org.eclipse.jst.j2ee.internal.earcreation.UpdateModuleReferencesInEARProjectCommand; import org.eclipse.jst.j2ee.internal.project.J2EECreationResourceHandler; import org.eclipse.wst.common.frameworks.internal.operations.WTPOperation; import org.eclipse.wst.common.internal.emfworkbench.EMFWorkbenchContext; import org.eclipse.wst.common.internal.emfworkbench.WorkbenchResourceHelper; import org.eclipse.wst.common.internal.emfworkbench.integration.ComposedEditModel; import org.eclipse.wst.common.internal.emfworkbench.integration.EditModel; import org.eclipse.wst.common.internal.emfworkbench.integration.LooseComposedEditModel; public class RenameModuleOperation extends WTPOperation { protected RenameOptions options; protected IProject renamedProject = null; protected LooseComposedEditModel renameEditModel = null; /* * key is an EAREditModel and the value is a list of rename commands. We cache the commands and * execute later because the modules still need to exist when we go to change module dependency * references. */ protected Map deferredCommands; protected IProgressMonitor monitor; protected RenameModuleDependencyOperation renameModuleDependencyOperation; protected List dirtyEarModels; protected static String EDIT_MODEL_KEY = "RENAME_MODULES"; //$NON-NLS-1$ public RenameModuleOperation(RenameOptions options) { this.options = options; } /** * @see HeadlessJ2EEOperation#execute(IProgressMonitor) */ protected void execute(IProgressMonitor aMonitor) throws CoreException, InvocationTargetException, InterruptedException { this.monitor = aMonitor; try { buildRenameCommandsIfNecessary(); if (options.shouldRenameModuleDependencies()) { renameModuleDependencies(); } checkIfEarsAreDirty(); executeDeferredCommands(); saveModelsIfNecessary(); } finally { releaseModels(); } } protected void checkIfEarsAreDirty() { dirtyEarModels = new ArrayList(); if (deferredCommands == null) return; Iterator models = deferredCommands.keySet().iterator(); while (models.hasNext()) { EAREditModel model = (EAREditModel) models.next(); if (model.isDirty() && !dirtyEarModels.contains(model)) { dirtyEarModels.add(model); } } } protected void buildRenameCommands() { deferredCommands = new HashMap(); List earProjects = EARNatureRuntime.getAllEARProjectsInWorkbench(); for (int i = 0; i < earProjects.size(); i++) { IProject p = (IProject) earProjects.get(i); EARNatureRuntime runtime = EARNatureRuntime.getRuntime(p); if (runtime != null) buildRenameCommands(runtime); } } protected void buildRenameCommands(EARNatureRuntime runtime) { List commands = new ArrayList(); List projects = options.getModuleAndUtilityProjects(); EAREditModel model = null; try { model = runtime.getEarEditModelForWrite(this); if (options.shouldRenameModules()) { for (int i = 0; i < projects.size(); i++) { IProject project = (IProject) projects.get(i); Module m = runtime.getModule(project); if (m != null) { String uri; //Do not rename the module uri unless it was //the same as the original project name. boolean changedUri = false; if (!m.getUri().startsWith(project.getName())) uri = m.getUri(); else { changedUri = true; // the following was taken from // WebProjectInfo.getDefaultUri() uri = options.getNewName().replace(' ', '_'); uri += "." + URI.createURI(m.getUri()).fileExtension(); //$NON-NLS-1$ } //AbstractCommand.class.getClass(); CompoundCommand compoundCommand = new CompoundCommand(); compoundCommand.append(new RemoveModuleFromEARProjectCommand(m, runtime.getProject())); renamedProject = project.getWorkspace().getRoot().getProject(options.getNewName()); compoundCommand.append(new AddModuleToEARProjectCommand(renamedProject, runtime.getProject(), uri, options.getNewContextRoot(), null)); if (changedUri) compoundCommand.append(new UpdateModuleReferencesInEARProjectCommand(runtime.getProject(), m, uri)); commands.add(compoundCommand); } } } } finally { if (!commands.isEmpty()) { deferredCommands.put(model, commands); } else { model.releaseAccess(this); } } } /** * Do this for unhandled exceptions */ /** * Do this for unhandled exceptions */ protected void releaseModels() { if (renameEditModel != null) { renameEditModel = null; } if (deferredCommands != null) { Iterator iterator = deferredCommands.keySet().iterator(); EditModel model = null; while (iterator.hasNext()) { model = (EditModel) iterator.next(); model.releaseAccess(this); } deferredCommands.clear(); } } public void release() { releaseModels(); } /** * After a normal execution flow, save the models if necessary */ protected void saveModelsIfNecessary() { if (deferredCommands == null) return; Iterator models = deferredCommands.keySet().iterator(); while (models.hasNext()) { EAREditModel model = (EAREditModel) models.next(); if (model.isDirty()) { if (dirtyEarModels.contains(model)) { model.saveIfNecessary(this); } else { model.save(this); } } } } protected void renameModuleDependencies() throws InvocationTargetException, InterruptedException { getRenameModuleDependencyOperation().run(monitor); } protected void executeDeferredCommands() { Iterator it = deferredCommands.entrySet().iterator(); while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); List commands = (List) entry.getValue(); executeCommands(commands); } } protected void executeCommands(List commands) { for (int i = 0; i < commands.size(); i++) { AbstractCommand cmd = (AbstractCommand) commands.get(i); cmd.execute(); } } /** * Use this only for validate edits */ public ComposedEditModel getRenameEditModel() { if (renameEditModel == null) initializeRenameEditModel(); return renameEditModel; } protected void initializeRenameEditModel() { if (options.getAllProjectsToRename().size() == 0) { throw new RuntimeException(J2EECreationResourceHandler.getString("RenameModuleOperation_UI_0")); //$NON-NLS-1$ } IProject project = null; project = (IProject) options.getAllProjectsToRename().get(0); buildRenameCommandsIfNecessary(); renameEditModel = new LooseComposedEditModel(EDIT_MODEL_KEY, (EMFWorkbenchContext) WorkbenchResourceHelper.getEMFContext(project)) { /** * @see org.eclipse.jst.j2ee.internal.internal.workbench.EditModel#getNonResourceFiles() */ public List getNonResourceFiles() { List result = super.getNonResourceFiles(); result.addAll(getAffectedNonResourceFiles()); return result; } }; Iterator it = deferredCommands.keySet().iterator(); while (it.hasNext()) { renameEditModel.addChild((J2EEEditModel) it.next()); } } protected void buildRenameCommandsIfNecessary() { if (deferredCommands != null && !deferredCommands.isEmpty()) return; buildRenameCommands(); } /** * Return a list of all the non-resource files that will get modified as a result of running * this operation; used for validate edit. */ protected List getAffectedNonResourceFiles() { if (options.shouldRenameModuleDependencies()) return getRenameModuleDependencyOperation().getAffectedFiles(); return Collections.EMPTY_LIST; } protected RenameModuleDependencyOperation getRenameModuleDependencyOperation() { if (renameModuleDependencyOperation == null) { List earEditModels = new ArrayList(); earEditModels.addAll(deferredCommands.keySet()); renameModuleDependencyOperation = new RenameModuleDependencyOperation(earEditModels, new HashSet(options.getModuleAndUtilityProjects()), renamedProject); } return renameModuleDependencyOperation; } public IStatus getStatus() { return renameModuleDependencyOperation.getStatus(); } }