// b) the parent node of a property state with STATUS_EXISTING_MODIFIED or STATUS_STALE_DESTROYED
// collect all candidates based on above criteria
Collection<NodeId> candidateIds = new LinkedList<NodeId>();
try {
HierarchyManager hierMgr = getHierarchyMgr();
ItemState[] states =
transientStore.values().toArray(new ItemState[0]);
for (ItemState state : states) {
if (state.getStatus() == ItemState.STATUS_EXISTING_MODIFIED
|| state.getStatus() == ItemState.STATUS_STALE_DESTROYED) {
NodeId nodeId;
if (state.isNode()) {
nodeId = (NodeId) state.getId();
} else {
nodeId = state.getParentId();
}
// remove any descendant candidates
boolean skip = false;
for (Iterator<NodeId> it = candidateIds.iterator(); it.hasNext();) {
NodeId id = it.next();
if (nodeId.equals(id) || hierMgr.isAncestor(id, nodeId)) {
// already a candidate or a descendant thereof
// => skip
skip = true;
break;
}
if (hierMgr.isAncestor(nodeId, id)) {
// candidate is a descendant => remove
it.remove();
}
}
if (!skip) {
// add to candidates
candidateIds.add(nodeId);
}
}
}
if (candidateIds.size() == 1) {
return candidateIds.iterator().next();
}
// pick (any) candidate with shortest path to start with
NodeId candidateId = null;
for (NodeId id : candidateIds) {
if (candidateId == null) {
candidateId = id;
} else {
if (hierMgr.getDepth(id) < hierMgr.getDepth(candidateId)) {
candidateId = id;
}
}
}
// starting with this candidate closest to root, find first parent
// which is an ancestor of all candidates
NodeState state = (NodeState) getItemState(candidateId);
NodeId parentId = state.getParentId();
boolean continueWithParent = false;
while (parentId != null) {
for (NodeId id : candidateIds) {
if (hierMgr.getRelativeDepth(parentId, id) == -1) {
continueWithParent = true;
break;
}
}
if (continueWithParent) {