/** * 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(); }