Package org.eclipse.core.internal.events

Source Code of org.eclipse.core.internal.events.ResourceDeltaFactory

/*******************************************************************************
* Copyright (c) 2000, 2005 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.core.internal.events;

import java.util.Map;
import org.eclipse.core.internal.dtree.DeltaDataTree;
import org.eclipse.core.internal.dtree.NodeComparison;
import org.eclipse.core.internal.resources.*;
import org.eclipse.core.internal.watson.ElementTree;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;

/**
* This class is used for calculating and building resource delta trees for notification
* and build purposes.
*/
public class ResourceDeltaFactory {
  /**
   * Singleton indicating no delta children
   */
  protected static final ResourceDelta[] NO_CHILDREN = new ResourceDelta[0];

  /**
   * Returns the resource delta representing the changes made between the given old and new trees,
   * starting from the given root element.
   * @param markerGeneration the start generation for which deltas should be computed, or -1
   * if marker deltas should not be provided.
   */
  public static ResourceDelta computeDelta(Workspace workspace, ElementTree oldTree, ElementTree newTree, IPath root, long markerGeneration) {
    //compute the underlying delta tree.
    ResourceComparator comparator = markerGeneration >= 0 ? ResourceComparator.getNotificationComparator() : ResourceComparator.getBuildComparator();
    newTree.immutable();
    DeltaDataTree delta = null;
    if (Path.ROOT.equals(root))
      delta = newTree.getDataTree().compareWith(oldTree.getDataTree(), comparator);
    else
      delta = newTree.getDataTree().compareWith(oldTree.getDataTree(), comparator, root);

    delta = delta.asReverseComparisonTree(comparator);
    IPath pathInTree = root.isRoot() ? Path.ROOT : root;
    IPath pathInDelta = Path.ROOT;

    // get the marker deltas for the delta info object....if needed
    Map allMarkerDeltas = null;
    if (markerGeneration >= 0)
      allMarkerDeltas = workspace.getMarkerManager().getMarkerDeltas(markerGeneration);

    //recursively walk the delta and create a tree of ResourceDelta objects.
    ResourceDeltaInfo deltaInfo = new ResourceDeltaInfo(workspace, allMarkerDeltas, comparator);
    ResourceDelta result = createDelta(workspace, delta, deltaInfo, pathInTree, pathInDelta);

    //compute node ID map and fix up moves
    deltaInfo.setNodeIDMap(computeNodeIDMap(result, new NodeIDMap()));
    result.fixMovesAndMarkers(oldTree);

    // check all the projects and if they were added and opened then tweek the flags
    // so the delta reports both.
    int segmentCount = result.getFullPath().segmentCount();
    if (segmentCount <= 1)
      checkForOpen(result, segmentCount);
    return result;
  }

  /**
   * Checks to see if added projects were also opens and tweaks the flags
   * accordingly. Should only be called for root and projects. Pass the segment count
   * in since we've already calculated it before.
   */
  protected static void checkForOpen(ResourceDelta delta, int segmentCount) {
    if (delta.getKind() == IResourceDelta.ADDED)
      if (delta.newInfo.isSet(ICoreConstants.M_OPEN))
        delta.status |= IResourceDelta.OPEN;
    // return for PROJECT
    if (segmentCount == 1)
      return;
    // recurse for ROOT
    IResourceDelta[] children = delta.children;
    for (int i = 0; i < children.length; i++)
      checkForOpen((ResourceDelta) children[i], 1);
  }

  /**
   * Creates the map from node id to element id for the old and new states.
   * Used for recognizing moves.  Returns the map.
   */
  protected static NodeIDMap computeNodeIDMap(ResourceDelta delta, NodeIDMap nodeIDMap) {
    IResourceDelta[] children = delta.children;
    for (int i = 0; i < children.length; i++) {
      ResourceDelta child = (ResourceDelta) children[i];
      IPath path = child.getFullPath();
      switch (child.getKind()) {
        case IResourceDelta.ADDED :
          nodeIDMap.putNewPath(child.newInfo.getNodeId(), path);
          break;
        case IResourceDelta.REMOVED :
          nodeIDMap.putOldPath(child.oldInfo.getNodeId(), path);
          break;
        case IResourceDelta.CHANGED :
          long oldID = child.oldInfo.getNodeId();
          long newID = child.newInfo.getNodeId();
          //don't add entries to the map if nothing has changed.
          if (oldID != newID) {
            nodeIDMap.putOldPath(oldID, path);
            nodeIDMap.putNewPath(newID, path);
          }
          break;
      }
      //recurse
      computeNodeIDMap(child, nodeIDMap);
    }
    return nodeIDMap;
  }

  /**
   * Recursively creates the tree of ResourceDelta objects rooted at
   * the given path.
   */
  protected static ResourceDelta createDelta(Workspace workspace, DeltaDataTree delta, ResourceDeltaInfo deltaInfo, IPath pathInTree, IPath pathInDelta) {
    // create the delta and fill it with information
    ResourceDelta result = new ResourceDelta(pathInTree, deltaInfo);

    // fill the result with information
    NodeComparison compare = (NodeComparison) delta.getData(pathInDelta);
    int comparison = compare.getUserComparison();
    result.setStatus(comparison);
    if (comparison == IResourceDelta.NO_CHANGE || Path.ROOT.equals(pathInTree)) {
      ResourceInfo info = workspace.getResourceInfo(pathInTree, true, false);
      result.setOldInfo(info);
      result.setNewInfo(info);
    } else {
      result.setOldInfo((ResourceInfo) compare.getOldData());
      result.setNewInfo((ResourceInfo) compare.getNewData());
    }
    // recurse over the children
    IPath[] childKeys = delta.getChildren(pathInDelta);
    int numChildren = childKeys.length;
    if (numChildren == 0) {
      result.setChildren(NO_CHILDREN);
    } else {
      ResourceDelta[] children = new ResourceDelta[numChildren];
      for (int i = 0; i < numChildren; i++) {
        //reuse the delta path if tree-relative and delta-relative are the same
        IPath newTreePath = pathInTree == pathInDelta ? childKeys[i] : pathInTree.append(childKeys[i].lastSegment());
        children[i] = createDelta(workspace, delta, deltaInfo, newTreePath, childKeys[i]);
      }
      result.setChildren(children);
    }

    // if this delta has children but no other changes, mark it as changed
    int status = result.status;
    if ((status & IResourceDelta.ALL_WITH_PHANTOMS) == 0 && numChildren != 0)
      result.setStatus(status |= IResourceDelta.CHANGED);

    // return the delta
    return result;
  }

  /**
   * Returns an empty build delta describing the fact that no
   * changes occurred in the given project.  The returned delta
   * is not appropriate for use as a notification delta because
   * it is rooted at a project, and does not contain marker deltas.
   */
  public static IResourceDelta newEmptyDelta(IProject project) {
    ResourceDelta result = new ResourceDelta(project.getFullPath(), new ResourceDeltaInfo(((Workspace) project.getWorkspace()), null, ResourceComparator.getBuildComparator()));
    result.setStatus(0);
    result.setChildren(NO_CHILDREN);
    ResourceInfo info = ((Project) project).getResourceInfo(true, false);
    result.setOldInfo(info);
    result.setNewInfo(info);
    return result;
  }
}
TOP

Related Classes of org.eclipse.core.internal.events.ResourceDeltaFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.