ModeShape/modeshape — pull request #879 by rhauch (2013-07-03 20:55:03+00:00)
Title: MODE-1984 Corrected shareable node behavior upon removing a shared node

When a shared node is removed, ModeShape's behavior is that this is the same as calling `node.removeShare()`, which just removes the share and does not affect the other nodes in the shared set. However, when the primary node was removed, ModeShape was incorrectly removing the node from the repository, even though the parents of the other nodes in the shared set still contained references to the shared node.

In particular, the problem appeared to manifest itself only when the shared node was looked up by identifier and then removed. The resulting node was an instance of `JcrNode` rather than `JcrSharedNode`, and thus the remove logic `JcrSharedNode` was never called.

Quite a few small changes were required to fix the problem. First, two unit tests were added to replicate the incorrect behavior. Then, several smaller changes were required in a number of other classes. For example, the logic of removing a shared node was moved out of the `JcrSharedNode` class and into the JcrNode base class. However, this additional logic only kicks in if the node is `mix:shareable`.

While working on this fix, I discovered another subtle bug in how the SessionNode removed a child when that child had additional parents. This was corrected and validated.

The final challenge with this fix was that when `node.save()` was called on the parent (or ancestor) of the parent from which the shared node was removed, the changes to the shared node (which no longer appeared as a descendant of the saved node) were not being saved. The cause turned out to be that when the *primary* node was removed, ModeShape was not recording that the old parent was removed from the additional nodes, and thus the logic to determine which nodes are affected by the `node.save()` never discovered that the removed node used to exist below the saved node.

All unit and integration tests pass after these changes.