// in case 8) parent of removed shareable node has removed child
// node entry.
NodeState n = (NodeState) state;
if (n.hasOverlayedState()) {
NodeId oldParentId = n.getOverlayedState().getParentId();
NodeId newParentId = n.getParentId();
if (newParentId != null && !oldParentId.equals(newParentId) &&
!n.isShareable()) {
// node moved
// generate node removed & node added event
NodeState oldParent;
try {
oldParent = (NodeState) changes.get(oldParentId);
} catch (NoSuchItemStateException e) {
// old parent has been deleted, retrieve from
// shared item state manager
oldParent = (NodeState) stateMgr.getItemState(oldParentId);
}
NodeTypeImpl oldParentNodeType = getNodeType(oldParent, session);
Set mixins = oldParent.getMixinTypeNames();
Path newPath = getPath(n.getNodeId(), hmgr);
Path oldPath = getZombiePath(n.getNodeId(), hmgr);
events.add(EventState.childNodeRemoved(oldParentId,
getParent(oldPath), n.getNodeId(),
oldPath.getNameElement(),
oldParentNodeType.getQName(),
mixins, session));
NodeState newParent = (NodeState) changes.get(newParentId);
NodeTypeImpl newParentNodeType = getNodeType(newParent, session);
mixins = newParent.getMixinTypeNames();
events.add(EventState.childNodeAdded(newParentId,
getParent(newPath), n.getNodeId(),
newPath.getNameElement(),
newParentNodeType.getQName(),
mixins, session));
events.add(EventState.nodeMoved(newParentId,
newPath, n.getNodeId(), oldPath,
newParentNodeType.getQName(), mixins,
session, false));
} else {
// a moved node always has a modified parent node
NodeState parent = null;
try {
// root node does not have a parent UUID
if (state.getParentId() != null) {
parent = (NodeState) changes.get(state.getParentId());
}
} catch (NoSuchItemStateException e) {
// should never happen actually. this would mean
// the parent of this modified node is deleted
String msg = "Parent of node " + state.getId() + " is deleted.";
log.error(msg);
throw new ItemStateException(msg, e);
}
if (parent != null) {
// check if node has been renamed
ChildNodeEntry moved = null;
for (Iterator removedNodes = parent.getRemovedChildNodeEntries().iterator(); removedNodes.hasNext();) {
ChildNodeEntry child = (ChildNodeEntry) removedNodes.next();
if (child.getId().equals(n.getNodeId())) {
// found node re-added with different name
moved = child;
}
}
if (moved != null) {
NodeTypeImpl nodeType = getNodeType(parent, session);
Set mixins = parent.getMixinTypeNames();
Path newPath = getPath(state.getId(), hmgr);
Path parentPath = getParent(newPath);
Path oldPath;
try {
if (moved.getIndex() == 0) {
oldPath = PathFactoryImpl.getInstance().create(parentPath, moved.getName(), false);
} else {
oldPath = PathFactoryImpl.getInstance().create(
parentPath, moved.getName(), moved.getIndex(), false);
}
} catch (RepositoryException e) {
// should never happen actually
String msg = "Malformed path for item: " + state.getId();
log.error(msg);
throw new ItemStateException(msg, e);
}
events.add(EventState.childNodeRemoved(
parent.getNodeId(), parentPath,
n.getNodeId(), oldPath.getNameElement(),
nodeType.getQName(), mixins, session));
events.add(EventState.childNodeAdded(
parent.getNodeId(), parentPath,
n.getNodeId(), newPath.getNameElement(),
nodeType.getQName(), mixins, session));
events.add(EventState.nodeMoved(
parent.getNodeId(), newPath, n.getNodeId(),
oldPath, nodeType.getQName(), mixins,
session, false));
}
}
}
}
// check if child nodes of modified node state have been reordered
List reordered = n.getReorderedChildNodeEntries();
NodeTypeImpl nodeType = getNodeType(n, session);
Set mixins = n.getMixinTypeNames();
if (reordered.size() > 0) {
// create a node removed and a node added event for every
// reorder
for (Iterator ro = reordered.iterator(); ro.hasNext();) {
ChildNodeEntry child = (ChildNodeEntry) ro.next();
Path.Element addedElem = getPathElement(child);
Path parentPath = getPath(n.getNodeId(), hmgr);
// get removed index
NodeState overlayed = (NodeState) n.getOverlayedState();
ChildNodeEntry entry = overlayed.getChildNodeEntry(child.getId());
if (entry == null) {
throw new ItemStateException("Unable to retrieve old child index for item: " + child.getId());
}
Path.Element removedElem = getPathElement(entry);
events.add(EventState.childNodeRemoved(n.getNodeId(),
parentPath, child.getId(), removedElem,
nodeType.getQName(), mixins, session));
events.add(EventState.childNodeAdded(n.getNodeId(),
parentPath, child.getId(), addedElem,
nodeType.getQName(), mixins, session));
List cne = n.getChildNodeEntries();
// index of the child node entry before which this
// child node entry was reordered
int idx = cne.indexOf(child) + 1;
Path.Element beforeElem = null;
if (idx < cne.size()) {
beforeElem = getPathElement((ChildNodeEntry) cne.get(idx));
}
events.add(EventState.nodeReordered(n.getNodeId(),
parentPath, child.getId(), addedElem,
removedElem, beforeElem, nodeType.getQName(), mixins,
session, false));
}
}
// create events if n is shareable
createShareableNodeEvents(n, changes, hmgr, stateMgr);
} else {
// property changed
Path path = getPath(state.getId(), hmgr);
NodeState parent = (NodeState) stateMgr.getItemState(state.getParentId());
NodeTypeImpl nodeType = getNodeType(parent, session);
Set mixins = parent.getMixinTypeNames();
events.add(EventState.propertyChanged(state.getParentId(),
getParent(path), path.getNameElement(),
nodeType.getQName(), mixins, session));
}
}
// 2. removed items
for (Iterator it = changes.deletedStates(); it.hasNext();) {
ItemState state = (ItemState) it.next();
if (state.isNode()) {
// node deleted
NodeState n = (NodeState) state;
NodeState parent = (NodeState) stateMgr.getItemState(n.getParentId());
NodeTypeImpl nodeType = getNodeType(parent, session);
Set mixins = parent.getMixinTypeNames();
Path path = getZombiePath(state.getId(), hmgr);
events.add(EventState.childNodeRemoved(n.getParentId(),
getParent(path),
n.getNodeId(),
path.getNameElement(),
nodeType.getQName(),
mixins,
session));
// create events if n is shareable
createShareableNodeEvents(n, changes, hmgr, stateMgr);
} else {
// property removed
// only create an event if node still exists
try {
NodeState n = (NodeState) changes.get(state.getParentId());
// node state exists -> only property removed
NodeTypeImpl nodeType = getNodeType(n, session);
Set mixins = n.getMixinTypeNames();
Path path = getZombiePath(state.getId(), hmgr);
events.add(EventState.propertyRemoved(state.getParentId(),
getParent(path),
path.getNameElement(),
nodeType.getQName(),
mixins,
session));
} catch (NoSuchItemStateException e) {
// node removed as well -> do not create an event
}
}
}
// 3. added items
for (Iterator it = changes.addedStates(); it.hasNext();) {
ItemState state = (ItemState) it.next();
if (state.isNode()) {
// node created
NodeState n = (NodeState) state;
NodeId parentId = n.getParentId();
// the parent of an added item is always modified or new
NodeState parent = (NodeState) changes.get(parentId);
NodeTypeImpl nodeType = getNodeType(parent, session);
Set mixins = parent.getMixinTypeNames();
Path path = getPath(n.getNodeId(), hmgr);