/** * Executes the updates. Resolving text node adjacency can be skipped if adjacent text nodes are * not to be expected. * * @param mergeTexts adjacent text nodes are to be expected and must be merged */ public void execute(final boolean mergeTexts) { check(); optimize(); applyValueUpdates(); if (cacheDistanceUpdates) data.cache = true; applyStructuralUpdates(); updateDistances(); if (mergeTexts) resolveTextAdjacency(); data.cache = false; }
/** * 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(); }