use of javax.jcr.MergeException in project jackrabbit by apache.
the class VersionManagerImplMerge method doMergeTest.
/**
* Performs the merge test. If the result is 'update', then the corresponding
* source node is returned. if the result is 'leave' or 'besteffort-fail'
* then <code>null</code> is returned. If the result of the merge test is
* 'fail' with bestEffort set to <code>false</code> a MergeException is
* thrown.
* <p>
* jsr170 - 8.2.10 Merge:
* [...]
* <ul>
* <li>If N is currently checked-in then:</li>
* <ul>
* <li>If V' is a successor (to any degree) of V, then the merge result
* for N is update.
* </li>
* <li>If V' is a predecessor (to any degree) of V or if V and
* V' are identical (i.e., are actually the same version),
* then the merge result for N is leave.
* </li>
* <li>If V is neither a successor of, predecessor of, nor
* identical with V', then the merge result for N is failed.
* This is the case where N and N' represent divergent
* branches of the version graph, thus determining the
* result of a merge is non-trivial.
* </li>
* </ul>
* <li>If N is currently checked-out then:</li>
* <ul>
* <li>If V' is a predecessor (to any degree) of V or if V and
* V' are identical (i.e., are actually the same version),
* then the merge result for N is leave.
* </li>
* <li>If any other relationship holds between V and V',
* then the merge result for N is fail.
* </li>
* </ul>
* </ul>
*
* @param state state to test
* @param srcRoot root node state of the source workspace
* @param failedIds the list to store the failed node ids.
* @param bestEffort the best effort flag
* @return the corresponding source node or <code>null</code>
* @throws RepositoryException if an error occurs.
* @throws AccessDeniedException if access is denied
*/
private NodeStateEx doMergeTest(NodeStateEx state, NodeStateEx srcRoot, List<ItemId> failedIds, boolean bestEffort) throws RepositoryException, AccessDeniedException {
// If N does not have a corresponding node then the merge result for N is leave.
NodeStateEx srcNode = getCorrespondingNode(state, srcRoot);
if (srcNode == null) {
return null;
}
// if not versionable, update
if (!state.getEffectiveNodeType().includesNodeType(NameConstants.MIX_VERSIONABLE) || failedIds == null) {
return srcNode;
}
// if source node is not versionable, leave
if (!srcNode.getEffectiveNodeType().includesNodeType(NameConstants.MIX_VERSIONABLE)) {
return null;
}
// test versions. the following code could be simplified but is
// intentionally expanded for follow the spec.
InternalVersion v = getBaseVersion(state);
InternalVersion vp = getBaseVersion(srcNode);
if (!isCheckedOut(state)) {
// If N is currently checked-in then:
if (vp.isMoreRecent(v)) {
// - If V' is an eventual successor of V, then the merge result for N is update.
return srcNode;
} else if (v.equals(vp) || v.isMoreRecent(vp)) {
// actually the same version), then the merge result for N is leave.
return null;
}
// - If V is neither an eventual successor of, eventual predecessor of, nor
// identical with V', then the merge result for N is failed. This is the case
// where N and N' represent divergent branches of the version graph.
// failed is covered below
} else {
// If N is currently checked-out then:
if (v.equals(vp) || v.isMoreRecent(vp)) {
// N is leave.
return null;
}
// - If any other relationship holds between V and V', then the merge result
// for N is fail.
// failed is covered below
}
if (vp.isMoreRecent(v) && !isCheckedOut(state)) {
// "newer" than N and therefore N should be updated to reflect N'.
return srcNode;
} else if (v.equals(vp) || v.isMoreRecent(vp)) {
// N' is "older" or the "same age" as N and therefore N should be left alone.
return null;
} else {
// thus determining the result of a merge is non-trivial.
if (bestEffort) {
// add 'offending' version to jcr:mergeFailed property
Set<NodeId> set = getMergeFailed(state);
set.add(vp.getId());
setMergeFailed(state, set);
failedIds.add(state.getNodeId());
state.store();
return null;
} else {
String msg = "Unable to merge nodes. Violating versions. " + safeGetJCRPath(state);
log.debug(msg);
throw new MergeException(msg);
}
}
}
use of javax.jcr.MergeException in project jackrabbit by apache.
the class MergeNodeTest method testMergeNodeBestEffortFalse.
/**
* Node.merge(): bestEffort is false and any merge fails a MergeException is
* thrown.<br>
*/
@SuppressWarnings("deprecation")
public void testMergeNodeBestEffortFalse() throws RepositoryException {
/// create successor versions for a node
// so merge fails for this node
// default workspace
Node originalNode = testRootNode.getNode(nodeName1);
originalNode.checkout();
originalNode.checkin();
// merge, besteffort set to false
try {
nodeToMerge.merge(workspace.getName(), false);
fail("bestEffort is false and any merge should throw a MergeException.");
} catch (MergeException e) {
// successful
}
}
use of javax.jcr.MergeException in project jackrabbit by apache.
the class MergeCheckedoutSubNodeTest method testFailIfCorrespondingNodeIsSuccessorJcr2.
/**
* VersionManager.merge(): If V' of a versionable subnode N' in the source workspace
* is a successor of V (the base version of a subnode N in this workspace),
* calling merge must fail.
*/
public void testFailIfCorrespondingNodeIsSuccessorJcr2() throws RepositoryException {
// make V' of a subnode N' in source workspace be a successor version of
// the base version of the corresponding subnode.
Node n = testRootNode.getNode(nodeName1 + "/" + nodeName2);
VersionManager versionManager = n.getSession().getWorkspace().getVersionManager();
String path = n.getPath();
versionManager.checkout(path);
versionManager.checkin(path);
versionManager.checkout(path);
try {
// merge, besteffort set to false to stop at the first failure
nodeToMerge.getSession().getWorkspace().getVersionManager().merge(nodeToMerge.getPath(), workspace.getName(), false);
fail("Merging a checkedout node if the version V' of the corresponding node is a successor of this node's base version must fail.");
} catch (MergeException e) {
// success
}
}
use of javax.jcr.MergeException in project jackrabbit by apache.
the class MergeNodeTest method testMergeNodeBestEffortFalseAmbiguousVersions.
/**
* A MergeVersionException is thrown if bestEffort is false and a
* versionable node is encountered whose corresponding node's base version
* is on a divergent branch from this node's base version.
*/
@SuppressWarnings("deprecation")
public void testMergeNodeBestEffortFalseAmbiguousVersions() throws RepositoryException {
/// create 2 independent base versions for a node and its corresponding node
// so merge fails for this node
// default workspace
Node originalNode = testRootNode.getNode(nodeName1);
originalNode.checkout();
originalNode.checkin();
// second workspace
nodeToMerge.checkin();
// "merge" the clonedNode with the newNode from the default workspace
nodeToMerge.checkout();
// merge, besteffort set to false
try {
nodeToMerge.merge(workspace.getName(), false);
fail("BestEffort is false and corresponding node's version is ambiguous. Merge should throw a MergeException.");
} catch (MergeException e) {
// successful
}
}
Aggregations