// existing node corresponding to C’s version history and the
// removeExisting flag of the restore is set to true, then that
// instance of C becomes the child of the restored N.
if (!removeExisting)
{
throw new ItemExistsException("Item with the same UUID " + versionableIdentifier
+ " as versionable child node "
+ userSession.getLocationFactory().createJCRPath(versionable.getQPath()).getAsString(false)
+ " already exists and removeExisting=false");
}
// else - leaving existed unchanged
}
else
{
// not found, gets last version (by time of creation) and restore it
NodeData lastVersionData = childHistory.getLastVersionData();
NodeData cvFrozen =
(NodeData)dataManager.getItemData(lastVersionData, new QPathEntry(Constants.JCR_FROZENNODE, 1),
ItemType.NODE);
ItemDataRestoreVisitor restoreVisitor =
new ItemDataRestoreVisitor(currentNode(), qname, childHistory, userSession, removeExisting, changes);
cvFrozen.accept(restoreVisitor);
changes.addAll(restoreVisitor.getRestoreChanges().getAllStates());
}
pushCurrent(null); // skip any childs of that node
}
else if (currentNode() != null)
{
// ordinary node for copy under nt:frozenNode
// [PN] 10.04.06 In case of COPY - copy node, otherwise we don't
// 8.2.11.3 INITIALIZE; 8.2.11.4 COMPUTE
// On restore of VN, the C stored as its child will be ignored, and the
// current C in the workspace will be left unchanged.
int action =
nodeTypeDataManager.getChildNodeDefinition(qname, frozen.getPrimaryTypeName(),
currentNode().getPrimaryTypeName(),
currentNode().getMixinTypeNames()).getOnParentVersion();
if (log.isDebugEnabled())
{
log.debug("Stored node " + frozen.getQPath().getAsString() + ", "
+ OnParentVersionAction.nameFromValue(action));
}
if (action == OnParentVersionAction.COPY || action == OnParentVersionAction.VERSION)
{
// copy
QPath restoredPath =
QPath.makeChildPath(currentNode().getQPath(), frozen.getQPath().getName(), frozen.getQPath().getIndex());
// jcr:uuid
String jcrUuid = null;
NodeData existing = null;
if (nodeTypeDataManager.isNodeType(Constants.MIX_REFERENCEABLE, frozen.getPrimaryTypeName(), frozen
.getMixinTypeNames()))
{
// copy uuid from frozen state of mix:referenceable,
// NOTE: mix:referenceable stored in frozen state with genereted ID
// (JCR_XITEM PK) as UUID must be unique,
// but jcr:uuid property containts real UUID.
QPath jcrUuidPath = QPath.makeChildPath(frozen.getQPath(), Constants.JCR_UUID);
try
{
jcrUuid =
new String(((PropertyData)dataManager.getItemData(frozen, new QPathEntry(Constants.JCR_UUID, 0),
ItemType.PROPERTY)).getValues().get(0).getAsByteArray());
}
catch (IOException e)
{
throw new RepositoryException("jcr:uuid, error of data read "
+ userSession.getLocationFactory().createJCRPath(jcrUuidPath).getAsString(false), e);
}
existing = (NodeData)dataManager.getItemData(jcrUuid);
}
else
{
// try to use existing node uuid, otherwise to generate one new
existing =
(NodeData)dataManager.getItemData(currentNode(), new QPathEntry(frozen.getQPath().getName(), frozen
.getQPath().getIndex()), ItemType.NODE);
if (existing != null)
{
jcrUuid = existing.getIdentifier();
}
else
{
jcrUuid = IdGenerator.generate();
}
}
if (existing != null && !existing.getQPath().isDescendantOf(restored.getQPath()))
{
NodeData existingDelegared = (NodeData)findDelegated(existing.getQPath());
if (existingDelegared != null)
{
// was restored by previous restore (Workspace.restore(...)), remove
// it from delegated log
deleteDelegated(existing.getQPath());
}
else
{
// exists in workspace
if (removeExisting)
{
// remove existed node, with validation (same as for restored
// root)
ItemDataRemoveVisitor removeVisitor = new RemoveVisitor();
removeVisitor.visit(existing);
changes.addAll(removeVisitor.getRemovedStates());
}
else
{
throw new ItemExistsException("Node with the same UUID as restored child node "
+ userSession.getLocationFactory().createJCRPath(restoredPath).getAsString(false)
+ " already exists and removeExisting=false. Existed "
+ userSession.getLocationFactory().createJCRPath(existing.getQPath()).getAsString(false) + " "
+ existing.getIdentifier());
}