/******************************************************************************* * Copyright 2005-2007, CHISEL Group, University of Victoria, Victoria, BC, Canada * and IBM Corporation. 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: * The Chisel Group, University of Victoria *******************************************************************************/ package net.sourceforge.tagsea.resources.sharing.ui; import java.util.HashMap; import java.util.HashSet; import java.util.Set; import java.util.TreeSet; import net.sourceforge.tagsea.TagSEAPlugin; import net.sourceforge.tagsea.core.IWaypoint; import net.sourceforge.tagsea.core.WaypointMatch; import net.sourceforge.tagsea.resources.IResourceWaypointAttributes; import net.sourceforge.tagsea.resources.ResourceWaypointPlugin; import net.sourceforge.tagsea.resources.waypoints.IMutableResourceWaypointDescriptor; import net.sourceforge.tagsea.resources.waypoints.IResourceWaypointDescriptor; import net.sourceforge.tagsea.resources.waypoints.ResourceWaypointProxyDescriptor; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.wizard.WizardPage; /** * Generic wizard page for importing resource waypoints has functionality for * discovering differences between a resource waypoint descriptor and a waypoint * in the workpsace. * @author Del Myers * */ public abstract class AbstractResourceWaypointImportWizardPage extends WizardPage { private HashMap<IWaypointIdentifier, Set<String>> attributeConflicts; private HashMap<IWaypointIdentifier, Boolean> conflictingTags; private HashSet<IWaypointIdentifier> checkedWaypoints; private HashMap<IWaypointIdentifier, IWaypoint> matchingWaypoints; /** * @param pageName * @param title * @param titleImage */ protected AbstractResourceWaypointImportWizardPage(String pageName, String title, ImageDescriptor titleImage) { super(pageName, title, titleImage); attributeConflicts = new HashMap<IWaypointIdentifier, Set<String>>(); checkedWaypoints = new HashSet<IWaypointIdentifier>(); matchingWaypoints = new HashMap<IWaypointIdentifier, IWaypoint>(); conflictingTags = new HashMap<IWaypointIdentifier, Boolean>(); } /** * Looks to find a matching waypoint for the given descriptor in the workspace. If one doesn't exist, * null is returned. If it does exist, then a set containing the names of the attributes that conflict * are returned. * @param descriptor the descriptor to check. * @param ignoreTextData whether or not line numbers and character offsets should be ignored. * @param ignoreRevision whether or not revisions should be ignored. * @return */ protected Set<String> findConflictingAttributes(IResourceWaypointDescriptor descriptor, boolean ignoreTextData, boolean ignoreRevision) { ResourceWaypointIdentifier id = new ResourceWaypointIdentifier(descriptor); if (checkedWaypoints.contains(id)) { return attributeConflicts.get(id); } IWaypoint wp = getWaypointForId(id); checkedWaypoints.add(id); if (wp != null) { Set<String> conflicts = new TreeSet<String>(); String[] atts = descriptor.getAttributes(); for (String att : atts) { if (ignoreRevision && att.equals(IResourceWaypointAttributes.ATTR_REVISION)) { continue; } if (ignoreTextData && ( att.equals(IResourceWaypointAttributes.ATTR_LINE) || att.equals(IResourceWaypointAttributes.ATTR_CHAR_END) || att.equals(IResourceWaypointAttributes.ATTR_CHAR_START) ) ){ continue; } if (att.equals(IResourceWaypointAttributes.ATTR_HANDLE_IDENTIFIER)) continue; Object thisValue = descriptor.getValue(att); Object thatValue = wp.getValue(att); if (thisValue == null && thatValue == null) { continue; } else if ((thisValue == null && thatValue != null) || (thisValue !=null && thatValue==null)) { conflicts.add(att); } else if (!thisValue.equals(thatValue)) { conflicts.add(att); } } attributeConflicts.put(id, conflicts); return conflicts; } return null; } /** * Returns true if a waypoint with the same id as the given descriptor exists in the workspace * and it has different tags than the descriptor, or if a waypoint with . False otherwise. * @param descriptor * @return */ protected boolean doTagsConflict(IResourceWaypointDescriptor descriptor) { ResourceWaypointIdentifier id = new ResourceWaypointIdentifier(descriptor); Boolean conflict = conflictingTags.get(id); if (conflict == null) { IWaypoint wp = getWaypointForId(id); if (wp != null) { conflict = !descriptor.getTags().equals(new ResourceWaypointProxyDescriptor(wp).getTags()); } else { conflict = false; } conflictingTags.put(id, conflict); } return conflict; } protected IWaypoint getWaypointForId(IWaypointIdentifier id) { if (checkedWaypoints.contains(id)) { return matchingWaypoints.get(id); } checkedWaypoints.add(id); WaypointMatch[] matches = TagSEAPlugin.getDefault().locate(ResourceWaypointPlugin.WAYPOINT_ID, id.getAttributes(), id.getTagNames()); if (matches != null && matches.length > 0) { matchingWaypoints.put(id, matches[0].getWaypoint()); return matches[0].getWaypoint(); } return null; } /** * Merges the given waypoint descriptor with the attributes and tags for the local workspace waypoint * if it exists so that the source descriptor's attributes are copied over the local waypoint's. If * A local waypoint doesn't exist, then the source is returned. If the waypoint exists, the returned * descriptor will be an instanceof ResourceWaypointProxyDescriptor and can be committed directly. * @param target * @param attributesToCopy * @param copyTags * @return */ protected IResourceWaypointDescriptor mergeDescriptor(IResourceWaypointDescriptor source, Set<String> attributesToCopy, boolean copyTags) { IWaypoint wp = getWaypointForId(new ResourceWaypointIdentifier(source)); IMutableResourceWaypointDescriptor result; if (wp == null) { return source; } else { result = new ResourceWaypointProxyDescriptor(wp); for (String attr : attributesToCopy) { result.setValue(attr, source.getValue(attr)); } if (copyTags) { result.setTags(source.getTags()); } } return result; } /** * Returns true if the page has conflicts with the waypoints in the workspace. * @return */ protected boolean pageHasConflicts(boolean ignoreTextData, boolean ignoreRevision) { boolean conflict = false; for (IResourceWaypointDescriptor d : getDescriptors()) { conflict |= doTagsConflict(d); if (!conflict) { Set<String> attrs =findConflictingAttributes(d, ignoreTextData, ignoreRevision); conflict |= (attrs != null && attrs.size() > 0); } if (conflict) break; } return conflict; } /** * Calculates the merged descriptors for this page. * @return */ protected abstract IResourceWaypointDescriptor[] calculateMergedDescriptors(); /** * Gets the unmerged descriptors for this page. * @return */ protected abstract IResourceWaypointDescriptor[] getDescriptors(); /* (non-Javadoc) * @see org.eclipse.jface.dialogs.DialogPage#dispose() */ @Override public void dispose() { attributeConflicts.clear(); checkedWaypoints.clear(); conflictingTags.clear(); matchingWaypoints.clear(); super.dispose(); } /** * Returns a resource for the given descriptor or null if it does not exist. * @param descriptor */ protected IResource getResourceForDescriptor(IResourceWaypointDescriptor descriptor) { return ResourcesPlugin.getWorkspace().getRoot().findMember(descriptor.getResource()); } }