/*
* #%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.disposition;
import static org.alfresco.module.org_alfresco_module_rm.test.util.bdt.BehaviourTest.test;
import java.io.Serializable;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import com.google.common.collect.ImmutableMap;
import org.alfresco.model.ContentModel;
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.disposition.DispositionActionDefinition;
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule;
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService;
import org.alfresco.module.org_alfresco_module_rm.job.publish.DispositionActionDefinitionPublishExecutor;
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.module.org_alfresco_module_rm.test.util.bdt.BehaviourTest;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.ApplicationContextHelper;
import org.springframework.extensions.webscripts.GUID;
/**
* Integration tests for updating the disposition schedule.
*
* @author Tom Page
* @since 2.3.1
*/
public class UpdateDispositionScheduleTest extends BaseRMTestCase
{
/** A unique prefix for the constants in this test. */
protected static final String TEST_PREFIX = UpdateDispositionScheduleTest.class.getName() + GUID.generate() + "_";
/** The name to use for the category. */
protected static final String CATEGORY_NAME = TEST_PREFIX + "Category";
/** The name to use for the folder. */
protected static final String FOLDER_NAME = TEST_PREFIX + "Folder";
/** The name to use for the record. */
protected static final String RECORD_NAME = TEST_PREFIX + "Record";
/** The executor for the disposition update job. */
private DispositionActionDefinitionPublishExecutor dispositionActionDefinitionPublishExecutor;
/** The internal disposition service is used to avoid permissions issues when updating the record. */
private DispositionService internalDispositionService;
/** The category node. */
private NodeRef category;
/** The folder node. */
private NodeRef folder;
/** The record node. */
private NodeRef record;
/** The 'disposition as of' date from before the 'when' step. */
private Date originalAsOfDate;
@Override
protected void setUp() throws Exception
{
super.setUp();
BehaviourTest.initBehaviourTests(retryingTransactionHelper);
// Get the application context
applicationContext = ApplicationContextHelper.getApplicationContext(getConfigLocations());
dispositionActionDefinitionPublishExecutor = applicationContext.getBean(DispositionActionDefinitionPublishExecutor.class);
internalDispositionService = (DispositionService) applicationContext.getBean("dispositionService");
}
/**
* <a href="https://issues.alfresco.com/jira/browse/RM-3386">RM-3386</a>
* <p><pre>
* Given a record subject to a disposition schedule
* And the next step is due to run at some period after the date the content was created
* When I update the period of the next step (and wait for this to be processed)
* Then the "as of" date is updated to be at the new period after the creation date.
* </pre>
*/
public void testUpdatePeriod()
{
test()
.given(() -> {
// Create a category.
category = filePlanService.createRecordCategory(filePlan, CATEGORY_NAME);
// Create a disposition schedule for the category (Cut off immediately, then Destroy 1 year after the creation date).
DispositionSchedule dispSched = utils.createBasicDispositionSchedule(category, "instructions", "authority", true, false);
Map<QName, Serializable> cutOffParams = ImmutableMap.of(PROP_DISPOSITION_ACTION_NAME, CutOffAction.NAME,
PROP_DISPOSITION_DESCRIPTION, "description",
PROP_DISPOSITION_PERIOD, CommonRMTestUtils.PERIOD_IMMEDIATELY);
dispositionService.addDispositionActionDefinition(dispSched, cutOffParams);
Map<QName, Serializable> destroyParams = ImmutableMap.of(PROP_DISPOSITION_ACTION_NAME, DestroyAction.NAME,
PROP_DISPOSITION_DESCRIPTION, "description",
PROP_DISPOSITION_PERIOD, CommonRMTestUtils.PERIOD_ONE_YEAR,
PROP_DISPOSITION_PERIOD_PROPERTY, ContentModel.PROP_CREATED);
dispositionService.addDispositionActionDefinition(dispSched, destroyParams);
// Create a folder containing a record within the category.
folder = recordFolderService.createRecordFolder(category, FOLDER_NAME);
record = fileFolderService.create(folder, RECORD_NAME, ContentModel.TYPE_CONTENT).getNodeRef();
dispositionService.cutoffDisposableItem(record);
// Ensure the update has been applied to the record.
internalDispositionService.updateNextDispositionAction(record);
originalAsOfDate = dispositionService.getNextDispositionAction(record).getAsOfDate();
})
.when(() -> {
// Update the Destroy step to be 3 years after the creation date.
DispositionSchedule dispSched = dispositionService.getDispositionSchedule(category);
DispositionActionDefinition destroy = dispSched.getDispositionActionDefinitionByName(DestroyAction.NAME);
Map<QName, Serializable> destroyParams = ImmutableMap.of(PROP_DISPOSITION_ACTION_NAME, DestroyAction.NAME,
PROP_DISPOSITION_DESCRIPTION, "description",
PROP_DISPOSITION_PERIOD, CommonRMTestUtils.PERIOD_THREE_YEARS,
PROP_DISPOSITION_PERIOD_PROPERTY, ContentModel.PROP_CREATED);
dispositionService.updateDispositionActionDefinition(destroy, destroyParams);
// Make the disposition action definition update job run.
dispositionActionDefinitionPublishExecutor.publish(destroy.getNodeRef());
})
.then()
.expect(true)
.from(() -> aboutTwoYearsApart(originalAsOfDate, dispositionService.getNextDispositionAction(record).getAsOfDate()))
.because("Increasing the destroy period by two years should increase the 'as of' date by two years.");
}
/**
* Check that the two given dates are approximately two years apart.
* <p>
* This actually just checks that they're more than one and less than three years apart, because leap years make
* things hard to calculate.
*
* @return true if the two dates are about two years apart.
*/
private boolean aboutTwoYearsApart(Date start, Date end)
{
long days = daysBetween(start, end);
long yearInDays = 365;
return (yearInDays < days) && (days < 3 * yearInDays);
}
/** Find the number of days between the two dates. */
private long daysBetween(Date start, Date end)
{
return TimeUnit.MILLISECONDS.toDays(end.getTime() - start.getTime());
}
}