mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
Work that's part of RM-2431 and RM-2432.
Added to the classified-content-model - various properties as described in RM-2431 along with a constraint on Reclassification Action. Addition to the ClassificationSchemeService of methods and types associated with Reclassification. (Upgrade, Downgrade, Declassify). See RM-2432. Behaviour bean that will automatically set lastReclassificationAction and lastReclassifyBy in response to any change to currentClassificationLevel. Also some util methods in RMCollections. Fixed some spelling mistakes in classification-related properties. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@108878 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -28,4 +28,5 @@ import java.io.Serializable;
|
||||
*/
|
||||
public interface ClassificationSchemeEntity extends Serializable
|
||||
{
|
||||
// Intentionally empty
|
||||
}
|
||||
|
@@ -19,6 +19,7 @@
|
||||
package org.alfresco.module.org_alfresco_module_rm.classification;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationException.LevelIdNotFound;
|
||||
import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationException.ReasonIdNotFound;
|
||||
@@ -78,4 +79,31 @@ public interface ClassificationSchemeService
|
||||
* @return The exemption categories in the order that they are defined.
|
||||
*/
|
||||
List<ExemptionCategory> getExemptionCategories();
|
||||
|
||||
/**
|
||||
* Identifies the reclassification type for the provided pair of {@link ClassificationLevel levels}.
|
||||
*
|
||||
* @param from the first classification level.
|
||||
* @param to the second classification level.
|
||||
* @return the reclassification represented by this change, or {@code null} if it is not a change.
|
||||
*/
|
||||
Reclassification getReclassification(ClassificationLevel from, ClassificationLevel to);
|
||||
|
||||
Set<String> getReclassificationValues();
|
||||
|
||||
/** Types of reclassification. */
|
||||
enum Reclassification
|
||||
{
|
||||
UPGRADE, DOWNGRADE, DECLASSIFY;
|
||||
|
||||
/** Returns the name of this enum value in a format suitable for storage in the Alfresco repo. */
|
||||
public String toModelString()
|
||||
{
|
||||
final String name = toString();
|
||||
final StringBuilder result = new StringBuilder(name.length());
|
||||
result.append(name.charAt(0))
|
||||
.append(name.substring(1).toLowerCase());
|
||||
return result.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -18,16 +18,21 @@
|
||||
*/
|
||||
package org.alfresco.module.org_alfresco_module_rm.classification;
|
||||
|
||||
import static java.util.Collections.unmodifiableSet;
|
||||
|
||||
import static org.alfresco.module.org_alfresco_module_rm.util.RMParameterCheck.checkNotBlank;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationException.LevelIdNotFound;
|
||||
import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationException.ReasonIdNotFound;
|
||||
import org.alfresco.module.org_alfresco_module_rm.classification.model.ClassifiedContentModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.util.ParameterCheck;
|
||||
|
||||
/**
|
||||
* @author Neil Mc Erlean
|
||||
@@ -122,4 +127,39 @@ public class ClassificationSchemeServiceImpl extends ServiceBaseImpl implements
|
||||
return (exemptionCategoryManager == null ? Collections.<ExemptionCategory>emptyList() :
|
||||
Collections.unmodifiableList(exemptionCategoryManager.getExemptionCategories()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Reclassification getReclassification(ClassificationLevel from, ClassificationLevel to)
|
||||
{
|
||||
ParameterCheck.mandatory("from", from);
|
||||
ParameterCheck.mandatory("to", to);
|
||||
|
||||
final List<ClassificationLevel> levels = getClassificationLevels();
|
||||
|
||||
final int fromIndex = levels.indexOf(from);
|
||||
final int toIndex = levels.indexOf(to);
|
||||
final int lastIndex = levels.size() - 1;
|
||||
|
||||
if (from.equals(to))
|
||||
{ return null; }
|
||||
else if (fromIndex < lastIndex && toIndex == lastIndex)
|
||||
{
|
||||
return Reclassification.DECLASSIFY;
|
||||
}
|
||||
else
|
||||
{
|
||||
return fromIndex < toIndex ? Reclassification.DOWNGRADE : Reclassification.UPGRADE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getReclassificationValues()
|
||||
{
|
||||
Set<String> result = new HashSet<>();
|
||||
for (Reclassification r : Reclassification.values())
|
||||
{
|
||||
result.add(r.toModelString());
|
||||
}
|
||||
return unmodifiableSet(result);
|
||||
}
|
||||
}
|
||||
|
@@ -44,8 +44,8 @@ import org.alfresco.service.namespace.QName;
|
||||
*
|
||||
* @author tpage
|
||||
*/
|
||||
public class ContentClassificationServiceImpl extends ServiceBaseImpl implements ContentClassificationService,
|
||||
ClassifiedContentModel
|
||||
public class ContentClassificationServiceImpl extends ServiceBaseImpl
|
||||
implements ContentClassificationService, ClassifiedContentModel
|
||||
{
|
||||
private ClassificationLevelManager levelManager;
|
||||
private ClassificationReasonManager reasonManager;
|
||||
|
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2015 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.alfresco.module.org_alfresco_module_rm.classification;
|
||||
|
||||
import static java.util.Collections.unmodifiableList;
|
||||
|
||||
import org.alfresco.module.org_alfresco_module_rm.classification.model.ClassifiedContentModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Check that a {@link ClassifiedContentModel#PROP_LAST_RECLASSIFICATION_ACTION reclassifiction action }value is valid.
|
||||
*
|
||||
* @author Neil Mc Erlean
|
||||
* @since 3.0.a
|
||||
*/
|
||||
public class ReclassificationValueConstraint extends ClassificationSchemeEntityConstraint
|
||||
{
|
||||
@Override
|
||||
protected List<String> getAllowedValues()
|
||||
{
|
||||
final Set<String> resultSet = classificationSchemeService.getReclassificationValues();
|
||||
List<String> result = new ArrayList<>(resultSet.size());
|
||||
result.addAll(resultSet);
|
||||
|
||||
return unmodifiableList(result);
|
||||
}
|
||||
}
|
@@ -54,6 +54,15 @@ public interface ClassifiedContentModel
|
||||
QName PROP_DECLASSIFICATION_EVENT = QName.createQName(CLF_URI, "declassificationEvent");
|
||||
QName PROP_DECLASSIFICATION_EXEMPTIONS = QName.createQName(CLF_URI, "declassificationExemptions");
|
||||
|
||||
QName PROP_LAST_RECLASSIFY_BY = QName.createQName(CLF_URI, "lastReclassifyBy");
|
||||
QName PROP_LAST_RECLASSIFY_AT = QName.createQName(CLF_URI, "lastReclassifyAt");
|
||||
QName PROP_LAST_RECLASSIFY_REASON = QName.createQName(CLF_URI, "lastReclassifyReason");
|
||||
QName PROP_LAST_RECLASSIFICATION_ACTION = QName.createQName(CLF_URI, "lastReclassificationAction");
|
||||
/** Reclassification allowed values. */
|
||||
String RECLASSIFICATION_UPGRADE = "UPGRADE";
|
||||
String RECLASSIFICATION_DOWNGRADE = "DOWNGRADE";
|
||||
String RECLASSIFICATION_DECLASSIFY = "DECLASSIFY";
|
||||
|
||||
/** Security Clearance aspect. */
|
||||
QName ASPECT_SECURITY_CLEARANCE = QName.createQName(CLF_URI, "securityClearance");
|
||||
QName PROP_CLEARANCE_LEVEL = QName.createQName(CLF_URI, "clearanceLevel");
|
||||
|
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2015 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
package org.alfresco.module.org_alfresco_module_rm.model.clf.aspect;
|
||||
|
||||
import static org.alfresco.module.org_alfresco_module_rm.classification.ClassificationSchemeService.Reclassification;
|
||||
import static org.alfresco.module.org_alfresco_module_rm.classification.model.ClassifiedContentModel.ASPECT_CLASSIFIED;
|
||||
import static org.alfresco.module.org_alfresco_module_rm.classification.model.ClassifiedContentModel.PROP_CURRENT_CLASSIFICATION;
|
||||
import static org.alfresco.module.org_alfresco_module_rm.classification.model.ClassifiedContentModel.PROP_LAST_RECLASSIFICATION_ACTION;
|
||||
import static org.alfresco.module.org_alfresco_module_rm.classification.model.ClassifiedContentModel.PROP_LAST_RECLASSIFY_AT;
|
||||
import static org.alfresco.module.org_alfresco_module_rm.util.RMCollectionUtils.Difference;
|
||||
import static org.alfresco.module.org_alfresco_module_rm.util.RMCollectionUtils.diffKey;
|
||||
|
||||
import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationLevel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationSchemeService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.classification.model.ClassifiedContentModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.model.BaseBehaviourBean;
|
||||
import org.alfresco.repo.node.NodeServicePolicies;
|
||||
import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
|
||||
import org.alfresco.repo.policy.annotation.Behaviour;
|
||||
import org.alfresco.repo.policy.annotation.BehaviourBean;
|
||||
import org.alfresco.repo.policy.annotation.BehaviourKind;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* clf:classification behaviour bean
|
||||
*
|
||||
* @since 3.0.a
|
||||
*/
|
||||
@BehaviourBean
|
||||
(
|
||||
defaultType = "clf:classified"
|
||||
)
|
||||
public class ClassifiedAspect extends BaseBehaviourBean
|
||||
implements NodeServicePolicies.OnUpdatePropertiesPolicy
|
||||
{
|
||||
private ClassificationSchemeService classificationSchemeService;
|
||||
|
||||
public void setClassificationSchemeService(ClassificationSchemeService service)
|
||||
{
|
||||
this.classificationSchemeService = service;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that on reclassification of content (in other words a change in the value of the
|
||||
* {@link ClassifiedContentModel#PROP_CURRENT_CLASSIFICATION clf:currentClassification} property)
|
||||
* that various metadata are correctly updated as a side-effect.
|
||||
*/
|
||||
@Override
|
||||
@Behaviour
|
||||
(
|
||||
kind = BehaviourKind.CLASS,
|
||||
notificationFrequency = NotificationFrequency.EVERY_EVENT
|
||||
)
|
||||
public void onUpdateProperties(final NodeRef nodeRef,
|
||||
final Map<QName, Serializable> before,
|
||||
final Map<QName, Serializable> after)
|
||||
{
|
||||
AuthenticationUtil.runAs(new RunAsWork<Void>()
|
||||
{
|
||||
public Void doWork()
|
||||
{
|
||||
final Difference classificationChange = diffKey(before, after, PROP_CURRENT_CLASSIFICATION);
|
||||
|
||||
if (classificationChange == Difference.CHANGED && nodeService.hasAspect(nodeRef, ASPECT_CLASSIFIED))
|
||||
{
|
||||
final String oldValue = (String)before.get(PROP_CURRENT_CLASSIFICATION);
|
||||
final String newValue = (String)after.get(PROP_CURRENT_CLASSIFICATION);
|
||||
|
||||
final ClassificationLevel oldLevel = classificationSchemeService.getClassificationLevelById(oldValue);
|
||||
final ClassificationLevel newLevel = classificationSchemeService.getClassificationLevelById(newValue);
|
||||
|
||||
Reclassification reclassification = classificationSchemeService.getReclassification(oldLevel, newLevel);
|
||||
|
||||
if (reclassification != null)
|
||||
{
|
||||
nodeService.setProperty(nodeRef, PROP_LAST_RECLASSIFICATION_ACTION, reclassification.toModelString());
|
||||
nodeService.setProperty(nodeRef, PROP_LAST_RECLASSIFY_AT, new Date());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName());
|
||||
}
|
||||
}
|
@@ -18,13 +18,17 @@
|
||||
*/
|
||||
package org.alfresco.module.org_alfresco_module_rm.util;
|
||||
|
||||
import static org.springframework.util.ObjectUtils.nullSafeEquals;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Various common helper methods for Collections.
|
||||
* Various common helper methods for Collections. This class is probably only appropriate for use with relatively
|
||||
* small collections as it has not been optimised for dealing with large collections.
|
||||
*
|
||||
* @author Neil Mc Erlean
|
||||
* @since 3.0
|
||||
@@ -58,4 +62,45 @@ public final class RMCollectionUtils
|
||||
}
|
||||
return duplicateElems;
|
||||
}
|
||||
|
||||
/**
|
||||
* This enum represents a change in an entry between 2 collections.
|
||||
*/
|
||||
public enum Difference
|
||||
{
|
||||
ADDED, REMOVED, CHANGED, UNCHANGED
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the change in a Map entry between two Maps.
|
||||
* Note that both maps must have the same types of key-value pair.
|
||||
*
|
||||
* @param from the first collection.
|
||||
* @param to the second collection.
|
||||
* @param key the key identifying the entry.
|
||||
* @param <K> the type of the key.
|
||||
* @param <V> the type of the value.
|
||||
* @return the {@link Difference}.
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code key} is {@code null}.
|
||||
*/
|
||||
public static <K, V> Difference diffKey(Map<K, V> from, Map<K, V> to, K key)
|
||||
{
|
||||
if (key == null) { throw new IllegalArgumentException("Key cannot be null."); }
|
||||
|
||||
if (from.containsKey(key))
|
||||
{
|
||||
if (to.containsKey(key))
|
||||
{
|
||||
if (nullSafeEquals(from.get(key), to.get(key))) { return Difference.UNCHANGED; }
|
||||
else { return Difference.CHANGED; }
|
||||
}
|
||||
else { return Difference.REMOVED; }
|
||||
}
|
||||
else
|
||||
{
|
||||
if (to.containsKey(key)) { return Difference.ADDED; }
|
||||
else { return Difference.UNCHANGED; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user