mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
RM-1144, Path substitution suggestion functionality
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@62684 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -571,6 +571,9 @@
|
|||||||
class="org.alfresco.repo.web.scripts.substitutionsuggestions.RmSubstitutionSuggestionsGet"
|
class="org.alfresco.repo.web.scripts.substitutionsuggestions.RmSubstitutionSuggestionsGet"
|
||||||
parent="webscript">
|
parent="webscript">
|
||||||
<property name="parameterProcessorComponent" ref="parameterProcessorComponent"/>
|
<property name="parameterProcessorComponent" ref="parameterProcessorComponent"/>
|
||||||
|
<property name="nodeService" ref="NodeService"/>
|
||||||
|
<property name="filePlanService" ref="FilePlanService" />
|
||||||
|
<property name="capabilityService" ref="CapabilityService" />
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
@@ -1,7 +1,7 @@
|
|||||||
<webscript>
|
<webscript>
|
||||||
<shortname>Get substitution suggestions for RM</shortname>
|
<shortname>Get substitution suggestions for RM</shortname>
|
||||||
<description>Gets a collection of substitution suggestions for a text fragment for RM.</description>
|
<description>Gets a collection of substitution suggestions for a text fragment for RM.</description>
|
||||||
<url>/api/rm/rm-substitutionsuggestions?fragment={fragment?}</url>
|
<url>/api/rm/rm-substitutionsuggestions?fragment={fragment}&path={path?}</url>
|
||||||
<format default="json">argument</format>
|
<format default="json">argument</format>
|
||||||
<authentication>user</authentication>
|
<authentication>user</authentication>
|
||||||
<transaction allow="readonly">required</transaction>
|
<transaction allow="readonly">required</transaction>
|
||||||
|
@@ -23,7 +23,18 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.capability.Capability;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
|
||||||
import org.alfresco.repo.action.parameter.ParameterProcessorComponent;
|
import org.alfresco.repo.action.parameter.ParameterProcessorComponent;
|
||||||
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
|
import org.alfresco.service.cmr.repository.StoreRef;
|
||||||
|
import org.alfresco.service.cmr.security.AccessStatus;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.apache.cxf.common.util.StringUtils;
|
||||||
import org.springframework.extensions.webscripts.Cache;
|
import org.springframework.extensions.webscripts.Cache;
|
||||||
import org.springframework.extensions.webscripts.DeclarativeWebScript;
|
import org.springframework.extensions.webscripts.DeclarativeWebScript;
|
||||||
import org.springframework.extensions.webscripts.Status;
|
import org.springframework.extensions.webscripts.Status;
|
||||||
@@ -43,14 +54,59 @@ public class RmSubstitutionSuggestionsGet extends DeclarativeWebScript
|
|||||||
|
|
||||||
private final static String SUBSTITUTIONS_MODEL_KEY = "substitutions";
|
private final static String SUBSTITUTIONS_MODEL_KEY = "substitutions";
|
||||||
|
|
||||||
private ParameterProcessorComponent parameterProcessorComponent;
|
private final static String RECORD_FOLDER_TYPE = "recordFolder";
|
||||||
|
private final static String RECORD_CATEGORY_TYPE = "recordCategory";
|
||||||
|
|
||||||
|
private final static String CREATE_CAPABILITY = "Create";
|
||||||
|
private final static String VIEW_CAPABILITY = "ViewRecords";
|
||||||
|
|
||||||
|
private final static int PATH_SUBSTITUTION_MINIMUM_FRAGMENT_LENGTH = 0;
|
||||||
|
private final static int PATH_SUBSTITUTION_MAXIMUM_NUMBER_RESULTS = 10;
|
||||||
|
|
||||||
|
private ParameterProcessorComponent parameterProcessorComponent;
|
||||||
|
private NodeService nodeService;
|
||||||
|
private FilePlanService filePlanService;
|
||||||
|
private CapabilityService capabilityService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the parameter processor component bean
|
||||||
|
*
|
||||||
|
* @param parameterProcessorComponent
|
||||||
|
*/
|
||||||
public void setParameterProcessorComponent(ParameterProcessorComponent parameterProcessorComponent)
|
public void setParameterProcessorComponent(ParameterProcessorComponent parameterProcessorComponent)
|
||||||
{
|
{
|
||||||
this.parameterProcessorComponent = parameterProcessorComponent;
|
this.parameterProcessorComponent = parameterProcessorComponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Set the parameter processor component bean
|
||||||
|
*
|
||||||
|
* @param parameterProcessorComponent
|
||||||
|
*/
|
||||||
|
public void setNodeService(NodeService nodeService)
|
||||||
|
{
|
||||||
|
this.nodeService = nodeService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param filePlanService file plan service
|
||||||
|
*/
|
||||||
|
public void setFilePlanService(FilePlanService filePlanService)
|
||||||
|
{
|
||||||
|
this.filePlanService = filePlanService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param filePlanService file plan service
|
||||||
|
*/
|
||||||
|
public void setCapabilityService(CapabilityService capabilityService)
|
||||||
|
{
|
||||||
|
this.capabilityService = capabilityService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a list of substitutions for the given fragment.
|
||||||
|
*
|
||||||
* @see org.springframework.extensions.webscripts.DeclarativeWebScript#executeImpl(org.springframework.extensions.webscripts.WebScriptRequest,
|
* @see org.springframework.extensions.webscripts.DeclarativeWebScript#executeImpl(org.springframework.extensions.webscripts.WebScriptRequest,
|
||||||
* org.springframework.extensions.webscripts.Status,
|
* org.springframework.extensions.webscripts.Status,
|
||||||
* org.springframework.extensions.webscripts.Cache)
|
* org.springframework.extensions.webscripts.Cache)
|
||||||
@@ -63,7 +119,7 @@ public class RmSubstitutionSuggestionsGet extends DeclarativeWebScript
|
|||||||
|
|
||||||
List<String> substitutionSuggestions = new ArrayList<String>();
|
List<String> substitutionSuggestions = new ArrayList<String>();
|
||||||
|
|
||||||
substitutionSuggestions.addAll(getSubPathSuggestions(path, fragment));
|
substitutionSuggestions.addAll(getSubPathSuggestions(req, path, fragment));
|
||||||
substitutionSuggestions.addAll(this.parameterProcessorComponent.getSubstitutionSuggestions(fragment));
|
substitutionSuggestions.addAll(this.parameterProcessorComponent.getSubstitutionSuggestions(fragment));
|
||||||
|
|
||||||
Map<String, Object> model = new HashMap<String, Object>();
|
Map<String, Object> model = new HashMap<String, Object>();
|
||||||
@@ -72,12 +128,148 @@ public class RmSubstitutionSuggestionsGet extends DeclarativeWebScript
|
|||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> getSubPathSuggestions(final String path, final String fragment) {
|
/**
|
||||||
|
* Return a list of path suggestions for the path fragment supplied.
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* @param fragment
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private List<String> getSubPathSuggestions(WebScriptRequest req, final String path, final String fragment) {
|
||||||
List<String> pathSuggestions = new ArrayList<String>();
|
List<String> pathSuggestions = new ArrayList<String>();
|
||||||
if(path != null)
|
if((path != null) && path.startsWith("/") && (fragment != null) && (fragment.length() >= PATH_SUBSTITUTION_MINIMUM_FRAGMENT_LENGTH))
|
||||||
{
|
{
|
||||||
// TODO - populate path suggestions
|
String[] pathFragments = path.split("/");
|
||||||
|
|
||||||
|
NodeRef currentNode = getFilePlan(req);
|
||||||
|
for(String pathFragment : pathFragments)
|
||||||
|
{
|
||||||
|
// ignore empty elements of the path produced by split
|
||||||
|
if(!pathFragment.isEmpty())
|
||||||
|
{
|
||||||
|
boolean foundThisPathFragment = false;
|
||||||
|
List<ChildAssociationRef> children = nodeService.getChildAssocs(currentNode);
|
||||||
|
for (ChildAssociationRef childAssoc : children) {
|
||||||
|
NodeRef childNodeRef = childAssoc.getChildRef();
|
||||||
|
String fileName = (String) nodeService.getProperty(childNodeRef, ContentModel.PROP_NAME);
|
||||||
|
if(fileName.equals(pathFragment) && isNodeRefAppropriateForPathSuggestion(childNodeRef))
|
||||||
|
{
|
||||||
|
foundThisPathFragment = true;
|
||||||
|
currentNode = childNodeRef;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!foundThisPathFragment)
|
||||||
|
{
|
||||||
|
currentNode = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(currentNode != null)
|
||||||
|
{
|
||||||
|
String lowerCaseFragment = fragment.toLowerCase();
|
||||||
|
List<ChildAssociationRef> children = nodeService.getChildAssocs(currentNode);
|
||||||
|
for (ChildAssociationRef childAssoc : children) {
|
||||||
|
NodeRef childNodeRef = childAssoc.getChildRef();
|
||||||
|
String fileName = (String) nodeService.getProperty(childNodeRef, ContentModel.PROP_NAME);
|
||||||
|
if((fragment.isEmpty() || fileName.toLowerCase().startsWith(lowerCaseFragment)) && isNodeRefAppropriateForPathSuggestion(childNodeRef))
|
||||||
|
{
|
||||||
|
pathSuggestions.add("/" + fileName);
|
||||||
|
if(pathSuggestions.size() >= PATH_SUBSTITUTION_MAXIMUM_NUMBER_RESULTS)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return pathSuggestions;
|
return pathSuggestions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility method to get the file plan from the passed parameters.
|
||||||
|
*
|
||||||
|
* @param req
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected NodeRef getFilePlan(WebScriptRequest req)
|
||||||
|
{
|
||||||
|
NodeRef filePlan = null;
|
||||||
|
|
||||||
|
Map<String, String> templateVars = req.getServiceMatch().getTemplateVars();
|
||||||
|
String siteId = templateVars.get("siteid");
|
||||||
|
if (siteId != null)
|
||||||
|
{
|
||||||
|
filePlan = filePlanService.getFilePlanBySiteId(siteId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filePlan == null)
|
||||||
|
{
|
||||||
|
String storeType = templateVars.get("store_type");
|
||||||
|
String storeId = templateVars.get("store_id");
|
||||||
|
String id = templateVars.get("id");
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(storeType) == false &&
|
||||||
|
StringUtils.isEmpty(storeId) == false &&
|
||||||
|
StringUtils.isEmpty(id) == false)
|
||||||
|
{
|
||||||
|
StoreRef storeRef = new StoreRef(storeType, storeId);
|
||||||
|
NodeRef nodeRef = new NodeRef(storeRef, id);
|
||||||
|
if (filePlanService.isFilePlan(nodeRef) == true)
|
||||||
|
{
|
||||||
|
filePlan = nodeRef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filePlan == null)
|
||||||
|
{
|
||||||
|
// Assume we are in a legacy repository and we will grab the default file plan
|
||||||
|
filePlan = filePlanService.getFilePlanBySiteId(FilePlanService.DEFAULT_RM_SITE_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
return filePlan;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifies record category and record folder types of nodeRef
|
||||||
|
*
|
||||||
|
* @param nodeRef Instance of NodeRef to be tested
|
||||||
|
* @return True if the passed NodeRef instance is a record category or record folder
|
||||||
|
*/
|
||||||
|
private boolean isNodeRefAppropriateForPathSuggestion(NodeRef nodeRef)
|
||||||
|
{
|
||||||
|
// check node type
|
||||||
|
QName type = nodeService.getType(nodeRef);
|
||||||
|
String typeLocalName = type.getLocalName();
|
||||||
|
boolean isCorrectType = (RECORD_FOLDER_TYPE.equals(typeLocalName) || RECORD_CATEGORY_TYPE.equals(typeLocalName));
|
||||||
|
|
||||||
|
// check permissions
|
||||||
|
boolean canView = false;
|
||||||
|
if(isCorrectType)
|
||||||
|
{
|
||||||
|
Capability createCapability = capabilityService.getCapability(CREATE_CAPABILITY);
|
||||||
|
Capability viewCapability = capabilityService.getCapability(VIEW_CAPABILITY);
|
||||||
|
if ((createCapability != null) && (viewCapability != null))
|
||||||
|
{
|
||||||
|
List<String> requiredCapabilities = new ArrayList<String>();
|
||||||
|
requiredCapabilities.add(CREATE_CAPABILITY);
|
||||||
|
requiredCapabilities.add(VIEW_CAPABILITY);
|
||||||
|
Map<Capability, AccessStatus> map = capabilityService.getCapabilitiesAccessState(nodeRef, requiredCapabilities);
|
||||||
|
if (map.containsKey(createCapability) && map.containsKey(viewCapability))
|
||||||
|
{
|
||||||
|
AccessStatus createAccessStatus = map.get(createCapability);
|
||||||
|
AccessStatus viewAccessStatus = map.get(viewCapability);
|
||||||
|
if (createAccessStatus.equals(AccessStatus.ALLOWED) && viewAccessStatus.equals(AccessStatus.ALLOWED))
|
||||||
|
{
|
||||||
|
canView = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return isCorrectType && canView;
|
||||||
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user