/* * 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(); } }