/** * Removes superfluous update operations. If a node T is deleted or replaced, all updates on the * descendant axis of T can be left out as they won't affect the database after all. * * <p>Superfluous updates can have a minimum PRE value of pre(T)+1 and a maximum PRE value of * pre(T)+size(T). * * <p>An update with location pre(T)+size(T) can only be removed if the update is an atomic insert * and the inserted node is then part of the subtree of T. */ public void optimize() { if (opt) return; check(); // traverse from lowest to highest PRE value int i = updStructural.size() - 1; while (i >= 0) { final BasicUpdate u = updStructural.get(i); // If this update can lead to superfluous updates ... if (u.destructive()) { // we determine the lowest and highest PRE values of a superfluous update final int pre = u.location; final int fol = pre + data.size(pre, data.kind(pre)); i--; // and have a look at the next candidate while (i >= 0) { final BasicUpdate desc = updStructural.get(i); final int descpre = desc.location; // if the candidate operates on the subtree of T and inserts a node ... if (descpre <= fol && (desc instanceof Insert || desc instanceof InsertAttr) && desc.parent() >= pre && desc.parent() < fol) { // it is removed. updStructural.remove(i--); // Other updates (not inserting a node) that operate on the subtree of T can // only have a PRE value that is smaller than the following PRE of T } else if (descpre < fol) { // these we delete. updStructural.remove(i--); // Else there's nothing to delete } else break; } } else i--; } opt = true; }