Java tutorial
/******************************************************************************* * 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.team.internal.ccvs.ui; import java.lang.reflect.InvocationTargetException; import org.eclipse.compare.CompareConfiguration; import org.eclipse.compare.CompareEditorInput; import org.eclipse.compare.ITypedElement; import org.eclipse.compare.structuremergeviewer.DiffNode; import org.eclipse.compare.structuremergeviewer.Differencer; import org.eclipse.compare.structuremergeviewer.IDiffContainer; import org.eclipse.compare.structuremergeviewer.IStructureComparator; import org.eclipse.core.runtime.*; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.viewers.*; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; import org.eclipse.team.core.TeamException; import org.eclipse.team.internal.ccvs.core.*; import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo; import org.eclipse.team.internal.ui.IPreferenceIds; import org.eclipse.team.internal.ui.TeamUIPlugin; /** * A compare input for comparing remote resources. Use <code>CVSLocalCompareInput</code> * when comparing resources in the workspace to remote resources. */ public class CVSCompareEditorInput extends CompareEditorInput { private ITypedElement left; private ITypedElement right; private ITypedElement ancestor; private Image leftImage; private Image rightImage; private Image ancestorImage; // comparison constants private static final int NODE_EQUAL = 0; private static final int NODE_NOT_EQUAL = 1; private static final int NODE_UNKNOWN = 2; String toolTipText; private String title; /** * Creates a new CVSCompareEditorInput. */ public CVSCompareEditorInput(ResourceEditionNode left, ResourceEditionNode right) { this(left, right, null); } public CVSCompareEditorInput(String title, String toolTip, ResourceEditionNode left, ResourceEditionNode right) { this(left, right, null); this.title = title; this.toolTipText = toolTip; } /** * Creates a new CVSCompareEditorInput. */ public CVSCompareEditorInput(ResourceEditionNode left, ResourceEditionNode right, ResourceEditionNode ancestor) { super(new CompareConfiguration()); // TODO: Invokers of this method should ensure that trees and contents are prefetched this.left = left; this.right = right; this.ancestor = ancestor; if (left != null) { this.leftImage = left.getImage(); } if (right != null) { this.rightImage = right.getImage(); } if (ancestor != null) { this.ancestorImage = ancestor.getImage(); } } /** * Returns the label for the given input element. */ private String getLabel(ITypedElement element) { if (element instanceof ResourceEditionNode) { ICVSRemoteResource edition = ((ResourceEditionNode) element).getRemoteResource(); ICVSResource resource = edition; if (edition instanceof ICVSRemoteFile) { try { String name = resource.getName(); String revision = ((ICVSRemoteFile) edition).getRevision(); String msg = null; if (isShowAuthor()) { String author = ((ICVSRemoteFile) edition).getLogEntry(new NullProgressMonitor()) .getAuthor(); msg = NLS.bind(CVSUIMessages.nameRevisionAndAuthor, new String[] { name, revision, author }); } else { msg = NLS.bind(CVSUIMessages.nameAndRevision, new String[] { name, revision }); } return msg; } catch (TeamException e) { // fall through } } try { if (edition.isContainer()) { CVSTag tag = ((ICVSRemoteFolder) edition).getTag(); if (tag == null) { return NLS.bind(CVSUIMessages.CVSCompareEditorInput_inHead, new String[] { edition.getName() }); } else if (tag.getType() == CVSTag.BRANCH) { return NLS.bind(CVSUIMessages.CVSCompareEditorInput_inBranch, (new Object[] { edition.getName(), tag.getName() })); } else { return NLS.bind(CVSUIMessages.CVSCompareEditorInput_repository, (new Object[] { edition.getName(), tag.getName() })); } } else { return NLS.bind(CVSUIMessages.CVSCompareEditorInput_repository, (new Object[] { edition.getName(), resource.getSyncInfo().getRevision() })); } } catch (TeamException e) { handle(e); // Fall through and get the default label } } return element.getName(); } private boolean isShowAuthor() { IPreferenceStore store = TeamUIPlugin.getPlugin().getPreferenceStore(); return store.getBoolean(IPreferenceIds.SHOW_AUTHOR_IN_COMPARE_EDITOR); } /** * Returns the label for the given input element. */ private String getVersionLabel(ITypedElement element) { if (element instanceof ResourceEditionNode) { ICVSRemoteResource edition = ((ResourceEditionNode) element).getRemoteResource(); ICVSResource resource = edition; try { if (edition.isContainer()) { CVSTag tag = ((ICVSRemoteFolder) resource).getTag(); if (tag == null) { return CVSUIMessages.CVSCompareEditorInput_headLabel; } else if (tag.getType() == CVSTag.BRANCH) { return NLS.bind(CVSUIMessages.CVSCompareEditorInput_branchLabel, new String[] { tag.getName() }); } else { return tag.getName(); } } else { return resource.getSyncInfo().getRevision(); } } catch (TeamException e) { handle(e); // Fall through and get the default label } } return element.getName(); } /* * Returns a guess of the resource name being compared, for display * in the title. */ private String guessResourceName() { if (left != null) { return left.getName(); } if (right != null) { return right.getName(); } if (ancestor != null) { return ancestor.getName(); } return ""; //$NON-NLS-1$ } /* * Returns a guess of the resource path being compared, for display * in the tooltip. */ private Object guessResourcePath() { if (left != null && left instanceof ResourceEditionNode) { return ((ResourceEditionNode) left).getRemoteResource().getRepositoryRelativePath(); } if (right != null && right instanceof ResourceEditionNode) { return ((ResourceEditionNode) right).getRemoteResource().getRepositoryRelativePath(); } if (ancestor != null && ancestor instanceof ResourceEditionNode) { return ((ResourceEditionNode) ancestor).getRemoteResource().getRepositoryRelativePath(); } return guessResourceName(); } /** * Handles a random exception and sanitizes it into a reasonable * error message. */ private void handle(Exception e) { // create a status Throwable t = e; // unwrap the invocation target exception if (t instanceof InvocationTargetException) { t = ((InvocationTargetException) t).getTargetException(); } IStatus error; if (t instanceof CoreException) { error = ((CoreException) t).getStatus(); } else if (t instanceof TeamException) { error = ((TeamException) t).getStatus(); } else { error = new Status(IStatus.ERROR, CVSUIPlugin.ID, 1, CVSUIMessages.internal, t); } setMessage(error.getMessage()); if (!(t instanceof TeamException)) { CVSUIPlugin.log(error.getSeverity(), error.getMessage(), t); } } /** * Sets up the title and pane labels for the comparison view. */ private void initLabels() { CompareConfiguration cc = getCompareConfiguration(); setLabels(cc, new StructuredSelection()); if (title == null) { if (ancestor != null) { title = NLS.bind(CVSUIMessages.CVSCompareEditorInput_titleAncestor, (new Object[] { guessResourceName(), getVersionLabel(ancestor), getVersionLabel(left), getVersionLabel(right) })); toolTipText = NLS.bind(CVSUIMessages.CVSCompareEditorInput_titleAncestor, (new Object[] { guessResourcePath(), getVersionLabel(ancestor), getVersionLabel(left), getVersionLabel(right) })); } else { String leftName = null; if (left != null) leftName = left.getName(); String rightName = null; if (right != null) rightName = right.getName(); if (leftName != null && !leftName.equals(rightName)) { title = NLS.bind(CVSUIMessages.CVSCompareEditorInput_titleNoAncestorDifferent, (new Object[] { leftName, getVersionLabel(left), rightName, getVersionLabel(right) })); } else { title = NLS.bind(CVSUIMessages.CVSCompareEditorInput_titleNoAncestor, (new Object[] { guessResourceName(), getVersionLabel(left), getVersionLabel(right) })); title = NLS.bind(CVSUIMessages.CVSCompareEditorInput_titleNoAncestor, (new Object[] { guessResourcePath(), getVersionLabel(left), getVersionLabel(right) })); } } } setTitle(title); } private void setLabels(CompareConfiguration cc, IStructuredSelection selection) { ITypedElement left = this.left; ITypedElement right = this.right; ITypedElement ancestor = this.ancestor; if (left != null) { cc.setLeftLabel(getLabel(left)); cc.setLeftImage(leftImage); } if (right != null) { cc.setRightLabel(getLabel(right)); cc.setRightImage(rightImage); } if (ancestor != null) { cc.setAncestorLabel(getLabel(ancestor)); cc.setAncestorImage(ancestorImage); } } /* (Non-javadoc) * Method declared on CompareEditorInput */ public boolean isSaveNeeded() { return false; } /* (non-Javadoc) * Method declared on CompareEditorInput */ protected Object prepareInput(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { final boolean threeWay = ancestor != null; if (right == null || left == null) { setMessage(CVSUIMessages.CVSCompareEditorInput_different); return null; } initLabels(); final Differencer d = new Differencer() { protected boolean contentsEqual(Object input1, Object input2) { int compare = teamEqual(input1, input2); if (compare == NODE_EQUAL) { return true; } if (compare == NODE_NOT_EQUAL) { return false; } //revert to slow content comparison return super.contentsEqual(input1, input2); } protected void updateProgress(IProgressMonitor progressMonitor, Object node) { if (node instanceof ITypedElement) { ITypedElement element = (ITypedElement) node; progressMonitor.subTask(NLS.bind(CVSUIMessages.CompareEditorInput_fileProgress, (new String[] { element.getName() }))); progressMonitor.worked(1); } } protected Object[] getChildren(Object input) { if (input instanceof IStructureComparator) { Object[] children = ((IStructureComparator) input).getChildren(); if (children != null) return children; } return null; } protected Object visit(Object data, int result, Object ancestor, Object left, Object right) { return new DiffNode((IDiffContainer) data, result, (ITypedElement) ancestor, (ITypedElement) left, (ITypedElement) right); } }; try { // do the diff Object result = null; monitor.beginTask(CVSUIMessages.CVSCompareEditorInput_comparing, 30); IProgressMonitor sub = new SubProgressMonitor(monitor, 30); sub.beginTask(CVSUIMessages.CVSCompareEditorInput_comparing, 100); try { result = d.findDifferences(threeWay, sub, null, ancestor, left, right); } finally { sub.done(); } return result; } catch (OperationCanceledException e) { throw new InterruptedException(e.getMessage()); } catch (RuntimeException e) { handle(e); return null; } finally { monitor.done(); } } /** * Compares two nodes to determine if they are equal. Returns NODE_EQUAL * of they are the same, NODE_NOT_EQUAL if they are different, and * NODE_UNKNOWN if comparison was not possible. */ protected int teamEqual(Object left, Object right) { // calculate the type for the left contribution ICVSRemoteResource leftEdition = null; if (left instanceof ResourceEditionNode) { leftEdition = ((ResourceEditionNode) left).getRemoteResource(); } // calculate the type for the right contribution ICVSRemoteResource rightEdition = null; if (right instanceof ResourceEditionNode) rightEdition = ((ResourceEditionNode) right).getRemoteResource(); // compare them if (leftEdition == null || rightEdition == null) { return NODE_UNKNOWN; } // if they're both non-files, they're the same if (leftEdition.isContainer() && rightEdition.isContainer()) { return NODE_EQUAL; } // if they have different types, they're different if (leftEdition.isContainer() != rightEdition.isContainer()) { return NODE_NOT_EQUAL; } String leftLocation = leftEdition.getRepository().getLocation(false); String rightLocation = rightEdition.getRepository().getLocation(false); if (!leftLocation.equals(rightLocation)) { return NODE_UNKNOWN; } try { ResourceSyncInfo leftInfo = ((ICVSResource) leftEdition).getSyncInfo(); ResourceSyncInfo rightInfo = ((ICVSResource) rightEdition).getSyncInfo(); if (leftEdition.getRepositoryRelativePath().equals(rightEdition.getRepositoryRelativePath()) && leftInfo.getRevision().equals(rightInfo.getRevision())) { return NODE_EQUAL; } else { if (considerContentIfRevisionOrPathDiffers()) { return NODE_UNKNOWN; } else { return NODE_NOT_EQUAL; } } } catch (TeamException e) { handle(e); return NODE_UNKNOWN; } } private boolean considerContentIfRevisionOrPathDiffers() { return CVSUIPlugin.getPlugin().getPreferenceStore().getBoolean(ICVSUIConstants.PREF_CONSIDER_CONTENTS); } public Viewer createDiffViewer(Composite parent) { final Viewer viewer = super.createDiffViewer(parent); viewer.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { CompareConfiguration cc = getCompareConfiguration(); setLabels(cc, (IStructuredSelection) event.getSelection()); } }); ((StructuredViewer) viewer).addOpenListener(new IOpenListener() { public void open(OpenEvent event) { ISelection selection = event.getSelection(); if (!selection.isEmpty() && selection instanceof IStructuredSelection) { Object o = ((IStructuredSelection) selection).getFirstElement(); if (o instanceof DiffNode) { updateLabelsFor((DiffNode) o); } } } }); ((StructuredViewer) viewer).addDoubleClickListener(new IDoubleClickListener() { public void doubleClick(DoubleClickEvent event) { ISelection selection = event.getSelection(); if (!selection.isEmpty() && selection instanceof IStructuredSelection) { Object o = ((IStructuredSelection) selection).getFirstElement(); if (o instanceof DiffNode) { DiffNode diffNode = ((DiffNode) o); if (diffNode.hasChildren()) { AbstractTreeViewer atv = ((AbstractTreeViewer) viewer); atv.setExpandedState(o, !atv.getExpandedState(o)); } } } } }); return viewer; } /* * Update the labels for the given DiffNode */ protected void updateLabelsFor(DiffNode node) { CompareConfiguration cc = getCompareConfiguration(); ITypedElement l = node.getLeft(); if (l == null) { cc.setLeftLabel(CVSUIMessages.CVSCompareEditorInput_0); cc.setLeftImage(null); } else { cc.setLeftLabel(getLabel(l)); cc.setLeftImage(l.getImage()); } ITypedElement r = node.getRight(); if (r == null) { cc.setRightLabel(CVSUIMessages.CVSCompareEditorInput_1); cc.setRightImage(null); } else { cc.setRightLabel(getLabel(r)); cc.setRightImage(r.getImage()); } } /* (non-Javadoc) * @see org.eclipse.compare.CompareEditorInput#getToolTipText() */ public String getToolTipText() { if (toolTipText != null) { return toolTipText; } return super.getToolTipText(); } }