/*
* #%L
* Alfresco Records Management Module
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
* -
* Alfresco 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 3 of the License, or
* (at your option) any later version.
* -
* Alfresco 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.module.org_alfresco_module_rm.test.integration.version;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.relationship.Relationship;
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionModel;
import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionPolicy;
import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionService;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionHistory;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.GUID;
import org.alfresco.util.PropertyMap;
/**
* Recordable versions base integration test
*
* @author Roy Wetherall
* @since 2.3
*/
public abstract class RecordableVersionsBaseTest extends BaseRMTestCase implements RecordableVersionModel
{
protected static final QName QNAME_PUBLISHER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "publisher");
protected static final QName QNAME_SUBJECT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "subject");
protected static final String DESCRIPTION = "description";
protected static final String PUBLISHER = "publisher";
protected static final String SUBJECT = "subject";
protected static final String OWNER = "GracieWetherall";
protected static final String CONTENT =
"Simple + Smart. A smarter way to build, a smarter way to deploy. Its simple because we focus on the end "
+ "user and smart because we support more open standards than any other ECM platform, while delivering all "
+ "the value a traditional platform provides.";
protected RecordableVersionService recordableVersionService;
@Override
protected void initServices()
{
super.initServices();
recordableVersionService = (RecordableVersionService)applicationContext.getBean("RecordableVersionService");
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase#isCollaborationSiteTest()
*/
@Override
protected boolean isCollaborationSiteTest()
{
return true;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase#setupCollaborationSiteTestDataImpl()
*/
@Override
protected void setupCollaborationSiteTestDataImpl()
{
super.setupCollaborationSiteTestDataImpl();
// create authentication for owner
createPerson(OWNER);
// prepare content
prepareContent(dmDocument);
}
protected void prepareContent(NodeRef content)
{
// add titled aspect
PropertyMap titledProperties = new PropertyMap(2);
titledProperties.put(ContentModel.PROP_TITLE, "document title");
titledProperties.put(ContentModel.PROP_DESCRIPTION, "document description");
nodeService.addAspect(content, ContentModel.ASPECT_TITLED, titledProperties);
// add ownable aspect
PropertyMap ownableProperties = new PropertyMap(1);
ownableProperties.put(ContentModel.PROP_OWNER, OWNER);
nodeService.addAspect(content, ContentModel.ASPECT_OWNABLE, ownableProperties);
// add Dublin core aspect
PropertyMap dublinCoreProperties = new PropertyMap(2);
dublinCoreProperties.put(QNAME_PUBLISHER, PUBLISHER);
dublinCoreProperties.put(QNAME_SUBJECT, SUBJECT);
nodeService.addAspect(content, ContentModel.ASPECT_DUBLINCORE, dublinCoreProperties);
// add content
ContentWriter writer = contentService.getWriter(content, ContentModel.PROP_CONTENT, true);
writer.setEncoding("UTF-8");
writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
writer.putContent(CONTENT);
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase#tearDownImpl()
*/
@Override
protected void tearDownImpl()
{
super.tearDownImpl();
// remove owner
personService.deletePerson(OWNER);
}
/**
* Helper to check that the current version is recorded
*/
protected void checkRecordedVersion(NodeRef document, String description, String versionLabel)
{
// double check that the document is not a record
assertFalse(recordService.isRecord(document));
// store document state
Map<QName, Serializable> beforeProperties = nodeService.getProperties(document);
Set<QName> beforeAspects = nodeService.getAspects(document);
// get the current version
Version version = versionService.getCurrentVersion(document);
// version has been created
assertNotNull(version);
// check the version properties
assertEquals(description, version.getDescription());
assertEquals(versionLabel, version.getVersionLabel());
// get the frozen state
NodeRef frozen = version.getFrozenStateNodeRef();
// check the properties
checkProperties(frozen, beforeProperties);
// compare aspects
checkAspects(frozen, beforeAspects);
// record version node reference is available on version
NodeRef record = recordableVersionService.getVersionRecord(version);
assertNotNull(record);
// check that the version record information has been added
assertTrue(nodeService.hasAspect(record, ASPECT_VERSION_RECORD));
assertEquals(versionLabel, nodeService.getProperty(record, RecordableVersionModel.PROP_VERSION_LABEL));
assertEquals(description, nodeService.getProperty(record, RecordableVersionModel.PROP_VERSION_DESCRIPTION));
// record version is an unfiled record
assertTrue(recordService.isRecord(record));
assertFalse(recordService.isFiled(record));
// check that the created record does not have either of the versionable aspects
assertFalse(nodeService.hasAspect(record, RecordableVersionModel.ASPECT_VERSIONABLE));
// check the version history
VersionHistory versionHistory = versionService.getVersionHistory(document);
assertNotNull(versionHistory);
Version headVersion = versionHistory.getHeadVersion();
assertNotNull(headVersion);
}
/**
* Helper method to check that the current version is not recorded
*/
protected void checkNotRecordedAspect(NodeRef document, String description, String versionLabel)
{
// double check that the document is not a record
assertFalse(recordService.isRecord(document));
// get the current version
Version version = versionService.getCurrentVersion(document);
// version has been created
assertNotNull(version);
// check the version properties
assertEquals(description, version.getDescription());
assertEquals(versionLabel, version.getVersionLabel());
// record version node reference is available on version
NodeRef record = recordableVersionService.getVersionRecord(version);
assertNull(record);
// check the version history
VersionHistory versionHistory = versionService.getVersionHistory(document);
assertNotNull(versionHistory);
Version headVersion = versionHistory.getHeadVersion();
assertNotNull(headVersion);
}
/**
* Helper to check the properties of a recorded version
*/
protected void checkProperties(NodeRef frozen, Map<QName, Serializable> beforeProperies)
{
Map<QName, Serializable> frozenProperties = nodeService.getProperties(frozen);
Map<QName, Serializable> cloneFrozenProperties = new HashMap<QName, Serializable>(frozenProperties);
for (Map.Entry<QName, Serializable> entry : beforeProperies.entrySet())
{
QName beforePropertyName = entry.getKey();
if (frozenProperties.containsKey(beforePropertyName))
{
Serializable frozenValue = frozenProperties.get(beforePropertyName);
assertEquals("Frozen property " + beforePropertyName.getLocalName() + " value is incorrect.", entry.getValue(), frozenValue);
cloneFrozenProperties.remove(beforePropertyName);
}
else if (!PROP_FILE_PLAN.equals(beforePropertyName) &&
!PROP_RECORDABLE_VERSION_POLICY.equals(beforePropertyName) &&
!ContentModel.PROP_AUTO_VERSION_PROPS.equals(beforePropertyName) &&
!ContentModel.PROP_AUTO_VERSION.equals(beforePropertyName) &&
!ContentModel.PROP_INITIAL_VERSION.equals(beforePropertyName) &&
!ContentModel.PROP_VERSION_TYPE.equals(beforePropertyName) &&
!ContentModel.PROP_VERSION_LABEL.equals(beforePropertyName))
{
fail("Property missing from frozen state .. " + beforePropertyName);
}
}
// filter out missing properties with null values
for (Map.Entry<QName, Serializable> entry : frozenProperties.entrySet())
{
if (entry.getValue() == null)
{
cloneFrozenProperties.remove(entry.getKey());
}
}
// remove "owner" from cloneFrozenProperties
cloneFrozenProperties.remove(ContentModel.PROP_OWNER);
// frozen properties should be empty
assertTrue("Properties in frozen state, but not in origional. " + cloneFrozenProperties.keySet(), cloneFrozenProperties.isEmpty());
}
/**
* Helper to check the aspects of a recorded version
*/
protected void checkAspects(NodeRef frozen, Set<QName> beforeAspects)
{
Set<QName> cloneBeforeAspects = new HashSet<QName>(beforeAspects);
// compare origional and frozen aspects
Set<QName> frozenAspects = nodeService.getAspects(frozen);
cloneBeforeAspects.removeAll(frozenAspects);
cloneBeforeAspects.remove(RecordableVersionModel.ASPECT_VERSIONABLE);
cloneBeforeAspects.remove(ContentModel.ASPECT_VERSIONABLE);
if (!cloneBeforeAspects.isEmpty())
{
fail("Aspects not present in frozen state. " + cloneBeforeAspects.toString());
}
frozenAspects.removeAll(beforeAspects);
if (!frozenAspects.isEmpty())
{
fail("Aspects in the frozen state, but not in origional. " + frozenAspects.toString());
}
}
/**
* Creates a document with three versions (1.0, 1.1, 1.2) all of which
* are recorded.
*
* @return NodeRef node reference
*/
protected NodeRef createDocumentWithRecordVersions()
{
// create document and initial version (1.0)
final NodeRef myDocument = doTestInTransaction(new Test<NodeRef>()
{
@Override
public NodeRef run() throws Exception
{
// create a document
NodeRef testDoc = fileFolderService.create(dmFolder, GUID.generate(), ContentModel.TYPE_CONTENT).getNodeRef();
ContentWriter writer = fileFolderService.getWriter(testDoc);
writer.setEncoding("UTF-8");
writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
writer.putContent(GUID.generate());
// make versionable
Map<QName, Serializable> props = new HashMap<QName, Serializable>(2);
props.put(RecordableVersionModel.PROP_RECORDABLE_VERSION_POLICY, RecordableVersionPolicy.ALL);
props.put(RecordableVersionModel.PROP_FILE_PLAN, filePlan);
nodeService.addAspect(testDoc, RecordableVersionModel.ASPECT_VERSIONABLE, props);
nodeService.addAspect(testDoc, ContentModel.ASPECT_VERSIONABLE, null);
return testDoc;
}
});
// create 1.1
doTestInTransaction(new Test<Void>()
{
@Override
public Void run() throws Exception
{
// update content
ContentWriter writer = fileFolderService.getWriter(myDocument);
writer.putContent(GUID.generate());
return null;
}
});
// create 1.2
doTestInTransaction(new Test<Void>()
{
@Override
public Void run() throws Exception
{
// update content
ContentWriter writer = fileFolderService.getWriter(myDocument);
writer.putContent(GUID.generate());
return null;
}
});
// we do these checks to ensure that the test data is in the correct state before we
// start to manipulate the versions and execute tests
doTestInTransaction(new Test<Void>()
{
@Override
public Void run() throws Exception
{
// verify that the version history looks as expected
VersionHistory versionHistory = versionService.getVersionHistory(myDocument);
assertNotNull(versionHistory);
Collection<Version> versions = versionHistory.getAllVersions();
assertEquals(3, versions.size());
// verify 1.2 setup as expected
Version version12 = versionHistory.getHeadVersion();
assertEquals("1.2", version12.getVersionLabel());
NodeRef recordVersion12 = recordableVersionService.getVersionRecord(version12);
assertNotNull(recordVersion12);
assertTrue(relationshipService.getRelationshipsTo(recordVersion12, "versions").isEmpty());
Set<Relationship> from12 = relationshipService.getRelationshipsFrom(recordVersion12, "versions");
assertEquals(1, from12.size());
// verify 1.1 setup as expected
Version version11 = versionHistory.getPredecessor(version12);
assertEquals("1.1", version11.getVersionLabel());
NodeRef recordVersion11 = recordableVersionService.getVersionRecord(version11);
assertNotNull(recordVersion11);
Set<Relationship> to11 = relationshipService.getRelationshipsTo(recordVersion11, "versions");
assertEquals(1, to11.size());
assertEquals(recordVersion12, to11.iterator().next().getSource());
Set<Relationship> from11 = relationshipService.getRelationshipsFrom(recordVersion11, "versions");
assertEquals(1, from11.size());
// verify 1.0 setup as expected
Version version10 = versionHistory.getPredecessor(version11);
assertEquals("1.0", version10.getVersionLabel());
NodeRef recordVersion10 = recordableVersionService.getVersionRecord(version10);
assertNotNull(recordVersion10);
Set<Relationship> to10 = relationshipService.getRelationshipsTo(recordVersion10, "versions");
assertEquals(1, to10.size());
assertEquals(recordVersion11, to10.iterator().next().getSource());
assertTrue(relationshipService.getRelationshipsFrom(recordVersion10, "versions").isEmpty());
return null;
}
});
return myDocument;
}
}