/**
  * Queue all the parent elements for a label update.
  *
  * @param element the element whose label and parent labels need to be updated
  */
 public void updateParentLabels(ISynchronizeModelElement element) {
   queueForLabelUpdate(element);
   while (element.getParent() != null) {
     element = (ISynchronizeModelElement) element.getParent();
     queueForLabelUpdate(element);
   }
 }
 private String getDebugDisplayLabel(ISynchronizeModelElement node) {
   if (node == null) {
     return "ROOT"; //$NON-NLS-1$
   }
   if (node.getResource() != null) {
     return node.getResource().getFullPath().toString();
   }
   return node.getName();
 }
 /**
  * This method is invoked whenever a node is removed the viewer by the provider or a sub-provider.
  * The handler removes any listener and notifies the root provider that a node was removed. The
  * node removed may have children for which a nodeRemoved callback was not invoked (see
  * modelObjectCleared).
  *
  * @param element the removed element
  * @param provider the provider that added the element
  */
 public void nodeRemoved(
     ISynchronizeModelElement element, AbstractSynchronizeModelProvider provider) {
   element.removePropertyChangeListener(listener);
   this.provider.nodeRemoved(element, provider);
   if (Policy.DEBUG_SYNC_MODELS) {
     System.out.println(
         "Node removed: "
             + getDebugDisplayLabel(element)
             + " -> "
             + getDebugDisplayLabel((ISynchronizeModelElement) element.getParent())
             + " : "
             + getDebugDisplayLabel(provider)); // $NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
   }
 }
 /**
  * Calculate and propagate problem markers in the element model
  *
  * @param element the ssynchronize element
  */
 private void propagateProblemMarkers(ISynchronizeModelElement element) {
   IResource resource = element.getResource();
   if (resource != null) {
     String property = provider.calculateProblemMarker(element);
     // If it doesn't have a direct change, a parent might
     boolean recalculateParentDecorations = hadProblemProperty(element, property);
     if (recalculateParentDecorations) {
       ISynchronizeModelElement parent = (ISynchronizeModelElement) element.getParent();
       if (parent != null) {
         propagateProblemMarkers(parent);
       }
     }
   }
 }
 /**
  * This method is invoked whenever a model object (i.e. node) is cleared from the model. This is
  * similar to node removal but is deep.
  *
  * @param node the node that was cleared
  */
 public void modelObjectCleared(ISynchronizeModelElement node) {
   node.removePropertyChangeListener(listener);
   this.provider.modelObjectCleared(node);
   if (Policy.DEBUG_SYNC_MODELS) {
     System.out.println("Node cleared: " + getDebugDisplayLabel(node)); // $NON-NLS-1$
   }
 }
 private void extractSynchronizeModelInfo(
     ISynchronizeModelElement d,
     IPath path,
     Vector<PatchFile> newList,
     Vector<PatchFile> removeList,
     Vector<PatchFile> changeList) {
   // Recursively traverse the tree for children and sort leaf elements into their respective
   // change kind sets.
   // Don't add entries for ChangeLog files though.
   if (d.hasChildren()) {
     IPath newPath = path.append(d.getName());
     for (IDiffElement element : d.getChildren()) {
       if (element instanceof ISynchronizeModelElement)
         extractSynchronizeModelInfo(
             (ISynchronizeModelElement) element, newPath, newList, removeList, changeList);
       else {
         if (!(d.getName().equals("ChangeLog"))) { // $NON-NLS-1$
           PatchFile p = new PatchFile(d.getResource());
           int kind = d.getKind() & Differencer.CHANGE_TYPE_MASK;
           if (kind == Differencer.CHANGE) {
             changeList.add(p);
           } else if (kind == Differencer.ADDITION) {
             p.setNewfile(true);
             newList.add(p);
           } else if (kind == Differencer.DELETION) {
             p.setRemovedFile(true);
             removeList.add(p);
           }
         } else {
           this.changeLogModified = true;
         }
       }
     }
   } else {
     if (!(d.getName().equals("ChangeLog"))) { // $NON-NLS-1$
       PatchFile p = new PatchFile(d.getResource());
       int kind = d.getKind() & Differencer.CHANGE_TYPE_MASK;
       if (kind == Differencer.CHANGE) {
         changeList.add(p);
       } else if (kind == Differencer.ADDITION) {
         p.setNewfile(true);
         newList.add(p);
       } else if (kind == Differencer.DELETION) {
         p.setRemovedFile(true);
         removeList.add(p);
       }
     } else {
       this.changeLogModified = true;
     }
   }
 }
  // none -> error
  // error -> none
  // none -> warning
  // warning -> none
  // warning -> error
  // error -> warning
  private boolean hadProblemProperty(ISynchronizeModelElement element, String property) {
    boolean hadError =
        element.getProperty(ISynchronizeModelElement.PROPAGATED_ERROR_MARKER_PROPERTY);
    boolean hadWarning =
        element.getProperty(ISynchronizeModelElement.PROPAGATED_WARNING_MARKER_PROPERTY);

    // Force recalculation of parents of phantom resources
    IResource resource = element.getResource();
    if (resource != null && resource.isPhantom()) {
      return true;
    }

    if (hadError) {
      if (!(property == ISynchronizeModelElement.PROPAGATED_ERROR_MARKER_PROPERTY)) {
        element.setPropertyToRoot(ISynchronizeModelElement.PROPAGATED_ERROR_MARKER_PROPERTY, false);
        if (property != null) {
          // error -> warning
          element.setPropertyToRoot(property, true);
        }
        // error -> none
        // recalculate parents
        return true;
      }
      return false;
    } else if (hadWarning) {
      if (!(property == ISynchronizeModelElement.PROPAGATED_WARNING_MARKER_PROPERTY)) {
        element.setPropertyToRoot(
            ISynchronizeModelElement.PROPAGATED_WARNING_MARKER_PROPERTY, false);
        if (property != null) {
          // warning -> error
          element.setPropertyToRoot(property, true);
          return false;
        }
        // warning ->  none
        return true;
      }
      return false;
    } else {
      if (property == ISynchronizeModelElement.PROPAGATED_ERROR_MARKER_PROPERTY) {
        // none -> error
        element.setPropertyToRoot(property, true);
        return false;
      } else if (property == ISynchronizeModelElement.PROPAGATED_WARNING_MARKER_PROPERTY) {
        // none -> warning
        element.setPropertyToRoot(property, true);
        return true;
      }
      return false;
    }
  }
  /*
   * Method that can be called from the UI thread to update the view model.
   */
  private void internalRunViewUpdate(final Runnable runnable, boolean preserveExpansion) {
    StructuredViewer viewer = getViewer();
    IResource[] expanded = null;
    IResource[] selected = null;
    try {
      if (Utils.canUpdateViewer(viewer)) {
        viewer.getControl().setRedraw(false);
        if (preserveExpansion) {
          expanded = provider.getExpandedResources();
          selected = provider.getSelectedResources();
        }
        if (viewer instanceof AbstractTreeViewer && additionsMap == null)
          additionsMap = new HashMap();
      }
      runnable.run();
    } finally {
      if (Utils.canUpdateViewer(viewer)) {
        try {
          if (additionsMap != null && !additionsMap.isEmpty() && Utils.canUpdateViewer(viewer)) {
            for (Iterator iter = additionsMap.keySet().iterator(); iter.hasNext(); ) {
              ISynchronizeModelElement parent = (ISynchronizeModelElement) iter.next();
              if (Policy.DEBUG_SYNC_MODELS) {
                System.out.println("Adding child view items of " + parent.getName()); // $NON-NLS-1$
              }
              Set toAdd = (Set) additionsMap.get(parent);
              ((AbstractTreeViewer) viewer).add(parent, toAdd.toArray(new Object[toAdd.size()]));
            }
            additionsMap = null;
          }
          if (expanded != null) {
            provider.expandResources(expanded);
          }
          if (selected != null) {
            provider.selectResources(selected);
          }
        } finally {
          viewer.getControl().setRedraw(true);
        }
      }
    }

    ISynchronizeModelElement root = provider.getModelRoot();
    if (root instanceof SynchronizeModelElement) ((SynchronizeModelElement) root).fireChanges();
  }
 /**
  * Add the element to the viewer.
  *
  * @param parent the parent of the element which is already added to the viewer
  * @param element the element to be added to the viewer
  */
 protected void doAdd(ISynchronizeModelElement parent, ISynchronizeModelElement element) {
   if (additionsMap == null) {
     if (Policy.DEBUG_SYNC_MODELS) {
       System.out.println("Added view item " + element.getName()); // $NON-NLS-1$
     }
     AbstractTreeViewer viewer = (AbstractTreeViewer) getViewer();
     viewer.add(parent, element);
   } else {
     // Accumulate the additions
     if (Policy.DEBUG_SYNC_MODELS) {
       System.out.println("Queueing view item for addition " + element.getName()); // $NON-NLS-1$
     }
     Set toAdd = (Set) additionsMap.get(parent);
     if (toAdd == null) {
       toAdd = new HashSet();
       additionsMap.put(parent, toAdd);
     }
     toAdd.add(element);
   }
 }
  private void prepareChangeLog(IProgressMonitor monitor) {

    Object element = selected.getFirstElement();

    IResource resource = null;
    Vector<PatchFile> newList = new Vector<PatchFile>();
    Vector<PatchFile> removeList = new Vector<PatchFile>();
    Vector<PatchFile> changeList = new Vector<PatchFile>();
    int totalChanges = 0;

    if (element instanceof IResource) {
      resource = (IResource) element;
    } else if (element instanceof ISynchronizeModelElement) {
      ISynchronizeModelElement sme = (ISynchronizeModelElement) element;
      resource = sme.getResource();
    } else if (element instanceof IAdaptable) {
      resource = (IResource) ((IAdaptable) element).getAdapter(IResource.class);
    }

    if (resource == null) return;

    IProject project = resource.getProject();
    // Get the repository provider so we can support multiple types of
    // code repositories without knowing exactly which (e.g. CVS, SVN, etc..).
    RepositoryProvider r = RepositoryProvider.getProvider(project);
    if (r == null) return;
    SyncInfoSet set = new SyncInfoSet();
    Subscriber s = r.getSubscriber();
    if (s == null) return;
    if (element instanceof ISynchronizeModelElement) {
      // We can extract the ChangeLog list from the synchronize view which
      // allows us to skip items removed from the view
      ISynchronizeModelElement d = (ISynchronizeModelElement) element;
      while (d.getParent() != null) d = (ISynchronizeModelElement) d.getParent();
      extractSynchronizeModelInfo(d, new Path(""), newList, removeList, changeList);
      totalChanges = newList.size() + removeList.size() + changeList.size();
    } else {
      // We can then get a list of all out-of-sync resources.
      s.collectOutOfSync(new IResource[] {project}, IResource.DEPTH_INFINITE, set, monitor);
      SyncInfo[] infos = set.getSyncInfos();
      totalChanges = infos.length;
      // Iterate through the list of changed resources and categorize them into
      // New, Removed, and Changed lists.
      for (SyncInfo info : infos) {
        int kind = SyncInfo.getChange(info.getKind());
        PatchFile p = new PatchFile(info.getLocal());

        // Check the type of entry and sort into lists.  Do not add an entry
        // for ChangeLog files.
        if (!(p.getPath().lastSegment().equals("ChangeLog"))) { // $NON-NLS-1$
          if (kind == SyncInfo.ADDITION) {
            p.setNewfile(true);
            newList.add(p);
          } else if (kind == SyncInfo.DELETION) {
            p.setRemovedFile(true);
            removeList.add(p);
          } else if (kind == SyncInfo.CHANGE) {
            if (info.getLocal().getType() == IResource.FILE) {
              changeList.add(p);
            }
          }
        } else {
          this.changeLogModified = true;
        }
      }
    }

    if (totalChanges == 0) return; // nothing to parse

    PatchFile[] patchFileInfoList = new PatchFile[totalChanges];

    // Group like changes together and sort them by path name.
    // We want removed files, then new files, then changed files.
    // To get this, we put them in the array in reverse order.
    int index = 0;
    if (changeList.size() > 0) {
      // Get the repository provider so we can support multiple types of
      // code repositories without knowing exactly which (e.g. CVS, SVN, etc..).
      Collections.sort(changeList, new PatchFileComparator());
      int size = changeList.size();
      for (int i = 0; i < size; ++i) {
        PatchFile p = changeList.get(i);
        getChangedLines(s, p, monitor);
        patchFileInfoList[index + (size - i - 1)] = p;
      }
      index += size;
    }

    if (newList.size() > 0) {
      Collections.sort(newList, new PatchFileComparator());
      int size = newList.size();
      for (int i = 0; i < size; ++i) patchFileInfoList[index + (size - i - 1)] = newList.get(i);
      index += size;
    }

    if (removeList.size() > 0) {
      Collections.sort(removeList, new PatchFileComparator());
      int size = removeList.size();
      for (int i = 0; i < size; ++i) patchFileInfoList[index + (size - i - 1)] = removeList.get(i);
    }

    // now, find out modified functions/classes.
    // try to use the the extension point. so it can be extended easily
    // for all files in patch file info list, get function guesses of each
    // file.
    monitor.subTask(Messages.getString("ChangeLog.WritingMessage")); // $NON-NLS-1$
    int unitwork = 250 / patchFileInfoList.length;
    for (PatchFile pf : patchFileInfoList) {
      // for each file
      if (pf != null) { // any ChangeLog changes will have null entries for them
        String[] funcGuessList = guessFunctionNames(pf);
        outputMultipleEntryChangeLog(pf, funcGuessList);
      }
      monitor.worked(unitwork);
    }
  }