/*
* #%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.recordfolder;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.action.impl.CompleteEventAction;
import org.alfresco.module.org_alfresco_module_rm.action.impl.CutOffAction;
import org.alfresco.module.org_alfresco_module_rm.action.impl.DestroyAction;
import org.alfresco.module.org_alfresco_module_rm.capability.Capability;
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionAction;
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule;
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
import org.alfresco.module.org_alfresco_module_rm.test.util.CommonRMTestUtils;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.namespace.QName;
import org.springframework.extensions.webscripts.GUID;
import net.sf.acegisecurity.vote.AccessDecisionVoter;
/**
* Move record folder tests.
*
* @author Roy Wetherall
* @since 2.2
*/
public class MoveRecordFolderTest extends BaseRMTestCase
{
@Override
protected boolean isRecordTest()
{
return true;
}
/**
* Given two categories, both with cut off immediately schedules, when the record is move then all the parts of the
* record should be correct based on the new schedule.
*
* @see https://issues.alfresco.com/jira/browse/RM-1345
*/
public void testMoveRecordFolderBeforeCutOffFolderLevelDisposition() throws Exception
{
doBehaviourDrivenTest(new BehaviourDrivenTest(null, false)
{
NodeRef recordFolder;
NodeRef destinationRecordCategory;
public void given()
{
doTestInTransaction(new VoidTest()
{
public void runImpl() throws Exception
{
NodeRef rcOne = createRecordCategory(false);
destinationRecordCategory = createRecordCategory(false);
recordFolder = recordFolderService.createRecordFolder(rcOne, GUID.generate());
// check for the lifecycle aspect
assertTrue(nodeService.hasAspect(recordFolder, ASPECT_DISPOSITION_LIFECYCLE));
// check the disposition action details
DispositionAction dispositionAction = dispositionService.getNextDispositionAction(recordFolder);
assertNotNull(dispositionAction);
assertNotNull(CutOffAction.NAME, dispositionAction.getName());
assertNotNull(dispositionAction.getAsOfDate());
assertTrue(dispositionService.isNextDispositionActionEligible(recordFolder));
}
});
doTestInTransaction(new VoidTest()
{
public void runImpl() throws Exception
{
// check the search aspect properties
assertTrue(nodeService.hasAspect(recordFolder, ASPECT_RM_SEARCH));
assertEquals(CutOffAction.NAME,
nodeService.getProperty(recordFolder, PROP_RS_DISPOSITION_ACTION_NAME));
assertNotNull(nodeService.getProperty(recordFolder, PROP_RS_DISPOSITION_ACTION_AS_OF));
}
});
}
public void when() throws Exception
{
doTestInTransaction(new VoidTest()
{
public void runImpl() throws Exception
{
// move record folder
fileFolderService.move(recordFolder, destinationRecordCategory, GUID.generate());
}
});
}
public void then()
{
doTestInTransaction(new VoidTest()
{
public void runImpl() throws Exception
{
// check for the lifecycle aspect
assertTrue(nodeService.hasAspect(recordFolder, ASPECT_DISPOSITION_LIFECYCLE));
// check the disposition action details
DispositionAction dispositionAction = dispositionService.getNextDispositionAction(recordFolder);
assertNotNull(dispositionAction);
assertNotNull(CutOffAction.NAME, dispositionAction.getName());
assertNotNull(dispositionAction.getAsOfDate());
assertTrue(dispositionService.isNextDispositionActionEligible(recordFolder));
// check the search aspect properties
assertTrue(nodeService.hasAspect(recordFolder, ASPECT_RM_SEARCH));
assertEquals(CutOffAction.NAME,
nodeService.getProperty(recordFolder, PROP_RS_DISPOSITION_ACTION_NAME));
assertNotNull(nodeService.getProperty(recordFolder, PROP_RS_DISPOSITION_ACTION_AS_OF));
}
});
}
});
}
/**
*
*/
public void testMoveRecordFolderBeforeCutOffIntoAFolderWithNoDisposition() throws Exception
{
doBehaviourDrivenTest(new BehaviourDrivenTest(null, false)
{
NodeRef recordFolder;
NodeRef destinationRecordCategory;
public void given()
{
doTestInTransaction(new VoidTest()
{
public void runImpl() throws Exception
{
NodeRef rcOne = createRecordCategory(false);
destinationRecordCategory = filePlanService.createRecordCategory(filePlan, GUID.generate());
recordFolder = recordFolderService.createRecordFolder(rcOne, GUID.generate());
// check for the lifecycle aspect
assertTrue(nodeService.hasAspect(recordFolder, ASPECT_DISPOSITION_LIFECYCLE));
// check the disposition action details
DispositionAction dispositionAction = dispositionService.getNextDispositionAction(recordFolder);
assertNotNull(dispositionAction);
assertNotNull(CutOffAction.NAME, dispositionAction.getName());
assertNotNull(dispositionAction.getAsOfDate());
assertTrue(dispositionService.isNextDispositionActionEligible(recordFolder));
}
});
doTestInTransaction(new VoidTest()
{
public void runImpl() throws Exception
{
// check the search aspect properties
assertTrue(nodeService.hasAspect(recordFolder, ASPECT_RM_SEARCH));
assertEquals(CutOffAction.NAME,
nodeService.getProperty(recordFolder, PROP_RS_DISPOSITION_ACTION_NAME));
assertNotNull(nodeService.getProperty(recordFolder, PROP_RS_DISPOSITION_ACTION_AS_OF));
}
});
}
public void when() throws Exception
{
doTestInTransaction(new VoidTest()
{
public void runImpl() throws Exception
{
// move record folder
fileFolderService.move(recordFolder, destinationRecordCategory, GUID.generate());
}
});
}
public void then()
{
doTestInTransaction(new VoidTest()
{
public void runImpl() throws Exception
{
// check for the lifecycle aspect
assertFalse(nodeService.hasAspect(recordFolder, ASPECT_DISPOSITION_LIFECYCLE));
// check the disposition action details
assertNull(dispositionService.getNextDispositionAction(recordFolder));
// check the search aspect properties
assertFalse(nodeService.hasAspect(recordFolder, ASPECT_RM_SEARCH));
}
});
}
});
}
/**
*
*/
public void testMoveRecordFolderWithRecordsBeforeCutOffRecordLevelDisposition() throws Exception
{
doBehaviourDrivenTest(new BehaviourDrivenTest(null, false)
{
NodeRef record;
NodeRef recordFolder;
NodeRef destinationRecordCategory;
public void given()
{
doTestInTransaction(new VoidTest()
{
public void runImpl() throws Exception
{
NodeRef rcOne = createRecordCategory(true);
destinationRecordCategory = createRecordCategory(true);
recordFolder = recordFolderService.createRecordFolder(rcOne, GUID.generate());
record = utils.createRecord(recordFolder, GUID.generate());
// check for the lifecycle aspect
assertFalse(nodeService.hasAspect(recordFolder, ASPECT_DISPOSITION_LIFECYCLE));
assertTrue(nodeService.hasAspect(record, ASPECT_DISPOSITION_LIFECYCLE));
// check the disposition action details
assertNull(dispositionService.getNextDispositionAction(recordFolder));
DispositionAction dispositionAction = dispositionService.getNextDispositionAction(record);
assertNotNull(dispositionAction);
assertNotNull(CutOffAction.NAME, dispositionAction.getName());
assertNotNull(dispositionAction.getAsOfDate());
assertTrue(dispositionService.isNextDispositionActionEligible(record));
}
});
doTestInTransaction(new VoidTest()
{
public void runImpl() throws Exception
{
// check the search aspect properties
assertTrue(nodeService.hasAspect(record, ASPECT_RM_SEARCH));
assertEquals(CutOffAction.NAME,
nodeService.getProperty(record, PROP_RS_DISPOSITION_ACTION_NAME));
assertNotNull(nodeService.getProperty(record, PROP_RS_DISPOSITION_ACTION_AS_OF));
}
});
}
public void when() throws Exception
{
doTestInTransaction(new VoidTest()
{
public void runImpl() throws Exception
{
// move record folder
fileFolderService.move(recordFolder, destinationRecordCategory, GUID.generate());
}
});
}
public void then()
{
doTestInTransaction(new VoidTest()
{
public void runImpl() throws Exception
{
// check for the lifecycle aspect
assertFalse(nodeService.hasAspect(recordFolder, ASPECT_DISPOSITION_LIFECYCLE));
assertTrue(nodeService.hasAspect(record, ASPECT_DISPOSITION_LIFECYCLE));
// check the disposition action details
assertNull(dispositionService.getNextDispositionAction(recordFolder));
DispositionAction dispositionAction = dispositionService.getNextDispositionAction(record);
assertNotNull(dispositionAction);
assertNotNull(CutOffAction.NAME, dispositionAction.getName());
assertNotNull(dispositionAction.getAsOfDate());
assertTrue(dispositionService.isNextDispositionActionEligible(record));
// check the search aspect properties
assertTrue(nodeService.hasAspect(record, ASPECT_RM_SEARCH));
assertEquals(CutOffAction.NAME,
nodeService.getProperty(record, PROP_RS_DISPOSITION_ACTION_NAME));
assertNotNull(nodeService.getProperty(record, PROP_RS_DISPOSITION_ACTION_AS_OF));
}
});
}
});
}
/**
* Try and move a folder from no disposition schedule to a disposition schedule
*
* @see https://issues.alfresco.com/jira/browse/RM-1039
*/
public void testMoveRecordFolderFromNoDisToDis() throws Exception
{
final NodeRef recordFolder = doTestInTransaction(new Test<NodeRef>()
{
@Override
public NodeRef run()
{
// create a record category (no disposition schedule)
NodeRef recordCategory = filePlanService.createRecordCategory(filePlan, "Caitlin Reed");
// create a record folder
return recordFolderService.createRecordFolder(recordCategory, "Grace Wetherall");
}
@Override
public void test(NodeRef result) throws Exception
{
assertNotNull(result);
assertNull(dispositionService.getDispositionSchedule(result));
assertFalse(nodeService.hasAspect(result, ASPECT_DISPOSITION_LIFECYCLE));
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(result, FILING));
}
});
final NodeRef record = doTestInTransaction(new Test<NodeRef>()
{
@Override
public NodeRef run()
{
// create a record
return fileFolderService.create(recordFolder, "mytest.txt", ContentModel.TYPE_CONTENT).getNodeRef();
}
@Override
public void test(NodeRef result) throws Exception
{
assertNotNull(result);
assertNull(dispositionService.getDispositionSchedule(result));
assertFalse(nodeService.hasAspect(result, ASPECT_DISPOSITION_LIFECYCLE));
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(result, FILING));
}
});
doTestInTransaction(new Test<NodeRef>()
{
@Override
public NodeRef run() throws Exception
{
Capability capability = capabilityService.getCapability("CreateModifyDestroyFolders");
assertEquals(AccessDecisionVoter.ACCESS_GRANTED, capability.evaluate(recordFolder));
assertEquals(AccessDecisionVoter.ACCESS_GRANTED, capability.evaluate(recordFolder, rmContainer));
// take a look at the move capability
Capability moveCapability = capabilityService.getCapability("Move");
assertEquals(AccessDecisionVoter.ACCESS_GRANTED, moveCapability.evaluate(recordFolder, rmContainer));
// move the node
return fileFolderService.move(recordFolder, rmContainer, null).getNodeRef();
}
@Override
public void test(NodeRef result) throws Exception
{
assertNotNull(result);
assertNotNull(dispositionService.getDispositionSchedule(result));
assertTrue(nodeService.hasAspect(result, ASPECT_DISPOSITION_LIFECYCLE));
DispositionAction dispositionAction = dispositionService.getNextDispositionAction(result);
assertNotNull(dispositionAction);
assertNull(dispositionAction.getAsOfDate());
assertEquals("cutoff", dispositionAction.getName());
assertEquals(1, dispositionAction.getEventCompletionDetails().size());
// take a look at the record and check things are as we would expect
assertFalse(nodeService.hasAspect(record, ASPECT_DISPOSITION_LIFECYCLE));
}
});
}
/**
* Try and move a cutoff folder
*
* @see https://issues.alfresco.com/jira/browse/RM-1039
*/
public void testMoveCutoffRecordFolder() throws Exception
{
final NodeRef destination = doTestInTransaction(new Test<NodeRef>()
{
@Override
public NodeRef run()
{
// create a record category (no disposition schedule)
return filePlanService.createRecordCategory(filePlan, "Caitlin Reed");
}
});
final NodeRef testFolder = doTestInTransaction(new Test<NodeRef>()
{
@Override
public NodeRef run()
{
// create folder
NodeRef testFolder = recordFolderService.createRecordFolder(rmContainer, "Peter Edward Francis");
// complete event
Map<String, Serializable> params = new HashMap<String, Serializable>(1);
params.put(CompleteEventAction.PARAM_EVENT_NAME, CommonRMTestUtils.DEFAULT_EVENT_NAME);
rmActionService.executeRecordsManagementAction(testFolder, CompleteEventAction.NAME, params);
// cutoff folder
rmActionService.executeRecordsManagementAction(testFolder, CutOffAction.NAME);
return testFolder;
}
@Override
public void test(NodeRef testFolder) throws Exception
{
// take a look at the move capability
Capability moveCapability = capabilityService.getCapability("MoveRecordFolder");
assertEquals(AccessDecisionVoter.ACCESS_DENIED, moveCapability.evaluate(testFolder, destination));
}
});
doTestInTransaction(new FailureTest()
{
@Override
public void run() throws Exception
{
fileFolderService.move(testFolder, destination, null).getNodeRef();
}
});
}
// try and move a destroyed folder
public void testMoveDestroyedRecordFolder() throws Exception
{
final NodeRef destination = doTestInTransaction(new Test<NodeRef>()
{
@Override
public NodeRef run()
{
// create a record category (no disposition schedule)
return filePlanService.createRecordCategory(filePlan, "Caitlin Reed");
}
});
final NodeRef testFolder = doTestInTransaction(new Test<NodeRef>()
{
@Override
public NodeRef run()
{
// create folder
NodeRef testFolder = recordFolderService.createRecordFolder(rmContainer, "Peter Edward Francis");
// complete event
Map<String, Serializable> params = new HashMap<String, Serializable>(1);
params.put(CompleteEventAction.PARAM_EVENT_NAME, CommonRMTestUtils.DEFAULT_EVENT_NAME);
rmActionService.executeRecordsManagementAction(testFolder, CompleteEventAction.NAME, params);
// cutoff & destroy folder
rmActionService.executeRecordsManagementAction(testFolder, CutOffAction.NAME);
rmActionService.executeRecordsManagementAction(testFolder, DestroyAction.NAME);
return testFolder;
}
});
doTestInTransaction(new Test<NodeRef>()
{
@Override
public NodeRef run() throws Exception
{
Capability moveCapability = capabilityService.getCapability("MoveRecordFolder");
assertEquals(AccessDecisionVoter.ACCESS_GRANTED, moveCapability.evaluate(testFolder, destination));
return fileFolderService.move(testFolder, destination, null).getNodeRef();
}
@Override
public void test(NodeRef result) throws Exception
{
assertNotNull(result);
}
});
}
private NodeRef createRecordCategory(boolean recordLevel)
{
NodeRef rc = filePlanService.createRecordCategory(filePlan, GUID.generate());
DispositionSchedule dis = utils.createBasicDispositionSchedule(rc, GUID.generate(), GUID.generate(),
recordLevel, false);
Map<QName, Serializable> adParams = new HashMap<QName, Serializable>(3);
adParams.put(PROP_DISPOSITION_ACTION_NAME, CutOffAction.NAME);
adParams.put(PROP_DISPOSITION_DESCRIPTION, GUID.generate());
adParams.put(PROP_DISPOSITION_PERIOD, CommonRMTestUtils.PERIOD_IMMEDIATELY);
dispositionService.addDispositionActionDefinition(dis, adParams);
return rc;
}
}