/*
* Copyright (C) 2009 eXo Platform SAS.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.exoplatform.services.jcr.api.version;
import org.exoplatform.services.jcr.JcrAPIBaseTest;
import java.util.ArrayList;
import java.util.List;
import javax.jcr.InvalidItemStateException;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.nodetype.NodeType;
import javax.jcr.nodetype.NodeTypeManager;
import javax.jcr.version.Version;
import javax.jcr.version.VersionHistory;
/**
* Created by The eXo Platform SAS Author : Peter Nedonosko
* peter.nedonosko@exoplatform.com.ua 24.02.2006
*/
public class BaseVersionTest extends JcrAPIBaseTest
{
protected Version version = null;
protected Version version2 = null;
protected Node versionableNode = null;
protected Node nonVersionableNode = null;
class BaseVersionFinder
{
private Version baseVersion = null;
private boolean baseVersionFound = false;
BaseVersionFinder(Version baseVersion)
{
this.baseVersion = baseVersion;
}
public Version getBaseVersion()
{
return baseVersion;
}
public boolean check(Version someVersion) throws RepositoryException
{
if (baseVersionFound)
return false;
baseVersionFound = baseVersion.isSame(someVersion);
return baseVersionFound;
}
public boolean isBaseVersionFound()
{
return baseVersionFound;
}
}
public void setUp() throws Exception
{
super.setUp();
NodeTypeManager ntManager = session.getWorkspace().getNodeTypeManager();
// build persistent versionable and non-versionable nodes
try
{
versionableNode = prepareVersionableNode(root, "versionableFolder1", ntManager.getNodeType("nt:folder"));
}
catch (RepositoryException e)
{
fail("Failed to create versionable test node." + e.getMessage());
}
try
{
nonVersionableNode = root.addNode("nonVersionableFolder1", "nt:unstructured");
root.save();
}
catch (RepositoryException e)
{
fail("Failed to create non-versionable test node." + e.getMessage());
}
}
protected Node prepareVersionableNode(Node parent, String name, NodeType nodetype) throws RepositoryException
{
Node versionable = parent.addNode(name, nodetype.getName());
if (!nodetype.isNodeType("mix:versionable"))
{
versionable.addMixin("mix:versionable");
}
parent.save();
return versionable;
}
protected void checkNotExisted(String nodeRelPath) throws RepositoryException
{
try
{
Node doc = versionableNode.getNode(nodeRelPath);
fail("A child node '" + nodeRelPath + "' must not be found");
}
catch (PathNotFoundException e)
{
// success
}
}
protected Node checkExisted(String nodeRelPath) throws RepositoryException
{
return checkExisted(nodeRelPath, null);
}
protected Node checkExisted(String nodeRelPath, String[] properties) throws RepositoryException
{
try
{
Node doc = versionableNode.getNode(nodeRelPath);
// PropertyIterator pi = doc1.getProperties();
// NodeIterator ni = doc1.getNodes();
if (log.isDebugEnabled())
log.debug("Node '" + nodeRelPath + "' found in versionable node: " + versionableNode.getPath());
if (properties != null)
{
for (String p : properties)
{
try
{
String pValue = doc.getProperty(p).getString();
if (log.isDebugEnabled())
log.debug("Node '" + nodeRelPath + "' property " + p + ": " + pValue);
}
catch (PathNotFoundException e)
{
fail("A child node's '" + nodeRelPath + "' property '" + p + "' must be found");
}
}
}
return doc;
}
catch (PathNotFoundException e)
{
fail("A child node '" + nodeRelPath + "' must be found");
}
return null;
}
protected void makeVersionable(Node anNode) throws RepositoryException
{
if (!anNode.isNodeType("mix:versionable"))
{
anNode.addMixin("mix:versionable");
}
}
// [PN] 06.05.06
protected void checkVersionHistory(Node versionable, int versionCount) throws RepositoryException
{
VersionHistory vHistory = versionable.getVersionHistory();
Version rootVersion = vHistory.getRootVersion();
if (log.isDebugEnabled())
log.debug("rootVersion " + rootVersion.getPath());
Version baseVersion = versionable.getBaseVersion();
if (log.isDebugEnabled())
log.debug("baseVersion " + baseVersion.getPath());
BaseVersionFinder baseVersionFinder = new BaseVersionFinder(baseVersion);
List<Value> refs = traverseVersionSubTree(rootVersion, baseVersionFinder, vHistory, " --");
if (refs.size() != versionCount)
{
fail("Version history contains not all versions for node " + versionable.getPath() + ", expected:"
+ versionCount + " was:" + refs.size());
}
if (!baseVersionFinder.isBaseVersionFound())
{
fail("Base version not founded in version history tree for node " + versionable.getPath()
+ ", but exists if call versionable.getBaseVersion() " + baseVersion.getPath());
}
}
protected void showVersionable(Node versionable) throws RepositoryException
{
VersionHistory vHistory = versionable.getVersionHistory();
Version baseVersion = versionable.getBaseVersion();
BaseVersionFinder baseVersionFinder = new BaseVersionFinder(baseVersion);
String vinfo = "";
// show prececessors
try
{
Property predecessors = versionable.getProperty("jcr:predecessors");
String pstr = "";
for (Value p : predecessors.getValues())
{
pstr += "\n -- ";
Version pv = (Version)session.getNodeByUUID(p.getString());
if (baseVersionFinder.check(pv))
pstr += pv.getPath() + " >>>Base version<<< ";
else
pstr += pv.getPath();
String[] pvls = vHistory.getVersionLabels(pv);
for (String pvl : pvls)
pstr += ", " + pvl;
}
vinfo += "\n jcr:predecessors " + pstr;
}
catch (PathNotFoundException e)
{
}
// show successors
try
{
Property sucessors = versionable.getProperty("jcr:successors");
String pstr = "";
for (Value s : sucessors.getValues())
{
pstr += "\n -- ";
Version sv = (Version)session.getNodeByUUID(s.getString());
if (baseVersionFinder.check(sv))
pstr += sv.getPath() + " >>>Base version<<< ";
else
pstr += sv.getPath();
String[] svls = vHistory.getVersionLabels(sv);
for (String svl : svls)
pstr += ", " + svl;
}
vinfo += "\n jcr:successors " + pstr;
}
catch (PathNotFoundException e)
{
}
if (log.isDebugEnabled())
log.debug("versionable " + versionable.getPath() + "\n jcr:baseVersion " + baseVersion.getPath() + vinfo);
}
protected List<Value> traverseVersionSubTree(Version ver, BaseVersionFinder baseVersionFinder,
VersionHistory vHistory, String outPrefix) throws RepositoryException
{
List<Value> successorsRefs = new ArrayList<Value>();
String vlInfo = "";
String[] versionLabels = vHistory.getVersionLabels(ver);
for (String vl : versionLabels)
{
vlInfo += (vlInfo.length() > 0 ? ", " + vl : vl);
}
if (baseVersionFinder.check(ver))
{
// this is a base version
vlInfo = (vlInfo.length() > 0 ? " [" + vlInfo + "]" : "") + " >>>Base version<<< ";
}
else
{
vlInfo = (vlInfo.length() > 0 ? " [" + vlInfo + "]" : "");
}
if (log.isDebugEnabled())
log.debug(outPrefix + " " + ver.getName() + vlInfo);
Value[] versionSuccessors = getSucessors(ver);
if (versionSuccessors != null)
{
for (Value sv : versionSuccessors)
{
Version successor = (Version)session.getNodeByUUID(sv.getString());
if (successor != null)
{
successorsRefs.add(sv);
List<Value> successorSuccessors =
traverseVersionSubTree(successor, baseVersionFinder, vHistory, " " + outPrefix);
if (successorSuccessors != null)
{
successorsRefs.addAll(successorSuccessors);
}
}
else
{
fail("No item for successor UUID " + sv.getString());
}
}
}
return successorsRefs;
}
protected Value[] showSucessors(Version ver, String outPrefix) throws RepositoryException
{
String vp = (outPrefix != null ? outPrefix : " ? ");
try
{
Value[] refs = getSucessors(ver);
for (Value ref : refs)
{
if (log.isDebugEnabled())
log.debug(vp + " sucessor: " + ref.getString());
}
return refs;
}
catch (PathNotFoundException e)
{
// fail("Property jcr:successors must exists for " + vp);
return null;
}
}
protected Value[] getSucessors(Version ver) throws RepositoryException
{
try
{
Property successors = ver.getProperty("jcr:successors");
return successors.getValues();
}
catch (PathNotFoundException e)
{
// fail("Property jcr:successors must exists for " + vp);
return null;
}
}
protected void tearDown() throws Exception
{
try
{
versionableNode.checkout();
versionableNode.remove();
nonVersionableNode.remove();
root.save();
}
catch (InvalidItemStateException e)
{
log.error("Error of tear down: " + e);
}
super.tearDown();
}
}