String vhIdentifier =
new String(((PropertyData)dataManager.getItemData(frozen, new QPathEntry(
Constants.JCR_CHILDVERSIONHISTORY, 0), ItemType.PROPERTY)).getValues().get(0).getAsByteArray());
NodeData cHistory = null;
if ((cHistory = (NodeData)dataManager.getItemData(vhIdentifier)) == null)
throw new RepositoryException("Version history is not found with uuid " + vhIdentifier);
childHistory = new VersionHistoryDataHelper(cHistory, dataManager, nodeTypeDataManager);
}
catch (IllegalStateException e)
{
throw new RepositoryException("jcr:childVersionHistory, error of data read "
+ userSession.getLocationFactory().createJCRPath(cvhpPropPath).getAsString(false), e);
}
catch (IOException e)
{
throw new RepositoryException("jcr:childVersionHistory, error of data read "
+ userSession.getLocationFactory().createJCRPath(cvhpPropPath).getAsString(false), e);
}
String versionableIdentifier = null;
try
{
versionableIdentifier =
new String(((PropertyData)dataManager.getItemData(childHistory, new QPathEntry(
Constants.JCR_VERSIONABLEUUID, 0), ItemType.PROPERTY)).getValues().get(0).getAsByteArray());
}
catch (IOException e)
{
throw new RepositoryException("jcr:childVersionHistory, error of data read "
+ userSession.getLocationFactory().createJCRPath(cvhpPropPath).getAsString(false), e);
}
NodeData versionable = (NodeData)dataManager.getItemData(versionableIdentifier);
if (versionable != null)
{
// exists,
// On restore of VN, if the workspace currently has an already
// 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());
}
}
}
AccessControlList acl = currentNode().getACL();
boolean isPrivilegeable =
nodeTypeDataManager.isNodeType(Constants.EXO_PRIVILEGEABLE, frozen.getPrimaryTypeName(),
frozen.getMixinTypeNames());
boolean isOwneable =
nodeTypeDataManager.isNodeType(Constants.EXO_OWNEABLE, frozen.getPrimaryTypeName(),
frozen.getMixinTypeNames());
if (isPrivilegeable || isOwneable)
{
List<AccessControlEntry> permissionEntries = new ArrayList<AccessControlEntry>();
permissionEntries.addAll((isPrivilegeable ? frozen.getACL() : currentNode().getACL())
.getPermissionEntries());
String owner = isOwneable ? frozen.getACL().getOwner() : currentNode().getACL().getOwner();
acl = new AccessControlList(owner, permissionEntries);
}
NodeData restoredData =
new TransientNodeData(restoredPath, jcrUuid, frozen.getPersistedVersion(), frozen.getPrimaryTypeName(),
frozen.getMixinTypeNames(), frozen.getOrderNumber(), currentNode().getIdentifier(), acl);
changes.add(ItemState.createAddedState(restoredData));
pushCurrent(restoredData);
}
else if (action == OnParentVersionAction.INITIALIZE || action == OnParentVersionAction.COMPUTE)
{
// current C in the workspace will be left unchanged,
NodeData existed =
(NodeData)dataManager.getItemData(currentNode(), new QPathEntry(frozen.getQPath().getName(), 0),
ItemType.NODE);
if (existed != null)
{
// copy existed - i.e. left unchanged
ItemDataCopyVisitor copyVisitor = new ItemDataCopyVisitor(currentNode(), frozen.getQPath().getName(),
// node,
nodeTypeDataManager, userSession.getTransientNodesManager(), true);
existed.accept(copyVisitor);
changes.addAll(copyVisitor.getItemAddStates());
} // else - nothing to do, i.e. left unchanged
pushCurrent(null); // JCR-193, skip any childs of that node now
}