Java tutorial
/******************************************************************************* * Copyright (c) 2006, 2013 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.team.internal.ui.synchronize; import org.eclipse.compare.*; import org.eclipse.compare.contentmergeviewer.ContentMergeViewer; import org.eclipse.compare.internal.ISavingSaveable; import org.eclipse.compare.structuremergeviewer.ICompareInput; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.*; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.team.internal.ui.*; import org.eclipse.team.ui.mapping.SaveableComparison; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.Saveable; import org.eclipse.ui.part.FileEditorInput; import org.eclipse.ui.texteditor.IDocumentProvider; /** * A saveable that wraps a compare input in which the left side is a {@link LocalResourceTypedElement} * and saves changes made to the file in compare when the viewers are flushed. * * @see LocalResourceTypedElement * @since 3.3 */ public abstract class LocalResourceSaveableComparison extends SaveableComparison implements IPropertyChangeListener, ISavingSaveable { private final ICompareInput input; private final CompareEditorInput editorInput; private boolean isSaving; private IContentChangeListener contentChangeListener; private ITypedElement fileElement; private IDocument document; /** * Create the resource-based saveable comparison. * @param input the compare input to be save * @param editorInput the editor input containing the comparison */ public LocalResourceSaveableComparison(ICompareInput input, CompareEditorInput editorInput) { this(input, editorInput, input.getLeft()); } /** * Create the resource-based saveable comparison. * @param input the compare input to be save * @param editorInput the editor input containing the comparison * @param fileElement the file element that handles the saving and change notification */ public LocalResourceSaveableComparison(ICompareInput input, CompareEditorInput editorInput, ITypedElement fileElement) { this.input = input; this.editorInput = editorInput; this.fileElement = fileElement; initializeContentChangeListeners(); } protected void initializeHashing() { Object document = getAdapter(IDocument.class); if (document != null) { this.document = (IDocument) document; } } private void initializeContentChangeListeners() { // We need to listen to saves to the input to catch the case // where Save was picked from the context menu ITypedElement te = getFileElement(); if (te instanceof IContentChangeNotifier) { if (contentChangeListener == null) { contentChangeListener = new IContentChangeListener() { public void contentChanged(IContentChangeNotifier source) { try { if (!isSaving) { performSave(new NullProgressMonitor()); } } catch (CoreException e) { TeamUIPlugin.log(e); } } }; } ((IContentChangeNotifier) te).addContentChangeListener(contentChangeListener); } } /** * Dispose of the saveable. */ public void dispose() { if (contentChangeListener != null) { ITypedElement te = getFileElement(); if (te instanceof IContentChangeNotifier) { ((IContentChangeNotifier) te).removeContentChangeListener(contentChangeListener); } } // Discard of the buffer ITypedElement left = getFileElement(); if (left instanceof LocalResourceTypedElement) ((LocalResourceTypedElement) left).discardBuffer(); document = null; } private ITypedElement getFileElement() { return fileElement; } /* (non-Javadoc) * @see org.eclipse.team.ui.mapping.SaveableCompareModel#performSave(org.eclipse.core.runtime.IProgressMonitor) */ protected void performSave(IProgressMonitor monitor) throws CoreException { if (checkForUpdateConflicts()) { return; } try { isSaving = true; monitor.beginTask(null, 100); // First, we need to flush the viewers so the changes get buffered // in the input flushViewers(Policy.subMonitorFor(monitor, 40)); // Then we tell the input to commit its changes // Only the left is ever saveable ITypedElement te = getFileElement(); if (te instanceof LocalResourceTypedElement) { LocalResourceTypedElement lrte = (LocalResourceTypedElement) te; lrte.commit(Policy.subMonitorFor(monitor, 60)); } } finally { // Make sure we fire a change for the compare input to update the viewers fireInputChange(); setDirty(false); isSaving = false; monitor.done(); } } /** * Flush the contents of any viewers into the compare input. * @param monitor a progress monitor * @throws CoreException */ protected void flushViewers(IProgressMonitor monitor) throws CoreException { if (editorInput instanceof SaveablesCompareEditorInput) { ((SaveablesCompareEditorInput) editorInput).saveChanges(monitor, this); } else { editorInput.saveChanges(monitor); } } /** * Fire an input change for the compare input after it has been * saved. */ protected abstract void fireInputChange(); /** * Check whether there is a conflicting save on the file. * @return <code>true</code> if there was and the user chose to cancel the operation */ private boolean checkForUpdateConflicts() { if (hasSaveConflict()) { if (Utils.RUNNING_TESTS) return !Utils.TESTING_FLUSH_ON_COMPARE_INPUT_CHANGE; final MessageDialog dialog = new MessageDialog(TeamUIPlugin.getStandardDisplay().getActiveShell(), TeamUIMessages.SyncInfoCompareInput_0, null, TeamUIMessages.SyncInfoCompareInput_1, MessageDialog.QUESTION, new String[] { TeamUIMessages.SyncInfoCompareInput_2, IDialogConstants.CANCEL_LABEL }, 0); int retval = dialog.open(); switch (retval) { // save case 0: return false; // cancel case 1: return true; } } return false; } private boolean hasSaveConflict() { ITypedElement left = getFileElement(); if (left instanceof LocalResourceTypedElement) { LocalResourceTypedElement te = (LocalResourceTypedElement) left; return !te.isSynchronized(); } return false; } /* (non-Javadoc) * @see org.eclipse.team.ui.mapping.SaveableCompareModel#isDirty() */ public boolean isDirty() { // We need to get the dirty state from the compare editor input // since it is our only connection to the merge viewer if (editorInput instanceof SaveablesCompareEditorInput) { return ((SaveablesCompareEditorInput) editorInput).isSaveNeeded(this); } return editorInput.isSaveNeeded(); } /* (non-Javadoc) * @see org.eclipse.team.ui.mapping.SaveableCompareModel#setDirty(boolean) */ protected void setDirty(boolean dirty) { if (editorInput instanceof SaveablesCompareEditorInput) { ((SaveablesCompareEditorInput) editorInput).setDirty(dirty, this); return; } // We need to set the dirty state on the compare editor input // since it is our only connection to the merge viewer editorInput.setDirty(dirty); } /* (non-Javadoc) * @see org.eclipse.team.ui.mapping.SaveableCompareModel#performRevert(org.eclipse.core.runtime.IProgressMonitor) */ protected void performRevert(IProgressMonitor monitor) { // Only the left is ever editable ITypedElement left = getFileElement(); if (left instanceof LocalResourceTypedElement) ((LocalResourceTypedElement) left).discardBuffer(); } /* (non-Javadoc) * @see org.eclipse.ui.Saveable#getName() */ public String getName() { // Return the name of the file element as held in the compare input if (input.getLeft() != null && input.getLeft().equals(fileElement)) { return input.getLeft().getName(); } if (input.getRight() != null && input.getRight().equals(fileElement)) { return input.getRight().getName(); } // Fallback call returning name of the main non-null element of the input // see org.eclipse.team.internal.ui.mapping.AbstractCompareInput#getMainElement() return input.getName(); } /* (non-Javadoc) * @see org.eclipse.ui.Saveable#getToolTipText() */ public String getToolTipText() { return editorInput.getToolTipText(); } /* (non-Javadoc) * @see org.eclipse.ui.Saveable#getImageDescriptor() */ public ImageDescriptor getImageDescriptor() { Image image = input.getImage(); if (image != null) return ImageDescriptor.createFromImage(image); return TeamUIPlugin.getImageDescriptor(ITeamUIImages.IMG_SYNC_VIEW); } /* (non-Javadoc) * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent) */ public void propertyChange(PropertyChangeEvent e) { String propertyName = e.getProperty(); if (CompareEditorInput.DIRTY_STATE.equals(propertyName)) { boolean changed = false; Object newValue = e.getNewValue(); if (newValue instanceof Boolean) changed = ((Boolean) newValue).booleanValue(); Object source = e.getSource(); if (source instanceof ContentMergeViewer) { ContentMergeViewer cmv = (ContentMergeViewer) source; if (input.getLeft() != null && input.getLeft().equals(fileElement)) { if (changed && cmv.internalIsLeftDirty()) setDirty(changed); else if (!changed && !cmv.internalIsLeftDirty()) { setDirty(changed); } } if (input.getRight() != null && input.getRight().equals(fileElement)) { if (changed && cmv.internalIsRightDirty()) setDirty(changed); else if (!changed && !cmv.internalIsRightDirty()) { setDirty(changed); } } } else { setDirty(changed); } } } /* * @see org.eclipse.ui.Saveable#hashCode() */ public int hashCode() { if (document != null) { return document.hashCode(); } return input.hashCode(); } /* * @see org.eclipse.ui.Saveable#equals(java.lang.Object) */ public boolean equals(Object obj) { if (this == obj) return true; if (!(obj instanceof Saveable)) return false; if (document != null) { Object otherDocument = ((Saveable) obj).getAdapter(IDocument.class); if (document == null && otherDocument == null) return false; return document != null && document.equals(otherDocument); } if (obj instanceof LocalResourceSaveableComparison) { LocalResourceSaveableComparison rscm = (LocalResourceSaveableComparison) obj; return rscm.input.equals(input); } return false; } public Object getAdapter(Class adapter) { if (adapter == IDocument.class) { if (document != null) return document; if (fileElement instanceof LocalResourceTypedElement) { LocalResourceTypedElement lrte = (LocalResourceTypedElement) fileElement; if (lrte.isConnected()) { ISharedDocumentAdapter sda = (ISharedDocumentAdapter) Utils.getAdapter(lrte, ISharedDocumentAdapter.class); if (sda != null) { IEditorInput input = sda.getDocumentKey(lrte); if (input != null) { IDocumentProvider provider = SharedDocumentAdapter.getDocumentProvider(input); if (provider != null) return provider.getDocument(input); } } } } } if (adapter == IEditorInput.class) { if (fileElement instanceof LocalResourceTypedElement) { LocalResourceTypedElement lrte = (LocalResourceTypedElement) fileElement; return new FileEditorInput((IFile) lrte.getResource()); } } return super.getAdapter(adapter); } /** * Return the compare input that is managed by this saveable. * @return the compare input that is managed by this saveable */ public ICompareInput getInput() { return input; } public boolean isConnectedToSharedDocument() { if (fileElement instanceof LocalResourceTypedElement) { LocalResourceTypedElement lrte = (LocalResourceTypedElement) fileElement; return lrte.isConnected(); } return false; } public boolean isSaving() { return isSaving; } }