예제 #1
0
  /**
   * Resolves unwanted text node adjacency which can result from structural changes in the database.
   * Adjacent text nodes are two text nodes A and B, where PRE(B)=PRE(A)+1 and PARENT(A)=PARENT(B).
   */
  private void resolveTextAdjacency() {
    // Text node merges are also gathered on a separate list to leverage optimizations.
    final AtomicUpdateList allMerges = new AtomicUpdateList(data);

    // keep track of the visited locations to avoid superfluous checks
    final IntSet s = new IntSet();
    // Text nodes have to be merged from the highest to the lowest pre value
    for (int i = 0; i < updStructural.size(); i++) {
      final BasicUpdate u = updStructural.get(i);
      final Data insseq = u.getInsertionData();
      // calculate the new location of the update, here we have to check for adjacency
      final int newLocation = u.location + u.accumulatedShifts - u.shifts;
      final int beforeNewLocation = newLocation - 1;
      // check surroundings of this location for adjacent text nodes depending on the
      // kind of update, first the one with higher PRE values (due to shifts!)
      // ... for insert/replace ...
      if (insseq != null) {
        // calculate the current following node
        final int followingNode = newLocation + insseq.meta.size;
        final int beforeFollowingNode = followingNode - 1;
        // check the nodes at the end of/after the insertion sequence
        if (!s.contains(beforeFollowingNode)) {
          final AtomicUpdateList merges = necessaryMerges(beforeFollowingNode, allMerges.data);
          mergeNodes(merges);
          allMerges.merge(merges);
          s.add(beforeFollowingNode);
        }
      }
      // check nodes for delete and for insert before the updated location
      if (!s.contains(beforeNewLocation)) {
        final AtomicUpdateList merges = necessaryMerges(beforeNewLocation, allMerges.data);
        mergeNodes(merges);
        allMerges.merge(merges);
        s.add(beforeNewLocation);
      }
    }

    allMerges.updateDistances();
    allMerges.clear();
  }
예제 #2
0
  /**
   * Updates distances to restore parent-child relationships that have been invalidated by
   * structural updates.
   *
   * <p>Each structural update (insert/delete) leads to a shift of higher PRE values. This
   * invalidates parent-child relationships. Distances are only updated after all structural updates
   * have been carried out to make sure each node (that has to be updated) is only touched once.
   */
  public void updateDistances() {
    accumulatePreValueShifts();
    final IntSet alreadyUpdatedNodes = new IntSet();

    for (final BasicUpdate update : updStructural) {
      int newPreOfAffectedNode = update.preOfAffectedNode + update.accumulatedShifts;

      /* Update distance for the affected node and all following siblings of nodes
       * on the ancestor-or-self axis. */
      while (newPreOfAffectedNode < data.meta.size) {
        if (alreadyUpdatedNodes.contains(newPreOfAffectedNode)) break;
        data.dist(
            newPreOfAffectedNode,
            data.kind(newPreOfAffectedNode),
            calculateNewDistance(newPreOfAffectedNode));
        alreadyUpdatedNodes.add(newPreOfAffectedNode);
        newPreOfAffectedNode += data.size(newPreOfAffectedNode, data.kind(newPreOfAffectedNode));
      }
    }
  }