/******************************************************************************* * Copyright (c) 2000, 2008 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.wst.jsdt.internal.ui.compare; import java.lang.reflect.InvocationTargetException; import java.util.List; import java.util.Map; import java.util.ResourceBundle; import org.eclipse.compare.EditionSelectionDialog; import org.eclipse.compare.IStreamContentAccessor; import org.eclipse.compare.ITypedElement; import org.eclipse.compare.structuremergeviewer.DocumentRangeNode; import org.eclipse.core.filebuffers.FileBuffers; import org.eclipse.core.filebuffers.ITextFileBuffer; import org.eclipse.core.filebuffers.ITextFileBufferManager; import org.eclipse.core.filebuffers.LocationKind; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.TextUtilities; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IEditorInput; import org.eclipse.wst.jsdt.core.IJavaScriptProject; import org.eclipse.wst.jsdt.core.IJavaScriptUnit; import org.eclipse.wst.jsdt.core.IMember; import org.eclipse.wst.jsdt.core.IParent; import org.eclipse.wst.jsdt.core.IType; import org.eclipse.wst.jsdt.core.dom.ASTNode; import org.eclipse.wst.jsdt.core.dom.BodyDeclaration; import org.eclipse.wst.jsdt.core.dom.ImportDeclaration; import org.eclipse.wst.jsdt.core.dom.JavaScriptUnit; import org.eclipse.wst.jsdt.core.dom.PackageDeclaration; import org.eclipse.wst.jsdt.core.dom.TypeDeclaration; import org.eclipse.wst.jsdt.core.dom.rewrite.ASTRewrite; import org.eclipse.wst.jsdt.core.dom.rewrite.ListRewrite; import org.eclipse.wst.jsdt.internal.corext.dom.ASTNodes; import org.eclipse.wst.jsdt.internal.corext.util.Resources; import org.eclipse.wst.jsdt.internal.ui.IJavaHelpContextIds; import org.eclipse.wst.jsdt.internal.ui.JavaScriptPlugin; import org.eclipse.wst.jsdt.internal.ui.javaeditor.JavaEditor; import org.eclipse.wst.jsdt.internal.ui.util.ExceptionHandler; import org.eclipse.wst.jsdt.ui.IWorkingCopyManager; class JavaAddElementFromHistoryImpl extends JavaHistoryActionImpl { private static final String BUNDLE_NAME= "org.eclipse.wst.jsdt.internal.ui.compare.AddFromHistoryAction"; //$NON-NLS-1$ JavaAddElementFromHistoryImpl() { super(true); } public void run(ISelection selection) { String errorTitle= CompareMessages.AddFromHistory_title; String errorMessage= CompareMessages.AddFromHistory_internalErrorMessage; Shell shell= getShell(); IJavaScriptUnit cu= null; IParent parent= null; IMember input= null; // analyze selection if (selection.isEmpty()) { // no selection: we try to use the editor's input JavaEditor editor= getEditor(); if (editor != null) { IEditorInput editorInput= editor.getEditorInput(); IWorkingCopyManager manager= JavaScriptPlugin.getDefault().getWorkingCopyManager(); if (manager != null) { cu= manager.getWorkingCopy(editorInput); parent= cu; } } } else { input= getEditionElement(selection); if (input != null) { cu= input.getJavaScriptUnit(); parent= input; input= null; } else { if (selection instanceof IStructuredSelection) { Object o= ((IStructuredSelection)selection).getFirstElement(); if (o instanceof IJavaScriptUnit) { cu= (IJavaScriptUnit) o; parent= cu; } } } } if (parent == null || cu == null) { String invalidSelectionMessage= CompareMessages.AddFromHistory_invalidSelectionMessage; MessageDialog.openInformation(shell, errorTitle, invalidSelectionMessage); return; } IFile file= getFile(parent); if (file == null) { MessageDialog.openError(shell, errorTitle, errorMessage); return; } boolean inEditor= beingEdited(file); IStatus status= Resources.makeCommittable(file, shell); if (!status.isOK()) { return; } // get the document where to insert the text IPath path= file.getFullPath(); ITextFileBufferManager bufferManager= FileBuffers.getTextFileBufferManager(); ITextFileBuffer textFileBuffer= null; try { bufferManager.connect(path, LocationKind.IFILE, null); textFileBuffer= bufferManager.getTextFileBuffer(path, LocationKind.IFILE); IDocument document= textFileBuffer.getDocument(); // configure EditionSelectionDialog and let user select an edition ITypedElement target= new JavaTextBufferNode(file, document, inEditor); ITypedElement[] editions= buildEditions(target, file); ResourceBundle bundle= ResourceBundle.getBundle(BUNDLE_NAME); EditionSelectionDialog d= new EditionSelectionDialog(shell, bundle); d.setAddMode(true); d.setHelpContextId(IJavaHelpContextIds.ADD_ELEMENT_FROM_HISTORY_DIALOG); ITypedElement selected= d.selectEdition(target, editions, parent); if (selected == null) return; // user cancel IJavaScriptUnit cu2= cu; if (parent instanceof IMember) cu2= ((IMember)parent).getJavaScriptUnit(); JavaScriptUnit root= parsePartialCompilationUnit(cu2); ASTRewrite rewriter= ASTRewrite.create(root.getAST()); ITypedElement[] results= d.getSelection(); for (int i= 0; i < results.length; i++) { // create an AST node ASTNode newNode= createASTNode(rewriter, results[i], TextUtilities.getDefaultLineDelimiter(document), cu.getJavaScriptProject()); if (newNode == null) { MessageDialog.openError(shell, errorTitle, errorMessage); return; } // now determine where to put the new node if (newNode instanceof PackageDeclaration) { rewriter.set(root, JavaScriptUnit.PACKAGE_PROPERTY, newNode, null); } else if (newNode instanceof ImportDeclaration) { ListRewrite lw= rewriter.getListRewrite(root, JavaScriptUnit.IMPORTS_PROPERTY); lw.insertFirst(newNode, null); } else { // class, interface, enum, annotation, method, field if (parent instanceof IJavaScriptUnit) { // top level ListRewrite lw= rewriter.getListRewrite(root, JavaScriptUnit.TYPES_PROPERTY); int index= ASTNodes.getInsertionIndex((BodyDeclaration)newNode, root.types()); lw.insertAt(newNode, index, null); } else if (parent instanceof IType) { ASTNode declaration= getBodyContainer(root, (IType)parent); if (declaration instanceof TypeDeclaration) { List container= ASTNodes.getBodyDeclarations(declaration); int index= ASTNodes.getInsertionIndex((BodyDeclaration)newNode, container); ListRewrite lw= rewriter.getListRewrite(declaration, ASTNodes.getBodyDeclarationsProperty(declaration)); lw.insertAt(newNode, index, null); } } else { JavaScriptPlugin.logErrorMessage("JavaAddElementFromHistoryImpl: unknown container " + parent); //$NON-NLS-1$ } } } Map options= null; IJavaScriptProject javaProject= cu2.getJavaScriptProject(); if (javaProject != null) options= javaProject.getOptions(true); applyChanges(rewriter, document, textFileBuffer, shell, inEditor, options); } catch(InvocationTargetException ex) { ExceptionHandler.handle(ex, shell, errorTitle, errorMessage); } catch(InterruptedException ex) { // shouldn't be called because is not cancelable Assert.isTrue(false); } catch(CoreException ex) { ExceptionHandler.handle(ex, shell, errorTitle, errorMessage); } finally { try { if (textFileBuffer != null) bufferManager.disconnect(path, LocationKind.IFILE, null); } catch (CoreException e) { JavaScriptPlugin.log(e); } } } /** * Creates a place holder ASTNode for the given element. * @param rewriter * @param element * @param delimiter the line delimiter * @param project * @return a ASTNode or null * @throws CoreException */ private ASTNode createASTNode(ASTRewrite rewriter, ITypedElement element, String delimiter, IJavaScriptProject project) throws CoreException { if (element instanceof IStreamContentAccessor) { String content= JavaCompareUtilities.readString((IStreamContentAccessor)element); if (content != null) { content= trimTextBlock(content, delimiter, project); if (content != null) { int type= getPlaceHolderType(element); if (type != -1) return rewriter.createStringPlaceholder(content, type); } } } return null; } /** * Returns the corresponding place holder type for the given element. * @return a place holder type (see ASTRewrite) or -1 if there is no corresponding placeholder */ private int getPlaceHolderType(ITypedElement element) { if (element instanceof DocumentRangeNode) { JavaNode jn= (JavaNode) element; switch (jn.getTypeCode()) { case JavaNode.PACKAGE: return ASTNode.PACKAGE_DECLARATION; case JavaNode.CLASS: case JavaNode.INTERFACE: return ASTNode.TYPE_DECLARATION; case JavaNode.CONSTRUCTOR: case JavaNode.METHOD: return ASTNode.FUNCTION_DECLARATION; case JavaNode.FIELD: return ASTNode.FIELD_DECLARATION; case JavaNode.INIT: return ASTNode.INITIALIZER; case JavaNode.IMPORT: case JavaNode.IMPORT_CONTAINER: return ASTNode.IMPORT_DECLARATION; case JavaNode.CU: return ASTNode.JAVASCRIPT_UNIT; } } return -1; } protected boolean isEnabled(ISelection selection) { if (selection.isEmpty()) { JavaEditor editor= getEditor(); if (editor != null) { // we check whether editor shows JavaScriptUnit IEditorInput editorInput= editor.getEditorInput(); IWorkingCopyManager manager= JavaScriptPlugin.getDefault().getWorkingCopyManager(); return manager.getWorkingCopy(editorInput) != null; } return false; } if (selection instanceof IStructuredSelection) { Object o= ((IStructuredSelection)selection).getFirstElement(); if (o instanceof IJavaScriptUnit) return true; } return super.isEnabled(selection); } }